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