10 template <
class DataPo
int,
class _NFilter,
typename T>
11 requires UNORIENTED_SPHERE_FIT_REQUIREMENTS
20 template <
class DataPo
int,
class _NFilter,
typename T>
21 requires UNORIENTED_SPHERE_FIT_REQUIREMENTS
23 const DataPoint& attributes)
25 Base::addLocalNeighbor(w, localQ, attributes);
27 basis << attributes.normal(), attributes.normal().dot(localQ);
29 m_matA += w * basis * basis.transpose();
30 m_sumDotPP += w * localQ.squaredNorm();
33 template <
class DataPo
int,
class _NFilter,
typename T>
34 requires UNORIENTED_SPHERE_FIT_REQUIREMENTS
37 PONCA_MULTIARCH_STD_MATH(sqrt);
38 constexpr int Dim = DataPoint::Dim;
41 if (Base::finalize() !=
STABLE)
42 return Base::m_eCurrentState;
43 if (Base::getNumNeighbors() < DataPoint::Dim)
45 if (Base::algebraicSphere().isValid())
48 Base::m_eCurrentState = Base::getNumNeighbors() < 2 * DataPoint::Dim ?
UNSTABLE :
STABLE;
53 m_matQ.template topLeftCorner<Dim, Dim>().setIdentity();
54 m_matQ.col(Dim).template head<Dim>() = Base::m_sumP * invSumW;
55 m_matQ.row(Dim).template head<Dim>() = Base::m_sumP * invSumW;
56 m_matQ(Dim, Dim) = m_sumDotPP * invSumW;
58 MatrixBB M = m_matQ.inverse() * m_matA;
60 VectorB eivals = m_solver.eigenvalues().real();
62 eivals.maxCoeff(&maxId);
64 VectorB eivec = m_solver.eigenvectors().col(maxId).real();
67 Base::m_ul = eivec.template head<Dim>();
68 Base::m_uq =
Scalar(0.5) * eivec(Dim);
69 Base::m_uc = -invSumW * (Base::m_ul.dot(Base::m_sumP) + m_sumDotPP * Base::m_uq);
71 Base::m_isNormalized =
false;
73 return Base::m_eCurrentState;
76 template <
class DataPo
int,
class _NFilter,
int DiffType,
typename T>
77 requires UNORIENTED_SPHERE_DER_REQUIREMENTS
81 for (
int dim = 0; dim < Base::NbDerivatives; ++dim)
82 m_dmatA[dim] = MatrixBB::Zero();
83 m_dSumDotPP = ScalarArray::Zero();
84 m_dUc = ScalarArray::Zero();
85 m_dUl = VectorArray::Zero();
86 m_dUq = ScalarArray::Zero();
89 template <
class DataPo
int,
class _NFilter,
int DiffType,
typename T>
90 requires UNORIENTED_SPHERE_DER_REQUIREMENTS
92 const DataPoint& attributes,
95 Base::addLocalNeighbor(w, localQ, attributes, dw);
97 basis << attributes.normal(), attributes.normal().dot(localQ);
98 const MatrixBB prod = basis * basis.transpose();
100 m_dSumDotPP += dw * localQ.squaredNorm();
102 for (
int dim = 0; dim < Base::NbDerivatives; ++dim)
104 m_dmatA[dim] += dw[dim] * prod;
108 template <
class DataPo
int,
class _NFilter,
int DiffType,
typename T>
109 requires UNORIENTED_SPHERE_DER_REQUIREMENTS
112 constexpr int Dim = DataPoint::Dim;
113 constexpr Scalar epsilon = Eigen::NumTraits<Scalar>::dummy_precision();
119 Base::m_solver.eigenvalues().real().maxCoeff(&i);
120 const Scalar eigenval_i = Base::m_solver.eigenvalues().real()[i];
121 const VectorB eigenvec_i = Base::m_solver.eigenvectors().real().col(i);
123 const Scalar invSumW =
Scalar(1) / Base::getWeightSum();
144 for (
int dim = 0; dim < Base::NbDerivatives; ++dim)
147 dQ.template topLeftCorner<Dim, Dim>().setZero();
148 dQ.col(Dim).template head<Dim>() = Base::m_dSumP.col(dim);
149 dQ.row(Dim).template head<Dim>() = Base::m_dSumP.col(dim);
150 dQ(Dim, Dim) = m_dSumDotPP[dim];
151 dQ -= Base::m_dSumW[dim] * Base::m_matQ;
154 const VectorB vec = (m_dmatA[dim] - eigenval_i * dQ) * eigenvec_i;
156 VectorB deigvec = VectorB::Zero();
157 for (
int j = 0; j < Dim + 1; ++j)
161 const Scalar eigenval_j = Base::m_solver.eigenvalues().real()[j];
163 eigenval_i - eigenval_j;
165 if (eigengap > epsilon)
167 const VectorB eigenvec_j = Base::m_solver.eigenvectors().real().col(j);
168 deigvec +=
Scalar(1) / eigengap * eigenvec_j.dot(vec) * eigenvec_j;
173 deigvec = Base::m_matQ * deigvec;
175 m_dUq[dim] =
Scalar(.5) * deigvec[dim];
176 m_dUl.col(dim) = deigvec.template head<Dim>();
181 (Base::m_sumP.transpose() * m_dUl + Base::m_sumDotPP * m_dUq +
182 Base::m_ul.transpose() * Base::m_dSumP + Base::m_uq * m_dSumDotPP + Base::m_dSumW * Base::m_uc);
186 return Base::m_eCurrentState;
189 template <
class DataPo
int,
class _NFilter,
int DiffType,
typename T>
190 requires UNORIENTED_SPHERE_DER_REQUIREMENTS
192 DataPoint, _NFilter,
DiffType, T>::dPotential()
const
195 ScalarArray dfield = m_dUc;
196 if (Base::isSpaceDer())
197 dfield.template tail<DataPoint::Dim>() += Base::m_ul;
201 template <
class DataPo
int,
class _NFilter,
int DiffType,
typename T>
202 requires UNORIENTED_SPHERE_DER_REQUIREMENTS
204 DataPoint, _NFilter,
DiffType, T>::dNormal()
const
207 VectorArray dgrad = m_dUl;
208 if (Base::isSpaceDer())
209 dgrad.template rightCols<DataPoint::Dim>().diagonal().array() += Scalar(2) * Base::m_uq;
210 Scalar norm = Base::m_ul.norm();
211 Scalar norm3 = norm * norm * norm;
212 return dgrad / norm - Base::m_ul * (Base::m_ul.transpose() * dgrad) / norm3;
215 template <
class DataPo
int,
class _NFilter,
int DiffType,
typename T>
216 requires UNORIENTED_SPHERE_DER_REQUIREMENTS
219 if (Base::isNormalized())
222 PONCA_MULTIARCH_STD_MATH(sqrt);
223 Scalar pn2 = Base::prattNorm2();
229 m_dUc = (m_dUc * pn - Base::m_uc * factor) / pn2;
230 m_dUl = (m_dUl * pn - Base::m_ul * factor) / pn2;
231 m_dUq = (m_dUq * pn - Base::m_uq * factor) / pn2;
233 Base::applyPrattNorm();
void addLocalNeighbor(Scalar w, const VectorType &localQ, const DataPoint &attributes, ScalarArray &dw)
Add a neighbor to perform the fit.
typename Base::ScalarArray ScalarArray
Alias to scalar derivatives array.
typename Base::VectorType VectorType
Alias to vector type.
typename DataPoint::Scalar Scalar
Alias to scalar type.
void init()
Set the evaluation position and reset the internal states.
FIT_RESULT finalize()
Finalize the procedure.
typename Base::VectorArray VectorArray
Alias to vector derivatives array.
bool applyPrattNorm()
Normalize the scalar field by the Pratt norm.
void addLocalNeighbor(Scalar w, const VectorType &localQ, const DataPoint &attributes)
Add a neighbor to perform the fit.
FIT_RESULT finalize()
Finalize the procedure.
void init()
Set the evaluation position and reset the internal states.
typename Base::VectorType VectorType
Alias to vector type.
typename DataPoint::Scalar Scalar
Alias to scalar type.
This Source Code Form is subject to the terms of the Mozilla Public License, v.
DiffType
Flags defining which derivatives need to be computed.
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.
@ CONFLICT_ERROR_FOUND
Multiple classes of the fitting procedure initialize the primitive.
@ STABLE
The fitting is stable and ready to use.
@ UNSTABLE
The fitting is ready to use but it is considered as unstable (if the number of neighbors is low for e...