diff --git a/export.cpp b/export.cpp index 3517d93..771be28 100644 --- a/export.cpp +++ b/export.cpp @@ -115,6 +115,14 @@ void SolveSpace::ExportViewTo(char *filename) { 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, v = SS.GW.projUp, n = u.Cross(v), @@ -212,6 +220,13 @@ void SolveSpace::ExportLinesAndMesh(SEdgeList *sel, SMesh *sm, ZERO(&hlrd); if(sm && !SS.GW.showHdnLines) { 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(); int cnt = 1234; @@ -306,7 +321,7 @@ void VectorFileWriter::Output(SEdgeList *sel, SMesh *sm) { } StartFile(); - if(sm) { + if(sm && SS.exportShadedTriangles) { for(tr = sm->l.First(); tr; tr = sm->l.NextAfter(tr)) { Triangle(tr); } diff --git a/graphicswin.cpp b/graphicswin.cpp index a503585..0827d21 100644 --- a/graphicswin.cpp +++ b/graphicswin.cpp @@ -144,6 +144,7 @@ void GraphicsWindow::Init(void) { showConstraints = true; showHdnLines = false; showShaded = true; + showEdges = true; showMesh = false; showTextWindow = true; diff --git a/groupmesh.cpp b/groupmesh.cpp index e2518bf..85d17f0 100644 --- a/groupmesh.cpp +++ b/groupmesh.cpp @@ -253,9 +253,7 @@ done: runningMesh.Clear(); runningShell.TriangulateInto(&runningMesh); emphEdges.Clear(); - if(h.v == SS.GW.activeGroup.v && SS.edgeColor != 0) { - runningShell.MakeEdgesInto(&emphEdges); - } + runningShell.MakeEdgesInto(&emphEdges); } SShell *Group::PreviousGroupShell(void) { @@ -298,7 +296,8 @@ void Group::Draw(void) { glEnable(GL_LIGHTING); glxFillMesh(specColor, &runningMesh, mh, ms1, ms2); glDisable(GL_LIGHTING); - + } + if(SS.GW.showEdges) { glLineWidth(1); glxDepthRangeOffset(2); glxColor3d(REDf (SS.edgeColor), diff --git a/mesh.cpp b/mesh.cpp index 181fd9b..a197065 100644 --- a/mesh.cpp +++ b/mesh.cpp @@ -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) { double ac = a.Element(which), bc = b.Element(which); if(ac < 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 || bc > c - KDTREE_EPS) { - gt->FindEdgeOn(a, b, n, cnt, inter); + gt->FindEdgeOn(a, b, n, cnt, inter, fwd); } } else { 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))) { (*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)) || (a.Equals(tr->b) && b.Equals(tr->c)) || (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); int n = 0, nOther = 0; - bool thisIntersects = false; - FindEdgeOn(a, b, &n, cnt, &thisIntersects); + bool thisIntersects = false, fwd; + FindEdgeOn(a, b, &n, cnt, &thisIntersects, &fwd); if(n != 1) { sel->AddEdge(a, b); if(leaky) *leaky = true; @@ -706,3 +714,35 @@ void SKdNode::MakeNakedEdgesInto(SEdgeList *sel, bool *inter, bool *leaky) { 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(); +} + diff --git a/polygon.h b/polygon.h index f816515..47c59ee 100644 --- a/polygon.h +++ b/polygon.h @@ -222,8 +222,10 @@ public: void MakeMeshInto(SMesh *m); 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 MakeTurningEdgesInto(SEdgeList *sel); void OcclusionTestLine(SEdge orig, SEdgeList *sel, int cnt); void SplitLinesAgainstTriangle(SEdgeList *sel, STriangle *tr); diff --git a/solvespace.cpp b/solvespace.cpp index a5ed8f9..10a768e 100644 --- a/solvespace.cpp +++ b/solvespace.cpp @@ -54,6 +54,10 @@ void SolveSpace::Init(char *cmdLine) { exportOffset = CnfThawFloat(0.0f, "ExportOffset"); // Draw back faces of triangles (when mesh is leaky/self-intersecting) 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 showToolbar = CnfThawDWORD(1, "ShowToolbar"); // Recent files menus @@ -118,6 +122,10 @@ void SolveSpace::Exit(void) { CnfFreezeFloat(exportOffset, "ExportOffset"); // Draw back faces of triangles (when mesh is leaky/self-intersecting) 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 CnfFreezeDWORD(showToolbar, "ShowToolbar"); diff --git a/solvespace.h b/solvespace.h index 8103370..a182f6d 100644 --- a/solvespace.h +++ b/solvespace.h @@ -444,6 +444,8 @@ public: float exportOffset; int drawBackFaces; int showToolbar; + int exportShadedTriangles; + int exportExactCurves; int CircleSides(double r); typedef enum { diff --git a/textscreens.cpp b/textscreens.cpp index 61eab6f..1831982 100644 --- a/textscreens.cpp +++ b/textscreens.cpp @@ -36,12 +36,14 @@ hs(SS.GW.showConstraints), (DWORD)(&SS.GW.showConstraints), &(SS.GW.ToggleBool) ); Printf(false, "%Bt%Ft " "%Fp%Ll%D%fshaded%E " - "%Fp%Ll%D%ffaces%E " + "%Fp%Ll%D%fedges%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.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.showFaces), (DWORD)(&SS.GW.showFaces), &(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; 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) { int i; Printf(true, "%Ft material color-(r, g, b)"); @@ -633,7 +643,7 @@ void TextWindow::ShowConfiguration(void) { } 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", REDf(SS.edgeColor), GREENf(SS.edgeColor), BLUEf(SS.edgeColor), &ScreenChangeEdgeColor, 0); @@ -665,6 +675,24 @@ void TextWindow::ShowConfiguration(void) { (double)SS.exportOffset, &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, "%Ft draw back faces: " "%Fh%f%Ll%s%E%Fs%s%E / %Fh%f%Ll%s%E%Fs%s%E", diff --git a/ui.h b/ui.h index ed97001..53aa551 100644 --- a/ui.h +++ b/ui.h @@ -145,6 +145,8 @@ public: static void ScreenGoToWebsite(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 ScreenStepDimFinish(int link, DWORD v); @@ -405,6 +407,7 @@ public: bool showConstraints; bool showTextWindow; bool showShaded; + bool showEdges; bool showFaces; bool showMesh; bool showHdnLines; diff --git a/wishlist.txt b/wishlist.txt index 656c6d7..f2a374f 100644 --- a/wishlist.txt +++ b/wishlist.txt @@ -2,15 +2,14 @@ marching algorithm for surface intersection surfaces of revolution (lathed) cylinder-line special cases -exact boundaries when near pwl trim +boundary avoidance when casting ray for point-in-shell tangent intersections short pwl edge avoidance exact curve export (at least for dxf) -hidden line removal from mesh -line styles (color, thickness) assembly ----- +line styles (color, thickness) loop detection incremental regen of entities? IGES and STEP export