dist/shape-points.es.js
/**
     * Use least-squares method to find Bezier control points for region.
     *
     * @param {Array<Array<Number>>} points - Array of digitized points
     * @param {Array<Number>} parameters - Parameter values for region
     * @param {Array<Number>} leftTangent - Unit tangent vector at start point
     * @param {Array<Number>} rightTangent - Unit tangent vector at end point
     * @returns {Array<Array<Number>>} Approximated Bezier curve: [first-point, control-point-1, control-point-2, second-point] where points are [x, y]
     */
Use least-squares method to find Bezier control points for region.


Use least - squares method to find Bezier control points for region .
function generateBezier(points, parameters, leftTangent, rightTangent) {
        var bezCurve,
        A,
            a,
        C,
            X,
        det_C0_C1,
            det_C0_X,
            det_X_C1,
        alpha_l,
            alpha_r,
        epsilon,
            segLength,
            i,
            len,
            tmp,
            u,
            ux,
            firstPoint = points[0],
            lastPoint = points[points.length - 1];
        bezCurve = [firstPoint, null, null, lastPoint];
        A = maths.zeros_Xx2x2(parameters.length);
        for (i = 0, len = parameters.length; i < len; i++) {
            u = parameters[i];
            ux = 1 - u;
            a = A[i];
            a[0] = maths.mulItems(leftTangent, 3 * u * (ux * ux));
            a[1] = maths.mulItems(rightTangent, 3 * ux * (u * u));
        }
        C = [[0, 0], [0, 0]];
        X = [0, 0];
        for (i = 0, len = points.length; i < len; i++) {
            u = parameters[i];
            a = A[i];
            C[0][0] += maths.dot(a[0], a[0]);
            C[0][1] += maths.dot(a[0], a[1]);
            C[1][0] += maths.dot(a[0], a[1]);
            C[1][1] += maths.dot(a[1], a[1]);
            tmp = maths.subtract(points[i], bezier.q([firstPoint, firstPoint, lastPoint, lastPoint], u));
            X[0] += maths.dot(a[0], tmp);
            X[1] += maths.dot(a[1], tmp);
        }
        det_C0_C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1];
        det_C0_X = C[0][0] * X[1] - C[1][0] * X[0];
        det_X_C1 = X[0] * C[1][1] - X[1] * C[0][1];
        alpha_l = det_C0_C1 === 0 ? 0 : det_X_C1 / det_C0_C1;
        alpha_r = det_C0_C1 === 0 ? 0 : det_C0_X / det_C0_C1;
        segLength = maths.vectorLen(maths.subtract(firstPoint, lastPoint));
        epsilon = 1.0e-6 * segLength;
        if (alpha_l < epsilon || alpha_r < epsilon) {
            bezCurve[1] = maths.addArrays(firstPoint, maths.mulItems(leftTangent, segLength / 3.0));
            bezCurve[2] = maths.addArrays(lastPoint, maths.mulItems(rightTangent, segLength / 3.0));
        } else {
            bezCurve[1] = maths.addArrays(firstPoint, maths.mulItems(leftTangent, alpha_l));
            bezCurve[2] = maths.addArrays(lastPoint, maths.mulItems(rightTangent, alpha_r));
        }
        return bezCurve;
    }
function generateBezier ( points , parameters , leftTangent , rightTangent ) { var bezCurve , A , a , C , X , det_C0_C1 , det_C0_X , det_X_C1 , alpha_l , alpha_r , epsilon , segLength , i , len , tmp , u , ux , firstPoint = points [ 0 ] , lastPoint = points [ points . length - 1 ] ; bezCurve = [ firstPoint , null , null , lastPoint ] ; A = maths . zeros_Xx2x2 ( parameters . length ) ; for ( i = 0 , len = parameters . length ; i < len ; i ++ ) { u = parameters [ i ] ; ux = 1 - u ; a = A [ i ] ; a [ 0 ] = maths . mulItems ( leftTangent , 3 * u * ( ux * ux ) ) ; a [ 1 ] = maths . mulItems ( rightTangent , 3 * ux * ( u * u ) ) ; } C = [ [ 0 , 0 ] , [ 0 , 0 ] ] ; X = [ 0 , 0 ] ; for ( i = 0 , len = points . length ; i < len ; i ++ ) { u = parameters [ i ] ; a = A [ i ] ; C [ 0 ] [ 0 ] += maths . dot ( a [ 0 ] , a [ 0 ] ) ; C [ 0 ] [ 1 ] += maths . dot ( a [ 0 ] , a [ 1 ] ) ; C [ 1 ] [ 0 ] += maths . dot ( a [ 0 ] , a [ 1 ] ) ; C [ 1 ] [ 1 ] += maths . dot ( a [ 1 ] , a [ 1 ] ) ; tmp = maths . subtract ( points [ i ] , bezier . q ( [ firstPoint , firstPoint , lastPoint , lastPoint ] , u ) ) ; X [ 0 ] += maths . dot ( a [ 0 ] , tmp ) ; X [ 1 ] += maths . dot ( a [ 1 ] , tmp ) ; } det_C0_C1 = C [ 0 ] [ 0 ] * C [ 1 ] [ 1 ] - C [ 1 ] [ 0 ] * C [ 0 ] [ 1 ] ; det_C0_X = C [ 0 ] [ 0 ] * X [ 1 ] - C [ 1 ] [ 0 ] * X [ 0 ] ; det_X_C1 = X [ 0 ] * C [ 1 ] [ 1 ] - X [ 1 ] * C [ 0 ] [ 1 ] ; alpha_l = det_C0_C1 === 0 ? 0 : det_X_C1 / det_C0_C1 ; alpha_r = det_C0_C1 === 0 ? 0 : det_C0_X / det_C0_C1 ; segLength = maths . vectorLen ( maths . subtract ( firstPoint , lastPoint ) ) ; epsilon = 1.0e-6 * segLength ; if ( alpha_l < epsilon || alpha_r < epsilon ) { bezCurve [ 1 ] = maths . addArrays ( firstPoint , maths . mulItems ( leftTangent , segLength / 3.0 ) ) ; bezCurve [ 2 ] = maths . addArrays ( lastPoint , maths . mulItems ( rightTangent , segLength / 3.0 ) ) ; } else { bezCurve [ 1 ] = maths . addArrays ( firstPoint , maths . mulItems ( leftTangent , alpha_l ) ) ; bezCurve [ 2 ] = maths . addArrays ( lastPoint , maths . mulItems ( rightTangent , alpha_r ) ) ; } return bezCurve ; }
Use least-squares method to find Bezier control points for region.
Use least - squares method to find Bezier control points for region .
//Bezier curve ctl pts //Precomputed rhs for eqn //Matrices C & X //Determinants of matrices //Alpha values, left and right //console.log('gb', parameters.length); //Compute the A's //Create the C and X matrices //Compute the determinants of C and X //Finally, derive alpha values //If alpha negative, use the Wu/Barsky heuristic (see text). //If alpha is 0, you get coincident control points that lead to //divide by zero in any subsequent NewtonRaphsonRootFind() call. //Fall back on standard (probably inaccurate) formula, and subdivide further if needed. //First and last control points of the Bezier curve are //positioned exactly at the first and last data points //Control points 1 and 2 are positioned an alpha distance out //on the tangent vectors, left and right, respectively