1template <
class DataPo
int,
class _WFunctor,
int DiffType,
typename T>
5 if (Base::finalize() ==
STABLE) {
7 Base::m_eCurrentState = computeCurvature(
false);
10 return Base::m_eCurrentState;
13template <
class DataPo
int,
class _WFunctor,
int DiffType,
typename T>
16 PONCA_MULTIARCH_STD_MATH(abs);
19 MatrixType dN = Base::dNormal().template middleCols<DataPoint::Dim>(Base::isScaleDer() ? 1: 0);
22 Mat32 B = tangentPlane(useNormal);
26 Mat22 S = B.transpose() * dN * B;
41 S(0,1) = S(1,0) = (S(0,1) + S(1,0))/Scalar(2);
42 Eigen::SelfAdjointEigenSolver<Mat22> eig2;
43 eig2.computeDirect(S);
45 if (eig2.info() != Eigen::Success)
return UNDEFINED;
47 Base::setCurvatureValues(eig2.eigenvalues()(0), eig2.eigenvalues()(1),
48 B * eig2.eigenvectors().col(0), B * eig2.eigenvectors().col(1));
50 return Base::m_eCurrentState;
53template <
class DataPo
int,
class _WFunctor,
int DiffType,
typename T>
54typename NormalDerivativesCurvatureEstimator<DataPoint, _WFunctor, DiffType, T>::Mat32
57 typedef typename VectorType::Index Index;
59 PONCA_MULTIARCH_STD_MATH(sqrt);
60 PONCA_MULTIARCH_STD_MATH(abs);
63 Index i0=Index(-1), i1=Index(-1), i2=Index(-1);
71 n.array().abs().minCoeff(&i0);
77 B.col(0)[i2] = -n[i1];
80 B.col(1) = B.col(0).cross(n);
88 MatrixType dN = Base::dNormal().template middleCols<DataPoint::Dim>(Base::isScaleDer() ? 1: 0);
92 Scalar sqNorm = dN.colwise().squaredNorm().maxCoeff(&i0);
93 B.col(0) = dN.col(i0) / sqrt(sqNorm);
97 VectorType v1 = dN.col(i1) - B.col(0).dot(dN.col(i1)) * B.col(0);
98 VectorType v2 = dN.col(i2) - B.col(0).dot(dN.col(i2)) * B.col(0);
99 Scalar v1norm2 = v1.squaredNorm();
100 Scalar v2norm2 = v2.squaredNorm();
101 if(v1norm2 > v2norm2) B.col(1) = v1 / sqrt(v1norm2);
102 else B.col(1) = v2 / sqrt(v2norm2);
108template <
class DataPo
int,
class _WFunctor,
int DiffType,
typename T>
112 Base::init(_evalPos);
113 m_cov = MatrixType::Zero();
114 m_cog = VectorType::Zero();
117template <
class DataPo
int,
class _WFunctor,
int DiffType,
typename T>
122 if( Base::addLocalNeighbor(w, localQ, attributes, dw) )
124 m_cov += w * attributes.normal() * attributes.normal().transpose();
125 m_cog += attributes.normal();
131template <
class DataPo
int,
class _WFunctor,
int DiffType,
typename T>
135 typedef typename VectorType::Index Index;
137 PONCA_MULTIARCH_STD_MATH(abs);
144 m_cog /= Base::getWeightSum();
147 m_cov = m_cov/Base::getWeightSum() - m_cog * m_cog.transpose();
149 m_solver.computeDirect(m_cov);
151 Scalar kmin = m_solver.eigenvalues()(1);
152 Scalar kmax = m_solver.eigenvalues()(2);
154 VectorType vmin = m_solver.eigenvectors().col(1);
155 VectorType vmax = m_solver.eigenvectors().col(2);
160 if(kmin<epsilon && kmax<epsilon)
167 Index i0 = -1, i1 = -1, i2 = -1;
168 n.rowwise().squaredNorm().minCoeff(&i0);
174 vmax[i0] = n[i1]*n[i1] + n[i2]*n[i2];
175 vmax[i1] = -n[i1]*n[i0];
176 vmax[i2] = -n[i2]*n[i0];
179 Base::setCurvatureValues(kmin, kmax, vmin, vmax);
184template <
class DataPo
int,
class _WFunctor,
int DiffType,
typename T>
188 Base::init(_evalPos);
190 m_cog = Vector2::Zero();
191 m_cov = Mat22::Zero();
193 m_tframe = Mat32::Zero();
196template <
class DataPo
int,
class _WFunctor,
int DiffType,
typename T>
201 if(m_pass == FIRST_PASS)
203 return Base::addLocalNeighbor(w, localQ, attributes, dw);
205 else if(m_pass == SECOND_PASS)
209 Vector2 proj = m_tframe.transpose() * n;
211 m_cov += proj * proj.transpose();
218template <
class DataPo
int,
class _WFunctor,
int DiffType,
typename T>
222 if(m_pass == FIRST_PASS)
232 Index i0 = -1, i1 = -1, i2 = -1;
233 n.rowwise().squaredNorm().minCoeff(&i0);
236 m_tframe.col(0)[i0] = 0;
237 m_tframe.col(0)[i1] = n[i2];
238 m_tframe.col(0)[i2] = -n[i1];
239 m_tframe.col(1)[i0] = n[i1]*n[i1] + n[i2]*n[i2];
240 m_tframe.col(1)[i1] = -n[i1]*n[i0];
241 m_tframe.col(1)[i2] = -n[i2]*n[i0];
244 m_pass = SECOND_PASS;
252 else if(m_pass == SECOND_PASS)
255 m_cog /= Base::getWeightSum();
258 m_cov = m_cov/Base::getWeightSum() - m_cog * m_cog.transpose();
260 m_solver.computeDirect(m_cov);
262 Base::m_kmin = m_solver.eigenvalues()(0);
263 Base::m_kmax = m_solver.eigenvalues()(1);
266 Base::m_v1 = m_tframe * m_solver.eigenvectors().col(0);
267 Base::m_v2 = m_tframe * m_solver.eigenvectors().col(1);
272 if(Base::m_kmin<epsilon && Base::m_kmax<epsilon)
278 Base::m_v2 = m_tframe.col(0);
279 Base::m_v1 = m_tframe.col(1);
Extension to compute curvature values based on a covariance analysis of normal vectors of neighbors.
typename DataPoint::Scalar Scalar
Alias to scalar type.
typename Base::ScalarArray ScalarArray
Alias to scalar derivatives array.
typename Base::VectorType VectorType
Alias to vector type.
Extension to compute curvature values from the Weingarten map .
typename DataPoint::MatrixType MatrixType
Alias to matrix type.
typename Base::VectorType VectorType
Alias to vector type.
typename DataPoint::Scalar Scalar
Alias to scalar type.
Extension to compute curvature values based on a covariance analysis of normal vectors of neighbors p...
typename Base::VectorType VectorType
Alias to vector type.
typename DataPoint::Scalar Scalar
Alias to scalar type.
typename Base::ScalarArray ScalarArray
Alias to scalar derivatives array.
FIT_RESULT
Enum corresponding to the state of a fitting method (and what the finalize function returns)
@ UNDEFINED
The fitting is undefined, you can't use it for valid results.
@ NEED_OTHER_PASS
The fitting procedure needs to analyse the neighborhood another time.
@ CONFLICT_ERROR_FOUND
Multiple classes of the fitting procedure initialize the primitive.
@ STABLE
The fitting is stable and ready to use.