127 using ExprPtr = expression_parser::ExpressionPtr;
129 int m_debug_print_counter = 0;
130 size_t m_tags_count = 0;
131 std::map<int64_t, std::string> m_tag_id_to_name;
132 std::map<std::string, int64_t> m_tag_name_to_id;
134 double time_env = 0.0;
135 igl::Timer isout_timer;
136 const double MAX_ENERGY = std::numeric_limits<double>::max();
139 std::vector<Vector3d> m_V_envelope;
140 std::vector<Vector3i> m_F_envelope;
141 std::shared_ptr<SampleEnvelope> m_envelope;
142 std::shared_ptr<SampleEnvelope> m_envelope_orig;
143 double m_envelope_eps = -1;
145 std::vector<std::tuple<ExprPtr, double>> m_sizing_field;
147 bool m_collapse_check_quality =
true;
150 std::shared_ptr<SampleEnvelope> m_order_2_edge_envelope;
152 tbb::enumerable_thread_specific<std::unique_ptr<polysolve::nonlinear::Solver>> m_solver;
155 double m_s_amips = -1;
156 double m_s_envelope = -1;
160 std::function<double(
const Vector3d&)> m_voronoi_split_fn =
nullptr;
163 : m_params(_m_params)
164 , m_envelope_eps(envelope_eps)
166 NUM_THREADS = _num_threads;
167 p_vertex_attrs = &m_vertex_attribute;
168 p_face_attrs = &m_face_attribute;
169 p_tet_attrs = &m_tet_attribute;
170 m_collapse_check_link_condition =
false;
171 m_collapse_check_manifold =
false;
175 optimization::deactivate_opt_logger();
178 m_s_envelope = 1. / (m_params.diag_l * m_params.eps * m_params.eps);
180 double& wa = m_params.w_amips;
181 double& we = m_params.w_envelope;
183 logger().info(
"w_envelope = {}", we);
197 void create_mesh_attributes(
198 const std::vector<VertexAttributes>& _vertex_attribute,
199 const std::vector<TetAttributes>& _tet_attribute)
201 auto n_tet = _tet_attribute.size();
202 m_vertex_attribute.resize(_vertex_attribute.size());
203 m_face_attribute.resize(4 * n_tet);
204 m_tet_attribute.resize(n_tet);
206 for (
auto i = 0; i < _vertex_attribute.size(); i++) {
207 m_vertex_attribute[i] = _vertex_attribute[i];
209 m_tet_attribute.m_attributes = tbb::concurrent_vector<TetAttributes>(_tet_attribute.size());
210 for (
auto i = 0; i < _tet_attribute.size(); i++) {
211 m_tet_attribute[i] = _tet_attribute[i];
213 for (
auto i = 0; i < _tet_attribute.size(); i++) {
219 void compute_vertex_partition()
221 auto partition_id = partition_TetMesh(*
this, NUM_THREADS);
223 m_vertex_attribute[i].partition_id = partition_id[i];
227 void compute_vertex_partition_morton()
229 if (NUM_THREADS == 0)
return;
231 wmtk::logger().info(
"Number of parts: {} by morton", NUM_THREADS);
233 tbb::task_arena arena(NUM_THREADS);
239 tbb::blocked_range<int>(0, V_v.size()),
240 [&](tbb::blocked_range<int> r) {
241 for (int i = r.begin(); i < r.end(); i++) {
242 V_v[i] = m_vertex_attribute[i].m_posf;
253 std::vector<sortstruct> list_v;
254 list_v.resize(V_v.size());
257 std::vector<Eigen::Vector3d> V = V_v;
258 Eigen::Vector3d vmin, vmax;
262 for (
size_t j = 0; j < V.size(); j++) {
263 for (
int i = 0; i < 3; i++) {
264 vmin(i) = std::min(vmin(i), V[j](i));
265 vmax(i) = std::max(vmax(i), V[j](i));
270 Eigen::Vector3d center = (vmin + vmax) / 2;
272 tbb::parallel_for(tbb::blocked_range<int>(0, V.size()), [&](tbb::blocked_range<int> r) {
273 for (int i = r.begin(); i < r.end(); i++) {
274 V[i] = V[i] - center;
278 Eigen::Vector3d scale_point =
281 double xscale, yscale, zscale;
282 xscale = fabs(scale_point[0]);
283 yscale = fabs(scale_point[1]);
284 zscale = fabs(scale_point[2]);
285 double scale = std::max(std::max(xscale, yscale), zscale);
288 tbb::blocked_range<int>(0, V.size()),
289 [&](tbb::blocked_range<int> r) {
290 for (int i = r.begin(); i < r.end(); i++) {
296 constexpr int multi = 1000;
297 tbb::parallel_for(tbb::blocked_range<int>(0, V.size()), [&](tbb::blocked_range<int> r) {
298 for (int i = r.begin(); i < r.end(); i++) {
299 list_v[i].morton = Resorting::MortonCode64(
300 int(V[i][0] * multi),
301 int(V[i][1] * multi),
302 int(V[i][2] * multi));
307 const auto morton_compare = [](
const sortstruct& a,
const sortstruct& b) {
308 return (a.morton < b.morton);
311 tbb::parallel_sort(list_v.begin(), list_v.end(), morton_compare);
313 int interval = list_v.size() / NUM_THREADS + 1;
316 tbb::blocked_range<int>(0, list_v.size()),
317 [&](tbb::blocked_range<int> r) {
318 for (int i = r.begin(); i < r.end(); i++) {
319 m_vertex_attribute[list_v[i].order].partition_id = i / interval;
325 size_t get_partition_id(
const Tuple& loc)
const
327 return m_vertex_attribute[loc.vid(*
this)].partition_id;
330 void init_envelope(
const MatrixXd& V,
const MatrixXi& F,
const bool use_exact);
332 CellTag string_set_to_cell_tag(
const std::set<std::string>& str_set);
334 void set_sizing_field(
const nlohmann::json& m_sizing_field_json);
336 double get_length2(
const Tuple& l)
const;
340 void write_msh(std::string file,
const bool write_envelope =
true);
341 void output_faces(std::string file, std::function<
bool(
const FaceAttributes&)> cond);
344 void split_all_edges();
345 bool split_edge_before(
const Tuple& t)
override;
346 bool split_edge_after(
const Tuple& loc)
override;
348 void smooth_all_vertices(
const size_t n_iters);
349 bool smooth_before(
const Tuple& t)
override;
350 bool smooth_after(
const Tuple& t)
override;
352 void collapse_all_edges(
bool is_limit_length =
true);
353 bool collapse_edge_before(
const Tuple& t)
override;
354 bool collapse_edge_after(
const Tuple& t)
override;
358 size_t swap_all_edges_44();
359 bool swap_edge_44_before(
const Tuple& t)
override;
360 double swap_edge_44_energy(
const std::vector<std::array<size_t, 4>>& tets,
const int op_case)
362 bool swap_edge_44_after(
const Tuple& t)
override;
364 size_t swap_all_edges_56();
365 bool swap_edge_56_before(
const Tuple& t)
override;
366 double swap_edge_56_energy(
const std::vector<std::array<size_t, 4>>& tets,
const int op_case)
368 bool swap_edge_56_after(
const Tuple& t)
override;
370 size_t swap_all_edges_32();
371 bool swap_edge_before(
const Tuple& t)
override;
372 bool swap_edge_after(
const Tuple& t)
override;
374 size_t swap_all_faces();
375 bool swap_face_before(
const Tuple& t)
override;
376 bool swap_face_after(
const Tuple& t)
override;
378 size_t swap_all_edges_all();
383 bool is_inverted_f(
const Tuple& loc)
const;
384 bool is_inverted(
const std::array<size_t, 4>& vs)
const;
385 bool is_inverted(
const Tuple& loc)
const;
386 double get_quality(
const std::array<size_t, 4>& vs)
const;
387 double get_quality(
const Tuple& loc)
const;
389 std::vector<std::array<double, 12>> get_amips_assembles(
const Tuple& t)
const;
391 std::shared_ptr<polysolve::nonlinear::Problem> get_amips_energy(
const Tuple& t)
const;
392 std::shared_ptr<polysolve::nonlinear::Problem> get_envelope_energy(
const Tuple& t)
const;
401 bool round(
const Tuple& loc);
407 bool all_rounded()
const;
410 bool is_edge_on_surface(
const Tuple& loc);
411 bool is_edge_on_bbox(
const Tuple& loc);
413 void mesh_improvement(
int max_its = 80);
414 std::tuple<double, double> local_operations(
415 const std::array<int, 4>& ops,
416 bool collapse_limit_length =
true);
417 std::tuple<double, double> get_max_avg_energy();
419 bool check_attributes();
421 std::vector<std::array<size_t, 3>> get_faces_by_condition(
422 std::function<
bool(
const FaceAttributes&)> cond)
const;
424 bool invariants(
const std::vector<Tuple>& t)
override;
427 std::atomic<int> cnt_split = 0, cnt_collapse = 0, cnt_swap = 0;
432 tbb::concurrent_map<std::array<size_t, 3>, std::vector<int>> tet_face_tags;
442 bool is_edge_on_surface =
false;
443 bool is_edge_open_boundary =
false;
444 std::vector<size_t> v1_param_type;
445 std::vector<size_t> v2_param_type;
447 std::vector<std::pair<FaceAttributes, std::array<size_t, 3>>> changed_faces;
453 std::map<simplex::Edge, TetAttributes>
tets;
455 tbb::enumerable_thread_specific<SplitInfoCache> split_cache;
463 bool is_limit_length;
465 std::vector<std::pair<FaceAttributes, std::array<size_t, 3>>> changed_faces;
467 std::vector<std::array<size_t, 3>> surface_faces;
469 std::vector<std::array<size_t, 2>> boundary_edges;
470 std::vector<size_t> changed_tids;
471 std::vector<double> changed_energies;
473 tbb::enumerable_thread_specific<CollapseInfoCache> collapse_cache;
482 tbb::enumerable_thread_specific<SwapInfoCache> swap_cache;
492 void init_from_image(
495 const MatrixSi& T_tags,
496 const std::vector<std::string>& tag_names);
497 void init_from_image(
500 const MatrixSi& T_tags,
501 const std::vector<std::string>& tag_names);
503 void init_surfaces_and_boundaries();
505 std::vector<std::array<size_t, 3>> triangulate_polygon_face(std::vector<Vector3r> points);
507 bool adjust_sizing_field_serial(
double max_energy);
518 void find_order_2_edges();
528 bool is_order_2_edge(
const Tuple& e)
const;
529 bool is_order_2_edge(
const std::array<size_t, 2>& e)
const;
531 void write_vtu(
const std::string& path);
533 void write_surface(
const std::string& path)
const;
538 bool vertex_is_on_surface(
const size_t vid)
const override;
540 bool face_is_on_surface(
const size_t fid)
const override;
542 size_t get_order_of_vertex(
const size_t vid)
const override;
546 void init_vertex_order();
551 double tet_volume(
const size_t tid)
const;
556 std::vector<ConnectedComponent> compute_connected_components(
const CellTag& tag_in)
const;
557 std::vector<ConnectedComponent> compute_connected_components(
const ExprPtr& expr)
const;
576 std::vector<ConnectedComponent> find_holes(
const std::vector<CellTag>& tag_in)
const;
586 void compute_tag_boundary(
const CellTag& tag, MatrixXd& V, MatrixXi& F)
const;
595 void keep_largest_connected_component(
596 const std::vector<CellTag>& lcc_tags,
597 const size_t n_lcc = 1);
599 void fill_holes_topo(
600 const std::vector<CellTag>& fill_holes_tags,
601 double threshold = std::numeric_limits<double>::infinity());
603 void seal_connected_components(
604 const std::vector<CellTag>& tag_sets,
605 const std::vector<ConnectedComponent>& components);
607 void tight_seal_topo(
608 const std::vector<std::vector<CellTag>>& tight_seal_tag_sets,
609 double threshold = std::numeric_limits<double>::infinity());
611 void resolve_overlaps(
const std::vector<std::array<ExprPtr, 2>>& intersecting_tags);
613 void replace_tags(
const std::vector<CellTag>& tags_in,
const std::vector<CellTag>& tags_out);
625 void tag_priority(
const std::vector<int64_t>& tags);