PolyFEM
Loading...
Searching...
No Matches
CMesh2D.cpp
Go to the documentation of this file.
3
8
9#include <geogram/basic/file_system.h>
10#include <geogram/mesh/mesh_io.h>
11#include <geogram/mesh/mesh_geometry.h>
12#include <geogram/mesh/mesh_repair.h>
13
14#include <cassert>
15#include <array>
16#include <unordered_map>
17#include <type_traits>
18
19namespace polyfem
20{
21 using namespace utils;
22
23 namespace mesh
24 {
25 void CMesh2D::remove_elements(const std::vector<bool> &keep)
26 {
27 assert(keep.size() == n_faces());
28
29 std::unordered_map<std::pair<int, int>, int, utils::HashPair> old_edge_ids;
30 std::unordered_map<std::pair<int, int>, EdgeNodes, utils::HashPair> old_edge_nodes;
31 for (int e = 0; e < n_edges(); ++e)
32 {
33 const std::pair<int, int> key = std::minmax(edge_vertex(e, 0), edge_vertex(e, 1));
34 if (has_boundary_ids())
35 old_edge_ids[key] = boundary_ids_[e];
36 if (e < edge_nodes_.size())
37 old_edge_nodes[key] = edge_nodes_[e];
38 }
39
40 auto filter_nodes = [&keep](auto &nodes) {
41 if (nodes.size() != keep.size())
42 return;
43 std::decay_t<decltype(nodes)> filtered;
44 for (int i = 0; i < keep.size(); ++i)
45 if (keep[i])
46 filtered.push_back(nodes[i]);
47 nodes = std::move(filtered);
48 };
49 filter_nodes(face_nodes_);
50 filter_nodes(cell_nodes_);
52
53 GEO::vector<GEO::index_t> to_delete(mesh_.facets.nb(), 0);
54 for (int f = 0; f < keep.size(); ++f)
55 to_delete[f] = keep[f] ? 0 : 1;
56 mesh_.facets.delete_elements(to_delete);
57
58 c2e_.reset();
59 boundary_vertices_.reset();
60 boundary_edges_.reset();
62 c2e_ = std::make_unique<GEO::Attribute<GEO::index_t>>(mesh_.facet_corners.attributes(), "edge_id");
63 boundary_vertices_ = std::make_unique<GEO::Attribute<bool>>(mesh_.vertices.attributes(), "boundary_vertex");
64 boundary_edges_ = std::make_unique<GEO::Attribute<bool>>(mesh_.edges.attributes(), "boundary_edge");
65
66 if (!old_edge_ids.empty())
67 {
68 boundary_ids_.resize(n_edges());
69 for (int e = 0; e < n_edges(); ++e)
70 {
71 const std::pair<int, int> key = std::minmax(edge_vertex(e, 0), edge_vertex(e, 1));
72 const auto it = old_edge_ids.find(key);
73 boundary_ids_[e] = it == old_edge_ids.end() ? get_default_boundary_id(e) : it->second;
74 }
75 }
76 else
77 boundary_ids_.clear();
78
79 edge_nodes_.clear();
80 if (!old_edge_nodes.empty())
81 {
82 edge_nodes_.resize(n_edges());
83 for (int e = 0; e < n_edges(); ++e)
84 {
85 const std::pair<int, int> key = std::minmax(edge_vertex(e, 0), edge_vertex(e, 1));
86 const auto it = old_edge_nodes.find(key);
87 if (it != old_edge_nodes.end())
88 edge_nodes_[e] = it->second;
89 }
90 }
91
92 in_ordered_edges_.resize(n_edges(), 2);
93 for (int e = 0; e < n_edges(); ++e)
94 in_ordered_edges_.row(e) << edge_vertex(e, 0), edge_vertex(e, 1);
96 }
97
98 void CMesh2D::refine(const int n_refinement, const double t)
99 {
100 // return;
101 if (n_refinement <= 0)
102 {
103 return;
104 }
105
106 orders_.resize(0, 0);
108
109 bool all_simplicial = true;
110 for (int e = 0; e < n_elements(); ++e)
111 {
112 all_simplicial &= is_simplex(e);
113 }
114
115 for (int i = 0; i < n_refinement; ++i)
116 {
117 GEO::Mesh mesh;
118 mesh.copy(mesh_);
119
120 c2e_.reset();
121 boundary_vertices_.reset();
122 boundary_edges_.reset();
123
124 mesh_.clear(false, false);
125
126 // TODO add tags to the refinement
127 if (all_simplicial)
128 {
130 }
131 else if (t <= 0)
132 {
134 }
135 else
136 {
138 }
139
141 c2e_ = std::make_unique<GEO::Attribute<GEO::index_t>>(mesh_.facet_corners.attributes(), "edge_id");
142 boundary_vertices_ = std::make_unique<GEO::Attribute<bool>>(mesh_.vertices.attributes(), "boundary_vertex");
143 boundary_edges_ = std::make_unique<GEO::Attribute<bool>>(mesh_.edges.attributes(), "boundary_edge");
144 }
145
148
149 in_ordered_vertices_ = Eigen::VectorXi::LinSpaced(mesh_.vertices.nb(), 0, mesh_.vertices.nb() - 1);
150 assert(in_ordered_vertices_[0] == 0);
151 assert(in_ordered_vertices_[1] == 1);
152 assert(in_ordered_vertices_[2] == 2);
153 assert(in_ordered_vertices_[in_ordered_vertices_.size() - 1] == mesh_.vertices.nb() - 1);
154
155 in_ordered_edges_.resize(mesh_.edges.nb(), 2);
156
157 for (int e = 0; e < (int)mesh_.edges.nb(); ++e)
158 {
159 for (int lv = 0; lv < 2; ++lv)
160 {
161 in_ordered_edges_(e, lv) = mesh_.edges.vertex(e, lv);
162 }
163 assert(in_ordered_edges_(e, 0) != in_ordered_edges_(e, 1));
164 }
165 assert(in_ordered_edges_.size() > 0);
166
167 in_ordered_faces_.resize(0, 0);
168 }
169
171 {
172 const Eigen::MatrixXd &V = data.vertices;
173 const Eigen::MatrixXi &F = data.elements;
174 edge_nodes_.clear();
175 face_nodes_.clear();
176 cell_nodes_.clear();
177
178 c2e_.reset();
179 boundary_vertices_.reset();
180 boundary_edges_.reset();
181
182 mesh_.clear(false, false);
183 mesh_.vertices.create_vertices(V.rows());
184 for (int i = 0; i < V.rows(); ++i)
185 {
186 GEO::vec3 &point = mesh_.vertices.point(i);
187 point[0] = V(i, 0);
188 point[1] = V(i, 1);
189 point[2] = 0;
190 }
191 for (int i = 0; i < F.rows(); ++i)
192 {
193 std::vector<GEO::index_t> vertices;
194 vertices.reserve(F.cols());
195 for (int j = 0; j < F.cols() && F(i, j) >= 0; ++j)
196 vertices.push_back(F(i, j));
197 if (vertices.size() < 3)
198 return false;
199 mesh_.facets.create_polygon(vertices.size(), vertices.data());
200 }
201
204
205 c2e_ = std::make_unique<GEO::Attribute<GEO::index_t>>(mesh_.facet_corners.attributes(), "edge_id");
206 boundary_vertices_ = std::make_unique<GEO::Attribute<bool>>(mesh_.vertices.attributes(), "boundary_vertex");
207 boundary_edges_ = std::make_unique<GEO::Attribute<bool>>(mesh_.edges.attributes(), "boundary_edge");
208
210 return true;
211 }
212
213 void CMesh2D::attach_higher_order_nodes(const Eigen::MatrixXd &V, const std::vector<std::vector<int>> &nodes)
214 {
215 edge_nodes_.clear();
216 face_nodes_.clear();
217 cell_nodes_.clear();
218
219 edge_nodes_.resize(n_edges());
220 face_nodes_.resize(n_faces());
221
222 orders_.resize(n_faces(), 1);
223
224 assert(nodes.size() == n_faces());
225
226 for (int f = 0; f < n_faces(); ++f)
227 {
228 auto index = get_index_from_face(f);
229
230 const auto &nodes_ids = nodes[f];
231
232 if (nodes_ids.size() == 3)
233 {
234 orders_(f) = 1;
235 continue;
236 }
237 // P2
238 else if (nodes_ids.size() == 6)
239 {
240 orders_(f) = 2;
241
242 for (int le = 0; le < 3; ++le)
243 {
244 auto &n = edge_nodes_[index.edge];
245
246 // nodes not aleardy created
247 if (n.nodes.size() <= 0)
248 {
249 n.v1 = index.vertex;
250 n.v2 = switch_vertex(index).vertex;
251
252 int node_index = 0;
253 if ((n.v1 == nodes_ids[0] && n.v2 == nodes_ids[1]) || (n.v2 == nodes_ids[0] && n.v1 == nodes_ids[1]))
254 node_index = 3;
255 else if ((n.v1 == nodes_ids[1] && n.v2 == nodes_ids[2]) || (n.v2 == nodes_ids[1] && n.v1 == nodes_ids[2]))
256 node_index = 4;
257 else
258 node_index = 5;
259
260 n.nodes.resize(1, 2);
261 n.nodes << V(nodes_ids[node_index], 0), V(nodes_ids[node_index], 1);
262 n.nodes_ids.push_back(nodes_ids[node_index]);
263 }
264 index = next_around_face(index);
265 }
266 }
267 // P3
268 else if (nodes_ids.size() == 10)
269 {
270 orders_(f) = 3;
271
272 for (int le = 0; le < 3; ++le)
273 {
274 auto &n = edge_nodes_[index.edge];
275
276 // nodes not aleardy created
277 if (n.nodes.size() <= 0)
278 {
279 n.v1 = index.vertex;
280 n.v2 = switch_vertex(index).vertex;
281
282 int node_index1 = 0;
283 int node_index2 = 0;
284 if (n.v1 == nodes_ids[0] && n.v2 == nodes_ids[1])
285 {
286 node_index1 = 3;
287 node_index2 = 4;
288 }
289 else if (n.v2 == nodes_ids[0] && n.v1 == nodes_ids[1])
290 {
291 node_index1 = 4;
292 node_index2 = 3;
293 }
294 else if (n.v1 == nodes_ids[1] && n.v2 == nodes_ids[2])
295 {
296 node_index1 = 5;
297 node_index2 = 6;
298 }
299 else if (n.v2 == nodes_ids[1] && n.v1 == nodes_ids[2])
300 {
301 node_index1 = 6;
302 node_index2 = 5;
303 }
304 else if (n.v1 == nodes_ids[2] && n.v2 == nodes_ids[0])
305 {
306 node_index1 = 7;
307 node_index2 = 8;
308 }
309 else
310 {
311 assert(n.v2 == nodes_ids[2] && n.v1 == nodes_ids[0]);
312 node_index1 = 8;
313 node_index2 = 7;
314 }
315
316 n.nodes.resize(2, 2);
317 n.nodes.row(0) << V(nodes_ids[node_index1], 0), V(nodes_ids[node_index1], 1);
318 n.nodes.row(1) << V(nodes_ids[node_index2], 0), V(nodes_ids[node_index2], 1);
319
320 n.nodes_ids.push_back(nodes_ids[node_index1]);
321 n.nodes_ids.push_back(nodes_ids[node_index2]);
322 }
323 index = next_around_face(index);
324 }
325
326 {
327 auto &n = face_nodes_[f];
328 n.v1 = mesh_.facets.vertex(f, 0);
329 n.v2 = mesh_.facets.vertex(f, 1);
330 n.v3 = mesh_.facets.vertex(f, 2);
331 n.nodes.resize(1, 2);
332 n.nodes << V(nodes_ids[9], 0), V(nodes_ids[9], 1);
333 n.nodes_ids.push_back(nodes_ids[9]);
334 }
335 }
336 // P4
337 else if (nodes_ids.size() == 15)
338 {
339 orders_(f) = 4;
340 assert(false);
341 // unsupported P4 for geometry, need meshes for testing
342 }
343 // unsupported
344 else
345 {
346 assert(false);
347 }
348 }
349
350 if (orders_.maxCoeff() == 1)
351 orders_.resize(0, 0);
352 }
353
354 std::pair<RowVectorNd, int> CMesh2D::edge_node(const Navigation::Index &index, const int n_new_nodes, const int i) const
355 {
356 if (orders_.size() <= 0 || orders_(index.face) == 1 || edge_nodes_.empty() || edge_nodes_[index.edge].nodes.rows() != n_new_nodes)
357 {
358 const auto v1 = point(index.vertex);
359 const auto v2 = point(switch_vertex(index).vertex);
360
361 const double t = i / (n_new_nodes + 1.0);
362
363 return std::make_pair((1 - t) * v1 + t * v2, -1);
364 }
365
366 const auto &n = edge_nodes_[index.edge];
367 if (n.v1 == index.vertex)
368 return std::make_pair(n.nodes.row(i - 1), n.nodes_ids[i - 1]);
369 else
370 {
371 assert(n.v2 == index.vertex);
372 return std::make_pair(n.nodes.row(n.nodes.rows() - i), n.nodes_ids[n.nodes_ids.size() - i]);
373 }
374 }
375
376 std::pair<RowVectorNd, int> CMesh2D::face_node(const Navigation::Index &index, const int n_new_nodes, const int i, const int j) const
377 {
378 if (is_simplex(index.face))
379 {
380 if (orders_.size() <= 0 || orders_(index.face) == 1 || orders_(index.face) == 2 || face_nodes_.empty() || face_nodes_[index.face].nodes.rows() != n_new_nodes)
381 {
382 const auto v1 = point(index.vertex);
383 const auto v2 = point(switch_vertex(index).vertex);
384 const auto v3 = point(switch_vertex(switch_edge(index)).vertex);
385
386 const double b2 = i / (n_new_nodes + 2.0);
387 const double b3 = j / (n_new_nodes + 2.0);
388 const double b1 = 1 - b3 - b2;
389 assert(b3 < 1);
390 assert(b3 > 0);
391
392 return std::make_pair(b1 * v1 + b2 * v2 + b3 * v3, -1);
393 }
394
395 assert(orders_(index.face) == 3);
396 // unsupported P4 for geometry
397 const auto &n = face_nodes_[index.face];
398 return std::make_pair(n.nodes.row(0), n.nodes_ids[0]);
399 }
400 else if (is_cube(index.face))
401 {
402 // supports only blilinear quads
403 assert(orders_.size() <= 0 || orders_(index.face) == 1);
404
405 const auto v1 = point(index.vertex);
406 const auto v2 = point(switch_vertex(index).vertex);
407 const auto v3 = point(switch_vertex(switch_edge(switch_vertex(index))).vertex);
408 const auto v4 = point(switch_vertex(switch_edge(index)).vertex);
409
410 const double b1 = i / (n_new_nodes + 1.0);
411 const double b2 = j / (n_new_nodes + 1.0);
412
413 return std::make_pair(v1 * (1 - b1) * (1 - b2) + v2 * b1 * (1 - b2) + v3 * b1 * b2 + v4 * (1 - b1) * b2, -1);
414 }
415
416 assert(false);
417 return std::make_pair(RowVectorNd(2, 1), -1);
418 }
419
421 {
422 GEO::vec3 min_corner, max_corner;
423 GEO::get_bbox(mesh_, &min_corner[0], &max_corner[0]);
424 min.resize(2);
425 max.resize(2);
426
427 min(0) = min_corner.x;
428 min(1) = min_corner.y;
429
430 max(0) = max_corner.x;
431 max(1) = max_corner.y;
432 }
433
435 {
436
437 GEO::vec3 min_corner, max_corner;
438 GEO::get_bbox(mesh_, &min_corner[0], &max_corner[0]);
439 GEO::vec3 extent = max_corner - min_corner;
440 double scaling = std::max(extent[0], std::max(extent[1], extent[2]));
441 // const GEO::vec3 origin = 0.5 * (min_corner + max_corner);
442 const GEO::vec3 origin = min_corner;
443 for (GEO::index_t v = 0; v < mesh_.vertices.nb(); ++v)
444 {
445 mesh_.vertices.point(v) = (mesh_.vertices.point(v) - origin) / scaling;
446 }
447 Eigen::RowVector2d shift;
448 shift << origin[0], origin[1];
449 for (auto &n : edge_nodes_)
450 {
451 if (n.nodes.size() > 0)
452 n.nodes = (n.nodes.rowwise() - shift) / scaling;
453 }
454 for (auto &n : face_nodes_)
455 {
456 if (n.nodes.size() > 0)
457 n.nodes = (n.nodes.rowwise() - shift) / scaling;
458 }
459 Eigen::Vector2d normalization_translation;
460 normalization_translation << -origin[0] / scaling, -origin[1] / scaling;
462 Eigen::Matrix2d::Identity() / scaling,
463 normalization_translation);
464
465 logger().debug("-- bbox before normalization:");
466 logger().debug(" min : {} {}", min_corner[0], min_corner[1]);
467 logger().debug(" max : {} {}", max_corner[0], max_corner[1]);
468 logger().debug(" extent: {} {}", max_corner[0] - min_corner[0], max_corner[1] - min_corner[1]);
469 GEO::get_bbox(mesh_, &min_corner[0], &max_corner[0]);
470 logger().debug("-- bbox after normalization:");
471 logger().debug(" min : {} {}", min_corner[0], min_corner[1]);
472 logger().debug(" max : {} {}", max_corner[0], max_corner[1]);
473 logger().debug(" extent: {} {}", max_corner[0] - min_corner[0], max_corner[1] - min_corner[1]);
474
475 Eigen::MatrixXd p0, p1, p;
476 get_edges(p0, p1);
477 p = p0 - p1;
478 logger().debug("-- edge length after normalization:");
479 logger().debug(" min: {}", p.rowwise().norm().minCoeff());
480 logger().debug(" max: {}", p.rowwise().norm().maxCoeff());
481 logger().debug(" avg: {}", p.rowwise().norm().mean());
482 }
483
484 double CMesh2D::edge_length(const int gid) const
485 {
486 const int v0 = mesh_.edges.vertex(gid, 0);
487 const int v1 = mesh_.edges.vertex(gid, 1);
488
489 return (point(v0) - point(v1)).norm();
490 }
491
492 void CMesh2D::set_point(const int global_index, const RowVectorNd &p)
493 {
494 mesh_.vertices.point(global_index).x = p(0);
495 mesh_.vertices.point(global_index).y = p(1);
496 }
497
498 RowVectorNd CMesh2D::point(const int global_index) const
499 {
500 const double *ptr = mesh_.vertices.point_ptr(global_index);
501 RowVectorNd p(2);
502 p(0) = ptr[0];
503 p(1) = ptr[1];
504 return p;
505 }
506
507 bool CMesh2D::is_boundary_element(const int element_global_id) const
508 {
509 auto index = get_index_from_face(element_global_id);
510
511 for (int i = 0; i < n_face_vertices(element_global_id); ++i)
512 {
513 if (is_boundary_edge(index.edge))
514 return true;
515
516 index = next_around_face(index);
517 }
518
519 return false;
520 }
521
522 // void CMesh2D::triangulate_faces(Eigen::MatrixXi &tris, Eigen::MatrixXd &pts, std::vector<int> &ranges) const
523 // {
524 // ranges.clear();
525
526 // std::vector<Eigen::MatrixXi> local_tris(mesh_.facets.nb());
527 // std::vector<Eigen::MatrixXd> local_pts(mesh_.facets.nb());
528
529 // int total_tris = 0;
530 // int total_pts = 0;
531
532 // ranges.push_back(0);
533
534 // for (GEO::index_t f = 0; f < mesh_.facets.nb(); ++f)
535 // {
536 // const int n_vertices = mesh_.facets.nb_vertices(f);
537
538 // Eigen::MatrixXd face_pts(n_vertices, 2);
539 // // Eigen::MatrixXi edges(n_vertices,2);
540 // local_tris[f].resize(n_vertices - 2, 3);
541
542 // for (int i = 0; i < n_vertices; ++i)
543 // {
544 // const int vertex = mesh_.facets.vertex(f, i);
545 // const double *pt = mesh_.vertices.point_ptr(vertex);
546 // face_pts(i, 0) = pt[0];
547 // face_pts(i, 1) = pt[1];
548
549 // // edges(i, 0) = i;
550 // // edges(i, 1) = (i+1) % n_vertices;
551 // }
552
553 // for (int i = 1; i < n_vertices - 1; ++i)
554 // {
555 // local_tris[f].row(i - 1) << 0, i, i + 1;
556 // }
557
558 // local_pts[f] = face_pts;
559
560 // total_tris += local_tris[f].rows();
561 // total_pts += local_pts[f].rows();
562
563 // ranges.push_back(total_tris);
564
565 // assert(local_pts[f].rows() == face_pts.rows());
566 // }
567
568 // tris.resize(total_tris, 3);
569 // pts.resize(total_pts, 2);
570
571 // int tri_index = 0;
572 // int pts_index = 0;
573 // for (std::size_t i = 0; i < local_tris.size(); ++i)
574 // {
575 // tris.block(tri_index, 0, local_tris[i].rows(), local_tris[i].cols()) = local_tris[i].array() + pts_index;
576 // tri_index += local_tris[i].rows();
577
578 // pts.block(pts_index, 0, local_pts[i].rows(), local_pts[i].cols()) = local_pts[i];
579 // pts_index += local_pts[i].rows();
580 // }
581 // }
582
588
593
595 {
596 const int v0 = mesh_.edges.vertex(index, 0);
597 const int v1 = mesh_.edges.vertex(index, 1);
598
599 return 0.5 * (point(v0) + point(v1));
600 }
601
602 void CMesh2D::compute_body_ids(const std::function<int(const size_t, const std::vector<int> &, const RowVectorNd &)> &marker)
603 {
604 body_ids_.resize(n_elements());
605 std::fill(body_ids_.begin(), body_ids_.end(), -1);
606
607 for (int e = 0; e < n_elements(); ++e)
608 {
609 const auto bary = face_barycenter(e);
610 body_ids_[e] = marker(e, element_vertices(e), bary);
611 }
612 }
613
614 void CMesh2D::compute_boundary_ids(const std::function<int(const size_t, const std::vector<int> &, const RowVectorNd &, bool)> &marker)
615 {
616 boundary_ids_.resize(n_edges());
617
618 for (int e = 0; e < n_edges(); ++e)
619 {
620 bool is_boundary = is_boundary_edge(e);
621 const auto p = edge_barycenter(e);
622 std::vector<int> vs = {edge_vertex(e, 0), edge_vertex(e, 1)};
623 std::sort(vs.begin(), vs.end());
624 boundary_ids_[e] = marker(e, vs, p, is_boundary);
625 }
626 }
627
628 void CMesh2D::append(const Mesh &mesh)
629 {
630 assert(typeid(mesh) == typeid(CMesh2D));
631 Mesh::append(mesh);
632
633 const CMesh2D &mesh2d = dynamic_cast<const CMesh2D &>(mesh);
634
635 const int n_v = n_vertices();
636 const int n_f = n_faces();
637
638 mesh_.vertices.create_vertices(mesh2d.n_vertices());
639 for (int i = n_v; i < (int)mesh_.vertices.nb(); ++i)
640 {
641 GEO::vec3 &p = mesh_.vertices.point(i);
642 set_point(i, mesh2d.point(i - n_v));
643 }
644
645 std::vector<GEO::index_t> indices;
646 for (int i = 0; i < mesh2d.n_faces(); ++i)
647 {
648 indices.clear();
649 for (int j = 0; j < mesh2d.mesh_.facets.nb_vertices(i); ++j)
650 indices.push_back(mesh2d.mesh_.facets.vertex(i, j) + n_v);
651
652 mesh_.facets.create_polygon(indices.size(), &indices[0]);
653 }
654
655 assert(n_vertices() == n_v + mesh2d.n_vertices());
656 assert(n_faces() == n_f + mesh2d.n_faces());
657
658 c2e_.reset();
659 boundary_vertices_.reset();
660 boundary_edges_.reset();
662 c2e_ = std::make_unique<GEO::Attribute<GEO::index_t>>(mesh_.facet_corners.attributes(), "edge_id");
663 boundary_vertices_ = std::make_unique<GEO::Attribute<bool>>(mesh_.vertices.attributes(), "boundary_vertex");
664 boundary_edges_ = std::make_unique<GEO::Attribute<bool>>(mesh_.edges.attributes(), "boundary_edge");
665 }
666
667 std::unique_ptr<Mesh> CMesh2D::copy() const
668 {
669 Eigen::MatrixXd vertices(n_vertices(), 2);
670 int max_face_size = 0;
671 for (int i = 0; i < n_vertices(); ++i)
672 vertices.row(i) = point(i);
673 for (int i = 0; i < n_faces(); ++i)
674 max_face_size = std::max(max_face_size, n_face_vertices(i));
675
676 Eigen::MatrixXi faces = Eigen::MatrixXi::Constant(n_faces(), max_face_size, -1);
677 for (int i = 0; i < n_faces(); ++i)
678 for (int j = 0; j < n_face_vertices(i); ++j)
679 faces(i, j) = face_vertex(i, j);
680
681 std::unique_ptr<CMesh2D> copy_mesh = std::make_unique<CMesh2D>();
682 copy_mesh->build_topology(MeshData(std::move(vertices), std::move(faces)));
683
684 // Manually copy parent's data
685 copy_mesh->elements_tag_ = this->elements_tag_;
686 copy_mesh->node_ids_ = this->node_ids_;
687 copy_mesh->boundary_ids_ = this->boundary_ids_;
688 copy_mesh->body_ids_ = this->body_ids_;
689 copy_mesh->geometry_ids_ = this->geometry_ids_;
690 copy_mesh->orders_ = this->orders_;
691 copy_mesh->is_rational_ = this->is_rational_;
692 copy_mesh->edge_nodes_ = this->edge_nodes_;
693 copy_mesh->face_nodes_ = this->face_nodes_;
694 copy_mesh->cell_nodes_ = this->cell_nodes_;
695 copy_mesh->cell_weights_ = this->cell_weights_;
696 copy_mesh->has_explicit_polyhedral_topology_ = this->has_explicit_polyhedral_topology_;
697 copy_mesh->higher_order_nodes_ = this->higher_order_nodes_;
698 copy_mesh->higher_order_connectivity_ = this->higher_order_connectivity_;
699 copy_mesh->in_ordered_vertices_ = this->in_ordered_vertices_;
700 copy_mesh->in_ordered_edges_ = this->in_ordered_edges_;
701 copy_mesh->in_ordered_faces_ = this->in_ordered_faces_;
702
703 return copy_mesh;
704 }
705 } // namespace mesh
706} // namespace polyfem
int V
Eigen::RowVectorXd point
virtual RowVectorNd edge_barycenter(const int index) const override
edge barycenter
Definition CMesh2D.cpp:594
Navigation::Index switch_edge(Navigation::Index idx) const override
Definition CMesh2D.hpp:85
void normalize() override
normalize the mesh
Definition CMesh2D.cpp:434
void compute_elements_tag() override
compute element types, see ElementType
Definition CMesh2D.cpp:583
int n_faces() const override
number of faces
Definition CMesh2D.hpp:33
int n_face_vertices(const int f_id) const override
number of vertices of a face
Definition CMesh2D.hpp:37
int n_vertices() const override
number of vertices
Definition CMesh2D.hpp:35
int n_edges() const override
number of edges
Definition CMesh2D.hpp:34
bool is_boundary_element(const int element_global_id) const override
is cell boundary
Definition CMesh2D.cpp:507
double edge_length(const int gid) const override
edge length
Definition CMesh2D.cpp:484
std::unique_ptr< GEO::Attribute< bool > > boundary_edges_
Definition CMesh2D.hpp:101
std::pair< RowVectorNd, int > edge_node(const Navigation::Index &index, const int n_new_nodes, const int i) const override
Definition CMesh2D.cpp:354
std::unique_ptr< Mesh > copy() const override
Create a copy of the mesh.
Definition CMesh2D.cpp:667
Navigation::Index switch_vertex(Navigation::Index idx) const override
Definition CMesh2D.hpp:84
int face_vertex(const int f_id, const int lv_id) const override
id of the face vertex
Definition CMesh2D.hpp:39
void compute_boundary_ids(const std::function< int(const size_t, const std::vector< int > &, const RowVectorNd &, bool)> &marker) override
computes boundary selections based on a function
Definition CMesh2D.cpp:614
void set_point(const int global_index, const RowVectorNd &p) override
Set the point.
Definition CMesh2D.cpp:492
bool build_topology(const MeshData &data) override
Construct only the dimension-specific topology.
Definition CMesh2D.cpp:170
bool is_boundary_edge(const int edge_global_id) const override
is edge boundary
Definition CMesh2D.hpp:48
std::unique_ptr< GEO::Attribute< GEO::index_t > > c2e_
Definition CMesh2D.hpp:99
std::unique_ptr< GEO::Attribute< bool > > boundary_vertices_
Definition CMesh2D.hpp:100
std::pair< RowVectorNd, int > face_node(const Navigation::Index &index, const int n_new_nodes, const int i, const int j) const override
Definition CMesh2D.cpp:376
void append(const Mesh &mesh) override
appends a new mesh to the end of this
Definition CMesh2D.cpp:628
int edge_vertex(const int e_id, const int lv_id) const override
id of the edge vertex
Definition CMesh2D.hpp:40
Navigation::Index get_index_from_face(int f, int lv=0) const override
Definition CMesh2D.hpp:81
virtual void bounding_box(RowVectorNd &min, RowVectorNd &max) const override
computes the bbox of the mesh
Definition CMesh2D.cpp:420
void remove_elements(const std::vector< bool > &keep) override
Remove all top-dimensional elements whose mask entry is false.
Definition CMesh2D.cpp:25
void attach_higher_order_nodes(const Eigen::MatrixXd &V, const std::vector< std::vector< int > > &nodes) override
attach high order nodes
Definition CMesh2D.cpp:213
void refine(const int n_refinement, const double t) override
refine the mesh
Definition CMesh2D.cpp:98
void compute_body_ids(const std::function< int(const size_t, const std::vector< int > &, const RowVectorNd &)> &marker) override
computes boundary selections based on a function
Definition CMesh2D.cpp:602
virtual RowVectorNd point(const int global_index) const override
point coordinates
Definition CMesh2D.cpp:498
virtual void update_elements_tag() override
Update elements types.
Definition CMesh2D.cpp:589
RowVectorNd face_barycenter(const int index) const override
face barycenter
Definition Mesh2D.cpp:69
Navigation::Index next_around_face(Navigation::Index idx) const
Definition Mesh2D.hpp:61
void get_edges(Eigen::MatrixXd &p0, Eigen::MatrixXd &p1) const override
Get all the edges.
Definition Mesh2D.cpp:21
Class to store the high-order edge nodes.
Definition Mesh.hpp:54
Format-independent input used to construct a runtime Mesh.
Definition MeshData.hpp:12
Eigen::MatrixXd vertices
Definition MeshData.hpp:21
Eigen::MatrixXi elements
Definition MeshData.hpp:22
Abstract mesh class to capture 2d/3d conforming and non-conforming meshes.
Definition Mesh.hpp:50
int n_elements() const
utitlity to return the number of elements, cells or faces in 3d and 2d
Definition Mesh.hpp:148
Eigen::MatrixXi orders_
list of geometry orders, one per cell
Definition Mesh.hpp:696
std::vector< ElementType > elements_tag_
list of element types
Definition Mesh.hpp:686
bool is_rational_
stores if the mesh is rational
Definition Mesh.hpp:698
bool has_boundary_ids() const
checks if surface selections are available
Definition Mesh.hpp:528
std::vector< std::vector< int > > higher_order_connectivity_
Definition Mesh.hpp:715
bool is_cube(const int el_id) const
checks if element is cube compatible
Definition Mesh.cpp:327
Eigen::MatrixXi in_ordered_faces_
Order of the input faces, TODO: change to std::vector of Eigen::Vector.
Definition Mesh.hpp:722
bool is_simplex(const int el_id) const
checks if element is simplex
Definition Mesh.cpp:374
std::vector< int > geometry_ids_
list of geometry labels, one per top-dimensional element
Definition Mesh.hpp:694
std::vector< int > boundary_ids_
list of surface labels
Definition Mesh.hpp:690
void clear_higher_order_data()
Definition Mesh.cpp:685
std::vector< int > node_ids_
list of node labels
Definition Mesh.hpp:688
std::vector< CellNodes > cell_nodes_
high-order nodes associates to cells
Definition Mesh.hpp:705
std::vector< std::vector< double > > cell_weights_
weights associates to cells for rational polynomail meshes
Definition Mesh.hpp:707
Eigen::MatrixXd higher_order_nodes_
Canonical connectivity is retained because the runtime edge/face caches do not preserve the original ...
Definition Mesh.hpp:714
std::vector< int > element_vertices(const int el_id) const
list of vids of an element
Definition Mesh.hpp:216
std::vector< int > body_ids_
list of volume labels
Definition Mesh.hpp:692
virtual int get_default_boundary_id(const int primitive) const
Get the default boundary selection of an element (face in 3d, edge in 2d)
Definition Mesh.hpp:454
void transform_higher_order_data(const MatrixNd &A, const VectorNd &b)
Definition Mesh.cpp:693
std::vector< FaceNodes > face_nodes_
high-order nodes associates to faces
Definition Mesh.hpp:703
std::vector< EdgeNodes > edge_nodes_
high-order nodes associates to edges
Definition Mesh.hpp:701
std::vector< std::vector< int > > faces() const
list of sorted faces.
Definition Mesh.cpp:405
void filter_element_data(const std::vector< bool > &keep)
Definition Mesh.cpp:46
Eigen::MatrixXi in_ordered_edges_
Order of the input edges.
Definition Mesh.hpp:720
virtual void append(const Mesh &mesh)
appends a new mesh to the end of this
Definition Mesh.cpp:456
bool has_explicit_polyhedral_topology_
Whether the source MeshData supplied explicit face/cell incidence.
Definition Mesh.hpp:711
Eigen::VectorXi in_ordered_vertices_
Order of the input vertices.
Definition Mesh.hpp:718
void prepare_mesh(GEO::Mesh &M)
SplitFunction catmul_clark_split_func()
SplitFunction polar_split_func(double t)
Helper function.
void refine_triangle_mesh(const GEO::Mesh &M_in, GEO::Mesh &M_out)
Refine a triangle mesh.
void orient_normals_2d(GEO::Mesh &M)
Orient facets of a 2D mesh so that each connected component has positive volume.
void generate_edges(GEO::Mesh &M)
assing edges to M
void refine_polygonal_mesh(const GEO::Mesh &M_in, GEO::Mesh &M_out, Polygons::SplitFunction split_func)
Refine a polygonal mesh.
void compute_element_tags(const GEO::Mesh &M, std::vector< ElementType > &element_tags)
Compute the type of each facet in a surface mesh.
Definition MeshUtils.cpp:94
spdlog::logger & logger()
Retrieves the current logger.
Definition Logger.cpp:44
Eigen::Matrix< double, 1, Eigen::Dynamic, Eigen::RowMajor, 1, 3 > RowVectorNd
Definition Types.hpp:13