Add code to assemble two shells into one, without checking for any

intersections or otherwise trying to make the result not
self-intersecting.

[git-p4: depot-paths = "//depot/solvespace/": change = 1955]
solver
Jonathan Westhues 2009-05-19 19:04:36 -08:00
parent bc6bdfade8
commit b4dfb1aded
5 changed files with 80 additions and 18 deletions

View File

@ -212,6 +212,7 @@ void Group::MenuGroup(int id) {
if(!GetOpenFile(g.impFile, SLVS_EXT, SLVS_PATTERN)) return; if(!GetOpenFile(g.impFile, SLVS_EXT, SLVS_PATTERN)) return;
} }
g.name.strcpy("import"); g.name.strcpy("import");
g.meshCombine = COMBINE_AS_ASSEMBLE;
break; break;
} }

View File

@ -100,8 +100,10 @@ void Group::GenerateShellForStepAndRepeat(void) {
if(src->meshCombine == COMBINE_AS_DIFFERENCE) { if(src->meshCombine == COMBINE_AS_DIFFERENCE) {
scratch->MakeFromDifferenceOf(soFar, &transd); scratch->MakeFromDifferenceOf(soFar, &transd);
} else { } else if(src->meshCombine == COMBINE_AS_UNION) {
scratch->MakeFromUnionOf(soFar, &transd); scratch->MakeFromUnionOf(soFar, &transd);
} else {
scratch->MakeFromAssemblyOf(soFar, &transd);
} }
SWAP(SShell *, scratch, soFar); SWAP(SShell *, scratch, soFar);
@ -244,8 +246,7 @@ void Group::GenerateShellAndMesh(void) {
} else if(meshCombine == COMBINE_AS_DIFFERENCE) { } else if(meshCombine == COMBINE_AS_DIFFERENCE) {
runningShell.MakeFromDifferenceOf(a, &thisShell); runningShell.MakeFromDifferenceOf(a, &thisShell);
} else { } else {
runningShell.MakeFromUnionOf(a, &thisShell); runningShell.MakeFromAssemblyOf(a, &thisShell);
// TODO, assembly
} }
done: done:

View File

@ -498,6 +498,78 @@ void SShell::CleanupAfterBoolean(void) {
} }
} }
//-----------------------------------------------------------------------------
// All curves contain handles to the two surfaces that they trim. After a
// Boolean or assembly, we must rewrite those handles to refer to the curves
// by their new IDs.
//-----------------------------------------------------------------------------
void SShell::RewriteSurfaceHandlesForCurves(SShell *a, SShell *b) {
SCurve *sc;
for(sc = curve.First(); sc; sc = curve.NextAfter(sc)) {
if(sc->source == SCurve::FROM_A) {
sc->surfA = a->surface.FindById(sc->surfA)->newH;
sc->surfB = a->surface.FindById(sc->surfB)->newH;
} else if(sc->source == SCurve::FROM_B) {
sc->surfA = b->surface.FindById(sc->surfA)->newH;
sc->surfB = b->surface.FindById(sc->surfB)->newH;
} else if(sc->source == SCurve::FROM_INTERSECTION) {
sc->surfA = a->surface.FindById(sc->surfA)->newH;
sc->surfB = b->surface.FindById(sc->surfB)->newH;
} else {
oops();
}
}
}
//-----------------------------------------------------------------------------
// Copy all the surfaces and curves from two different shells into a single
// shell. The only difficulty is to rewrite all of their handles; we don't
// look for any surface intersections, so if two objects interfere then the
// result is just self-intersecting. This is used for assembly, since it's
// much faster than merging as union.
//-----------------------------------------------------------------------------
void SShell::MakeFromAssemblyOf(SShell *a, SShell *b) {
Vector t = Vector::From(0, 0, 0);
Quaternion q = Quaternion::IDENTITY;
int i = 0;
SShell *ab;
// First, copy over all the curves. Note which shell (a or b) each curve
// came from, but assign it a new ID.
SCurve *c, cn;
for(i = 0; i < 2; i++) {
ab = (i == 0) ? a : b;
for(c = ab->curve.First(); c; c = ab->curve.NextAfter(c)) {
cn = SCurve::FromTransformationOf(c, t, q);
cn.source = (i == 0) ? SCurve::FROM_A : SCurve::FROM_B;
// surfA and surfB are wrong now, and we can't fix them until
// we've assigned IDs to the surfaces. So we'll get that later.
c->newH = curve.AddAndAssignId(&cn);
}
}
// Likewise copy over all the surfaces.
SSurface *s, sn;
for(i = 0; i < 2; i++) {
ab = (i == 0) ? a : b;
for(s = ab->surface.First(); s; s = ab->surface.NextAfter(s)) {
sn = SSurface::FromTransformationOf(s, t, q, true);
// All the trim curve IDs get rewritten; we know the new handles
// to the curves since we recorded them in the previous step.
STrimBy *stb;
for(stb = sn.trim.First(); stb; stb = sn.trim.NextAfter(stb)) {
stb->curve = ab->curve.FindById(stb->curve)->newH;
}
s->newH = surface.AddAndAssignId(&sn);
}
}
// Finally, rewrite the surfaces associated with each curve to use the
// new handles.
RewriteSurfaceHandlesForCurves(a, b);
}
void SShell::MakeFromBoolean(SShell *a, SShell *b, int type) { void SShell::MakeFromBoolean(SShell *a, SShell *b, int type) {
a->MakeClassifyingBsps(); a->MakeClassifyingBsps();
b->MakeClassifyingBsps(); b->MakeClassifyingBsps();
@ -540,20 +612,7 @@ void SShell::MakeFromBoolean(SShell *a, SShell *b, int type) {
// Now that we've copied the surfaces, we know their new hSurfaces, so // Now that we've copied the surfaces, we know their new hSurfaces, so
// rewrite the curves to refer to the surfaces by their handles in the // rewrite the curves to refer to the surfaces by their handles in the
// result. // result.
for(sc = curve.First(); sc; sc = curve.NextAfter(sc)) { RewriteSurfaceHandlesForCurves(a, b);
if(sc->source == SCurve::FROM_A) {
sc->surfA = a->surface.FindById(sc->surfA)->newH;
sc->surfB = a->surface.FindById(sc->surfB)->newH;
} else if(sc->source == SCurve::FROM_B) {
sc->surfA = b->surface.FindById(sc->surfA)->newH;
sc->surfB = b->surface.FindById(sc->surfB)->newH;
} else if(sc->source == SCurve::FROM_INTERSECTION) {
sc->surfA = a->surface.FindById(sc->surfA)->newH;
sc->surfB = b->surface.FindById(sc->surfB)->newH;
} else {
oops();
}
}
// And clean up the piecewise linear things we made as a calculation aid // And clean up the piecewise linear things we made as a calculation aid
a->CleanupAfterBoolean(); a->CleanupAfterBoolean();

View File

@ -297,6 +297,7 @@ public:
bool seg, bool trimmed, bool inclTangent); bool seg, bool trimmed, bool inclTangent);
void MakeCoincidentEdgesInto(SSurface *proto, bool sameNormal, void MakeCoincidentEdgesInto(SSurface *proto, bool sameNormal,
SEdgeList *el, SShell *useCurvesFrom); SEdgeList *el, SShell *useCurvesFrom);
void RewriteSurfaceHandlesForCurves(SShell *a, SShell *b);
void CleanupAfterBoolean(void); void CleanupAfterBoolean(void);
static const int INSIDE = 100; static const int INSIDE = 100;
@ -312,6 +313,7 @@ public:
void MakeFromCopyOf(SShell *a); void MakeFromCopyOf(SShell *a);
void MakeFromTransformationOf(SShell *a, Vector trans, Quaternion q); void MakeFromTransformationOf(SShell *a, Vector trans, Quaternion q);
void MakeFromAssemblyOf(SShell *a, SShell *b);
void TriangulateInto(SMesh *sm); void TriangulateInto(SMesh *sm);
void MakeEdgesInto(SEdgeList *sel); void MakeEdgesInto(SEdgeList *sel);

View File

@ -2,7 +2,6 @@
marching algorithm for surface intersection marching algorithm for surface intersection
tangent intersections tangent intersections
put back the meshes put back the meshes
assembly
----- -----
line styles (color, thickness) line styles (color, thickness)