Don't merge two coincident surfaces unless they share an edge.

Otherwise, we might merge in ways that make things slower (because
the bboxes aren't as tight) or less robust (because the
intersection needs to be split in more places, and that might fail).

[git-p4: depot-paths = "//depot/solvespace/": change = 2003]
This commit is contained in:
Jonathan Westhues 2009-06-29 20:38:40 -08:00
parent f865901bd2
commit 4ca7548ffe
3 changed files with 67 additions and 20 deletions

View File

@ -225,6 +225,26 @@ intersects:
return cnt; return cnt;
} }
//-----------------------------------------------------------------------------
// Returns true if the intersecting edge list contains an edge that shares
// an endpoint with one of our edges.
//-----------------------------------------------------------------------------
bool SEdgeList::ContainsEdgeFrom(SEdgeList *sel) {
SEdge *se;
for(se = l.First(); se; se = l.NextAfter(se)) {
if(sel->ContainsEdge(se)) return true;
}
return false;
}
bool SEdgeList::ContainsEdge(SEdge *set) {
SEdge *se;
for(se = l.First(); se; se = l.NextAfter(se)) {
if((se->a).Equals(set->a) && (se->b).Equals(set->b)) return true;
if((se->b).Equals(set->a) && (se->a).Equals(set->b)) return true;
}
return false;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Remove unnecessary edges: if two are anti-parallel then remove both, and if // Remove unnecessary edges: if two are anti-parallel then remove both, and if
// two are parallel then remove one. // two are parallel then remove one.

View File

@ -26,6 +26,8 @@ public:
bool AssembleContour(Vector first, Vector last, SContour *dest, bool AssembleContour(Vector first, Vector last, SContour *dest,
SEdge *errorAt, bool keepDir); SEdge *errorAt, bool keepDir);
int AnyEdgeCrossings(Vector a, Vector b, Vector *pi=NULL); int AnyEdgeCrossings(Vector a, Vector b, Vector *pi=NULL);
bool ContainsEdgeFrom(SEdgeList *sel);
bool ContainsEdge(SEdge *se);
void CullExtraneousEdges(void); void CullExtraneousEdges(void);
void MergeCollinearSegments(Vector a, Vector b); void MergeCollinearSegments(Vector a, Vector b);
}; };

View File

@ -16,11 +16,17 @@ void SShell::MergeCoincidentSurfaces(void) {
// Let someone else clean up the empty surfaces; we can certainly merge // Let someone else clean up the empty surfaces; we can certainly merge
// them, but we don't know how to calculate a reasonable bounding box. // them, but we don't know how to calculate a reasonable bounding box.
if(si->trim.n == 0) continue; if(si->trim.n == 0) continue;
// And for now we handle only coincident planes, so no sense wasting
// time on other surfaces.
if(si->degm != 1 || si->degn != 1) continue;
SEdgeList sel; SEdgeList sel;
ZERO(&sel); ZERO(&sel);
si->MakeEdgesInto(this, &sel, false);
bool merged = false; bool mergedThisTime, merged = false;
do {
mergedThisTime = false;
for(j = i + 1; j < surface.n; j++) { for(j = i + 1; j < surface.n; j++) {
sj = &(surface.elem[j]); sj = &(surface.elem[j]);
@ -30,13 +36,27 @@ void SShell::MergeCoincidentSurfaces(void) {
// But we do merge surfaces with different face entities, since // But we do merge surfaces with different face entities, since
// otherwise we'd hardly ever merge anything. // otherwise we'd hardly ever merge anything.
// This surface is coincident, so it gets merged. // This surface is coincident. But let's not merge coincident
// surfaces if they contain disjoint contours; that just makes
// the bounding box tests less effective, and possibly things
// less robust.
SEdgeList tel;
ZERO(&tel);
sj->MakeEdgesInto(this, &tel, false);
if(!sel.ContainsEdgeFrom(&tel)) {
tel.Clear();
continue;
}
tel.Clear();
sj->tag = 1; sj->tag = 1;
merged = true; merged = true;
mergedThisTime = true;
sj->MakeEdgesInto(this, &sel, false); sj->MakeEdgesInto(this, &sel, false);
sj->trim.Clear(); sj->trim.Clear();
// All the references to this surface get replaced with the new srf // All the references to this surface get replaced with the
// new srf
SCurve *sc; SCurve *sc;
for(sc = curve.First(); sc; sc = curve.NextAfter(sc)) { for(sc = curve.First(); sc; sc = curve.NextAfter(sc)) {
if(sc->surfA.v == sj->h.v) sc->surfA = si->h; if(sc->surfA.v == sj->h.v) sc->surfA = si->h;
@ -44,8 +64,12 @@ void SShell::MergeCoincidentSurfaces(void) {
} }
} }
// If this iteration merged a contour onto ours, then we have to
// go through the surfaces again; that might have made a new
// surface touch us.
} while(mergedThisTime);
if(merged) { if(merged) {
si->MakeEdgesInto(this, &sel, false);
sel.CullExtraneousEdges(); sel.CullExtraneousEdges();
si->trim.Clear(); si->trim.Clear();
si->TrimFromEdgeList(&sel, false); si->TrimFromEdgeList(&sel, false);
@ -95,6 +119,7 @@ void SShell::MergeCoincidentSurfaces(void) {
si->ctrl[1][0] = si->ctrl[1][0] =
Vector::From(umax, vmin, nt).ScaleOutOfCsys(u, v, n); Vector::From(umax, vmin, nt).ScaleOutOfCsys(u, v, n);
} }
sel.Clear();
} }
surface.RemoveTagged(); surface.RemoveTagged();