7#include <igl/writeMESH.h>
9#include <geogram/mesh/mesh_io.h>
20 assert(keep.size() ==
n_cells());
22 std::vector<int> old_node_ids(
vertices.size(), -1);
26 std::vector<int> old_boundary_ids(
faces.size(), -1);
28 for (
int f = 0; f <
n_faces(); ++f)
31 for (
int e = 0; e < keep.size(); ++e)
37 element.is_ghost =
true;
38 for (
const int face : element.faces)
39 faces[face].remove_element(full_id);
40 for (
const int edge : element.edges)
41 edges[edge].remove_element(full_id);
42 for (
const int vertex : element.vertices)
43 vertices[vertex].remove_element(full_id);
58 for (
int f = 0; f <
n_faces(); ++f)
77 if (n_refinement <= 0)
80 std::vector<bool> refine_mask(
elements.size(),
false);
81 for (
int i = 0; i <
elements.size(); i++)
83 refine_mask[i] =
true;
85 for (
int i = 0; i < refine_mask.size(); i++)
89 refine(n_refinement - 1, t);
95 for (
int lv = 0; lv <
n_cell_edges(element_global_id); lv++)
106 const Eigen::MatrixXd &
V = data.
vertices;
107 const Eigen::MatrixXi &
F = data.
elements;
108 if (
F.cols() != 4 ||
F.minCoeff() < 0)
122 for (
int i = 0; i <
V.rows(); i++)
126 for (
int i = 0; i <
F.rows(); i++)
138 for (
int f = 0; f <
n_cells(); ++f)
139 if (nodes[f].size() != 4)
140 throw std::runtime_error(
"NCMesh doesn't support high order mesh!");
148 auto extent = max - min;
149 double scale = extent.maxCoeff();
152 v.pos = (v.pos - min.transpose()) / scale;
212 for (
int d = 0; d < 3; d++)
214 if (v.pos[d] > max[d])
216 if (v.pos[d] < min[d])
227 for (
int f = 0; f <
n_faces(); ++f)
233 for (
int vid = 0; vid < vs.size(); ++vid)
236 std::sort(vs.begin(), vs.end());
248 for (
int e = 0; e <
n_cells(); ++e)
257 assert(boundary_ids.size() ==
n_faces());
259 for (
int i = 0; i < boundary_ids.size(); i++)
266 assert(body_ids.size() ==
n_cells());
268 for (
int i = 0; i < body_ids.size(); i++)
389 idx.element_patch = lf;
394 idx.face_corner = lv;
395 idx.vertex =
face_vertex(idx.face, idx.face_corner);
397 idx.edge =
face_edge(idx.face, idx.face_corner);
406 idx.element_patch = 0;
409 idx.vertex =
face_vertex(idx.face, idx.face_corner);
423 for (
int i = 0; i < 4; i++)
425 const int f_id =
cell_face(idx.element, i);
426 for (
int j = 0; j < 3; j++)
429 if (idx.edge == e_id)
431 idx.element_patch = i;
460 int v0_ = v0, v1_ = v1;
466 for (
int i = 0; i < 4; i++)
468 const int fid =
cell_face(idx.element, i);
472 idx.element_patch = i;
474 for (
int j = 0; j < 3; j++)
480 if ((ev0 == v0_ && ev1 == v1_) || (ev0 == v1_ && ev1 == v0_))
498 std::vector<uint32_t> hs;
506 std::vector<uint32_t> hs;
528 if (idx.edge ==
face_edge(idx.face, idx.face_corner))
529 idx.edge =
face_edge(idx.face, (idx.face_corner + 2) % 3);
531 idx.edge =
face_edge(idx.face, idx.face_corner);
536 for (
int i = 0; i < 4; i++)
538 const int fid =
cell_face(idx.element, i);
544 idx.element_patch = i;
558 if (face.n_elem() != 2)
569 if (
cell_face(idx.element, f) == idx.face)
570 idx.element_patch = f;
605 if (
elements[id_full].is_not_valid())
606 throw std::runtime_error(
"Cannot refine an invalid element!");
608 const auto v =
elements[id_full].vertices;
609 elements[id_full].is_refined =
true;
612 for (
int f = 0; f <
elements[id_full].faces.size(); f++)
615 for (
int e = 0; e <
elements[id_full].edges.size(); e++)
618 for (
int i = 0; i < v.size(); i++)
619 vertices[v(i)].remove_element(id_full);
621 if (
elements[id_full].children(0) >= 0)
623 for (
int c = 0; c <
elements[id_full].children.size(); c++)
625 const int child_id =
elements[id_full].children(c);
627 elem.is_ghost =
false;
630 for (
int f = 0; f < elem.faces.size(); f++)
631 faces[elem.faces(f)].add_element(child_id);
633 for (
int e = 0; e < elem.edges.size(); e++)
634 edges[elem.edges(e)].add_element(child_id);
636 for (
int v = 0; v < elem.vertices.size(); v++)
637 vertices[elem.vertices(v)].add_element(child_id);
647 const int v5 =
get_vertex(Eigen::Vector2i(v1, v2));
648 const int v8 =
get_vertex(Eigen::Vector2i(v3, v2));
649 const int v6 =
get_vertex(Eigen::Vector2i(v1, v3));
650 const int v7 =
get_vertex(Eigen::Vector2i(v1, v4));
651 const int v9 =
get_vertex(Eigen::Vector2i(v4, v2));
652 const int v10 =
get_vertex(Eigen::Vector2i(v3, v4));
655 for (
int i = 0; i < v.size(); i++)
656 for (
int j = 0; j < i; j++)
666 for (
int i = 0; i < v.size(); i++)
667 for (
int j = 0; j < i; j++)
668 for (
int k = 0; k < j; k++)
674 int facei =
get_face(v[i], vij, vik);
675 int facej =
get_face(v[j], vjk, vij);
676 int facek =
get_face(v[k], vjk, vik);
677 int facem =
get_face(vij, vjk, vik);
678 faces[facei].boundary_id =
faces[fid].boundary_id;
679 faces[facej].boundary_id =
faces[fid].boundary_id;
680 faces[facek].boundary_id =
faces[fid].boundary_id;
681 faces[facem].boundary_id =
faces[fid].boundary_id;
686 add_element(Eigen::Vector4i(v1, v5, v6, v7), id_full);
688 add_element(Eigen::Vector4i(v5, v2, v8, v9), id_full);
690 add_element(Eigen::Vector4i(v6, v8, v3, v10), id_full);
692 add_element(Eigen::Vector4i(v7, v9, v10, v4), id_full);
694 add_element(Eigen::Vector4i(v5, v6, v7, v9), id_full);
696 add_element(Eigen::Vector4i(v5, v9, v8, v6), id_full);
698 add_element(Eigen::Vector4i(v6, v7, v9, v10), id_full);
700 add_element(Eigen::Vector4i(v6, v10, v9, v8), id_full);
707 std::vector<int> full_ids(ids.size());
708 for (
int i = 0; i < ids.size(); i++)
711 for (
int i : full_ids)
717 const int parent_id =
elements[id_full].parent;
720 for (
int i = 0; i < parent.children.size(); i++)
721 if (
elements[parent.children(i)].is_not_valid())
722 throw std::runtime_error(
"Invalid siblings in coarsening!");
725 for (
int c = 0; c < parent.children.size(); c++)
727 auto &elem =
elements[parent.children(c)];
728 elem.is_ghost =
true;
731 for (
int f = 0; f < elem.faces.size(); f++)
732 faces[elem.faces(f)].remove_element(parent.children(c));
734 for (
int e = 0; e < elem.edges.size(); e++)
735 edges[elem.edges(e)].remove_element(parent.children(c));
737 for (
int v = 0; v < elem.vertices.size(); v++)
738 vertices[elem.vertices(v)].remove_element(parent.children(c));
742 parent.is_refined =
false;
745 for (
int f = 0; f < parent.faces.size(); f++)
746 faces[parent.faces(f)].add_element(parent_id);
748 for (
int e = 0; e < parent.edges.size(); e++)
749 edges[parent.edges(e)].add_element(parent_id);
751 for (
int v = 0; v < parent.vertices.size(); v++)
752 vertices[parent.vertices(v)].add_element(parent_id);
759 for (
auto &face :
faces)
761 if (face.n_elem() == 1)
762 face.isboundary =
true;
764 face.isboundary =
false;
767 for (
auto &face :
faces)
769 if (face.leader >= 0 && face.n_elem() > 0 &&
faces[face.leader].n_elem() > 0)
771 face.isboundary =
false;
772 faces[face.leader].isboundary =
false;
777 vert.isboundary =
false;
779 for (
auto &edge :
edges)
780 edge.isboundary =
false;
782 for (
auto &face :
faces)
784 if (face.isboundary && face.n_elem())
786 for (
int j = 0; j < 3; j++)
787 vertices[face.vertices(j)].isboundary =
true;
789 for (
int j = 0; j < 3; j++)
790 for (
int i = 0; i < j; i++)
791 edges[
find_edge(face.vertices(i), face.vertices(j))].isboundary =
true;
801 for (
int i = 0, e = 0; i <
elements.size(); i++)
815 for (
int i = 0, j = 0; i <
vertices.size(); i++)
827 for (
int i = 0, j = 0; i <
edges.size(); i++)
829 if (
edges[i].n_elem() == 0)
839 for (
int i = 0, j = 0; i <
faces.size(); i++)
841 if (
faces[i].n_elem() == 0)
852 assert(
typeid(mesh) ==
typeid(
NCMesh3D));
865 for (
int i = 0; i < mesh3d.
n_cells(); i++)
867 Eigen::Vector4i cell = mesh3d.
elements[i].vertices;
868 cell = cell.array() + n_v;
877 return std::make_unique<NCMesh3D>(*
this);
882 std::sort(v.data(), v.data() + v.size());
885 return search->second;
891 std::sort(v.data(), v.data() + v.size());
904 std::sort(v.data(), v.data() + v.size());
907 return search->second;
913 std::sort(v.data(), v.data() + v.size());
917 edges.emplace_back(v);
918 id =
edges.size() - 1;
925 std::sort(v.data(), v.data() + v.size());
928 return search->second;
934 std::sort(v.data(), v.data() + v.size());
938 faces.emplace_back(v);
939 id =
faces.size() - 1;
947 std::vector<follower_edge> list1, list2;
950 double p_mid = (p1 + p2) / 2;
951 traverse_edge(Eigen::Vector2i(v[0], v_mid), p1, p_mid, depth + 1, list1);
954 std::make_move_iterator(list1.begin()),
955 std::make_move_iterator(list1.end()));
956 traverse_edge(Eigen::Vector2i(v_mid, v[1]), p_mid, p2, depth + 1, list2);
959 std::make_move_iterator(list2.begin()),
960 std::make_move_iterator(list2.end()));
965 if (follower_id >= 0 &&
edges[follower_id].n_elem() > 0)
966 list.emplace_back(follower_id, p1, p2);
971 for (
auto &edge :
edges)
974 edge.followers.clear();
975 edge.weights.setConstant(-1);
978 for (
int e_id = 0; e_id <
edges.size(); e_id++)
980 auto &edge =
edges[e_id];
981 if (edge.n_elem() == 0)
983 std::vector<follower_edge> followers;
985 for (
auto &s : followers)
987 if (
edges[s.id].leader >= 0 && std::abs(
edges[s.id].weights(1) -
edges[s.id].weights(0)) < std::abs(s.p2 - s.p1))
989 edge.followers.push_back(s.id);
990 edges[s.id].leader = e_id;
991 edges[s.id].weights << s.p1, s.p2;
996 for (
auto &edge :
edges)
997 if (edge.leader >= 0 && edge.followers.size())
998 edge.followers.clear();
1000 void NCMesh3D::traverse_face(
int v1,
int v2,
int v3, Eigen::Vector2d p1, Eigen::Vector2d p2, Eigen::Vector2d p3,
int depth, std::vector<follower_face> &face_list, std::vector<int> &edge_list)
const
1005 std::vector<follower_face> list1, list2, list3, list4;
1006 std::vector<int> list1_, list2_, list3_, list4_;
1013 if (v12 >= 0 && v23 >= 0 && v31 >= 0)
1015 auto p12 = (p1 + p2) / 2, p23 = (p2 + p3) / 2, p31 = (p1 + p3) / 2;
1016 traverse_face(v1, v12, v31, p1, p12, p31, depth + 1, list1, list1_);
1017 traverse_face(v12, v2, v23, p12, p2, p23, depth + 1, list2, list2_);
1018 traverse_face(v31, v23, v3, p31, p23, p3, depth + 1, list3, list3_);
1019 traverse_face(v12, v23, v31, p12, p23, p31, depth + 1, list4, list4_);
1021 face_list.insert(face_list.end(), std::make_move_iterator(list1.begin()), std::make_move_iterator(list1.end()));
1022 face_list.insert(face_list.end(), std::make_move_iterator(list2.begin()), std::make_move_iterator(list2.end()));
1023 face_list.insert(face_list.end(), std::make_move_iterator(list3.begin()), std::make_move_iterator(list3.end()));
1024 face_list.insert(face_list.end(), std::make_move_iterator(list4.begin()), std::make_move_iterator(list4.end()));
1026 edge_list.insert(edge_list.end(), std::make_move_iterator(list1_.begin()), std::make_move_iterator(list1_.end()));
1027 edge_list.insert(edge_list.end(), std::make_move_iterator(list2_.begin()), std::make_move_iterator(list2_.end()));
1028 edge_list.insert(edge_list.end(), std::make_move_iterator(list3_.begin()), std::make_move_iterator(list3_.end()));
1029 edge_list.insert(edge_list.end(), std::make_move_iterator(list4_.begin()), std::make_move_iterator(list4_.end()));
1033 int follower_id =
find_face(Eigen::Vector3i(v1, v2, v3));
1034 if (follower_id >= 0 &&
faces[follower_id].n_elem() > 0)
1035 face_list.emplace_back(follower_id, p1, p2, p3);
1040 Eigen::Matrix<int, 4, 3> fv;
1041 fv.row(0) << 0, 1, 2;
1042 fv.row(1) << 0, 1, 3;
1043 fv.row(2) << 1, 2, 3;
1044 fv.row(3) << 2, 0, 3;
1046 for (
auto &face :
faces)
1049 face.followers.clear();
1052 for (
auto &edge :
edges)
1054 edge.leader_face = -1;
1057 for (
int f_id = 0; f_id <
faces.size(); f_id++)
1059 auto &face =
faces[f_id];
1060 if (face.n_elem() == 0)
1062 std::vector<follower_face> followers;
1063 std::vector<int> interior_edges;
1064 traverse_face(face.vertices(0), face.vertices(1), face.vertices(2), Eigen::Vector2d(0, 0), Eigen::Vector2d(1, 0), Eigen::Vector2d(0, 1), 0, followers, interior_edges);
1065 for (
auto &s : followers)
1067 faces[s.id].leader = f_id;
1068 face.followers.push_back(s.id);
1070 for (
int s : interior_edges)
1071 if (s >= 0 &&
edges[s].leader < 0 &&
edges[s].n_elem() > 0)
1072 edges[s].leader_face = f_id;
1083 for (
auto &small_edge :
edges)
1086 if (small_edge.n_elem() == 0)
1090 int large_edge = small_edge.leader;
1093 assert(
edges[large_edge].leader < 0);
1096 for (
int j = 0; j < 2; j++)
1098 const int v_id = small_edge.vertices(j);
1105 for (
auto &small_face :
faces)
1108 if (small_face.n_elem() == 0)
1112 int large_face = small_face.leader;
1117 for (
int j = 0; j < 3; j++)
1119 const int v_id = small_face.vertices(j);
1121 if (v_id !=
faces[large_face].
vertices(0) && v_id !=
faces[large_face].vertices(1) && v_id !=
faces[large_face].vertices(2))
1133 const int level = (parent < 0) ? 0 :
elements[parent].level + 1;
1138 if ((e1.cross(e2)).dot(e3) < 0)
1139 std::swap(v[2], v[3]);
1143 assert((e1.cross(e2)).dot(e3) > 0);
1145 elements.emplace_back(3, v, level, parent);
1151 const int face012 =
get_face(v[0], v[1], v[2]);
1152 const int face013 =
get_face(v[0], v[1], v[3]);
1153 const int face123 =
get_face(v[1], v[2], v[3]);
1154 const int face203 =
get_face(v[2], v[0], v[3]);
1156 faces[face012].add_element(
id);
1157 faces[face013].add_element(
id);
1158 faces[face123].add_element(
id);
1159 faces[face203].add_element(
id);
1161 elements[id].faces << face012, face013, face123, face203;
1164 const int edge01 =
get_edge(v[0], v[1]);
1165 const int edge12 =
get_edge(v[1], v[2]);
1166 const int edge20 =
get_edge(v[2], v[0]);
1167 const int edge03 =
get_edge(v[0], v[3]);
1168 const int edge13 =
get_edge(v[1], v[3]);
1169 const int edge23 =
get_edge(v[2], v[3]);
1171 edges[edge01].add_element(
id);
1172 edges[edge12].add_element(
id);
1173 edges[edge20].add_element(
id);
1174 edges[edge03].add_element(
id);
1175 edges[edge13].add_element(
id);
1176 edges[edge23].add_element(
id);
1178 elements[id].edges << edge01, edge12, edge20, edge03, edge13, edge23;
1182 for (
int i = 0; i < v.size(); i++)
Format-independent input used to construct a runtime Mesh.
bool has_polyhedral_topology() const
Abstract mesh class to capture 2d/3d conforming and non-conforming meshes.
std::vector< ElementType > elements_tag_
list of element types
bool has_boundary_ids() const
checks if surface selections are available
bool has_node_ids() const
checks if points selections are available
virtual void set_body_ids(const std::vector< int > &body_ids)
Set the volume sections.
std::vector< int > boundary_ids_
list of surface labels
void clear_higher_order_data()
std::vector< int > node_ids_
list of node labels
std::vector< int > element_vertices(const int el_id) const
list of vids of an element
std::vector< int > body_ids_
list of volume labels
virtual int get_default_boundary_id(const int primitive) const
Get the default boundary selection of an element (face in 3d, edge in 2d)
void filter_element_data(const std::vector< bool > &keep)
virtual void append(const Mesh &mesh)
appends a new mesh to the end of this
virtual void set_boundary_ids(const std::vector< int > &boundary_ids)
Set the boundary selection from a vector.
void remove_elements(const std::vector< bool > &keep) override
Remove all top-dimensional elements whose mask entry is false.
int find_vertex(Eigen::Vector2i v) const
bool is_boundary_element(const int element_global_id) const override
is cell boundary
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
std::vector< int > all_to_valid_elemMap
int n_faces() const override
number of faces
int valid_to_all_edge(const int id) const
Navigation3D::Index next_around_edge(Navigation3D::Index idx) const override
int face_edge(const int f_id, const int le_id) const
int n_cell_faces(const int c_id) const override
void traverse_edge(Eigen::Vector2i v, double p1, double p2, int depth, std::vector< follower_edge > &list) const
std::unordered_map< Eigen::Vector2i, int, ArrayHasher2D > midpointMap
int n_cells() const override
number of cells
void build_element_vertex_adjacency()
void prepare_mesh() override
method used to finalize the mesh.
std::vector< ncBoundary > edges
int valid_to_all_face(const int id) const
void bounding_box(RowVectorNd &min, RowVectorNd &max) const override
computes the bbox of the mesh
void append(const Mesh &mesh) override
appends a new mesh to the end of this
std::vector< int > refineHistory
double edge_length(const int gid) const override
edge length
int n_edges() const override
number of edges
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
int get_edge(Eigen::Vector2i v)
void set_point(const int global_index, const RowVectorNd &p) override
Set the point.
int add_element(Eigen::Vector4i v, int parent=-1)
int get_face(Eigen::Vector3i v)
void attach_higher_order_nodes(const Eigen::MatrixXd &V, const std::vector< std::vector< int > > &nodes) override
attach high order nodes
int n_face_vertices(const int f_id) const override
number of vertices of a face
RowVectorNd cell_barycenter(const int c) const override
cell barycenter
std::vector< uint32_t > edge_neighs(const int e_gid) const override
int all_to_valid_elem(const int id) const
int n_vertices() const override
number of vertices
std::vector< ncVert > vertices
Navigation3D::Index get_index_from_element_edge(int hi, int v0, int v1) const override
std::unordered_map< Eigen::Vector2i, int, ArrayHasher2D > edgeMap
void traverse_face(int v1, int v2, int v3, Eigen::Vector2d p1, Eigen::Vector2d p2, Eigen::Vector2d p3, int depth, std::vector< follower_face > &face_list, std::vector< int > &edge_list) const
void refine(const int n_refinement, const double t) override
refine the mesh
void normalize() override
normalize the mesh
std::vector< int > all_to_valid_vertexMap
int all_to_valid_edge(const int id) const
bool build_topology(const MeshData &data) override
Construct only the dimension-specific topology.
void get_face_elements_neighs(const int f_id, std::vector< int > &ids) const
std::unique_ptr< Mesh > copy() const override
Create a copy of the mesh.
int valid_to_all_elem(const int id) const
void refine_element(int id_full)
Navigation3D::Index switch_vertex(Navigation3D::Index idx) const override
RowVectorNd kernel(const int cell_id) const override
bool is_boundary_vertex(const int vertex_global_id) const override
is vertex boundary
int cell_face(const int c_id, const int lf_id) const override
void compute_elements_tag() override
compute element types, see ElementType
RowVectorNd point(const int global_index) const override
point coordinates
std::vector< int > all_to_valid_edgeMap
int find_edge(Eigen::Vector2i v) const
Navigation3D::Index get_index_from_element(int hi, int lf, int lv) const override
bool is_boundary_face(const int face_global_id) const override
is face boundary
int cell_vertex(const int f_id, const int lv_id) const override
id of the vertex of a cell
std::vector< int > all_to_valid_faceMap
void coarsen_element(int id_full)
Navigation3D::Index next_around_face(Navigation3D::Index idx) const override
std::vector< int > valid_to_all_elemMap
std::vector< int > valid_to_all_edgeMap
void build_face_follower_chain()
RowVectorNd face_barycenter(const int f) const override
face barycenter
void build_edge_follower_chain()
int n_cell_edges(const int c_id) const override
Navigation3D::Index switch_element(Navigation3D::Index idx) const override
void get_vertex_elements_neighs(const int v_id, std::vector< int > &ids) const override
std::vector< ncElem > elements
std::unordered_map< Eigen::Vector3i, int, ArrayHasher3D > faceMap
RowVectorNd edge_barycenter(const int e) const override
edge barycenter
std::vector< int > valid_to_all_faceMap
std::vector< uint32_t > vertex_neighs(const int v_gid) const override
std::vector< int > valid_to_all_vertexMap
std::array< int, 4 > get_ordered_vertices_from_tet(const int element_index) const override
void update_elements_tag() override
Update elements types.
int valid_to_all_vertex(const int id) const
int edge_vertex(const int e_id, const int lv_id) const override
id of the edge vertex
void refine_elements(const std::vector< int > &ids)
void build_index_mapping()
int get_vertex(Eigen::Vector2i v)
int find_face(Eigen::Vector3i v) const
void get_edge_elements_neighs(const int e_id, std::vector< int > &ids) const override
Navigation3D::Index switch_face(Navigation3D::Index idx) const override
int face_vertex(const int f_id, const int lv_id) const override
id of the face vertex
int all_to_valid_face(const int id) const
Navigation3D::Index get_index_from_element_face(int hi, int v0, int v1, int v2) const override
void set_body_ids(const std::vector< int > &body_ids) override
Set the volume sections.
void set_boundary_ids(const std::vector< int > &boundary_ids) override
Set the boundary selection from a vector.
std::vector< ncBoundary > faces
Navigation3D::Index switch_edge(Navigation3D::Index idx) const override
std::tuple< bool, int, Tree > is_valid(const int dim, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const Eigen::VectorXd &u, const double threshold, const unsigned max_iter)
Eigen::Matrix< double, 1, Eigen::Dynamic, Eigen::RowMajor, 1, 3 > RowVectorNd