Generate intersection curves for surfaces of extrusion along a
parallel axis (which are always lines parallel to that axis). Remove short pwl segments when possible, to avoid short edges that get misclassified. [git-p4: depot-paths = "//depot/solvespace/": change = 1952]solver
parent
d6d198ee40
commit
40ed1b7ac1
|
@ -36,9 +36,9 @@ SCurve SCurve::MakeCopySplitAgainst(SShell *agnstA, SShell *agnstB,
|
||||||
ret = *this;
|
ret = *this;
|
||||||
ZERO(&(ret.pts));
|
ZERO(&(ret.pts));
|
||||||
|
|
||||||
Vector *p = pts.First();
|
SCurvePt *p = pts.First();
|
||||||
if(!p) oops();
|
if(!p) oops();
|
||||||
Vector prev = *p;
|
SCurvePt prev = *p;
|
||||||
ret.pts.Add(p);
|
ret.pts.Add(p);
|
||||||
p = pts.NextAfter(p);
|
p = pts.NextAfter(p);
|
||||||
|
|
||||||
|
@ -47,8 +47,10 @@ SCurve SCurve::MakeCopySplitAgainst(SShell *agnstA, SShell *agnstB,
|
||||||
ZERO(&il);
|
ZERO(&il);
|
||||||
|
|
||||||
// Find all the intersections with the two passed shells
|
// Find all the intersections with the two passed shells
|
||||||
if(agnstA) agnstA->AllPointsIntersecting(prev, *p, &il, true,true,true);
|
if(agnstA)
|
||||||
if(agnstB) agnstB->AllPointsIntersecting(prev, *p, &il, true,true,true);
|
agnstA->AllPointsIntersecting(prev.p, p->p, &il, true, true, true);
|
||||||
|
if(agnstB)
|
||||||
|
agnstB->AllPointsIntersecting(prev.p, p->p, &il, true, true, true);
|
||||||
|
|
||||||
if(il.n > 0) {
|
if(il.n > 0) {
|
||||||
// The intersections were generated by intersecting the pwl
|
// The intersections were generated by intersecting the pwl
|
||||||
|
@ -65,8 +67,8 @@ SCurve SCurve::MakeCopySplitAgainst(SShell *agnstA, SShell *agnstB,
|
||||||
// And now sort them in order along the line. Note that we must
|
// And now sort them in order along the line. Note that we must
|
||||||
// do that after refining, in case the refining would make two
|
// do that after refining, in case the refining would make two
|
||||||
// points switch places.
|
// points switch places.
|
||||||
LineStart = prev;
|
LineStart = prev.p;
|
||||||
LineDirection = p->Minus(prev);
|
LineDirection = (p->p).Minus(prev.p);
|
||||||
qsort(il.elem, il.n, sizeof(il.elem[0]), ByTAlongLine);
|
qsort(il.elem, il.n, sizeof(il.elem[0]), ByTAlongLine);
|
||||||
|
|
||||||
// And now uses the intersections to generate our split pwl edge(s)
|
// And now uses the intersections to generate our split pwl edge(s)
|
||||||
|
@ -76,7 +78,11 @@ SCurve SCurve::MakeCopySplitAgainst(SShell *agnstA, SShell *agnstB,
|
||||||
// On-edge intersection will generate same split point for
|
// On-edge intersection will generate same split point for
|
||||||
// both surfaces, so don't create zero-length edge.
|
// both surfaces, so don't create zero-length edge.
|
||||||
if(!prev.Equals(pi->p)) {
|
if(!prev.Equals(pi->p)) {
|
||||||
ret.pts.Add(&(pi->p));
|
SCurvePt scpt;
|
||||||
|
scpt.tag = 0;
|
||||||
|
scpt.p = pi->p;
|
||||||
|
scpt.vertex = true;
|
||||||
|
ret.pts.Add(&scpt);
|
||||||
}
|
}
|
||||||
prev = pi->p;
|
prev = pi->p;
|
||||||
}
|
}
|
||||||
|
@ -329,8 +335,8 @@ SSurface SSurface::MakeCopyTrimAgainst(SShell *agnst, SShell *parent,
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
for(i = 1; i < sc->pts.n; i++) {
|
for(i = 1; i < sc->pts.n; i++) {
|
||||||
Vector a = sc->pts.elem[i-1],
|
Vector a = sc->pts.elem[i-1].p,
|
||||||
b = sc->pts.elem[i];
|
b = sc->pts.elem[i].p;
|
||||||
|
|
||||||
Point2d auv, buv;
|
Point2d auv, buv;
|
||||||
ss->ClosestPointTo(a, &(auv.x), &(auv.y));
|
ss->ClosestPointTo(a, &(auv.x), &(auv.y));
|
||||||
|
@ -506,6 +512,22 @@ void SShell::MakeFromBoolean(SShell *a, SShell *b, int type) {
|
||||||
// the surfaces in B (which is all of the intersection curves).
|
// the surfaces in B (which is all of the intersection curves).
|
||||||
a->MakeIntersectionCurvesAgainst(b, this);
|
a->MakeIntersectionCurvesAgainst(b, this);
|
||||||
|
|
||||||
|
SCurve *sc;
|
||||||
|
for(sc = curve.First(); sc; sc = curve.NextAfter(sc)) {
|
||||||
|
SSurface *srfA, *srfB;
|
||||||
|
if(sc->source == SCurve::FROM_A) {
|
||||||
|
srfA = a->surface.FindById(sc->surfA);
|
||||||
|
srfB = a->surface.FindById(sc->surfB);
|
||||||
|
} else if(sc->source == SCurve::FROM_B) {
|
||||||
|
srfA = b->surface.FindById(sc->surfA);
|
||||||
|
srfB = b->surface.FindById(sc->surfB);
|
||||||
|
} else if(sc->source == SCurve::FROM_INTERSECTION) {
|
||||||
|
srfA = a->surface.FindById(sc->surfA);
|
||||||
|
srfB = b->surface.FindById(sc->surfB);
|
||||||
|
}
|
||||||
|
sc->RemoveShortSegments(srfA, srfB);
|
||||||
|
}
|
||||||
|
|
||||||
if(b->surface.n == 0 || a->surface.n == 0) {
|
if(b->surface.n == 0 || a->surface.n == 0) {
|
||||||
// Then trim and copy the surfaces
|
// Then trim and copy the surfaces
|
||||||
a->CopySurfacesTrimAgainst(b, this, type, true);
|
a->CopySurfacesTrimAgainst(b, this, type, true);
|
||||||
|
@ -518,7 +540,6 @@ void SShell::MakeFromBoolean(SShell *a, SShell *b, int type) {
|
||||||
// Now that we've copied the surfaces, we know their new hSurfaces, so
|
// Now that we've copied the surfaces, we know their new hSurfaces, so
|
||||||
// rewrite the curves to refer to the surfaces by their handles in the
|
// rewrite the curves to refer to the surfaces by their handles in the
|
||||||
// result.
|
// result.
|
||||||
SCurve *sc;
|
|
||||||
for(sc = curve.First(); sc; sc = curve.NextAfter(sc)) {
|
for(sc = curve.First(); sc; sc = curve.NextAfter(sc)) {
|
||||||
if(sc->source == SCurve::FROM_A) {
|
if(sc->source == SCurve::FROM_A) {
|
||||||
sc->surfA = a->surface.FindById(sc->surfA)->newH;
|
sc->surfA = a->surface.FindById(sc->surfA)->newH;
|
||||||
|
|
|
@ -388,9 +388,10 @@ SCurve SCurve::FromTransformationOf(SCurve *a, Vector t, Quaternion q) {
|
||||||
ret.surfA = a->surfA;
|
ret.surfA = a->surfA;
|
||||||
ret.surfB = a->surfB;
|
ret.surfB = a->surfB;
|
||||||
|
|
||||||
Vector *p;
|
SCurvePt *p;
|
||||||
for(p = a->pts.First(); p; p = a->pts.NextAfter(p)) {
|
for(p = a->pts.First(); p; p = a->pts.NextAfter(p)) {
|
||||||
Vector pp = (q.Rotate(*p)).Plus(t);
|
SCurvePt pp = *p;
|
||||||
|
pp.p = (q.Rotate(p->p)).Plus(t);
|
||||||
ret.pts.Add(&pp);
|
ret.pts.Add(&pp);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -400,6 +401,55 @@ void SCurve::Clear(void) {
|
||||||
pts.Clear();
|
pts.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// When we split line segments wherever they intersect a surface, we introduce
|
||||||
|
// extra pwl points. This may create very short edges that could be removed
|
||||||
|
// without violating the chord tolerance. Those are ugly, and also break
|
||||||
|
// stuff in the Booleans. So remove them.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void SCurve::RemoveShortSegments(SSurface *srfA, SSurface *srfB) {
|
||||||
|
if(pts.n < 2) return;
|
||||||
|
pts.ClearTags();
|
||||||
|
|
||||||
|
Vector prev = pts.elem[0].p;
|
||||||
|
int i, a;
|
||||||
|
for(i = 1; i < pts.n - 1; i++) {
|
||||||
|
SCurvePt *sct = &(pts.elem[i]),
|
||||||
|
*scn = &(pts.elem[i+1]);
|
||||||
|
if(sct->vertex) {
|
||||||
|
prev = sct->p;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
bool mustKeep = false;
|
||||||
|
|
||||||
|
// We must check against both surfaces; the piecewise linear edge
|
||||||
|
// may have a different chord tolerance in the two surfaces. (For
|
||||||
|
// example, a circle in the surface of a cylinder is just a straight
|
||||||
|
// line, so it always has perfect chord tol, but that circle in
|
||||||
|
// a plane is a circle so it doesn't).
|
||||||
|
for(a = 0; a < 2; a++) {
|
||||||
|
SSurface *srf = (a == 0) ? srfA : srfB;
|
||||||
|
Vector puv, nuv;
|
||||||
|
srf->ClosestPointTo(prev, &(puv.x), &(puv.y));
|
||||||
|
srf->ClosestPointTo(scn->p, &(nuv.x), &(nuv.y));
|
||||||
|
|
||||||
|
if(srf->ChordToleranceForEdge(nuv, puv) > SS.ChordTolMm()) {
|
||||||
|
mustKeep = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mustKeep) {
|
||||||
|
prev = sct->p;
|
||||||
|
} else {
|
||||||
|
sct->tag = 1;
|
||||||
|
// and prev is unchanged, since there's no longer any point
|
||||||
|
// in between
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pts.RemoveTagged();
|
||||||
|
}
|
||||||
|
|
||||||
STrimBy STrimBy::EntireCurve(SShell *shell, hSCurve hsc, bool backwards) {
|
STrimBy STrimBy::EntireCurve(SShell *shell, hSCurve hsc, bool backwards) {
|
||||||
STrimBy stb;
|
STrimBy stb;
|
||||||
ZERO(&stb);
|
ZERO(&stb);
|
||||||
|
@ -407,12 +457,12 @@ STrimBy STrimBy::EntireCurve(SShell *shell, hSCurve hsc, bool backwards) {
|
||||||
SCurve *sc = shell->curve.FindById(hsc);
|
SCurve *sc = shell->curve.FindById(hsc);
|
||||||
|
|
||||||
if(backwards) {
|
if(backwards) {
|
||||||
stb.finish = sc->pts.elem[0];
|
stb.finish = sc->pts.elem[0].p;
|
||||||
stb.start = sc->pts.elem[sc->pts.n - 1];
|
stb.start = sc->pts.elem[sc->pts.n - 1].p;
|
||||||
stb.backwards = true;
|
stb.backwards = true;
|
||||||
} else {
|
} else {
|
||||||
stb.start = sc->pts.elem[0];
|
stb.start = sc->pts.elem[0].p;
|
||||||
stb.finish = sc->pts.elem[sc->pts.n - 1];
|
stb.finish = sc->pts.elem[sc->pts.n - 1].p;
|
||||||
stb.backwards = false;
|
stb.backwards = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -199,6 +199,20 @@ void SBezier::SplitAt(double t, SBezier *bef, SBezier *aft) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SBezier::MakePwlInto(List<SCurvePt> *l) {
|
||||||
|
List<Vector> lv;
|
||||||
|
ZERO(&lv);
|
||||||
|
MakePwlInto(&lv);
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < lv.n; i++) {
|
||||||
|
SCurvePt scpt;
|
||||||
|
scpt.tag = 0;
|
||||||
|
scpt.p = lv.elem[i];
|
||||||
|
scpt.vertex = (i == 0) || (i == (lv.n - 1));
|
||||||
|
l->Add(&scpt);
|
||||||
|
}
|
||||||
|
lv.Clear();
|
||||||
|
}
|
||||||
void SBezier::MakePwlInto(List<Vector> *l) {
|
void SBezier::MakePwlInto(List<Vector> *l) {
|
||||||
l->Add(&(ctrl[0]));
|
l->Add(&(ctrl[0]));
|
||||||
MakePwlWorker(l, 0.0, 1.0);
|
MakePwlWorker(l, 0.0, 1.0);
|
||||||
|
|
|
@ -202,7 +202,7 @@ void SSurface::MakeTrimEdgesInto(SEdgeList *sel, bool asUv,
|
||||||
increment = 1;
|
increment = 1;
|
||||||
}
|
}
|
||||||
for(i = first; i != (last + increment); i += increment) {
|
for(i = first; i != (last + increment); i += increment) {
|
||||||
Vector *pt = &(sc->pts.elem[i]);
|
Vector *pt = &(sc->pts.elem[i].p);
|
||||||
if(asUv) {
|
if(asUv) {
|
||||||
ClosestPointTo(*pt, &u, &v);
|
ClosestPointTo(*pt, &u, &v);
|
||||||
ptuv = Vector::From(u, v, 0);
|
ptuv = Vector::From(u, v, 0);
|
||||||
|
|
|
@ -7,6 +7,7 @@ double Bernstein(int k, int deg, double t);
|
||||||
double BernsteinDerivative(int k, int deg, double t);
|
double BernsteinDerivative(int k, int deg, double t);
|
||||||
|
|
||||||
class SSurface;
|
class SSurface;
|
||||||
|
class SCurvePt;
|
||||||
|
|
||||||
// Utility data structure, a two-dimensional BSP to accelerate polygon
|
// Utility data structure, a two-dimensional BSP to accelerate polygon
|
||||||
// operations.
|
// operations.
|
||||||
|
@ -67,6 +68,7 @@ public:
|
||||||
Vector Start(void);
|
Vector Start(void);
|
||||||
Vector Finish(void);
|
Vector Finish(void);
|
||||||
bool Equals(SBezier *b);
|
bool Equals(SBezier *b);
|
||||||
|
void MakePwlInto(List<SCurvePt> *l);
|
||||||
void MakePwlInto(List<Vector> *l);
|
void MakePwlInto(List<Vector> *l);
|
||||||
void MakePwlWorker(List<Vector> *l, double ta, double tb);
|
void MakePwlWorker(List<Vector> *l, double ta, double tb);
|
||||||
|
|
||||||
|
@ -123,6 +125,13 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
// Stuff for the surface trim curves: piecewise linear
|
// Stuff for the surface trim curves: piecewise linear
|
||||||
|
class SCurvePt {
|
||||||
|
public:
|
||||||
|
int tag;
|
||||||
|
Vector p;
|
||||||
|
bool vertex;
|
||||||
|
};
|
||||||
|
|
||||||
class SCurve {
|
class SCurve {
|
||||||
public:
|
public:
|
||||||
hSCurve h;
|
hSCurve h;
|
||||||
|
@ -139,7 +148,7 @@ public:
|
||||||
bool isExact;
|
bool isExact;
|
||||||
SBezier exact;
|
SBezier exact;
|
||||||
|
|
||||||
List<Vector> pts;
|
List<SCurvePt> pts;
|
||||||
|
|
||||||
hSSurface surfA;
|
hSSurface surfA;
|
||||||
hSSurface surfB;
|
hSSurface surfB;
|
||||||
|
@ -147,6 +156,7 @@ public:
|
||||||
static SCurve FromTransformationOf(SCurve *a, Vector t, Quaternion q);
|
static SCurve FromTransformationOf(SCurve *a, Vector t, Quaternion q);
|
||||||
SCurve MakeCopySplitAgainst(SShell *agnstA, SShell *agnstB,
|
SCurve MakeCopySplitAgainst(SShell *agnstA, SShell *agnstB,
|
||||||
SSurface *srfA, SSurface *srfB);
|
SSurface *srfA, SSurface *srfB);
|
||||||
|
void RemoveShortSegments(SSurface *srfA, SSurface *srfB);
|
||||||
|
|
||||||
void Clear(void);
|
void Clear(void);
|
||||||
};
|
};
|
||||||
|
|
|
@ -35,7 +35,7 @@ void SSurface::AddExactIntersectionCurve(SBezier *sb, SSurface *srfB,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(existing) {
|
if(existing) {
|
||||||
Vector *v;
|
SCurvePt *v;
|
||||||
for(v = existing->pts.First(); v; v = existing->pts.NextAfter(v)) {
|
for(v = existing->pts.First(); v; v = existing->pts.NextAfter(v)) {
|
||||||
sc.pts.Add(v);
|
sc.pts.Add(v);
|
||||||
}
|
}
|
||||||
|
@ -51,11 +51,11 @@ void SSurface::AddExactIntersectionCurve(SBezier *sb, SSurface *srfB,
|
||||||
|
|
||||||
if(0 && sb->deg == 1) {
|
if(0 && sb->deg == 1) {
|
||||||
dbp(" ");
|
dbp(" ");
|
||||||
Vector *prev = NULL, *v;
|
SCurvePt *prev = NULL, *v;
|
||||||
dbp("split.pts.n =%d", split.pts.n);
|
dbp("split.pts.n =%d", split.pts.n);
|
||||||
for(v = split.pts.First(); v; v = split.pts.NextAfter(v)) {
|
for(v = split.pts.First(); v; v = split.pts.NextAfter(v)) {
|
||||||
if(prev) {
|
if(prev) {
|
||||||
SS.nakedEdges.AddEdge(*prev, *v);
|
SS.nakedEdges.AddEdge(prev->p, v->p);
|
||||||
}
|
}
|
||||||
prev = v;
|
prev = v;
|
||||||
}
|
}
|
||||||
|
@ -79,6 +79,11 @@ void SSurface::IntersectAgainst(SSurface *b, SShell *agnstA, SShell *agnstB,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector alongt, alongb;
|
||||||
|
SBezier oft, ofb;
|
||||||
|
bool isExtdt = this->IsExtrusion(&oft, &alongt),
|
||||||
|
isExtdb = b->IsExtrusion(&ofb, &alongb);
|
||||||
|
|
||||||
if(degm == 1 && degn == 1 && b->degm == 1 && b->degn == 1) {
|
if(degm == 1 && degn == 1 && b->degm == 1 && b->degn == 1) {
|
||||||
// Line-line intersection; it's a plane or nothing.
|
// Line-line intersection; it's a plane or nothing.
|
||||||
Vector na = NormalAt(0, 0).WithMagnitude(1),
|
Vector na = NormalAt(0, 0).WithMagnitude(1),
|
||||||
|
@ -139,8 +144,8 @@ void SSurface::IntersectAgainst(SSurface *b, SShell *agnstA, SShell *agnstB,
|
||||||
p.Plus(dl.ScaledBy(tmax)));
|
p.Plus(dl.ScaledBy(tmax)));
|
||||||
AddExactIntersectionCurve(&bezier, b, agnstA, agnstB, into);
|
AddExactIntersectionCurve(&bezier, b, agnstA, agnstB, into);
|
||||||
}
|
}
|
||||||
} else if((degm == 1 && degn == 1 && b->IsExtrusion(NULL, NULL)) ||
|
} else if((degm == 1 && degn == 1 && isExtdb) ||
|
||||||
(b->degm == 1 && b->degn == 1 && this->IsExtrusion(NULL, NULL)))
|
(b->degm == 1 && b->degn == 1 && isExtdt))
|
||||||
{
|
{
|
||||||
// The intersection between a plane and a surface of extrusion
|
// The intersection between a plane and a surface of extrusion
|
||||||
SSurface *splane, *sext;
|
SSurface *splane, *sext;
|
||||||
|
@ -202,6 +207,55 @@ void SSurface::IntersectAgainst(SSurface *b, SShell *agnstA, SShell *agnstB,
|
||||||
|
|
||||||
AddExactIntersectionCurve(&bezier, b, agnstA, agnstB, into);
|
AddExactIntersectionCurve(&bezier, b, agnstA, agnstB, into);
|
||||||
}
|
}
|
||||||
|
} else if(isExtdt && isExtdb &&
|
||||||
|
sqrt(fabs(alongt.Dot(alongb))) >
|
||||||
|
sqrt(alongt.Magnitude() * alongb.Magnitude()) - LENGTH_EPS)
|
||||||
|
{
|
||||||
|
// Two surfaces of extrusion along the same axis. So they might
|
||||||
|
// intersect along some number of lines parallel to the axis.
|
||||||
|
Vector axis = alongt.WithMagnitude(1);
|
||||||
|
|
||||||
|
List<SInter> inters;
|
||||||
|
ZERO(&inters);
|
||||||
|
List<Vector> lv;
|
||||||
|
ZERO(&lv);
|
||||||
|
|
||||||
|
Vector axisa = axis.ScaledBy((b->ctrl[0][0]).Dot(axis)),
|
||||||
|
axisb = axis.ScaledBy((b->ctrl[0][1]).Dot(axis)),
|
||||||
|
axisc = (axisa.Plus(axisb)).ScaledBy(0.5);
|
||||||
|
|
||||||
|
oft.MakePwlInto(&lv);
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < lv.n - 1; i++) {
|
||||||
|
Vector pa = lv.elem[i], pb = lv.elem[i+1];
|
||||||
|
pa = pa.Minus(axis.ScaledBy(pa.Dot(axis)));
|
||||||
|
pb = pb.Minus(axis.ScaledBy(pb.Dot(axis)));
|
||||||
|
pa = pa.Plus(axisc);
|
||||||
|
pb = pb.Plus(axisc);
|
||||||
|
|
||||||
|
b->AllPointsIntersecting(pa, pb, &inters, true, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
SInter *si;
|
||||||
|
for(si = inters.First(); si; si = inters.NextAfter(si)) {
|
||||||
|
Vector p = (si->p).Minus(axis.ScaledBy((si->p).Dot(axis)));
|
||||||
|
double ub, vb;
|
||||||
|
b->ClosestPointTo(p, &ub, &vb, true);
|
||||||
|
SSurface plane;
|
||||||
|
plane = SSurface::FromPlane(p, axis.Normal(0), axis.Normal(1));
|
||||||
|
|
||||||
|
b->PointOnSurfaces(this, &plane, &ub, &vb);
|
||||||
|
|
||||||
|
p = b->PointAt(ub, vb);
|
||||||
|
|
||||||
|
SBezier bezier;
|
||||||
|
bezier = SBezier::From(p.Plus(axisa), p.Plus(axisb));
|
||||||
|
AddExactIntersectionCurve(&bezier, b, agnstA, agnstB, into);
|
||||||
|
}
|
||||||
|
|
||||||
|
inters.Clear();
|
||||||
|
lv.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// need to implement general numerical surface intersection for tough
|
// need to implement general numerical surface intersection for tough
|
||||||
|
@ -632,6 +686,7 @@ int SShell::ClassifyPoint(Vector p, Vector edge_n, Vector surf_n) {
|
||||||
|
|
||||||
if(d < dmin) {
|
if(d < dmin) {
|
||||||
dmin = d;
|
dmin = d;
|
||||||
|
|
||||||
if(d < LENGTH_EPS) {
|
if(d < LENGTH_EPS) {
|
||||||
// Edge-on-face (unless edge-on-edge above supercedes)
|
// Edge-on-face (unless edge-on-edge above supercedes)
|
||||||
double dot = (si->surfNormal).Dot(edge_n);
|
double dot = (si->surfNormal).Dot(edge_n);
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
|
|
||||||
marching algorithm for surface intersection
|
marching algorithm for surface intersection
|
||||||
boundary avoidance when casting ray for point-in-shell
|
|
||||||
tangent intersections
|
tangent intersections
|
||||||
short pwl edge avoidance
|
surfaces with coincident control points
|
||||||
assembly
|
assembly
|
||||||
|
|
||||||
-----
|
-----
|
||||||
|
|
Loading…
Reference in New Issue