17 #include <igl/edges.h>
18 #include <igl/remove_duplicate_vertices.h>
29 return a[0] * b[1] - a[1] * b[0];
45 auto S_pab =
abs(
det(AP, AB)) / 2;
46 auto S_pbc =
abs(
det(BP, BC)) / 2;
47 auto S_pca =
abs(
det(CP, CA)) / 2;
48 auto S_abc =
abs(
det(AB, -CA)) / 2;
50 if (S_pab + S_pbc + S_pca != S_abc) {
55 if (S_pab * S_pbc * S_pca > 0) {
61 if (S_pbc * S_pca > 0) {
64 }
else if (S_pca == 0) {
74 if (S_pca * S_pab > 0) {
77 }
else if (S_pab == 0) {
87 if (S_pab * S_pbc > 0) {
90 }
else if (S_pbc == 0) {
111 Rational dd = e0[0] * e1[1] - e0[0] * s1[1] - e0[1] * e1[0] + e0[1] * s1[0] + e1[0] * s0[1] -
112 e1[1] * s0[0] + s0[0] * s1[1] - s0[1] * s1[0];
118 t0 = (e1[0] * s0[1] - e1[0] * s1[1] - e1[1] * s0[0] + e1[1] * s1[0] + s0[0] * s1[1] -
121 t1 = (e0[0] * s0[1] - e0[0] * s1[1] - e0[1] * s0[0] + e0[1] * s1[0] + s0[0] * s1[1] -
125 if (t0 < 0 || t0 > 1 || t1 < 0 || t1 > 1) {
129 res = (1 - t0) * s0 + t0 * e0;
131 const Vector2r p1 = (1 - t1) * s1 + t1 * e1;
133 assert(res[0] == p1[0] && res[1] == p1[1]);
140 if (point[0] >= bbox_min[0] && point[0] <= bbox_max[0] && point[1] >= bbox_min[1] &&
141 point[1] <= bbox_max[1]) {
153 if (bbox_min_0[0] > bbox_max_1[0] || bbox_max_0[0] < bbox_min_1[0]) {
156 if (bbox_min_0[1] > bbox_max_1[1] || bbox_max_0[1] < bbox_min_1[1]) {
162 std::array<wmtk::Vector2r, 2>
182 x_min = (x_min > p2[0]) ? p2[0] : x_min;
183 x_max = (x_max < p2[0]) ? p2[0] : x_max;
184 y_min = (y_min > p2[1]) ? p2[1] : y_min;
185 y_max = (y_max < p2[1]) ? p2[1] : y_max;
223 constexpr
static std::array<int, 4> __quadrants{{4, 1, 3, 2}};
225 size_t size = V.size();
227 std::vector<char> quadrants(size);
228 for (
size_t i = 0; i < size; ++i) {
231 int64_t sign_x, sign_y;
232 sign_x = (b[0] < 0) ? 1 : 0;
233 sign_y = (b[1] < 0) ? 1 : 0;
234 quadrants[i] = __quadrants[2 * sign_y + sign_x];
237 auto comp = [&](int64_t ai, int64_t bi) ->
bool {
238 const char qa = quadrants[ai];
239 const char qb = quadrants[bi];
243 return b[0] * a[1] > a[0] * b[1];
250 std::vector<int64_t> ordered_indices(size);
252 std::iota(ordered_indices.begin(), ordered_indices.end(), 0);
254 std::sort(ordered_indices.begin(), ordered_indices.end(), comp);
255 return ordered_indices;
261 std::vector<std::vector<std::tuple<int64_t, bool, bool>>>& VV,
262 std::vector<Vector2r>& V_pos,
263 std::vector<int64_t>& stack,
264 std::vector<int>& in_stack,
265 std::vector<int>& is_on_input,
266 std::vector<int>& is_used,
267 std::vector<std::vector<int64_t>>& in_stack_idx,
269 const int64_t v_prev,
270 std::vector<std::array<int64_t, 3>>& FV,
271 std::vector<std::array<int, 3>>& local_e_on_input)
273 if (in_stack[v] == 1) {
275 const int64_t begin_idx = in_stack_idx[v].back();
276 const int64_t end_idx = stack.size() - 1;
278 bool new_poly =
true;
279 for (int64_t i = begin_idx; i < end_idx; ++i) {
287 assert(end_idx - begin_idx >= 2);
290 for (int64_t i = begin_idx; i < end_idx; ++i) {
294 if (end_idx - begin_idx == 2) {
296 FV.push_back({{stack[begin_idx], stack[begin_idx + 1], stack[end_idx]}});
297 local_e_on_input.push_back(
298 {{is_on_input[begin_idx + 1], is_on_input[end_idx], is_on_input[begin_idx]}});
303 int64_t centroid_idx = V_pos.size();
304 for (int64_t i = begin_idx; i < end_idx + 1; ++i) {
305 centroid = centroid + V_pos[stack[i]];
306 int64_t next_stack_idx = (i == end_idx) ? begin_idx : i + 1;
307 FV.push_back({{stack[i], stack[next_stack_idx], centroid_idx}});
308 local_e_on_input.push_back({{0, 0, is_on_input[i]}});
311 V_pos.push_back(centroid /
double(end_idx - begin_idx + 1));
320 in_stack_idx[v].push_back(stack.size() - 1);
322 std::map<int64_t, int64_t> global_to_local_idx;
323 for (int64_t i = 0; i < VV[v].size(); ++i) {
324 global_to_local_idx[std::get<0>(VV[v][i])] = i;
328 std::vector<Vector2r> out_vec;
329 std::vector<int64_t> out_vertices;
332 std::vector<std::array<double, 2>> out_vec_double;
333 std::array<double, 2> prev_vec_double = {
334 {prev_vector[0].to_double(), prev_vector[1].to_double()}};
337 for (int64_t i = 0; i < VV[v].size(); ++i) {
338 if (std::get<0>(VV[v][i]) == v_prev) {
342 out_vec.push_back(V_pos[std::get<0>(VV[v][i])] - V_pos[v]);
343 out_vec_double.push_back(
344 {{(V_pos[std::get<0>(VV[v][i])] - V_pos[v])[0].to_double(),
345 (V_pos[std::get<0>(VV[v][i])] - V_pos[v])[1].to_double()}});
346 out_vertices.push_back(std::get<0>(VV[v][i]));
350 out_vec.push_back(prev_vector);
351 out_vertices.push_back(-1);
353 int64_t base_idx = out_vec.size() - 1;
358 std::vector<int64_t> ccw_vertices;
359 std::vector<Vector2r> ccw_vec;
360 std::vector<int64_t> ccw_local_idx;
362 int64_t start_idx = -1;
363 for (int64_t i = 0; i < cyclic_order_idx.size(); ++i) {
364 if (cyclic_order_idx[i] == base_idx) {
369 assert(start_idx > -1);
373 bool has_colinear_out =
false;
374 int64_t colinear_out_idx = -1;
375 int64_t iter = (start_idx + 1) % out_vec.size();
377 if (prev_vector[0] * out_vec[cyclic_order_idx[iter]][1] ==
378 prev_vector[1] * out_vec[cyclic_order_idx[iter]][0]) {
379 has_colinear_out =
true;
380 colinear_out_idx = iter;
381 iter = (iter + 1) % out_vec.size();
384 while (iter != start_idx) {
385 if (prev_vector[0] * out_vec[cyclic_order_idx[iter]][1] >=
386 prev_vector[1] * out_vec[cyclic_order_idx[iter]][0]) {
387 ccw_vertices.push_back(out_vertices[cyclic_order_idx[iter]]);
388 ccw_vec.push_back(out_vec[cyclic_order_idx[iter]]);
390 iter = (iter + 1) % out_vec.size();
393 if (has_colinear_out) {
394 ccw_vertices.push_back(out_vertices[cyclic_order_idx[colinear_out_idx]]);
395 ccw_vec.push_back(out_vec[cyclic_order_idx[colinear_out_idx]]);
400 for (int64_t i = 0; i < ccw_vertices.size(); ++i) {
401 if (!std::get<2>(VV[v][global_to_local_idx[ccw_vertices[i]]]) &&
402 ccw_vertices[i] != v_prev) {
403 is_on_input.push_back(
404 (std::get<1>(VV[v][global_to_local_idx[ccw_vertices[i]]])) ? 1 : 0);
405 is_used.push_back(0);
406 std::get<2>(VV[v][global_to_local_idx[ccw_vertices[i]]]) =
true;
421 is_on_input.pop_back();
428 in_stack_idx[v].pop_back();
432 std::vector<std::vector<std::tuple<int64_t, bool, bool>>>& VV,
433 std::vector<Vector2r>& V_pos,
434 std::vector<std::array<int64_t, 3>>& FV,
435 std::vector<std::array<int, 3>>& local_e_on_input)
437 std::vector<int> in_stack(VV.size(), 0);
438 std::vector<std::vector<int64_t>> in_stack_idx(VV.size());
440 std::vector<int64_t> stack;
441 std::vector<int> is_on_input;
442 std::vector<int> is_used;
448 for (int64_t i = 0; i < VV.size(); ++i) {
451 in_stack_idx[i].push_back(stack.size() - 1);
453 for (int64_t j = 0; j < VV[i].size(); ++j) {
454 if (!std::get<2>(VV[i][j])) {
455 is_on_input.push_back((std::get<1>(VV[i][j])) ? 1 : 0);
456 is_used.push_back(0);
457 std::get<2>(VV[i][j]) =
true;
459 std::get<0>(VV[i][j]),
467 V_pos[std::get<0>(VV[i][j])] - V_pos[i],
472 is_on_input.pop_back();
479 in_stack_idx[i].pop_back();
486 std::vector<Vector2r>& v_final,
487 std::vector<std::array<int64_t, 3>>& FV_new,
488 std::vector<std::array<int, 3>>& local_e_on_input)
491 std::move(_trimesh));
498 Eigen::MatrixX<int64_t> EV_tmp;
505 Eigen::MatrixX<double> V_edge_double;
509 Eigen::VectorX<int64_t> _SVI, _SVJ;
510 Eigen::MatrixX<int64_t> EV_in;
511 Eigen::MatrixX<double> V_edge_tmp;
513 igl::remove_duplicate_vertices(V_edge_double, EV_tmp, 0, V_edge_tmp, _SVI, _SVJ, EV_in);
515 Eigen::MatrixX<Rational> V_edge;
517 V_edge.resize(V_edge_tmp.rows(), V_edge_tmp.cols());
518 for (int64_t i = 0; i < V_edge_tmp.rows(); ++i) {
519 for (int64_t j = 0; j < V_edge_tmp.cols(); ++j) {
520 V_edge(i, j) =
Rational(V_edge_tmp(i, j));
576 std::vector<std::array<int64_t, 2>> EV;
577 for (int64_t i = 0; i < EV_in.rows(); ++i) {
578 EV.push_back({{EV_in(i, 0), EV_in(i, 1)}});
585 auto bbox_min_handle =
588 auto bbox_max_handle =
592 auto position_handle =
596 auto segment_index_handle =
598 auto segment_index_accessor = trimesh.
create_accessor<int64_t>(segment_index_handle);
600 std::vector<attribute::MeshAttributeHandle> pass_through_attributes;
601 pass_through_attributes.push_back(bbox_min_handle);
602 pass_through_attributes.push_back(bbox_max_handle);
603 pass_through_attributes.push_back(position_handle);
612 const Vector2r& p0 = position_accessor.const_vector_attribute(v0);
613 const Vector2r& p1 = position_accessor.const_vector_attribute(v1);
614 const Vector2r& p2 = position_accessor.const_vector_attribute(v2);
618 bbox_min_accessor.vector_attribute(f) =
bbox[0];
619 bbox_max_accessor.vector_attribute(f) =
bbox[1];
623 for (int64_t i = 0; i < V_edge.rows(); ++i) {
632 bbox_min_accessor.const_vector_attribute(f),
633 bbox_max_accessor.const_vector_attribute(f))) {
642 const Vector2r& p0 = position_accessor.const_vector_attribute(v0);
643 const Vector2r& p1 = position_accessor.const_vector_attribute(v1);
644 const Vector2r& p2 = position_accessor.const_vector_attribute(v2);
646 const std::array<Vector2r, 3> ps = {{p0, p1, p2}};
650 if (in_tri_case == -1) {
653 switch (in_tri_case) {
658 for (
const auto& attr : pass_through_attributes) {
666 segment_index_handle,
670 for (
const auto& attr : pass_through_attributes) {
677 segment_index_handle,
684 position_accessor.vector_attribute(new_v) = p;
687 const Tuple new_f0 = new_v;
697 bbox_min_accessor.vector_attribute(new_f0) = bbox_0[0];
698 bbox_max_accessor.vector_attribute(new_f0) = bbox_0[1];
699 bbox_min_accessor.vector_attribute(new_f1) = bbox_1[0];
700 bbox_max_accessor.vector_attribute(new_f1) = bbox_1[1];
701 bbox_min_accessor.vector_attribute(new_f2) = bbox_2[0];
702 bbox_max_accessor.vector_attribute(new_f2) = bbox_2[1];
705 const auto original_edge =
708 const Tuple neighbor_f =
713 const Vector2r& pn = position_accessor.const_vector_attribute(oppo_v);
716 bbox_min_accessor.vector_attribute(neighbor_f) = bbox_n[0];
717 bbox_max_accessor.vector_attribute(neighbor_f) = bbox_n[1];
722 segment_index_accessor.scalar_attribute(new_v) = i;
730 for (
const auto& attr : pass_through_attributes) {
738 segment_index_handle,
747 position_accessor.vector_attribute(new_v) = p;
750 const Tuple new_f0 = new_v;
758 bbox_min_accessor.vector_attribute(new_f0) = bbox_0[0];
759 bbox_max_accessor.vector_attribute(new_f0) = bbox_0[1];
760 bbox_min_accessor.vector_attribute(new_f1) = bbox_1[0];
761 bbox_max_accessor.vector_attribute(new_f1) = bbox_1[1];
770 position_accessor.const_vector_attribute(trimesh.
switch_tuples(
772 {PrimitiveType::Edge, PrimitiveType::Vertex}));
777 bbox_min_accessor.vector_attribute(new_f2) = bbox_2[0];
778 bbox_max_accessor.vector_attribute(new_f2) = bbox_2[1];
779 bbox_min_accessor.vector_attribute(new_f3) = bbox_3[0];
780 bbox_max_accessor.vector_attribute(new_f3) = bbox_3[1];
783 segment_index_accessor.scalar_attribute(new_v) = i;
791 for (
const auto& attr : pass_through_attributes) {
799 segment_index_handle,
807 {PrimitiveType::Vertex, PrimitiveType::Edge})))
812 position_accessor.vector_attribute(new_v) = p;
815 const Tuple new_f0 = new_v;
823 bbox_min_accessor.vector_attribute(new_f0) = bbox_0[0];
824 bbox_max_accessor.vector_attribute(new_f0) = bbox_0[1];
825 bbox_min_accessor.vector_attribute(new_f1) = bbox_1[0];
826 bbox_max_accessor.vector_attribute(new_f1) = bbox_1[1];
835 position_accessor.const_vector_attribute(trimesh.
switch_tuples(
837 {PrimitiveType::Edge, PrimitiveType::Vertex}));
842 bbox_min_accessor.vector_attribute(new_f2) = bbox_2[0];
843 bbox_max_accessor.vector_attribute(new_f2) = bbox_2[1];
844 bbox_min_accessor.vector_attribute(new_f3) = bbox_3[0];
845 bbox_max_accessor.vector_attribute(new_f3) = bbox_3[1];
848 segment_index_accessor.scalar_attribute(new_v) = i;
856 for (
const auto& attr : pass_through_attributes) {
864 segment_index_handle,
875 position_accessor.vector_attribute(new_v) = p;
878 const Tuple new_f0 = new_v;
886 bbox_min_accessor.vector_attribute(new_f0) = bbox_0[0];
887 bbox_max_accessor.vector_attribute(new_f0) = bbox_0[1];
888 bbox_min_accessor.vector_attribute(new_f1) = bbox_1[0];
889 bbox_max_accessor.vector_attribute(new_f1) = bbox_1[1];
898 position_accessor.const_vector_attribute(trimesh.
switch_tuples(
900 {PrimitiveType::Edge, PrimitiveType::Vertex}));
905 bbox_min_accessor.vector_attribute(new_f2) = bbox_2[0];
906 bbox_max_accessor.vector_attribute(new_f2) = bbox_2[1];
907 bbox_min_accessor.vector_attribute(new_f3) = bbox_3[0];
908 bbox_max_accessor.vector_attribute(new_f3) = bbox_3[1];
911 segment_index_accessor.scalar_attribute(new_v) = i;
917 segment_index_accessor.scalar_attribute(v0) = i;
922 segment_index_accessor.scalar_attribute(v1) = i;
927 segment_index_accessor.scalar_attribute(v2) = i;
931 throw std::runtime_error(
"wrong inside triangle case");
946 std::vector<int64_t> v_map_seg_to_tri(V_edge.rows());
949 for (int64_t i = 0; i < vs.size(); ++i) {
950 int64_t seg_idx = segment_index_accessor.const_scalar_attribute(vs[i]);
956 assert(seg_idx < V_edge.rows());
957 v_map_seg_to_tri[seg_idx] = i;
964 Eigen::MatrixX<int64_t> FV;
965 Eigen::MatrixX<Rational> V_tris;
970 Eigen::MatrixX<int64_t>
edges;
974 v_final.resize(V_tris.rows());
976 for (int64_t i = 0; i < V_tris.rows(); ++i) {
977 v_final[i] = V_tris.row(i);
980 std::vector<Segment> segments;
981 for (int64_t i = 0; i <
edges.rows(); ++i) {
986 for (
int i = 0; i < EV.size(); ++i) {
987 EV[i][0] = v_map_seg_to_tri[EV[i][0]];
988 EV[i][1] = v_map_seg_to_tri[EV[i][1]];
991 for (int64_t i = 0; i < EV.size(); ++i) {
992 const int64_t idx0 = EV[i][0];
993 const int64_t idx1 = EV[i][1];
1000 std::vector<Segment> new_segments;
1001 bool s_already_exist =
false;
1003 for (int64_t j = 0; j < segments.size(); ++j) {
1004 auto& seg = segments[j];
1006 if (seg.deprecated)
continue;
1014 if ((s.
p0 == seg.p0 && s.
p1 == seg.p1) || (s.
p0 == seg.p1 && s.
p1 == seg.p0)) {
1016 s_already_exist =
true;
1017 seg.is_on_input =
true;
1022 seg.deprecated =
true;
1024 std::vector<std::pair<int64_t, Vector2r>> all_points;
1028 all_points.push_back(p);
1030 for (
const auto& p : seg.points_on_segment) {
1031 all_points.push_back(p);
1034 auto comp = [](
const std::pair<int64_t, Vector2r>& v0,
1035 const std::pair<int64_t, Vector2r>& v1) {
1036 if (v0.second[0] == v1.second[0]) {
1037 return v0.second[1] < v1.second[1];
1039 return v0.second[0] < v1.second[0];
1042 auto equal = [](
const std::pair<int64_t, Vector2r>& v0,
1043 const std::pair<int64_t, Vector2r>& v1) {
1044 return v0.second[0] == v1.second[0] && v0.second[1] == v1.second[1];
1048 std::sort(all_points.begin(), all_points.end(), comp);
1050 std::unique(all_points.begin(), all_points.end(), equal),
1053 int64_t p0_idx = -1, p1_idx = -1;
1055 for (int64_t k = 0; k < all_points.size(); ++k) {
1056 if (idx0 == all_points[k].first) {
1059 if (idx1 == all_points[k].first) {
1064 assert(p0_idx != -1 && p1_idx != -1);
1067 int64_t start_idx, end_idx;
1069 if (p0_idx < p1_idx) {
1078 if (start_idx != 0) {
1080 all_points[0].second,
1081 all_points[start_idx].second,
1082 all_points[0].first,
1083 all_points[start_idx].first);
1084 for (int64_t k = 1; k < start_idx; ++k) {
1090 new_segments.push_back(s0);
1094 for (int64_t k = start_idx; k <= end_idx; ++k) {
1098 if (end_idx != all_points.size() - 1) {
1100 all_points[end_idx].second,
1101 all_points[all_points.size() - 1].second,
1102 all_points[end_idx].first,
1103 all_points[all_points.size() - 1].first);
1104 for (int64_t k = end_idx + 1; k < all_points.size() - 1; ++k) {
1110 new_segments.push_back(s1);
1124 assert(t0 >= 0 && t0 <= 1);
1125 assert(t1 >= 0 && t1 <= 1);
1128 bool v_exist_on_0 =
false;
1129 bool v_exist_on_1 =
false;
1130 int64_t new_v_idx = -1;
1134 v_exist_on_0 =
true;
1140 for (int64_t k = 0; k < seg.points_on_segment.size(); ++k) {
1141 if (res == seg.points_on_segment[k].second) {
1142 v_exist_on_1 =
true;
1143 new_v_idx = seg.points_on_segment[k].first;
1148 if (!v_exist_on_0 && !v_exist_on_1) {
1149 v_final.push_back(res);
1150 new_v_idx = v_final.size() - 1;
1153 assert(new_v_idx > -1);
1155 if (!v_exist_on_0) {
1169 if (!v_exist_on_1) {
1180 seg.points_on_segment.push_back(std::make_pair(new_v_idx, res));
1185 for (
const auto& seg : new_segments) {
1186 segments.push_back(seg);
1189 if (!s_already_exist) {
1190 segments.push_back(s);
1196 auto comp = [](
const std::pair<int64_t, Vector2r>& v0,
const std::pair<int64_t, Vector2r>& v1) {
1197 if (v0.second[0] == v1.second[0]) {
1198 return v0.second[1] < v1.second[1];
1200 return v0.second[0] < v1.second[0];
1203 for (int64_t i = 0; i < segments.size(); ++i) {
1204 if (segments[i].deprecated) {
1207 std::sort(segments[i].points_on_segment.begin(), segments[i].points_on_segment.end(), comp);
1212 std::vector<std::vector<std::tuple<int64_t, bool, bool>>> VV(v_final.size());
1214 for (int64_t i = 0; i < segments.size(); ++i) {
1215 if (segments[i].deprecated) {
1218 for (int64_t j = 0; j < segments[i].points_on_segment.size() - 1; ++j) {
1219 VV[segments[i].points_on_segment[j].first].push_back(std::make_tuple(
1220 segments[i].points_on_segment[j + 1].first,
1221 segments[i].is_on_input,
1223 VV[segments[i].points_on_segment[j + 1].first].push_back(std::make_tuple(
1224 segments[i].points_on_segment[j].first,
1225 segments[i].is_on_input,
attribute::Accessor< T, Derived, Dim > create_accessor(const TypedAttributeHandle< T > &handle)
constructs an accessor that is aware of the derived mesh's type
Tuple switch_tuples(const Tuple &tuple, const ContainerType &op_sequence) const
Performs a sequence of switch_tuple operations in the order specified in op_sequence.
attribute::MeshAttributeHandle register_attribute(const std::string &name, PrimitiveType type, int64_t size, bool replace=false, T default_value=T(0))
void serialize(MeshWriter &writer, const Mesh *local_root=nullptr) const
attribute::MeshAttributeHandle get_attribute_handle(const std::string &name, const PrimitiveType ptype) const
std::vector< Tuple > get_all(PrimitiveType type) const
Generate a vector of Tuples from global vertex/edge/triangle/tetrahedron index.
virtual std::tuple< std::vector< std::vector< int64_t > >, std::vector< std::vector< int64_t > > > consolidate()
Consolidate the attributes, moving all valid simplexes at the beginning of the corresponding vector.
Tuple switch_tuple(const Tuple &tuple, PrimitiveType type) const final override
switch the orientation of the Tuple of the given dimension
bool is_boundary(PrimitiveType pt, const Tuple &tuple) const final override
check if a simplex (encoded as a tuple/primitive pair) lies on a boundary or not
std::vector< std::pair< int64_t, Vector2r > > points_on_segment
void set_new_attribute_strategy(const attribute::MeshAttributeHandle &attribute, const std::shared_ptr< const operations::BaseCollapseNewAttributeStrategy > &other)
void set_new_attribute_strategy(const attribute::MeshAttributeHandle &attribute, const std::shared_ptr< const operations::BaseSplitNewAttributeStrategy > &other)
The return tuple is the new vertex, pointing to the original vertex.
EdgeCollapse & collapse()
static Simplex face(const Mesh &m, const Tuple &t)
static Simplex edge(const Mesh &m, const Tuple &t)
void get_position_matrix(MatrixX< double > &matrix)
void get_EV_matrix(MatrixX< int64_t > &matrix)
void get_FV_matrix(MatrixX< int64_t > &matrix)
void dfs_triangulate(std::vector< std::vector< std::tuple< int64_t, bool, bool >>> &VV, std::vector< Vector2r > &V_pos, std::vector< std::array< int64_t, 3 >> &FV, std::vector< std::array< int, 3 >> &local_e_on_input)
std::array< wmtk::Vector2r, 2 > compute_bbox(const wmtk::Vector2r &p0, const wmtk::Vector2r &p1, const wmtk::Vector2r &p2)
bool is_colinear(const Vector2r &p0, const Vector2r &p1, const Vector2r &q0, const Vector2r &q1)
wmtk::Rational det(const wmtk::Vector2r &a, const wmtk::Vector2r &b)
std::vector< int64_t > cyclic_order(const std::vector< Vector2r > &V)
void dfs_triangulate_aux(int64_t v, std::vector< std::vector< std::tuple< int64_t, bool, bool >>> &VV, std::vector< Vector2r > &V_pos, std::vector< int64_t > &stack, std::vector< int > &in_stack, std::vector< int > &is_on_input, std::vector< int > &is_used, std::vector< std::vector< int64_t >> &in_stack_idx, const Vector2r &prev_vector, const int64_t v_prev, std::vector< std::array< int64_t, 3 >> &FV, std::vector< std::array< int, 3 >> &local_e_on_input)
void edge_insertion(TriMesh &_trimesh, EdgeMesh &edgemesh, std::vector< Vector2r > &v_final, std::vector< std::array< int64_t, 3 >> &FV_new, std::vector< std::array< int, 3 >> &local_e_on_input)
bool segment_segment_inter(const Vector2r &s0, const Vector2r &e0, const Vector2r &s1, const Vector2r &e1, Vector2r &res, Rational &t0, Rational &t1)
int is_point_inside_triangle(const wmtk::Vector2r &P, const wmtk::Vector2r &A, const wmtk::Vector2r &B, const wmtk::Vector2r &C)
bool is_bbox_intersect(const Vector2r &bbox_min_0, const Vector2r &bbox_max_0, const Vector2r &bbox_min_1, const Vector2r &bbox_max_1)
bool is_point_in_bbox(const Vector2r &point, const Vector2r &bbox_min, const Vector2r &bbox_max)
std::vector< Tuple > edges(const Mesh &m, const Simplex &simplex)
int wmtk_orient2d(double p0x, double p0y, double p1x, double p1y, double p2x, double p2y)
Rational abs(const Rational &r0)
Vector< Rational, 2 > Vector2r