From f7485c214105a882fb84f7e2ef9ed4adbcbdb9a2 Mon Sep 17 00:00:00 2001 From: Gilbert Bernstein Date: Wed, 13 Feb 2013 16:14:32 -0800 Subject: [PATCH] implemented isSolid() test; simplified cork.h; trimmed number of headers This commit closes issue #2 and issue #8 --- Makefile | 20 ++-- src/cork.cpp | 249 ++++++++++++++++------------------------- src/cork.h | 91 +++++---------- src/main.cpp | 144 +++++++++++------------- src/mesh/mesh.decl.h | 3 + src/mesh/mesh.isct.tpp | 33 ++++++ src/mesh/mesh.tpp | 28 +++++ 7 files changed, 261 insertions(+), 307 deletions(-) diff --git a/Makefile b/Makefile index 15a52c6..a9fbb62 100644 --- a/Makefile +++ b/Makefile @@ -12,12 +12,12 @@ SUBDIRECTORIES := util file_formats math isct mesh rawmesh accel # make sure the subdirectories are mirrored in # the obj/ debug/ and depend/ directories # (HACK: use this dummy variable to get access to shell commands) -SHELL_HACK := $(shell mkdir -p bin lib) +SHELL_HACK := $(shell mkdir -p bin lib include) SHELL_HACK := $(shell mkdir -p $(addprefix obj/,$(SUBDIRECTORIES))) SHELL_HACK := $(shell mkdir -p $(addprefix debug/,$(SUBDIRECTORIES))) SHELL_HACK := $(shell mkdir -p $(addprefix depend/,$(SUBDIRECTORIES))) # also make a directory to expose headers in -SHELL_HACK := $(shell mkdir -p $(addprefix include/,$(SUBDIRECTORIES))) +#SHELL_HACK := $(shell mkdir -p $(addprefix include/,$(SUBDIRECTORIES))) # +----------+ # | Platform | @@ -121,14 +121,14 @@ MESH_HEADERS := mesh.h mesh.decl.h \ ACCEL_HEADERS := aabvh.h FILE_HEADERS := files.h HEADERS := \ - cork.h \ - $(addprefix math/,$(MATH_HEADERS))\ - $(addprefix util/,$(UTIL_HEADERS))\ - $(addprefix isct/,$(ISCT_HEADERS))\ - $(addprefix mesh/,$(MESH_HEADERS))\ - $(addprefix rawmesh/,$(RAWMESH_HEADERS))\ - $(addprefix accel/,$(ACCEL_HEADERS))\ - $(addprefix file_formats/,$(FILE_HEADERS)) + cork.h +# $(addprefix math/,$(MATH_HEADERS))\ +# $(addprefix util/,$(UTIL_HEADERS))\ +# $(addprefix isct/,$(ISCT_HEADERS))\ +# $(addprefix mesh/,$(MESH_HEADERS))\ +# $(addprefix rawmesh/,$(RAWMESH_HEADERS))\ +# $(addprefix accel/,$(ACCEL_HEADERS))\ +# $(addprefix file_formats/,$(FILE_HEADERS)) HEADER_COPIES := $(addprefix include/,$(HEADERS)) # +-----------------------------+ diff --git a/src/cork.cpp b/src/cork.cpp index 2b5a1c5..01059b5 100644 --- a/src/cork.cpp +++ b/src/cork.cpp @@ -27,6 +27,16 @@ #include "mesh.h" + +void freeCorkTriMesh(CorkTriMesh *mesh) +{ + delete[] mesh->triangles; + delete[] mesh->vertices; + mesh->n_triangles = 0; + mesh->n_vertices = 0; +} + + struct CorkTriangle; struct CorkVertex : @@ -97,223 +107,152 @@ struct CorkTriangle : using RawCorkMesh = RawMesh; using CorkMesh = Mesh; -void cMesh2CorkMesh( - uint n_triangles_in, uint *triangles_in, - uint n_vertices_in, float *vertices_in, +void corkTriMesh2CorkMesh( + CorkTriMesh in, CorkMesh *mesh_out ) { RawCorkMesh raw; - raw.vertices.resize(n_vertices_in); - raw.triangles.resize(n_triangles_in); - if(n_vertices_in == 0 || n_triangles_in == 0) { + raw.vertices.resize(in.n_vertices); + raw.triangles.resize(in.n_triangles); + if(in.n_vertices == 0 || in.n_triangles == 0) { ERROR("empty mesh input to Cork routine."); *mesh_out = CorkMesh(raw); return; } uint max_ref_idx = 0; - for(uint i=0; i n_vertices_in) { - ERROR("mesh input to Cork routine has an out of range vertex index."); + if(max_ref_idx > in.n_vertices) { + ERROR("mesh input to Cork routine has an out of range reference " + "to a vertex."); raw.vertices.clear(); raw.triangles.clear(); *mesh_out = CorkMesh(raw); return; } - for(uint i=0; iraw(); - *n_triangles_out = raw.triangles.size(); - *n_vertices_out = raw.vertices.size(); + out->n_triangles = raw.triangles.size(); + out->n_vertices = raw.vertices.size(); - *triangles_out = new uint[(*n_triangles_out) * 3]; - *vertices_out = new float[(*n_vertices_out) * 3]; + out->triangles = new uint[(out->n_triangles) * 3]; + out->vertices = new float[(out->n_vertices) * 3]; - for(uint i=0; i<*n_triangles_out; i++) { - (*triangles_out)[3*i+0] = raw.triangles[i].a; - (*triangles_out)[3*i+1] = raw.triangles[i].b; - (*triangles_out)[3*i+2] = raw.triangles[i].c; + for(uint i=0; in_triangles; i++) { + (out->triangles)[3*i+0] = raw.triangles[i].a; + (out->triangles)[3*i+1] = raw.triangles[i].b; + (out->triangles)[3*i+2] = raw.triangles[i].c; } - for(uint i=0; i<*n_vertices_out; i++) { - (*vertices_out)[3*i+0] = raw.vertices[i].pos.x; - (*vertices_out)[3*i+1] = raw.vertices[i].pos.y; - (*vertices_out)[3*i+2] = raw.vertices[i].pos.z; + for(uint i=0; in_vertices; i++) { + (out->vertices)[3*i+0] = raw.vertices[i].pos.x; + (out->vertices)[3*i+1] = raw.vertices[i].pos.y; + (out->vertices)[3*i+2] = raw.vertices[i].pos.z; } } +bool isSolid(CorkTriMesh cmesh) +{ + CorkMesh mesh; + corkTriMesh2CorkMesh(cmesh, &mesh); + + bool solid = true; + + if(mesh.isSelfIntersecting()) { + ERROR("isSolid() was given a self-intersecting mesh"); + solid = false; + } + + if(!mesh.isClosed()) { + ERROR("isSolid() was given a non-closed mesh"); + solid = false; + } + + return solid; +} + void computeUnion( - // input mesh 0 - uint n_triangles_in0, uint *triangles_in0, - uint n_vertices_in0, float *vertices_in0, - // input mesh 1 - uint n_triangles_in1, uint *triangles_in1, - uint n_vertices_in1, float *vertices_in1, - // output mesh - uint *n_triangles_out, uint **triangles_out, - uint *n_vertices_out, float **vertices_out + CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out ) { - // convert input - CorkMesh in0, in1; - cMesh2CorkMesh( - n_triangles_in0, triangles_in0, - n_vertices_in0, vertices_in0, - &in0); - cMesh2CorkMesh( - n_triangles_in1, triangles_in1, - n_vertices_in1, vertices_in1, - &in1); + CorkMesh cmIn0, cmIn1; + corkTriMesh2CorkMesh(in0, &cmIn0); + corkTriMesh2CorkMesh(in1, &cmIn1); - in0.boolUnion(in1); + cmIn0.boolUnion(cmIn1); - // convert output - corkMesh2CMesh(&in0, - n_triangles_out, triangles_out, - n_vertices_out, vertices_out); + corkMesh2CorkTriMesh(&cmIn0, out); } void computeDifference( - // input mesh 0 - uint n_triangles_in0, uint *triangles_in0, - uint n_vertices_in0, float *vertices_in0, - // input mesh 1 - uint n_triangles_in1, uint *triangles_in1, - uint n_vertices_in1, float *vertices_in1, - // output mesh - uint *n_triangles_out, uint **triangles_out, - uint *n_vertices_out, float **vertices_out + CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out ) { - // convert input - CorkMesh in0, in1; - cMesh2CorkMesh( - n_triangles_in0, triangles_in0, - n_vertices_in0, vertices_in0, - &in0); - cMesh2CorkMesh( - n_triangles_in1, triangles_in1, - n_vertices_in1, vertices_in1, - &in1); + CorkMesh cmIn0, cmIn1; + corkTriMesh2CorkMesh(in0, &cmIn0); + corkTriMesh2CorkMesh(in1, &cmIn1); - in0.boolDiff(in1); + cmIn0.boolDiff(cmIn1); - // convert output - corkMesh2CMesh(&in0, - n_triangles_out, triangles_out, - n_vertices_out, vertices_out); + corkMesh2CorkTriMesh(&cmIn0, out); } void computeIntersection( - // input mesh 0 - uint n_triangles_in0, uint *triangles_in0, - uint n_vertices_in0, float *vertices_in0, - // input mesh 1 - uint n_triangles_in1, uint *triangles_in1, - uint n_vertices_in1, float *vertices_in1, - // output mesh - uint *n_triangles_out, uint **triangles_out, - uint *n_vertices_out, float **vertices_out + CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out ) { - // convert input - CorkMesh in0, in1; - cMesh2CorkMesh( - n_triangles_in0, triangles_in0, - n_vertices_in0, vertices_in0, - &in0); - cMesh2CorkMesh( - n_triangles_in1, triangles_in1, - n_vertices_in1, vertices_in1, - &in1); + CorkMesh cmIn0, cmIn1; + corkTriMesh2CorkMesh(in0, &cmIn0); + corkTriMesh2CorkMesh(in1, &cmIn1); - in0.boolIsct(in1); + cmIn0.boolIsct(cmIn1); - // convert output - corkMesh2CMesh(&in0, - n_triangles_out, triangles_out, - n_vertices_out, vertices_out); + corkMesh2CorkTriMesh(&cmIn0, out); } void computeSymmetricDifference( - // input mesh 0 - uint n_triangles_in0, uint *triangles_in0, - uint n_vertices_in0, float *vertices_in0, - // input mesh 1 - uint n_triangles_in1, uint *triangles_in1, - uint n_vertices_in1, float *vertices_in1, - // output mesh - uint *n_triangles_out, uint **triangles_out, - uint *n_vertices_out, float **vertices_out + CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out ) { - // convert input - CorkMesh in0, in1; - cMesh2CorkMesh( - n_triangles_in0, triangles_in0, - n_vertices_in0, vertices_in0, - &in0); - cMesh2CorkMesh( - n_triangles_in1, triangles_in1, - n_vertices_in1, vertices_in1, - &in1); + CorkMesh cmIn0, cmIn1; + corkTriMesh2CorkMesh(in0, &cmIn0); + corkTriMesh2CorkMesh(in1, &cmIn1); - in0.boolXor(in1); + cmIn0.boolXor(cmIn1); - // convert output - corkMesh2CMesh(&in0, - n_triangles_out, triangles_out, - n_vertices_out, vertices_out); + corkMesh2CorkTriMesh(&cmIn0, out); } void resolveIntersections( - // input mesh 0 - uint n_triangles_in0, uint *triangles_in0, - uint n_vertices_in0, float *vertices_in0, - // input mesh 1 - uint n_triangles_in1, uint *triangles_in1, - uint n_vertices_in1, float *vertices_in1, - // output mesh - uint *n_triangles_out, uint **triangles_out, - uint *n_vertices_out, float **vertices_out + CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out ) { - // convert input - CorkMesh in0, in1; - cMesh2CorkMesh( - n_triangles_in0, triangles_in0, - n_vertices_in0, vertices_in0, - &in0); - cMesh2CorkMesh( - n_triangles_in1, triangles_in1, - n_vertices_in1, vertices_in1, - &in1); + CorkMesh cmIn0, cmIn1; + corkTriMesh2CorkMesh(in0, &cmIn0); + corkTriMesh2CorkMesh(in1, &cmIn1); - in0.disjointUnion(in1); - in0.resolveIntersections(); + cmIn0.disjointUnion(cmIn1); + cmIn0.resolveIntersections(); - // convert output - corkMesh2CMesh(&in0, - n_triangles_out, triangles_out, - n_vertices_out, vertices_out); + corkMesh2CorkTriMesh(&cmIn0, out); } diff --git a/src/cork.h b/src/cork.h index 77eb296..78bcb8a 100644 --- a/src/cork.h +++ b/src/cork.h @@ -29,85 +29,46 @@ typedef unsigned int uint; #endif -// TODO: describe input format here. +// if a mesh is taken as input, the client must manage the memory +// if a mesh is given as output, please use the provided +// function to free the allocated memory. +struct CorkTriMesh +{ + uint n_triangles; + uint n_vertices; + uint *triangles; + float *vertices; +}; -// the inputs to a Boolean operation must be "solid": -// - closed (aka. watertight; -// every edge has an even number of incident triangles) +void freeCorkTriMesh(CorkTriMesh *mesh); + +// the inputs to Boolean operations must be "solid": +// - closed (aka. watertight; see comment at bottom) // - non-self-intersecting -// - have consistent CCW triangle orientation -// This function will test whether or not a given mesh is solid -bool isSolid( - uint n_triangles, uint *triangles, - uint n_vertices, float *vertices -); +// additionally, inputs should use a counter-clockwise convention +// for triangle facing. If the triangles are presented in clockwise +// orientation, the object is interpreted as its unbounded complement + +// This function will test whether or not a mesh is solid +bool isSolid(CorkTriMesh mesh); // Boolean operations follow // result = A U B -void computeUnion( - // input mesh 0 - uint n_triangles_in0, uint *triangles_in0, - uint n_vertices_in0, float *vertices_in0, - // input mesh 1 - uint n_triangles_in1, uint *triangles_in1, - uint n_vertices_in1, float *vertices_in1, - // output mesh - uint *n_triangles_out, uint **triangles_out, - uint *n_vertices_out, float **vertices_out -); +void computeUnion(CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out); // result = A - B -void computeDifference( - // input mesh 0 - uint n_triangles_in0, uint *triangles_in0, - uint n_vertices_in0, float *vertices_in0, - // input mesh 1 - uint n_triangles_in1, uint *triangles_in1, - uint n_vertices_in1, float *vertices_in1, - // output mesh - uint *n_triangles_out, uint **triangles_out, - uint *n_vertices_out, float **vertices_out -); +void computeDifference(CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out); // result = A ^ B -void computeIntersection( - // input mesh 0 - uint n_triangles_in0, uint *triangles_in0, - uint n_vertices_in0, float *vertices_in0, - // input mesh 1 - uint n_triangles_in1, uint *triangles_in1, - uint n_vertices_in1, float *vertices_in1, - // output mesh - uint *n_triangles_out, uint **triangles_out, - uint *n_vertices_out, float **vertices_out -); +void computeIntersection(CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out); // result = A XOR B void computeSymmetricDifference( - // input mesh 0 - uint n_triangles_in0, uint *triangles_in0, - uint n_vertices_in0, float *vertices_in0, - // input mesh 1 - uint n_triangles_in1, uint *triangles_in1, - uint n_vertices_in1, float *vertices_in1, - // output mesh - uint *n_triangles_out, uint **triangles_out, - uint *n_vertices_out, float **vertices_out -); + CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out); -// An operation which is not a Boolean operation, but is related: +// Not a Boolean operation, but related: // No portion of either surface is deleted. However, the // curve of intersection between the two surfaces is made explicit, // such that the two surfaces are now connected. -void resolveIntersections( - // input mesh 0 - uint n_triangles_in0, uint *triangles_in0, - uint n_vertices_in0, float *vertices_in0, - // input mesh 1 - uint n_triangles_in1, uint *triangles_in1, - uint n_vertices_in1, float *vertices_in1, - // output mesh - uint *n_triangles_out, uint **triangles_out, - uint *n_vertices_out, float **vertices_out -); +void resolveIntersections(CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out); diff --git a/src/main.cpp b/src/main.cpp index bf04497..89c5f5b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -43,55 +43,49 @@ using std::ostream; #include "cork.h" -void file2cmesh( - const Files::FileMesh &in, - uint *n_triangles_out, uint **triangles_out, - uint *n_vertices_out, float **vertices_out +void file2corktrimesh( + const Files::FileMesh &in, CorkTriMesh *out ) { - *n_vertices_out = in.vertices.size(); - *n_triangles_out = in.triangles.size(); + out->n_vertices = in.vertices.size(); + out->n_triangles = in.triangles.size(); - *triangles_out = new uint[(*n_triangles_out) * 3]; - *vertices_out = new float[(*n_vertices_out) * 3]; + out->triangles = new uint[(out->n_triangles) * 3]; + out->vertices = new float[(out->n_vertices) * 3]; - for(uint i=0; i<*n_triangles_out; i++) { - (*triangles_out)[3*i+0] = in.triangles[i].a; - (*triangles_out)[3*i+1] = in.triangles[i].b; - (*triangles_out)[3*i+2] = in.triangles[i].c; + for(uint i=0; in_triangles; i++) { + (out->triangles)[3*i+0] = in.triangles[i].a; + (out->triangles)[3*i+1] = in.triangles[i].b; + (out->triangles)[3*i+2] = in.triangles[i].c; } - for(uint i=0; i<*n_vertices_out; i++) { - (*vertices_out)[3*i+0] = in.vertices[i].pos.x; - (*vertices_out)[3*i+1] = in.vertices[i].pos.y; - (*vertices_out)[3*i+2] = in.vertices[i].pos.z; + for(uint i=0; in_vertices; i++) { + (out->vertices)[3*i+0] = in.vertices[i].pos.x; + (out->vertices)[3*i+1] = in.vertices[i].pos.y; + (out->vertices)[3*i+2] = in.vertices[i].pos.z; } } -void cmesh2file( - uint n_triangles_in, uint *triangles_in, - uint n_vertices_in, float *vertices_in, - Files::FileMesh &out +void corktrimesh2file( + CorkTriMesh in, Files::FileMesh &out ) { - out.vertices.resize(n_vertices_in); - out.triangles.resize(n_triangles_in); + out.vertices.resize(in.n_vertices); + out.triangles.resize(in.n_triangles); - for(uint i=0; i 0) { @@ -99,22 +93,13 @@ void loadMesh(string filename, exit(1); } - file2cmesh(filemesh, - n_triangles_out, triangles_out, - n_vertices_out, vertices_out - ); + file2corktrimesh(filemesh, out); } -void saveMesh(string filename, - uint n_triangles_in, uint *triangles_in, - uint n_vertices_in, float *vertices_in -) { +void saveMesh(string filename, CorkTriMesh in) +{ Files::FileMesh filemesh; - cmesh2file( - n_triangles_in, triangles_in, - n_vertices_in, vertices_in, - filemesh - ); + corktrimesh2file(in, filemesh); if(Files::writeTriMesh(filename, &filemesh) > 0) { cerr << "Unable to write to " << filename << endl; @@ -222,51 +207,37 @@ std::function< void( const std::vector::iterator & ) > genericBinaryOp( - std::function< void( - // input mesh 0 - uint n_triangles_in0, uint *triangles_in0, - uint n_vertices_in0, float *vertices_in0, - // input mesh 1 - uint n_triangles_in1, uint *triangles_in1, - uint n_vertices_in1, float *vertices_in1, - // output mesh - uint *n_triangles_out, uint **triangles_out, - uint *n_vertices_out, float **vertices_out - ) > binop + std::function< void(CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out) > + binop ) { return [binop] (std::vector::iterator &args, const std::vector::iterator &end) { // data... - uint nTri0, nTri1, nTriOut; - uint nVert0, nVert1, nVertOut; - uint *tri0, *tri1, *triOut; - float *vert0, *vert1, *vertOut; + CorkTriMesh in0; + CorkTriMesh in1; + CorkTriMesh out; if(args == end) { cerr << "too few args" << endl; exit(1); } - loadMesh(*args, &nTri0, &tri0, &nVert0, &vert0); + loadMesh(*args, &in0); args++; if(args == end) { cerr << "too few args" << endl; exit(1); } - loadMesh(*args, &nTri1, &tri1, &nVert1, &vert1); + loadMesh(*args, &in1); args++; - binop( - nTri0, tri0, nVert0, vert0, - nTri1, tri1, nVert1, vert1, - &nTriOut, &triOut, &nVertOut, &vertOut - ); + binop(in0, in1, &out); if(args == end) { cerr << "too few args" << endl; exit(1); } - saveMesh(*args, nTriOut, triOut, nVertOut, vertOut); + saveMesh(*args, out); args++; - delete [] tri0; - delete [] tri1; - delete [] triOut; - delete [] vert0; - delete [] vert1; - delete [] vertOut; + freeCorkTriMesh(&out); + + delete[] in0.vertices; + delete[] in0.triangles; + delete[] in1.vertices; + delete[] in1.triangles; }; } @@ -293,6 +264,25 @@ int main(int argc, char *argv[]) CmdList cmds; // add cmds + cmds.regCmd("solid", + "-solid in Determine whether the input mesh represents\n" + " a solid object. (aka. watertight) (technically\n" + " solid == closed and non-self-intersecting)", + [](std::vector::iterator &args, + const std::vector::iterator &end) { + CorkTriMesh in; + if(args == end) { cerr << "too few args" << endl; exit(1); } + string filename = *args; + loadMesh(*args, &in); + args++; + + bool solid = isSolid(in); + cout << "The mesh " << filename << " is: " << endl; + cout << " " << ((solid)? "SOLID" : "NOT SOLID") << endl; + + delete[] in.vertices; + delete[] in.triangles; + }); cmds.regCmd("union", "-union in0 in1 out Compute the Boolean union of in0 and in1,\n" " and output the result", @@ -308,7 +298,7 @@ int main(int argc, char *argv[]) cmds.regCmd("xor", "-xor in0 in1 out Compute the Boolean XOR of in0 and in1,\n" " and output the result\n" - " (aka. the symmetric difference)\n", + " (aka. the symmetric difference)", genericBinaryOp(computeSymmetricDifference)); cmds.regCmd("resolve", "-resolve in0 in1 out Intersect the two meshes in0 and in1,\n" diff --git a/src/mesh/mesh.decl.h b/src/mesh/mesh.decl.h index 5967a72..1401c91 100644 --- a/src/mesh/mesh.decl.h +++ b/src/mesh/mesh.decl.h @@ -184,6 +184,8 @@ public: std::function func); + // checks if the mesh is closed + bool isClosed(); public: // REMESHING module // REQUIRES: @@ -194,6 +196,7 @@ public: // REMESHING module public: // ISCT (intersections) module void resolveIntersections(); // makes all intersections explicit + bool isSelfIntersecting(); // is the mesh self-intersecting? // TESTING void testingComputeStaticIsctPoints(std::vector *points); void testingComputeStaticIsct(std::vector *points, diff --git a/src/mesh/mesh.isct.tpp b/src/mesh/mesh.isct.tpp index c4c5b5c..3ffdd4e 100644 --- a/src/mesh/mesh.isct.tpp +++ b/src/mesh/mesh.isct.tpp @@ -789,6 +789,8 @@ public: // create edges as necessary... }*/ + bool hasIntersections(); // test for iscts, exit if one is found + void findIntersections(); void resolveAllIntersections(); private: @@ -1056,6 +1058,29 @@ void Mesh::IsctProblem::findIntersections() }); } +template +bool Mesh::IsctProblem::hasIntersections() +{ + bool foundIsct = false; + Empty3d::degeneracy_count = 0; + // Find some edge-triangle intersection point... + bvh_edge_tri([&](Eptr eisct, Tptr tisct)->bool{ + if(checkIsct(eisct,tisct)) { + foundIsct = true; + return false; // break; + } + if(Empty3d::degeneracy_count > 0) { + return false; // break; + } + return true; // continue + }); + + if(Empty3d::degeneracy_count > 0 || foundIsct) { + return true; + } else { + return false; + } +} template inline @@ -1471,5 +1496,13 @@ void Mesh::resolveIntersections() //iproblem.print(); } +template +bool Mesh::isSelfIntersecting() +{ + IsctProblem iproblem(this); + + return iproblem.hasIntersections(); +} + diff --git a/src/mesh/mesh.tpp b/src/mesh/mesh.tpp index e593573..f765a3f 100644 --- a/src/mesh/mesh.tpp +++ b/src/mesh/mesh.tpp @@ -186,6 +186,34 @@ typename Mesh::Isct +template +bool Mesh::isClosed() +{ + EGraphCache chains = createEGraphCache(); + // count up how many times each edge is encountered in one + // orientation vs. the other + for(Tri &tri : tris) { + chains(tri.a, tri.b).data ++; + chains(tri.b, tri.a).data --; + + chains(tri.b, tri.c).data ++; + chains(tri.c, tri.b).data --; + + chains(tri.c, tri.a).data ++; + chains(tri.a, tri.c).data --; + } + // now go through and see if any of these are non-zero + bool closed = true; + chains.for_each([&](uint i, uint j, EGraphEntry &entry) { + if(entry.data != 0) + closed = false; + }); + return closed; +} + + + + static inline bool contains(const ShortVec &list, uint item) {