PolyFEM
Loading...
Searching...
No Matches
SlimSmooth.cpp
Go to the documentation of this file.
1#include "SlimSmooth.hpp"
2
3#include <ipc/utils/eigen_ext.hpp>
4#include <igl/boundary_facets.h>
7#include <igl/slim.h>
8
9namespace polyfem::mesh
10{
11 bool apply_slim(const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const Eigen::MatrixXd &V_new, Eigen::MatrixXd &V_smooth, const int max_iters)
12 {
13 const int dim = F.cols() - 1;
14
15 if (utils::is_flipped(V_new, F))
16 {
17 adjoint_logger().warn("Mesh is flipped before SLIM!");
18 return false;
19 }
20
21 Eigen::MatrixXd V_extended;
22 V_extended.setZero(V.rows(), 3);
23 V_extended.leftCols(dim) = V;
24
25 Eigen::VectorXi boundary_indices;
26 {
27 Eigen::MatrixXi boundary;
28 igl::boundary_facets(F, boundary);
29 std::set<int> slim_constrained_nodes;
30 for (int i = 0; i < boundary.rows(); ++i)
31 for (int j = 0; j < boundary.cols(); ++j)
32 slim_constrained_nodes.insert(boundary(i, j));
33
34 boundary_indices.setZero(slim_constrained_nodes.size());
35 int i = 0;
36 for (const auto &c : slim_constrained_nodes)
37 boundary_indices(i++) = c;
38 }
39
40 const double soft_const_p = 1e5;
41 const int slim_iters = 2;
42 const double tol = 1e-8;
43
44 const Eigen::MatrixXd boundary_constraints = V_new(boundary_indices, Eigen::all);
45
46 igl::SLIMData slim_data;
47 slim_data.exp_factor = 5;
48 igl::slim_precompute(
49 V_extended,
50 F,
51 V,
52 slim_data,
53 igl::SYMMETRIC_DIRICHLET,
54 boundary_indices,
55 boundary_constraints,
56 soft_const_p);
57
58 V_smooth.setZero(V.rows(), V.cols());
59
60 double error = 0;
61 int it = 0;
62 bool good_enough = false;
63
64 do
65 {
66 igl::slim_solve(slim_data, slim_iters);
67 error = (slim_data.V_o(boundary_indices, Eigen::all) - boundary_constraints).squaredNorm() / boundary_indices.size();
68 good_enough = error < 1e-7;
69 V_smooth = slim_data.V_o.leftCols(dim);
70 it += slim_iters;
71 } while (it < max_iters && !good_enough);
72
73 V_smooth(boundary_indices, Eigen::all) = boundary_constraints;
74 logger().debug("SLIM finished in {} iterations", it);
75
76 if (good_enough)
77 logger().debug("SLIM succeeded.");
78 else
79 logger().warn("SLIM cannot smooth correctly. Error: {}", error);
80
81 return good_enough;
82 }
83} // namespace polyfem::mesh
int V
bool apply_slim(const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const Eigen::MatrixXd &V_new, Eigen::MatrixXd &V_smooth, const int max_iters)
bool is_flipped(const Eigen::MatrixXd &V, const Eigen::MatrixXi &F)
Determine if any simplex is inverted or collapses.
spdlog::logger & logger()
Retrieves the current logger.
Definition Logger.cpp:44
spdlog::logger & adjoint_logger()
Retrieves the current logger for adjoint.
Definition Logger.cpp:30