/*
Solving the Nearest Point-on-Curve Problem
and
A Bezier Curve-Based Root-Finder
by Philip J. Schneider
from "Graphics Gems", Academic Press, 1990
*/

 /*    point_on_curve.c    */

#include <stdio.h>
#include <malloc.h>
#include <math.h>
#include "GraphicsGems.h"

#define TESTMODE

/*
 *  Forward declarations
 */
Point2  NearestPointOnCurve();
static    int    FindRoots();
static    Point2    *ConvertToBezierForm();
static    double    ComputeXIntercept();
static    int    ControlPolygonFlatEnough();
static    int    CrossingCount();
static    Point2    Bezier();
static    Vector2    V2ScaleII();

int        MAXDEPTH = 64;    /*  Maximum depth for recursion */

#define    EPSILON    (ldexp(1.0,-MAXDEPTH-1)) /*Flatness control value */
#define    DEGREE    3            /*  Cubic Bezier curve        */
#define    W_DEGREE 5            /*  Degree of eqn to find roots of */

#ifdef TESTMODE
/*
 *  main :
 *    Given a cubic Bezier curve (i.e., its control points), and some
 *    arbitrary point in the plane, find the point on the curve
 *    closest to that arbitrary point.
 */
main()
{

 static Point2 bezCurve[4] = {    /*  A cubic Bezier curve    */
    { 0.0, 0.0 },
    { 1.0, 2.0 },
    { 3.0, 3.0 },
    { 4.0, 2.0 },
    };
    static Point2 arbPoint = { 3.5, 2.0 }; /*Some arbitrary point*/
    Point2    pointOnCurve;         /*  Nearest point on the curve */

    /*  Find the closest point */
    pointOnCurve = NearestPointOnCurve(arbPoint, bezCurve);
    printf("pointOnCurve : (%4.4f, %4.4f)\n", pointOnCurve.x,
        pointOnCurve.y);
}
#endif /* TESTMODE */


/*
 *  NearestPointOnCurve :
 *      Compute the parameter value of the point on a Bezier
 *        curve segment closest to some arbtitrary, user-input point.
 *        Return the point on the curve at that parameter value.
 *
 */
Point2 NearestPointOnCurve(P, V)
    Point2     P;            /* The user-supplied point      */
    Point2     *V;            /* Control points of cubic Bezier */
{
    Point2    *w;            /* Ctl pts for 5th-degree eqn    */
    double     t_candidate[W_DEGREE];    /* Possible roots        */
    int     n_solutions;        /* Number of roots found    */
    double    t;            /* Parameter value of closest pt*/

    /*  Convert problem to 5th-degree Bezier form    */
    w = ConvertToBezierForm(P, V);

    /* Find all possible roots of 5th-degree equation */
    n_solutions = FindRoots(w, W_DEGREE, t_candidate, 0);
    free((char *)w);

    /* Compare distances of P to all candidates, and to t=0, and t=1 */
    {
        double     dist, new_dist;
        Point2     p;
        Vector2  v;
        int        i;


    /* Check distance to beginning of curve, where t = 0    */
        dist = V2SquaredLength(V2Sub(&P, &V[0], &v));
            t = 0.0;

    /* Find distances for candidate points    */
        for (i = 0; i < n_solutions; i++) {
            p = Bezier(V, DEGREE, t_candidate[i],
            (Point2 *)NULL, (Point2 *)NULL);
            new_dist = V2SquaredLength(V2Sub(&P, &p, &v));
            if (new_dist < dist) {
                    dist = new_dist;
                    t = t_candidate[i];
            }
        }

    /* Finally, look at distance to end point, where t = 1.0 */
        new_dist = V2SquaredLength(V2Sub(&P, &V[DEGREE], &v));
            if (new_dist < dist) {
                dist = new_dist;
            t = 1.0;
        }
    }

    /*  Return the point on the curve at parameter value t */
    printf("t : %4.12f\n", t);
    return (Bezier(V, DEGREE, t, (Point2 *)NULL, (Point2 *)NULL));
}


/*
 *  ConvertToBezierForm :
 *        Given a point and a Bezier curve, generate a 5th-degree
 *        Bezier-format equation whose solution finds the point on the
 *      curve nearest the user-defined point.
 */
static Point2 *ConvertToBezierForm(P, V)
    Point2     P;            /* The point to find t for    */
    Point2     *V;            /* The control points        */
{
    int     i, j, k, m, n, ub, lb;
    int     row, column;        /* Table indices        */
    Vector2     c[DEGREE+1];        /* V(i)'s - P            */
    Vector2     d[DEGREE];        /* V(i+1) - V(i)        */
    Point2     *w;            /* Ctl pts of 5th-degree curve  */
    double     cdTable[3][4];        /* Dot product of c, d        */
    static double z[3][4] = {    /* Precomputed "z" for cubics    */
    {1.0, 0.6, 0.3, 0.1},
    {0.4, 0.6, 0.6, 0.4},
    {0.1, 0.3, 0.6, 1.0},
    };


    /*Determine the c's -- these are vectors created by subtracting*/
    /* point P from each of the control points                */
    for (i = 0; i <= DEGREE; i++) {
        V2Sub(&V[i], &P, &c[i]);
    }
    /* Determine the d's -- these are vectors created by subtracting*/
    /* each control point from the next                    */
    for (i = 0; i <= DEGREE - 1; i++) {
        d[i] = V2ScaleII(V2Sub(&V[i+1], &V[i], &d[i]), 3.0);
    }

    /* Create the c,d table -- this is a table of dot products of the */
    /* c's and d's                            */
    for (row = 0; row <= DEGREE - 1; row++) {
        for (column = 0; column <= DEGREE; column++) {
            cdTable[row][column] = V2Dot(&d[row], &c[column]);
        }
    }

    /* Now, apply the z's to the dot products, on the skew diagonal*/
    /* Also, set up the x-values, making these "points"        */
    w = (Point2 *)malloc((unsigned)(W_DEGREE+1) * sizeof(Point2));
    for (i = 0; i <= W_DEGREE; i++) {
        w[i].y = 0.0;
        w[i].x = (double)(i) / W_DEGREE;
    }

    n = DEGREE;
    m = DEGREE-1;
    for (k = 0; k <= n + m; k++) {
        lb = MAX(0, k - m);
        ub = MIN(k, n);
        for (i = lb; i <= ub; i++) {
            j = k - i;
            w[i+j].y += cdTable[j][i] * z[j][i];
        }
    }

    return (w);
}


/*
 *  FindRoots :
 *    Given a 5th-degree equation in Bernstein-Bezier form, find
 *    all of the roots in the interval [0, 1].  Return the number
 *    of roots found.
 */
static int FindRoots(w, degree, t, depth)
    Point2     *w;            /* The control points        */
    int     degree;        /* The degree of the polynomial    */
    double     *t;            /* RETURN candidate t-values    */
    int     depth;        /* The depth of the recursion    */
{
    int     i;
    Point2     Left[W_DEGREE+1],    /* New left and right         */
              Right[W_DEGREE+1];    /* control polygons        */
    int     left_count,        /* Solution count from        */
        right_count;        /* children            */
    double     left_t[W_DEGREE+1],    /* Solutions from kids        */
               right_t[W_DEGREE+1];

    switch (CrossingCount(w, degree)) {
           case 0 : {    /* No solutions here    */
         return 0;
    }
    case 1 : {    /* Unique solution    */
        /* Stop recursion when the tree is deep enough    */
        /* if deep enough, return 1 solution at midpoint     */
        if (depth >= MAXDEPTH) {
            t[0] = (w[0].x + w[W_DEGREE].x) / 2.0;
            return 1;
        }
        if (ControlPolygonFlatEnough(w, degree)) {
            t[0] = ComputeXIntercept(w, degree);
            return 1;
        }
        break;
    }
}

    /* Otherwise, solve recursively after    */
    /* subdividing control polygon        */
    Bezier(w, degree, 0.5, Left, Right);
    left_count  = FindRoots(Left,  degree, left_t, depth+1);
    right_count = FindRoots(Right, degree, right_t, depth+1);


    /* Gather solutions together    */
    for (i = 0; i < left_count; i++) {
        t[i] = left_t[i];
    }
    for (i = 0; i < right_count; i++) {
         t[i+left_count] = right_t[i];
    }

    /* Send back total number of solutions    */
    return (left_count+right_count);
}


/*
 * CrossingCount :
 *    Count the number of times a Bezier control polygon
 *    crosses the 0-axis. This number is >= the number of roots.
 *
 */
static int CrossingCount(V, degree)
    Point2    *V;            /*  Control pts of Bezier curve    */
    int        degree;            /*  Degreee of Bezier curve     */
{
    int     i;
    int     n_crossings = 0;    /*  Number of zero-crossings    */
    int        sign, old_sign;        /*  Sign of coefficients    */

    sign = old_sign = SGN(V[0].y);
    for (i = 1; i <= degree; i++) {
        sign = SGN(V[i].y);
        if (sign != old_sign) n_crossings++;
        old_sign = sign;
    }
    return n_crossings;
}



/*
 *  ControlPolygonFlatEnough :
 *    Check if the control polygon of a Bezier curve is flat enough
 *    for recursive subdivision to bottom out.
 *
 */
static int ControlPolygonFlatEnough(V, degree)
    Point2    *V;        /* Control points    */
    int     degree;        /* Degree of polynomial    */
{
    int     i;            /* Index variable        */
    double     *distance;        /* Distances from pts to line    */
    double     max_distance_above;    /* maximum of these        */
    double     max_distance_below;
    double     error;            /* Precision of root        */
    double     intercept_1,
               intercept_2,
               left_intercept,
               right_intercept;
    double     a, b, c;        /* Coefficients of implicit    */
                        /* eqn for line from V[0]-V[deg]*/

    /* Find the  perpendicular distance        */
    /* from each interior control point to     */
    /* line connecting V[0] and V[degree]    */
    distance = (double *)malloc((unsigned)(degree + 1) *                     sizeof(double));
    {
    double    abSquared;

    /* Derive the implicit equation for line connecting first *'
    /*  and last control points */
    a = V[0].y - V[degree].y;
    b = V[degree].x - V[0].x;
    c = V[0].x * V[degree].y - V[degree].x * V[0].y;

    abSquared = (a * a) + (b * b);

        for (i = 1; i < degree; i++) {
        /* Compute distance from each of the points to that line    */
            distance[i] = a * V[i].x + b * V[i].y + c;
            if (distance[i] > 0.0) {
                distance[i] = (distance[i] * distance[i]) / abSquared;
            }
            if (distance[i] < 0.0) {
                distance[i] = -((distance[i] * distance[i]) /                         abSquared);
            }
        }
    }


    /* Find the largest distance    */
    max_distance_above = 0.0;
    max_distance_below = 0.0;
    for (i = 1; i < degree; i++) {
        if (distance[i] < 0.0) {
            max_distance_below = MIN(max_distance_below, distance[i]);
        };
        if (distance[i] > 0.0) {
            max_distance_above = MAX(max_distance_above, distance[i]);
        }
    }
    free((char *)distance);

    {
    double    det, dInv;
    double    a1, b1, c1, a2, b2, c2;

    /*  Implicit equation for zero line */
    a1 = 0.0;
    b1 = 1.0;
    c1 = 0.0;

    /*  Implicit equation for "above" line */
    a2 = a;
    b2 = b;
    c2 = c + max_distance_above;

    det = a1 * b2 - a2 * b1;
    dInv = 1.0/det;

    intercept_1 = (b1 * c2 - b2 * c1) * dInv;

    /*  Implicit equation for "below" line */
    a2 = a;
    b2 = b;
    c2 = c + max_distance_below;

    det = a1 * b2 - a2 * b1;
    dInv = 1.0/det;

    intercept_2 = (b1 * c2 - b2 * c1) * dInv;
    }

    /* Compute intercepts of bounding box    */
    left_intercept = MIN(intercept_1, intercept_2);
    right_intercept = MAX(intercept_1, intercept_2);

    error = 0.5 * (right_intercept-left_intercept);
    if (error < EPSILON) {
        return 1;
    }
    else {
        return 0;
    }
}



/*
 *  ComputeXIntercept :
 *    Compute intersection of chord from first control point to last
 *      with 0-axis.
 *
 */
/* NOTE: "T" and "Y" do not have to be computed, and there are many useless
 * operations in the following (e.g. "0.0 - 0.0").
 */
static double ComputeXIntercept(V, degree)
    Point2     *V;            /*  Control points    */
    int        degree;         /*  Degree of curve    */
{
    double    XLK, YLK, XNM, YNM, XMK, YMK;
    double    det, detInv;
    double    S, T;
    double    X, Y;

    XLK = 1.0 - 0.0;
    YLK = 0.0 - 0.0;
    XNM = V[degree].x - V[0].x;
    YNM = V[degree].y - V[0].y;
    XMK = V[0].x - 0.0;
    YMK = V[0].y - 0.0;

    det = XNM*YLK - YNM*XLK;
    detInv = 1.0/det;

    S = (XNM*YMK - YNM*XMK) * detInv;
/*  T = (XLK*YMK - YLK*XMK) * detInv; */

    X = 0.0 + XLK * S;
/*  Y = 0.0 + YLK * S; */

    return X;
}


/*
 *  Bezier :
 *    Evaluate a Bezier curve at a particular parameter value
 *      Fill in control points for resulting sub-curves if "Left" and
 *    "Right" are non-null.
 *
 */
static Point2 Bezier(V, degree, t, Left, Right)
    int     degree;        /* Degree of bezier curve    */
    Point2     *V;            /* Control pts            */
    double     t;            /* Parameter value        */
    Point2     *Left;        /* RETURN left half ctl pts    */
    Point2     *Right;        /* RETURN right half ctl pts    */
{
    int     i, j;        /* Index variables    */
    Point2     Vtemp[W_DEGREE+1][W_DEGREE+1];


    /* Copy control points    */
    for (j =0; j <= degree; j++) {
        Vtemp[0][j] = V[j];
    }

    /* Triangle computation    */
    for (i = 1; i <= degree; i++) {
        for (j =0 ; j <= degree - i; j++) {
            Vtemp[i][j].x =
                  (1.0 - t) * Vtemp[i-1][j].x + t * Vtemp[i-1][j+1].x;
            Vtemp[i][j].y =
                  (1.0 - t) * Vtemp[i-1][j].y + t * Vtemp[i-1][j+1].y;
        }
    }

    if (Left != NULL) {
        for (j = 0; j <= degree; j++) {
            Left[j]  = Vtemp[j][0];
        }
    }
    if (Right != NULL) {
        for (j = 0; j <= degree; j++) {
            Right[j] = Vtemp[degree-j][j];
        }
    }

    return (Vtemp[degree][0]);
}

static Vector2 V2ScaleII(v, s)
    Vector2    *v;
    double    s;
{
    Vector2 result;

    result.x = v->x * s; result.y = v->y * s;
    return (result);
}
