diff --git a/src/bsp.cpp b/src/bsp.cpp index 825dc0c3..bba7265c 100644 --- a/src/bsp.cpp +++ b/src/bsp.cpp @@ -29,7 +29,7 @@ SBsp3 *SBsp3::FromMesh(SMesh *m) { } for(i = 0; i < mc.l.n; i++) { - bsp3 = bsp3->Insert(&(mc.l.elem[i]), NULL); + bsp3 = InsertOrCreate(bsp3, &(mc.l.elem[i]), NULL); } mc.Clear(); @@ -86,12 +86,12 @@ void SBsp3::InsertHow(int how, STriangle *tr, SMesh *instead) { switch(how) { case POS: if(instead && !pos) goto alt; - pos = pos->Insert(tr, instead); + pos = InsertOrCreate(pos, tr, instead); break; case NEG: if(instead && !neg) goto alt; - neg = neg->Insert(tr, instead); + neg = InsertOrCreate(neg, tr, instead); break; case COPLANAR: { @@ -192,7 +192,7 @@ SBsp3 *SBsp3::InsertConvex(STriMeta meta, Vector *vertex, int cnt, if(onc == 2) { if(!instead) { SEdge se = SEdge::From(on[0], on[1]); - edges = edges->InsertEdge(&se, n, out); + edges = SBsp2::InsertOrCreateEdge(edges, &se, n, out); } } @@ -239,10 +239,10 @@ SBsp3 *SBsp3::InsertConvex(STriMeta meta, Vector *vertex, int cnt, if(!instead) { if(inters == 2) { SEdge se = SEdge::From(inter[0], inter[1]); - edges = edges->InsertEdge(&se, n, out); + edges = SBsp2::InsertOrCreateEdge(edges, &se, n, out); } else if(inters == 1 && onc == 1) { SEdge se = SEdge::From(inter[0], on[0]); - edges = edges->InsertEdge(&se, n, out); + edges = SBsp2::InsertOrCreateEdge(edges, &se, n, out); } else if(inters == 0 && onc == 2) { // We already handled this on-plane existing edge } else { @@ -261,13 +261,13 @@ triangulate: for(i = 0; i < cnt - 2; i++) { STriangle tr = STriangle::From(meta, vertex[0], vertex[i+1], vertex[i+2]); - r = r->Insert(&tr, instead); + r = InsertOrCreate(r, &tr, instead); } return r; } -SBsp3 *SBsp3::Insert(STriangle *tr, SMesh *instead) { - if(!this) { +SBsp3 *SBsp3::InsertOrCreate(SBsp3 *where, STriangle *tr, SMesh *instead) { + if(where == NULL) { if(instead) { if(instead->flipNormal) { instead->atLeastOneDiscarded = true; @@ -284,7 +284,11 @@ SBsp3 *SBsp3::Insert(STriangle *tr, SMesh *instead) { r->tri = *tr; return r; } + where->Insert(tr, instead); + return where; +} +void SBsp3::Insert(STriangle *tr, SMesh *instead) { double dt[3] = { (tr->a).Dot(n), (tr->b).Dot(n), (tr->c).Dot(n) }; int inc = 0, posc = 0, negc = 0; @@ -306,7 +310,7 @@ SBsp3 *SBsp3::Insert(STriangle *tr, SMesh *instead) { // All vertices in-plane if(inc == 3) { InsertHow(COPLANAR, tr, instead); - return this; + return; } // No split required @@ -319,7 +323,7 @@ SBsp3 *SBsp3::Insert(STriangle *tr, SMesh *instead) { else oops(); if(!instead) { SEdge se = SEdge::From(a, b); - edges = edges->InsertEdge(&se, n, tr->Normal()); + edges = SBsp2::InsertOrCreateEdge(edges, &se, n, tr->Normal()); } } @@ -328,7 +332,7 @@ SBsp3 *SBsp3::Insert(STriangle *tr, SMesh *instead) { } else { InsertHow(NEG, tr, instead); } - return this; + return; } // The polygon must be split into two pieces, one above, one below. @@ -356,10 +360,10 @@ SBsp3 *SBsp3::Insert(STriangle *tr, SMesh *instead) { if(!instead) { SEdge se = SEdge::From(a, bPc); - edges = edges->InsertEdge(&se, n, tr->Normal()); + edges = SBsp2::InsertOrCreateEdge(edges, &se, n, tr->Normal()); } - return this; + return; } if(posc == 2 && negc == 1) { @@ -391,21 +395,20 @@ SBsp3 *SBsp3::Insert(STriangle *tr, SMesh *instead) { } if(!instead) { SEdge se = SEdge::From(aPb, cPa); - edges = edges->InsertEdge(&se, n, alone.Normal()); + edges = SBsp2::InsertOrCreateEdge(edges, &se, n, alone.Normal()); } - return this; + return; } void SBsp3::GenerateInPaintOrder(SMesh *m) { - if(!this) return; // Doesn't matter which branch we take if the normal has zero z // component, so don't need a separate case for that. if(n.z < 0) { - pos->GenerateInPaintOrder(m); + if(pos) pos->GenerateInPaintOrder(m); } else { - neg->GenerateInPaintOrder(m); + if(neg) neg->GenerateInPaintOrder(m); } SBsp3 *flip = this; @@ -415,16 +418,15 @@ void SBsp3::GenerateInPaintOrder(SMesh *m) { } if(n.z < 0) { - neg->GenerateInPaintOrder(m); + if(neg) neg->GenerateInPaintOrder(m); } else { - pos->GenerateInPaintOrder(m); + if(pos) pos->GenerateInPaintOrder(m); } } void SBsp3::DebugDraw(void) { - if(!this) return; - pos->DebugDraw(); + if(pos) pos->DebugDraw(); Vector norm = tri.Normal(); glNormal3d(norm.x, norm.y, norm.z); @@ -458,10 +460,10 @@ void SBsp3::DebugDraw(void) { ssglDepthRangeOffset(0); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - more->DebugDraw(); - neg->DebugDraw(); + if(more) more->DebugDraw(); + if(neg) neg->DebugDraw(); - edges->DebugDraw(n, d); + if(edges) edges->DebugDraw(n, d); } ///////////////////////////////// @@ -475,8 +477,8 @@ Vector SBsp2::IntersectionWith(Vector a, Vector b) { return (a.ScaledBy(db/dab)).Plus(b.ScaledBy(-da/dab)); } -SBsp2 *SBsp2::InsertEdge(SEdge *nedge, Vector nnp, Vector out) { - if(!this) { +SBsp2 *SBsp2::InsertOrCreateEdge(SBsp2 *where, SEdge *nedge, Vector nnp, Vector out) { + if(where == NULL) { // Brand new node; so allocate for it, and fill us in. SBsp2 *r = Alloc(); r->np = nnp; @@ -488,6 +490,11 @@ SBsp2 *SBsp2::InsertEdge(SEdge *nedge, Vector nnp, Vector out) { r->edge = *nedge; return r; } + where->InsertEdge(nedge, nnp, out); + return where; +} + +void SBsp2::InsertEdge(SEdge *nedge, Vector nnp, Vector out) { double dt[2] = { (nedge->a).Dot(no), (nedge->b).Dot(no) }; @@ -503,12 +510,12 @@ SBsp2 *SBsp2::InsertEdge(SEdge *nedge, Vector nnp, Vector out) { } if((isPos[0] && isPos[1])||(isPos[0] && isOn[1])||(isOn[0] && isPos[1])) { - pos = pos->InsertEdge(nedge, nnp, out); - return this; + pos = InsertOrCreateEdge(pos, nedge, nnp, out); + return; } if((isNeg[0] && isNeg[1])||(isNeg[0] && isOn[1])||(isOn[0] && isNeg[1])) { - neg = neg->InsertEdge(nedge, nnp, out); - return this; + neg = InsertOrCreateEdge(neg, nedge, nnp, out); + return; } if(isOn[0] && isOn[1]) { SBsp2 *m = Alloc(); @@ -523,7 +530,7 @@ SBsp2 *SBsp2::InsertEdge(SEdge *nedge, Vector nnp, Vector out) { m->more = more; more = m; - return this; + return; } if((isPos[0] && isNeg[1]) || (isNeg[0] && isPos[1])) { Vector aPb = IntersectionWith(nedge->a, nedge->b); @@ -532,13 +539,13 @@ SBsp2 *SBsp2::InsertEdge(SEdge *nedge, Vector nnp, Vector out) { SEdge eb = SEdge::From(aPb, nedge->b); if(isPos[0]) { - pos = pos->InsertEdge(&ea, nnp, out); - neg = neg->InsertEdge(&eb, nnp, out); + pos = InsertOrCreateEdge(pos, &ea, nnp, out); + neg = InsertOrCreateEdge(neg, &eb, nnp, out); } else { - neg = neg->InsertEdge(&ea, nnp, out); - pos = pos->InsertEdge(&eb, nnp, out); + neg = InsertOrCreateEdge(neg, &ea, nnp, out); + pos = InsertOrCreateEdge(pos, &eb, nnp, out); } - return this; + return; } oops(); } @@ -659,8 +666,6 @@ void SBsp2::InsertTriangle(STriangle *tr, SMesh *m, SBsp3 *bsp3) { } void SBsp2::DebugDraw(Vector n, double d) { - if(!this) return; - if(fabs((edge.a).Dot(n) - d) > LENGTH_EPS) oops(); if(fabs((edge.b).Dot(n) - d) > LENGTH_EPS) oops(); @@ -669,9 +674,9 @@ void SBsp2::DebugDraw(Vector n, double d) { ssglVertex3v(edge.a); ssglVertex3v(edge.b); glEnd(); - pos->DebugDraw(n, d); - neg->DebugDraw(n, d); - more->DebugDraw(n, d); + if(pos) pos->DebugDraw(n, d); + if(neg) neg->DebugDraw(n, d); + if(more) more->DebugDraw(n, d); ssglLineWidth(1); } diff --git a/src/export.cpp b/src/export.cpp index 964a91de..eb8a9536 100644 --- a/src/export.cpp +++ b/src/export.cpp @@ -308,7 +308,7 @@ void SolveSpaceUI::ExportLinesAndMesh(SEdgeList *sel, SBezierList *sbl, SMesh *s // Use the BSP routines to generate the split triangles in paint order. SBsp3 *bsp = SBsp3::FromMesh(&smp); SMesh sms = {}; - bsp->GenerateInPaintOrder(&sms); + if(bsp) bsp->GenerateInPaintOrder(&sms); // And cull the back-facing triangles STriangle *tr; sms.l.ClearTags(); diff --git a/src/expr.cpp b/src/expr.cpp index 4d630da4..52e06b05 100644 --- a/src/expr.cpp +++ b/src/expr.cpp @@ -547,7 +547,6 @@ hParam Expr::ReferencedParams(ParamList *pl) { //----------------------------------------------------------------------------- std::string Expr::Print(void) { - if(!this) return "0"; char c; switch(op) { diff --git a/src/mesh.cpp b/src/mesh.cpp index 7880814b..2750569f 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -247,7 +247,7 @@ void SMesh::AddAgainstBsp(SMesh *srcm, SBsp3 *bsp3) { STriangle *st = &(srcm->l.elem[i]); int pn = l.n; atLeastOneDiscarded = false; - bsp3->Insert(st, this); + SBsp3::InsertOrCreate(NULL, st, this); if(!atLeastOneDiscarded && (l.n != (pn+1))) { l.n = pn; if(flipNormal) { diff --git a/src/polygon.h b/src/polygon.h index a4ea0830..69284d31 100644 --- a/src/polygon.h +++ b/src/polygon.h @@ -180,7 +180,8 @@ public: void InsertTriangleHow(int how, STriangle *tr, SMesh *m, SBsp3 *bsp3); void InsertTriangle(STriangle *tr, SMesh *m, SBsp3 *bsp3); Vector IntersectionWith(Vector a, Vector b); - SBsp2 *InsertEdge(SEdge *nedge, Vector nnp, Vector out); + void InsertEdge(SEdge *nedge, Vector nnp, Vector out); + static SBsp2 *InsertOrCreateEdge(SBsp2 *where, SEdge *nedge, Vector nnp, Vector out); static SBsp2 *Alloc(void); void DebugDraw(Vector n, double d); @@ -206,7 +207,8 @@ public: enum { POS = 100, NEG = 101, COPLANAR = 200 }; void InsertHow(int how, STriangle *str, SMesh *instead); - SBsp3 *Insert(STriangle *str, SMesh *instead); + void Insert(STriangle *str, SMesh *instead); + static SBsp3 *InsertOrCreate(SBsp3 *where, STriangle *str, SMesh *instead); void InsertConvexHow(int how, STriMeta meta, Vector *vertex, int n, SMesh *instead); diff --git a/src/srf/boolean.cpp b/src/srf/boolean.cpp index d87dec0c..802aaa58 100644 --- a/src/srf/boolean.cpp +++ b/src/srf/boolean.cpp @@ -83,10 +83,10 @@ SCurve SCurve::MakeCopySplitAgainst(SShell *agnstA, SShell *agnstB, // some slop if points are close to edge and pwl is too coarse, // and it doesn't hurt to split unnecessarily. Point2d dummy = { 0, 0 }; - int c = pi->srf->bsp->ClassifyPoint(puv, dummy, pi->srf); + int c = (pi->srf->bsp) ? pi->srf->bsp->ClassifyPoint(puv, dummy, pi->srf) : SBspUv::OUTSIDE; if(c == SBspUv::OUTSIDE) { - double d; - d = pi->srf->bsp->MinimumDistanceToEdge(puv, pi->srf); + double d = VERY_POSITIVE; + if(pi->srf->bsp) d = pi->srf->bsp->MinimumDistanceToEdge(puv, pi->srf); if(d > SS.ChordTolMm()) { pi->tag = 1; continue; @@ -467,7 +467,7 @@ SSurface SSurface::MakeCopyTrimAgainst(SShell *parent, ss->ClosestPointTo(a, &(auv.x), &(auv.y)); ss->ClosestPointTo(b, &(buv.x), &(buv.y)); - int c = ss->bsp->ClassifyEdge(auv, buv, ss); + int c = (ss->bsp) ? ss->bsp->ClassifyEdge(auv, buv, ss) : SBspUv::OUTSIDE; if(c != SBspUv::OUTSIDE) { Vector ta = Vector::From(0, 0, 0); Vector tb = Vector::From(0, 0, 0); @@ -571,7 +571,7 @@ SSurface SSurface::MakeCopyTrimAgainst(SShell *parent, int indir_shell, outdir_shell, indir_orig, outdir_orig; - int c_this = origBsp->ClassifyEdge(auv, buv, &ret); + int c_this = (origBsp) ? origBsp->ClassifyEdge(auv, buv, &ret) : SBspUv::OUTSIDE; TagByClassifiedEdge(c_this, &indir_orig, &outdir_orig); agnst->ClassifyEdge(&indir_shell, &outdir_shell, @@ -807,7 +807,7 @@ SBspUv *SBspUv::From(SEdgeList *el, SSurface *srf) { SBspUv *bsp = NULL; for(se = work.l.First(); se; se = work.l.NextAfter(se)) { - bsp = bsp->InsertEdge((se->a).ProjectXy(), (se->b).ProjectXy(), srf); + bsp = InsertOrCreateEdge(bsp, (se->a).ProjectXy(), (se->b).ProjectXy(), srf); } work.Clear(); @@ -850,14 +850,18 @@ double SBspUv::ScaledDistanceToLine(Point2d pt, Point2d a, Point2d b, bool seg, return pt.DistanceToLine(a, b, seg); } -SBspUv *SBspUv::InsertEdge(Point2d ea, Point2d eb, SSurface *srf) { - if(!this) { +SBspUv *SBspUv::InsertOrCreateEdge(SBspUv *where, const Point2d &ea, const Point2d &eb, SSurface *srf) { + if(where == NULL) { SBspUv *ret = Alloc(); ret->a = ea; ret->b = eb; return ret; } + where->InsertEdge(ea, eb, srf); + return where; +} +void SBspUv::InsertEdge(Point2d ea, Point2d eb, SSurface *srf) { double dea = ScaledSignedDistanceToLine(ea, a, b, srf), deb = ScaledSignedDistanceToLine(eb, a, b, srf); @@ -871,21 +875,21 @@ SBspUv *SBspUv::InsertEdge(Point2d ea, Point2d eb, SSurface *srf) { } else if(fabs(dea) < LENGTH_EPS) { // Point A lies on this lie, but point B does not if(deb > 0) { - pos = pos->InsertEdge(ea, eb, srf); + pos = InsertOrCreateEdge(pos, ea, eb, srf); } else { - neg = neg->InsertEdge(ea, eb, srf); + neg = InsertOrCreateEdge(neg, ea, eb, srf); } } else if(fabs(deb) < LENGTH_EPS) { // Point B lies on this lie, but point A does not if(dea > 0) { - pos = pos->InsertEdge(ea, eb, srf); + pos = InsertOrCreateEdge(pos, ea, eb, srf); } else { - neg = neg->InsertEdge(ea, eb, srf); + neg = InsertOrCreateEdge(neg, ea, eb, srf); } } else if(dea > 0 && deb > 0) { - pos = pos->InsertEdge(ea, eb, srf); + pos = InsertOrCreateEdge(pos, ea, eb, srf); } else if(dea < 0 && deb < 0) { - neg = neg->InsertEdge(ea, eb, srf); + neg = InsertOrCreateEdge(neg, ea, eb, srf); } else { // New edge crosses this one; we need to split. Point2d n = ((b.Minus(a)).Normal()).WithMagnitude(1); @@ -893,18 +897,17 @@ SBspUv *SBspUv::InsertEdge(Point2d ea, Point2d eb, SSurface *srf) { double t = (d - n.Dot(ea)) / (n.Dot(eb.Minus(ea))); Point2d pi = ea.Plus((eb.Minus(ea)).ScaledBy(t)); if(dea > 0) { - pos = pos->InsertEdge(ea, pi, srf); - neg = neg->InsertEdge(pi, eb, srf); + pos = InsertOrCreateEdge(pos, ea, pi, srf); + neg = InsertOrCreateEdge(neg, pi, eb, srf); } else { - neg = neg->InsertEdge(ea, pi, srf); - pos = pos->InsertEdge(pi, eb, srf); + neg = InsertOrCreateEdge(neg, ea, pi, srf); + pos = InsertOrCreateEdge(pos, pi, eb, srf); } } - return this; + return; } int SBspUv::ClassifyPoint(Point2d p, Point2d eb, SSurface *srf) { - if(!this) return OUTSIDE; double dp = ScaledSignedDistanceToLine(p, a, b, srf); @@ -951,10 +954,9 @@ int SBspUv::ClassifyEdge(Point2d ea, Point2d eb, SSurface *srf) { } double SBspUv::MinimumDistanceToEdge(Point2d p, SSurface *srf) { - if(!this) return VERY_POSITIVE; - double dn = neg->MinimumDistanceToEdge(p, srf), - dp = pos->MinimumDistanceToEdge(p, srf); + double dn = (neg) ? neg->MinimumDistanceToEdge(p, srf) : VERY_POSITIVE; + double dp = (pos) ? pos->MinimumDistanceToEdge(p, srf) : VERY_POSITIVE; Point2d as = a, bs = b; ScalePoints(&p, &as, &bs, srf); diff --git a/src/srf/raycast.cpp b/src/srf/raycast.cpp index d751b338..808287f2 100644 --- a/src/srf/raycast.cpp +++ b/src/srf/raycast.cpp @@ -361,7 +361,7 @@ void SSurface::AllPointsIntersecting(Vector a, Vector b, // And that it lies inside our trim region Point2d dummy = { 0, 0 }; - int c = bsp->ClassifyPoint(puv, dummy, this); + int c = (bsp) ? bsp->ClassifyPoint(puv, dummy, this) : SBspUv::OUTSIDE; if(trimmed && c == SBspUv::OUTSIDE) { continue; } @@ -527,7 +527,7 @@ bool SShell::ClassifyEdge(int *indir, int *outdir, if((pp.Minus(p)).Magnitude() > LENGTH_EPS) continue; Point2d dummy = { 0, 0 }; - int c = srf->bsp->ClassifyPoint(puv, dummy, srf); + int c = (srf->bsp) ? srf->bsp->ClassifyPoint(puv, dummy, srf) : SBspUv::OUTSIDE; if(c == SBspUv::OUTSIDE) continue; // Edge-on-face (unless edge-on-edge above superceded) diff --git a/src/srf/surface.h b/src/srf/surface.h index 2e582584..86d69db3 100644 --- a/src/srf/surface.h +++ b/src/srf/surface.h @@ -45,7 +45,8 @@ public: double ScaledDistanceToLine(Point2d pt, Point2d a, Point2d b, bool seg, SSurface *srf); - SBspUv *InsertEdge(Point2d a, Point2d b, SSurface *srf); + void InsertEdge(Point2d a, Point2d b, SSurface *srf); + static SBspUv *InsertOrCreateEdge(SBspUv *where, const Point2d &ea, const Point2d &eb, SSurface *srf); int ClassifyPoint(Point2d p, Point2d eb, SSurface *srf); int ClassifyEdge(Point2d ea, Point2d eb, SSurface *srf); double MinimumDistanceToEdge(Point2d p, SSurface *srf);