#include "solvespace.h" void SSurface::IntersectAgainst(SSurface *b, SShell *agnstA, SShell *agnstB, SShell *into) { Vector amax, amin, bmax, bmin; GetAxisAlignedBounding(&amax, &amin); b->GetAxisAlignedBounding(&bmax, &bmin); if(Vector::BoundingBoxesDisjoint(amax, amin, bmax, bmin)) { // They cannot possibly intersect, no curves to generate return; } if(degm == 1 && degn == 1 && b->degm == 1 && b->degn == 1) { // Plane-plane intersection, easy; result is a line Vector pta = ctrl[0][0], ptb = b->ctrl[0][0]; Vector na = NormalAt(0, 0), nb = b->NormalAt(0, 0); na = na.WithMagnitude(1); nb = nb.WithMagnitude(1); Vector d = (na.Cross(nb)); if(d.Magnitude() < LENGTH_EPS) { // parallel planes, no intersection return; } Vector inter = Vector::AtIntersectionOfPlanes(na, na.Dot(pta), nb, nb.Dot(ptb)); // The intersection curve can't be longer than the longest curve // that lies in both planes, which is the diagonal of the shorter; // so just pick one, and then give some slop, not critical. double maxl = ((ctrl[0][0]).Minus(ctrl[1][1])).Magnitude(); Vector v; SCurve sc; ZERO(&sc); sc.surfA = h; sc.surfB = b->h; v = inter.Minus(d.WithMagnitude(5*maxl)); sc.pts.Add(&v); v = inter.Plus(d.WithMagnitude(5*maxl)); sc.pts.Add(&v); // Now split the line where it intersects our existing surfaces SCurve split = sc.MakeCopySplitAgainst(agnstA, agnstB); sc.Clear(); split.interCurve = true; into->curve.AddAndAssignId(&split); } // need to implement general numerical surface intersection for tough // cases, just giving up for now } void SSurface::AllPointsIntersecting(Vector a, Vector b, List *l) { if(degm == 1 && degn == 1) { // line-plane intersection Vector p = ctrl[0][0]; Vector n = NormalAt(0, 0).WithMagnitude(1); double d = n.Dot(p); if((n.Dot(a) - d < -LENGTH_EPS && n.Dot(b) - d > LENGTH_EPS) || (n.Dot(b) - d < -LENGTH_EPS && n.Dot(a) - d > LENGTH_EPS)) { // It crosses the plane, one point of intersection // (a + t*(b - a)) dot n = d // (a dot n) + t*((b - a) dot n) = d // t = (d - (a dot n))/((b - a) dot n) double t = (d - a.Dot(n)) / ((b.Minus(a)).Dot(n)); Vector pi = a.Plus((b.Minus(a)).ScaledBy(t)); Point2d puv, dummy = { 0, 0 }; ClosestPointTo(pi, &(puv.x), &(puv.y)); if(bsp->ClassifyPoint(puv, dummy) != SBspUv::OUTSIDE) { l->Add(&pi); } } } } void SShell::AllPointsIntersecting(Vector a, Vector b, List *il) { SSurface *ss; for(ss = surface.First(); ss; ss = surface.NextAfter(ss)) { ss->AllPointsIntersecting(a, b, il); } }