10template <
class DataPo
int,
class _WFunctor,
typename T>
20template<
class DataPo
int,
class _WFunctor,
typename T>
24 const DataPoint &attributes) {
25 if( Base::addLocalNeighbor(w, localQ, attributes) )
28 basis << attributes.normal(), attributes.normal().dot(localQ);
30 m_matA += w * basis * basis.transpose();
31 m_sumDotPP += w * localQ.squaredNorm();
39template <
class DataPo
int,
class _WFunctor,
typename T>
43 PONCA_MULTIARCH_STD_MATH(sqrt);
44 constexpr int Dim = DataPoint::Dim;
47 if(Base::finalize() !=
STABLE)
48 return Base::m_eCurrentState;
49 if(Base::getNumNeighbors() < DataPoint::Dim)
51 if (Base::algebraicSphere().isValid())
54 Base::m_eCurrentState = Base::getNumNeighbors() < 2*DataPoint::Dim ?
UNSTABLE :
STABLE;
59 m_matQ.template topLeftCorner<Dim,Dim>().setIdentity();
60 m_matQ.col(Dim).template head<Dim>() = Base::m_sumP * invSumW;
61 m_matQ.row(Dim).template head<Dim>() = Base::m_sumP * invSumW;
62 m_matQ(Dim,Dim) = m_sumDotPP * invSumW;
64 MatrixBB M = m_matQ.inverse() * m_matA;
66 VectorB eivals = m_solver.eigenvalues().real();
68 eivals.maxCoeff(&maxId);
70 VectorB eivec = m_solver.eigenvectors().col(maxId).real();
73 Base::m_ul = eivec.template head<Dim>();
74 Base::m_uq =
Scalar(0.5) * eivec(Dim);
75 Base::m_uc = -invSumW * (Base::m_ul.dot(Base::m_sumP) + m_sumDotPP * Base::m_uq);
77 Base::m_isNormalized =
false;
79 return Base::m_eCurrentState;
84template <
class DataPo
int,
class _WFunctor,
int DiffType,
typename T>
89 for(
int dim = 0; dim < Base::NbDerivatives; ++dim)
90 m_dmatA[dim] = MatrixBB::Zero();
91 m_dSumDotPP = ScalarArray::Zero();
92 m_dUc = ScalarArray::Zero();
93 m_dUl = VectorArray::Zero();
94 m_dUq = ScalarArray::Zero();
97template <
class DataPo
int,
class _WFunctor,
int DiffType,
typename T>
102 const DataPoint &attributes,
105 if( Base::addLocalNeighbor(w, localQ, attributes, dw) )
108 basis << attributes.normal(), attributes.normal().dot(localQ);
109 const MatrixBB prod = basis * basis.transpose();
111 m_dSumDotPP += dw * localQ.squaredNorm();
113 for(
int dim = 0; dim < Base::NbDerivatives; ++dim)
115 m_dmatA[dim] += dw[dim] * prod;
123template <
class DataPo
int,
class _WFunctor,
int DiffType,
typename T>
127 constexpr int Dim = DataPoint::Dim;
128 constexpr Scalar epsilon = Eigen::NumTraits<Scalar>::dummy_precision();
134 Base::m_solver.eigenvalues().real().maxCoeff(&i);
135 const Scalar eigenval_i = Base::m_solver.eigenvalues().real()[i];
136 const VectorB eigenvec_i = Base::m_solver.eigenvectors().real().col(i);
138 const Scalar invSumW =
Scalar(1) / Base::getWeightSum();
159 for(
int dim = 0; dim < Base::NbDerivatives; ++dim)
162 dQ.template topLeftCorner<Dim,Dim>().setZero();
163 dQ.col(Dim).template head<Dim>() = Base::m_dSumP.col(dim);
164 dQ.row(Dim).template head<Dim>() = Base::m_dSumP.col(dim);
165 dQ(Dim,Dim) = m_dSumDotPP[dim];
166 dQ -= Base::m_dSumW[dim] * Base::m_matQ;
169 const VectorB vec = (m_dmatA[dim] - eigenval_i * dQ) * eigenvec_i;
171 VectorB deigvec = VectorB::Zero();
172 for(
int j = 0; j < Dim+1; ++j)
176 const Scalar eigenval_j = Base::m_solver.eigenvalues().real()[j];
177 const Scalar eigengap = eigenval_i - eigenval_j;
179 if(eigengap > epsilon)
181 const VectorB eigenvec_j = Base::m_solver.eigenvectors().real().col(j);
182 deigvec +=
Scalar(1)/eigengap * eigenvec_j.dot(vec) * eigenvec_j;
187 deigvec = Base::m_matQ * deigvec;
189 m_dUq[dim] =
Scalar(.5) * deigvec[dim];
190 m_dUl.col(dim) = deigvec.template head<Dim>();
194 m_dUc = -invSumW*( Base::m_sumP.transpose() * m_dUl
195 + Base::m_sumDotPP * m_dUq
196 + Base::m_ul.transpose() * Base::m_dSumP
197 + Base::m_uq * m_dSumDotPP
198 + Base::m_dSumW * Base::m_uc);
202 return Base::m_eCurrentState;
205template <
class DataPo
int,
class _WFunctor,
int DiffType,
typename T>
210 ScalarArray dfield = m_dUc;
211 if(Base::isSpaceDer())
212 dfield.template tail<DataPoint::Dim>() += Base::m_ul;
216template <
class DataPo
int,
class _WFunctor,
int DiffType,
typename T>
218UnorientedSphereDerImpl<DataPoint, _WFunctor, DiffType, T>::dNormal()
const
221 VectorArray dgrad = m_dUl;
222 if(Base::isSpaceDer())
223 dgrad.template rightCols<DataPoint::Dim>().diagonal().array() += Scalar(2)*Base::m_uq;
224 Scalar norm = Base::m_ul.norm();
225 Scalar norm3 = norm*norm*norm;
226 return dgrad / norm - Base::m_ul * (Base::m_ul.transpose() * dgrad) / norm3;
typename Base::VectorType VectorType
Alias to vector type.
bool addLocalNeighbor(Scalar w, const VectorType &localQ, const DataPoint &attributes, ScalarArray &dw)
Add a neighbor to perform the fit.
typename DataPoint::Scalar Scalar
Alias to scalar type.
typename Base::ScalarArray ScalarArray
Alias to scalar derivatives array.
void init(const VectorType &_evalPos)
Set the evaluation position and reset the internal states.
typename Base::VectorArray VectorArray
Alias to vector derivatives array.
FIT_RESULT finalize()
Finalize the procedure.
typename Base::VectorType VectorType
Alias to vector type.
bool addLocalNeighbor(Scalar w, const VectorType &localQ, const DataPoint &attributes)
Add a neighbor to perform the fit.
FIT_RESULT finalize()
Finalize the procedure.
typename DataPoint::Scalar Scalar
Alias to scalar type.
void init(const VectorType &_evalPos)
Set the evaluation position and reset the internal states.
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)
@ 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...