Put back code to generate emphasized edges from a mesh; so now we
can show edges for both meshes and shells, and export them and hidden line remove and all the usual stuff. And fix the zoom to fit on startup, so that it considers hidden entities too. That avoids the problem where things get generated at stupid chord tolerance because no entities were visible and the mesh of course did not yet exist. [git-p4: depot-paths = "//depot/solvespace/": change = 1961]
This commit is contained in:
parent
7536ccb054
commit
842645d61f
@ -248,7 +248,8 @@ void SolveSpace::ExportLinesAndMesh(SEdgeList *sel, SBezierList *sbl, SMesh *sm,
|
|||||||
// Generate the edges where a curved surface turns from front-facing
|
// Generate the edges where a curved surface turns from front-facing
|
||||||
// to back-facing.
|
// to back-facing.
|
||||||
if(SS.GW.showEdges) {
|
if(SS.GW.showEdges) {
|
||||||
root->MakeTurningEdgesInto(sel);
|
root->MakeCertainEdgesInto(sel, SKdNode::TURNING_EDGES,
|
||||||
|
false, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
root->ClearTags();
|
root->ClearTags();
|
||||||
@ -864,8 +865,9 @@ void SvgFileWriter::StartFile(void) {
|
|||||||
"\r\n"
|
"\r\n"
|
||||||
"<title>Exported SVG</title>\r\n"
|
"<title>Exported SVG</title>\r\n"
|
||||||
"\r\n",
|
"\r\n",
|
||||||
ptMax.x - ptMin.x, ptMax.y - ptMin.y,
|
(ptMax.x - ptMin.x) + 1, (ptMax.y - ptMin.y) + 1,
|
||||||
ptMax.x - ptMin.x, ptMax.y - ptMin.y);
|
(ptMax.x - ptMin.x) + 1, (ptMax.y - ptMin.y) + 1);
|
||||||
|
// A little bit of extra space for the stroke width.
|
||||||
}
|
}
|
||||||
|
|
||||||
void SvgFileWriter::LineSegment(double x0, double y0, double x1, double y1) {
|
void SvgFileWriter::LineSegment(double x0, double y0, double x1, double y1) {
|
||||||
|
@ -252,6 +252,9 @@ void GraphicsWindow::HandlePointForZoomToFit(Vector p,
|
|||||||
{
|
{
|
||||||
double w;
|
double w;
|
||||||
Vector pp = ProjectPoint4(p, &w);
|
Vector pp = ProjectPoint4(p, &w);
|
||||||
|
// If div is true, then we calculate a perspective projection of the point.
|
||||||
|
// If not, then we do a parallel projection regardless of the current
|
||||||
|
// scale factor.
|
||||||
if(div) {
|
if(div) {
|
||||||
pp = pp.ScaledBy(1.0/w);
|
pp = pp.ScaledBy(1.0/w);
|
||||||
}
|
}
|
||||||
@ -262,15 +265,15 @@ void GraphicsWindow::HandlePointForZoomToFit(Vector p,
|
|||||||
pmin->y = min(pmin->y, pp.y);
|
pmin->y = min(pmin->y, pp.y);
|
||||||
*wmin = min(*wmin, w);
|
*wmin = min(*wmin, w);
|
||||||
}
|
}
|
||||||
void GraphicsWindow::LoopOverPoints(
|
void GraphicsWindow::LoopOverPoints(Point2d *pmax, Point2d *pmin, double *wmin,
|
||||||
Point2d *pmax, Point2d *pmin, double *wmin, bool div)
|
bool div, bool includingInvisibles)
|
||||||
{
|
{
|
||||||
HandlePointForZoomToFit(Vector::From(0, 0, 0), pmax, pmin, wmin, div);
|
HandlePointForZoomToFit(Vector::From(0, 0, 0), pmax, pmin, wmin, div);
|
||||||
|
|
||||||
int i, j;
|
int i, j;
|
||||||
for(i = 0; i < SK.entity.n; i++) {
|
for(i = 0; i < SK.entity.n; i++) {
|
||||||
Entity *e = &(SK.entity.elem[i]);
|
Entity *e = &(SK.entity.elem[i]);
|
||||||
if(!e->IsVisible()) continue;
|
if(!(e->IsVisible() || includingInvisibles)) continue;
|
||||||
if(e->IsPoint()) {
|
if(e->IsPoint()) {
|
||||||
HandlePointForZoomToFit(e->PointGetNum(), pmax, pmin, wmin, div);
|
HandlePointForZoomToFit(e->PointGetNum(), pmax, pmin, wmin, div);
|
||||||
} else if(e->type == Entity::CIRCLE) {
|
} else if(e->type == Entity::CIRCLE) {
|
||||||
@ -306,11 +309,11 @@ void GraphicsWindow::LoopOverPoints(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void GraphicsWindow::ZoomToFit(void) {
|
void GraphicsWindow::ZoomToFit(bool includingInvisibles) {
|
||||||
// On the first run, ignore perspective.
|
// On the first run, ignore perspective.
|
||||||
Point2d pmax = { -1e12, -1e12 }, pmin = { 1e12, 1e12 };
|
Point2d pmax = { -1e12, -1e12 }, pmin = { 1e12, 1e12 };
|
||||||
double wmin = 1;
|
double wmin = 1;
|
||||||
LoopOverPoints(&pmax, &pmin, &wmin, false);
|
LoopOverPoints(&pmax, &pmin, &wmin, false, includingInvisibles);
|
||||||
|
|
||||||
double xm = (pmax.x + pmin.x)/2, ym = (pmax.y + pmin.y)/2;
|
double xm = (pmax.x + pmin.x)/2, ym = (pmax.y + pmin.y)/2;
|
||||||
double dx = pmax.x - pmin.x, dy = pmax.y - pmin.y;
|
double dx = pmax.x - pmin.x, dy = pmax.y - pmin.y;
|
||||||
@ -335,7 +338,7 @@ void GraphicsWindow::ZoomToFit(void) {
|
|||||||
pmax.x = -1e12; pmax.y = -1e12;
|
pmax.x = -1e12; pmax.y = -1e12;
|
||||||
pmin.x = 1e12; pmin.y = 1e12;
|
pmin.x = 1e12; pmin.y = 1e12;
|
||||||
wmin = 1;
|
wmin = 1;
|
||||||
LoopOverPoints(&pmax, &pmin, &wmin, true);
|
LoopOverPoints(&pmax, &pmin, &wmin, true, includingInvisibles);
|
||||||
|
|
||||||
// Adjust the scale so that no points are behind the camera
|
// Adjust the scale so that no points are behind the camera
|
||||||
if(wmin < 0.1) {
|
if(wmin < 0.1) {
|
||||||
@ -359,7 +362,7 @@ void GraphicsWindow::MenuView(int id) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MNU_ZOOM_TO_FIT:
|
case MNU_ZOOM_TO_FIT:
|
||||||
SS.GW.ZoomToFit();
|
SS.GW.ZoomToFit(false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MNU_NEAREST_ORTHO:
|
case MNU_NEAREST_ORTHO:
|
||||||
@ -718,6 +721,10 @@ void GraphicsWindow::ToggleBool(int link, DWORD v) {
|
|||||||
// so not meaningful to show them and hide the shaded.
|
// so not meaningful to show them and hide the shaded.
|
||||||
if(!SS.GW.showShaded) SS.GW.showFaces = false;
|
if(!SS.GW.showShaded) SS.GW.showFaces = false;
|
||||||
|
|
||||||
|
// We might need to regenerate the mesh and edge list, since the edges
|
||||||
|
// wouldn't have been generated if they were previously hidden.
|
||||||
|
if(SS.GW.showEdges) (SK.GetGroup(SS.GW.activeGroup))->displayDirty = true;
|
||||||
|
|
||||||
SS.GenerateAll();
|
SS.GenerateAll();
|
||||||
InvalidateGraphics();
|
InvalidateGraphics();
|
||||||
SS.later.showTW = true;
|
SS.later.showTW = true;
|
||||||
|
@ -321,6 +321,9 @@ void Group::GenerateShellAndMesh(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Group::GenerateDisplayItems(void) {
|
void Group::GenerateDisplayItems(void) {
|
||||||
|
// This is potentially slow (since we've got to triangulate a shell, or
|
||||||
|
// to find the emphasized edges for a mesh), so we will run it only
|
||||||
|
// if its inputs have changed.
|
||||||
if(displayDirty) {
|
if(displayDirty) {
|
||||||
displayMesh.Clear();
|
displayMesh.Clear();
|
||||||
runningShell.TriangulateInto(&displayMesh);
|
runningShell.TriangulateInto(&displayMesh);
|
||||||
@ -335,7 +338,11 @@ void Group::GenerateDisplayItems(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
displayEdges.Clear();
|
displayEdges.Clear();
|
||||||
runningShell.MakeEdgesInto(&displayEdges);
|
|
||||||
|
if(SS.GW.showEdges) {
|
||||||
|
runningShell.MakeEdgesInto(&displayEdges);
|
||||||
|
displayMesh.MakeEmphasizedEdgesInto(&displayEdges);
|
||||||
|
}
|
||||||
|
|
||||||
displayDirty = false;
|
displayDirty = false;
|
||||||
}
|
}
|
||||||
|
131
mesh.cpp
131
mesh.cpp
@ -77,11 +77,28 @@ void SMesh::MakeEdgesInPlaneInto(SEdgeList *sel, Vector n, double d) {
|
|||||||
// Select the naked edges in our resulting open mesh.
|
// Select the naked edges in our resulting open mesh.
|
||||||
SKdNode *root = SKdNode::From(&m);
|
SKdNode *root = SKdNode::From(&m);
|
||||||
root->SnapToMesh(&m);
|
root->SnapToMesh(&m);
|
||||||
root->MakeNakedEdgesInto(sel, false, NULL, NULL);
|
root->MakeCertainEdgesInto(sel, SKdNode::NAKED_OR_SELF_INTER_EDGES,
|
||||||
|
false, NULL, NULL);
|
||||||
|
|
||||||
m.Clear();
|
m.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SMesh::MakeEmphasizedEdgesInto(SEdgeList *sel) {
|
||||||
|
SKdNode *root = SKdNode::From(this);
|
||||||
|
root->MakeCertainEdgesInto(sel, SKdNode::EMPHASIZED_EDGES,
|
||||||
|
false, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// When we are called, all of the triangles from l.elem[start] to the end must
|
||||||
|
// be coplanar. So we try to find a set of fewer triangles that covers the
|
||||||
|
// exact same area, in order to reduce the number of triangles in the mesh.
|
||||||
|
// We use this after a triangle has been split against the BSP.
|
||||||
|
//
|
||||||
|
// This is really ugly code; basically it just pastes things together to
|
||||||
|
// form convex polygons, merging collinear edges when possible, then
|
||||||
|
// triangulates the convex poly.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
void SMesh::Simplify(int start) {
|
void SMesh::Simplify(int start) {
|
||||||
int maxTriangles = (l.n - start) + 10;
|
int maxTriangles = (l.n - start) + 10;
|
||||||
|
|
||||||
@ -756,7 +773,8 @@ void SKdNode::OcclusionTestLine(SEdge orig, SEdgeList *sel, int cnt) {
|
|||||||
// mesh, otherwise not.
|
// mesh, otherwise not.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void SKdNode::FindEdgeOn(Vector a, Vector b, int *n, int cnt,
|
void SKdNode::FindEdgeOn(Vector a, Vector b, int *n, int cnt,
|
||||||
bool coplanarIsInter, bool *inter, bool *fwd)
|
bool coplanarIsInter, bool *inter, bool *fwd,
|
||||||
|
DWORD *face)
|
||||||
{
|
{
|
||||||
if(gt && lt) {
|
if(gt && lt) {
|
||||||
double ac = a.Element(which),
|
double ac = a.Element(which),
|
||||||
@ -764,12 +782,12 @@ void SKdNode::FindEdgeOn(Vector a, Vector b, int *n, int cnt,
|
|||||||
if(ac < c + KDTREE_EPS ||
|
if(ac < c + KDTREE_EPS ||
|
||||||
bc < c + KDTREE_EPS)
|
bc < c + KDTREE_EPS)
|
||||||
{
|
{
|
||||||
lt->FindEdgeOn(a, b, n, cnt, coplanarIsInter, inter, fwd);
|
lt->FindEdgeOn(a, b, n, cnt, coplanarIsInter, inter, fwd, face);
|
||||||
}
|
}
|
||||||
if(ac > c - KDTREE_EPS ||
|
if(ac > c - KDTREE_EPS ||
|
||||||
bc > c - KDTREE_EPS)
|
bc > c - KDTREE_EPS)
|
||||||
{
|
{
|
||||||
gt->FindEdgeOn(a, b, n, cnt, coplanarIsInter, inter, fwd);
|
gt->FindEdgeOn(a, b, n, cnt, coplanarIsInter, inter, fwd, face);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -794,6 +812,8 @@ void SKdNode::FindEdgeOn(Vector a, Vector b, int *n, int cnt,
|
|||||||
} else {
|
} else {
|
||||||
*fwd = false;
|
*fwd = false;
|
||||||
}
|
}
|
||||||
|
// And record the triangle's face
|
||||||
|
*face = tr->meta.face;
|
||||||
} 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))))
|
||||||
@ -848,15 +868,16 @@ void SKdNode::FindEdgeOn(Vector a, Vector b, int *n, int cnt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Report all naked edges of the mesh (i.e., edges that don't join up to
|
// Pick certain classes of edges out from our mesh. These might be:
|
||||||
// a single anti-parallel edge of another triangle), and all edges that
|
// * naked edges (i.e., edges with no anti-parallel neighbor) and self-
|
||||||
// intersect another triangle. If coplanarIsInter, then edges coplanar with
|
// intersecting edges (i.e., edges that cross another triangle)
|
||||||
// another triangle and within it are reported, otherwise not. We report
|
// * turning edges (i.e., edges where a front-facing triangle joins
|
||||||
// in *inter and *leaky whether the mesh is self-intersecting or leaky
|
// a back-facing triangle)
|
||||||
// (having naked edges) respectively.
|
// * emphasized edges (i.e., edges where a triangle from one face joins
|
||||||
|
// a triangle from a different face)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void SKdNode::MakeNakedEdgesInto(SEdgeList *sel, bool coplanarIsInter,
|
void SKdNode::MakeCertainEdgesInto(SEdgeList *sel, int how,
|
||||||
bool *inter, bool *leaky)
|
bool coplanarIsInter, bool *inter, bool *leaky)
|
||||||
{
|
{
|
||||||
if(inter) *inter = false;
|
if(inter) *inter = false;
|
||||||
if(leaky) *leaky = false;
|
if(leaky) *leaky = false;
|
||||||
@ -871,57 +892,51 @@ void SKdNode::MakeNakedEdgesInto(SEdgeList *sel, bool coplanarIsInter,
|
|||||||
for(i = 0; i < m.l.n; i++) {
|
for(i = 0; i < m.l.n; i++) {
|
||||||
STriangle *tr = &(m.l.elem[i]);
|
STriangle *tr = &(m.l.elem[i]);
|
||||||
|
|
||||||
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, nOther = 0;
|
|
||||||
bool thisIntersects = false, fwd;
|
|
||||||
FindEdgeOn(a, b, &n, cnt, coplanarIsInter, &thisIntersects, &fwd);
|
|
||||||
if(n != 1) {
|
|
||||||
sel->AddEdge(a, b);
|
|
||||||
if(leaky) *leaky = true;
|
|
||||||
}
|
|
||||||
if(thisIntersects) {
|
|
||||||
sel->AddEdge(a, b);
|
|
||||||
if(inter) *inter = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
cnt++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Report all the edges of the mesh where a front- and back-facing triangle
|
|
||||||
// join. These edges should be drawn when we generate a wireframe drawing
|
|
||||||
// of the part.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
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++) {
|
for(j = 0; j < 3; j++) {
|
||||||
Vector a = (j == 0) ? tr->a : ((j == 1) ? tr->b : tr->c);
|
Vector a = (j == 0) ? tr->a : ((j == 1) ? tr->b : tr->c);
|
||||||
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;
|
int n = 0;
|
||||||
bool inter, fwd;
|
bool thisIntersects = false, fwd;
|
||||||
FindEdgeOn(a, b, &n, cnt, true, &inter, &fwd);
|
DWORD face;
|
||||||
if(n == 1) {
|
FindEdgeOn(a, b, &n, cnt, coplanarIsInter,
|
||||||
// and its neighbour is front-facing, so generate the edge.
|
&thisIntersects, &fwd, &face);
|
||||||
if(fwd) sel->AddEdge(a, b);
|
|
||||||
|
switch(how) {
|
||||||
|
case NAKED_OR_SELF_INTER_EDGES:
|
||||||
|
if(n != 1) {
|
||||||
|
sel->AddEdge(a, b);
|
||||||
|
if(leaky) *leaky = true;
|
||||||
|
}
|
||||||
|
if(thisIntersects) {
|
||||||
|
sel->AddEdge(a, b);
|
||||||
|
if(inter) *inter = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TURNING_EDGES:
|
||||||
|
if((tr->Normal().z < LENGTH_EPS) &&
|
||||||
|
(n == 1) &&
|
||||||
|
fwd)
|
||||||
|
{
|
||||||
|
// This triangle is back-facing (or on edge), and
|
||||||
|
// this edge has exactly one mate, and that mate is
|
||||||
|
// front-facing. So this is a turning edge.
|
||||||
|
sel->AddEdge(a, b);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EMPHASIZED_EDGES:
|
||||||
|
if(tr->meta.face != face && n == 1) {
|
||||||
|
// The two triangles that join at this edge come from
|
||||||
|
// different faces; either really different faces,
|
||||||
|
// or one is from a face and the other is zero (i.e.,
|
||||||
|
// not from a face).
|
||||||
|
sel->AddEdge(a, b);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: oops();
|
||||||
}
|
}
|
||||||
|
|
||||||
cnt++;
|
cnt++;
|
||||||
|
10
polygon.h
10
polygon.h
@ -192,6 +192,7 @@ public:
|
|||||||
void MakeFromAssemblyOf(SMesh *a, SMesh *b);
|
void MakeFromAssemblyOf(SMesh *a, SMesh *b);
|
||||||
|
|
||||||
void MakeEdgesInPlaneInto(SEdgeList *sel, Vector n, double d);
|
void MakeEdgesInPlaneInto(SEdgeList *sel, Vector n, double d);
|
||||||
|
void MakeEmphasizedEdgesInto(SEdgeList *sel);
|
||||||
|
|
||||||
bool IsEmpty(void);
|
bool IsEmpty(void);
|
||||||
void RemapFaces(Group *g, int remap);
|
void RemapFaces(Group *g, int remap);
|
||||||
@ -232,10 +233,13 @@ public:
|
|||||||
void ClearTags(void);
|
void ClearTags(void);
|
||||||
|
|
||||||
void FindEdgeOn(Vector a, Vector b, int *n, int cnt, bool coplanarIsInter,
|
void FindEdgeOn(Vector a, Vector b, int *n, int cnt, bool coplanarIsInter,
|
||||||
bool *inter, bool *fwd);
|
bool *inter, bool *fwd,
|
||||||
void MakeNakedEdgesInto(SEdgeList *sel, bool coplanarIsInter,
|
DWORD *face);
|
||||||
|
static const int NAKED_OR_SELF_INTER_EDGES = 100;
|
||||||
|
static const int TURNING_EDGES = 200;
|
||||||
|
static const int EMPHASIZED_EDGES = 300;
|
||||||
|
void MakeCertainEdgesInto(SEdgeList *sel, int how, bool coplanarIsInter,
|
||||||
bool *inter, bool *leaky);
|
bool *inter, bool *leaky);
|
||||||
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);
|
||||||
|
@ -213,13 +213,15 @@ void SolveSpace::AfterNewFile(void) {
|
|||||||
GW.height = h;
|
GW.height = h;
|
||||||
|
|
||||||
// The triangles haven't been generated yet, but zoom to fit the entities
|
// The triangles haven't been generated yet, but zoom to fit the entities
|
||||||
// roughly in the window, since that sets the mesh tolerance.
|
// roughly in the window, since that sets the mesh tolerance. Consider
|
||||||
GW.ZoomToFit();
|
// invisible entities, so we still get something reasonable if the only
|
||||||
|
// thing visible is the not-yet-generated surfaces.
|
||||||
|
GW.ZoomToFit(true);
|
||||||
|
|
||||||
GenerateAll(0, INT_MAX);
|
GenerateAll(0, INT_MAX);
|
||||||
later.showTW = true;
|
later.showTW = true;
|
||||||
// Then zoom to fit again, to fit the triangles
|
// Then zoom to fit again, to fit the triangles
|
||||||
GW.ZoomToFit();
|
GW.ZoomToFit(false);
|
||||||
|
|
||||||
UpdateWindowTitle();
|
UpdateWindowTitle();
|
||||||
}
|
}
|
||||||
@ -420,7 +422,9 @@ void SolveSpace::MenuAnalyze(int id) {
|
|||||||
SMesh *m = &(SK.GetGroup(SS.GW.activeGroup)->displayMesh);
|
SMesh *m = &(SK.GetGroup(SS.GW.activeGroup)->displayMesh);
|
||||||
SKdNode *root = SKdNode::From(m);
|
SKdNode *root = SKdNode::From(m);
|
||||||
bool inters, leaks;
|
bool inters, leaks;
|
||||||
root->MakeNakedEdgesInto(&(SS.nakedEdges), true, &inters, &leaks);
|
root->MakeCertainEdgesInto(&(SS.nakedEdges),
|
||||||
|
SKdNode::NAKED_OR_SELF_INTER_EDGES, true, &inters, &leaks);
|
||||||
|
|
||||||
InvalidateGraphics();
|
InvalidateGraphics();
|
||||||
|
|
||||||
char *intersMsg = inters ?
|
char *intersMsg = inters ?
|
||||||
@ -446,7 +450,9 @@ void SolveSpace::MenuAnalyze(int id) {
|
|||||||
SMesh *m = &(SK.GetGroup(SS.GW.activeGroup)->displayMesh);
|
SMesh *m = &(SK.GetGroup(SS.GW.activeGroup)->displayMesh);
|
||||||
SKdNode *root = SKdNode::From(m);
|
SKdNode *root = SKdNode::From(m);
|
||||||
bool inters, leaks;
|
bool inters, leaks;
|
||||||
root->MakeNakedEdgesInto(&(SS.nakedEdges), false, &inters, &leaks);
|
root->MakeCertainEdgesInto(&(SS.nakedEdges),
|
||||||
|
SKdNode::NAKED_OR_SELF_INTER_EDGES, false, &inters, &leaks);
|
||||||
|
|
||||||
InvalidateGraphics();
|
InvalidateGraphics();
|
||||||
|
|
||||||
if(inters) {
|
if(inters) {
|
||||||
|
5
ui.h
5
ui.h
@ -301,8 +301,9 @@ public:
|
|||||||
Vector VectorFromProjs(Vector rightUpForward);
|
Vector VectorFromProjs(Vector rightUpForward);
|
||||||
void HandlePointForZoomToFit(Vector p, Point2d *pmax, Point2d *pmin,
|
void HandlePointForZoomToFit(Vector p, Point2d *pmax, Point2d *pmin,
|
||||||
double *wmin, bool div);
|
double *wmin, bool div);
|
||||||
void LoopOverPoints(Point2d *pmax, Point2d *pmin, double *wmin, bool div);
|
void LoopOverPoints(Point2d *pmax, Point2d *pmin, double *wmin, bool div,
|
||||||
void ZoomToFit(void);
|
bool includingInvisibles);
|
||||||
|
void ZoomToFit(bool includingInvisibles);
|
||||||
|
|
||||||
hGroup activeGroup;
|
hGroup activeGroup;
|
||||||
void EnsureValidActives(void);
|
void EnsureValidActives(void);
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
|
|
||||||
marching algorithm for surface intersection
|
marching algorithm for surface intersection
|
||||||
tangent intersections
|
tangent intersections
|
||||||
put back the meshes
|
|
||||||
|
|
||||||
-----
|
-----
|
||||||
line styles (color, thickness)
|
line styles (color, thickness)
|
||||||
loop detection
|
loop detection
|
||||||
incremental regen of entities?
|
|
||||||
IGES and STEP export
|
IGES and STEP export
|
||||||
|
incremental regen of entities?
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user