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