Wildmeshing Toolkit
Loading...
Searching...
No Matches
TopoOffsetTriMesh.h
1#pragma once
2#include <wmtk/TriMesh.h>
3#include <wmtk/TriOptimizerMesh.h>
4#include <algorithm>
5#include <atomic>
6#include <functional>
7#include <set>
8#include <wmtk/threading/enumerable_thread_specific.hpp>
9#include "Parameters.h"
10#include "SimplicialComplexBVH.hpp"
11
12using CellTag = std::set<int64_t>;
13
14
15namespace wmtk::components::topological_offset {
16
17
18const int64_t TEMP_OFFSET_TRI_TAG = -1;
19const CellTag TEMP_OFFSET_TRI_TAG_SET{TEMP_OFFSET_TRI_TAG};
20
30constexpr double TOPOLOGY_BLOCK_AVG_FRAC = 0.05;
31
41{
42public:
43 int label = 0;
44 bool m_is_on_input = false; // on the input complex
45 bool m_is_on_offset = false; // on the offset boundary itself
46 bool m_is_on_region = false; // on some OTHER tag region's boundary
47};
48
49
53{
54public:
55 int label = 0;
56};
57
58
62{
63public:
64 int label = 0;
65};
66
67
84{
85public: // mode for splitting in marching tets
86 enum class EdgeSplitMode {
87 Midpoint = 0, // used for simplicial embedding steps
88 Initial = 1, // this is used to initialize the complex. Its a little hacky
89 Optimization = 2 // the optimization phase; the shared engine places the vertex
90 };
91
92public:
93 int m_vtu_counter = 0;
94 std::array<size_t, 3> m_init_counts = {{0, 0, 0}};
95 size_t m_tags_count;
96 SimplicialComplexBVH m_input_complex_bvh;
97 EdgeSplitMode m_edge_split_mode = EdgeSplitMode::Midpoint;
98
99 // tag name maps
100 std::map<std::string, int64_t> m_tag_name_to_id;
101 std::map<int64_t, std::string> m_tag_id_to_name;
102 CellTag m_offset_output_tag_ids;
103
104 // if in 'singlebody' mode
105 bool m_singlebody = false;
106 int64_t m_single_tag;
107
108 // just for retaining in output. dont actually use
109 bool m_has_envelope = false;
110 MatrixXd m_V_envelope;
111 MatrixXi m_F_envelope;
112
126 static constexpr int INPUT_SURFACE_CLASS = 0;
127 static constexpr int OFFSET_SURFACE_CLASS = 1;
128 static constexpr int REGION_SURFACE_CLASS = 2;
129
132
136 // m_vertex_attribute, m_edge_attribute and m_face_attribute are the base's; these three
137 // are registered alongside them in its attribute groups.
138 VertexExtraCol m_vertex_extra;
139 EdgeExtraCol m_edge_extra;
140 FaceExtraCol m_face_extra;
141
142 TopoOffsetTriMesh(Parameters& _m_offset_params, int _num_threads = 0)
143 : wmtk::TriOptimizerMesh(_m_offset_params)
144 , m_offset_params(_m_offset_params)
145 {
146 NUM_THREADS = _num_threads;
147 m_vertex_attr_group.add(&m_vertex_extra);
148 m_edge_attr_group.add(&m_edge_extra);
149 m_face_attr_group.add(&m_face_extra);
150 }
151
152 ~TopoOffsetTriMesh() override = default;
153
161 void set_vertex_position(const size_t vid, const Vector2d& p)
162 {
163 m_vertex_attribute[vid].m_posf = p;
164 m_vertex_attribute[vid].m_pos = to_rational(p);
165 m_vertex_attribute[vid].m_is_rounded = true;
166 }
167
170 bool edge_is_offset(const size_t eid) const
171 {
172 return m_edge_attribute[eid].m_is_surface_fs &&
173 m_edge_attribute[eid].m_surface_class == OFFSET_SURFACE_CLASS;
174 }
175 bool edge_is_region_boundary(const size_t eid) const
176 {
177 return m_edge_attribute[eid].m_is_surface_fs &&
178 m_edge_attribute[eid].m_surface_class == REGION_SURFACE_CLASS;
179 }
187 {
188 EdgeAttributes tags;
189 EdgeExtra2d extra;
190 };
192 {
193 FaceAttributes attrs;
194 FaceExtra2d extra;
195 };
196 EdgeSnapshot2d edge_snapshot(const size_t eid) const
197 {
198 return EdgeSnapshot2d{m_edge_attribute[eid], m_edge_extra[eid]};
199 }
200 void restore_edge(const size_t eid, const EdgeSnapshot2d& s)
201 {
202 m_edge_attribute[eid] = s.tags;
203 m_edge_extra[eid] = s.extra;
204 }
205 FaceSnapshot2d face_snapshot(const size_t fid) const
206 {
207 return FaceSnapshot2d{m_face_attribute[fid], m_face_extra[fid]};
208 }
209 void restore_face(const size_t fid, const FaceSnapshot2d& s)
210 {
211 m_face_attribute[fid] = s.attrs;
212 m_face_extra[fid] = s.extra;
213 }
214
224
239 bool face_in_region(const size_t fid) const;
240
243 bool face_is_input_complex(const size_t fid) const;
244
257 bool vertex_is_on_surface(const size_t vid) const override;
258 bool edge_is_on_surface(const std::array<size_t, 2>& vids) const override;
259
262 bool project_offset_vertex(const Tuple& t);
263
277 bool region_boundary_tangent(const Tuple& t, Vector2d& tang) const;
278
308 const size_t vid,
309 const Vector2d& p0,
310 const Vector2d& tang,
311 const double cap,
312 const std::function<bool()>& rejected);
313
315 void optimize_offset(const std::filesystem::path& output_file);
316
320 bool face_is_offset_band(const size_t fid) const;
321
340 {
341 const std::optional<Tuple> opp = t.switch_face(*this);
342 if (!opp) return false; // domain boundary: frozen, never a region boundary
343 const size_t fa = t.fid(*this), fb = opp->fid(*this);
345 return false; // input-complex boundary: frozen, not the envelope's job
346 }
348 return false; // offset boundary: exempt by design, it is what the optimization moves
349 }
350 return m_face_attribute[fa].tags != m_face_attribute[fb].tags;
351 }
352
362 std::pair<double, double> compute_distance_deviation() const;
363
366 mutable size_t m_worst_dist_vid = static_cast<size_t>(-1);
367 void log_worst_dist_vertex() const;
368
382 std::pair<double, double> compute_normal_deviation() const;
383
393 double edge_normal_deviation(const Tuple& e) const;
394
397 bool offset_field_normal(const Vector2d& p, Vector2d& n) const;
398
401 bool edge_is_offset_surface_live(const Tuple& e) const;
402
405 double max_offset_normal_deviation_at_vertex(const size_t vid) const;
406
411
415 std::vector<std::array<double, 4>> optimization_metrics;
416
421 std::vector<std::array<int, 3>> op_counts;
422 std::atomic<int> iter_cnt_split = 0, iter_cnt_collapse = 0, iter_cnt_swap = 0;
426 std::atomic<int> iter_cnt_collapse_nd_reject = 0;
427 std::atomic<int> iter_cnt_swap_nd_reject = 0;
428
433
438
448 {
449 std::map<size_t, int> face_label;
450 size_t v1_id = 0;
451 size_t v2_id = 0;
452 };
454
455 bool marching_split_edge_before(const Tuple& t);
456 bool marching_split_edge_after(const Tuple& t);
457
467 bool collapse_edge_before(const Tuple& t) override;
468
477 bool swap_edge_before(const Tuple& t) override;
478
481 bool swap_edge_after(const Tuple& t) override;
482 bool collapse_before_vertex(size_t v1, size_t v2) override;
483 void collapse_after_vertex(size_t v1, size_t v2) override;
486 bool collapse_edge_after(const Tuple& t) override;
487 void split_after_vertex(size_t v_new) override;
488
508 bool split_adjust_position(size_t v_new, const std::vector<Tuple>& children) override;
509
510 bool smooth_before(const Tuple& t) override;
511 bool smooth_after(const Tuple& t) override;
512
515 bool edge_is_input(const size_t eid) const
516 {
517 return m_edge_attribute[eid].m_is_surface_fs &&
518 m_edge_attribute[eid].m_surface_class == INPUT_SURFACE_CLASS;
519 }
520
530 bool vertex_is_frozen(const size_t vid) const
531 {
532 return m_vertex_extra[vid].m_is_on_input || !m_vertex_attribute[vid].on_bbox_faces.empty();
533 }
534 bool edge_is_frozen(const size_t eid) const
535 {
536 return edge_is_input(eid) || m_edge_attribute[eid].m_is_bbox_fs >= 0;
537 }
538
550
574
595
599 bool region_boundary_is_outside_envelope(const size_t vid) const;
600
612 {
613 std::atomic<int> attempted{0};
614 std::atomic<int> before_bbox{0};
615 std::atomic<int> before_unrounded{0};
616 std::atomic<int> before_on_input{0};
617 std::atomic<int> offset_attempted{0};
618 std::atomic<int> offset_no_neighbours{0};
619 std::atomic<int> offset_on_complex{0};
620 std::atomic<int> offset_inverted{0};
621 std::atomic<int> offset_envelope{0};
622 std::atomic<int> offset_accepted{0};
626 std::atomic<int> offset_clamped{0};
627 std::atomic<int> offset_clamp_env{0};
628 std::atomic<int> offset_clamp_inv{0};
633 std::atomic<int> offset_slid{0};
636 std::atomic<long long> offset_err_before_nano{0};
637 std::atomic<long long> offset_err_after_nano{0};
638 std::atomic<int> offset_err_max_before_nano{0};
639 std::atomic<int> offset_err_max_after_nano{0};
640 std::atomic<int> interior_attempted{0};
641 std::atomic<int> region_attempted{0};
642
643 void reset()
644 {
645 offset_err_before_nano.store(0);
646 offset_err_after_nano.store(0);
647 for (std::atomic<int>* c :
648 {&attempted,
657 &offset_accepted,
662 &offset_err_max_before_nano,
663 &offset_err_max_after_nano,
666 c->store(0);
667 }
668 }
669 };
670 SmoothTrace m_smooth_trace;
671 void log_smooth_trace() const;
672
674
686 std::shared_ptr<SampleEnvelope> surface_envelope_for_edge(
687 const std::array<size_t, 2>& vids) const override
688 {
689 const auto [t, eid] = tuple_from_edge(vids);
690 if (eid == static_cast<size_t>(-1) || !t.is_valid(*this)) {
691 // The segment does not exist yet -- an operation asking about one it is about to
692 // create. Answer with the envelope: containing a segment that turns out not to be a
693 // region boundary only ever costs a rejected operation, while missing one that is
694 // lets a region drift.
695 return m_envelope;
696 }
697 // LIVE, not edge_is_region_boundary(eid): this is called from inside the very
698 // split/collapse/swap passes that create the segment being asked about, well before the
699 // next label_offset_boundary() would ever revisit its cached class. See
700 // edge_is_region_boundary_live()'s comment for the collapse case that motivated this.
701 return edge_is_region_boundary_live(t) ? m_envelope : nullptr;
702 }
703
706 bool smoothing_position_is_allowed(size_t vid, const Vector2d&) const override
707 {
708 return !m_vertex_extra[vid].m_is_on_input;
709 }
710
720 size_t refine_sizing_around_worst(double) override { return update_sizing_field(); }
721 size_t update_sizing_field();
722 void write_smoothing_debug_output(const std::string& path) const override
723 {
724 const_cast<TopoOffsetTriMesh*>(this)->write_vtu(path);
725 }
726
727
736 void init_from_image(
737 const MatrixXd& V,
738 const MatrixXi& F,
739 const MatrixSi& F_tags,
740 const MatrixXd& V_env,
741 const MatrixXi& F_env,
742 const std::vector<std::string>& tag_names);
743
747 bool ambient_assert();
748
752 void label_input_complex();
753
758 bool empty_input_complex();
759
764
766 bool split_edge_before(const Tuple& t) override;
767 bool split_edge_after(const Tuple& t) override;
768 bool split_face_before(const Tuple& t) override;
769 bool split_face_after(const Tuple& t) override;
770 bool invariants(const std::vector<Tuple>& tris) override;
772
776 void execute_offset(const std::filesystem::path& output_file);
777
788 void marching_tris();
789
790
792
796 bool is_simplicially_embedded() const;
797
802 bool tri_is_simp_emb(const Tuple& t) const;
803
809
810 // variable offset stuff
811
815 bool tag_tri_consistent_topology(size_t f_id, int64_t tag) const;
816
821 bool offset_tri_consistent_topology(const size_t f_id) const;
822
827 bool tri_is_in_offset_conservative(const size_t f_id, const double threshold_r) const;
828
835
840 void set_offset_tri_tags();
841
846 bool offset_is_manifold();
847
849 void write_input_complex(const std::string& path);
850 void write_vtu(const std::string& path);
851 // void write_msh(const std::string& file);
852 void write_msh_groups(const std::string& file);
854
855private:
862 {
863 size_t v1_id;
864 size_t v2_id;
865 Vector2d new_v_pos;
866 VertexExtra2d new_v_extra;
867
868 // cache edge attributes
869 EdgeSnapshot2d split_eattr;
870 std::map<simplex::Edge, EdgeSnapshot2d> existing_eattr;
871
872 // cache face attributes
873 std::map<size_t, FaceSnapshot2d> opp_v_fattr;
874 };
876
878 {
879 size_t v1_id;
880 size_t v2_id;
881 size_t v3_id;
882 Vector2d new_v_pos;
883 VertexExtra2d new_v_extra;
884
885 std::map<simplex::Edge, EdgeSnapshot2d> existing_eattr; // 3 orig edges
886 FaceSnapshot2d split_fattr; // split face attributes
887 };
889
890private: // helpers
894 bool any_tag_present(const CellTag& tag1, const CellTag& tag2) const
895 {
896 for (const int64_t& i : tag1) {
897 if (tag2.find(i) != tag2.end()) {
898 return true;
899 }
900 }
901 return false;
902
903 // if (tag2.empty()) {
904 // return tag1.empty();
905 // }
906 // if (tag1.empty()) { // tag1 is ambient and tag2 is not
907 // return false;
908 // }
909
910 // for (const int64_t& i : tag1) {
911 // if (tag2.find(i) != tag2.end()) {
912 // return true;
913 // }
914 // }
915 // return false;
916 }
917
921 void sort_edges_by_length(std::vector<simplex::Edge>& edges)
922 {
923 std::sort(
924 edges.begin(),
925 edges.end(),
926 [this](const simplex::Edge& e1, const simplex::Edge& e2) {
927 double len1 = (m_vertex_attribute[e1.vertices()[0]].m_posf -
928 m_vertex_attribute[e1.vertices()[1]].m_posf)
929 .squaredNorm();
930 double len2 = (m_vertex_attribute[e2.vertices()[0]].m_posf -
931 m_vertex_attribute[e2.vertices()[1]].m_posf)
932 .squaredNorm();
933 return len1 > len2;
934 });
935 }
936
937public: // helpers
941 size_t edge_id_from_simplex(const simplex::Edge& e) const
942 {
943 const auto& verts = e.vertices();
944 const auto incident = simplex_incident_triangles(e);
945 const auto& faces = incident.faces();
946
947 assert(!faces.empty()); // throw error here otherwise
948
949 const size_t f_id = tuple_from_simplex(faces.front()).fid(*this);
950 const Tuple t_edge = tuple_from_edge(verts[0], verts[1], f_id);
951 return t_edge.eid(*this);
952 }
953
958 {
959 const auto& v = e.vertices();
960 const auto faces = simplex_incident_triangles(e).faces();
961 assert(!faces.empty());
962 const size_t fid = tuple_from_simplex(faces.front()).fid(*this);
963 return tuple_from_edge(v[0], v[1], fid);
964 }
965
969 std::vector<Tuple> get_edge_adjacent_faces(const Tuple& f) const
970 {
971 std::vector<Tuple> adj_tris;
972 auto tri_1 = f.switch_face(*this);
973 if (tri_1) {
974 adj_tris.push_back(tri_1.value());
975 }
976 auto tri_2 = f.switch_edge(*this).switch_face(*this);
977 if (tri_2) {
978 adj_tris.push_back(tri_2.value());
979 }
980 auto tri_3 = f.switch_vertex(*this).switch_edge(*this).switch_face(*this);
981 if (tri_3) {
982 adj_tris.push_back(tri_3.value());
983 }
984 return adj_tris;
985 }
986};
987
988
989} // namespace wmtk::components::topological_offset
Whether a codimension-1 simplex is tracked surface, and which bbox side it lies on.
Definition SurfaceTagAttributes.h:15
Definition TriMesh.h:31
size_t fid(const TriMesh &) const
Definition TriMesh.h:79
Tuple switch_vertex(const TriMesh &m) const
Definition TriMesh.cpp:158
Tuple switch_edge(const TriMesh &m) const
Definition TriMesh.cpp:187
std::optional< Tuple > switch_face(const TriMesh &m) const
Definition TriMesh.cpp:214
Tuple tuple_from_edge(size_t vid1, size_t vid2, size_t fid) const
Definition TriMesh.cpp:2204
What triwild and simwild's 2D mesh share.
Definition TriOptimizerMesh.h:38
AttributeContainerGroup m_edge_attr_group
What p_edge_attrs points at, so a derived class can register more.
Definition TriOptimizerMesh.h:110
AttributeContainerGroup m_vertex_attr_group
What p_vertex_attrs points at, so a derived class can register more.
Definition TriOptimizerMesh.h:95
AttributeContainerGroup m_face_attr_group
What p_face_attrs points at, so a derived class can register more.
Definition TriOptimizerMesh.h:121
Definition TopoOffsetTriMesh.h:53
Definition TopoOffsetTriMesh.h:62
The offset's 2D mesh, on the shared 2D optimizer.
Definition TopoOffsetTriMesh.h:84
std::pair< double, double > compute_distance_deviation() const
How far the offset boundary is from where it should be: {max, avg} over vertices.
Definition Optimize2d.cpp:1024
void label_input_complex()
label input complex simplices as per boolean expression (or single body mode)
Definition TopoOffsetTriMesh.cpp:117
void set_vertex_position(const size_t vid, const Vector2d &p)
Place a vertex, keeping its exact and rounded coordinates in step.
Definition TopoOffsetTriMesh.h:161
Parameters & m_offset_params
The base holds only wmtk::OptimizerParameters; this is the same object, typed.
Definition TopoOffsetTriMesh.h:131
void init_from_image(const MatrixXd &V, const MatrixXi &F, const MatrixSi &F_tags, const MatrixXd &V_env, const MatrixXi &F_env, const std::vector< std::string > &tag_names)
initialize TriMesh from vertex, face, tag data
Definition TopoOffsetTriMesh.cpp:13
void init_region_boundary_envelope_from_input()
Build the same envelope from the INPUT mesh, before the offset exists.
Definition Optimize2d.cpp:255
bool split_face_before(const Tuple &t) override
User specified preparations and desideratas for a face split.
Definition EdgeSplittingTri.cpp:194
void set_offset_tri_tags()
update 'tags' data for triangles in the offset region (tris labelled 2) based on the given offset tag...
Definition TopoOffsetTriMesh.cpp:685
bool vertex_is_on_surface(const size_t vid) const override
The substructure the link condition is evaluated against, DERIVED not cached.
Definition Optimize2d.cpp:46
bool offset_is_manifold()
verify that the closed offset region (simplices labelled 1 or 2) form a manifold region....
Definition TopoOffsetTriMesh.cpp:720
void optimize_offset(const std::filesystem::path &output_file)
The 2D optimization phase: split / collapse / swap / smooth on the shared driver.
Definition Optimize2d.cpp:1298
double max_offset_normal_deviation_at_vertex(const size_t vid) const
Definition Optimize2d.cpp:1268
size_t m_worst_dist_vid
Definition TopoOffsetTriMesh.h:366
double minimize_distance_along_tangent(const size_t vid, const Vector2d &p0, const Vector2d &tang, const double cap, const std::function< bool()> &rejected)
Put a vertex at the distance-error minimum along its region tangent.
Definition Optimize2d.cpp:818
bool tag_tri_consistent_topology(size_t f_id, int64_t tag) const
check if removing the given face from the given tag set would retain its topology
Definition Spatial.cpp:335
bool edge_is_region_boundary_live(const Tuple &t) const
Live region-boundary test for an edge that currently exists in the mesh.
Definition TopoOffsetTriMesh.h:339
void grow_offset_conservative()
grow offset region conservatively using conservative checks while ensuring consistent topology
Definition TopoOffsetTriMesh.cpp:627
bool empty_input_complex()
check if the input complex is empty. Only valid after calling init_from_image(...)....
Definition TopoOffsetTriMesh.cpp:273
void init_input_complex_bvh()
initialize BVH for input complex. Must be called after init_from_image(...)
Definition TopoOffsetTriMesh.cpp:286
size_t edge_id_from_simplex(const simplex::Edge &e) const
get global id of edge from simplex::Edge object
Definition TopoOffsetTriMesh.h:941
bool face_is_offset_band(const size_t fid) const
Definition Optimize2d.cpp:1018
Tuple get_tuple_from_edge(const simplex::Edge &e) const
get Tuple simplex::Edge object
Definition TopoOffsetTriMesh.h:957
void marching_tris()
execute simplistic marching tris. All edges with one vertex labelled 0 and the other 1/2 are split,...
Definition TopoOffsetTriMesh.cpp:562
bool offset_field_normal(const Vector2d &p, Vector2d &n) const
Definition Optimize2d.cpp:1201
bool face_in_region(const size_t fid) const
Whether face fid belongs to the closed offset region, read from its LABEL.
Definition Optimize2d.cpp:56
void sort_edges_by_length(std::vector< simplex::Edge > &edges)
sort vector of edge simplices in place by decreasing length
Definition TopoOffsetTriMesh.h:921
bool swap_edge_after(const Tuple &t) override
Definition Optimize2d.cpp:350
double edge_normal_deviation(const Tuple &e) const
Paper Definition 5 for a 1-simplex: max angle between the offset normal at the edge's center and the ...
Definition Optimize2d.cpp:1215
void init_offset_sizing_field()
Definition Optimize2d.cpp:895
void warn_if_offset_reaches_domain_boundary() const
Warn if the offset band has grown into the domain boundary.
Definition Optimize2d.cpp:222
bool edge_is_offset_surface_live(const Tuple &e) const
Definition Optimize2d.cpp:1254
bool split_edge_after(const Tuple &t) override
User specified modifications and desideratas after an edge split.
Definition EdgeSplittingTri.cpp:123
bool invariants(const std::vector< Tuple > &tris) override
User specified invariants that can't be violated.
Definition TopoOffsetTriMesh.cpp:770
wmtk::threading::enumerable_thread_specific< double > m_collapse_nd_before
Definition TopoOffsetTriMesh.h:432
void execute_offset(const std::filesystem::path &output_file)
entry point for offset procedure
Definition TopoOffsetTriMesh.cpp:394
bool edge_is_input(const size_t eid) const
Definition TopoOffsetTriMesh.h:515
bool project_offset_vertex(const Tuple &t)
Definition Optimize2d.cpp:605
static constexpr int INPUT_SURFACE_CLASS
SurfaceTagAttributes::m_surface_class: which of the three tracked surfaces an edge belongs to.
Definition TopoOffsetTriMesh.h:126
bool smooth_before(const Tuple &t) override
User specified preparations and desideratas for an edge smooth.
Definition Optimize2d.cpp:524
std::shared_ptr< SampleEnvelope > surface_envelope_for_edge(const std::array< size_t, 2 > &vids) const override
Only REGION_SURFACE_CLASS segments carry a containment requirement.
Definition TopoOffsetTriMesh.h:686
wmtk::threading::enumerable_thread_specific< double > m_swap_nd_before
Definition TopoOffsetTriMesh.h:436
bool split_edge_before(const Tuple &t) override
User specified preparations and desideratas for an edge split.
Definition EdgeSplittingTri.cpp:9
bool split_face_after(const Tuple &t) override
User specified modifications and desideratas after a face split.
Definition EdgeSplittingTri.cpp:226
std::pair< double, double > compute_normal_deviation() const
How far the offset boundary faces from where it should be: {max, avg} in DEGREES.
Definition Optimize2d.cpp:1279
bool smoothing_position_is_allowed(size_t vid, const Vector2d &) const override
Definition TopoOffsetTriMesh.h:706
bool edge_is_on_surface(const std::array< size_t, 2 > &vids) const override
Is an edge part of the substructure.
Definition Optimize2d.cpp:28
bool any_tag_present(const CellTag &tag1, const CellTag &tag2) const
determine if any tag from tag1 is also present in tag2.
Definition TopoOffsetTriMesh.h:894
std::atomic< int > iter_cnt_collapse_nd_reject
Definition TopoOffsetTriMesh.h:426
bool offset_tri_consistent_topology(const size_t f_id) const
check if adding a triangle to the offset region does not change the topology of the offset....
Definition Spatial.cpp:283
bool tri_is_in_offset_conservative(const size_t f_id, const double threshold_r) const
check if a triangle is inside the offset (implicitly defined via BVH distance field to input complex)...
Definition Spatial.cpp:242
void label_offset_boundary()
Tag the two tracked surfaces for the optimization phase.
Definition Optimize2d.cpp:66
void simplicial_embedding()
make mesh a simplicial embedding of the input complex (simplices labelled 1)
Definition TopoOffsetTriMesh.cpp:499
bool edge_is_offset(const size_t eid) const
Definition TopoOffsetTriMesh.h:170
bool swap_edge_before(const Tuple &t) override
Reject a flip whose new edge already exists.
Definition Optimize2d.cpp:178
bool face_is_input_complex(const size_t fid) const
Definition Optimize2d.cpp:61
void init_region_boundary_envelope()
Build the containment envelope over every tag-region boundary, once, before the optimization starts.
Definition Optimize2d.cpp:285
bool smooth_after(const Tuple &t) override
User specified modifications and desideras after an edge smooth.
Definition Optimize2d.cpp:548
bool collapse_edge_after(const Tuple &t) override
Definition Optimize2d.cpp:400
bool split_adjust_position(size_t v_new, const std::vector< Tuple > &children) override
Carry each parent's region label onto the two children it became.
Definition Optimize2d.cpp:486
std::vector< Tuple > get_edge_adjacent_faces(const Tuple &f) const
get faces (as Tuples) that are edge-adjacent to the given face (as Tuple)
Definition TopoOffsetTriMesh.h:969
std::vector< std::array< int, 3 > > op_counts
Definition TopoOffsetTriMesh.h:421
bool ambient_assert()
ensure ambient tag does not overlap any other tags in mesh.
Definition TopoOffsetTriMesh.cpp:103
bool vertex_is_frozen(const size_t vid) const
The two simplex sets the optimization may not touch at all.
Definition TopoOffsetTriMesh.h:530
bool is_simplicially_embedded() const
check if the input complex (simplices labelled 1) are simplicially embedded w.r.t....
Definition TopoOffsetTriMesh.cpp:454
bool collapse_edge_before(const Tuple &t) override
Reject any collapse that violates the substructure link condition.
Definition Optimize2d.cpp:373
bool region_boundary_tangent(const Tuple &t, Vector2d &tang) const
The direction the REGION curve runs through this vertex, if it has one.
Definition Optimize2d.cpp:784
bool tri_is_simp_emb(const Tuple &t) const
check if a triangle satisfies simpicial embedding criteria w.r.t. input complex (simplices labelled 1...
Definition TopoOffsetTriMesh.cpp:473
bool region_boundary_is_outside_envelope(const size_t vid) const
Definition Optimize2d.cpp:328
std::vector< std::array< double, 4 > > optimization_metrics
Definition TopoOffsetTriMesh.h:415
size_t refine_sizing_around_worst(double) override
Sizing refinement over the offset polyline.
Definition TopoOffsetTriMesh.h:720
Per-vertex data the shared 2D optimizer knows nothing about.
Definition TopoOffsetTriMesh.h:41
Definition Simplex.hpp:46
Definition enumerable_thread_specific.hpp:26
Definition TriOptimizerMesh.h:73
What the offset needs on top of the parameters every wmtk optimizer shares.
Definition Parameters.h:25
An edge's / face's shared attributes together with the offset's own label.
Definition TopoOffsetTriMesh.h:187
Why smoothing refused a vertex, one counter per site where it can say no.
Definition TopoOffsetTriMesh.h:612
std::atomic< long long > offset_err_before_nano
Definition TopoOffsetTriMesh.h:636
std::atomic< int > offset_no_neighbours
no offset-boundary neighbour to average
Definition TopoOffsetTriMesh.h:618
std::atomic< int > offset_clamp_env
... and the envelope is what stopped it
Definition TopoOffsetTriMesh.h:627
std::atomic< int > offset_attempted
dispatched to project_offset_vertex()
Definition TopoOffsetTriMesh.h:617
std::atomic< int > interior_attempted
dispatched to the shared AMIPS smoother
Definition TopoOffsetTriMesh.h:640
std::atomic< int > offset_envelope
search exhausted, still outside the envelope
Definition TopoOffsetTriMesh.h:621
std::atomic< int > offset_clamped
accepted with the search fraction < 0.99
Definition TopoOffsetTriMesh.h:626
std::atomic< int > attempted
smooth_before() entered
Definition TopoOffsetTriMesh.h:613
std::atomic< int > region_attempted
... of which sat on another region's boundary
Definition TopoOffsetTriMesh.h:641
std::atomic< int > offset_clamp_inv
Definition TopoOffsetTriMesh.h:628
std::atomic< int > offset_on_complex
sits on the complex, no offset direction
Definition TopoOffsetTriMesh.h:619
std::atomic< int > before_on_input
input complex, frozen
Definition TopoOffsetTriMesh.h:616
std::atomic< int > offset_slid
Definition TopoOffsetTriMesh.h:633
std::atomic< int > before_unrounded
base smooth_before said no: could not round
Definition TopoOffsetTriMesh.h:615
std::atomic< int > before_bbox
base smooth_before said no: on the bounding box
Definition TopoOffsetTriMesh.h:614
std::atomic< int > offset_inverted
search exhausted, a face still inverts
Definition TopoOffsetTriMesh.h:620