Skip to content

Instantly share code, notes, and snippets.

@tunght13488
Last active December 15, 2023 10:13
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save tunght13488/6744e77c242cc7a94859 to your computer and use it in GitHub Desktop.
Save tunght13488/6744e77c242cc7a94859 to your computer and use it in GitHub Desktop.
quadratic bezier curve length in javascript
/*
* http://en.wikipedia.org/wiki/B%C3%A9zier_curve
* http://www.malczak.linuxpl.com/blog/quadratic-bezier-curve-length/g
*/
function Point(x, y) {
this.x = x;
this.y = y;
}
function quadraticBezierLength(p0, p1, p2) {
var a = new Point(
p0.x - 2 * p1.x + p2.x,
p0.y - 2 * p1.y + p2.y
);
var b = new Point(
2 * p1.x - 2 * p0.x,
2 * p1.y - 2 * p0.y
);
var A = 4 * (a.x * a.x + a.y * a.y);
var B = 4 * (a.x * b.x + a.y * b.y);
var C = b.x * b.x + b.y * b.y;
var Sabc = 2 * sqrt(A+B+C);
var A_2 = sqrt(A);
var A_32 = 2 * A * A_2;
var C_2 = 2 * sqrt(C);
var BA = B / A_2;
return (A_32 * Sabc + A_2 * B * (Sabc - C_2) + (4 * C * A - B * B) * log((2 * A_2 + BA + Sabc) / (BA + C_2))) / (4 * A_32);
}
@herrstrietzel
Copy link

herrstrietzel commented Sep 22, 2023

As commented before, we should also check for actually linear commands:

/**
* p0: previous command's final point
* cp1: quadratic bézier control point
* p: final point
*/

function quadraticBezierLength(p0, cp1, p, t = 1) {
    if (t === 0) {
        return 0;
    }

    const interpolate = (p1, p2, t) => {
        let pt = { x: (p2.x - p1.x) * t + p1.x, y: (p2.y - p1.y) * t + p1.y };
        return pt;
    }
    const getLineLength = (p1, p2) => {
        return Math.sqrt(
            (p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y)
        );
    }

    // is flat/linear 
    let l1 = getLineLength(p0, cp1) + getLineLength(cp1, p);
    let l2 = getLineLength(p0, p);
    if (l1 === l2) {
        let m1 = interpolate(p0, cp1, t);
        let m2 = interpolate(cp1, p, t);
        p = interpolate(m1, m2, t);
        let lengthL;
        lengthL = Math.sqrt((p.x - p0.x) * (p.x - p0.x) + (p.y - p0.y) * (p.y - p0.y));
        return lengthL;
    }

    let a, b, c, d, e, e1, d1, v1x, v1y;

    v1x = cp1.x * 2;
    v1y = cp1.y * 2;
    d = p0.x - v1x + p.x;
    d1 = p0.y - v1y + p.y;
    e = v1x - 2 * p0.x;
    e1 = v1y - 2 * p0.y;
    a = 4 * (d * d + d1 * d1);
    b = 4 * (d * e + d1 * e1);
    c = e * e + e1 * e1;

    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))))
    );
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment