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>
10#include "SimplicialComplexBVH.hpp"
13#include <wmtk/utils/DisableWarnings.hpp>
14#include <wmtk/utils/EnableWarnings.hpp>
17using CellTag = std::set<int64_t>;
20namespace wmtk::components::topological_offset {
23const int64_t TEMP_OFFSET_TET_TAG = -1;
24const CellTag TEMP_OFFSET_TET_TAG_SET{TEMP_OFFSET_TET_TAG};
45 size_t component_id = 0;
46 bool m_is_on_input =
false;
47 bool m_is_on_offset =
false;
131 enum class EdgeSplitMode {
144 int m_vtu_counter = 0;
145 std::array<size_t, 4> m_init_counts = {{0, 0, 0, 0}};
147 SimplicialComplexBVH m_input_complex_bvh;
148 EdgeSplitMode m_edge_split_mode = EdgeSplitMode::Midpoint;
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;
156 bool m_singlebody =
false;
157 int64_t m_single_tag;
161 std::vector<Vector3d> m_V_envelope;
162 std::vector<Vector3i> m_F_envelope;
165 double m_envelope_eps = -1;
195 return FaceSnapshot{m_face_attribute[fid], m_face_extra[fid]};
197 void restore_face(
const size_t fid,
const FaceSnapshot& s)
199 m_face_attribute[fid] = s.tags;
200 m_face_extra[fid] = s.extra;
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;
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;
241 return expr && expr->eval(tags);
247 return m_face_attribute[fid].m_is_surface_fs &&
253 return m_face_attribute[fid].m_is_surface_fs &&
258 std::atomic<int> cnt_split = 0, cnt_collapse = 0;
264 NUM_THREADS = _num_threads;
269 p_edge_attrs = &m_edge_attribute;
270 p_tet_attrs = &m_tet_attribute;
272 m_collapse_check_link_condition =
false;
273 m_collapse_check_manifold =
false;
275 optimization::deactivate_opt_logger();
278 ~TopoOffsetTetMesh()
override =
default;
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
285 m_tet_attribute[tid].m_quality = q;
298 const std::array<size_t, 3>& vids)
const override
300 for (
const size_t v : vids) {
301 if (!m_vertex_extra[v].m_is_on_input)
return nullptr;
311 bool check_surface_topology()
const override {
return m_offset_params.perform_sanity_checks; }
321 void write_optimization_debug_output(
const std::string& path)
override { write_vtu(path); }
345 bool swap_before_surface(
346 const std::vector<size_t>& tids,
351 bool swap_after_cells(
const std::vector<size_t>& tids,
bool is_surface_flip)
override;
364 bool collapse_after_connectivity(
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
370 return is_order_2_edge(e);
372 void collapse_after_vertex(
size_t v1,
size_t v2)
override;
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)
395 bool is_edge_on_input =
false;
396 bool is_edge_on_offset =
false;
397 std::map<simplex::Edge, TetAttributes> tets;
424 const MatrixSi& T_tags,
425 const MatrixXd& V_env,
426 const MatrixXi F_env,
427 const std::vector<std::string>& tag_names);
429 void init_surfaces_and_boundaries();
434 bool is_edge_on_offset(
const Tuple& loc);
487 std::vector<std::array<size_t, 3>> get_faces_by_condition(
495 bool marching_split_edge_before(
const Tuple& t);
501 bool invariants(
const std::vector<Tuple>& tets)
override;
563 double m_max_normal_deviation_swap_max_deg = 75.0;
609 static double mean_ratio_metric(
const Vector3d& p0,
const Vector3d& p1,
const Vector3d& p2);
641 const Tuple& face_abc,
642 const Tuple& face_abd,
729 void write_input_complex(
const std::string& path);
730 void write_vtu(
const std::string& path);
732 void write_msh_groups(
const std::string& file);
750 bool is_edge_on_input =
false;
751 bool is_edge_on_offset =
false;
752 bool is_edge_open_boundary =
false;
754 std::vector<std::pair<FaceAttributes, std::array<size_t, 3>>> changed_faces;
758 std::map<size_t, EdgeAttributes> internal_e;
759 std::map<simplex::Edge, EdgeAttributes> external_e;
760 std::map<simplex::Edge, EdgeAttributes> link_e;
763 std::map<size_t, FaceSnapshot> split_f;
764 std::map<simplex::Edge, FaceSnapshot> internal_f;
765 std::map<std::pair<simplex::Edge, size_t>,
FaceSnapshot>
769 std::map<simplex::Edge, TetAttributes> tets;
780 std::map<simplex::Edge, EdgeAttributes> existing_e;
783 std::map<simplex::Face, FaceSnapshot> existing_f;
787 std::map<size_t, TetAttributes> tets;
793 std::array<size_t, 4> v_ids;
796 std::map<simplex::Edge, EdgeAttributes> existing_e;
799 std::map<simplex::Face, FaceSnapshot> existing_f;
810 bool is_order_2_edge(
const Tuple& e)
const;
811 bool is_order_2_edge(
const std::array<size_t, 2>& e)
const;
838 for (
const int64_t& i : tag1) {
839 if (tag2.find(i) != tag2.end()) {
855 double len1 = (m_vertex_attribute[e1.vertices()[0]].m_posf -
856 m_vertex_attribute[e1.vertices()[1]].m_posf)
858 double len2 = (m_vertex_attribute[e2.vertices()[0]].m_posf -
859 m_vertex_attribute[e2.vertices()[1]].m_posf)
873 size_t get_partition_id(
const Tuple& loc)
const
875 return m_vertex_attribute[loc.vid(*
this)].partition_id;
883 std::vector<Tuple> adj_tets;
884 auto tet_1 = t.switch_tetrahedron(*
this);
886 adj_tets.push_back(tet_1.value());
888 auto tet_2 = t.switch_face(*this).switch_tetrahedron(*
this);
890 adj_tets.push_back(tet_2.value());
892 auto tet_3 = t.switch_edge(*this).switch_face(*this).switch_tetrahedron(*
this);
894 adj_tets.push_back(tet_3.value());
897 t.switch_vertex(*this).switch_edge(*this).switch_face(*this).switch_tetrahedron(*
this);
899 adj_tets.push_back(tet_4.value());
910 std::vector<size_t> ret_v_ids;
911 for (
const size_t& other_v_id : onering_v_ids) {
913 if (m_edge_attribute[e_id].label != 0) {
914 ret_v_ids.push_back(other_v_id);
926 for (
const Tuple& v : verts) {
927 size_t v_id = v.vid(*
this);
928 m_vertex_extra[v_id].component_id = 0;
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
Definition TopoOffsetTetMesh.h:52
Definition TopoOffsetTetMesh.h:79
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
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
Definition TopoOffsetTetMesh.h:742
A face's shared surface tags together with the offset's own label.
Definition TopoOffsetTetMesh.h:189
Definition TopoOffsetTetMesh.h:774
Definition TopoOffsetTetMesh.h:394
Definition TopoOffsetTetMesh.h:792