22#define M_PI 3.14159265358979323846264338327950288
26#define M_SQRT2 1.41421356237309504880168872420969808
53 double fEndptsX[2] = {0, 1};
54 double fEndptsY[2] = {-1, 0};
57 double fControlLength;
59 std::array<double, 4> fCubicX;
60 std::array<double, 4> fCubicY;
77 std::array<double, 4>*
X, std::array<double, 4>*
Y) {
78 constexpr static double kM = -4.0/3;
80 double d = x0*x1 + y0*y1;
82 *
X = {x0, x0 - y0*c, x1 + y1*c, x1};
83 *
Y = {y0, y0 + x0*c, y1 - x1*c, y1};
87static double lerp(
double x,
double y,
double T) {
92static std::tuple<double, double, double>
eval_cubic(
double x[],
double T) {
95 double bc =
lerp(
x[1],
x[2],
T);
96 double cd =
lerp(
x[2],
x[3],
T);
98 double bcd =
lerp(bc, cd,
T);
99 double abcd =
lerp(abc, bcd,
T);
100 return {abcd, 3 * (bcd - abc) , 6 * (cd - 2*bc +
ab) };
111 constexpr static double kInitialT = .25;
112 double T = kInitialT;
113 for (
int i = 0;
i < 64; ++
i) {
116 double dError = 2*(
x*
dx +
y*dy);
117 double ddError = 2*(
x*ddx +
y*ddy +
dx*
dx + dy*dy);
118 T -= dError / ddError;
123void SampleFitCubicToCircle::fitCubic() {
124 fInfoStrings.
clear();
126 std::array<double, 4>
X,
Y;
130 fInfoStrings.
push_back().
printf(
"control length=%0.14f", fControlLength);
135 for (
int i = 0;
i < 4; ++
i) {
144 fTheta = std::atan2(fEndptsY[1], fEndptsX[1]) - std::atan2(fEndptsY[0], fEndptsX[0]);
147 fTheta = 360 - fTheta;
152 for (
const SkString& infoString : fInfoStrings) {
153 SkDebugf(
"%s\n", infoString.c_str());
166 kRadius * 2), 0, 360,
false, circlePaint);
174 cubicPath.
moveTo(fCubicX[0], fCubicY[0]);
175 cubicPath.
cubicTo(fCubicX[1], fCubicY[1], fCubicX[2], fCubicY[2], fCubicX[3], fCubicY[3]);
176 canvas->
drawPath(cubicPath, cubicPaint);
183 {(
float)fCubicX[3], (
float)fCubicY[3]}};
188 constexpr static float kInfoTextSize = 16;
190 int infoY = 10 + kInfoTextSize;
191 for (
const SkString& infoString : fInfoStrings) {
192 canvas->
drawString(infoString.c_str(), 10, infoY,
font, textPaint);
193 infoY += kInfoTextSize * 3/2;
205 that->fEndptsX[fPtIdx] =
dx/l;
206 that->fEndptsY[fPtIdx] = dy/l;
207 if (that->fEndptsX[0] * that->fEndptsY[1] - that->fEndptsY[0] * that->fEndptsX[1] < 0) {
208 std::swap(that->fEndptsX[0], that->fEndptsX[1]);
209 std::swap(that->fEndptsY[0], that->fEndptsY[1]);
221 double dx0 =
x - fCubicX[0];
222 double dy0 =
y - fCubicY[0];
223 double dx3 =
x - fCubicX[3];
224 double dy3 =
y - fCubicY[3];
225 if (dx0*dx0 + dy0*dy0 < dx3*dx3 + dy3*dy3) {
239 if (unichar ==
'E') {
240 constexpr static double kMaxErrorT = 0.21132486540519;
242 double lastError = -1;
243 for (
double theta = fTheta; lastError != 0; theta /= 2) {
244 double rads = theta *
M_PI/180;
245 std::array<double, 4>
X,
Y;
250 if ((
float)
error <= 0) {
static constexpr int kCenterX
double find_max_error_T(double cubicX[4], double cubicY[4])
static constexpr int kCenterY
static double lerp(double x, double y, double T)
static constexpr int kRadius
static float fit_cubic_to_unit_circle(double x0, double y0, double x1, double y1, std::array< double, 4 > *X, std::array< double, 4 > *Y)
static std::tuple< double, double, double > eval_cubic(double x[], double T)
static const int points[]
constexpr SkColor SK_ColorBLUE
constexpr SkColor SK_ColorBLACK
constexpr SkColor SK_ColorGREEN
constexpr SkColor SK_ColorWHITE
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
void swap(sk_sp< T > &a, sk_sp< T > &b)
void doClick(SampleFitCubicToCircle *that)
bool onChar(SkUnichar) override
void draw(SkCanvas *) override
Click * onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey) override
bool onClick(Click *) override
void load(SkScalar w, SkScalar h) override
void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint &paint)
void clear(SkColor color)
void drawArc(const SkRect &oval, SkScalar startAngle, SkScalar sweepAngle, bool useCenter, const SkPaint &paint)
void drawPath(const SkPath &path, const SkPaint &paint)
void drawString(const char str[], SkScalar x, SkScalar y, const SkFont &font, const SkPaint &paint)
@ kPoints_PointMode
draw each point separately
void setStyle(Style style)
void setColor(SkColor color)
void setAntiAlias(bool aa)
@ kStroke_Style
set to stroke geometry
void setStrokeWidth(SkScalar width)
SkPath & moveTo(SkScalar x, SkScalar y)
SkPath & cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar x3, SkScalar y3)
void printf(const char format[],...) SK_PRINTF_LIKE(2
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
const uint8_t uint32_t uint32_t GError ** error
skia_private::AutoTArray< sk_sp< SkImageFilter > > filters TypedMatrix matrix TypedMatrix matrix SkScalar dx
font
Font Metadata and Metrics.
const myers::Point & get< 0 >(const myers::Segment &s)
SIN Vec< N, float > abs(const Vec< N, float > &x)
SIN Vec< N, float > sqrt(const Vec< N, float > &x)
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)