// from http://blog.gludion.com/2009/08/distance-to-quadratic-bezier-curve.html // (currently only used by testing) double SkDQuad::nearestT(const SkDPoint& pt) const { SkDVector pos = fPts[0] - pt; // search points P of bezier curve with PM.(dP / dt) = 0 // a calculus leads to a 3d degree equation : SkDVector A = fPts[1] - fPts[0]; SkDVector B = fPts[2] - fPts[1]; B -= A; double a = B.dot(B); double b = 3 * A.dot(B); double c = 2 * A.dot(A) + pos.dot(B); double d = pos.dot(A); double ts[3]; int roots = SkDCubic::RootsValidT(a, b, c, d, ts); double d0 = pt.distanceSquared(fPts[0]); double d2 = pt.distanceSquared(fPts[2]); double distMin = SkTMin(d0, d2); int bestIndex = -1; for (int index = 0; index < roots; ++index) { SkDPoint onQuad = ptAtT(ts[index]); double dist = pt.distanceSquared(onQuad); if (distMin > dist) { distMin = dist; bestIndex = index; } } if (bestIndex >= 0) { return ts[bestIndex]; } return d0 < d2 ? 0 : 1; }
int SkIntersections::closestTo(double rangeStart, double rangeEnd, const SkDPoint& testPt, double* closestDist) const { int closest = -1; *closestDist = SK_ScalarMax; for (int index = 0; index < fUsed; ++index) { if (!between(rangeStart, fT[0][index], rangeEnd)) { continue; } const SkDPoint& iPt = fPt[index]; double dist = testPt.distanceSquared(iPt); if (*closestDist > dist) { *closestDist = dist; closest = index; } } return closest; }