51 const std::vector<Tuple> &element_tuples,
52 const bool include_global_boundary)
56 std::unordered_set<size_t> global_element_ids;
59 m_elements.resize(element_tuples.size(), m.dim() + 1);
60 m_body_ids.reserve(element_tuples.size());
61 for (
int fi = 0; fi < num_elements(); fi++)
63 const Tuple &elem = element_tuples[fi];
64 global_element_ids.insert(m.element_id(elem));
66 const auto vids = m.element_vids(elem);
68 for (
int i = 0; i < vids.size(); ++i)
70 if (m_global_to_local.find(vids[i]) == m_global_to_local.end())
71 m_global_to_local[vids[i]] = m_global_to_local.size();
72 m_elements(fi, i) = m_global_to_local[vids[i]];
75 m_body_ids.push_back(m.element_attrs[m.element_id(elem)].body_id);
79 m_num_local_vertices = m_global_to_local.size();
83 std::vector<Tuple> local_boundary_facets;
86 for (
int fi = 0; fi < num_elements(); fi++)
88 const Tuple &elem = element_tuples[fi];
90 for (
int i = 0; i < M::FACETS_PER_ELEMENT; ++i)
92 const Tuple facet = m.tuple_from_facet(m.element_id(elem), i);
95 if (m.is_boundary_facet(facet))
97 local_boundary_facets.push_back(facet);
102 if constexpr (std::is_same_v<M, TriMesh>)
103 adjacent_tid = facet.switch_face(m)->fid(m);
105 adjacent_tid = facet.switch_tetrahedron(m)->tid(m);
108 if (global_element_ids.find(adjacent_tid) != global_element_ids.end())
111 for (
const size_t &vid : m.facet_vids(facet))
112 m_fixed_vertices.push_back(m_global_to_local[vid]);
120 std::vector<Tuple> facets_tuples;
121 facets_tuples.reserve(num_elements() * M::FACETS_PER_ELEMENT);
122 std::vector<Tuple> local_boundary_facets;
123 for (
const Tuple &elem : element_tuples)
124 for (
int i = 0; i < M::FACETS_PER_ELEMENT; ++i)
125 facets_tuples.push_back(m.tuple_from_facet(m.element_id(elem), i));
127 if constexpr (std::is_same_v<M, TriMesh>)
131 for (
const Tuple &t : facets_tuples)
133 auto vids = m.facet_vids(t);
135 v = m_global_to_local[v];
137 const int boundary_id = m.boundary_attrs[m.facet_id(t)].boundary_id;
139 if constexpr (std::is_same_v<M, TriMesh>)
142 std::get<Remesher::FaceMap<int>>(m_boundary_ids)[vids] = boundary_id;
147 if (include_global_boundary)
151 const std::unordered_map<int, int> prev_global_to_local = m_global_to_local;
153 const std::vector<Tuple> global_boundary_facets = m.boundary_facets();
155 boundary_facets().resize(global_boundary_facets.size(), m_elements.cols() - 1);
156 for (
int i = 0; i < global_boundary_facets.size(); i++)
158 const Tuple &facet = global_boundary_facets[i];
159 const auto vids = m.facet_vids(facet);
161 const bool is_new_facet = std::any_of(vids.begin(), vids.end(), [&](
size_t vid) {
162 return prev_global_to_local.find(vid) == prev_global_to_local.end();
165 for (
int j = 0; j < vids.size(); ++j)
167 if (m_global_to_local.find(vids[j]) == m_global_to_local.end())
168 m_global_to_local[vids[j]] = m_global_to_local.size();
170 boundary_facets()(i, j) = m_global_to_local[vids[j]];
173 m_fixed_vertices.push_back(boundary_facets()(i, j));
182 boundary_facets().resize(local_boundary_facets.size(), m_elements.cols() - 1);
183 for (
int i = 0; i < local_boundary_facets.size(); i++)
185 const auto vids = m.facet_vids(local_boundary_facets[i]);
186 for (
int j = 0; j < vids.size(); ++j)
187 boundary_facets()(i, j) = m_global_to_local[vids[j]];
191 if (m_boundary_faces.rows() > 0)
192 igl::edges(m_boundary_faces, m_boundary_edges);
194 remove_duplicate_fixed_vertices();
198 init_vertex_attributes(m);
200 init_local_to_global();
202 const int tmp_num_vertices = num_vertices();
205 if (include_global_boundary && m.obstacle().n_vertices() > 0)
208 const Obstacle &obstacle = m.obstacle();
217 for (
int i = 0; i < obstacle.
n_vertices(); i++)
218 m_fixed_vertices.push_back(i + tmp_num_vertices);
231 const M &m,
const std::vector<Tuple> &one_ring,
const int n)
234 assert(!has_duplicate_elements(m, one_ring));
236 std::vector<Tuple> elements = one_ring;
237 std::unordered_set<size_t> visited_vertices;
238 std::unordered_set<size_t> visited_elements;
239 for (
const auto &element : elements)
241 visited_elements.insert(m.element_id(element));
244 std::vector<Tuple> new_elements = elements;
246 for (
int i = 1; i < n; i++)
248 std::vector<Tuple> new_new_elements;
249 for (
const auto &elem : new_elements)
251 for (
const Tuple &v : m.element_vertices(elem))
253 if (visited_vertices.find(v.vid(m)) != visited_vertices.end())
255 visited_vertices.insert(v.vid(m));
257 std::vector<Tuple> tmp = m.get_one_ring_elements_for_vertex(v);
260 if (visited_elements.find(m.element_id(t1)) != visited_elements.end())
262 visited_elements.insert(m.element_id(t1));
263 elements.push_back(t1);
264 new_new_elements.push_back(t1);
268 new_elements = new_new_elements;
269 if (new_elements.empty())
273 assert(!has_duplicate_elements(m, elements));
280 const M &m,
const Tuple ¢er,
const double area)
284 double current_area = 0;
286 std::vector<Tuple> elements = m.get_one_ring_elements_for_vertex(center);
287 std::unordered_set<size_t> visited_vertices{{center.vid(m)}};
288 std::unordered_set<size_t> visited_faces;
289 for (
const auto &element : elements)
290 visited_faces.insert(m.element_id(element));
292 std::vector<Tuple> new_elements = elements;
295 while (current_area < area)
298 std::vector<Tuple> new_new_elements;
299 for (
const auto &elem : new_elements)
301 current_area += m.element_volume(elem);
302 const auto vs = m.element_vertices(elem);
303 for (
int vi = 0; vi < 3; vi++)
305 const Tuple &v = vs[vi];
306 if (visited_vertices.find(v.vid(m)) != visited_vertices.end())
308 visited_vertices.insert(v.vid(m));
310 std::vector<Tuple> tmp = m.get_one_ring_elements_for_vertex(v);
313 if (visited_faces.find(m.element_id(t1)) != visited_faces.end())
315 visited_faces.insert(m.element_id(t1));
316 elements.push_back(t1);
317 new_new_elements.push_back(t1);
321 new_elements = new_new_elements;
322 if (new_elements.empty())
332 const M &m,
const VectorNd ¢er,
const double volume,
const int n_ring_size)
336 const int dim = m.dim();
337 const double radius = dim == 2 ? std::sqrt(volume / igl::PI) : std::cbrt(0.75 * volume / igl::PI);
338 constexpr double eps_radius = 1e-10;
339 const VectorNd sphere_min = center.array() - radius;
340 const VectorNd sphere_max = center.array() + radius;
342 const std::vector<Tuple> elements = m.get_elements();
347 std::vector<Tuple> intersecting_elements;
348 std::unordered_set<size_t> intersecting_fid;
349 double intersecting_volume = 0;
350 std::vector<Tuple> one_ring;
351 for (
const Tuple &element : elements)
354 m.element_aabb(element, el_min, el_max);
361 const auto vids = m.element_vids(element);
362 if constexpr (std::is_same_v<M, TriMesh>)
365 m.vertex_attrs[vids[0]].rest_position,
366 m.vertex_attrs[vids[1]].rest_position,
367 m.vertex_attrs[vids[2]].rest_position,
375 static_assert(std::is_same_v<M, TetMesh>);
377 m.vertex_attrs[vids[0]].rest_position,
378 m.vertex_attrs[vids[1]].rest_position,
379 m.vertex_attrs[vids[2]].rest_position,
380 m.vertex_attrs[vids[3]].rest_position,
387 intersecting_elements.push_back(element);
388 intersecting_fid.insert(m.element_id(element));
389 intersecting_volume += m.element_volume(element);
392 if constexpr (std::is_same_v<M, TriMesh>)
395 m.vertex_attrs[vids[0]].rest_position,
396 m.vertex_attrs[vids[1]].rest_position,
397 m.vertex_attrs[vids[2]].rest_position,
405 static_assert(std::is_same_v<M, TetMesh>);
407 m.vertex_attrs[vids[0]].rest_position,
408 m.vertex_attrs[vids[1]].rest_position,
409 m.vertex_attrs[vids[2]].rest_position,
410 m.vertex_attrs[vids[3]].rest_position,
417 one_ring.push_back(element);
419 assert(!intersecting_elements.empty());
424 for (
int i = 0; intersecting_volume < volume && i < intersecting_elements.size(); ++i)
426 const size_t element_id = m.element_id(intersecting_elements[i]);
428 for (
int j = 0; j < M::FACETS_PER_ELEMENT; ++j)
430 const Tuple facet = m.tuple_from_facet(element_id, j);
432 std::optional<Tuple> neighbor;
433 if constexpr (std::is_same_v<M, TriMesh>)
434 neighbor = facet.switch_face(m);
436 neighbor = facet.switch_tetrahedron(m);
438 if (!neighbor.has_value() || intersecting_fid.find(m.element_id(neighbor.value())) != intersecting_fid.end())
441 intersecting_elements.push_back(neighbor.value());
442 intersecting_fid.insert(m.element_id(neighbor.value()));
443 intersecting_volume += m.element_volume(neighbor.value());
446 assert(intersecting_volume >= volume);
451 for (
const auto &e : n_ring(m, one_ring, n_ring_size))
453 if (intersecting_fid.find(m.element_id(e)) == intersecting_fid.end())
455 intersecting_elements.push_back(e);
456 intersecting_fid.insert(m.element_id(e));
457 intersecting_volume += m.element_volume(e);
461 assert(!has_duplicate_elements(m, intersecting_elements));
463 return intersecting_elements;
525 assert(permutation.size() == num_vertices());
530 m_projection_quantities, permutation, -1,
537 for (
auto &[glob_vi, loc_vi] : m_global_to_local)
538 loc_vi = permutation[loc_vi];
540 std::vector<int> new_local_to_global(m_local_to_global.size());
541 for (
int i = 0; i < m_local_to_global.size(); ++i)
542 new_local_to_global[permutation[i]] = m_local_to_global[i];
543 m_local_to_global = new_local_to_global;
545 for (
int &vi : m_fixed_vertices)
546 vi = permutation[vi];
548 if constexpr (std::is_same_v<M, TriMesh>)
552 for (
const auto &[e,
id] : old_boundary_ids)
554 const size_t v0 = permutation[e[0]], v1 = permutation[e[1]];
555 new_boundary_ids[{{v0, v1}}] = id;
557 m_boundary_ids = new_boundary_ids;
563 for (
const auto &[f,
id] : old_boundary_ids)
565 const size_t v0 = permutation[f[0]], v1 = permutation[f[1]], v2 = permutation[f[2]];
566 new_boundary_ids[{{v0, v1, v2}}] = id;
568 m_boundary_ids = new_boundary_ids;
577 std::vector<polyfem::basis::ElementBases> bases;
579 std::vector<LocalBoundary> local_boundary;
580 Eigen::VectorXi vertex_to_basis;
581 std::unique_ptr<Mesh> mesh =
Mesh::create(rest_positions(), elements());
583 *mesh, formulation, bases, local_boundary, vertex_to_basis);
585 assert(n_bases == num_local_vertices());
586 assert(vertex_to_basis.size() == num_local_vertices());
587 n_bases = num_vertices();
588 vertex_to_basis.conservativeResize(n_bases);
590 const int start_i = num_local_vertices();
591 if (start_i < n_bases)
594 std::iota(vertex_to_basis.begin() + start_i, vertex_to_basis.end(), start_i);
597 assert(std::all_of(vertex_to_basis.begin(), vertex_to_basis.end(), [](
const int basis_id) {
598 return basis_id >= 0;
601 reorder_vertices(vertex_to_basis);