Search code examples
graphicsgeometrybezieralgebraanalytic-geometry

Quadratic Bezier curve arc length


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.


Solution

  • 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.