| 7 | using namespace PyMesh; |
| 8 | |
| 9 | VectorI ManifoldCheck::is_vertex_manifold( |
| 10 | const MatrixIr& faces) { |
| 11 | const size_t num_faces = faces.rows(); |
| 12 | if (num_faces == 0) return VectorI(0); |
| 13 | const size_t num_vertices = faces.maxCoeff()+1; |
| 14 | const size_t vertex_per_face = faces.cols(); |
| 15 | |
| 16 | std::vector<std::vector<VectorI> > opposite_edges(num_vertices); |
| 17 | if (vertex_per_face == 3) { |
| 18 | for (size_t i=0; i<num_faces; i++) { |
| 19 | const auto& f = faces.row(i); |
| 20 | opposite_edges[f[0]].push_back(Vector2I(f[1], f[2])); |
| 21 | opposite_edges[f[1]].push_back(Vector2I(f[2], f[0])); |
| 22 | opposite_edges[f[2]].push_back(Vector2I(f[0], f[1])); |
| 23 | } |
| 24 | } else if (vertex_per_face == 4) { |
| 25 | for (size_t i=0; i<num_faces; i++) { |
| 26 | const auto& f = faces.row(i); |
| 27 | opposite_edges[f[0]].push_back(Vector2I(f[1], f[2])); |
| 28 | opposite_edges[f[0]].push_back(Vector2I(f[2], f[3])); |
| 29 | opposite_edges[f[1]].push_back(Vector2I(f[2], f[3])); |
| 30 | opposite_edges[f[1]].push_back(Vector2I(f[3], f[0])); |
| 31 | opposite_edges[f[2]].push_back(Vector2I(f[3], f[0])); |
| 32 | opposite_edges[f[2]].push_back(Vector2I(f[0], f[1])); |
| 33 | opposite_edges[f[3]].push_back(Vector2I(f[0], f[1])); |
| 34 | opposite_edges[f[3]].push_back(Vector2I(f[1], f[2])); |
| 35 | } |
| 36 | } else { |
| 37 | std::stringstream err_msg; |
| 38 | err_msg << "Vertex manifold check does not support face with " |
| 39 | << vertex_per_face << " vertices."; |
| 40 | throw NotImplementedError(err_msg.str()); |
| 41 | } |
| 42 | |
| 43 | VectorI is_manifold(num_vertices); |
| 44 | is_manifold.setConstant(1.0); |
| 45 | |
| 46 | for (size_t i=0; i<num_vertices; i++) { |
| 47 | const auto& entries = opposite_edges[i]; |
| 48 | if (entries.empty()) continue; |
| 49 | try { |
| 50 | auto edge_loops = EdgeUtils::chain_edges( |
| 51 | MatrixUtils::rowstack(entries)); |
| 52 | is_manifold[i] = edge_loops.size() == 1; |
| 53 | } catch (...) { |
| 54 | is_manifold[i] = 0; |
| 55 | } |
| 56 | } |
| 57 | return is_manifold; |
| 58 | } |
| 59 | |
| 60 | MatrixIr ManifoldCheck::is_edge_manifold(const MatrixIr& faces) { |
| 61 | const size_t num_faces = faces.rows(); |
nothing calls this directly
no test coverage detected