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:
parent
f865901bd2
commit
4ca7548ffe
20
polygon.cpp
20
polygon.cpp
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user