Skip to content

Commit

Permalink
Resovle a huge performance regression introduced by commit ab10e38 wh…
Browse files Browse the repository at this point in the history
…ile still fixing the NURBS issues resolved by that commit with only modest speed penalty. The performance is significantly improved by using bounding box tests on curves prior to doing complex intersection testing.
  • Loading branch information
phkahler committed Oct 23, 2020
1 parent 0761339 commit 0f1ece2
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 14 deletions.
48 changes: 34 additions & 14 deletions src/srf/boolean.cpp
Expand Up @@ -20,18 +20,36 @@ void SShell::MakeFromIntersectionOf(SShell *a, SShell *b) {
MakeFromBoolean(a, b, SSurface::CombineAs::INTERSECTION);
}

// We will be inserting existing verticies into curves to split them
// todo: this is only using the ends of exact curves, and it is only
// using them to split existing curves, not new intersections.
// It resolves some issues but we could do better. We will need to
// reorder things so the surface intersection curves exist prior to
// splitting any curves at all in order to have their verticies too.
// Better still would be to get curve/surface intersection to work
// more reliably at the edges - maybe do curve/curve tests as part
// of the curve-surface intersection test.
void SCurve::GetAxisAlignedBounding(Vector *ptMax, Vector *ptMin) const {
*ptMax = {VERY_NEGATIVE, VERY_NEGATIVE, VERY_NEGATIVE};
*ptMin = {VERY_POSITIVE, VERY_POSITIVE, VERY_POSITIVE};

for(int i = 0; i <= exact.deg; i++) {
exact.ctrl[i].MakeMaxMin(ptMax, ptMin);
}
}

// We will be inserting other curve verticies into our curves to split them.
// This is helpful when curved surfaces become tangent along a trim and the
// usual tests for curve-surface intersection don't split the curve at a vertex.
// This is faster than the previous version that split at surface corners and
// handles more buggy cases. It's not clear this is the best way but it works ok.
static void FindVertsOnCurve(List<SInter> *l, const SCurve *curve, SShell *sh) {

Vector amax, amin;
curve->GetAxisAlignedBounding(&amax, &amin);

for(auto sc : sh->curve) {
if(!sc.isExact) continue;

Vector cmax, cmin;
sc.GetAxisAlignedBounding(&cmax, &cmin);

if(Vector::BoundingBoxesDisjoint(amax, amin, cmax, cmin)) {
// They cannot possibly intersect, no curves to generate
continue;
}

for(int i=0; i<2; i++) {
Vector pt = sc.exact.ctrl[ i==0 ? 0 : sc.exact.deg ];
double t;
Expand Down Expand Up @@ -63,11 +81,13 @@ SCurve SCurve::MakeCopySplitAgainst(SShell *agnstA, SShell *agnstB,

// First find any vertex that lies on our curve.
List<SInter> vertpts = {};
if(agnstA)
FindVertsOnCurve(&vertpts, this, agnstA);
if(agnstB)
FindVertsOnCurve(&vertpts, this, agnstB);

if(isExact) {
if(agnstA)
FindVertsOnCurve(&vertpts, this, agnstA);
if(agnstB)
FindVertsOnCurve(&vertpts, this, agnstB);
}

const SCurvePt *p = pts.First();
ssassert(p != NULL, "Cannot split an empty curve");
SCurvePt prev = *p;
Expand Down
1 change: 1 addition & 0 deletions src/srf/surface.h
Expand Up @@ -219,6 +219,7 @@ class SCurve {
SSurface *GetSurfaceB(SShell *a, SShell *b) const;

void Clear();
void GetAxisAlignedBounding(Vector *ptMax, Vector *ptMin) const;
};

// A segment of a curve by which a surface is trimmed: indicates which curve,
Expand Down

0 comments on commit 0f1ece2

Please sign in to comment.