2#include <wmtk/TriMesh.h>
3#include <wmtk/TriOptimizerMesh.h>
12#include <wmtk/optimization/EnergySum.hpp>
13#include <wmtk/optimization/solver.hpp>
14#include <wmtk/threading/enumerable_thread_specific.hpp>
15#include "OffsetPotential.hpp"
16#include "Parameters.h"
17#include "SimplicialComplexBVH.hpp"
18#include "TagEnvelopes.hpp"
20using CellTag = std::set<int64_t>;
22namespace wmtk::components::topological_offset {
25const int64_t TEMP_OFFSET_TRI_TAG = -1;
26const CellTag TEMP_OFFSET_TRI_TAG_SET{TEMP_OFFSET_TRI_TAG};
40 bool m_is_on_input =
false;
41 bool m_is_on_offset =
false;
42 bool m_is_on_region =
false;
48 bool m_turn_start_valid =
false;
95 std::array<Eigen::Vector2d, 3> rest_pos;
114 enum class EdgeSplitMode {
120 int m_vtu_counter = 0;
121 std::array<size_t, 3> m_init_counts = {{0, 0, 0}};
207 void init_region_potentials(
double delta,
double effective_factor);
208 void assign_band_regions();
211 int vertex_region(
const size_t vid)
const
215 int edge_region(
const size_t va,
const size_t vb)
const
217 const int a = vertex_region(va), b = vertex_region(vb);
218 return (a >= 0 && a == b) ? a : -1;
220 const OffsetPotential2D& potential_for_region(
const int region)
const
226 const OffsetPotential2D& potential_for(
const size_t vid)
const
228 return potential_for_region(vertex_region(vid));
234 const int r = vertex_region(vid);
238 const OffsetPotential2D& potential_for_edge(
const size_t va,
const size_t vb)
const
240 return potential_for_region(edge_region(va, vb));
242 const OffsetPotential2D& potential_for_face(
const size_t fid)
const
280 std::vector<Eigen::Vector2i>
E;
287 std::map<int64_t, TagPolyline2d> m_tag_polyline;
296 mutable std::mutex m_isect_mutex;
321 std::shared_ptr<SampleEnvelope>
containment_for(uint64_t region_mask,
bool on_offset)
const;
370 bool walk_along_curve(int64_t tag,
const Vector2d& x,
double s, Vector2d& out)
const;
379 bool curve_tangent(int64_t tag,
const Vector2d& x,
const Vector2d& prefer, Vector2d& tau)
const;
488 EdgeSplitMode m_edge_split_mode = EdgeSplitMode::Midpoint;
491 std::map<std::string, int64_t> m_tag_name_to_id;
492 std::map<int64_t, std::string> m_tag_id_to_name;
493 CellTag m_offset_output_tag_ids;
496 bool m_singlebody =
false;
497 int64_t m_single_tag;
500 bool m_has_envelope =
false;
501 MatrixXd m_V_envelope;
502 MatrixXi m_F_envelope;
516 static constexpr int OFFSET_SURFACE_CLASS = 1;
534 NUM_THREADS = _num_threads;
541 optimization::deactivate_opt_logger();
554 m_vertex_attribute[vid].m_posf = p;
555 m_vertex_attribute[vid].m_pos = to_rational(p);
556 m_vertex_attribute[vid].m_is_rounded =
true;
563 return m_edge_attribute[eid].m_is_surface_fs &&
564 m_edge_attribute[eid].m_surface_class == OFFSET_SURFACE_CLASS;
571 return m_edge_attribute[eid].m_is_surface_fs &&
572 m_edge_attribute[eid].m_surface_class != OFFSET_SURFACE_CLASS;
594 void restore_edge(
const size_t eid,
const EdgeSnapshot2d& s)
596 m_edge_attribute[eid] = s.tags;
597 m_edge_extra[eid] = s.extra;
599 FaceSnapshot2d face_snapshot(
const size_t fid)
const
601 return FaceSnapshot2d{m_face_attribute[fid], m_face_extra[fid]};
603 void restore_face(
const size_t fid,
const FaceSnapshot2d& s)
605 m_face_attribute[fid] = s.attrs;
606 m_face_extra[fid] = s.extra;
668 void log_worst_dist_vertex()
const;
701 mutable int m_debug_last_round = -1;
702 mutable char m_debug_last_phase =
'?';
712 double m_quality_max_amips = 0.;
717 std::atomic<int> iter_cnt_recollapsed{0};
718 std::atomic<int> iter_cnt_recollapsed_same_pass{0};
719 std::atomic<int> iter_cnt_split = 0, iter_cnt_collapse = 0, iter_cnt_swap = 0;
720 std::atomic<int> iter_cnt_collapse_offset_removed{0};
723 std::atomic<int> iter_cnt_swap_offset_reject{0};
726 std::atomic<int> iter_cnt_split_offset{0};
733 std::map<size_t, int> face_label;
751 bool marching_split_edge_before(
const Tuple& t);
752 bool marching_split_edge_after(
const Tuple& t);
776 bool collapse_before_vertex(
size_t v1,
size_t v2)
override;
777 void collapse_after_vertex(
size_t v1,
size_t v2)
override;
778 void split_after_vertex(
size_t v_new)
override;
819 return !m_vertex_attribute[vid].on_bbox_faces.empty();
821 bool edge_is_on_domain_boundary(
const size_t eid)
const
823 return m_edge_attribute[eid].m_is_bbox_fs >= 0;
890 std::atomic<long long> res_after_nano{0};
891 std::atomic<long long> res_max_before_nano{0};
892 std::atomic<long long> res_max_after_nano{0};
896 for (std::atomic<int>* c :
909 for (std::atomic<long long>* c :
910 {&
res_before_nano, &res_after_nano, &res_max_before_nano, &res_max_after_nano}) {
915 SmoothTrace m_smooth_trace;
933 mutable std::atomic<size_t> m_needle_smooth_offered{0};
934 mutable std::atomic<size_t> m_needle_smooth_reached{0};
935 mutable std::atomic<size_t> m_needle_smooth_fixed{0};
936 mutable std::atomic<size_t> m_needle_smooth_stationary{0};
966 void record_flatness(
const char* op,
double parent_flat,
size_t child_fid)
const;
967 mutable std::atomic<size_t> m_flat_created_split{0};
968 mutable std::atomic<size_t> m_flat_created_collapse{0};
969 mutable std::atomic<size_t> m_flat_worsened_split{0};
970 mutable std::atomic<size_t> m_flat_genesis_reports{0};
971 static constexpr double kFlatThreshold = 1e-3;
977 void log_smooth_trace()
const;
1037 return m_vertex_extra[vid].m_is_on_region || !m_vertex_attribute[vid].on_bbox_faces.empty();
1045 for (
const int64_t t : tags) {
1047 if (it !=
m_tag_bit.end()) bits |= (uint64_t(1) << it->second);
1088 const std::optional<Tuple> opp = e.switch_face(*
this);
1090 return tag_bits(m_face_attribute[e.fid(*
this)].tags);
1092 const auto& t0 = m_face_attribute[e.fid(*
this)].tags;
1093 const auto& t1 = m_face_attribute[opp->fid(*
this)].tags;
1095 std::set_symmetric_difference(
1100 std::inserter(diff, diff.begin()));
1132 const std::array<size_t, 2>& vids)
const override
1145 bool all_offset =
true;
1146 for (
const size_t v : vids) {
1147 all_offset = all_offset && m_vertex_extra[v].m_is_on_offset;
1164 if (mask != 0 && all_offset) {
1166 const size_t eid = std::get<1>(*found);
1167 if (m_edge_attribute[eid].m_is_surface_fs) {
1179 const std::shared_ptr<SampleEnvelope> base =
containment_for(mask, all_offset);
1235 std::shared_ptr<SampleEnvelope> best;
1236 double worst_d2 = -1.;
1239 if (it ==
m_tag_bit.end() || !(mask & (uint64_t(1) << it->second)))
continue;
1242 if ((mask & (mask - 1)) == 0)
break;
1243 worst_d2 = env->squared_distance(m_vertex_attribute[vid].m_posf);
1246 const double d2 = env->squared_distance(m_vertex_attribute[vid].m_posf);
1247 if (d2 > worst_d2) {
1301 static_cast<size_t>(-1);
1308 const Vector2d& x)
const;
1314 const size_t vid)
const override
1316 std::shared_ptr<polysolve::nonlinear::Problem> front;
1322 if (!front)
return rest;
1323 if (!rest)
return front;
1324 auto sum = std::make_shared<optimization::EnergySum>();
1325 sum->add_energy(front);
1326 sum->add_energy(rest);
1344 mutable std::atomic<bool> m_released_tube_dirty{
false};
1345 mutable std::mutex m_released_mutex;
1360 bool face_is_plastic(
size_t fid)
const
1391 const std::shared_ptr<const OffsetPotential2D>& pot)
const;
1421 return m_phase != OptPhase::B ? wmtk::TriOptimizerMesh::optimization_stop_metric() : 1.;
1500 double max_reachable = 0., avg_reachable = 0.;
1501 double max_pinned = 0.;
1502 size_t n_reachable = 0, n_pinned = 0;
1512 size_t worst_outside_vid =
static_cast<size_t>(-1);
1513 double worst_outside_dist = 0.;
1569 template <
typename Visit>
1574 const Vector2d p0 = m_vertex_attribute[e.vid(*
this)].m_posf;
1575 const Vector2d p1 = m_vertex_attribute[e.switch_vertex(*this).vid(*
this)].m_posf;
1576 for (
int i = 1; i <= k; ++i) {
1577 const double t = double(i) / double(k + 1);
1578 visit(Vector2d((1. - t) * p0 + t * p1));
1601 double max_reachable = 0., avg_reachable = 0.;
1602 double max_pinned = 0.;
1603 size_t n_reachable = 0, n_pinned = 0;
1653 size_t n_vertices = 0, n_edges = 0, n_unmeasurable = 0;
1655 size_t worst_vid =
static_cast<size_t>(-1);
1656 Vector2d worst_edge_mid = Vector2d::Zero();
1657 double worst_edge_len = 0.;
1664 double max_edge_on_level = 0.;
1665 Vector2d worst_on_level_mid = Vector2d::Zero();
1684 size_t n_placed = 0, n_travelling = 0, n_pressed_on = 0, n_stuck = 0;
1687 size_t worst_stuck_vid =
static_cast<size_t>(-1);
1688 double worst_stuck_rho = 0.;
1694 std::vector<Refinable> refinable;
1695 bool vertices_ok()
const {
return max_vertex <=
bar; }
1698 bool converged()
const {
return vertices_ok() && n_unmeasurable == 0; }
1705 double ratio()
const {
return bar > 0. ? std::max(max_vertex,
max_edge) /
bar : 0.; }
1707 EnergyCriterion energy_criterion();
1715 double front_chord_target(
size_t va,
size_t vb,
double len,
double sag,
double tube)
const;
1857 mutable std::atomic<size_t> m_deg_split_created{0};
1858 mutable std::atomic<size_t> m_deg_collapse_offered{0};
1859 mutable std::atomic<size_t> m_deg_collapse_allowed{0};
1860 mutable std::atomic<size_t> m_deg_collapse_by_ringmax{0};
1861 mutable std::atomic<size_t> m_deg_collapse_by_stop{0};
1862 mutable std::atomic<size_t> m_deg_collapse_by_unrounded{0};
1878 void report_needle(
const char* op,
size_t fid,
double parent_q)
const;
1879 static constexpr size_t kNeedleReports = 12;
1889 mutable std::atomic<size_t> m_needle_reports{0};
1901 size_t m_stuck_calls = 0;
1946 const char ph = (
m_phase == OptPhase::A) ?
'A' : (
m_phase == OptPhase::B ?
'B' :
'S');
1947 if (
m_ab_round != m_debug_last_round || ph != m_debug_last_phase) {
1949 m_debug_last_phase = ph;
1955 std::string label = path;
1956 if (path.rfind(
"debug_", 0) == 0) {
1957 label = fmt::format(
1963 }
else if (path.rfind(
"phase_", 0) == 0) {
1964 label = fmt::format(
"r{}{}_end",
m_ab_round, ph);
1992 const MatrixSi& F_tags,
1993 const MatrixXd& V_env,
1994 const MatrixXi& F_env,
1995 const std::vector<std::string>& tag_names,
1996 const std::string& curve_name =
"");
2038 std::vector<int> m_phi_P;
2045 bool invariants(
const std::vector<Tuple>& tris)
override;
2069 void execute_offset(
const std::filesystem::path& output_file);
2127 void write_input_complex(
const std::string& path);
2128 void write_vtu(
const std::string& path);
2130 void write_msh_groups(
const std::string& file);
2148 std::map<simplex::Edge, EdgeSnapshot2d> existing_eattr;
2151 std::map<size_t, FaceSnapshot2d> opp_v_fattr;
2163 std::map<simplex::Edge, EdgeSnapshot2d> existing_eattr;
2174 for (
const int64_t& i : tag1) {
2175 if (tag2.find(i) != tag2.end()) {
2191 double len1 = (m_vertex_attribute[e1.vertices()[0]].m_posf -
2192 m_vertex_attribute[e1.vertices()[1]].m_posf)
2194 double len2 = (m_vertex_attribute[e2.vertices()[0]].m_posf -
2195 m_vertex_attribute[e2.vertices()[1]].m_posf)
2207 const auto& verts = e.vertices();
2208 const auto incident = simplex_incident_triangles(e);
2209 const auto& faces = incident.faces();
2211 assert(!faces.empty());
2213 const size_t f_id = tuple_from_simplex(faces.front()).
fid(*
this);
2215 return t_edge.eid(*
this);
2223 const auto& v = e.vertices();
2224 const auto faces = simplex_incident_triangles(e).faces();
2225 assert(!faces.empty());
2226 const size_t fid = tuple_from_simplex(faces.front()).
fid(*
this);
2235 std::vector<Tuple> adj_tris;
2238 adj_tris.push_back(tri_1.value());
2242 adj_tris.push_back(tri_2.value());
2246 adj_tris.push_back(tri_3.value());
Whether a codimension-1 simplex is tracked surface, and which bbox side it lies on.
Definition SurfaceTagAttributes.h:15
size_t fid(const TriMesh &) const
Definition TriMesh.h:80
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
std::optional< std::tuple< Tuple, size_t > > try_tuple_from_edge(const std::array< size_t, 2 > &vids) const
tuple_from_edge for callers where a missing edge is an answer, not a bug.
Definition TriMesh.cpp:2042
Tuple tuple_from_edge(size_t vid1, size_t vid2, size_t fid) const
Definition TriMesh.cpp:2202
What triwild and simwild's 2D mesh share.
Definition TriOptimizerMesh.h:39
AttributeContainerGroup m_edge_attr_group
What p_edge_attrs points at, so a derived class can register more.
Definition TriOptimizerMesh.h:111
AttributeContainerGroup m_vertex_attr_group
What p_vertex_attrs points at, so a derived class can register more.
Definition TriOptimizerMesh.h:96
AttributeContainerGroup m_face_attr_group
What p_face_attrs points at, so a derived class can register more.
Definition TriOptimizerMesh.h:122
std::string m_debug_pass_name
Definition TriOptimizerMesh.h:158
The offset potential: the scalar field on space whose level set the front is placed on.
Definition OffsetPotential.hpp:37
The offset's 2D mesh, on the shared 2D optimizer.
Definition TopoOffsetTriMesh.h:112
void rebuild_offset_envelope()
Definition Optimize2d.cpp:3661
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:3213
void stamp_plastic_rests()
Stamp rest := current for every plastic face; called before every operation group.
Definition Optimize2d.cpp:348
void stamp_rest_face(size_t fid)
Definition Optimize2d.cpp:339
int m_n_regions
One field per connected piece of the input complex, and which one each band vertex is placed on.
Definition TopoOffsetTriMesh.h:199
int64_t tangent_curve_tag(size_t vid, const Vector2d &x) const
Which tag's boundary curve a vertex slides along, or -1.
Definition Optimize2d.cpp:495
int m_debug_pass
Definition TopoOffsetTriMesh.h:700
void label_input_complex()
label input complex simplices as per boolean expression (or single body mode)
Definition TopoOffsetTriMesh.cpp:406
double edge_interpolation_residual(const Tuple &e) const
The interpolation residual of front edge e, see EnergyCriterion. -1 when unmeasurable.
Definition Optimize2d.cpp:2704
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:552
std::string envelope_key_name(int64_t tag) const
The name a tag or pseudo-tag prints under.
Definition TopoOffsetTriMesh.cpp:210
Parameters & m_offset_params
The base holds only wmtk::OptimizerParameters; this is the same object, typed.
Definition TopoOffsetTriMesh.h:519
double band_vertex_distance_error(const size_t vid) const
Definition Optimize2d.cpp:2497
std::vector< char > m_placement_pressed
Definition TopoOffsetTriMesh.h:1771
void write_smoothing_debug_output(const std::string &path) const override
Put the frames beside the run's own output, and rename them into one timeline.
Definition TopoOffsetTriMesh.h:1944
std::atomic< int > m_placement_tangential
Definition TopoOffsetTriMesh.h:1024
void log_front_profile(size_t vid)
Diagnostic: the front objective of one vertex along its normal, offset term vs total.
Definition Optimize2d.cpp:3044
void audit_surface_containment(const std::string &when) const
Which tracked edges are outside their envelope, and by how much.
Definition Optimize2d.cpp:1067
double optimization_stop_metric() const override
1.0 in Phase B, where the metric is normalized; the base's stop_energy in Phase A.
Definition TopoOffsetTriMesh.h:1418
void needle_scan(const char *when) const
Definition Optimize2d.cpp:2206
void log_stuck_refine_census(double max_metric, double filter_energy)
Why Phase A is stuck: a census of the faces stuck-refine is about to chase.
Definition Optimize2d.cpp:1924
std::shared_ptr< polysolve::nonlinear::Problem > smoothing_extra_energy(const size_t vid) const override
Definition TopoOffsetTriMesh.h:1313
bool split_face_before(const Tuple &t) override
User specified preparations and desideratas for a face split.
Definition EdgeSplittingTri.cpp:196
std::set< int64_t > m_source_tags
Definition TopoOffsetTriMesh.h:1336
Vector2d front_vertex_move_direction(size_t vid) const
Definition FrontSmooth2d.cpp:173
int offset_residual_samples() const
Definition TopoOffsetTriMesh.h:1426
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:1201
std::map< int64_t, int > m_tag_bit
Definition TopoOffsetTriMesh.h:291
bool front_vertex_alignment_traps_1d_solve(size_t vid) const
Definition FrontSmooth2d.cpp:212
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:50
std::vector< int64_t > m_phi_point_region
per m_phi_P entry: region index, -1 unknown
Definition TopoOffsetTriMesh.h:204
std::atomic< int > m_placement_env_entry_outside
Definition TopoOffsetTriMesh.h:1012
bool band_vertex_is_reachable(const size_t vid) const
Definition TopoOffsetTriMesh.h:1751
bool collapse_quality_allowed(size_t v1, size_t v2, double q, double ring_max) const override
Instrumentation only: which operation manufactures the MAX_ENERGY needles.
Definition Optimize2d.cpp:2124
size_t refine_front_from_sag(const std::vector< EnergyCriterion::Refinable > &edges)
Definition Optimize2d.cpp:3150
bool offset_is_manifold()
verify that the closed offset region (simplices labelled 1 or 2) form a manifold region....
Definition TopoOffsetTriMesh.cpp:1236
void report_needle(const char *op, size_t fid, double parent_q) const
Where the first needles come from – a tripwire, not a census.
Definition Optimize2d.cpp:2153
void optimize_offset(const std::filesystem::path &output_file)
The 2D optimization phase: split / collapse / swap / smooth on the shared driver.
Definition Optimize2d.cpp:3922
void report_outside_support(const char *when, const DistanceSplit &s) const
Definition Optimize2d.cpp:3192
std::shared_ptr< SampleEnvelope > m_released_envelope
Definition TopoOffsetTriMesh.h:1343
double offset_residual_tolerance() const
Definition TopoOffsetTriMesh.h:1434
GradientSplit gradient_split(bool include_edge_samples=true) const
Definition Optimize2d.cpp:2589
std::shared_ptr< SampleEnvelope > released_envelope() const
Definition Optimize2d.cpp:3607
double m_gradient_reference
See offset_gradient_tolerance(). Nothing sets it on the single-phase path; it stays 0.
Definition TopoOffsetTriMesh.h:704
std::vector< int64_t > m_phi_vert_region
per m_phi_V row: region index
Definition TopoOffsetTriMesh.h:201
size_t m_worst_dist_vid
Definition TopoOffsetTriMesh.h:667
std::atomic< int > iter_cnt_split_offset_before
Splits of an offset-boundary edge: offered, accepted.
Definition TopoOffsetTriMesh.h:725
std::array< size_t, 6 > m_deg_prev_counts
Values at the previous census, so each census can report deltas rather than totals.
Definition TopoOffsetTriMesh.h:1864
size_t m_debug_seq
Monotonic frame counter for the debug timeline. Mutable because the write hook is const.
Definition TopoOffsetTriMesh.h:697
EdgeSamples offset_edge_samples(const Tuple &e) const
The Phi residual at offset_residual_samples interior points of band edge e.
Definition Optimize2d.cpp:2513
bool empty_input_complex()
check if the input complex is empty. Only valid after calling init_from_image(...)....
Definition TopoOffsetTriMesh.cpp:588
void build_boundary_envelopes(const char *when, EnvelopeSetup setup)
Definition TopoOffsetTriMesh.cpp:230
bool smooth_plastic_vertex(const Tuple &t)
Definition Optimize2d.cpp:364
OptPhase m_phase
Which phase is running. Read by every hook that differs between them; see OptPhase.
Definition TopoOffsetTriMesh.h:410
std::shared_ptr< SimplicialComplexBVH > m_input_complex_bvh
The input complex as loaded. Built once, never rebuilt.
Definition TopoOffsetTriMesh.h:157
void init_input_complex_bvh()
Build the input complex's BVH and its smooth offset potential, from one extraction.
Definition TopoOffsetTriMesh.cpp:601
bool face_is_deformable(size_t fid) const
Under deform_others the same set as face_is_plastic(): every face outside the band.
Definition Optimize2d.cpp:313
double front_chord_target(size_t va, size_t vb, double len, double sag, double tube) const
Definition Optimize2d.cpp:3109
bool phase_places_front() const
Definition TopoOffsetTriMesh.h:407
size_t edge_id_from_simplex(const simplex::Edge &e) const
get global id of edge from simplex::Edge object
Definition TopoOffsetTriMesh.h:2205
std::atomic< int > iter_cnt_collapse_offset_reject
Operations refused because they would have left an offset-boundary face over tolerance.
Definition TopoOffsetTriMesh.h:722
void log_refine_block_census(const std::string &when, double filter_energy) const
For every element above filter_energy, why its edges cannot be split.
Definition Optimize2d.cpp:1747
std::map< uint64_t, std::shared_ptr< SampleEnvelope > > m_offset_isect_cache
Memoized "region tubes AND the offset envelope", keyed by the region mask.
Definition TopoOffsetTriMesh.h:309
bool face_is_offset_band(const size_t fid) const
Definition Optimize2d.cpp:2454
Tuple get_tuple_from_edge(const simplex::Edge &e) const
get Tuple simplex::Edge object
Definition TopoOffsetTriMesh.h:2221
std::vector< int > m_vertex_region
per vertex: region of its band faces, -1 / -2 as above
Definition TopoOffsetTriMesh.h:206
Vector2d offset_vertex_normal(const size_t vid) const
The normal at an offset vertex. Every caller that needs one goes through here, so switching the defin...
Definition Optimize2d.cpp:1034
void check_no_vertex_on_both_surfaces(const char *when) const
Definition Optimize2d.cpp:3528
void marching_tris()
execute simplistic marching tris. All edges with one vertex labelled 0 and the other 1/2 are split,...
Definition TopoOffsetTriMesh.cpp:1136
uint64_t tag_bits(const CellTag &tags) const
Definition TopoOffsetTriMesh.h:1042
double gradient_reference() const
Definition TopoOffsetTriMesh.h:1472
void classify_curve_edges()
Mark the mesh edges that lie on the input's curve group (EdgeExtra2d::on_curve).
Definition TopoOffsetTriMesh.cpp:370
double face_flatness(size_t fid) const
Scale-invariant flatness: 2*area / longest_edge^2.
Definition Optimize2d.cpp:2265
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:60
void sort_edges_by_length(std::vector< simplex::Edge > &edges)
sort vector of edge simplices in place by decreasing length
Definition TopoOffsetTriMesh.h:2185
bool swap_edge_after(const Tuple &t) override
Definition Optimize2d.cpp:652
bool m_freeze_front
The final Phase A: front vertices are not smoothed (see smooth_before()).
Definition TopoOffsetTriMesh.h:417
uint64_t vertex_boundary_mask(const size_t vid) const
The tag boundaries this vertex lies on – the raw mask gated on the vertex still being region geometry...
Definition TopoOffsetTriMesh.h:1062
double front_vertex_normal_gradient(size_t vid) const
Definition Optimize2d.cpp:1050
double max_band_vertex_distance() const
Definition TopoOffsetTriMesh.cpp:937
MatrixXi m_phi_F
the complex faces, in the same vertex index space (for per-region BVHs)
Definition TopoOffsetTriMesh.h:2037
DistanceSplit residual_split() const
Definition Optimize2d.cpp:2534
std::vector< bool > band_vertex_mask() const
Definition Optimize2d.cpp:2460
void for_each_offset_edge_sample(const Tuple &e, Visit &&visit) const
Visit the same interior sample points offset_edge_samples() measures on.
Definition TopoOffsetTriMesh.h:1570
std::set< int64_t > m_deform_tags
The released tags. Filled by release_deformable_regions(); empty = feature inactive.
Definition TopoOffsetTriMesh.h:1333
std::shared_ptr< SampleEnvelope > envelope_for_mask(uint64_t mask) const
The envelope a simplex with this boundary mask is contained in, or null.
Definition Optimize2d.cpp:197
bool m_converged
Definition TopoOffsetTriMesh.h:707
void init_offset_sizing_field()
Definition Optimize2d.cpp:1624
std::vector< std::array< int, 3 > > churn_counts
Definition TopoOffsetTriMesh.h:687
void warn_if_offset_reaches_domain_boundary() const
Warn if the offset band has grown into the domain boundary.
Definition Optimize2d.cpp:164
double edge_conv_ratio(const Tuple &e) const
The edge test divided by its bar (1 = bar), per front_conv_criterion; -1 unmeasurable.
Definition Optimize2d.cpp:2909
double offset_gradient_tolerance() const
The convergence tolerance: the bound on |grad (Phi - c)^2| at a band vertex.
Definition TopoOffsetTriMesh.h:1456
bool edge_is_offset_surface_live(const Tuple &e) const
Definition Optimize2d.cpp:3514
bool split_edge_after(const Tuple &t) override
User specified modifications and desideratas after an edge split.
Definition EdgeSplittingTri.cpp:120
uint64_t edge_boundary_bits(const Tuple &e) const
Diagnostic only: which tag boundaries the incident faces say this edge lies on right now – the same s...
Definition TopoOffsetTriMesh.h:1086
bool vertex_is_on_domain_boundary(const size_t vid) const
Identification only – no operation refuses the domain wall through these.
Definition TopoOffsetTriMesh.h:817
std::optional< EnergyCriterion > m_energy_verdict
Definition TopoOffsetTriMesh.h:1722
bool invariants(const std::vector< Tuple > &tris) override
User specified invariants that can't be violated.
Definition TopoOffsetTriMesh.cpp:1286
double face_criterion_rel(const size_t fid) const
Definition Optimize2d.cpp:3291
double phase_b_front_gradient_linf()
Definition Optimize2d.cpp:2856
std::shared_ptr< const OffsetPotential2D > potential_ptr_for(const size_t vid) const
Definition TopoOffsetTriMesh.h:232
void optimize_offset_single_phase()
TriWild's loop, the front placed inside its smoothing passes.
Definition Optimize2d.cpp:3731
std::vector< int > m_face_region
per face: band's region, -1 none, -2 reached from two
Definition TopoOffsetTriMesh.h:205
std::set< std::pair< long, long > > m_stuck_prev_cells
Definition TopoOffsetTriMesh.h:1900
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, const std::string &curve_name="")
initialize TriMesh from vertex, face, tag data
Definition TopoOffsetTriMesh.cpp:13
void check_offset_within_support(const char *when) const
Stop the run if any reachable band vertex has left the potential's support.
Definition Optimize2d.cpp:3187
bool project_into_containment(size_t vid, Vector2d &x) const
Move x back inside every region tube this vertex lies on. True if it ended up inside all of them.
Definition Optimize2d.cpp:266
std::shared_ptr< OffsetPotential2D > m_offset_potential
The smooth offset potential, and with it the definition of the offset itself.
Definition TopoOffsetTriMesh.h:168
MatrixXd m_curve_V
The curve group as loaded, kept because the classification below is redone on demand.
Definition TopoOffsetTriMesh.h:128
std::vector< int64_t > m_phi_seg_region
per m_phi_E row: region index, -1 unknown
Definition TopoOffsetTriMesh.h:202
int64_t m_curve_tag
Definition TopoOffsetTriMesh.h:126
static constexpr int INPUT_SURFACE_CLASS
SurfaceTagAttributes::m_surface_class: which of the two tracked surfaces an edge belongs to....
Definition TopoOffsetTriMesh.h:515
bool smooth_before(const Tuple &t) override
User specified preparations and desideratas for an edge smooth.
Definition Optimize2d.cpp:905
MatrixXd m_phi_V
Definition TopoOffsetTriMesh.h:2035
std::shared_ptr< SampleEnvelope > surface_envelope_for_edge(const std::array< size_t, 2 > &vids) const override
Class-0 segments – every region boundary, the input complex and the domain wall included – carry a co...
Definition TopoOffsetTriMesh.h:1131
uint64_t edge_mask(const std::array< size_t, 2 > &vids) const
Definition TopoOffsetTriMesh.h:1069
bool smoothing_position_is_allowed(const size_t, const Vector2d &) const override
No per-vertex positional constraint. The per-tag envelopes close that hole structurally – the same de...
Definition TopoOffsetTriMesh.h:1205
static constexpr int64_t m_wall_tag
pseudo-tag: the domain wall's tube
Definition TopoOffsetTriMesh.h:442
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:230
bool face_is_released_band(size_t fid) const
Definition Optimize2d.cpp:320
void record_flatness(const char *op, double parent_flat, size_t child_fid) const
Genesis: flatness transitions recorded at the operation hooks. {op, parent, child}.
Definition Optimize2d.cpp:2277
void mark_input_complex_vertices()
Definition TopoOffsetTriMesh.cpp:339
std::shared_ptr< polysolve::nonlinear::Problem > phase_b_front_objective(size_t vid, const Vector2d &x) const
Definition FrontSmooth2d.cpp:284
std::atomic< size_t > m_needle_smooth_reports
Worst-case record: the best (lowest) ring max any needle-adjacent smooth achieved.
Definition TopoOffsetTriMesh.h:938
double m_front_gradient_reference
Definition TopoOffsetTriMesh.h:486
std::shared_ptr< SampleEnvelope > containment_for(uint64_t region_mask, bool on_offset) const
The containment a simplex with this region mask, on/off the offset front, must satisfy – the intersec...
Definition Optimize2d.cpp:237
std::vector< std::shared_ptr< OffsetPotential2D > > m_region_potentials
one per piece
Definition TopoOffsetTriMesh.h:200
std::atomic< int > iter_cnt_split_born
Definition TopoOffsetTriMesh.h:716
bool vertex_is_on_region(const size_t vid) const
Is this vertex on a region boundary – a tag boundary, or the domain wall.
Definition TopoOffsetTriMesh.h:1035
wmtk::threading::enumerable_thread_specific< double > m_collapse_parent_flatness
The flattest face in the collapse's ring before it ran, for record_flatness().
Definition TopoOffsetTriMesh.h:973
double front_vertex_conv_ratio(size_t vid) const
Definition Optimize2d.cpp:2879
bool edge_is_on_surface(const std::array< size_t, 2 > &vids) const override
Is an edge part of the substructure.
Definition Optimize2d.cpp:33
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:2172
Vector2d front_vertex_normal(size_t vid) const
The field's outward unit direction at front vertex vid (zero where grad Phi vanishes).
Definition FrontSmooth2d.cpp:205
size_t refine_sizing_around_worst(double max_metric) override
TriWild's stall-driven sizing refinement, verbatim.
Definition Optimize2d.cpp:3313
std::vector< int64_t > m_phi_face_region
per m_phi_F row: region index, -1 unknown
Definition TopoOffsetTriMesh.h:203
static constexpr double kNeedleQuality
What counts as a needle for the tripwire – deliberately far below MAX_ENERGY.
Definition TopoOffsetTriMesh.h:1888
std::shared_ptr< polysolve::nonlinear::Problem > phase_b_front_energy(size_t vid, const std::shared_ptr< const OffsetPotential2D > &pot) const
Definition FrontSmooth2d.cpp:332
std::map< int64_t, std::shared_ptr< SampleEnvelope > > m_tag_envelopes
One containment envelope per input tag, ambient included. Both phases.
Definition TopoOffsetTriMesh.h:263
bool front_vertex_touches_other(size_t vid) const
Definition Optimize2d.cpp:3084
std::map< uint64_t, std::shared_ptr< SampleEnvelope > > m_isect_cache
Definition TopoOffsetTriMesh.h:295
bool optimization_bare_coarsen_passes() const override
Definition TopoOffsetTriMesh.h:1910
void label_offset_boundary()
Tag the two tracked surfaces for the optimization phase.
Definition Optimize2d.cpp:70
bool edge_borders_released_boundary(const Tuple &e) const
Definition Optimize2d.cpp:3583
bool edge_is_region(const size_t eid) const
Definition TopoOffsetTriMesh.h:569
bool curve_tangent(int64_t tag, const Vector2d &x, const Vector2d &prefer, Vector2d &tau) const
The unit tangent of tag tag's curve at x's foot, or false if there is none.
Definition Optimize2d.cpp:514
void append_frame_label(size_t idx, const std::string &label) const
Definition Optimize2d.cpp:3721
double band_vertex_residual(const size_t vid) const
Definition Optimize2d.cpp:2506
std::vector< std::array< double, 8 > > optimization_metrics
Definition TopoOffsetTriMesh.h:684
void simplicial_embedding()
make mesh a simplicial embedding of the input complex (simplices labelled 1)
Definition TopoOffsetTriMesh.cpp:1073
bool edge_is_offset(const size_t eid) const
Definition TopoOffsetTriMesh.h:561
static constexpr int64_t m_complex_tag
Definition TopoOffsetTriMesh.h:443
std::tuple< double, double > optimization_quality_stats() override
The loop's convergence metric, normalized so that 1.0 means "done".
Definition Optimize2d.cpp:3259
bool swap_edge_before(const Tuple &t) override
Reject a flip whose new edge already exists.
Definition Optimize2d.cpp:129
bool face_is_input_complex(const size_t fid) const
Definition Optimize2d.cpp:65
void log_region_edge_mask_health(const std::string &when) const
Are the tracked region boundaries actually contained by anything?
Definition Optimize2d.cpp:1232
void pre_optimize_input_mesh()
TriWild over the input mesh, before any of the offset exists.
Definition Optimize2d.cpp:1450
bool smooth_after(const Tuple &t) override
User specified modifications and desideras after an edge smooth.
Definition Optimize2d.cpp:937
bool collapse_edge_after(const Tuple &t) override
A collapse is accepted by the same criterion the smoothing minimises.
Definition Optimize2d.cpp:666
void needle_forensics() const
The full post-mortem on why nothing removes the flat faces.
Definition Optimize2d.cpp:2329
bool walk_along_curve(int64_t tag, const Vector2d &x, double s, Vector2d &out) const
March s of arclength along tag tag's boundary polyline from x's foot on it.
Definition Optimize2d.cpp:562
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:852
wmtk::threading::enumerable_thread_specific< double > m_collapse_survivor_sizing
Definition TopoOffsetTriMesh.h:976
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:2233
std::vector< std::array< int, 3 > > op_counts
Definition TopoOffsetTriMesh.h:692
std::vector< Eigen::Vector2d > m_env_polyline_V
Definition TopoOffsetTriMesh.h:286
wmtk::threading::enumerable_thread_specific< std::pair< double, Vector2d > > m_needle_pre
Why smoothing does not lift a sliver's apex off its opposite edge.
Definition TopoOffsetTriMesh.h:932
void collapse_pass_begin() override
Definition Optimize2d.cpp:776
int m_ab_round
Definition TopoOffsetTriMesh.h:695
void init_surfaces_and_boundaries()
Classify every region boundary, build the per-tag containment envelopes, and tag the domain wall – on...
Definition TopoOffsetTriMesh.cpp:140
void release_deformable_regions()
Definition Optimize2d.cpp:426
bool m_quality_converged
Definition TopoOffsetTriMesh.h:711
bool m_plastic_active
set in optimize_offset() when deform_others
Definition TopoOffsetTriMesh.h:1359
double ring_max_quality(size_t vid) const
Max AMIPS over the faces incident to vid. -1 if it has none.
Definition Optimize2d.cpp:2255
void write_phi_grid(const std::string &path, int n) const
Sample the smooth offset potential on a dense grid and write it as <path>_phi.vtu.
Definition TopoOffsetTriMesh.cpp:1445
EnvelopeSetup
Which boundaries the region-class envelopes hold, and how they are built.
Definition TopoOffsetTriMesh.h:437
bool ambient_assert()
ensure ambient tag does not overlap any other tags in mesh.
Definition TopoOffsetTriMesh.cpp:356
std::shared_ptr< SampleEnvelope > smoothing_containment_envelope(const size_t vid) const override
... and it is not contained by one either, except in Phase A.
Definition TopoOffsetTriMesh.h:1266
size_t m_front_gradient_worst_vid
Definition TopoOffsetTriMesh.h:1300
bool edge_is_complex_boundary(const Tuple &e) const
Definition TopoOffsetTriMesh.cpp:218
OptPhase
Which half of the alternating optimization is running.
Definition TopoOffsetTriMesh.h:403
bool is_simplicially_embedded() const
check if the input complex (simplices labelled 1) are simplicially embedded w.r.t....
Definition TopoOffsetTriMesh.cpp:1028
std::shared_ptr< SampleEnvelope > smoothing_energy_envelope(const size_t vid) const override
The offset boundary is the one tracked surface with no envelope, in either role.
Definition TopoOffsetTriMesh.h:1223
bool collapse_edge_before(const Tuple &t) override
Reject any collapse that violates the substructure link condition.
Definition Optimize2d.cpp:700
std::shared_ptr< polysolve::nonlinear::Problem > rest_energy_for_vertex(size_t vid) const
Definition Optimize2d.cpp:459
std::shared_ptr< SampleEnvelope > m_offset_envelope
The tube the offset boundary may not leave during Phase A, of half-width offset_envelope_rel x target...
Definition TopoOffsetTriMesh.h:467
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:1047
std::atomic< int > m_placement_projected
Definition TopoOffsetTriMesh.h:1018
void init_offset_potential()
Build the smooth offset potential from the extraction init_input_complex_bvh() kept.
Definition TopoOffsetTriMesh.cpp:820
bool smooth_front_vertex_phase_b(const Tuple &t)
Phase B placement of a front vertex: the shared smoother with the offset's options.
Definition FrontSmooth2d.cpp:77
Definition Simplex.hpp:46
Definition enumerable_thread_specific.hpp:26
Definition TriOptimizerMesh.h:74
What the offset needs on top of the parameters every wmtk optimizer shares.
Definition Parameters.h:20
bool deform_others
Definition Parameters.h:83
The band's distance error, split by whether the optimizer can do anything about it.
Definition TopoOffsetTriMesh.h:1499
size_t n_outside_support
Definition TopoOffsetTriMesh.h:1511
double max_at_vertex
Definition TopoOffsetTriMesh.h:1507
The residual sampled at points along a band edge – see offset_edge_samples().
Definition TopoOffsetTriMesh.h:1537
An edge's / face's shared attributes together with the offset's own label.
Definition TopoOffsetTriMesh.h:581
Definition TopoOffsetTriMesh.h:2140
Definition TopoOffsetTriMesh.h:1690
The "energy_gradient" criterion: the front is at a critical point of Phase B's energy,...
Definition TopoOffsetTriMesh.h:1647
double bar
the ratios' bar, 1
Definition TopoOffsetTriMesh.h:1652
bool converged_single() const
Definition TopoOffsetTriMesh.h:1704
double tube
Definition TopoOffsetTriMesh.h:1683
size_t n_at_floor
chords over the tube whose ends are already at the sizing floor
Definition TopoOffsetTriMesh.h:1686
bool converged() const
The alternating loop's test (and 3D's): the vertex test alone.
Definition TopoOffsetTriMesh.h:1698
double max_edge
RATIOS to the bar (1 = bar): the vertex measure per front_conv_criterion; the edge test.
Definition TopoOffsetTriMesh.h:1650
size_t n_edges_over
Definition TopoOffsetTriMesh.h:1663
size_t n_pressed_touching
of the pressed, those touching another front or a wall
Definition TopoOffsetTriMesh.h:1685
size_t n_edges_pressed
skipped: pressed (see m_placement_pressed)
Definition TopoOffsetTriMesh.h:1654
Definition TopoOffsetTriMesh.h:586
Definition TopoOffsetTriMesh.h:2156
The convergence criterion's own split: ||grad (Phi - c)^2|| at band vertices – the deciding measure –...
Definition TopoOffsetTriMesh.h:1600
double max_in_edge_pinned
Definition TopoOffsetTriMesh.h:1611
size_t worst_vid
Definition TopoOffsetTriMesh.h:1621
double max_at_vertex
Definition TopoOffsetTriMesh.h:1608
size_t n_skipped_inverted
Definition TopoOffsetTriMesh.h:1618
size_t n_edge_samples
Edge-interior samples measured into max_in_edge (not part of n_reachable).
Definition TopoOffsetTriMesh.h:1615
double max_normal_aligned
max |2 (Phi - c) grad Phi . n| at band vertices, reachable AND pinned.
Definition TopoOffsetTriMesh.h:1613
Definition TopoOffsetTriMesh.h:732
double parent_flatness
Definition TopoOffsetTriMesh.h:747
double parent_q_max
Definition TopoOffsetTriMesh.h:744
uint64_t edge_bits
Definition TopoOffsetTriMesh.h:741
What smoothing did with each class of vertex, per pass.
Definition TopoOffsetTriMesh.h:871
std::atomic< int > offset_accepted
... and the smoother kept the new position
Definition TopoOffsetTriMesh.h:880
std::atomic< int > offset_attempted
reached the smoother with the offset term
Definition TopoOffsetTriMesh.h:879
std::atomic< int > interior_attempted
reached it without one
Definition TopoOffsetTriMesh.h:881
std::atomic< int > before_phase_b_not_offset
Phase B: on an input surface, neither placed nor relaxed.
Definition TopoOffsetTriMesh.h:875
std::atomic< int > attempted
smooth_before() entered
Definition TopoOffsetTriMesh.h:872
std::atomic< int > region_attempted
Definition TopoOffsetTriMesh.h:882
std::atomic< int > before_phase_b_enveloped_background
Phase B: envelope-held.
Definition TopoOffsetTriMesh.h:877
std::atomic< long long > res_before_nano
Definition TopoOffsetTriMesh.h:889
std::atomic< int > before_unrounded
base smooth_before said no: could not round
Definition TopoOffsetTriMesh.h:874
std::atomic< int > before_bbox
base smooth_before said no: on the bounding box
Definition TopoOffsetTriMesh.h:873
std::atomic< int > before_phase_b_enveloped_offset
Phase B: on-offset AND held.
Definition TopoOffsetTriMesh.h:878
The per-tag boundary polyline, with the adjacency an arclength walk needs.
Definition TopoOffsetTriMesh.h:279
std::vector< std::vector< int > > at_vertex
polyline vertex -> incident segment ids
Definition TopoOffsetTriMesh.h:281
std::vector< Eigen::Vector2i > E
segments, indexing m_env_polyline_V
Definition TopoOffsetTriMesh.h:280