47static inline void grad(
const Eigen::PlainObjectBase<DerivedV> &
V,
48 const Eigen::PlainObjectBase<DerivedF> &F,
49 Eigen::SparseMatrix<typename DerivedV::Scalar> &
G,
52 Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 3> eperp21(F.rows(), 3),
55 for (
int i = 0; i < F.rows(); ++i) {
62 Eigen::Matrix<typename DerivedV::Scalar, 1, 3> v32 =
V.row(i3) -
V.row(i2);
63 Eigen::Matrix<typename DerivedV::Scalar, 1, 3> v13 =
V.row(i1) -
V.row(i3);
64 Eigen::Matrix<typename DerivedV::Scalar, 1, 3> v21 =
V.row(i2) -
V.row(i1);
65 Eigen::Matrix<typename DerivedV::Scalar, 1, 3> n = v32.cross(v13);
70 double dblA = std::sqrt(n.dot(n));
71 Eigen::Matrix<typename DerivedV::Scalar, 1, 3> u;
80 double h =
sqrt((dblA) /
83 Eigen::VectorXd v1,
v2, v3;
86 v3 << h / 2., (
sqrt(3) / 2.) * h, 0;
96 double norm21 = std::sqrt(v21.dot(v21));
97 double norm13 = std::sqrt(v13.dot(v13));
98 eperp21.row(i) = u.cross(v21);
99 eperp21.row(i) = eperp21.row(i) / std::sqrt(eperp21.row(i).dot(eperp21.row(i)));
100 eperp21.row(i) *= norm21 / dblA;
101 eperp13.row(i) = u.cross(v13);
102 eperp13.row(i) = eperp13.row(i) / std::sqrt(eperp13.row(i).dot(eperp13.row(i)));
103 eperp13.row(i) *= norm13 / dblA;
107 rs.reserve(F.rows() * 4 * 3);
109 cs.reserve(F.rows() * 4 * 3);
110 std::vector<double> vs;
111 vs.reserve(F.rows() * 4 * 3);
114 for (
int r = 0; r < 3; r++) {
115 for (
int j = 0; j < 4; j++) {
116 for (
int i = r * F.rows(); i < (r + 1) * F.rows(); i++)
122 for (
int r = 0; r < 3; r++) {
123 for (
int i = 0; i < F.rows(); i++)
124 cs.push_back(F(i, 1));
125 for (
int i = 0; i < F.rows(); i++)
126 cs.push_back(F(i, 0));
127 for (
int i = 0; i < F.rows(); i++)
128 cs.push_back(F(i, 2));
129 for (
int i = 0; i < F.rows(); i++)
130 cs.push_back(F(i, 0));
134 for (
int i = 0; i < F.rows(); i++)
135 vs.push_back(eperp13(i, 0));
136 for (
int i = 0; i < F.rows(); i++)
137 vs.push_back(-eperp13(i, 0));
138 for (
int i = 0; i < F.rows(); i++)
139 vs.push_back(eperp21(i, 0));
140 for (
int i = 0; i < F.rows(); i++)
141 vs.push_back(-eperp21(i, 0));
142 for (
int i = 0; i < F.rows(); i++)
143 vs.push_back(eperp13(i, 1));
144 for (
int i = 0; i < F.rows(); i++)
145 vs.push_back(-eperp13(i, 1));
146 for (
int i = 0; i < F.rows(); i++)
147 vs.push_back(eperp21(i, 1));
148 for (
int i = 0; i < F.rows(); i++)
149 vs.push_back(-eperp21(i, 1));
150 for (
int i = 0; i < F.rows(); i++)
151 vs.push_back(eperp13(i, 2));
152 for (
int i = 0; i < F.rows(); i++)
153 vs.push_back(-eperp13(i, 2));
154 for (
int i = 0; i < F.rows(); i++)
155 vs.push_back(eperp21(i, 2));
156 for (
int i = 0; i < F.rows(); i++)
157 vs.push_back(-eperp21(i, 2));
160 G.resize(3 * F.rows(),
V.rows());
161 std::vector<Eigen::Triplet<typename DerivedV::Scalar>> triplets;
162 for (
int i = 0; i < (
int)vs.size(); ++i) {
163 triplets.push_back(Eigen::Triplet<typename DerivedV::Scalar>(rs[i], cs[i], vs[i]));
165 G.setFromTriplets(triplets.begin(), triplets.end());
186static inline void polar_svd(
const Eigen::PlainObjectBase<DerivedA> &A,
187 Eigen::PlainObjectBase<DerivedR> &
R,
188 Eigen::PlainObjectBase<DerivedT> &T,
189 Eigen::PlainObjectBase<DerivedU> &
U,
190 Eigen::PlainObjectBase<DerivedS> &S,
191 Eigen::PlainObjectBase<DerivedV> &
V)
194 Eigen::JacobiSVD<DerivedA> svd;
195 svd.compute(A, Eigen::ComputeFullU | Eigen::ComputeFullV);
198 S = svd.singularValues();
199 R =
U *
V.transpose();
200 const auto &SVT = S.asDiagonal() *
V.adjoint();
202 if (
R.determinant() < 0) {
205 W.col(
V.cols() - 1) *= -1.;
206 R =
U *
W.transpose();
215 const Eigen::MatrixXi &F,
216 const Eigen::MatrixXd &F1,
217 const Eigen::MatrixXd &F2,
218 Eigen::SparseMatrix<double> &D1,
219 Eigen::SparseMatrix<double> &D2)
221 Eigen::SparseMatrix<double>
G;
223 Eigen::SparseMatrix<double> Dx =
G.block(0, 0, F.rows(),
V.rows());
224 Eigen::SparseMatrix<double> Dy =
G.block(F.rows(), 0, F.rows(),
V.rows());
225 Eigen::SparseMatrix<double> Dz =
G.block(2 * F.rows(), 0, F.rows(),
V.rows());
227 D1 = F1.col(0).asDiagonal() * Dx + F1.col(1).asDiagonal() * Dy + F1.col(2).asDiagonal() * Dz;
228 D2 = F2.col(0).asDiagonal() * Dx + F2.col(1).asDiagonal() * Dy + F2.col(2).asDiagonal() * Dz;
277 const double eps = 1
e-8;
278 double exp_f = s.exp_factor;
280 for (
int i = 0; i < s.Ji.rows(); ++i) {
281 typedef Eigen::Matrix<double, 2, 2> Mat2;
282 typedef Eigen::Matrix<double, 2, 1>
Vec2;
283 Mat2 ji, ri, ti, ui, vi;
285 Vec2 closest_sing_vec;
290 ji(0, 0) = s.Ji(i, 0);
291 ji(0, 1) = s.Ji(i, 1);
292 ji(1, 0) = s.Ji(i, 2);
293 ji(1, 1) = s.Ji(i, 3);
301 switch (s.slim_energy) {
307 double s1_g = 2 * (s1 -
pow(s1, -3));
308 double s2_g = 2 * (s2 -
pow(s2, -3));
309 m_sing_new <<
sqrt(s1_g / (2 * (s1 - 1))),
sqrt(s2_g / (2 * (s2 - 1)));
313 double s1_g = 2 * (
log(s1) / s1);
314 double s2_g = 2 * (
log(s2) / s2);
315 m_sing_new <<
sqrt(s1_g / (2 * (s1 - 1))),
sqrt(s2_g / (2 * (s2 - 1)));
319 double s1_g = 1 / (2 * s2) - s2 / (2 *
pow(s1, 2));
320 double s2_g = 1 / (2 * s1) - s1 / (2 *
pow(s2, 2));
322 double geo_avg =
sqrt(s1 * s2);
323 double s1_min = geo_avg;
324 double s2_min = geo_avg;
326 m_sing_new <<
sqrt(s1_g / (2 * (s1 - s1_min))),
sqrt(s2_g / (2 * (s2 - s2_min)));
329 closest_sing_vec << s1_min, s2_min;
330 ri = ui * closest_sing_vec.asDiagonal() * vi.transpose();
334 double s1_g = 2 * (s1 -
pow(s1, -3));
335 double s2_g = 2 * (s2 -
pow(s2, -3));
337 double in_exp = exp_f * ((
pow(s1, 2) +
pow(s2, 2)) / (2 * s1 * s2));
338 double exp_thing =
exp(in_exp);
340 s1_g *= exp_thing * exp_f;
341 s2_g *= exp_thing * exp_f;
343 m_sing_new <<
sqrt(s1_g / (2 * (s1 - 1))),
sqrt(s2_g / (2 * (s2 - 1)));
347 double s1_g = 2 * (s1 -
pow(s1, -3));
348 double s2_g = 2 * (s2 -
pow(s2, -3));
350 double in_exp = exp_f * (
pow(s1, 2) +
pow(s1, -2) +
pow(s2, 2) +
pow(s2, -2));
351 double exp_thing =
exp(in_exp);
353 s1_g *= exp_thing * exp_f;
354 s2_g *= exp_thing * exp_f;
356 m_sing_new <<
sqrt(s1_g / (2 * (s1 - 1))),
sqrt(s2_g / (2 * (s2 - 1)));
361 if (std::abs(s1 - 1) <
eps)
363 if (std::abs(s2 - 1) <
eps)
365 mat_W = ui * m_sing_new.asDiagonal() * ui.transpose();
367 s.W_11(i) = mat_W(0, 0);
368 s.W_12(i) = mat_W(0, 1);
369 s.W_21(i) = mat_W(1, 0);
370 s.W_22(i) = mat_W(1, 1);
374 s.Ri(i, 0) = ri(0, 0);
375 s.Ri(i, 1) = ri(1, 0);
376 s.Ri(i, 2) = ri(0, 1);
377 s.Ri(i, 3) = ri(1, 1);
382static inline void local_basis(
const Eigen::PlainObjectBase<DerivedV> &
V,
383 const Eigen::PlainObjectBase<DerivedF> &F,
384 Eigen::PlainObjectBase<DerivedV> &B1,
385 Eigen::PlainObjectBase<DerivedV> &B2,
386 Eigen::PlainObjectBase<DerivedV> &B3)
388 using namespace Eigen;
390 B1.resize(F.rows(), 3);
391 B2.resize(F.rows(), 3);
392 B3.resize(F.rows(), 3);
394 for (
unsigned i = 0; i < F.rows(); ++i) {
395 Eigen::Matrix<typename DerivedV::Scalar, 1, 3> v1 =
397 Eigen::Matrix<typename DerivedV::Scalar, 1, 3> t =
V.row(
F(i, 2)) -
V.row(F(i, 0));
398 Eigen::Matrix<typename DerivedV::Scalar, 1, 3> v3 = v1.cross(t).normalized();
399 Eigen::Matrix<typename DerivedV::Scalar, 1, 3>
v2 = v1.cross(v3).normalized();
410 if (!s.has_pre_calc) {
415 Eigen::MatrixXd F1, F2, F3;
419 s.W_11.resize(s.f_n);
420 s.W_12.resize(s.f_n);
421 s.W_21.resize(s.f_n);
422 s.W_22.resize(s.f_n);
424 s.Dx.makeCompressed();
425 s.Dy.makeCompressed();
426 s.Dz.makeCompressed();
427 s.Ri.resize(s.f_n, s.dim * s.dim);
428 s.Ji.resize(s.f_n, s.dim * s.dim);
429 s.rhs.resize(s.dim * s.v_num);
432 s.WGL_M.resize(s.dim * s.dim * s.f_n);
433 for (
int i = 0; i < s.dim * s.dim; i++)
434 for (
int j = 0; j < s.f_n; j++)
435 s.WGL_M(i * s.f_n + j) = s.M(j);
437 s.first_solve =
true;
438 s.has_pre_calc =
true;
446 std::vector<Eigen::Triplet<double>> IJV;
448 IJV.reserve(4 * (s.Dx.outerSize() + s.Dy.outerSize()));
454 for (
int k = 0; k < s.Dx.outerSize(); ++k) {
455 for (Eigen::SparseMatrix<double>::InnerIterator it(s.Dx, k); it; ++it) {
458 double val = it.value();
459 double weight = s.weightPerFaceMap(dx_r);
461 IJV.push_back(Eigen::Triplet<double>(dx_r, dx_c, weight * val * s.W_11(dx_r)));
462 IJV.push_back(Eigen::Triplet<double>(dx_r, s.v_n + dx_c, weight * val * s.W_12(dx_r)));
464 IJV.push_back(Eigen::Triplet<double>(2 * s.f_n + dx_r, dx_c, weight * val * s.W_21(dx_r)));
466 Eigen::Triplet<double>(2 * s.f_n + dx_r, s.v_n + dx_c, weight * val * s.W_22(dx_r)));
470 for (
int k = 0; k < s.Dy.outerSize(); ++k) {
471 for (Eigen::SparseMatrix<double>::InnerIterator it(s.Dy, k); it; ++it) {
474 double val = it.value();
475 double weight = s.weightPerFaceMap(dy_r);
477 IJV.push_back(Eigen::Triplet<double>(s.f_n + dy_r, dy_c, weight * val * s.W_11(dy_r)));
479 Eigen::Triplet<double>(s.f_n + dy_r, s.v_n + dy_c, weight * val * s.W_12(dy_r)));
481 IJV.push_back(Eigen::Triplet<double>(3 * s.f_n + dy_r, dy_c, weight * val * s.W_21(dy_r)));
483 Eigen::Triplet<double>(3 * s.f_n + dy_r, s.v_n + dy_c, weight * val * s.W_22(dy_r)));
487 A.setFromTriplets(IJV.begin(), IJV.end());
494 Eigen::VectorXd f_rhs(s.dim * s.dim * s.f_n);
501 for (
int i = 0; i < s.f_n; i++) {
502 f_rhs(i + 0 * s.f_n) = s.W_11(i) * s.Ri(i, 0) + s.W_12(i) * s.Ri(i, 1);
503 f_rhs(i + 1 * s.f_n) = s.W_11(i) * s.Ri(i, 2) + s.W_12(i) * s.Ri(i, 3);
504 f_rhs(i + 2 * s.f_n) = s.W_21(i) * s.Ri(i, 0) + s.W_22(i) * s.Ri(i, 1);
505 f_rhs(i + 3 * s.f_n) = s.W_21(i) * s.Ri(i, 2) + s.W_22(i) * s.Ri(i, 3);
508 Eigen::VectorXd uv_flat(s.dim * s.v_n);
509 for (
int i = 0; i < s.dim; i++)
510 for (
int j = 0; j < s.v_n; j++)
511 uv_flat(s.v_n * i + j) = s.V_o(j, i);
513 s.rhs = (At * s.WGL_M.asDiagonal() * f_rhs + s.proximal_p * uv_flat);
553 const Eigen::MatrixXd &Ji,
554 Eigen::VectorXd &areas,
555 Eigen::VectorXd &singularValues,
556 bool gatherSingularValues)
561 Eigen::Matrix<double, 2, 2> ji;
562 for (
int i = 0; i < s.f_n; i++) {
568 typedef Eigen::Matrix<double, 2, 2> Mat2;
569 typedef Eigen::Matrix<double, 2, 1>
Vec2;
576 switch (s.slim_energy) {
578 energy += areas(i) * (
pow(s1 - 1, 2) +
pow(s2 - 1, 2));
582 energy += areas(i) * (
pow(s1, 2) +
pow(s1, -2) +
pow(s2, 2) +
pow(s2, -2));
584 if (gatherSingularValues) {
585 singularValues(i) = s1;
586 singularValues(i + s.F.rows()) = s2;
592 exp(s.exp_factor * (
pow(s1, 2) +
pow(s1, -2) +
pow(s2, 2) +
pow(s2, -2)));
596 energy += areas(i) * (
pow(
log(s1), 2) +
pow(
log(s2), 2));
600 energy += areas(i) * ((
pow(s1, 2) +
pow(s2, 2)) / (2 * s1 * s2));
604 energy += areas(i) *
exp(s.exp_factor * ((
pow(s1, 2) +
pow(s2, 2)) / (2 * s1 * s2)));
691 Eigen::VectorXd &areas)
693 int nFaces = singularValues.rows() / 2;
695 Eigen::VectorXd areasChained(2 * nFaces);
696 areasChained << areas, areas;
721 Eigen::VectorXd squaredSingularValues = singularValues.cwiseProduct(singularValues);
722 Eigen::VectorXd inverseSquaredSingularValues =
723 singularValues.cwiseProduct(singularValues).cwiseInverse();
725 Eigen::VectorXd weightedSquaredSingularValues = squaredSingularValues.cwiseProduct(areasChained);
726 Eigen::VectorXd weightedInverseSquaredSingularValues = inverseSquaredSingularValues.cwiseProduct(
729 double s1 = weightedSquaredSingularValues.head(nFaces).sum();
730 double s2 = weightedSquaredSingularValues.tail(nFaces).sum();
732 double t1 = weightedInverseSquaredSingularValues.head(nFaces).sum();
733 double t2 = weightedInverseSquaredSingularValues.tail(nFaces).sum();
767 Eigen::VectorXd singularValues;
768 bool are_pins_present = data.b.rows() > 0;
770 if (are_pins_present) {
771 singularValues.resize(data.F.rows() * 2);
772 data.energy =
compute_energy(data, data.V_o, singularValues) / data.mesh_area;
775 for (
int i = 0; i < iter_num; i++) {
776 Eigen::MatrixXd dest_res;
783 std::function<
double(Eigen::MatrixXd &)> compute_energy_func = [&](Eigen::MatrixXd &aaa) {
784 return are_pins_present ?
compute_energy(data, aaa, singularValues) :
792 data.energy * data.mesh_area) /
795 if (are_pins_present) {
798 data.Dx /= data.globalScaleInvarianceFactor;
799 data.Dy /= data.globalScaleInvarianceFactor;
800 data.energy =
compute_energy(data, data.V_o, singularValues) / data.mesh_area;