Cubic curve distance improvement

This commit is contained in:
Chlumsky 2025-06-20 13:03:17 +02:00
parent 54535fc7c0
commit 15833154b3
1 changed files with 9 additions and 8 deletions

View File

@ -199,9 +199,9 @@ SignedDistance QuadraticSegment::signedDistance(Point2 origin, double &param) co
double minDistance = nonZeroSign(crossProduct(epDir, qa))*qa.length(); // distance from A double minDistance = nonZeroSign(crossProduct(epDir, qa))*qa.length(); // distance from A
param = -dotProduct(qa, epDir)/dotProduct(epDir, epDir); param = -dotProduct(qa, epDir)/dotProduct(epDir, epDir);
{ {
epDir = direction(1);
double distance = (p[2]-origin).length(); // distance from B double distance = (p[2]-origin).length(); // distance from B
if (distance < fabs(minDistance)) { if (distance < fabs(minDistance)) {
epDir = direction(1);
minDistance = nonZeroSign(crossProduct(epDir, p[2]-origin))*distance; minDistance = nonZeroSign(crossProduct(epDir, p[2]-origin))*distance;
param = dotProduct(origin-p[1], epDir)/dotProduct(epDir, epDir); param = dotProduct(origin-p[1], epDir)/dotProduct(epDir, epDir);
} }
@ -235,9 +235,9 @@ SignedDistance CubicSegment::signedDistance(Point2 origin, double &param) const
double minDistance = nonZeroSign(crossProduct(epDir, qa))*qa.length(); // distance from A double minDistance = nonZeroSign(crossProduct(epDir, qa))*qa.length(); // distance from A
param = -dotProduct(qa, epDir)/dotProduct(epDir, epDir); param = -dotProduct(qa, epDir)/dotProduct(epDir, epDir);
{ {
epDir = direction(1);
double distance = (p[3]-origin).length(); // distance from B double distance = (p[3]-origin).length(); // distance from B
if (distance < fabs(minDistance)) { if (distance < fabs(minDistance)) {
epDir = direction(1);
minDistance = nonZeroSign(crossProduct(epDir, p[3]-origin))*distance; minDistance = nonZeroSign(crossProduct(epDir, p[3]-origin))*distance;
param = dotProduct(epDir-(p[3]-origin), epDir)/dotProduct(epDir, epDir); param = dotProduct(epDir-(p[3]-origin), epDir)/dotProduct(epDir, epDir);
} }
@ -246,19 +246,20 @@ SignedDistance CubicSegment::signedDistance(Point2 origin, double &param) const
for (int i = 0; i <= MSDFGEN_CUBIC_SEARCH_STARTS; ++i) { for (int i = 0; i <= MSDFGEN_CUBIC_SEARCH_STARTS; ++i) {
double t = (double) i/MSDFGEN_CUBIC_SEARCH_STARTS; double t = (double) i/MSDFGEN_CUBIC_SEARCH_STARTS;
Vector2 qe = qa+3*t*ab+3*t*t*br+t*t*t*as; Vector2 qe = qa+3*t*ab+3*t*t*br+t*t*t*as;
Vector2 d1 = 3*ab+6*t*br+3*t*t*as;
for (int step = 0; step < MSDFGEN_CUBIC_SEARCH_STEPS; ++step) { for (int step = 0; step < MSDFGEN_CUBIC_SEARCH_STEPS; ++step) {
// Improve t // Improve t
Vector2 d1 = 3*ab+6*t*br+3*t*t*as;
Vector2 d2 = 6*br+6*t*as; Vector2 d2 = 6*br+6*t*as;
t -= dotProduct(qe, d1)/(dotProduct(d1, d1)+dotProduct(qe, d2)); t -= dotProduct(qe, d1)/(dotProduct(d1, d1)+dotProduct(qe, d2));
if (t <= 0 || t >= 1) if (t <= 0 || t >= 1)
break; break;
qe = qa+3*t*ab+3*t*t*br+t*t*t*as; qe = qa+3*t*ab+3*t*t*br+t*t*t*as;
double distance = qe.length(); d1 = 3*ab+6*t*br+3*t*t*as;
if (distance < fabs(minDistance)) { }
minDistance = nonZeroSign(crossProduct(d1, qe))*distance; double distance = qe.length();
param = t; if (distance < fabs(minDistance)) {
} minDistance = nonZeroSign(crossProduct(d1, qe))*distance;
param = t;
} }
} }