Generate additional edges wherever a front- and back-facing

triangle join. And add controls to show and hide the solid model
edges (independently of the shaded mesh), and to suppress the
shaded triangles from SVG/EPS output.

[git-p4: depot-paths = "//depot/solvespace/": change = 1932]
This commit is contained in:
Jonathan Westhues 2009-03-17 20:26:04 -08:00
parent 1a845c3432
commit d4b842a242
10 changed files with 115 additions and 18 deletions

View File

@ -115,6 +115,14 @@ void SolveSpace::ExportViewTo(char *filename) {
sm = &((SS.GetGroup(SS.GW.activeGroup))->runningMesh); sm = &((SS.GetGroup(SS.GW.activeGroup))->runningMesh);
} }
if(SS.GW.showEdges) {
SEdgeList *emph = &((SS.GetGroup(SS.GW.activeGroup))->emphEdges);
SEdge *se;
for(se = emph->l.First(); se; se = emph->l.NextAfter(se)) {
edges.AddEdge(se->a, se->b);
}
}
Vector u = SS.GW.projRight, Vector u = SS.GW.projRight,
v = SS.GW.projUp, v = SS.GW.projUp,
n = u.Cross(v), n = u.Cross(v),
@ -212,6 +220,13 @@ void SolveSpace::ExportLinesAndMesh(SEdgeList *sel, SMesh *sm,
ZERO(&hlrd); ZERO(&hlrd);
if(sm && !SS.GW.showHdnLines) { if(sm && !SS.GW.showHdnLines) {
SKdNode *root = SKdNode::From(&smp); SKdNode *root = SKdNode::From(&smp);
// Generate the edges where a curved surface turns from front-facing
// to back-facing.
if(SS.GW.showEdges) {
root->MakeTurningEdgesInto(sel);
}
root->ClearTags(); root->ClearTags();
int cnt = 1234; int cnt = 1234;
@ -306,7 +321,7 @@ void VectorFileWriter::Output(SEdgeList *sel, SMesh *sm) {
} }
StartFile(); StartFile();
if(sm) { if(sm && SS.exportShadedTriangles) {
for(tr = sm->l.First(); tr; tr = sm->l.NextAfter(tr)) { for(tr = sm->l.First(); tr; tr = sm->l.NextAfter(tr)) {
Triangle(tr); Triangle(tr);
} }

View File

@ -144,6 +144,7 @@ void GraphicsWindow::Init(void) {
showConstraints = true; showConstraints = true;
showHdnLines = false; showHdnLines = false;
showShaded = true; showShaded = true;
showEdges = true;
showMesh = false; showMesh = false;
showTextWindow = true; showTextWindow = true;

View File

@ -253,9 +253,7 @@ done:
runningMesh.Clear(); runningMesh.Clear();
runningShell.TriangulateInto(&runningMesh); runningShell.TriangulateInto(&runningMesh);
emphEdges.Clear(); emphEdges.Clear();
if(h.v == SS.GW.activeGroup.v && SS.edgeColor != 0) { runningShell.MakeEdgesInto(&emphEdges);
runningShell.MakeEdgesInto(&emphEdges);
}
} }
SShell *Group::PreviousGroupShell(void) { SShell *Group::PreviousGroupShell(void) {
@ -298,7 +296,8 @@ void Group::Draw(void) {
glEnable(GL_LIGHTING); glEnable(GL_LIGHTING);
glxFillMesh(specColor, &runningMesh, mh, ms1, ms2); glxFillMesh(specColor, &runningMesh, mh, ms1, ms2);
glDisable(GL_LIGHTING); glDisable(GL_LIGHTING);
}
if(SS.GW.showEdges) {
glLineWidth(1); glLineWidth(1);
glxDepthRangeOffset(2); glxDepthRangeOffset(2);
glxColor3d(REDf (SS.edgeColor), glxColor3d(REDf (SS.edgeColor),

View File

@ -476,19 +476,21 @@ void SKdNode::MakeMeshInto(SMesh *m) {
} }
} }
void SKdNode::FindEdgeOn(Vector a, Vector b, int *n, int cnt, bool *inter) { void SKdNode::FindEdgeOn(Vector a, Vector b, int *n, int cnt,
bool *inter, bool *fwd)
{
if(gt && lt) { if(gt && lt) {
double ac = a.Element(which), double ac = a.Element(which),
bc = b.Element(which); bc = b.Element(which);
if(ac < c + KDTREE_EPS || if(ac < c + KDTREE_EPS ||
bc < c + KDTREE_EPS) bc < c + KDTREE_EPS)
{ {
lt->FindEdgeOn(a, b, n, cnt, inter); lt->FindEdgeOn(a, b, n, cnt, inter, fwd);
} }
if(ac > c - KDTREE_EPS || if(ac > c - KDTREE_EPS ||
bc > c - KDTREE_EPS) bc > c - KDTREE_EPS)
{ {
gt->FindEdgeOn(a, b, n, cnt, inter); gt->FindEdgeOn(a, b, n, cnt, inter, fwd);
} }
} else { } else {
STriangleLl *ll; STriangleLl *ll;
@ -503,6 +505,12 @@ void SKdNode::FindEdgeOn(Vector a, Vector b, int *n, int cnt, bool *inter) {
(a.Equals(tr->a) && b.Equals(tr->c))) (a.Equals(tr->a) && b.Equals(tr->c)))
{ {
(*n)++; (*n)++;
// Record whether this triangle is front- or back-facing.
if(tr->Normal().z > LENGTH_EPS) {
*fwd = true;
} else {
*fwd = false;
}
} else if(((a.Equals(tr->a) && b.Equals(tr->b)) || } else if(((a.Equals(tr->a) && b.Equals(tr->b)) ||
(a.Equals(tr->b) && b.Equals(tr->c)) || (a.Equals(tr->b) && b.Equals(tr->c)) ||
(a.Equals(tr->c) && b.Equals(tr->a)))) (a.Equals(tr->c) && b.Equals(tr->a))))
@ -688,8 +696,8 @@ void SKdNode::MakeNakedEdgesInto(SEdgeList *sel, bool *inter, bool *leaky) {
Vector b = (j == 0) ? tr->b : ((j == 1) ? tr->c : tr->a); Vector b = (j == 0) ? tr->b : ((j == 1) ? tr->c : tr->a);
int n = 0, nOther = 0; int n = 0, nOther = 0;
bool thisIntersects = false; bool thisIntersects = false, fwd;
FindEdgeOn(a, b, &n, cnt, &thisIntersects); FindEdgeOn(a, b, &n, cnt, &thisIntersects, &fwd);
if(n != 1) { if(n != 1) {
sel->AddEdge(a, b); sel->AddEdge(a, b);
if(leaky) *leaky = true; if(leaky) *leaky = true;
@ -706,3 +714,35 @@ void SKdNode::MakeNakedEdgesInto(SEdgeList *sel, bool *inter, bool *leaky) {
m.Clear(); m.Clear();
} }
void SKdNode::MakeTurningEdgesInto(SEdgeList *sel) {
SMesh m;
ZERO(&m);
ClearTags();
MakeMeshInto(&m);
int cnt = 1234;
int i, j;
for(i = 0; i < m.l.n; i++) {
STriangle *tr = &(m.l.elem[i]);
if(tr->Normal().z > LENGTH_EPS) continue;
// So this is a back-facing triangle
for(j = 0; j < 3; j++) {
Vector a = (j == 0) ? tr->a : ((j == 1) ? tr->b : tr->c);
Vector b = (j == 0) ? tr->b : ((j == 1) ? tr->c : tr->a);
int n = 0;
bool inter, fwd;
FindEdgeOn(a, b, &n, cnt, &inter, &fwd);
if(n == 1) {
// and its neighbour is front-facing, so generate the edge.
if(fwd) sel->AddEdge(a, b);
}
cnt++;
}
}
m.Clear();
}

View File

@ -222,8 +222,10 @@ public:
void MakeMeshInto(SMesh *m); void MakeMeshInto(SMesh *m);
void ClearTags(void); void ClearTags(void);
void FindEdgeOn(Vector a, Vector b, int *n, int cnt, bool *inter); void FindEdgeOn(Vector a, Vector b, int *n, int cnt,
bool *inter, bool *fwd);
void MakeNakedEdgesInto(SEdgeList *sel, bool *inter=NULL, bool *leaky=NULL); void MakeNakedEdgesInto(SEdgeList *sel, bool *inter=NULL, bool *leaky=NULL);
void MakeTurningEdgesInto(SEdgeList *sel);
void OcclusionTestLine(SEdge orig, SEdgeList *sel, int cnt); void OcclusionTestLine(SEdge orig, SEdgeList *sel, int cnt);
void SplitLinesAgainstTriangle(SEdgeList *sel, STriangle *tr); void SplitLinesAgainstTriangle(SEdgeList *sel, STriangle *tr);

View File

@ -54,6 +54,10 @@ void SolveSpace::Init(char *cmdLine) {
exportOffset = CnfThawFloat(0.0f, "ExportOffset"); exportOffset = CnfThawFloat(0.0f, "ExportOffset");
// Draw back faces of triangles (when mesh is leaky/self-intersecting) // Draw back faces of triangles (when mesh is leaky/self-intersecting)
drawBackFaces = CnfThawDWORD(1, "DrawBackFaces"); drawBackFaces = CnfThawDWORD(1, "DrawBackFaces");
// Export shaded triangles in a 2d view
exportShadedTriangles = CnfThawDWORD(1, "ExportShadedTriangles");
// Export exact curves (instead of pwl) when possible
exportExactCurves = CnfThawDWORD(0, "ExportExactCurves");
// Show toolbar in the graphics window // Show toolbar in the graphics window
showToolbar = CnfThawDWORD(1, "ShowToolbar"); showToolbar = CnfThawDWORD(1, "ShowToolbar");
// Recent files menus // Recent files menus
@ -118,6 +122,10 @@ void SolveSpace::Exit(void) {
CnfFreezeFloat(exportOffset, "ExportOffset"); CnfFreezeFloat(exportOffset, "ExportOffset");
// Draw back faces of triangles (when mesh is leaky/self-intersecting) // Draw back faces of triangles (when mesh is leaky/self-intersecting)
CnfFreezeDWORD(drawBackFaces, "DrawBackFaces"); CnfFreezeDWORD(drawBackFaces, "DrawBackFaces");
// Export shaded triangles in a 2d view
CnfFreezeDWORD(exportShadedTriangles, "ExportShadedTriangles");
// Export exact curves (instead of pwl) when possible
CnfFreezeDWORD(exportExactCurves, "ExportExactCurves");
// Show toolbar in the graphics window // Show toolbar in the graphics window
CnfFreezeDWORD(showToolbar, "ShowToolbar"); CnfFreezeDWORD(showToolbar, "ShowToolbar");

View File

@ -444,6 +444,8 @@ public:
float exportOffset; float exportOffset;
int drawBackFaces; int drawBackFaces;
int showToolbar; int showToolbar;
int exportShadedTriangles;
int exportExactCurves;
int CircleSides(double r); int CircleSides(double r);
typedef enum { typedef enum {

View File

@ -36,12 +36,14 @@ hs(SS.GW.showConstraints), (DWORD)(&SS.GW.showConstraints), &(SS.GW.ToggleBool)
); );
Printf(false, "%Bt%Ft " Printf(false, "%Bt%Ft "
"%Fp%Ll%D%fshaded%E " "%Fp%Ll%D%fshaded%E "
"%Fp%Ll%D%ffaces%E " "%Fp%Ll%D%fedges%E "
"%Fp%Ll%D%fmesh%E " "%Fp%Ll%D%fmesh%E "
"%Fp%Ll%D%fhidden-lines%E", "%Fp%Ll%D%ffaces%E "
"%Fp%Ll%D%fhidden-lns%E",
hs(SS.GW.showShaded), (DWORD)(&SS.GW.showShaded), &(SS.GW.ToggleBool), hs(SS.GW.showShaded), (DWORD)(&SS.GW.showShaded), &(SS.GW.ToggleBool),
hs(SS.GW.showFaces), (DWORD)(&SS.GW.showFaces), &(SS.GW.ToggleBool), hs(SS.GW.showEdges), (DWORD)(&SS.GW.showEdges), &(SS.GW.ToggleBool),
hs(SS.GW.showMesh), (DWORD)(&SS.GW.showMesh), &(SS.GW.ToggleBool), hs(SS.GW.showMesh), (DWORD)(&SS.GW.showMesh), &(SS.GW.ToggleBool),
hs(SS.GW.showFaces), (DWORD)(&SS.GW.showFaces), &(SS.GW.ToggleBool),
hs(SS.GW.showHdnLines), (DWORD)(&SS.GW.showHdnLines), &(SS.GW.ToggleBool) hs(SS.GW.showHdnLines), (DWORD)(&SS.GW.showHdnLines), &(SS.GW.ToggleBool)
); );
} }
@ -607,6 +609,14 @@ void TextWindow::ScreenChangeBackFaces(int link, DWORD v) {
SS.drawBackFaces = !SS.drawBackFaces; SS.drawBackFaces = !SS.drawBackFaces;
InvalidateGraphics(); InvalidateGraphics();
} }
void TextWindow::ScreenChangeShadedTriangles(int link, DWORD v) {
SS.exportShadedTriangles = !SS.exportShadedTriangles;
InvalidateGraphics();
}
void TextWindow::ScreenChangeExactCurves(int link, DWORD v) {
SS.exportExactCurves = !SS.exportExactCurves;
InvalidateGraphics();
}
void TextWindow::ShowConfiguration(void) { void TextWindow::ShowConfiguration(void) {
int i; int i;
Printf(true, "%Ft material color-(r, g, b)"); Printf(true, "%Ft material color-(r, g, b)");
@ -633,7 +643,7 @@ void TextWindow::ShowConfiguration(void) {
} }
Printf(false, ""); Printf(false, "");
Printf(false, "%Ft edge color r,g,b (0,0,0 for no edges)%E"); Printf(false, "%Ft edge color r,g,b%E");
Printf(false, "%Ba %@, %@, %@ %Fl%Ll%f%D[change]%E", Printf(false, "%Ba %@, %@, %@ %Fl%Ll%f%D[change]%E",
REDf(SS.edgeColor), GREENf(SS.edgeColor), BLUEf(SS.edgeColor), REDf(SS.edgeColor), GREENf(SS.edgeColor), BLUEf(SS.edgeColor),
&ScreenChangeEdgeColor, 0); &ScreenChangeEdgeColor, 0);
@ -665,6 +675,24 @@ void TextWindow::ShowConfiguration(void) {
(double)SS.exportOffset, (double)SS.exportOffset,
&ScreenChangeExportOffset, 0); &ScreenChangeExportOffset, 0);
Printf(false, "");
Printf(false, "%Ft export shaded 2d triangles: "
"%Fh%f%Ll%s%E%Fs%s%E / %Fh%f%Ll%s%E%Fs%s%E",
&ScreenChangeShadedTriangles,
(SS.exportShadedTriangles ? "" : "yes"),
(SS.exportShadedTriangles ? "yes" : ""),
&ScreenChangeShadedTriangles,
(!SS.exportShadedTriangles ? "" : "no"),
(!SS.exportShadedTriangles ? "no" : ""));
Printf(false, "%Ft export exact curves in DXF: "
"%Fh%f%Ll%s%E%Fs%s%E / %Fh%f%Ll%s%E%Fs%s%E",
&ScreenChangeExactCurves,
(SS.exportExactCurves ? "" : "yes"),
(SS.exportExactCurves ? "yes" : ""),
&ScreenChangeExactCurves,
(!SS.exportExactCurves ? "" : "no"),
(!SS.exportExactCurves ? "no" : ""));
Printf(false, ""); Printf(false, "");
Printf(false, "%Ft draw back faces: " Printf(false, "%Ft draw back faces: "
"%Fh%f%Ll%s%E%Fs%s%E / %Fh%f%Ll%s%E%Fs%s%E", "%Fh%f%Ll%s%E%Fs%s%E / %Fh%f%Ll%s%E%Fs%s%E",

3
ui.h
View File

@ -145,6 +145,8 @@ public:
static void ScreenGoToWebsite(int link, DWORD v); static void ScreenGoToWebsite(int link, DWORD v);
static void ScreenChangeBackFaces(int link, DWORD v); static void ScreenChangeBackFaces(int link, DWORD v);
static void ScreenChangeExactCurves(int link, DWORD v);
static void ScreenChangeShadedTriangles(int link, DWORD v);
static void ScreenStepDimSteps(int link, DWORD v); static void ScreenStepDimSteps(int link, DWORD v);
static void ScreenStepDimFinish(int link, DWORD v); static void ScreenStepDimFinish(int link, DWORD v);
@ -405,6 +407,7 @@ public:
bool showConstraints; bool showConstraints;
bool showTextWindow; bool showTextWindow;
bool showShaded; bool showShaded;
bool showEdges;
bool showFaces; bool showFaces;
bool showMesh; bool showMesh;
bool showHdnLines; bool showHdnLines;

View File

@ -2,15 +2,14 @@
marching algorithm for surface intersection marching algorithm for surface intersection
surfaces of revolution (lathed) surfaces of revolution (lathed)
cylinder-line special cases cylinder-line special cases
exact boundaries when near pwl trim boundary avoidance when casting ray for point-in-shell
tangent intersections tangent intersections
short pwl edge avoidance short pwl edge avoidance
exact curve export (at least for dxf) exact curve export (at least for dxf)
hidden line removal from mesh
line styles (color, thickness)
assembly assembly
----- -----
line styles (color, thickness)
loop detection loop detection
incremental regen of entities? incremental regen of entities?
IGES and STEP export IGES and STEP export