53 const std::vector<Tuple> &element_tuples,
54 const bool include_global_boundary)
58 std::unordered_set<size_t> global_element_ids;
61 m_elements.resize(element_tuples.size(), m.dim() + 1);
62 m_body_ids.reserve(element_tuples.size());
63 for (
int fi = 0; fi < num_elements(); fi++)
65 const Tuple &elem = element_tuples[fi];
66 global_element_ids.insert(m.element_id(elem));
68 const auto vids = m.element_vids(elem);
70 for (
int i = 0; i < vids.size(); ++i)
72 if (m_global_to_local.find(vids[i]) == m_global_to_local.end())
73 m_global_to_local[vids[i]] = m_global_to_local.size();
74 m_elements(fi, i) = m_global_to_local[vids[i]];
77 m_body_ids.push_back(m.element_attrs[m.element_id(elem)].body_id);
81 m_num_local_vertices = m_global_to_local.size();
85 std::vector<Tuple> local_boundary_facets;
88 for (
int fi = 0; fi < num_elements(); fi++)
90 const Tuple &elem = element_tuples[fi];
92 for (
int i = 0; i < M::FACETS_PER_ELEMENT; ++i)
94 const Tuple facet = m.tuple_from_facet(m.element_id(elem), i);
97 if (m.is_boundary_facet(facet))
99 local_boundary_facets.push_back(facet);
104 if constexpr (std::is_same_v<M, TriMesh>)
105 adjacent_tid = facet.switch_face(m)->fid(m);
107 adjacent_tid = facet.switch_tetrahedron(m)->tid(m);
110 if (global_element_ids.find(adjacent_tid) != global_element_ids.end())
113 for (
const size_t &vid : m.facet_vids(facet))
114 m_fixed_vertices.push_back(m_global_to_local[vid]);
122 std::vector<Tuple> facets_tuples;
123 facets_tuples.reserve(num_elements() * M::FACETS_PER_ELEMENT);
124 std::vector<Tuple> local_boundary_facets;
125 for (
const Tuple &elem : element_tuples)
126 for (
int i = 0; i < M::FACETS_PER_ELEMENT; ++i)
127 facets_tuples.push_back(m.tuple_from_facet(m.element_id(elem), i));
129 if constexpr (std::is_same_v<M, TriMesh>)
133 for (
const Tuple &t : facets_tuples)
135 auto vids = m.facet_vids(t);
137 v = m_global_to_local[v];
139 const int boundary_id = m.boundary_attrs[m.facet_id(t)].boundary_id;
141 if constexpr (std::is_same_v<M, TriMesh>)
144 std::get<Remesher::FaceMap<int>>(m_boundary_ids)[vids] = boundary_id;
149 if (include_global_boundary)
153 const std::unordered_map<int, int> prev_global_to_local = m_global_to_local;
155 const std::vector<Tuple> global_boundary_facets = m.boundary_facets();
157 boundary_facets().resize(global_boundary_facets.size(), m_elements.cols() - 1);
158 for (
int i = 0; i < global_boundary_facets.size(); i++)
160 const Tuple &facet = global_boundary_facets[i];
161 const auto vids = m.facet_vids(facet);
163 const bool is_new_facet = std::any_of(vids.begin(), vids.end(), [&](
size_t vid) {
164 return prev_global_to_local.find(vid) == prev_global_to_local.end();
167 for (
int j = 0; j < vids.size(); ++j)
169 if (m_global_to_local.find(vids[j]) == m_global_to_local.end())
170 m_global_to_local[vids[j]] = m_global_to_local.size();
172 boundary_facets()(i, j) = m_global_to_local[vids[j]];
175 m_fixed_vertices.push_back(boundary_facets()(i, j));
184 boundary_facets().resize(local_boundary_facets.size(), m_elements.cols() - 1);
185 for (
int i = 0; i < local_boundary_facets.size(); i++)
187 const auto vids = m.facet_vids(local_boundary_facets[i]);
188 for (
int j = 0; j < vids.size(); ++j)
189 boundary_facets()(i, j) = m_global_to_local[vids[j]];
193 if (m_boundary_faces.rows() > 0)
194 igl::edges(m_boundary_faces, m_boundary_edges);
196 remove_duplicate_fixed_vertices();
200 init_vertex_attributes(m);
202 init_local_to_global();
204 const int tmp_num_vertices = num_vertices();
207 if (include_global_boundary && m.obstacle().n_vertices() > 0)
210 const Obstacle &obstacle = m.obstacle();
219 for (
int i = 0; i < obstacle.
n_vertices(); i++)
220 m_fixed_vertices.push_back(i + tmp_num_vertices);
233 const M &m,
const std::vector<Tuple> &one_ring,
const int n)
236 assert(!has_duplicate_elements(m, one_ring));
238 std::vector<Tuple> elements = one_ring;
239 std::unordered_set<size_t> visited_vertices;
240 std::unordered_set<size_t> visited_elements;
241 for (
const auto &element : elements)
243 visited_elements.insert(m.element_id(element));
246 std::vector<Tuple> new_elements = elements;
248 for (
int i = 1; i < n; i++)
250 std::vector<Tuple> new_new_elements;
251 for (
const auto &elem : new_elements)
253 for (
const Tuple &v : m.element_vertices(elem))
255 if (visited_vertices.find(v.vid(m)) != visited_vertices.end())
257 visited_vertices.insert(v.vid(m));
259 std::vector<Tuple> tmp = m.get_one_ring_elements_for_vertex(v);
262 if (visited_elements.find(m.element_id(t1)) != visited_elements.end())
264 visited_elements.insert(m.element_id(t1));
265 elements.push_back(t1);
266 new_new_elements.push_back(t1);
270 new_elements = new_new_elements;
271 if (new_elements.empty())
275 assert(!has_duplicate_elements(m, elements));
282 const M &m,
const Tuple ¢er,
const double area)
286 double current_area = 0;
288 std::vector<Tuple> elements = m.get_one_ring_elements_for_vertex(center);
289 std::unordered_set<size_t> visited_vertices{{center.vid(m)}};
290 std::unordered_set<size_t> visited_faces;
291 for (
const auto &element : elements)
292 visited_faces.insert(m.element_id(element));
294 std::vector<Tuple> new_elements = elements;
297 while (current_area < area)
300 std::vector<Tuple> new_new_elements;
301 for (
const auto &elem : new_elements)
303 current_area += m.element_volume(elem);
304 const auto vs = m.element_vertices(elem);
305 for (
int vi = 0; vi < 3; vi++)
307 const Tuple &v = vs[vi];
308 if (visited_vertices.find(v.vid(m)) != visited_vertices.end())
310 visited_vertices.insert(v.vid(m));
312 std::vector<Tuple> tmp = m.get_one_ring_elements_for_vertex(v);
315 if (visited_faces.find(m.element_id(t1)) != visited_faces.end())
317 visited_faces.insert(m.element_id(t1));
318 elements.push_back(t1);
319 new_new_elements.push_back(t1);
323 new_elements = new_new_elements;
324 if (new_elements.empty())
334 const M &m,
const VectorNd ¢er,
const double volume,
const int n_ring_size)
338 const int dim = m.dim();
339 const double radius = dim == 2 ? std::sqrt(volume / igl::PI) : std::cbrt(0.75 * volume / igl::PI);
340 constexpr double eps_radius = 1e-10;
341 const VectorNd sphere_min = center.array() - radius;
342 const VectorNd sphere_max = center.array() + radius;
344 const std::vector<Tuple> elements = m.get_elements();
349 std::vector<Tuple> intersecting_elements;
350 std::unordered_set<size_t> intersecting_fid;
351 double intersecting_volume = 0;
352 std::vector<Tuple> one_ring;
353 for (
const Tuple &element : elements)
356 m.element_aabb(element, el_min, el_max);
363 const auto vids = m.element_vids(element);
364 if constexpr (std::is_same_v<M, TriMesh>)
367 m.vertex_attrs[vids[0]].rest_position,
368 m.vertex_attrs[vids[1]].rest_position,
369 m.vertex_attrs[vids[2]].rest_position,
377 static_assert(std::is_same_v<M, TetMesh>);
379 m.vertex_attrs[vids[0]].rest_position,
380 m.vertex_attrs[vids[1]].rest_position,
381 m.vertex_attrs[vids[2]].rest_position,
382 m.vertex_attrs[vids[3]].rest_position,
389 intersecting_elements.push_back(element);
390 intersecting_fid.insert(m.element_id(element));
391 intersecting_volume += m.element_volume(element);
394 if constexpr (std::is_same_v<M, TriMesh>)
397 m.vertex_attrs[vids[0]].rest_position,
398 m.vertex_attrs[vids[1]].rest_position,
399 m.vertex_attrs[vids[2]].rest_position,
407 static_assert(std::is_same_v<M, TetMesh>);
409 m.vertex_attrs[vids[0]].rest_position,
410 m.vertex_attrs[vids[1]].rest_position,
411 m.vertex_attrs[vids[2]].rest_position,
412 m.vertex_attrs[vids[3]].rest_position,
419 one_ring.push_back(element);
421 assert(!intersecting_elements.empty());
426 for (
int i = 0; intersecting_volume < volume && i < intersecting_elements.size(); ++i)
428 const size_t element_id = m.element_id(intersecting_elements[i]);
430 for (
int j = 0; j < M::FACETS_PER_ELEMENT; ++j)
432 const Tuple facet = m.tuple_from_facet(element_id, j);
434 std::optional<Tuple> neighbor;
435 if constexpr (std::is_same_v<M, TriMesh>)
436 neighbor = facet.switch_face(m);
438 neighbor = facet.switch_tetrahedron(m);
440 if (!neighbor.has_value() || intersecting_fid.find(m.element_id(neighbor.value())) != intersecting_fid.end())
443 intersecting_elements.push_back(neighbor.value());
444 intersecting_fid.insert(m.element_id(neighbor.value()));
445 intersecting_volume += m.element_volume(neighbor.value());
448 assert(intersecting_volume >= volume);
453 for (
const auto &e : n_ring(m, one_ring, n_ring_size))
455 if (intersecting_fid.find(m.element_id(e)) == intersecting_fid.end())
457 intersecting_elements.push_back(e);
458 intersecting_fid.insert(m.element_id(e));
459 intersecting_volume += m.element_volume(e);
463 assert(!has_duplicate_elements(m, intersecting_elements));
465 return intersecting_elements;
527 assert(permutation.size() == num_vertices());
532 m_projection_quantities, permutation, -1,
539 for (
auto &[glob_vi, loc_vi] : m_global_to_local)
540 loc_vi = permutation[loc_vi];
542 std::vector<int> new_local_to_global(m_local_to_global.size());
543 for (
int i = 0; i < m_local_to_global.size(); ++i)
544 new_local_to_global[permutation[i]] = m_local_to_global[i];
545 m_local_to_global = new_local_to_global;
547 for (
int &vi : m_fixed_vertices)
548 vi = permutation[vi];
550 if constexpr (std::is_same_v<M, TriMesh>)
554 for (
const auto &[e,
id] : old_boundary_ids)
556 const size_t v0 = permutation[e[0]], v1 = permutation[e[1]];
557 new_boundary_ids[{{v0, v1}}] = id;
559 m_boundary_ids = new_boundary_ids;
565 for (
const auto &[f,
id] : old_boundary_ids)
567 const size_t v0 = permutation[f[0]], v1 = permutation[f[1]], v2 = permutation[f[2]];
568 new_boundary_ids[{{v0, v1, v2}}] = id;
570 m_boundary_ids = new_boundary_ids;
579 std::vector<polyfem::basis::ElementBases> bases;
581 std::vector<LocalBoundary> local_boundary;
582 Eigen::VectorXi vertex_to_basis;
583 std::unique_ptr<Mesh> mesh =
Mesh::create(rest_positions(), elements());
585 *mesh, formulation, bases, local_boundary, vertex_to_basis);
587 assert(n_bases == num_local_vertices());
588 assert(vertex_to_basis.size() == num_local_vertices());
589 n_bases = num_vertices();
590 vertex_to_basis.conservativeResize(n_bases);
592 const int start_i = num_local_vertices();
593 if (start_i < n_bases)
596 std::iota(vertex_to_basis.begin() + start_i, vertex_to_basis.end(), start_i);
599 assert(std::all_of(vertex_to_basis.begin(), vertex_to_basis.end(), [](
const int basis_id) {
600 return basis_id >= 0;
603 reorder_vertices(vertex_to_basis);