diff --git a/src/srf/surface.h b/src/srf/surface.h index ba4414a..393be4a 100644 --- a/src/srf/surface.h +++ b/src/srf/surface.h @@ -342,6 +342,7 @@ public: void GetAxisAlignedBounding(Vector *ptMax, Vector *ptMin) const; bool CoincidentWithPlane(Vector n, double d) const; bool CoincidentWith(SSurface *ss, bool sameNormal) const; + bool ContainsPlaneCurve(SCurve *sc) const; bool IsExtrusion(SBezier *of, Vector *along) const; bool IsCylinder(Vector *axis, Vector *center, double *r, Vector *start, Vector *finish) const; diff --git a/src/srf/surfinter.cpp b/src/srf/surfinter.cpp index ddcbad2..1e4fb39 100644 --- a/src/srf/surfinter.cpp +++ b/src/srf/surfinter.cpp @@ -313,6 +313,38 @@ void SSurface::IntersectAgainst(SSurface *b, SShell *agnstA, SShell *agnstB, inters.Clear(); lv.Clear(); } else { + if((degm == 1 && degn == 1) || (b->degm == 1 && b->degn == 1)) { + // we should only be here if just one surface is a plane because the + // plane-plane case was already handled above. Need to check the other + // nonplanar surface for trim curves that lie in the plane and are not + // already trimming both surfaces. This happens when we cut a Lathe shell + // on one of the seams for example. + // This also seems necessary to merge some coincident surfaces. + SSurface *splane, *sext; + SShell *shext; + if(degm == 1 && degn == 1) { // this and other checks assume coplanar ctrl pts. + splane = this; + sext = b; + shext = agnstB; + } else { + splane = b; + sext = this; + shext = agnstA; + } + SCurve *sc; + for(sc = shext->curve.First(); sc; sc = shext->curve.NextAfter(sc)) { + if(sc->source == SCurve::Source::INTERSECTION) continue; + if(!sc->isExact) continue; + if((sc->surfA != sext->h) && (sc->surfB != sext->h)) continue; + // we have a curve belonging to the curved surface and not the plane. + // does it lie completely in the plane? + if(splane->ContainsPlaneCurve(sc)) { + SBezier bezier = sc->exact; + AddExactIntersectionCurve(&bezier, b, agnstA, agnstB, into); + } + } + } + // Try intersecting the surfaces numerically, by a marching algorithm. // First, we find all the intersections between a surface and the // boundary of the other surface. @@ -505,6 +537,24 @@ bool SSurface::CoincidentWithPlane(Vector n, double d) const { return true; } +//----------------------------------------------------------------------------- +// Does a planar surface contain a curve? Does the curve lie completely in plane? +//----------------------------------------------------------------------------- +bool SSurface::ContainsPlaneCurve(SCurve *sc) const { + if(degm != 1 || degn != 1) return false; + if(!sc->isExact) return false; // we don't handle those (yet?) + + Vector p = ctrl[0][0]; + Vector n = NormalAt(0, 0).WithMagnitude(1); + double d = n.Dot(p); + + // check all control points on the curve + for(int i=0; i<= sc->exact.deg; i++) { + if(fabs(n.Dot(sc->exact.ctrl[i]) - d) > LENGTH_EPS) return false; + } + return true; +} + //----------------------------------------------------------------------------- // In our shell, find all surfaces that are coincident with the prototype // surface (with same or opposite normal, as specified), and copy all of