Add an interference check for assembled parts. That's easy once the
BSP stuff works. The failures are reported with red stripes and no depth buffering, and in a message in the text window. Also improve convergence of point-on-line constraints, and don't write triangles to export files with limited precision, because that was making the coplanar tests fail. [git-p4: depot-paths = "//depot/solvespace/": change = 1774]solver
parent
64c7a4e61b
commit
71391e6a55
|
@ -567,14 +567,21 @@ void Constraint::Generate(IdList<Equation,hEquation> *l) {
|
|||
ExprVector ea = a->PointGetExprs();
|
||||
ExprVector eb = b->PointGetExprs();
|
||||
ExprVector eab = ea.Minus(eb);
|
||||
|
||||
// Construct a vector from the point to either endpoint of
|
||||
// the line segment, and choose the longer of these.
|
||||
ExprVector eap = ea.Minus(ep);
|
||||
ExprVector ebp = eb.Minus(ep);
|
||||
ExprVector elp =
|
||||
(ebp.Magnitude()->Eval() > eap.Magnitude()->Eval()) ?
|
||||
ebp : eap;
|
||||
|
||||
if(p->group.v == group.v) {
|
||||
AddEq(l, VectorsParallel(0, eab, eap), 0);
|
||||
AddEq(l, VectorsParallel(1, eab, eap), 1);
|
||||
AddEq(l, VectorsParallel(0, eab, elp), 0);
|
||||
AddEq(l, VectorsParallel(1, eab, elp), 1);
|
||||
} else {
|
||||
AddEq(l, VectorsParallel(0, eap, eab), 0);
|
||||
AddEq(l, VectorsParallel(1, eap, eab), 1);
|
||||
AddEq(l, VectorsParallel(0, elp, eab), 0);
|
||||
AddEq(l, VectorsParallel(1, elp, eab), 1);
|
||||
}
|
||||
} else {
|
||||
AddEq(l, PointLineDistance(workplane, ptA, entityA), 0);
|
||||
|
|
2
file.cpp
2
file.cpp
|
@ -234,7 +234,7 @@ bool SolveSpace::SaveToFile(char *filename) {
|
|||
double mag = tr->Normal().Magnitude();
|
||||
dbp("triangle: mag=%.5f", mag); */
|
||||
fprintf(fh, "Triangle %08x %08x "
|
||||
"%.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f\n",
|
||||
"%.20f %.20f %.20f %.20f %.20f %.20f %.20f %.20f %.20f\n",
|
||||
tr->meta.face, tr->meta.color,
|
||||
CO(tr->a), CO(tr->b), CO(tr->c));
|
||||
}
|
||||
|
|
31
mesh.cpp
31
mesh.cpp
|
@ -225,7 +225,7 @@ void SMesh::MakeFromDifference(SMesh *a, SMesh *b) {
|
|||
SBsp3 *bspb = SBsp3::FromMesh(b);
|
||||
|
||||
flipNormal = true;
|
||||
keepCoplanar = false;
|
||||
keepCoplanar = true;
|
||||
AddAgainstBsp(b, bspa);
|
||||
|
||||
flipNormal = false;
|
||||
|
@ -235,6 +235,31 @@ void SMesh::MakeFromDifference(SMesh *a, SMesh *b) {
|
|||
dbp("tris = %d", l.n);
|
||||
}
|
||||
|
||||
bool SMesh::MakeFromInterferenceCheck(SMesh *srca, SMesh *srcb, SMesh *error) {
|
||||
SBsp3 *bspa = SBsp3::FromMesh(srca);
|
||||
SBsp3 *bspb = SBsp3::FromMesh(srcb);
|
||||
|
||||
error->Clear();
|
||||
error->flipNormal = true;
|
||||
error->keepCoplanar = false;
|
||||
|
||||
error->AddAgainstBsp(srcb, bspa);
|
||||
error->AddAgainstBsp(srca, bspb);
|
||||
// Now we have a list of all the triangles (or fragments thereof) from
|
||||
// A that lie inside B, or vice versa. That's the interference, and
|
||||
// we report it so that it can be flagged.
|
||||
|
||||
// But as far as the actual model, we just copy everything over.
|
||||
int i;
|
||||
for(i = 0; i < srca->l.n; i++) {
|
||||
AddTriangle(&(srca->l.elem[i]));
|
||||
}
|
||||
for(i = 0; i < srcb->l.n; i++) {
|
||||
AddTriangle(&(srcb->l.elem[i]));
|
||||
}
|
||||
return (error->l.n == 0);
|
||||
}
|
||||
|
||||
DWORD SMesh::FirstIntersectionWith(Point2d mp) {
|
||||
Vector gu = SS.GW.projRight, gv = SS.GW.projUp;
|
||||
Vector gn = (gu.Cross(gv)).WithMagnitude(1);
|
||||
|
@ -325,7 +350,9 @@ void SBsp3::InsertInPlane(bool pos2, STriangle *tr, SMesh *m) {
|
|||
ll = ll->more;
|
||||
}
|
||||
|
||||
if(m->flipNormal && ((!pos2 && !onFace) || (onFace && !sameNormal))) {
|
||||
if(m->flipNormal && ((!pos2 && !onFace) ||
|
||||
(onFace && !sameNormal && m->keepCoplanar)))
|
||||
{
|
||||
m->AddTriangle(tr->meta, tr->c, tr->b, tr->a);
|
||||
} else if(!(m->flipNormal) && ((pos2 && !onFace) ||
|
||||
(onFace && sameNormal && m->keepCoplanar)))
|
||||
|
|
|
@ -191,6 +191,7 @@ public:
|
|||
void AddAgainstBsp(SMesh *srcm, SBsp3 *bsp3);
|
||||
void MakeFromUnion(SMesh *a, SMesh *b);
|
||||
void MakeFromDifference(SMesh *a, SMesh *b);
|
||||
bool MakeFromInterferenceCheck(SMesh *srca, SMesh *srcb, SMesh *errorAt);
|
||||
|
||||
DWORD FirstIntersectionWith(Point2d mp);
|
||||
};
|
||||
|
|
28
sketch.cpp
28
sketch.cpp
|
@ -737,13 +737,22 @@ void Group::GenerateMesh(void) {
|
|||
// So our group's mesh appears in outm. Combine this with the previous
|
||||
// group's mesh, using the requested operation.
|
||||
mesh.Clear();
|
||||
bool prevMeshError = meshError.yes;
|
||||
meshError.yes = false;
|
||||
meshError.interferesAt.Clear();
|
||||
SMesh *a = PreviousGroupMesh();
|
||||
if(meshCombine == COMBINE_AS_UNION) {
|
||||
mesh.MakeFromUnion(a, &outm);
|
||||
} else if(meshCombine == COMBINE_AS_DIFFERENCE) {
|
||||
mesh.MakeFromDifference(a, &outm);
|
||||
} else {
|
||||
|
||||
if(!mesh.MakeFromInterferenceCheck(a, &outm, &(meshError.interferesAt)))
|
||||
meshError.yes = true;
|
||||
// And the list of failed triangles appears in meshError.interferesAt
|
||||
}
|
||||
if(prevMeshError != meshError.yes) {
|
||||
// The error is reported in the text window for the group.
|
||||
SS.later.showTW = true;
|
||||
}
|
||||
outm.Clear();
|
||||
}
|
||||
|
@ -789,6 +798,23 @@ void Group::Draw(void) {
|
|||
if(SS.GW.showShaded) glxFillMesh(specColor, &mesh, mh, ms1, ms2);
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
if(meshError.yes) {
|
||||
// Draw the error triangles in bright red stripes, with no Z buffering
|
||||
GLubyte mask[32*32/8];
|
||||
memset(mask, 0xf0, sizeof(mask));
|
||||
glPolygonStipple(mask);
|
||||
|
||||
int specColor = 0;
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glColor3d(0, 0, 0);
|
||||
glxFillMesh(0, &meshError.interferesAt, 0, 0, 0);
|
||||
glEnable(GL_POLYGON_STIPPLE);
|
||||
glColor3d(1, 0, 0);
|
||||
glxFillMesh(0, &meshError.interferesAt, 0, 0, 0);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDisable(GL_POLYGON_STIPPLE);
|
||||
}
|
||||
|
||||
if(SS.GW.showMesh) glxDebugMesh(&mesh);
|
||||
|
||||
if(!SS.GW.showShaded) return;
|
||||
|
|
4
sketch.h
4
sketch.h
|
@ -124,6 +124,10 @@ public:
|
|||
bool yes;
|
||||
} polyError;
|
||||
SMesh mesh;
|
||||
struct {
|
||||
SMesh interferesAt;
|
||||
bool yes;
|
||||
} meshError;
|
||||
|
||||
static const int COMBINE_AS_UNION = 0;
|
||||
static const int COMBINE_AS_DIFFERENCE = 1;
|
||||
|
|
|
@ -656,6 +656,9 @@ void TextWindow::ShowGroupInfo(void) {
|
|||
Group::COMBINE_AS_ASSEMBLE,
|
||||
(asy || !asa ? "" : "assemble"), (asy && asa ? "assemble" : ""));
|
||||
}
|
||||
if(g->type == Group::IMPORTED && g->meshError.yes) {
|
||||
Printf(false, "%Fx the parts interfere!");
|
||||
}
|
||||
|
||||
if(g->type == Group::EXTRUDE) {
|
||||
#define TWOX(v) v v
|
||||
|
|
Loading…
Reference in New Issue