double Measurement::NearestPointOnCurve(QPointF P, vector<QPointF> V) { QPointF *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*/ QPointF v_arr[4]; for(int i=0; i<4; i++) v_arr[i]=V[i]; /* Convert problem to 5th-degree Bezier form */ w = ConvertToBezierForm(P, v_arr); /* 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; QPointF p; QPointF v; int i; /* Check distance to beginning of curve, where t = 0 */ dist = V2SquaredLength(V2Sub(&P, &v_arr[0], &v)); t = 0.0; /* Find distances for candidate points */ for (i = 0; i < n_solutions; i++) { p = Bezier(v_arr, DEGREE, t_candidate[i], (QPointF *)NULL, (QPointF *)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); QPointF b=Bezier(v_arr, DEGREE, t, (QPointF *)NULL, (QPointF *)NULL); return V2DistanceBetween2Points(&P,&b); }
/* * ComputeMaxError : * Find the maximum squared distance of digitized points * to fitted curve. */ static double ComputeMaxError( Point2 *d, /* Array of digitized points */ int first, int last, /* Indices defining region */ BezierCurve bezCurve, /* Fitted Bezier curve */ double *u, /* Parameterization of points */ int *splitPoint) /* Point of maximum error */ { int i; double maxDist; /* Maximum error */ double dist; /* Current error */ Point2 P; /* Point on curve */ Vector2 v; /* Vector from point to curve */ *splitPoint = (last - first + 1)/2; maxDist = 0.0; for (i = first + 1; i < last; i++) { P = BezierII(3, bezCurve, u[i-first]); v = V2SubII(P, d[i]); dist = V2SquaredLength(&v); if (dist >= maxDist) { maxDist = dist; *splitPoint = i; } } return (maxDist); }
/* * ComputeMaxError : * Find the maximum squared distance of digitized points * to fitted curve. */ static double ComputeMaxError(Point2 *d, int first, int last, BezierCurve bezCurve, double *u, int *splitPoint) { int i; double maxDist; /* Maximum error */ double dist; /* Current error */ Point2 P; /* Point on curve */ Vector2 v; /* Vector from point to curve */ *splitPoint = (last - first + 1)/2; maxDist = 0.0; for (i = first + 1; i < last; i++) { P = BezierII(3, bezCurve, u[i-first]); v = V2SubII(P, d[i]); dist = V2SquaredLength(&v); if (dist >= maxDist) { maxDist = dist; *splitPoint = i; } } return (maxDist); }
/* returns length of input vector */ double V2Length(Vector2 *a) { return(sqrt(V2SquaredLength(a))); }