I am trying to calculate the length of a quadratic Bezier curve. Found a solution and a formula to calculate the length of the entire curve in a "closed form" - without having to do numeric methods. The solution is covered at: quadratic Bezier curve length. The function is below:
function quadraticBezierLength(x1, y1, x2, y2, x3, y3) {
let a, b, c, d, e, u, a1, e1, c1, d1, u1, v1x, v1y;
v1x = x2 * 2;
v1y = y2 * 2;
d = x1 - v1x + x3;
d1 = y1 - v1y + y3;
e = v1x - 2 * x1;
e1 = v1y - 2 * y1;
c1 = a = 4 * (d * d + d1 * d1);
c1 += b = 4 * (d * e + d1 * e1);
c1 += c = e * e + e1 * e1;
c1 = 2 * Math.sqrt(c1);
a1 = 2 * a * (u = Math.sqrt(a));
u1 = b / u;
a = 4 * c * a - b * b;
c = 2 * Math.sqrt(c);
return (
(a1 * c1 + u * b * (c1 - c) + a * Math.log((2 * u + u1 + c1) / (u1 + c))) /
(4 * a1)
);
}
It seems to be working correctly. I actually need L(t)
rather than the length of the complete curve. It is another task. However, fortunately, someone solved it before me, and shared at length of a quadratic curve segment. I wrote a function based on this solution:
function quadraticBezierArcLength(t, x1, y1, x2, y2, x3, y3) {
let a, b, c, d, e, e1, d1, v1x, v1y;
v1x = x2 * 2;
v1y = y2 * 2;
d = x1 - v1x + x3;
d1 = y1 - v1y + y3;
e = v1x - 2 * x1;
e1 = v1y - 2 * y1;
a = 4 * (d * d + d1 * d1);
b = 4 * (d * e + d1 * e1);
c = e * e + e1 * e1;
a = 4 * c * a - b * b;
c = 2 * Math.sqrt(c);
const bt = b / (2 * a),
ct = c / a,
ut = t + bt,
k = ct - bt ** 2;
return (
(Math.sqrt(a) / 2) *
(ut * Math.sqrt(ut ** 2 + k) -
bt * Math.sqrt(bt ** 2 + k) +
k *
Math.log((ut + Math.sqrt(ut ** 2 + k)) / (bt + Math.sqrt(bt ** 2 + k))))
);
}
If I am not mistaken, the implementation in code is correct. Yet, the length values are definitely wrong. The only time it returns what I expect is when t
equals 0
.
Is there an error in my quadraticBezierArcLength
function, or the formula wrong? I want the length along the curve of a segment from the point with coordinates {x1, x2} to the point C(t)
. I would expect that when t === 1
, the results of both functions are the same, at the very least.
You seem to have added two unnecessary lines to the calculation. Here's a fiddle where I have commented out those two lines, along with the function copied from the original answer.
//a = 4 * c * a - b * b;
//c = 2 * Math.sqrt(c);
The original answer also used the absolute function, which you have removed.