10 template <
class DataPo
int,
class _NFilter,
typename T>
19 template <
class DataPo
int,
class _NFilter,
typename T>
21 const DataPoint& attributes)
23 Base::addLocalNeighbor(w, localQ, attributes);
25 basis << attributes.normal(), attributes.normal().dot(localQ);
27 m_matA += w * basis * basis.transpose();
28 m_sumDotPP += w * localQ.squaredNorm();
31 template <
class DataPo
int,
class _NFilter,
typename T>
34 PONCA_MULTIARCH_STD_MATH(sqrt);
35 constexpr int Dim = DataPoint::Dim;
38 if (Base::finalize() !=
STABLE)
39 return Base::m_eCurrentState;
40 if (Base::getNumNeighbors() < DataPoint::Dim)
42 if (Base::algebraicSphere().isValid())
45 Base::m_eCurrentState = Base::getNumNeighbors() < 2 * DataPoint::Dim ?
UNSTABLE :
STABLE;
50 m_matQ.template topLeftCorner<Dim, Dim>().setIdentity();
51 m_matQ.col(Dim).template head<Dim>() = Base::m_sumP * invSumW;
52 m_matQ.row(Dim).template head<Dim>() = Base::m_sumP * invSumW;
53 m_matQ(Dim, Dim) = m_sumDotPP * invSumW;
55 MatrixBB M = m_matQ.inverse() * m_matA;
57 VectorB eivals = m_solver.eigenvalues().real();
59 eivals.maxCoeff(&maxId);
61 VectorB eivec = m_solver.eigenvectors().col(maxId).real();
64 Base::m_ul = eivec.template head<Dim>();
65 Base::m_uq =
Scalar(0.5) * eivec(Dim);
66 Base::m_uc = -invSumW * (Base::m_ul.dot(Base::m_sumP) + m_sumDotPP * Base::m_uq);
68 Base::m_isNormalized =
false;
70 return Base::m_eCurrentState;
73 template <
class DataPo
int,
class _NFilter,
int DiffType,
typename T>
77 for (
int dim = 0; dim < Base::NbDerivatives; ++dim)
78 m_dmatA[dim] = MatrixBB::Zero();
79 m_dSumDotPP = ScalarArray::Zero();
80 m_dUc = ScalarArray::Zero();
81 m_dUl = VectorArray::Zero();
82 m_dUq = ScalarArray::Zero();
85 template <
class DataPo
int,
class _NFilter,
int DiffType,
typename T>
87 const DataPoint& attributes,
90 Base::addLocalNeighbor(w, localQ, attributes, dw);
92 basis << attributes.normal(), attributes.normal().dot(localQ);
93 const MatrixBB prod = basis * basis.transpose();
95 m_dSumDotPP += dw * localQ.squaredNorm();
97 for (
int dim = 0; dim < Base::NbDerivatives; ++dim)
99 m_dmatA[dim] += dw[dim] * prod;
103 template <
class DataPo
int,
class _NFilter,
int DiffType,
typename T>
106 constexpr int Dim = DataPoint::Dim;
107 constexpr Scalar epsilon = Eigen::NumTraits<Scalar>::dummy_precision();
113 Base::m_solver.eigenvalues().real().maxCoeff(&i);
114 const Scalar eigenval_i = Base::m_solver.eigenvalues().real()[i];
115 const VectorB eigenvec_i = Base::m_solver.eigenvectors().real().col(i);
117 const Scalar invSumW =
Scalar(1) / Base::getWeightSum();
138 for (
int dim = 0; dim < Base::NbDerivatives; ++dim)
141 dQ.template topLeftCorner<Dim, Dim>().setZero();
142 dQ.col(Dim).template head<Dim>() = Base::m_dSumP.col(dim);
143 dQ.row(Dim).template head<Dim>() = Base::m_dSumP.col(dim);
144 dQ(Dim, Dim) = m_dSumDotPP[dim];
145 dQ -= Base::m_dSumW[dim] * Base::m_matQ;
148 const VectorB vec = (m_dmatA[dim] - eigenval_i * dQ) * eigenvec_i;
150 VectorB deigvec = VectorB::Zero();
151 for (
int j = 0; j < Dim + 1; ++j)
155 const Scalar eigenval_j = Base::m_solver.eigenvalues().real()[j];
157 eigenval_i - eigenval_j;
159 if (eigengap > epsilon)
161 const VectorB eigenvec_j = Base::m_solver.eigenvectors().real().col(j);
162 deigvec +=
Scalar(1) / eigengap * eigenvec_j.dot(vec) * eigenvec_j;
167 deigvec = Base::m_matQ * deigvec;
169 m_dUq[dim] =
Scalar(.5) * deigvec[dim];
170 m_dUl.col(dim) = deigvec.template head<Dim>();
175 (Base::m_sumP.transpose() * m_dUl + Base::m_sumDotPP * m_dUq +
176 Base::m_ul.transpose() * Base::m_dSumP + Base::m_uq * m_dSumDotPP + Base::m_dSumW * Base::m_uc);
180 return Base::m_eCurrentState;
183 template <
class DataPo
int,
class _NFilter,
int DiffType,
typename T>
185 DataPoint, _NFilter,
DiffType, T>::dPotential()
const
188 ScalarArray dfield = m_dUc;
189 if (Base::isSpaceDer())
190 dfield.template tail<DataPoint::Dim>() += Base::m_ul;
194 template <
class DataPo
int,
class _NFilter,
int DiffType,
typename T>
196 DataPoint, _NFilter,
DiffType, T>::dNormal()
const
199 VectorArray dgrad = m_dUl;
200 if (Base::isSpaceDer())
201 dgrad.template rightCols<DataPoint::Dim>().diagonal().array() += Scalar(2) * Base::m_uq;
202 Scalar norm = Base::m_ul.norm();
203 Scalar norm3 = norm * norm * norm;
204 return dgrad / norm - Base::m_ul * (Base::m_ul.transpose() * dgrad) / norm3;
FIT_RESULT finalize()
Finalize the procedure.
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.
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.
typename DataPoint::Scalar Scalar
Alias to scalar type.
void addLocalNeighbor(Scalar w, const VectorType &localQ, const DataPoint &attributes)
Add a neighbor to perform the fit.
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...