Ponca  7abd0fd82719106ad460aa0f2070dffbe375d727
Point Cloud Analysis library
Loading...
Searching...
No Matches
weingarten.hpp
1#include <Eigen/Eigenvalues>
2#include <Eigen/Core>
3
4namespace Ponca
5{
7 template <class DataPoint, class _NFilter, typename T>
8 requires FUNDAMENTAL_FORM_WEINGARTEN_ESTIMATOR_REQUIREMENTS
9 typename FundamentalFormWeingartenEstimator<DataPoint, _NFilter, T>::Matrix2 FundamentalFormWeingartenEstimator<
10 DataPoint, _NFilter, T>::firstFundamentalForm() const
11 {
12 Matrix2 first;
13 firstFundamentalForm(first);
14 return first;
15 }
16
17 template <class DataPoint, class _NFilter, typename T>
18 requires FUNDAMENTAL_FORM_WEINGARTEN_ESTIMATOR_REQUIREMENTS
19 template <typename Matrix2Derived>
21 {
22 Base::firstFundamentalFormComponents(first(0, 0), first(1, 0), first(1, 1));
23 first(0, 1) = first(1, 0); // diagonal
24 }
25
26 template <class DataPoint, class _NFilter, typename T>
27 requires FUNDAMENTAL_FORM_WEINGARTEN_ESTIMATOR_REQUIREMENTS
28 typename FundamentalFormWeingartenEstimator<DataPoint, _NFilter, T>::Matrix2 FundamentalFormWeingartenEstimator<
29 DataPoint, _NFilter, T>::secondFundamentalForm() const
30 {
31 Matrix2 second;
32 secondFundamentalForm(second);
33 return second;
34 }
35
36 template <class DataPoint, class _NFilter, typename T>
37 requires FUNDAMENTAL_FORM_WEINGARTEN_ESTIMATOR_REQUIREMENTS
38 template <typename Matrix2Derived>
40 {
41 Base::secondFundamentalFormComponents(second(0, 0), second(1, 0), second(1, 1));
42 second(0, 1) = second(1, 0); // diagonal
43 }
44
45 template <class DataPoint, class _NFilter, typename T>
46 requires FUNDAMENTAL_FORM_WEINGARTEN_ESTIMATOR_REQUIREMENTS
47 typename FundamentalFormWeingartenEstimator<DataPoint, _NFilter, T>::Matrix2 FundamentalFormWeingartenEstimator<
48 DataPoint, _NFilter, T>::weingartenMap() const
49 {
50 Matrix2 w;
51 weingartenMap(w);
52 return w;
53 }
54
55 template <class DataPoint, class _NFilter, typename T>
56 requires FUNDAMENTAL_FORM_WEINGARTEN_ESTIMATOR_REQUIREMENTS
57 template <typename Matrix2Derived>
59 {
60 w = firstFundamentalForm().inverse() * secondFundamentalForm();
61 }
62
63 template <class DataPoint, class _NFilter, typename T>
64 requires FUNDAMENTAL_FORM_WEINGARTEN_ESTIMATOR_REQUIREMENTS
66 DataPoint, _NFilter, T>::kMean() const
67 {
68 Scalar E, F, G, L, M, N;
69 Base::firstFundamentalFormComponents(E, F, G);
70 Base::secondFundamentalFormComponents(L, M, N);
71 return (G * L - Scalar(2) * F * M + E * N) / (Scalar(2) * (E * G - F * F));
72 }
73
74 template <class DataPoint, class _NFilter, typename T>
75 requires FUNDAMENTAL_FORM_WEINGARTEN_ESTIMATOR_REQUIREMENTS
77 DataPoint, _NFilter, T>::GaussianCurvature() const
78 {
79 Scalar E, F, G, L, M, N;
80 Base::firstFundamentalFormComponents(E, F, G);
81 Base::secondFundamentalFormComponents(L, M, N);
82 return (L * N - M * M) / (E * G - F * F);
83 }
84
86 template <class DataPoint, class _NFilter, int DiffType, typename T>
87 requires NORMAL_DERIVATIVE_WEINGARTEN_ESTIMATOR_REQUIREMENTS
88 typename NormalDerivativeWeingartenEstimator<DataPoint, _NFilter, DiffType, T>::Matrix2
90 {
91 Matrix2 w;
92 weingartenMap(w);
93 return w;
94 }
95
96 template <class DataPoint, class _NFilter, int DiffType, typename T>
97 requires NORMAL_DERIVATIVE_WEINGARTEN_ESTIMATOR_REQUIREMENTS
99 {
100
101 PONCA_MULTIARCH_STD_MATH(abs);
102 PONCA_MULTIARCH_STD_MATH(sqrt);
103
104 using Index = typename VectorType::Index;
105
106 Base::finalize();
107 // Test if base finalize end on a viable case (stable / unstable)
108 if (this->isReady())
109 {
110 Index i0 = Index(-1), i1 = Index(-1), i2 = Index(-1);
111
112 MatrixType dN = Base::dNormal().template middleCols<DataPoint::Dim>(Base::isScaleDer() ? 1 : 0);
113
114 VectorType n = Base::primitiveGradient();
115 n.array().abs().minCoeff(&i0); // i0: dimension where n extends the least
116 i1 = (i0 + 1) % 3;
117 i2 = (i0 + 2) % 3;
118
119 m_tangentBasis.col(0) = n;
120
121 m_tangentBasis.col(1)[i0] = 0;
122 m_tangentBasis.col(1)[i1] = n[i2];
123 m_tangentBasis.col(1)[i2] = -n[i1];
124
125 m_tangentBasis.col(1).normalize();
126 m_tangentBasis.col(2) = m_tangentBasis.col(1).cross(n);
127 }
128 return Base::m_eCurrentState;
129 }
130
131 template <class DataPoint, class _NFilter, int DiffType, typename T>
132 requires NORMAL_DERIVATIVE_WEINGARTEN_ESTIMATOR_REQUIREMENTS
133 template <typename Matrix2Derived>
135 {
136 PONCA_MULTIARCH_STD_MATH(abs);
137 PONCA_MULTIARCH_STD_MATH(sqrt);
138
139 using Index = typename VectorType::Index;
140 using Matrix32 = Eigen::Matrix<Scalar, 3, 2>;
141
142 // Get the object space Weingarten map dN
143 MatrixType dN = Base::dNormal().template middleCols<DataPoint::Dim>(Base::isScaleDer() ? 1 : 0);
144
145 // Compute tangent-space change of basis function
146 auto B = m_tangentBasis.template rightCols<2>();
147
148 // Compute the 2x2 matrix representing the shape operator by transforming dN to the basis B.
149 // Recall that dN is a bilinear form, it thus transforms as follows:
150 W = B.transpose() * dN * B;
151
152 // Recall that at this stage, the shape operator represented by W describes the normal curvature K_n(u) in the
153 // direction u \in R^2 as follows:
154 // K_n(u) = u^T W u
155 // The principal curvatures are fully defined by the values and the directions of the extrema of K_n.
156 //
157 // If the normal field N(x) comes from the gradient of a scalar field, then N(x) is curl-free, and dN and W are
158 // symmetric matrices. In this case, the extrema of the previous quadratic form are directly obtained by the
159 // eigenvalue decomposition of W. However, if N(x) is only an approximation of the normal field of a surface,
160 // then N(x) is not necessarily curl-free, and in this case W is not symmetric. In this case, we first have to
161 // find an equivalent symmetric matrix W' such that:
162 // K_n(u) = u^T W' u,
163 // for any u \in R^2.
164 // It is easy to see that such a W' is simply obtained as:
165 // W' = (W + W^T)/2
166 W(0, 1) = W(1, 0) = (W(0, 1) + W(1, 0)) / Scalar(2);
167 }
168
169 template <class DataPoint, class _NFilter, int DiffType, typename T>
170 requires NORMAL_DERIVATIVE_WEINGARTEN_ESTIMATOR_REQUIREMENTS
173 const VectorType& _q, bool _isPositionVector) const
174 {
175 return m_tangentBasis.normalized().transpose() *
176 Base::getNeighborFrame().convertToLocalBasis(_q, _isPositionVector);
177 }
178
179 template <class DataPoint, class _NFilter, int DiffType, typename T>
180 requires NORMAL_DERIVATIVE_WEINGARTEN_ESTIMATOR_REQUIREMENTS
183 const VectorType& _lq, bool _isPositionVector) const
184 {
185 return Base::getNeighborFrame().convertToGlobalBasis(m_tangentBasis.normalized().transpose().inverse() * _lq,
186 _isPositionVector);
187 }
188
189 namespace internal
190 {
192 template <class DataPoint, class _NFilter, typename T>
193 requires WIENGARTEN_CURVATURE_ESTIMATOR_REQUIREMENTS
195 {
196 if (Base::finalize() != STABLE)
197 return Base::m_eCurrentState;
198
199 Matrix2 w;
200 Base::weingartenMap(w);
201 m_solver.computeDirect(w);
202
203 return Base::m_eCurrentState;
204 }
205 } // namespace internal
206} // namespace Ponca
207
Compute a Weingarten map from fundamental forms.
Definition weingarten.h:42
Matrix2 weingartenMap() const
Returns the Weingarten Map.
typename DataPoint::Scalar Scalar
Alias to scalar type.
Definition weingarten.h:43
Matrix2 secondFundamentalForm() const
Assembles and returns the second fundamental form from the base class.
Matrix2 firstFundamentalForm() const
Assembles and returns the first fundamental form from the base class.
typename Base::VectorType VectorType
Alias to vector type.
Definition weingarten.h:112
FIT_RESULT finalize()
Finalize the procedure.
VectorType tangentPlaneToWorld(const VectorType &_q, bool _isPositionVector=true) const
Transform a point from the tangent plane [h, u, v]^T to ambient space.
VectorType worldToTangentPlane(const VectorType &_q, bool _isPositionVector=true) const
Express a point in ambient space relatively to the tangent plane.
typename DataPoint::MatrixType MatrixType
Alias to matrix type.
Definition weingarten.h:113
typename DataPoint::Scalar Scalar
Alias to scalar type.
Definition weingarten.h:112
Matrix2 weingartenMap() const
Returns the Weingarten Map.
FIT_RESULT finalize()
Finalize the procedure.
This Source Code Form is subject to the terms of the Mozilla Public License, v.
Definition concepts.h:11
FIT_RESULT
Enum corresponding to the state of a fitting method (and what the finalize function returns)
Definition enums.h:15
@ STABLE
The fitting is stable and ready to use.
Definition enums.h:17