| 22 | } |
| 23 | |
| 24 | Mesh::Ptr MeshCutter::cut_with_face_labels(const std::vector<size_t>& comp_ids) const { |
| 25 | const size_t num_faces = m_mesh->get_num_faces(); |
| 26 | if (comp_ids.size() != num_faces) { |
| 27 | throw RuntimeError("Comp ids size does not match the number of faces in mesh"); |
| 28 | } |
| 29 | const size_t dim = m_mesh->get_dim(); |
| 30 | const size_t num_vertices = m_mesh->get_num_vertices(); |
| 31 | const size_t vertex_per_face = m_mesh->get_vertex_per_face(); |
| 32 | const auto& vertices = m_mesh->get_vertices(); |
| 33 | const auto& faces = m_mesh->get_faces(); |
| 34 | |
| 35 | std::vector<size_t> added_vertices; |
| 36 | std::vector<std::unordered_map<size_t, size_t>> index_map(num_vertices); |
| 37 | for (size_t i=0; i<num_vertices; i++) { |
| 38 | const auto& adj_faces = m_mesh->get_vertex_adjacent_faces(i); |
| 39 | const size_t num_adj_faces = adj_faces.size(); |
| 40 | if (num_adj_faces == 0) continue; |
| 41 | |
| 42 | bool is_interior_vtx = true; |
| 43 | for (size_t j=1; is_interior_vtx && j<num_adj_faces; j++) { |
| 44 | is_interior_vtx &= (comp_ids[adj_faces[0]] == comp_ids[adj_faces[j]]); |
| 45 | } |
| 46 | if (is_interior_vtx) continue; |
| 47 | |
| 48 | auto min_id = comp_ids[adj_faces[0]]; |
| 49 | for (size_t j=0; j<num_adj_faces; j++) { |
| 50 | if (min_id > comp_ids[adj_faces[j]]) { |
| 51 | min_id = comp_ids[adj_faces[j]]; |
| 52 | } |
| 53 | } |
| 54 | |
| 55 | auto& m = index_map[i]; |
| 56 | m[min_id] = i; |
| 57 | for (size_t j=0; j<num_adj_faces; j++) { |
| 58 | const auto itr = m.find(comp_ids[adj_faces[j]]); |
| 59 | if (itr == m.end()) { |
| 60 | m[comp_ids[adj_faces[j]]] = num_vertices + added_vertices.size(); |
| 61 | added_vertices.push_back(i); |
| 62 | } |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | const size_t num_added_vertices = added_vertices.size(); |
| 67 | VectorF new_vertices((num_vertices + num_added_vertices) * dim); |
| 68 | new_vertices.segment(0, num_vertices * dim) = vertices; |
| 69 | for (size_t i=0; i<num_added_vertices; i++) { |
| 70 | new_vertices.segment((num_vertices+i)*dim, dim) = |
| 71 | vertices.segment(added_vertices[i]*dim, dim); |
| 72 | } |
| 73 | |
| 74 | VectorI new_faces = faces; |
| 75 | for (size_t i=0; i<num_faces; i++) { |
| 76 | const auto id = comp_ids[i]; |
| 77 | for (size_t j=0; j<vertex_per_face; j++) { |
| 78 | const auto& m = index_map[new_faces[i*vertex_per_face+j]]; |
| 79 | if (m.empty()) continue; |
| 80 | assert(m.find(id) != m.end()); |
| 81 | new_faces[i*vertex_per_face+j] = m.at(id); |