Wildmeshing Toolkit
amips.hpp
Go to the documentation of this file.
1 #pragma once
2 #include <Eigen/Dense>
3 #include <wmtk/Types.hpp>
4 
5 namespace wmtk::function::utils {
6 
7 namespace detail {
8 // returns v0,v1,v2 of the target triangle as row vectors
9 extern const Eigen::Matrix<double, 2, 3> amips_target_triangle;
10 // maps from the embedding of the reference triangle to the barycentric coordinates
11 extern const Eigen::Matrix2d amips_reference_to_barycentric;
12 
13 } // namespace detail
14 
15 
16 // Given an basis vectors following a "v1-v0,v2-v0" convention for a triangle (v0,v1,v2)
17 // return the AMIPS energy for a triangle.
18 // Input are assumed to be column vectors, opposite of the standard IGL formation
19 template <typename Derived>
20 auto amips(const Eigen::MatrixBase<Derived>& B)
21 {
22  using Scalar = typename Derived::Scalar;
23  constexpr static int Rows = Derived::RowsAtCompileTime;
24  constexpr static int Cols = Derived::ColsAtCompileTime;
25 
26 
27  // check that these are vectors
28  static_assert(Cols == 2);
29  static_assert(Rows == 2);
30 
31 
32  // MTAO: Why can't this work with more than 2 rows?
33  // define of transform matrix F = Dm@Ds.inv
34  Eigen::Matrix<Scalar, Rows, 2> J;
35  J = B * detail::amips_reference_to_barycentric.template cast<Scalar>();
36 
37  auto Jdet = J.determinant();
38  if (abs(Jdet) < std::numeric_limits<double>::denorm_min()) {
39  return static_cast<Scalar>(std::numeric_limits<double>::infinity());
40  }
41  assert(Jdet >= 0);
42 
43  return (J * J.transpose()).trace() / Jdet;
44 }
45 
46 
47 //
48 template <typename V0Type, typename V1Type, typename V2Type>
49 auto amips(
50  const Eigen::MatrixBase<V0Type>& v0,
51  const Eigen::MatrixBase<V1Type>& v1,
52  const Eigen::MatrixBase<V2Type>& v2)
53 {
54  using Scalar = typename V0Type::Scalar;
55  constexpr static int Rows = V0Type::RowsAtCompileTime;
56  constexpr static int Cols0 = V0Type::ColsAtCompileTime;
57  constexpr static int Cols1 = V1Type::ColsAtCompileTime;
58  constexpr static int Cols2 = V1Type::ColsAtCompileTime;
59 
60 
61  // check that these are vectors
62  static_assert(Cols0 == 1);
63  static_assert(Cols1 == 1);
64  static_assert(Cols2 == 1);
65 
66  // just check that the inputs had the right dimensions
67  constexpr static int Rows1 = V1Type::RowsAtCompileTime;
68  constexpr static int Rows2 = V1Type::RowsAtCompileTime;
69  static_assert(Rows == Rows1);
70  static_assert(Rows == Rows2);
71 
72  Eigen::Matrix<Scalar, 2, 2> Dm;
73 
74 
75  static_assert(Rows == 2 || Rows == 3);
76 
77  if constexpr (Rows == 2) {
78  Dm.col(0) = (v1.template cast<Scalar>() - v0);
79  Dm.col(1) = (v2.template cast<Scalar>() - v0);
80  } else if constexpr (Rows == 3) {
81  // in 3d we compute a basis
82  // local vectors
83  Eigen::Matrix<Scalar, Rows, 2> V;
84  V.col(0) = v1.template cast<Scalar>() - v0;
85  V.col(1) = v2.template cast<Scalar>() - v0;
86 
87  // compute a basis plane
88  Eigen::Matrix<Scalar, 3, 2> B = V;
89 
90  auto e0 = B.col(0);
91  auto e1 = B.col(1);
92 
93  // TODO: shouldnt we make sure the normms are over some eps instead of 0?
94  auto e0norm = e0.norm();
95  assert(e0norm > 0); // check norm is not 0
96  e0 = e0 / e0norm;
97 
98  Vector3<Scalar> n = e0.cross(e1);
99  e1 = n.cross(e0);
100  auto e1norm = e1.norm();
101  assert(e1norm > 0); // check norm is not 0
102  e1 = e1 / e1norm;
103 
104 
105  Dm = (B.transpose() * V).eval();
106  }
107 
108 
109  return amips(Dm);
110 }
111 
112 double Tet_AMIPS_energy(const std::array<double, 12>& T);
113 void Tet_AMIPS_hessian(const std::array<double, 12>& T, Eigen::Matrix3d& result_0);
114 void Tet_AMIPS_jacobian(const std::array<double, 12>& T, Eigen::Vector3d& result_0);
115 
116 } // namespace wmtk::function::utils
const Eigen::Matrix2d amips_reference_to_barycentric
Definition: amips.cpp:42
const Eigen::Matrix< double, 2, 3 > amips_target_triangle
Definition: amips.cpp:30
void Tet_AMIPS_jacobian(const std::array< double, 12 > &T, Eigen::Vector3d &result_0)
Definition: amips.cpp:108
auto amips(const Eigen::MatrixBase< Derived > &B)
Definition: amips.hpp:20
double Tet_AMIPS_energy(const std::array< double, 12 > &T)
Definition: amips.cpp:380
void Tet_AMIPS_hessian(const std::array< double, 12 > &T, Eigen::Matrix3d &result_0)
Definition: amips.cpp:205
Vector< T, 3 > Vector3
Definition: Types.hpp:24
Rational abs(const Rational &r0)
Definition: Rational.cpp:328
Vector< double, 3 > Vector3d
Definition: Types.hpp:39