Warn if exporting a non-watertight mesh.
If a generated mesh is non-watertight, and this is not noticed for some reason (e.g. the markers are dismissed), and the mesh is exported for further processing, it could cause problems down the line.pull/109/head
parent
3b241392d4
commit
fdd08cbead
|
@ -812,7 +812,7 @@ void SolveSpaceUI::ExportMeshTo(const std::string &filename) {
|
||||||
Error("Couldn't write to '%s'", filename.c_str());
|
Error("Couldn't write to '%s'", filename.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
ShowNakedEdges(/*reportOnlyWhenNotOkay=*/true);
|
||||||
if(FilenameHasExtension(filename, ".stl")) {
|
if(FilenameHasExtension(filename, ".stl")) {
|
||||||
ExportMeshAsStlTo(f, m);
|
ExportMeshAsStlTo(f, m);
|
||||||
} else if(FilenameHasExtension(filename, ".obj")) {
|
} else if(FilenameHasExtension(filename, ".obj")) {
|
||||||
|
|
|
@ -596,34 +596,7 @@ void SolveSpaceUI::MenuAnalyze(Command id) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Command::NAKED_EDGES: {
|
case Command::NAKED_EDGES: {
|
||||||
SS.nakedEdges.Clear();
|
ShowNakedEdges(/*reportOnlyWhenNotOkay=*/false);
|
||||||
|
|
||||||
Group *g = SK.GetGroup(SS.GW.activeGroup);
|
|
||||||
SMesh *m = &(g->displayMesh);
|
|
||||||
SKdNode *root = SKdNode::From(m);
|
|
||||||
bool inters, leaks;
|
|
||||||
root->MakeCertainEdgesInto(&(SS.nakedEdges),
|
|
||||||
EdgeKind::NAKED_OR_SELF_INTER, /*coplanarIsInter=*/true, &inters, &leaks);
|
|
||||||
|
|
||||||
InvalidateGraphics();
|
|
||||||
|
|
||||||
const char *intersMsg = inters ?
|
|
||||||
"The mesh is self-intersecting (NOT okay, invalid)." :
|
|
||||||
"The mesh is not self-intersecting (okay, valid).";
|
|
||||||
const char *leaksMsg = leaks ?
|
|
||||||
"The mesh has naked edges (NOT okay, invalid)." :
|
|
||||||
"The mesh is watertight (okay, valid).";
|
|
||||||
|
|
||||||
std::string cntMsg = ssprintf("\n\nThe model contains %d triangles, from "
|
|
||||||
"%d surfaces.", g->displayMesh.l.n, g->runningShell.surface.n);
|
|
||||||
|
|
||||||
if(SS.nakedEdges.l.n == 0) {
|
|
||||||
Message("%s\n\n%s\n\nZero problematic edges, good.%s",
|
|
||||||
intersMsg, leaksMsg, cntMsg.c_str());
|
|
||||||
} else {
|
|
||||||
Error("%s\n\n%s\n\n%d problematic edges, bad.%s",
|
|
||||||
intersMsg, leaksMsg, SS.nakedEdges.l.n, cntMsg.c_str());
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -811,6 +784,40 @@ void SolveSpaceUI::MenuAnalyze(Command id) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SolveSpaceUI::ShowNakedEdges(bool reportOnlyWhenNotOkay) {
|
||||||
|
SS.nakedEdges.Clear();
|
||||||
|
|
||||||
|
Group *g = SK.GetGroup(SS.GW.activeGroup);
|
||||||
|
SMesh *m = &(g->displayMesh);
|
||||||
|
SKdNode *root = SKdNode::From(m);
|
||||||
|
bool inters, leaks;
|
||||||
|
root->MakeCertainEdgesInto(&(SS.nakedEdges),
|
||||||
|
EdgeKind::NAKED_OR_SELF_INTER, /*coplanarIsInter=*/true, &inters, &leaks);
|
||||||
|
|
||||||
|
if(reportOnlyWhenNotOkay && !inters && !leaks && SS.nakedEdges.l.n == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
InvalidateGraphics();
|
||||||
|
|
||||||
|
const char *intersMsg = inters ?
|
||||||
|
"The mesh is self-intersecting (NOT okay, invalid)." :
|
||||||
|
"The mesh is not self-intersecting (okay, valid).";
|
||||||
|
const char *leaksMsg = leaks ?
|
||||||
|
"The mesh has naked edges (NOT okay, invalid)." :
|
||||||
|
"The mesh is watertight (okay, valid).";
|
||||||
|
|
||||||
|
std::string cntMsg = ssprintf("\n\nThe model contains %d triangles, from "
|
||||||
|
"%d surfaces.", g->displayMesh.l.n, g->runningShell.surface.n);
|
||||||
|
|
||||||
|
if(SS.nakedEdges.l.n == 0) {
|
||||||
|
Message("%s\n\n%s\n\nZero problematic edges, good.%s",
|
||||||
|
intersMsg, leaksMsg, cntMsg.c_str());
|
||||||
|
} else {
|
||||||
|
Error("%s\n\n%s\n\n%d problematic edges, bad.%s",
|
||||||
|
intersMsg, leaksMsg, SS.nakedEdges.l.n, cntMsg.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SolveSpaceUI::MenuHelp(Command id) {
|
void SolveSpaceUI::MenuHelp(Command id) {
|
||||||
switch(id) {
|
switch(id) {
|
||||||
case Command::WEBSITE:
|
case Command::WEBSITE:
|
||||||
|
|
|
@ -881,6 +881,7 @@ public:
|
||||||
bool PruneGroups(hGroup hg);
|
bool PruneGroups(hGroup hg);
|
||||||
bool PruneRequests(hGroup hg);
|
bool PruneRequests(hGroup hg);
|
||||||
bool PruneConstraints(hGroup hg);
|
bool PruneConstraints(hGroup hg);
|
||||||
|
static void ShowNakedEdges(bool reportOnlyWhenNotOkay);
|
||||||
|
|
||||||
enum class Generate : uint32_t {
|
enum class Generate : uint32_t {
|
||||||
DIRTY,
|
DIRTY,
|
||||||
|
|
Loading…
Reference in New Issue