2 #if defined(__GNUG__) && !defined(__clang__)
3 #pragma GCC diagnostic push
6 #pragma GCC diagnostic ignored "-Wdangling-pointer"
12 #include <Eigen/src/Core/MapBase.h>
15 #if defined(__GNUG__) && !defined(__clang__)
16 #pragma GCC diagnostic pop
41 return m_mesh.switch_tuples(tuple, {
PE,
PV});
53 for (
int i = 0; i < 3; ++i) {
71 t = m_mesh.switch_vertex(t);
78 const std::array<Tuple, 2> ear_edges{
79 {m_mesh.switch_edge(t), m_mesh.switch_edge(m_mesh.switch_vertex(t))}};
83 face_data.
fid = m_mesh.id_face(t);
84 face_data.
opposite_vid = m_mesh.id_vertex(m_mesh.switch_vertex(ear_edges[0]));
89 face_data.
ears.begin(),
90 [&](
const Tuple& edge) {
92 const int64_t ear_fid = ff_accessor.const_vector_attribute(edge)[edge.m_local_eid];
96 m_mesh.id_edge(edge)};
105 const Tuple& operating_tuple)
107 , ff_accessor(*m.m_ff_accessor)
108 , fe_accessor(*m.m_fe_accessor)
109 , fv_accessor(*m.m_fv_accessor)
110 , vf_accessor(*m.m_vf_accessor)
111 , ef_accessor(*m.m_ef_accessor)
115 assert(m.is_connectivity_valid());
116 m_operating_tuple = operating_tuple;
118 m_operating_edge_id = m_mesh.id_edge(m_operating_tuple);
119 m_spine_vids[0] = m_mesh.id_vertex(m_operating_tuple);
120 m_spine_vids[1] = m_mesh.id_vertex(m_mesh.switch_vertex(m_operating_tuple));
125 for (
size_t d = 0; d < simplex_ids_to_delete.size(); ++d) {
127 "Deleting {} {}-simplices [{}]",
128 simplex_ids_to_delete[d].size(),
130 fmt::join(simplex_ids_to_delete[d],
","));
131 for (
const int64_t
id : simplex_ids_to_delete[d]) {
132 flag_accessors[d].index_access().scalar_attribute(
id) = 0;
138 const std::array<std::vector<int64_t>, 3>
144 std::array<std::vector<int64_t>, 3> ids;
152 const std::array<std::vector<int64_t>, 3>
157 std::array<std::vector<int64_t>, 3> ids;
172 ids[0].emplace_back(m.
id(v));
173 ids[1].emplace_back(m.
id(e));
182 for (
size_t i = 0; i < ids.size(); ++i) {
183 std::sort(ids[i].begin(), ids[i].end());
201 const int64_t new_fid,
202 const int64_t old_fid)
213 auto ear_ff = ff_accessor.index_access().vector_attribute(ear.
fid);
214 auto ear_fe = fe_accessor.index_access().vector_attribute(ear.
fid);
215 for (
int i = 0; i < 3; ++i) {
216 if (ear_ff[i] == old_fid) {
223 ef_accessor.index_access().scalar_attribute(ear.
eid) = ear.
fid;
228 assert(!m_incident_face_datas.empty());
242 for (
auto& face_data : m_incident_face_datas) {
243 const EarData& ear0 = face_data.ears[0];
244 const EarData& ear1 = face_data.ears[1];
245 const int64_t& f_old = face_data.
fid;
246 const int64_t& v1 = m_spine_vids[1];
249 assert(ear0.
fid > -1 || ear1.
fid > -1);
251 assert(ear0.
fid != ear1.
fid);
254 int64_t& new_opp_vf = vf_accessor.index_access().scalar_attribute(face_data.opposite_vid);
256 new_opp_vf = (ear0.
fid < 0) ? ear1.
fid : ear0.
fid;
258 face_data.new_edge_id = ear1.
eid;
260 face_data.merged_edge_fid = new_opp_vf;
262 int64_t& ef_val = ef_accessor.index_access().scalar_attribute(ear1.
eid);
263 int64_t& vf_val = vf_accessor.index_access().scalar_attribute(v1);
272 update_ids_in_ear(new_f0_ear, ear1.
fid, f_old);
273 update_ids_in_ear(ear1, ear0.
fid, f_old);
280 assert(m_incident_face_datas.size() == 2);
281 const int64_t f_old_top = m_incident_face_datas[0].fid;
282 const int64_t f0_top = m_incident_face_datas[0].split_f[0];
283 const int64_t f1_top = m_incident_face_datas[0].split_f[1];
284 const int64_t f_old_bottom = m_incident_face_datas[1].fid;
285 const int64_t f0_bottom = m_incident_face_datas[1].split_f[0];
286 const int64_t f1_bottom = m_incident_face_datas[1].split_f[1];
287 auto ff_old_top = ff_accessor.index_access().const_vector_attribute(f_old_top);
288 auto ff_old_bottom = ff_accessor.index_access().const_vector_attribute(f_old_bottom);
295 int64_t local_eid_top = -1;
296 int64_t local_eid_bottom = -1;
297 for (
size_t i = 0; i < 3; ++i) {
298 if (ff_old_top[i] == f_old_bottom) {
301 if (ff_old_bottom[i] == f_old_top) {
302 local_eid_bottom = i;
305 assert(local_eid_top > -1);
306 assert(local_eid_bottom > -1);
308 ff_accessor.index_access().vector_attribute(f0_top)[local_eid_top] = f0_bottom;
309 ff_accessor.index_access().vector_attribute(f0_bottom)[local_eid_bottom] = f0_top;
310 ff_accessor.index_access().vector_attribute(f1_top)[local_eid_top] = f1_bottom;
311 ff_accessor.index_access().vector_attribute(f1_bottom)[local_eid_bottom] = f1_top;
316 const auto& new_fids = face_data.
split_f;
318 "TriSplitreplacing topology of face {} with {}",
320 fmt::join(new_fids,
","));
322 if (!m_mesh.is_free()) {
323 std::vector<int64_t> splitting_edges =
325 assert(splitting_edges[0] > -1);
327 split_edge_eid = splitting_edges[0];
342 const int64_t f_old = face_data.
fid;
343 auto old_fv = fv_accessor.index_access().const_vector_attribute(f_old).eval();
344 auto old_fe = fe_accessor.index_access().const_vector_attribute(f_old).eval();
345 auto old_ff = ff_accessor.index_access().const_vector_attribute(f_old).eval();
348 for (
int j = 0; j < 2; ++j) {
349 int other_index = 1 - j;
350 const int64_t f = face_data.
split_f[j];
351 const auto& ear = face_data.
ears[j];
353 const auto& other_ear = face_data.
ears[other_index];
355 const int64_t other_f = face_data.
split_f[other_index];
356 const int64_t other_v =
357 m_spine_vids[other_index];
358 const int64_t se = split_spine_eids[j];
362 update_ids_in_ear(ear, f, f_old);
364 auto fv = fv_accessor.index_access().vector_attribute(f);
365 auto fe = fe_accessor.index_access().vector_attribute(f);
366 auto ff = ff_accessor.index_access().vector_attribute(f);
371 for (
size_t i = 0; i < 3; ++i) {
374 if (fe[i] == other_ear.eid) {
375 if (m_mesh.is_free()) {
376 fe[i] = m_free_split_e[j];
378 const int64_t& split_edge_eid = face_data.
new_edge_id;
380 fe[i] = split_edge_eid;
381 logger().trace(
"ff[{},{}] = {}", f, i, other_f);
382 logger().trace(
"fe[{},{}] = {}", f, i, split_edge_eid);
387 if (fe[i] == m_operating_edge_id) {
388 logger().trace(
"fe[{},{}] = {}", f, i, se);
393 if (fv[i] == other_v) {
394 if (m_mesh.is_free()) {
395 fv[i] = m_free_split_v[j];
397 fv[i] = split_new_vid;
401 logger().trace(
"ef[{}] = {}", ear.eid, f);
402 logger().trace(
"ef[{}] = {}", se, f);
404 ef_accessor.index_access().scalar_attribute(ear.eid) = f;
405 ef_accessor.index_access().scalar_attribute(se) = f;
407 logger().trace(
"vf[{}] = {}", m_spine_vids[j], f);
408 vf_accessor.index_access().scalar_attribute(m_spine_vids[j]) = f;
411 vf_accessor.index_access().scalar_attribute(v_opp) = new_fids[0];
413 if (m_mesh.is_free()) {
414 for (
size_t j = 0; j < 2; ++j) {
415 ef_accessor.index_access().scalar_attribute(m_free_split_e[j]) = new_fids[j];
416 vf_accessor.index_access().scalar_attribute(m_free_split_v[j]) = new_fids[j];
419 const int64_t f = face_data.
split_f[1];
420 auto fv = fv_accessor.index_access().vector_attribute(f);
421 for (
int j = 0; j < 3; ++j) {
423 logger().trace(
"fv[{},{}] = {}", f, j, split_new_vid);
424 fv(j) = split_new_vid;
426 logger().trace(
"vf[{}] = {}", split_new_vid, new_fids[1]);
427 vf_accessor.index_access().scalar_attribute(split_new_vid) = new_fids[1];
432 const int64_t& split_edge_eid = face_data.
new_edge_id;
433 logger().trace(
"ef[{}] = {}", split_edge_eid, new_fids[0]);
434 logger().trace(
"vf[{}] = {}", split_new_vid, new_fids[0]);
435 ef_accessor.index_access().scalar_attribute(split_edge_eid) = new_fids[0];
436 vf_accessor.index_access().scalar_attribute(split_new_vid) = new_fids[0];
451 simplex_ids_to_delete = get_split_simplices_to_delete(m_operating_tuple, m_mesh);
457 assert(m_operating_tuple == adjacent_facets[0]);
459 assert(m_incident_face_datas.empty());
462 adjacent_facets.begin(),
463 adjacent_facets.end(),
464 std::back_inserter(m_incident_face_datas),
465 [&](
const Tuple& t) { return get_incident_face_data(t); });
467 assert(m_incident_face_datas[0].fid == m_mesh.id_face(m_operating_tuple));
468 assert(m_incident_face_datas[0].local_operating_tuple == m_operating_tuple);
470 std::vector<std::vector<Tuple>> bsc(2);
471 if (m_mesh.has_child_mesh_in_dimension(0)) {
472 auto& this_bsc = bsc[0];
473 this_bsc.reserve(m_incident_face_datas.size() + 2);
475 this_bsc.emplace_back(m_operating_tuple);
476 this_bsc.emplace_back(m_mesh.switch_vertex(m_operating_tuple));
477 for (
const auto& data : m_incident_face_datas) {
478 this_bsc.emplace_back(m_mesh.switch_tuples(
479 data.local_operating_tuple,
480 {PrimitiveType::Edge, PrimitiveType::Vertex}));
483 if (m_mesh.has_child_mesh_in_dimension(1)) {
484 auto& this_bsc = bsc[1];
506 hash_update_region.
add(v_closed_star);
510 global_ids_to_potential_tuples.resize(3);
519 for (
const auto& s :
faces) {
520 const int64_t index =
static_cast<int64_t
>(s.primitive_type());
521 if (!m_mesh.has_child_mesh_in_dimension(index))
continue;
522 global_ids_to_potential_tuples.at(index).emplace_back(
527 create_spine_simplices();
528 fill_split_facet_data();
534 const size_t facet_size = m_incident_face_datas.size();
535 std::vector<int64_t> new_facet_ids =
537 assert(new_facet_ids.size() == 2 * facet_size);
538 for (
size_t j = 0; j < facet_size; ++j) {
539 std::array<int64_t, 2> arr;
541 new_facet_ids.begin() + 2 * j,
542 new_facet_ids.begin() + 2 * (j + 1),
545 split_facet_data().add_facet(m_mesh, m_operating_tuple, arr);
546 m_incident_face_datas[j].split_f = arr;
552 split_edge_precompute();
554 assert(m_incident_face_datas.size() <= 2);
558 replace_incident_face(face_data);
560 if (m_incident_face_datas.size() > 1) {
561 connect_faces_across_spine();
577 const int64_t new_tuple_fid = m_incident_face_datas[0].split_f[1];
578 if (m_mesh.is_free()) {
580 m_mesh.tuple_from_global_ids(new_tuple_fid, split_spine_eids[1], m_free_split_v[1]);
581 assert(m_mesh.id_vertex(m_output_tuple) == m_free_split_v[1]);
584 m_mesh.tuple_from_global_ids(new_tuple_fid, split_spine_eids[1], split_new_vid);
585 assert(m_mesh.id_vertex(m_output_tuple) == split_new_vid);
587 assert(m_mesh.id_face(m_output_tuple) == new_tuple_fid);
588 assert(m_mesh.is_valid(m_output_tuple));
595 if (m_mesh.is_free()) {
598 assert(new_vids.size() == 3);
600 std::copy(new_vids.begin() + 1, new_vids.end(), m_free_split_v.begin());
601 split_new_vid = new_vids[0];
605 assert(new_eids.size() == 4);
607 auto midpoint = new_eids.begin() + 2;
608 std::copy(new_eids.begin(), midpoint, split_spine_eids.begin());
609 std::copy(midpoint, new_eids.end(), m_free_split_e.begin());
614 assert(new_vids.size() == 1);
615 split_new_vid = new_vids[0];
616 logger().trace(
"new split vid {}", split_new_vid);
620 assert(new_eids.size() == 2);
622 std::copy(new_eids.begin(), new_eids.end(), split_spine_eids.begin());
623 logger().trace(
"new split eids {}", fmt::join(split_spine_eids,
","));
636 m_incident_face_datas.emplace_back(get_incident_face_data(f));
639 assert(m_incident_face_datas.size() <= 2);
640 if (m_incident_face_datas[0].fid != m_mesh.id_face(m_operating_tuple)) {
641 assert(m_incident_face_datas.size() == 2);
642 std::swap(m_incident_face_datas[0], m_incident_face_datas[1]);
645 if (m_mesh.has_child_mesh()) {
646 global_ids_to_potential_tuples.resize(3);
654 m_mesh.switch_vertex(m_operating_tuple));
655 std::array<simplex::internal::VisitedArray<wmtk::simplex::IdSimplex>, 3> visited;
664 visited[0].visited_array().size() + visited[1].visited_array().size() +
665 visited[2].visited_array().size());
666 for (
size_t j = 0; j < visited.size(); ++j) {
667 if (!m_mesh.has_child_mesh_in_dimension(j)) {
670 const auto& arr = visited[j];
671 for (
size_t i = 0; i < arr.visited_array().size(); ++i) {
678 const int64_t index =
static_cast<int64_t
>(s.primitive_type());
680 global_ids_to_potential_tuples.at(index).emplace_back(
686 simplex_ids_to_delete = get_collapse_simplices_to_delete(m_operating_tuple, m_mesh);
692 collapse_edge_precompute();
694 if (!m_mesh.is_free()) {
705 const int64_t& v0 = m_spine_vids[0];
706 const int64_t& v1 = m_spine_vids[1];
709 for (
const int64_t fid : v0_neighbors) {
710 bool is_fid_deleted =
false;
711 for (int64_t i = 0; i < m_incident_face_datas.size(); ++i) {
712 if (m_incident_face_datas[i].fid == fid) {
713 is_fid_deleted =
true;
717 if (is_fid_deleted) {
720 auto fv = fv_accessor.index_access().vector_attribute(fid);
721 for (int64_t i = 0; i < 3; ++i) {
729 const int64_t& ret_eid = m_incident_face_datas[0].ears[1].eid;
730 const int64_t& ret_vid = m_spine_vids[1];
731 const int64_t& ef0 = m_incident_face_datas[0].ears[0].fid;
732 const int64_t& ef1 = m_incident_face_datas[0].ears[1].fid;
734 const int64_t new_tuple_fid = (ef0 > -1) ? ef0 : ef1;
737 m_output_tuple = m_mesh.edge_tuple_from_id(ret_eid);
744 if (m_mesh.id_vertex(m_output_tuple) != ret_vid) {
745 m_output_tuple = m_mesh.switch_vertex(m_output_tuple);
747 assert(m_mesh.id_vertex(m_output_tuple) == ret_vid);
748 if (m_mesh.id_face(m_output_tuple) != new_tuple_fid) {
749 m_output_tuple = m_mesh.switch_face(m_output_tuple);
751 assert(m_mesh.id_face(m_output_tuple) == new_tuple_fid);
752 assert(m_mesh.is_valid(m_output_tuple));
766 return EdgeOperationData::request_simplex_indices(m_mesh, type, count);
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.
std::vector< int64_t > request_simplex_indices(PrimitiveType type, int64_t count)
const attribute::Accessor< char > get_flag_accessor(PrimitiveType type) const
static const std::array< std::vector< int64_t >, 3 > get_split_simplices_to_delete(const Tuple &tuple, const TriMesh &m)
gather all simplices that are deleted in a split
IncidentFaceData get_incident_face_data(Tuple t)
static const std::array< std::vector< int64_t >, 3 > get_collapse_simplices_to_delete(const Tuple &tuple, const TriMesh &m)
gather all simplices that are deleted in a collapse
TriMeshOperationExecutor(TriMesh &m, const Tuple &operating_tuple)
void fill_split_facet_data()
Tuple next_edge(const Tuple &tuple) const
jump to the next edge
std::vector< int64_t > request_simplex_indices(const PrimitiveType type, int64_t count)
void create_spine_simplices()
void collapse_edge_precompute()
Tuple prev_edge(const Tuple &tuple) const
jump to the previous edge
void replace_incident_face(IncidentFaceData &face_data)
void split_edge_precompute()
void connect_faces_across_spine()
void update_ids_in_ear(const EarData &ear, const int64_t new_fid, const int64_t old_fid)
handling the topology glueing of ear to non-ear face, transfering data from ear-oldface to ear-newfac...
Tuple switch_edge(const Tuple &tuple) const
int64_t id(const Tuple &tuple, PrimitiveType type) const
void reserve(const size_t new_cap)
void add(const Simplex &simplex)
Add simplex to the collection.
const std::vector< Simplex > & simplex_vector() const
Return const reference to the simplex vector.
void sort_and_clean()
Sort simplex vector and remove duplicates.
static Simplex edge(const Mesh &m, const Tuple &t)
static Simplex vertex(const Mesh &m, const Tuple &t)
static bool equal(const Mesh &m, const Simplex &s0, const Simplex &s1)
void emplace_back(const T &val)
void top_dimension_cofaces_tuples(const PointMesh &mesh, const Simplex &simplex, SimplexCollection &collection)
TopDimensionCofacesIterable top_dimension_cofaces_iterable(const Mesh &mesh, const Simplex &simplex)
SimplexCollection open_star(const Mesh &mesh, const Simplex &simplex, const bool sort_and_clean)
SimplexCollection closed_star(const Mesh &mesh, const Simplex &simplex, const bool sort_and_clean)
The closed star contains the input simplex, all its top dimension cofaces, and their faces.
void top_dimension_cofaces(const Simplex &simplex, SimplexCollection &simplex_collection, const bool sort_and_clean)
Get all top dimension cofaces of the given simplex.
ClosedStarIterable closed_star_iterable(const Mesh &mesh, const Simplex &simplex)
SimplexCollection faces(const Mesh &mesh, const Simplex &simplex, const bool sort_and_clean)
Returns all faces of a simplex.
constexpr PrimitiveType PV
constexpr int8_t get_primitive_type_id(PrimitiveType t)
Get a unique integer id corresponding to each primitive type.
spdlog::logger & logger()
Retrieves the current logger.
constexpr PrimitiveType PE
An ear is a face that is adjacent to a face that is incident to the edge on which the operation is pe...
Data on the incident face relevant for performing operations.
std::array< int64_t, 2 > split_f
std::array< EarData, 2 > ears
Tuple local_operating_tuple