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>
6#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
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
35 boundary_indices.setZero(slim_constrained_nodes.size());
36 int i = 0;
37 for (const auto &c : slim_constrained_nodes)
38 boundary_indices(i++) = c;
39 }
40
41 const double soft_const_p = 1e5;
42 const int slim_iters = 2;
43 const double tol = 1e-8;
44
45 const Eigen::MatrixXd boundary_constraints = V_new(boundary_indices, Eigen::all);
46
47 igl::SLIMData slim_data;
48 slim_data.exp_factor = 5;
49 igl::slim_precompute(
50 V_extended,
51 F,
52 V,
53 slim_data,
54 igl::SYMMETRIC_DIRICHLET,
55 boundary_indices,
56 boundary_constraints,
57 soft_const_p);
58
59 V_smooth.setZero(V.rows(), V.cols());
60
61 double error = 0;
62 int it = 0;
63 bool good_enough = false;
64
65 do
66 {
67 igl::slim_solve(slim_data, slim_iters);
68 error = (slim_data.V_o(boundary_indices, Eigen::all) - boundary_constraints).squaredNorm() / boundary_indices.size();
69 good_enough = error < 1e-7;
70 V_smooth = slim_data.V_o.leftCols(dim);
71 it += slim_iters;
72 } while (it < max_iters && !good_enough);
73
74 V_smooth(boundary_indices, Eigen::all) = boundary_constraints;
75 logger().debug("SLIM finished in {} iterations", it);
76
77 if (good_enough)
78 logger().debug("SLIM succeeded.");
79 else
80 logger().warn("SLIM cannot smooth correctly. Error: {}", error);
81
82 return good_enough;
83 }
84} // 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)
spdlog::logger & logger()
Retrieves the current logger.
Definition Logger.cpp:42
spdlog::logger & adjoint_logger()
Retrieves the current logger for adjoint.
Definition Logger.cpp:28