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.
typename Base::VectorArray VectorArray
Alias to vector derivatives array.
void init()
Set the evaluation position and reset the internal states.
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()
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...