7#include <igl/barycentric_coordinates.h>
9#include <geogram/mesh/mesh_io.h>
14 using namespace utils;
27 const Eigen::Vector3d e0 = (v2 - v1).transpose();
28 const Eigen::Vector3d e1 = (v3 - v1).transpose();
30 return e0.cross(e1).norm() / 2;
36 p1.resize(p0.rows(), p0.cols());
38 for (std::size_t e = 0; e <
n_edges(); ++e)
43 p0.row(e) =
point(v0);
44 p1.row(e) =
point(v1);
48 void Mesh3D::get_edges(Eigen::MatrixXd &p0, Eigen::MatrixXd &p1,
const std::vector<bool> &valid_elements)
const
51 for (
size_t i = 0; i < valid_elements.size(); ++i)
53 if (valid_elements[i])
64 for (
size_t i = 0; i < valid_elements.size(); ++i)
66 if (!valid_elements[i])
87 const double t = i / (n_new_nodes + 1.0);
89 return std::make_pair((1 - t) * v1 + t * v2, -1);
94 return std::make_pair(n.nodes.row(i - 1), n.nodes_ids[i - 1]);
96 return std::make_pair(n.nodes.row(n.nodes.rows() - i), n.nodes_ids[n.nodes_ids.size() - i]);
103 const int tmp = n_new_nodes == 2 ? 3 : n_new_nodes;
120 const double b2 = i / (n_new_nodes + 2.0);
121 const double b3 = j / (n_new_nodes + 2.0);
122 const double b1 = 1 - b3 - b2;
126 return std::make_pair(b1 * v1 + b2 * v2 + b3 * v3, -1);
129 const int ii = i - 1;
130 const int jj = j - 1;
134 int lindex = jj * n_new_nodes + ii;
138 static const std::array<int, 3> remapping = {{0, 2, 1}};
143 lindex = remapping[lindex];
151 else if (n.v2 == index.
vertex)
156 lindex = remapping[lindex];
164 lindex = (lindex + 1) % 3;
166 else if (n.v3 == index.
vertex)
171 lindex = remapping[lindex];
179 lindex = (lindex + 2) % 3;
187 return std::make_pair(n.nodes.row(lindex), n.nodes_ids[lindex]);
189 else if (is_prism_quad)
194 const int lindex = (j - 1) * n_new_nodes + (i - 1);
205 const double b1 = i / (n_new_nodesq + 1.0);
206 const double b2 = j / (n_new_nodes + 1.0);
211 return std::make_pair(v1 * (1 - b1) * (1 - b2) + v2 * b1 * (1 - b2) + v3 * b1 * b2 + v4 * (1 - b1) * b2, -1);
215 const double b1 = i / (n_new_nodes + 1.0);
216 const double b2 = j / (n_new_nodesq + 1.0);
221 return std::make_pair(v1 * (1 - b1) * (1 - b2) + v2 * b1 * (1 - b2) + v3 * b1 * b2 + v4 * (1 - b1) * b2, -1);
224 const double b1 = i / (n_new_nodes + 1.0);
225 const double b2 = j / (n_new_nodes + 1.0);
227 return std::make_pair(v1 * (1 - b1) * (1 - b2) + v2 * b1 * (1 - b2) + v3 * b1 * b2 + v4 * (1 - b1) * b2, -1);
238 const int tmp = n_new_nodes == 2 ? 3 : n_new_nodes;
251 const double b2 = i / (n_new_nodes + 2.0);
252 const double b3 = j / (n_new_nodes + 2.0);
253 const double b1 = 1 - b3 - b2;
257 return std::make_pair(b1 * v1 + b2 * v2 + b3 * v3, -1);
260 const int ii = i - 1;
261 const int jj = j - 1;
265 int lindex = jj * n_new_nodes + ii;
269 static const std::array<int, 3> remapping = {{0, 2, 1}};
274 lindex = remapping[lindex];
282 else if (n.v2 == index.
vertex)
287 lindex = remapping[lindex];
295 lindex = (lindex + 1) % 3;
297 else if (n.v3 == index.
vertex)
302 lindex = remapping[lindex];
310 lindex = (lindex + 2) % 3;
318 return std::make_pair(n.nodes.row(lindex), n.nodes_ids[lindex]);
330 const double b1 = i / (n_new_nodes + 1.0);
331 const double b2 = j / (n_new_nodes + 1.0);
333 return std::make_pair(v1 * (1 - b1) * (1 - b2) + v2 * b1 * (1 - b2) + v3 * b1 * b2 + v4 * (1 - b1) * b2, -1);
344 assert(n_new_nodes == 1);
346 assert(n.nodes.rows() == 1);
347 return std::make_pair(n.nodes, n.nodes_ids[0]);
350 if (n_new_nodes == 1)
355 if (n_new_nodes == 1)
364 const double w1 = double(i) / (n_new_nodes + 3);
365 const double w2 = double(j) / (n_new_nodes + 3);
366 const double w3 = double(k) / (n_new_nodes + 3);
367 const double w4 = 1 - w1 - w2 - w3;
374 return std::make_pair(w4 * v1 + w1 * v2 + w2 * v3 + w3 * v4, -1);
393 const double b1 = i / (n_new_nodes + 1.0);
394 const double b2 = j / (n_new_nodes + 1.0);
396 const double b3 = k / (n_new_nodes + 1.0);
398 RowVectorNd blin1 = v1 * (1 - b1) * (1 - b2) + v2 * b1 * (1 - b2) + v3 * b1 * b2 + v4 * (1 - b1) * b2;
399 RowVectorNd blin2 = v5 * (1 - b1) * (1 - b2) + v6 * b1 * (1 - b2) + v7 * b1 * b2 + v8 * (1 - b1) * b2;
401 return std::make_pair((1 - b3) * blin1 + b3 * blin2, -1);
406 const double n = n_new_nodes;
407 const double zv = 1.0 - k / n;
412 xv = 0.5 * (1.0 - zv);
413 yv = 0.5 * (1.0 - zv);
417 const double hk = 1.0 / (k + 1);
418 xv = i * hk * (1.0 - zv);
419 yv = j * hk * (1.0 - zv);
423 const auto v0 =
point(vids[0]);
424 const auto v1 =
point(vids[1]);
425 const auto v2 =
point(vids[2]);
426 const auto v3 =
point(vids[3]);
427 const auto v4 =
point(vids[4]);
432 const double one_minus_z = 1.0 -
z;
434 const double N0 = (one_minus_z * (one_minus_z -
x -
y) +
x *
y) / one_minus_z;
435 const double N1 =
x * (one_minus_z -
y) / one_minus_z;
436 const double N2 =
x *
y / one_minus_z;
437 const double N3 =
y * (one_minus_z -
x) / one_minus_z;
440 const RowVectorNd node = N0 * v0 + N1 * v1 + N2 * v2 + N3 * v3 + N4 * v4;
442 return std::make_pair(node, -1);
506 assert(
is_cube(element_index));
508 std::array<int, 8> v;
512 for (
int i = 0; i < 8; ++i)
513 v[i] = to_vertex[i](idx).vertex;
531 std::array<int, 4> v;
533 for (
int lv = 0; lv < 3; ++lv)
555 std::array<int, 6> v;
559 for (
int i = 0; i < 3; ++i)
562 if (idx.vertex != start.
vertex)
565 for (
int i = 0; i < 3; ++i)
570 assert(start.
vertex == v[0]);
573 for (
int i = 0; i < 3; ++i)
578 assert(start.
vertex == v[3]);
585 std::array<int, 5> v;
596 for (
int k = 0; k < 3; ++k)
611 for (
int lv = 0; lv < 4; ++lv)
629 auto &box = boxes[i];
630 box[0].setConstant(std::numeric_limits<double>::max());
631 box[1].setConstant(std::numeric_limits<double>::min());
636 for (
int d = 0; d < 3; ++d)
638 box[0][d] = std::min(box[0][d],
point(v_id)[d]);
639 box[1][d] = std::max(box[1][d],
point(v_id)[d]);
651 const auto A =
point(indices[0]);
652 const auto B =
point(indices[1]);
653 const auto C =
point(indices[2]);
654 const auto D =
point(indices[3]);
656 igl::barycentric_coordinates(p, A, B, C, D, coord);
665 const auto A =
point(indices[0]);
666 const auto B =
point(indices[1]);
667 const auto C =
point(indices[2]);
668 const auto D =
point(indices[3]);
670 Eigen::MatrixXd coords(4, 4);
671 coords << A, 1, B, 1, C, 1, D, 1;
672 coords.transposeInPlace();
674 jacobian = coords * reference_map;
676 assert(jacobian.determinant() > 0);
void to_vertex_functions(std::array< std::function< Navigation3D::Index(Navigation3D::Index)>, 8 > &to_vertex) const
virtual Navigation3D::Index get_index_from_element(int hi, int lf, int lv) const =0
double tri_area(const int gid) const override
area of a tri face of a tet mesh
void compute_cell_jacobian(const int el_id, const Eigen::MatrixXd &reference_map, Eigen::MatrixXd &jacobian) const
virtual int n_cell_edges(const int c_id) const =0
virtual int cell_edge(const int c_id, const int le_id) const =0
std::array< int, 5 > get_ordered_vertices_from_pyramid(const int element_index) const
void elements_boxes(std::vector< std::array< Eigen::Vector3d, 2 > > &boxes) const override
constructs a box around every element (3d cell, 2d face)
std::array< int, 8 > get_ordered_vertices_from_hex(const int element_index) const
std::pair< RowVectorNd, int > cell_node(const Navigation3D::Index &index, const int n_new_nodes, const int i, const int j, const int k) const
void get_edges(Eigen::MatrixXd &p0, Eigen::MatrixXd &p1) const override
Get all the edges.
virtual Navigation3D::Index switch_edge(Navigation3D::Index idx) const =0
void barycentric_coords(const RowVectorNd &p, const int el_id, Eigen::MatrixXd &coord) const override
constructs barycentric coodiantes for a point p.
std::pair< RowVectorNd, int > face_node(const Navigation3D::Index &index, const int n_new_nodes, const int i, const int j) const
std::pair< RowVectorNd, int > edge_node(const Navigation3D::Index &index, const int n_new_nodes, const int i) const
virtual std::array< int, 4 > get_ordered_vertices_from_tet(const int element_index) const
void to_edge_functions(std::array< std::function< Navigation3D::Index(Navigation3D::Index)>, 12 > &to_edge) const
std::array< int, 6 > get_ordered_vertices_from_prism(const int element_index) const
virtual Navigation3D::Index next_around_face(Navigation3D::Index idx) const =0
virtual Navigation3D::Index switch_face(Navigation3D::Index idx) const =0
void to_face_functions(std::array< std::function< Navigation3D::Index(Navigation3D::Index)>, 6 > &to_face) const
virtual Navigation3D::Index switch_vertex(Navigation3D::Index idx) const =0
int n_elements() const
utitlity to return the number of elements, cells or faces in 3d and 2d
virtual int n_vertices() const =0
number of vertices
Eigen::MatrixXi orders_
list of geometry orders, one per cell
bool is_cube(const int el_id) const
checks if element is cube compatible
bool is_simplex(const int el_id) const
checks if element is simplex
bool is_prism(const int el_id) const
checks if element is a prism
std::vector< CellNodes > cell_nodes_
high-order nodes associates to cells
virtual int edge_vertex(const int e_id, const int lv_id) const =0
id of the edge vertex
std::vector< FaceNodes > face_nodes_
high-order nodes associates to faces
std::vector< EdgeNodes > edge_nodes_
high-order nodes associates to edges
bool is_pyramid(const int el_id) const
checks if element is a pyramid
virtual RowVectorNd cell_barycenter(const int c) const =0
cell barycenter
virtual int n_edges() const =0
number of edges
virtual int cell_vertex(const int f_id, const int lv_id) const =0
id of the vertex of a cell
virtual int n_face_vertices(const int f_id) const =0
number of vertices of a face
virtual int n_cell_vertices(const int c_id) const =0
number of vertices of a cell
virtual int face_vertex(const int f_id, const int lv_id) const =0
id of the face vertex
Eigen::Matrix< double, 1, Eigen::Dynamic, Eigen::RowMajor, 1, 3 > RowVectorNd