@@ -20,6 +20,29 @@ void SShell::MakeFromIntersectionOf(SShell *a, SShell *b) {
2020 MakeFromBoolean (a, b, SSurface::CombineAs::INTERSECTION);
2121}
2222
23+ // We will be inserting existing verticies into curves to split them
24+ // todo: this is only using the ends of exact curves, and it is only
25+ // using them to split existing curves, not new intersections.
26+ // It resolves some issues but we could do better. We will need to
27+ // reorder things so the surface intersection curves exist prior to
28+ // splitting any curves at all in order to have their verticies too.
29+ static void FindVertsOnCurve (List<SInter> *l, const SCurve *curve, SShell *sh) {
30+ for (auto sc : sh->curve ) {
31+ if (!sc.isExact ) continue ;
32+ for (int i=0 ; i<2 ; i++) {
33+ Vector pt = sc.exact .ctrl [ i==0 ? 0 : sc.exact .deg ];
34+ double t;
35+ curve->exact .ClosestPointTo (pt, &t, /* must converge=*/ false );
36+ double d = pt.Minus (curve->exact .PointAt (t)).Magnitude ();
37+ if ((t>LENGTH_EPS) && (t<(1.0 -LENGTH_EPS)) && (d < LENGTH_EPS)) {
38+ SInter inter;
39+ inter.p = pt;
40+ l->Add (&inter);
41+ }
42+ }
43+ }
44+ }
45+
2346// -----------------------------------------------------------------------------
2447// Take our original pwl curve. Wherever an edge intersects a surface within
2548// either agnstA or agnstB, split the piecewise linear element. Then refine
@@ -35,12 +58,21 @@ SCurve SCurve::MakeCopySplitAgainst(SShell *agnstA, SShell *agnstB,
3558 ret = *this ;
3659 ret.pts = {};
3760
61+ // First find any vertex that lies on our curve.
62+ List<SInter> vertpts = {};
63+ if (agnstA)
64+ FindVertsOnCurve (&vertpts, this , agnstA);
65+ if (agnstB)
66+ FindVertsOnCurve (&vertpts, this , agnstB);
67+
3868 const SCurvePt *p = pts.First ();
3969 ssassert (p != NULL , " Cannot split an empty curve" );
4070 SCurvePt prev = *p;
4171 ret.pts .Add (p);
4272 p = pts.NextAfter (p);
43-
73+
74+ if (vertpts.n > 0 ) dbp (" Verts on curve: %d" , vertpts.n );
75+
4476 for (; p; p = pts.NextAfter (p)) {
4577 List<SInter> il = {};
4678
@@ -100,12 +132,21 @@ SCurve SCurve::MakeCopySplitAgainst(SShell *agnstA, SShell *agnstB,
100132 pi->p = (pi->srf )->PointAt (puv);
101133 }
102134 il.RemoveTagged ();
103-
135+ }
136+ // Now add any vertex that is on this segment
137+ const Vector lineStart = prev.p ;
138+ const Vector lineDirection = (p->p ).Minus (prev.p );
139+ for (auto vtx : vertpts) {
140+ double t = (vtx.p .Minus (lineStart)).DivProjected (lineDirection);
141+ if ((0.0 < t) && (t < 1.0 )) {
142+ il.Add (&vtx);
143+ }
144+ }
145+ if (!il.IsEmpty ()) {
146+ SInter *pi;
104147 // And now sort them in order along the line. Note that we must
105148 // do that after refining, in case the refining would make two
106149 // points switch places.
107- const Vector lineStart = prev.p ;
108- const Vector lineDirection = (p->p ).Minus (prev.p );
109150 std::sort (il.begin (), il.end (), [&](const SInter &a, const SInter &b) {
110151 double ta = (a.p .Minus (lineStart)).DivProjected (lineDirection);
111152 double tb = (b.p .Minus (lineStart)).DivProjected (lineDirection);
@@ -133,6 +174,7 @@ SCurve SCurve::MakeCopySplitAgainst(SShell *agnstA, SShell *agnstB,
133174 ret.pts .Add (p);
134175 prev = *p;
135176 }
177+ vertpts.Clear ();
136178 return ret;
137179}
138180
0 commit comments