6#include <wmtk/utils/TriQualityUtils.hpp>
8#include <igl/predicates/predicates.h>
16 const size_t num_vertices,
const Eigen::MatrixXi &triangles)
19 p_vertex_attrs = &vertex_attrs;
20 p_edge_attrs = &boundary_attrs;
21 p_face_attrs = &element_attrs;
24 std::vector<std::array<size_t, 3>> tri(triangles.rows());
25 for (
int i = 0; i < triangles.rows(); i++)
26 for (
int j = 0; j < triangles.cols(); j++)
27 tri[i][j] = (
size_t)triangles(i, j);
30 wmtk::TriMesh::create_mesh(num_vertices, tri);
34 WildTriRemesher::BoundaryMap<int> WildTriRemesher::boundary_ids()
const
36 const std::vector<Tuple> edges = get_edges();
37 EdgeMap<int> boundary_ids;
38 for (
const Tuple &edge : edges)
40 const size_t e0 = edge.vid(*
this);
41 const size_t e1 = edge.switch_vertex(*this).vid(*
this);
42 boundary_ids[{{e0, e1}}] = boundary_attrs[edge.eid(*
this)].boundary_id;
48 bool WildTriRemesher::is_rest_inverted(
const Tuple &loc)
const
51 const std::array<size_t, 3> vids = oriented_tri_vids(loc);
53 igl::predicates::exactinit();
56 const igl::predicates::Orientation orientation =
57 igl::predicates::orient2d(
58 vertex_attrs[vids[0]].rest_position,
59 vertex_attrs[vids[1]].rest_position,
60 vertex_attrs[vids[2]].rest_position);
63 return orientation != igl::predicates::Orientation::POSITIVE;
67 bool WildTriRemesher::is_inverted(
const Tuple &loc)
const
70 const std::array<size_t, 3> vids = oriented_tri_vids(loc);
72 igl::predicates::exactinit();
74 for (
int i = 0; i < n_quantities() / 3 + 2; ++i)
77 const igl::predicates::Orientation orientation =
78 igl::predicates::orient2d(
79 vertex_attrs[vids[0]].position_i(i),
80 vertex_attrs[vids[1]].position_i(i),
81 vertex_attrs[vids[2]].position_i(i));
84 if (orientation != igl::predicates::Orientation::POSITIVE)
92 double WildTriRemesher::element_volume(
const Tuple &e)
const
94 const std::array<size_t, 3> vids = oriented_tri_vids(e);
95 return utils::triangle_area_2D(
96 vertex_attrs[vids[0]].rest_position,
97 vertex_attrs[vids[1]].rest_position,
98 vertex_attrs[vids[2]].rest_position);
102 size_t WildTriRemesher::facet_id(
const Tuple &t)
const
108 size_t WildTriRemesher::element_id(
const Tuple &t)
const
114 Tuple WildTriRemesher::tuple_from_element(
size_t elem_id)
const
116 return tuple_from_tri(elem_id);
120 Tuple WildTriRemesher::tuple_from_facet(
size_t elem_id,
int local_facet_id)
const
122 return tuple_from_edge(elem_id, local_facet_id);
126 bool WildTriRemesher::is_boundary_edge(
const Tuple &e)
const
128 return TriMesh::is_boundary_edge(e);
132 bool WildTriRemesher::is_body_boundary_edge(
const Tuple &e)
const
134 const auto adj_face =
e.switch_face(*
this);
135 return !adj_face.has_value()
136 || element_attrs[element_id(e)].body_id
137 != element_attrs[element_id(*adj_face)].body_id;
141 bool WildTriRemesher::is_boundary_vertex(
const Tuple &v)
const
143 return TriMesh::is_boundary_vertex(v);
147 bool WildTriRemesher::is_body_boundary_vertex(
const Tuple &v)
const
149 for (
const auto &e : get_one_ring_edges_for_vertex(v))
150 if (is_body_boundary_edge(
e))
156 bool WildTriRemesher::is_boundary_facet(
const Tuple &t)
const
158 return is_boundary_edge(t);
162 bool WildTriRemesher::is_boundary_op()
const
164 return op_cache->is_boundary_op();
168 Eigen::MatrixXi WildTriRemesher::boundary_edges()
const
170 const std::vector<Tuple> boundary_edge_tuples = boundary_facets();
171 Eigen::MatrixXi BE(boundary_edge_tuples.size(), 2);
172 for (
int i = 0; i < BE.rows(); ++i)
174 BE(i, 0) = boundary_edge_tuples[i].vid(*
this);
175 BE(i, 1) = boundary_edge_tuples[i].switch_vertex(*this).vid(*
this);
177 if (obstacle().n_edges() > 0)
178 utils::append_rows(BE, obstacle().
e().array() + vert_capacity());
183 Eigen::MatrixXi WildTriRemesher::boundary_faces()
const
185 return Eigen::MatrixXi();
189 std::vector<Tuple> WildTriRemesher::get_facets()
const
195 std::vector<Tuple> WildTriRemesher::get_elements()
const
201 std::array<Tuple, 2> WildTriRemesher::facet_vertices(
const Tuple &t)
const
203 return {{t, t.switch_vertex(*
this)}};
207 std::array<size_t, 2> WildTriRemesher::facet_vids(
const Tuple &t)
const
209 return {{t.vid(*
this), t.switch_vertex(*this).vid(*
this)}};
213 std::array<Tuple, 3> WildTriRemesher::element_vertices(
const Tuple &t)
const
215 return oriented_tri_vertices(t);
219 std::array<size_t, 3> WildTriRemesher::element_vids(
const Tuple &t)
const
221 return oriented_tri_vids(t);
225 std::array<size_t, 3> WildTriRemesher::orient_preserve_element_reorder(
226 const std::array<size_t, 3> &conn,
const size_t v0)
const
228 return wmtk::orient_preserve_tri_reorder(conn, v0);
232 std::vector<Tuple> WildTriRemesher::get_one_ring_elements_for_vertex(
const Tuple &t)
const
234 return get_one_ring_tris_for_vertex(t);
238 std::vector<Tuple> WildTriRemesher::get_one_ring_boundary_edges_for_vertex(
const Tuple &v)
const
240 std::vector<Tuple> edges;
241 for (
const auto &e : get_one_ring_edges_for_vertex(v))
242 if (is_boundary_edge(
e))
248 std::vector<Tuple> WildTriRemesher::get_incident_elements_for_edge(
const Tuple &t)
const
250 std::vector<Tuple> tris{{t}};
251 if (t.switch_face(*
this))
252 tris.push_back(t.switch_face(*this).value());
257 CollapseEdgeTo WildTriRemesher::collapse_boundary_edge_to(
const Tuple &e)
const
259 const int eid =
e.eid(*
this);
260 const int v0i =
e.vid(*
this);
261 const int v1i =
e.switch_vertex(*this).vid(*
this);
263 const Eigen::Vector2d &v0 = vertex_attrs[v0i].rest_position;
264 const Eigen::Vector2d &v1 = vertex_attrs[v1i].rest_position;
266 const int boundary_id = boundary_attrs[eid].boundary_id;
268 const auto is_collinear = [&](
const Tuple &e0) {
269 const size_t e0_id = e0.eid(*
this);
270 const size_t v2_id = e0.vid(*
this);
271 const size_t v3_id = e0.switch_vertex(*this).vid(*
this);
273 && boundary_attrs[e0_id].boundary_id == boundary_id
274 && is_body_boundary_edge(e0)
275 && utils::are_edges_collinear(
276 v0, v1, vertex_attrs[v2_id].rest_position,
277 vertex_attrs[v3_id].rest_position);
280 const std::vector<Tuple> v0_edges = get_one_ring_edges_for_vertex(e);
281 const bool is_v0_collinear = std::any_of(v0_edges.begin(), v0_edges.end(), is_collinear);
283 const std::vector<Tuple> v1_edges = get_one_ring_edges_for_vertex(
e.switch_vertex(*
this));
284 const bool is_v1_collinear = std::any_of(v1_edges.begin(), v1_edges.end(), is_collinear);
286 if (!is_v0_collinear && !is_v1_collinear)
287 return CollapseEdgeTo::ILLEGAL;
288 else if (!is_v0_collinear)
289 return CollapseEdgeTo::V0;
290 else if (!is_v1_collinear)
291 return CollapseEdgeTo::V1;
293 return CollapseEdgeTo::MIDPOINT;
297 WildTriRemesher::EdgeAttributes &WildTriRemesher::edge_attr(
const size_t e_id)
299 return boundary_attrs[e_id];
303 const WildTriRemesher::EdgeAttributes &WildTriRemesher::edge_attr(
const size_t e_id)
const
305 return boundary_attrs[e_id];
void init_attributes_and_connectivity(const size_t num_vertices, const Eigen::MatrixXi &elements) override
Create an internal mesh representation and associate attributes.
typename WMTKMesh::Tuple Tuple
WildTetRemesher::Tuple Tuple