7 VBezier VBezier::fromPoints(const VPointF &p1, const VPointF &p2,
8 const VPointF &p3, const VPointF &p4)
22 float VBezier::length() const
24 VBezier left, right; /* bez poly splits */
25 float len = 0.0; /* arc length */
26 float chord; /* chord length */
29 len = len + VLine::length(x1, y1, x2, y2);
30 len = len + VLine::length(x2, y2, x3, y3);
31 len = len + VLine::length(x3, y3, x4, y4);
33 chord = VLine::length(x1, y1, x4, y4);
35 if ((len - chord) > 0.01) {
36 split(&left, &right); /* split in two */
37 length = left.length() + /* try left side */
38 right.length(); /* try right side */
46 VBezier VBezier::onInterval(float t0, float t1) const
48 if (t0 == 0 && t1 == 1) return *this;
50 VBezier bezier = *this;
53 bezier.parameterSplitLeft(t0, &result);
54 float trueT = (t1 - t0) / (1 - t0);
55 bezier.parameterSplitLeft(trueT, &result);
60 float VBezier::tAtLength(float l) const
64 const float error = 0.01;
65 if (l > len || vCompare(l, len)) return t;
69 float lastBigger = 1.0;
71 VBezier right = *this;
73 right.parameterSplitLeft(t, &left);
74 float lLen = left.length();
75 if (fabs(lLen - l) < error) break;
78 t += (lastBigger - t) * 0.5;
87 void VBezier::splitAtLength(float len, VBezier *left, VBezier *right)
92 t = right->tAtLength(len);
93 right->parameterSplitLeft(t, left);
96 VPointF VBezier::derivative(float t) const
98 // p'(t) = 3 * (-(1-2t+t^2) * p0 + (1 - 4 * t + 3 * t^2) * p1 + (2 * t - 3 * t^2) * p2 + t^2 * p3)
103 float a = -m_t * m_t;
104 float b = 1 - 4 * t + 3 * d;
105 float c = 2 * t - 3 * d;
107 return 3 * VPointF(a * x1 + b * x2 + c * x3 + d * x4,
108 a * y1 + b * y2 + c * y3 + d * y4);
112 float VBezier::angleAt(float t) const
114 if (t < 0 || t > 1) {
117 return VLine({}, derivative(t)).angle();