25 "logest edge split works only for edge, triangle, or tet meshes: {}",
34 std::vector<attribute::MeshAttributeHandle> other_position_handles =
39 std::vector<attribute::MeshAttributeHandle> pass_through_attributes =
42 for (
auto& h : other_position_handles) {
43 pass_through_attributes.emplace_back(h);
48 auto visited_edge_flag =
51 auto update_flag_func = [](Eigen::Ref<const Eigen::MatrixXd> P) -> Eigen::VectorX<char> {
52 assert(P.cols() == 2);
53 assert(P.rows() == 2 || P.rows() == 3);
54 return Eigen::VectorX<char>::Constant(1,
char(1));
57 std::make_shared<wmtk::operations::SingleAttributeTransferStrategy<char, double>>(
64 auto edge_length_attribute =
66 auto edge_length_accessor = mesh.
create_accessor(edge_length_attribute.as<
double>());
68 auto compute_edge_length = [](Eigen::Ref<const Eigen::MatrixXd> P) -> Eigen::VectorXd {
69 assert(P.cols() == 2);
70 assert(P.rows() == 2 || P.rows() == 3);
71 return Eigen::VectorXd::Constant(1, (P.col(0) - P.col(1)).norm());
73 auto edge_length_update =
74 std::make_shared<wmtk::operations::SingleAttributeTransferStrategy<double, double>>(
75 edge_length_attribute,
78 edge_length_update->run_on_all();
82 Eigen::VectorXd bmin(position_handle.
dimension());
83 bmin.setConstant(std::numeric_limits<double>::max());
84 Eigen::VectorXd bmax(position_handle.
dimension());
85 bmax.setConstant(std::numeric_limits<double>::lowest());
91 const auto p = pt_accessor.vector_attribute(v);
92 for (int64_t d = 0; d < bmax.size(); ++d) {
93 bmin[d] = std::min(bmin[d], p[d]);
94 bmax[d] = std::max(bmax[d], p[d]);
98 const double bbdiag = (bmax - bmin).norm();
100 const double length_abs = bbdiag * options.
length_rel;
103 "bbox max {}, bbox min {}, diag {}, target edge length {}",
111 return -edge_length_accessor.const_scalar_attribute(s.tuple());
113 pass_through_attributes.push_back(edge_length_attribute);
115 std::make_shared<TodoLargerInvariant>(mesh, edge_length_attribute.as<
double>(), length_abs);
118 auto invariant_interior_edge = std::make_shared<invariants::InvariantCollection>(mesh);
119 auto invariant_interior_vertex = std::make_shared<invariants::InvariantCollection>(mesh);
121 auto set_all_invariants = [&](
auto&& m) {
122 invariant_interior_edge->add(
124 invariant_interior_vertex->add(
130 auto invariant_mm_map = std::make_shared<MultiMeshMapValidInvariant>(mesh);
133 std::vector<attribute::MeshAttributeHandle> position_handles;
134 position_handles.emplace_back(position_handle);
138 auto split = std::make_shared<wmtk::operations::EdgeSplit>(mesh);
139 split->add_invariant(todo);
141 split->set_new_attribute_strategy(
145 split->add_transfer_strategy(tag_update);
147 split->set_priority(long_edges_first_priority);
148 split->add_transfer_strategy(edge_length_update);
151 for (
const auto& pos_handle : position_handles) {
152 split->set_new_attribute_strategy(pos_handle);
155 for (
const auto& attr : pass_through_attributes) {
156 split->set_new_attribute_strategy(attr);
159 auto propagate_position = [](
const Eigen::MatrixXd& P) -> Eigen::VectorXd {
return P; };
160 for (
auto& h : other_position_handles) {
161 auto transfer_position =
162 std::make_shared<operations::SingleAttributeTransferStrategy<double, double>>(
166 split->add_transfer_strategy(transfer_position);
176 "Executed {} ops (S/F) {}/{}. Time: collecting: {}, sorting: {}, executing: {}",