Skip to content

Commit 162897e

Browse files
phkahlerwhitequark
authored andcommitted
Reimplement DivPivoting as DivProjected.
The old implementation was an approximation, whereas the new one is exact.
1 parent 7f9117b commit 162897e

File tree

8 files changed

+24
-35
lines changed

8 files changed

+24
-35
lines changed

src/drawconstraint.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ int Constraint::DoLineTrimmedAgainstBox(Canvas *canvas, Canvas::hStroke hcs,
148148
}
149149
if(j < 4) continue;
150150

151-
double t = (p.Minus(a)).DivPivoting(dl);
151+
double t = (p.Minus(a)).DivProjected(dl);
152152
tmin = min(t, tmin);
153153
tmax = max(t, tmax);
154154
}
@@ -642,7 +642,7 @@ void Constraint::DoLayout(DrawAs how, Canvas *canvas,
642642
// Draw the projection marker from the closest point on the
643643
// projected line to the projected point on the real line.
644644
Vector lAB = (lA.Minus(lB));
645-
double t = (lA.Minus(closest)).DivPivoting(lAB);
645+
double t = (lA.Minus(closest)).DivProjected(lAB);
646646

647647
Vector lA = SK.GetEntity(line->point[0])->PointGetNum();
648648
Vector lB = SK.GetEntity(line->point[1])->PointGetNum();

src/dsc.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ class Vector {
120120
Vector ScaledBy(double s) const;
121121
Vector ProjectInto(hEntity wrkpl) const;
122122
Vector ProjectVectorInto(hEntity wrkpl) const;
123-
double DivPivoting(Vector delta) const;
123+
double DivProjected(Vector delta) const;
124124
Vector ClosestOrtho() const;
125125
void MakeMaxMin(Vector *maxv, Vector *minv) const;
126126
Vector ClampWithin(double minv, double maxv) const;
@@ -187,7 +187,7 @@ class Point2d {
187187
Point2d Plus(const Point2d &b) const;
188188
Point2d Minus(const Point2d &b) const;
189189
Point2d ScaledBy(double s) const;
190-
double DivPivoting(Point2d delta) const;
190+
double DivProjected(Point2d delta) const;
191191
double Dot(Point2d p) const;
192192
double DistanceTo(const Point2d &p) const;
193193
double DistanceToLine(const Point2d &p0, const Point2d &dp, bool asSegment) const;

src/modify.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -373,8 +373,8 @@ void GraphicsWindow::MakeTangentArc() {
373373
tp[1] = t[1];
374374

375375
// And convert those points to parameter values along the curve.
376-
t[0] += (pa0.Minus(p0)).DivPivoting(t0);
377-
t[1] += (pa1.Minus(p1)).DivPivoting(t1);
376+
t[0] += (pa0.Minus(p0)).DivProjected(t0);
377+
t[1] += (pa1.Minus(p1)).DivProjected(t1);
378378
}
379379

380380
// Stupid check for convergence, and for an out of range result (as

src/polygon.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -164,13 +164,13 @@ bool SEdge::EdgeCrosses(Vector ea, Vector eb, Vector *ppi, SPointList *spl) cons
164164
// on the other
165165
bool inters = false;
166166
double t;
167-
t = a.Minus(ea).DivPivoting(d);
167+
t = a.Minus(ea).DivProjected(d);
168168
if(t > t_eps && t < (1 - t_eps)) inters = true;
169-
t = b.Minus(ea).DivPivoting(d);
169+
t = b.Minus(ea).DivProjected(d);
170170
if(t > t_eps && t < (1 - t_eps)) inters = true;
171-
t = ea.Minus(a).DivPivoting(dthis);
171+
t = ea.Minus(a).DivProjected(dthis);
172172
if(t > tthis_eps && t < (1 - tthis_eps)) inters = true;
173-
t = eb.Minus(a).DivPivoting(dthis);
173+
t = eb.Minus(a).DivProjected(dthis);
174174
if(t > tthis_eps && t < (1 - tthis_eps)) inters = true;
175175

176176
if(inters) {
@@ -500,8 +500,8 @@ void SEdgeList::MergeCollinearSegments(Vector a, Vector b) {
500500
const Vector lineStart = a;
501501
const Vector lineDirection = b.Minus(a);
502502
std::sort(l.begin(), l.end(), [&](const SEdge &a, const SEdge &b) {
503-
double ta = (a.a.Minus(lineStart)).DivPivoting(lineDirection);
504-
double tb = (b.a.Minus(lineStart)).DivPivoting(lineDirection);
503+
double ta = (a.a.Minus(lineStart)).DivProjected(lineDirection);
504+
double tb = (b.a.Minus(lineStart)).DivProjected(lineDirection);
505505

506506
return (ta < tb);
507507
});

src/srf/boolean.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ SCurve SCurve::MakeCopySplitAgainst(SShell *agnstA, SShell *agnstB,
9696
const Vector lineStart = prev.p;
9797
const Vector lineDirection = (p->p).Minus(prev.p);
9898
std::sort(il.begin(), il.end(), [&](const SInter &a, const SInter &b) {
99-
double ta = (a.p.Minus(lineStart)).DivPivoting(lineDirection);
100-
double tb = (b.p.Minus(lineStart)).DivPivoting(lineDirection);
99+
double ta = (a.p.Minus(lineStart)).DivProjected(lineDirection);
100+
double tb = (b.p.Minus(lineStart)).DivProjected(lineDirection);
101101

102102
return (ta < tb);
103103
});

src/srf/ratpoly.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ void SBezier::ClosestPointTo(Vector p, double *t, bool mustConverge) const {
155155

156156
Vector dp = TangentAt(*t);
157157
Vector pc = p.ClosestPointOnLine(p0, dp);
158-
*t += (pc.Minus(p0)).DivPivoting(dp);
158+
*t += (pc.Minus(p0)).DivProjected(dp);
159159
}
160160
if(mustConverge) {
161161
dbp("didn't converge (closest point on bezier curve)");

src/srf/raycast.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ void SSurface::AllPointsIntersecting(Vector a, Vector b,
311311
}
312312
int i;
313313
for(i = 0; i < ip_n; i++) {
314-
double t = (ip[i].Minus(ap)).DivPivoting(bp.Minus(ap));
314+
double t = (ip[i].Minus(ap)).DivProjected(bp.Minus(ap));
315315
// This is a point on the circle; but is it on the arc?
316316
Point2d pp = ap.Plus((bp.Minus(ap)).ScaledBy(t));
317317
double theta = atan2(pp.y, pp.x);
@@ -354,7 +354,7 @@ void SSurface::AllPointsIntersecting(Vector a, Vector b,
354354

355355
// Make sure the point lies within the finite line segment
356356
Vector pxyz = PointAt(puv.x, puv.y);
357-
double t = (pxyz.Minus(a)).DivPivoting(ba);
357+
double t = (pxyz.Minus(a)).DivProjected(ba);
358358
if(asSegment && (t > 1 - LENGTH_EPS/bam || t < LENGTH_EPS/bam)) {
359359
continue;
360360
}
@@ -566,7 +566,7 @@ bool SShell::ClassifyEdge(Class *indir, Class *outdir,
566566

567567
SInter *si;
568568
for(si = l.First(); si; si = l.NextAfter(si)) {
569-
double t = ((si->p).Minus(p)).DivPivoting(ray);
569+
double t = ((si->p).Minus(p)).DivProjected(ray);
570570
if(t*ray.Magnitude() < -LENGTH_EPS) {
571571
// wrong side, doesn't count
572572
continue;

src/util.cpp

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,7 @@ bool Vector::OnLineSegment(Vector a, Vector b, double tol) const {
607607

608608
if(distsq >= tol*tol) return false;
609609

610-
double t = (this->Minus(a)).DivPivoting(d);
610+
double t = (this->Minus(a)).DivProjected(d);
611611
// On-endpoint already tested
612612
if(t < 0 || t > 1) return false;
613613
return true;
@@ -696,16 +696,9 @@ Vector4 Vector::Project4d() const {
696696
return Vector4::From(1, x, y, z);
697697
}
698698

699-
double Vector::DivPivoting(Vector delta) const {
700-
double mx = fabs(delta.x), my = fabs(delta.y), mz = fabs(delta.z);
701-
702-
if(mx > my && mx > mz) {
703-
return x/delta.x;
704-
} else if(my > mz) {
705-
return y/delta.y;
706-
} else {
707-
return z/delta.z;
708-
}
699+
double Vector::DivProjected(Vector delta) const {
700+
return (x*delta.x + y*delta.y + z*delta.z)
701+
/ (delta.x*delta.x + delta.y*delta.y + delta.z*delta.z);
709702
}
710703

711704
Vector Vector::ClosestOrtho() const {
@@ -995,12 +988,8 @@ Point2d Point2d::ScaledBy(double s) const {
995988
return { x * s, y * s };
996989
}
997990

998-
double Point2d::DivPivoting(Point2d delta) const {
999-
if(fabs(delta.x) > fabs(delta.y)) {
1000-
return x/delta.x;
1001-
} else {
1002-
return y/delta.y;
1003-
}
991+
double Point2d::DivProjected(Point2d delta) const {
992+
return (x*delta.x + y*delta.y) / (delta.x*delta.x + delta.y*delta.y);
1004993
}
1005994

1006995
double Point2d::MagSquared() const {

0 commit comments

Comments
 (0)