127 int m_debug_print_counter = 0;
128 size_t m_tags_count = 0;
129 std::map<int64_t, std::string> m_tag_id_to_name;
130 std::map<std::string, int64_t> m_tag_name_to_id;
132 double time_env = 0.0;
133 igl::Timer isout_timer;
134 const double MAX_ENERGY = std::numeric_limits<double>::max();
137 std::vector<Vector3d> m_V_envelope;
138 std::vector<Vector3i> m_F_envelope;
139 std::shared_ptr<SampleEnvelope> m_envelope;
140 std::shared_ptr<SampleEnvelope> m_envelope_orig;
141 double m_envelope_eps = -1;
143 using ExprPtr = expression_parser::ExpressionPtr;
144 std::vector<std::tuple<ExprPtr, double>> m_length_regions;
146 bool m_collapse_check_quality =
true;
149 std::shared_ptr<SampleEnvelope> m_order_2_edge_envelope;
151 tbb::enumerable_thread_specific<std::unique_ptr<polysolve::nonlinear::Solver>> m_solver;
154 double m_s_amips = -1;
155 double m_s_envelope = -1;
159 std::function<double(
const Vector3d&)> m_voronoi_split_fn =
nullptr;
162 : m_params(_m_params)
163 , m_envelope_eps(envelope_eps)
165 NUM_THREADS = _num_threads;
166 p_vertex_attrs = &m_vertex_attribute;
167 p_face_attrs = &m_face_attribute;
168 p_tet_attrs = &m_tet_attribute;
169 m_collapse_check_link_condition =
false;
170 m_collapse_check_manifold =
false;
174 optimization::deactivate_opt_logger();
177 m_s_envelope = 1. / (m_params.diag_l * m_params.eps * m_params.eps);
179 double& wa = m_params.w_amips;
180 double& we = m_params.w_envelope;
182 logger().info(
"w_envelope = {}", we);
196 void create_mesh_attributes(
197 const std::vector<VertexAttributes>& _vertex_attribute,
198 const std::vector<TetAttributes>& _tet_attribute)
200 auto n_tet = _tet_attribute.size();
201 m_vertex_attribute.resize(_vertex_attribute.size());
202 m_face_attribute.resize(4 * n_tet);
203 m_tet_attribute.resize(n_tet);
205 for (
auto i = 0; i < _vertex_attribute.size(); i++) {
206 m_vertex_attribute[i] = _vertex_attribute[i];
208 m_tet_attribute.m_attributes = tbb::concurrent_vector<TetAttributes>(_tet_attribute.size());
209 for (
auto i = 0; i < _tet_attribute.size(); i++) {
210 m_tet_attribute[i] = _tet_attribute[i];
212 for (
auto i = 0; i < _tet_attribute.size(); i++) {
218 void compute_vertex_partition()
220 auto partition_id = partition_TetMesh(*
this, NUM_THREADS);
222 m_vertex_attribute[i].partition_id = partition_id[i];
226 void compute_vertex_partition_morton()
228 if (NUM_THREADS == 0)
return;
230 wmtk::logger().info(
"Number of parts: {} by morton", NUM_THREADS);
232 tbb::task_arena arena(NUM_THREADS);
238 tbb::blocked_range<int>(0, V_v.size()),
239 [&](tbb::blocked_range<int> r) {
240 for (int i = r.begin(); i < r.end(); i++) {
241 V_v[i] = m_vertex_attribute[i].m_posf;
252 std::vector<sortstruct> list_v;
253 list_v.resize(V_v.size());
256 std::vector<Eigen::Vector3d> V = V_v;
257 Eigen::Vector3d vmin, vmax;
261 for (
size_t j = 0; j < V.size(); j++) {
262 for (
int i = 0; i < 3; i++) {
263 vmin(i) = std::min(vmin(i), V[j](i));
264 vmax(i) = std::max(vmax(i), V[j](i));
269 Eigen::Vector3d center = (vmin + vmax) / 2;
271 tbb::parallel_for(tbb::blocked_range<int>(0, V.size()), [&](tbb::blocked_range<int> r) {
272 for (int i = r.begin(); i < r.end(); i++) {
273 V[i] = V[i] - center;
277 Eigen::Vector3d scale_point =
280 double xscale, yscale, zscale;
281 xscale = fabs(scale_point[0]);
282 yscale = fabs(scale_point[1]);
283 zscale = fabs(scale_point[2]);
284 double scale = std::max(std::max(xscale, yscale), zscale);
287 tbb::blocked_range<int>(0, V.size()),
288 [&](tbb::blocked_range<int> r) {
289 for (int i = r.begin(); i < r.end(); i++) {
295 constexpr int multi = 1000;
296 tbb::parallel_for(tbb::blocked_range<int>(0, V.size()), [&](tbb::blocked_range<int> r) {
297 for (int i = r.begin(); i < r.end(); i++) {
298 list_v[i].morton = Resorting::MortonCode64(
299 int(V[i][0] * multi),
300 int(V[i][1] * multi),
301 int(V[i][2] * multi));
306 const auto morton_compare = [](
const sortstruct& a,
const sortstruct& b) {
307 return (a.morton < b.morton);
310 tbb::parallel_sort(list_v.begin(), list_v.end(), morton_compare);
312 int interval = list_v.size() / NUM_THREADS + 1;
315 tbb::blocked_range<int>(0, list_v.size()),
316 [&](tbb::blocked_range<int> r) {
317 for (int i = r.begin(); i < r.end(); i++) {
318 m_vertex_attribute[list_v[i].order].partition_id = i / interval;
324 size_t get_partition_id(
const Tuple& loc)
const
326 return m_vertex_attribute[loc.vid(*
this)].partition_id;
329 void init_envelope(
const MatrixXd& V,
const MatrixXi& F,
const bool use_exact);
331 CellTag string_set_to_cell_tag(
const std::set<std::string>& str_set);
333 void set_length_regions(
const nlohmann::json& length_region_json);
335 double get_length2(
const Tuple& l)
const;
339 void write_msh(std::string file,
const bool write_envelope =
true);
340 void output_faces(std::string file, std::function<
bool(
const FaceAttributes&)> cond);
343 void split_all_edges();
344 bool split_edge_before(
const Tuple& t)
override;
345 bool split_edge_after(
const Tuple& loc)
override;
347 void smooth_all_vertices(
const size_t n_iters);
348 bool smooth_before(
const Tuple& t)
override;
349 bool smooth_after(
const Tuple& t)
override;
351 void collapse_all_edges(
bool is_limit_length =
true);
352 bool collapse_edge_before(
const Tuple& t)
override;
353 bool collapse_edge_after(
const Tuple& t)
override;
357 size_t swap_all_edges_44();
358 bool swap_edge_44_before(
const Tuple& t)
override;
359 double swap_edge_44_energy(
const std::vector<std::array<size_t, 4>>& tets,
const int op_case)
361 bool swap_edge_44_after(
const Tuple& t)
override;
363 size_t swap_all_edges_56();
364 bool swap_edge_56_before(
const Tuple& t)
override;
365 double swap_edge_56_energy(
const std::vector<std::array<size_t, 4>>& tets,
const int op_case)
367 bool swap_edge_56_after(
const Tuple& t)
override;
369 size_t swap_all_edges_32();
370 bool swap_edge_before(
const Tuple& t)
override;
371 bool swap_edge_after(
const Tuple& t)
override;
373 size_t swap_all_faces();
374 bool swap_face_before(
const Tuple& t)
override;
375 bool swap_face_after(
const Tuple& t)
override;
377 size_t swap_all_edges_all();
382 bool is_inverted_f(
const Tuple& loc)
const;
383 bool is_inverted(
const std::array<size_t, 4>& vs)
const;
384 bool is_inverted(
const Tuple& loc)
const;
385 double get_quality(
const std::array<size_t, 4>& vs)
const;
386 double get_quality(
const Tuple& loc)
const;
388 std::vector<std::array<double, 12>> get_amips_assembles(
const Tuple& t)
const;
390 std::shared_ptr<polysolve::nonlinear::Problem> get_amips_energy(
const Tuple& t)
const;
391 std::shared_ptr<polysolve::nonlinear::Problem> get_envelope_energy(
const Tuple& t)
const;
400 bool round(
const Tuple& loc);
406 bool all_rounded()
const;
409 bool is_edge_on_surface(
const Tuple& loc);
410 bool is_edge_on_bbox(
const Tuple& loc);
412 void mesh_improvement(
int max_its = 80);
413 std::tuple<double, double> local_operations(
414 const std::array<int, 4>& ops,
415 bool collapse_limit_length =
true);
416 std::tuple<double, double> get_max_avg_energy();
418 bool check_attributes();
420 std::vector<std::array<size_t, 3>> get_faces_by_condition(
421 std::function<
bool(
const FaceAttributes&)> cond)
const;
423 bool invariants(
const std::vector<Tuple>& t)
override;
426 std::atomic<int> cnt_split = 0, cnt_collapse = 0, cnt_swap = 0;
431 tbb::concurrent_map<std::array<size_t, 3>, std::vector<int>> tet_face_tags;
441 bool is_edge_on_surface =
false;
442 bool is_edge_open_boundary =
false;
443 std::vector<size_t> v1_param_type;
444 std::vector<size_t> v2_param_type;
446 std::vector<std::pair<FaceAttributes, std::array<size_t, 3>>> changed_faces;
452 std::map<simplex::Edge, TetAttributes>
tets;
454 tbb::enumerable_thread_specific<SplitInfoCache> split_cache;
462 bool is_limit_length;
464 std::vector<std::pair<FaceAttributes, std::array<size_t, 3>>> changed_faces;
466 std::vector<std::array<size_t, 3>> surface_faces;
468 std::vector<std::array<size_t, 2>> boundary_edges;
469 std::vector<size_t> changed_tids;
470 std::vector<double> changed_energies;
472 tbb::enumerable_thread_specific<CollapseInfoCache> collapse_cache;
481 tbb::enumerable_thread_specific<SwapInfoCache> swap_cache;
491 void init_from_image(
494 const MatrixSi& T_tags,
495 const std::vector<std::string>& tag_names);
496 void init_from_image(
499 const MatrixSi& T_tags,
500 const std::vector<std::string>& tag_names);
502 void init_surfaces_and_boundaries();
504 std::vector<std::array<size_t, 3>> triangulate_polygon_face(std::vector<Vector3r> points);
506 bool adjust_sizing_field_serial(
double max_energy);
517 void find_order_2_edges();
527 bool is_order_2_edge(
const Tuple& e)
const;
528 bool is_order_2_edge(
const std::array<size_t, 2>& e)
const;
530 void write_vtu(
const std::string& path);
532 void write_surface(
const std::string& path)
const;
537 bool vertex_is_on_surface(
const size_t vid)
const override;
539 bool face_is_on_surface(
const size_t fid)
const override;
541 size_t get_order_of_vertex(
const size_t vid)
const override;
545 void init_vertex_order();
550 double tet_volume(
const size_t tid)
const;
555 std::vector<ConnectedComponent> compute_connected_components(
const CellTag& tag_in)
const;
574 std::vector<ConnectedComponent> find_holes(
const std::vector<CellTag>& tag_in)
const;
584 void compute_tag_boundary(
const CellTag& tag, MatrixXd& V, MatrixXi& F)
const;
593 void keep_largest_connected_component(
594 const std::vector<CellTag>& lcc_tags,
595 const size_t n_lcc = 1);
597 void fill_holes_topo(
598 const std::vector<CellTag>& fill_holes_tags,
599 double threshold = std::numeric_limits<double>::infinity());
601 void seal_connected_components(
602 const std::vector<CellTag>& tag_sets,
603 const std::vector<ConnectedComponent>& components);
605 void tight_seal_topo(
606 const std::vector<std::vector<CellTag>>& tight_seal_tag_sets,
607 double threshold = std::numeric_limits<double>::infinity());
609 void resolve_intersections(
const std::vector<CellTag>& intersecting_tags);
611 void replace_tags(
const std::vector<CellTag>& tags_in,
const std::vector<CellTag>& tags_out);
623 void tag_priority(
const std::vector<int64_t>& tags);