Wildmeshing Toolkit
Loading...
Searching...
No Matches
TopoOffsetTetMesh.h
1#pragma once
2
3#include <wmtk/TetMesh.h>
4#include <wmtk/TetOptimizerMesh.h>
5#include <wmtk/envelope/Envelope.hpp>
6#include <wmtk/optimization/solver.hpp>
7#include <wmtk/simplex/Simplex.hpp>
8#include <wmtk/threading/enumerable_thread_specific.hpp>
9#include "Parameters.h"
10#include "SimplicialComplexBVH.hpp"
11
12// clang-format off
13#include <wmtk/utils/DisableWarnings.hpp>
14#include <wmtk/utils/EnableWarnings.hpp>
15// clang-format on
16
17using CellTag = std::set<int64_t>;
18
19
20namespace wmtk::components::topological_offset {
21
22
23const int64_t TEMP_OFFSET_TET_TAG = -1;
24const CellTag TEMP_OFFSET_TET_TAG_SET{TEMP_OFFSET_TET_TAG};
25
26
27// for all attributes:
28// label: 0=default, 1=input, 2=offset
29
42{
43public:
44 int label = 0;
45 size_t component_id = 0;
46 bool m_is_on_input = false; // is this vertex on the input complex
47 bool m_is_on_offset = false; // is this vertex on the offset surface
48};
49
50
52{
53public:
54 int label = 0; // label: 0=default, 1=input, 2=offset
55};
56
57
72{
73public:
74 int label = 0; // label: 0=default, 1=input, 2=offset
75};
76
77
79{
80public:
81 int label = 0; // label: 0=default, 1=input, 2=offset
82 CellTag tag;
83 double m_quality = 0; // AMIPS energy, kept up to date by smoothing
84};
85
86
96{
97 Vector3d point; // the sample point, on (or near a corner of) the face
98 Vector3d nearest; // nearest point on the input complex to `point`
99 Vector3d normal; // (point - nearest).normalized()
100 double weight; // 1 for the face centroid, 0.1 for the 3 near-corner samples
101};
102
103
120{
121public:
128 static constexpr int OFFSET_SURFACE_CLASS = 1;
129
130public: // mode for splitting in marching tets
131 enum class EdgeSplitMode {
132 Midpoint = 0, // used for simplicial embedding steps
133 Initial = 1, // this is used to initialize the complex. Its a little hacky
134
135 // only one of these is used, hard coded in execute_offset()
136 BinarySearch = 2, // bisection root finding algo
137 LogRootFind = 3, // 'custom' root finding, using the fact that d(x) - d* < 0 at first vertex
138 SphereTracing = 4, // use sphere tracing to compute the zero of the distance field
139
140 Optimization = 5 // this is used in the optimization phase of the algorithm
141 };
142
143public:
144 int m_vtu_counter = 0;
145 std::array<size_t, 4> m_init_counts = {{0, 0, 0, 0}};
146 size_t m_tags_count;
147 SimplicialComplexBVH m_input_complex_bvh;
148 EdgeSplitMode m_edge_split_mode = EdgeSplitMode::Midpoint;
149
150 // tag map stuff
151 std::map<std::string, int64_t> m_tag_name_to_id;
152 std::map<int64_t, std::string> m_tag_id_to_name;
153 CellTag m_offset_output_tag_ids;
154
155 // if in 'singlebody' mode
156 bool m_singlebody = false;
157 int64_t m_single_tag;
158
159 // dont actually use, just for retaining in output
160 bool m_has_envelope;
161 std::vector<Vector3d> m_V_envelope;
162 std::vector<Vector3i> m_F_envelope;
163 // m_envelope itself lives on the base, which is what checks tracked-surface triangles
164 // against it.
165 double m_envelope_eps = -1;
166
170
175 // m_vertex_attribute and m_face_attribute are the base's; these two are registered
176 // alongside them in its attribute groups.
177 VertexExtraCol m_vertex_extra;
178 FaceExtraCol m_face_extra;
179 EdgeAttCol m_edge_attribute;
180 TetAttCol m_tet_attribute;
181
189 {
190 FaceAttributes tags;
191 FaceExtra extra;
192 };
193 FaceSnapshot face_snapshot(const size_t fid) const
194 {
195 return FaceSnapshot{m_face_attribute[fid], m_face_extra[fid]};
196 }
197 void restore_face(const size_t fid, const FaceSnapshot& s)
198 {
199 m_face_attribute[fid] = s.tags;
200 m_face_extra[fid] = s.extra;
201 }
202
217 void set_vertex_position(const size_t vid, const Vector3d& p)
218 {
219 m_vertex_attribute[vid].m_posf = p;
220 m_vertex_attribute[vid].m_pos = to_rational(p);
221 m_vertex_attribute[vid].m_is_rounded = true;
222 }
223
234 bool cell_in_region(const size_t tid) const
235 {
236 const CellTag& tags = m_tet_attribute[tid].tag;
237 for (const int64_t t : m_offset_output_tag_ids) {
238 if (tags.count(t) != 0) return true; // in the offset band
239 }
240 const ExpressionPtr& expr = m_offset_params.offset_selection;
241 return expr && expr->eval(tags); // in the input complex it wraps
242 }
243
245 bool face_is_offset(const size_t fid) const
246 {
247 return m_face_attribute[fid].m_is_surface_fs &&
248 m_face_attribute[fid].m_surface_class == OFFSET_SURFACE_CLASS;
249 }
251 bool face_is_input(const size_t fid) const
252 {
253 return m_face_attribute[fid].m_is_surface_fs &&
254 m_face_attribute[fid].m_surface_class != OFFSET_SURFACE_CLASS;
255 }
256
257 // debug use
258 std::atomic<int> cnt_split = 0, cnt_collapse = 0;
259
260 TopoOffsetTetMesh(Parameters& _m_offset_params, int _num_threads = 0)
261 : wmtk::TetOptimizerMesh(_m_offset_params, nullptr)
262 , m_offset_params(_m_offset_params)
263 {
264 NUM_THREADS = _num_threads;
265 // The base owns the vertex and face slots; register the offset's own data with its
266 // groups so it is resized, protected and rolled back with them.
267 m_vertex_attr_group.add(&m_vertex_extra);
268 m_face_attr_group.add(&m_face_extra);
269 p_edge_attrs = &m_edge_attribute;
270 p_tet_attrs = &m_tet_attribute;
271
272 m_collapse_check_link_condition = false;
273 m_collapse_check_manifold = false;
274
275 optimization::deactivate_opt_logger();
276 }
277
278 ~TopoOffsetTetMesh() override = default;
279
281
282 double cell_quality(const size_t tid) const override { return m_tet_attribute[tid].m_quality; }
283 void set_cell_quality(const size_t tid, const double q) override
284 {
285 m_tet_attribute[tid].m_quality = q;
286 }
287
297 std::shared_ptr<SampleEnvelope> surface_envelope_for_face(
298 const std::array<size_t, 3>& vids) const override
299 {
300 for (const size_t v : vids) {
301 if (!m_vertex_extra[v].m_is_on_input) return nullptr;
302 }
303 return m_envelope;
304 }
305
310 bool allow_surface_swap() const override { return true; }
311 bool check_surface_topology() const override { return m_offset_params.perform_sanity_checks; }
312
316 std::shared_ptr<SampleEnvelope> smoothing_energy_envelope(const size_t) const override
317 {
318 return nullptr;
319 }
320
321 void write_optimization_debug_output(const std::string& path) override { write_vtu(path); }
322
330 size_t refine_sizing_around_worst(double) override { return update_sizing_field(); }
331
344 bool swap_before_interior(const std::vector<size_t>& tids) override;
345 bool swap_before_surface(
346 const std::vector<size_t>& tids,
347 size_t a,
348 size_t b,
349 size_t c,
350 size_t d) override;
351 bool swap_after_cells(const std::vector<size_t>& tids, bool is_surface_flip) override;
352
362 bool collapse_edge_before(const Tuple& t) override;
363 bool collapse_before_vertex(size_t v1, size_t v2, double edge_length) override;
364 bool collapse_after_connectivity(
365 size_t v1,
366 size_t v2,
367 const std::vector<std::array<size_t, 2>>& boundary_edges) override;
368 bool collapse_is_order_2_edge(const std::array<size_t, 2>& e) override
369 {
370 return is_order_2_edge(e);
371 }
372 void collapse_after_vertex(size_t v1, size_t v2) override;
373
381 bool split_before_cells(const Tuple& edge, const std::vector<Tuple>& parents) override;
382 bool split_after_cells(size_t v1, size_t v2, size_t v_new, const std::vector<Tuple>& children)
383 override;
384 void split_after_vertex(size_t v_new, bool is_edge_open_boundary) override;
385
388 bool is_open_boundary_edge(const Tuple& e) override { return is_order_2_edge(e); }
389
390private:
394 {
395 bool is_edge_on_input = false;
396 bool is_edge_on_offset = false;
397 std::map<simplex::Edge, TetAttributes> tets;
398 };
400
401public:
402private:
405
406public:
407private:
408 bool swap_capture_tag(const std::vector<size_t>& tids);
411
412public:
421 void init_from_image(
422 const MatrixXd& V,
423 const MatrixXi& T,
424 const MatrixSi& T_tags,
425 const MatrixXd& V_env,
426 const MatrixXi F_env,
427 const std::vector<std::string>& tag_names);
428
429 void init_surfaces_and_boundaries();
430
433 bool is_edge_on_input(const Tuple& loc);
434 bool is_edge_on_offset(const Tuple& loc);
435
439 bool ambient_assert();
440
445 void label_input_complex();
446
451 bool empty_input_complex();
452
457
464 void edge_split_binary_search(const size_t v1, const size_t v2, Vector3d& p_new) const;
465 void edge_split_binary_search(const Vector3d& v1_pos, const Vector3d& v2_pos, Vector3d& p_new)
466 const;
467
473 void edge_split_log_root_find(const size_t v1, const size_t v2, Vector3d& p_new) const;
474
480 void edge_split_sphere_tracing(const size_t v1, const size_t v2, Vector3d& p_new) const;
481
485 size_t flood_fill();
486
487 std::vector<std::array<size_t, 3>> get_faces_by_condition(
488 std::function<bool(const FaceAttributes&)> cond) const;
489
493 bool split_edge_before(const Tuple& t) override;
494 bool split_edge_after(const Tuple& t) override;
495 bool marching_split_edge_before(const Tuple& t);
496 bool marching_split_edge_after(const Tuple& t);
497 bool split_face_before(const Tuple& t) override;
498 bool split_face_after(const Tuple& t) override;
499 bool split_tet_before(const Tuple& t) override;
500 bool split_tet_after(const Tuple& t) override;
501 bool invariants(const std::vector<Tuple>& tets) override;
504 bool smooth_before(const Tuple& t) override;
505 bool smooth_after(const Tuple& t) override;
507
511 void execute_offset(const std::filesystem::path& output_file);
512
516 void optimize_offset(const std::filesystem::path& output_file);
517
519
524 bool is_offset_face(const Tuple& f) const;
525 bool is_offset_face(const size_t fid) const;
526
530 std::vector<Tuple> get_offset_surface_faces_for_vertex(const Tuple& t) const;
531
542 std::array<OffsetSurfaceSample, 4> offset_surface_samples(const Tuple& f) const;
543
551 bool smooth_after_offset_surface(const Tuple& t);
553
555
556 // max angle (degrees, 0-90, orientation independent) allowed between an offset-surface
557 // face's own normal and the input-complex normal it is supposed to approximate, checked by
558 // collapse_edge_before/after and offset_swap_normal_deviation_ok(). Exposed to the user as
559 // /max_normal_deviation_deg (see Parameters::max_normal_deviation_deg). See
560 // face_normal_deviation() and
561 // https://github.com/wildmeshing/topological-offsets/blob/main/components/topological_offsets/wmtk/components/topological_offsets/internal/invariants/NormalDeviationAfterInvariant.cpp
562 // and .../invariants/OffsetCollapseBeforeInvariant.cpp
563 double m_max_normal_deviation_swap_max_deg = 75.0;
564
574 double face_normal_deviation(const Tuple& f) const;
575
579 double max_offset_surface_normal_deviation_at_vertex(size_t vid) const;
580
592 double collapse_normal_deviation(size_t v_from, size_t v_to, size_t remove_vid) const;
594
595
597 // Bounds and thresholds for the sizing field are user-configurable; see
598 // Parameters::min_sizing_scalar / max_sizing_scalar / sizing_mrm_threshold /
599 // sizing_gradation. Refinement stops at min_sizing_scalar; coarsening never exceeds
600 // max_sizing_scalar (default: the base target itself, since a sizing_scalar > 1 would mean
601 // "coarser than what the user asked for", which update_sizing_field() never has a reason
602 // to produce).
603
609 static double mean_ratio_metric(const Vector3d& p0, const Vector3d& p1, const Vector3d& p2);
610
625 size_t update_sizing_field();
627
629
630
641 const Tuple& face_abc,
642 const Tuple& face_abd,
643 size_t a,
644 size_t b,
645 size_t c,
646 size_t d) const;
648
655 void marching_tets();
656
657
659
663 bool is_simplicially_embedded() const;
664
669 bool tet_is_simp_emb(const Tuple& t) const;
670
676
678
681 bool tag_tet_consistent_topology(size_t t_id, int64_t tag) const;
682
687 bool offset_tet_consistent_topology(const size_t t_id) const;
688
693 bool tet_is_in_offset_conservative(const size_t t_id, const double threshold_r) const;
694
699 bool tet_is_in_offset_aggressive(const size_t t_id) const;
700
706
713
718 void set_offset_tet_tags();
719
726 bool offset_is_manifold();
727
729 void write_input_complex(const std::string& path); // write components labeled to be offset
730 void write_vtu(const std::string& path);
731 // void write_msh(const std::string& file);
732 void write_msh_groups(const std::string& file);
734
735private:
742 {
743 size_t v1_id;
744 size_t v2_id;
745 // The marching-tets placement and the offset's own data for the new vertex. The
746 // shared attributes (position, rounding, bbox, order) are written in `after`.
747 Vector3d new_v_pos;
748 VertexExtra new_v_extra;
749
750 bool is_edge_on_input = false;
751 bool is_edge_on_offset = false;
752 bool is_edge_open_boundary = false;
753
754 std::vector<std::pair<FaceAttributes, std::array<size_t, 3>>> changed_faces;
755
756 // cache edge attributes
757 EdgeAttributes split_e;
758 std::map<size_t, EdgeAttributes> internal_e;
759 std::map<simplex::Edge, EdgeAttributes> external_e; // edge is boundary edge (not link)
760 std::map<simplex::Edge, EdgeAttributes> link_e; // link edge around splitted edge
761
762 // cache face attributes
763 std::map<size_t, FaceSnapshot> split_f; // splitted faces
764 std::map<simplex::Edge, FaceSnapshot> internal_f; // new faces created by split
765 std::map<std::pair<simplex::Edge, size_t>, FaceSnapshot>
766 external_f; // closed star boundary faces of splitted edge
767
768 // cache tet attributes
769 std::map<simplex::Edge, TetAttributes> tets;
770 };
772
774 {
775 size_t v1_id;
776 size_t v2_id;
777 size_t v3_id;
778
779 // cache edge attributes
780 std::map<simplex::Edge, EdgeAttributes> existing_e;
781
782 // cache face attributes
783 std::map<simplex::Face, FaceSnapshot> existing_f;
784 int splitf_label;
785
786 // cache tet attributes
787 std::map<size_t, TetAttributes> tets;
788 };
790
792 {
793 std::array<size_t, 4> v_ids;
794
795 // cache retained edge attributes
796 std::map<simplex::Edge, EdgeAttributes> existing_e;
797
798 // cache retained face attributes
799 std::map<simplex::Face, FaceSnapshot> existing_f;
800
801 // cache tet attribute
802 TetAttributes tet;
803 };
805
806
807public:
808 // substructure functions
809
810 bool is_order_2_edge(const Tuple& e) const;
811 bool is_order_2_edge(const std::array<size_t, 2>& e) const;
812
813 bool vertex_is_on_surface(const size_t vid) const override;
814
815 bool face_is_on_surface(const size_t fid) const override;
816
817 size_t get_order_of_vertex(const size_t vid) const override;
821 void init_vertex_order();
822
823private: // helpers
829 bool any_tag_present(const CellTag& tag1, const CellTag& tag2)
830 {
831 if (tag2.empty()) {
832 return tag1.empty();
833 }
834 if (tag1.empty()) { // tag1 is ambient, tag2 is not
835 return false;
836 }
837
838 for (const int64_t& i : tag1) {
839 if (tag2.find(i) != tag2.end()) {
840 return true;
841 }
842 }
843 return false;
844 }
845
849 void sort_edges_by_length(std::vector<simplex::Edge>& edges)
850 {
851 std::sort(
852 edges.begin(),
853 edges.end(),
854 [this](const simplex::Edge& e1, const simplex::Edge& e2) {
855 double len1 = (m_vertex_attribute[e1.vertices()[0]].m_posf -
856 m_vertex_attribute[e1.vertices()[1]].m_posf)
857 .norm();
858 double len2 = (m_vertex_attribute[e2.vertices()[0]].m_posf -
859 m_vertex_attribute[e2.vertices()[1]].m_posf)
860 .norm();
861 return len1 > len2;
862 });
863 }
864
865public: // helpers
872
873 size_t get_partition_id(const Tuple& loc) const
874 {
875 return m_vertex_attribute[loc.vid(*this)].partition_id;
876 }
877
881 std::vector<Tuple> get_face_adjacent_tets(const Tuple& t) const
882 {
883 std::vector<Tuple> adj_tets;
884 auto tet_1 = t.switch_tetrahedron(*this);
885 if (tet_1) {
886 adj_tets.push_back(tet_1.value());
887 }
888 auto tet_2 = t.switch_face(*this).switch_tetrahedron(*this);
889 if (tet_2) {
890 adj_tets.push_back(tet_2.value());
891 }
892 auto tet_3 = t.switch_edge(*this).switch_face(*this).switch_tetrahedron(*this);
893 if (tet_3) {
894 adj_tets.push_back(tet_3.value());
895 }
896 auto tet_4 =
897 t.switch_vertex(*this).switch_edge(*this).switch_face(*this).switch_tetrahedron(*this);
898 if (tet_4) {
899 adj_tets.push_back(tet_4.value());
900 }
901 return adj_tets;
902 }
903
907 std::vector<size_t> connected_components_helper(const size_t& v_id)
908 {
909 auto onering_v_ids = get_one_ring_vids_for_vertex(v_id);
910 std::vector<size_t> ret_v_ids;
911 for (const size_t& other_v_id : onering_v_ids) {
912 size_t e_id = tuple_from_edge({{v_id, other_v_id}}).eid(*this);
913 if (m_edge_attribute[e_id].label != 0) { // edge labelled 1 or 2
914 ret_v_ids.push_back(other_v_id);
915 }
916 }
917 return ret_v_ids;
918 }
919
924 {
925 auto verts = get_vertices();
926 for (const Tuple& v : verts) {
927 size_t v_id = v.vid(*this);
928 m_vertex_extra[v_id].component_id = 0;
929 }
930 }
931};
932
933
934} // namespace wmtk::components::topological_offset
Whether a codimension-1 simplex is tracked surface, and which bbox side it lies on.
Definition SurfaceTagAttributes.h:15
a Tuple refers to a global vid and a global tet id, and a local edge id and local face id
Definition TetMesh.h:49
std::vector< size_t > get_one_ring_vids_for_vertex(size_t vid, std::vector< size_t > &cache)
Get the one ring vids for vertex.
Definition TetMesh.cpp:835
Tuple tuple_from_edge(size_t tid, int local_eid) const
get a Tuple from global tetra index and local edge index (from 0-5).
Definition TetMesh.cpp:377
std::vector< Tuple > get_vertices() const
Definition TetMesh.cpp:346
What tetwild and simwild's 3D mesh share.
Definition TetOptimizerMesh.h:45
AttributeContainerGroup m_vertex_attr_group
What p_vertex_attrs points at, so a derived class can register more.
Definition TetOptimizerMesh.h:92
AttributeContainerGroup m_face_attr_group
What p_face_attrs points at, so a derived class can register more.
Definition TetOptimizerMesh.h:107
std::shared_ptr< SampleEnvelope > m_envelope
Surface envelope: what a surface vertex is pulled toward and checked against.
Definition TetOptimizerMesh.h:124
Per-face data the shared optimizer knows nothing about.
Definition TopoOffsetTetMesh.h:72
The offset's tet mesh, on the shared 3D optimizer.
Definition TopoOffsetTetMesh.h:120
bool is_edge_on_input(const Tuple &loc)
Definition TopoOffsetTetMesh.cpp:195
std::vector< Tuple > get_face_adjacent_tets(const Tuple &t) const
get tets (as Tuples) that are face-adjacent to the given tet (as Tuple)
Definition TopoOffsetTetMesh.h:881
bool split_edge_after(const Tuple &t) override
This function computes the attributes for the added simplices. User specified modifications and desid...
Definition EdgeSplittingTet.cpp:286
size_t refine_sizing_around_worst(double) override
The offset's sizing refinement, as the base's stall escape hatch.
Definition TopoOffsetTetMesh.h:330
void grow_offset_aggressive()
Grow offset region aggressively. A tet is considered in the offset if all its vertices are in the off...
Definition TopoOffsetTetMesh.cpp:1238
bool offset_swap_normal_deviation_ok(const Tuple &face_abc, const Tuple &face_abd, size_t a, size_t b, size_t c, size_t d) const
OffsetSwapInvariant analogue: for the offset-surface diagonal flip (a,b) -> (c,d) across the two curr...
Definition Swap.cpp:98
void edge_split_log_root_find(const size_t v1, const size_t v2, Vector3d &p_new) const
uses custom root finding routine, attempting to find first root (nearest to v1) to split edge at
Definition EdgeSplittingTet.cpp:42
bool is_offset_face(const Tuple &f) const
true if face f has exactly one incident tet labelled 2 (offset), i.e. it lies on the boundary between...
Definition Smooth.cpp:44
bool face_is_input(const size_t fid) const
Whether face fid carries input-complex geometry.
Definition TopoOffsetTetMesh.h:251
void sort_edges_by_length(std::vector< simplex::Edge > &edges)
sort edge simplices in place by decreasing edge length
Definition TopoOffsetTetMesh.h:849
bool tet_is_in_offset_conservative(const size_t t_id, const double threshold_r) const
check if a tet is inside the offset (implicitly defined via BVH distance field to input complex) via ...
Definition Spatial.cpp:11
size_t get_order_of_vertex(const size_t vid) const override
Get the order of a vertex.
Definition TopoOffsetTetMesh.cpp:718
void reset_connected_components()
reset connected component assignments.
Definition TopoOffsetTetMesh.h:923
void edge_split_binary_search(const size_t v1, const size_t v2, Vector3d &p_new) const
split edge at point by minimizing m_offset_params.target_distance - d() (where d() is distance to inp...
Definition EdgeSplittingTet.cpp:14
size_t flood_fill()
label connected simplicial complex components (simplices labelled 1 or 2)
Definition TopoOffsetTetMesh.cpp:652
void init_from_image(const MatrixXd &V, const MatrixXi &T, const MatrixSi &T_tags, const MatrixXd &V_env, const MatrixXi F_env, const std::vector< std::string > &tag_names)
initialize TetMesh from vertex, tet, and tag data
Definition TopoOffsetTetMesh.cpp:30
bool split_after_cells(size_t v1, size_t v2, size_t v_new, const std::vector< Tuple > &children) override
Restore application cell data on the children made by a split.
Definition EdgeSplittingTet.cpp:654
bool cell_in_region(const size_t tid) const
Whether tet tid belongs to the closed offset region, read from its TAGS.
Definition TopoOffsetTetMesh.h:234
bool collapse_edge_before(const Tuple &t) override
Collapse policy that is the offset's own.
Definition Collapse.cpp:76
void marching_tets()
execute simplistic marching tets. All edges with one vertex labelled 0 and the other 1/2 are split....
Definition TopoOffsetTetMesh.cpp:1103
bool smooth_before(const Tuple &t) override
Definition Smooth.cpp:22
bool split_edge_before(const Tuple &t) override
Definition EdgeSplittingTet.cpp:122
void set_offset_tet_tags()
update 'tags' data for tets in the offset region (tets labelled 2) based on the given offset tag valu...
Definition TopoOffsetTetMesh.cpp:1300
bool split_tet_after(const Tuple &t) override
Compute the attributes for the added simplices.
Definition EdgeSplittingTet.cpp:576
bool face_is_on_surface(const size_t fid) const override
Is a face part of the substructure.
Definition TopoOffsetTetMesh.cpp:713
bool ambient_assert()
check that the ambient tag does not overlap with any other tags
Definition TopoOffsetTetMesh.cpp:249
void compute_vertex_partition()
assign each vertex a partition id (by spatial Morton order) for the parallel ExecutePass policies (kP...
Definition TopoOffsetTetMesh.cpp:737
void grow_offset_conservative()
grow offset region conservatively using conservative checks while ensuring consistent topology
Definition TopoOffsetTetMesh.cpp:1175
bool marching_split_edge_after(const Tuple &t)
Definition EdgeSplittingTet.cpp:294
bool face_is_offset(const size_t fid) const
Whether face fid is on the offset boundary (as opposed to the input complex).
Definition TopoOffsetTetMesh.h:245
bool split_face_before(const Tuple &t) override
User specified preparations and desideratas for a face split before changing the connectivity.
Definition EdgeSplittingTet.cpp:382
Parameters & m_offset_params
Definition TopoOffsetTetMesh.h:169
bool offset_is_manifold()
verify that the closed offset region (simplices labelled 1 or 2) form a manifold region....
Definition TopoOffsetTetMesh.cpp:1335
void init_vertex_order()
Compute the vertex order for every vertex.
Definition TopoOffsetTetMesh.cpp:723
double face_normal_deviation(const Tuple &f) const
max angle (degrees, 0-90, orientation independent) between offset-surface face f's own normal and any...
Definition Collapse.cpp:12
bool tag_tet_consistent_topology(size_t t_id, int64_t tag) const
check if removing the tet would change the topology of any label
Definition Spatial.cpp:142
static double mean_ratio_metric(const Vector3d &p0, const Vector3d &p1, const Vector3d &p2)
unsigned mean ratio metric of a triangle: 2*sqrt(3)*area / (sum of squared edge lengths)....
Definition TopoOffsetTetMesh.cpp:828
void execute_offset(const std::filesystem::path &output_file)
main function from which all others are called
Definition TopoOffsetTetMesh.cpp:773
bool is_simplicially_embedded() const
check if the input complex (simplices labelled 1) are simplicially embedded w.r.t....
Definition TopoOffsetTetMesh.cpp:964
bool any_tag_present(const CellTag &tag1, const CellTag &tag2)
determine if any tag from tag1 is also present in tag2.
Definition TopoOffsetTetMesh.h:829
std::shared_ptr< SampleEnvelope > smoothing_energy_envelope(const size_t) const override
Definition TopoOffsetTetMesh.h:316
void set_vertex_position(const size_t vid, const Vector3d &p)
Place a vertex, keeping its exact and rounded coordinates in step.
Definition TopoOffsetTetMesh.h:217
std::vector< size_t > connected_components_helper(const size_t &v_id)
get all one-ring vertices through input simplices (labelled 1)
Definition TopoOffsetTetMesh.h:907
bool collapse_before_vertex(size_t v1, size_t v2, double edge_length) override
Definition Collapse.cpp:88
bool tet_is_in_offset_aggressive(const size_t t_id) const
check if a tet is inside the offset (implicitly defined via BVH distance field to input complex) by c...
Definition Spatial.cpp:51
static constexpr int OFFSET_SURFACE_CLASS
SurfaceTagAttributes::m_surface_class for the offset boundary.
Definition TopoOffsetTetMesh.h:128
void simplicial_embedding()
make mesh a simplicial embedding of the input complex (simplices labelled 1)
Definition TopoOffsetTetMesh.cpp:1009
void init_input_complex_bvh()
initialize BVH for input complex. Must be called after init_from_image(...)
Definition TopoOffsetTetMesh.cpp:498
std::shared_ptr< SampleEnvelope > surface_envelope_for_face(const std::array< size_t, 3 > &vids) const override
Only the input complex is envelope-constrained.
Definition TopoOffsetTetMesh.h:297
bool allow_surface_swap() const override
Definition TopoOffsetTetMesh.h:310
bool is_open_boundary_edge(const Tuple &e) override
Definition TopoOffsetTetMesh.h:388
bool swap_before_interior(const std::vector< size_t > &tids) override
Which tag the tets a swap creates should carry.
Definition Swap.cpp:53
void label_input_complex()
label input simplicial complex simplices, as defined in m_offset_params.offset_selection
Definition TopoOffsetTetMesh.cpp:268
void split_after_vertex(size_t v_new, bool is_edge_open_boundary) override
Application metadata not represented by the shared vertex attributes.
Definition EdgeSplittingTet.cpp:675
double collapse_normal_deviation(size_t v_from, size_t v_to, size_t remove_vid) const
OffsetCollapseBeforeInvariant analogue: pools offset_surface_samples() normals from every offset-surf...
Definition Collapse.cpp:49
bool swap_capture_tag(const std::vector< size_t > &tids)
Definition Swap.cpp:19
bool tet_is_simp_emb(const Tuple &t) const
check if a tet satisfies simpicial embedding criteria w.r.t. input complex (simplices labelled 1)
Definition TopoOffsetTetMesh.cpp:981
double max_offset_surface_normal_deviation_at_vertex(size_t vid) const
max face_normal_deviation() over the offset-surface faces incident to vertex vid
Definition Collapse.cpp:40
bool invariants(const std::vector< Tuple > &tets) override
Definition TopoOffsetTetMesh.cpp:1377
bool offset_tet_consistent_topology(const size_t t_id) const
check if adding a tet to the offset region does not change the topology of the offset....
Definition Spatial.cpp:64
bool split_tet_before(const Tuple &t) override
User specified preparations and desideratas for a tet split before changing the connectivity.
Definition EdgeSplittingTet.cpp:539
std::array< OffsetSurfaceSample, 4 > offset_surface_samples(const Tuple &f) const
the 4 offset-field samples for face f (centroid + one near each corner), following Quadrics....
Definition Smooth.cpp:93
void optimize_offset(const std::filesystem::path &output_file)
optimize the offset
Definition TopoOffsetTetMesh.cpp:893
wmtk::threading::enumerable_thread_specific< double > m_collapse_nd_before
The worse of the two endpoints' offset-surface deviation before the collapse.
Definition TopoOffsetTetMesh.h:404
bool split_before_cells(const Tuple &edge, const std::vector< Tuple > &parents) override
Split policy that is the offset's own.
Definition EdgeSplittingTet.cpp:638
bool vertex_is_on_surface(const size_t vid) const override
Is a vertex part of the substructure.
Definition TopoOffsetTetMesh.cpp:708
bool empty_input_complex()
check if the input complex is empty. Only valid after calling init_from_image(...)....
Definition TopoOffsetTetMesh.cpp:485
void edge_split_sphere_tracing(const size_t v1, const size_t v2, Vector3d &p_new) const
split edge at first root of d(l) - d*, where d(l) is distance to input complex, using sphere tracing ...
Definition EdgeSplittingTet.cpp:84
bool split_face_after(const Tuple &t) override
Compute the attributes for the added simplices.
Definition EdgeSplittingTet.cpp:456
bool swap_after_cells(const std::vector< size_t > &tids, bool is_surface_flip) override
Propagate application data to the cells made by a successful topological swap.
Definition Swap.cpp:89
std::vector< Tuple > get_offset_surface_faces_for_vertex(const Tuple &t) const
offset-surface faces (see is_offset_face()) incident to vertex t
Definition Smooth.cpp:54
wmtk::threading::enumerable_thread_specific< CellTag > m_swap_tag
The tag swap_after_cells writes onto the tets the swap created, chosen in before.
Definition TopoOffsetTetMesh.h:410
double cell_quality(const size_t tid) const override
The quality of cell tid, and how to write it.
Definition TopoOffsetTetMesh.h:282
bool smooth_after(const Tuple &t) override
User specified modifications and desideratas for after smoothing a vertex.
Definition Smooth.cpp:33
size_t update_sizing_field()
refine or coarsen the sizing field (VertexAttributes::m_sizing_scalar) based on the mean ratio metric...
Definition TopoOffsetTetMesh.cpp:842
bool smooth_after_offset_surface(const Tuple &t)
quadrics-based smoothing step for offset surface vertices: blends a Laplacian step with a projection ...
Definition Smooth.cpp:122
Per-vertex data the shared optimizer knows nothing about.
Definition TopoOffsetTetMesh.h:42
Definition Simplex.hpp:46
Definition enumerable_thread_specific.hpp:26
one sample of the input complex's implicit offset field, taken near a point on an offset-surface face...
Definition TopoOffsetTetMesh.h:96
What the offset needs on top of the parameters every wmtk optimizer shares.
Definition Parameters.h:25
A face's shared surface tags together with the offset's own label.
Definition TopoOffsetTetMesh.h:189