Ponca  7d8ac87a7de01d881c9fde3c42e397b44bffb901
Point Cloud Analysis library
Loading...
Searching...
No Matches
cncFormulaEigen.h
1
62#pragma once
63
64#include <Eigen/Dense>
65
66namespace Ponca::internal
67{
68
73 template <typename DataPoint>
74 struct CNCEigen
75 {
76 using MatrixType = typename DataPoint::MatrixType;
77 using Scalar = typename DataPoint::Scalar;
78 using VectorType = typename DataPoint::VectorType;
80 static constexpr Scalar epsilon = Eigen::NumTraits<Scalar>::epsilon();
81
84 {
86 static bool isDegenerate(const VectorType& a, const VectorType& b, const VectorType& c)
87 {
88 Scalar d[3] = {(a - b).norm(), (a - c).norm(), (b - c).norm()};
89 // Checks that the spherical triangle is small or thin.
90 if ((d[0] < epsilon) || (d[1] < epsilon) || (d[2] < epsilon))
91 return true;
92 // Checks that the spherical triangle is flat.
93 size_t m = 0;
94 if (d[1] > d[m])
95 m = 1;
96 if (d[2] > d[m])
97 m = 2;
98 return (fabs(d[m] - d[(m + 1) % 3] - d[(m + 2) % 3]) < epsilon);
99 }
100
102 static void polarTriangle(const VectorType& a, const VectorType& b, const VectorType& c, VectorType& Ap,
103 VectorType& Bp, VectorType& Cp)
104 {
105 Ap = b.cross(c);
106 Bp = c.cross(a);
107 Cp = a.cross(b);
108 // Reorient points.
109 if (Ap.dot(a) < 0.0)
110 Ap = -Ap;
111 if (Bp.dot(b) < 0.0)
112 Bp = -Bp;
113 if (Cp.dot(c) < 0.0)
114 Cp = -Cp;
115 }
116
121 static void interiorAngles(const VectorType& a, const VectorType& b, const VectorType& c, Scalar& alpha,
122 Scalar& beta, Scalar& gamma)
123 {
124 VectorType Ta, Tb, Tc;
125 polarTriangle(a, b, c, Ta, Tb, Tc);
126 Ta /= Ta.norm();
127 Tb /= Tb.norm();
128 Tc /= Tc.norm();
129 if (Ta == VectorType::Zero() || Tb == VectorType::Zero() || Tc == VectorType::Zero())
130 alpha = beta = gamma = Scalar(0.0);
131 else
132 {
133 Scalar ca = std::max(Scalar(-1.0), std::min(Scalar(1.0), Tb.dot(Tc)));
134 Scalar cb = std::max(Scalar(-1.0), std::min(Scalar(1.0), Tc.dot(Ta)));
135 Scalar cc = std::max(Scalar(-1.0), std::min(Scalar(1.0), Ta.dot(Tb)));
136 alpha = acos(ca);
137 beta = acos(cb);
138 gamma = acos(cc);
139 }
140 }
141
143 static Scalar area(const VectorType& a, const VectorType& b, const VectorType& c)
144 {
145 Scalar alpha, beta, gamma;
146 if (isDegenerate(a, b, c))
147 return Scalar(0.0);
149 return ((fabs(alpha) < epsilon) || (fabs(beta) < epsilon) || (fabs(gamma) < epsilon))
150 ? Scalar(0.0)
151 : Scalar(2.0 * M_PI) - alpha - beta - gamma;
152 }
153
155 static Scalar algebraicArea(const VectorType& a, const VectorType& b, const VectorType& c)
156 {
157 Scalar S = area(a, b, c);
158 VectorType M = a + b + c;
159 VectorType X = (b - a).cross(c - a);
160 if (M.template lpNorm<1>() <= epsilon || X.template lpNorm<1>() <= epsilon)
161 return 0.0;
162 return M.dot(X) < 0.0 ? -S : S;
163 }
164 };
165
166 // ---------------------- Main functions ----------------
167 public:
170
183 static Scalar mu0InterpolatedU(const VectorType& a, const VectorType& b, const VectorType& c,
184 const VectorType& ua, const VectorType& ub, const VectorType& uc,
185 bool unit_u = false)
186 {
187 // MU0=1/2*det( uM, B-A, C-A )
188 // = 1/2 < ( (u_A + u_B + u_C)/3.0 ) | (AB x AC ) >
189 VectorType uM = (ua + ub + uc) / 3.0;
190 if (unit_u)
191 {
192 auto uM_norm = uM.norm();
193 uM = uM_norm == Scalar(0.0) ? uM : uM / uM_norm;
194 }
195 return Scalar(0.5) * ((b - a).cross(c - a)).dot(uM);
196 }
197
210 static Scalar mu1InterpolatedU(const VectorType& a, const VectorType& b, const VectorType& c,
211 const VectorType& ua, const VectorType& ub, const VectorType& uc,
212 bool unit_u = false)
213 {
214 // MU1=1/2( | uM u_C-u_B A | + | uM u_A-u_C B | + | uM u_B-u_A C |
215 VectorType uM = (ua + ub + uc) / Scalar(3.0);
216 if (unit_u)
217 uM /= uM.norm();
218 return Scalar(0.25) * (uM.cross(uc - ub).dot(a) + uM.cross(ua - uc).dot(b) + uM.cross(ub - ua).dot(c));
219 }
220
233 static Scalar mu2InterpolatedU(const VectorType& a, const VectorType& b, const VectorType& c,
234 const VectorType& ua, const VectorType& ub, const VectorType& uc,
235 bool unit_u = false)
236 {
237 // Using non unitary interpolated normals give
238 // MU2=1/2*det( uA, uB, uC )
239 // When normals are unitary, it is the area of a spherical triangle.
240 if (unit_u)
242 else
243 return Scalar(0.5) * (ua.cross(ub).dot(uc));
244 }
245
255 static MatrixType muXYInterpolatedU(const VectorType& a, const VectorType& b, const VectorType& c,
256 const VectorType& ua, const VectorType& ub, const VectorType& uc,
257 bool unit_u = false)
258 {
259 MatrixType T = MatrixType::Zero();
260 VectorType uM = (ua + ub + uc) / 3.0;
261 if (unit_u)
262 uM /= uM.norm();
263 const VectorType uac = uc - ua;
264 const VectorType uab = ub - ua;
265 const VectorType ab = b - a;
266 const VectorType ac = c - a;
267 for (size_t i = 0; i < 3; ++i)
268 {
269 VectorType X = VectorType::Zero();
270 X(i) = Scalar(1.0);
271 for (size_t j = 0; j < 3; ++j)
272 {
273 // Since RealVector Y = RealVector::base( j, 1.0 );
274 // < Y | uac > = uac[ j ]
275 const Scalar tij = Scalar(0.5) * uM.dot(uac[j] * X.cross(ab) - uab[j] * X.cross(ac));
276 T(i, j) = tij;
277 }
278 }
279 return T;
280 }
281
283
284 // ---------------------- Helper functions ----------------
285 public:
288
294 static std::pair<VectorType, VectorType> curvDirFromTensor(const MatrixType& tensor, const Scalar area,
295 const VectorType& N)
296 {
297 auto Mt = tensor.transpose();
298 auto M = tensor;
299 M += Mt;
300 M *= 0.5;
301 const Scalar coef_N = Scalar(1000.0) * area;
302 // Adding 1000 area n x n to anisotropic measure
303 for (int j = 0; j < 3; j++)
304 for (int k = 0; k < 3; k++)
305 M(j, k) += coef_N * N[j] * N[k];
306
307 Eigen::SelfAdjointEigenSolver<MatrixType> eigensolver(M);
308 if (eigensolver.info() != Eigen::Success)
309 abort();
310
311 // SelfAdjointEigenSolver returns sorted eigenvalues, no
312 // need to reorder the eigenvectors.
313 assert(eigensolver.eigenvalues()(0) <= eigensolver.eigenvalues()(1));
314 assert(eigensolver.eigenvalues()(1) <= eigensolver.eigenvalues()(2));
315 VectorType v1 = eigensolver.eigenvectors().col(1);
316 VectorType v2 = eigensolver.eigenvectors().col(0);
317 return std::pair<VectorType, VectorType>(v1, v2);
318 }
319
325 static std::tuple<Scalar, Scalar, VectorType, VectorType> curvaturesFromTensor(const MatrixType& tensor,
326 const Scalar area,
327 const VectorType& N)
328 {
329 auto Mt = tensor.transpose();
330 auto M = tensor;
331 M += Mt;
332 M *= 0.5;
333 const Scalar coef_N = Scalar(1000.0) * area;
334 // Adding 1000 area n x n to anisotropic measure
335 for (int j = 0; j < 3; j++)
336 for (int k = 0; k < 3; k++)
337 M(j, k) += coef_N * N[j] * N[k];
338
339 Eigen::SelfAdjointEigenSolver<MatrixType> eigensolver(M);
340 if (eigensolver.info() == Eigen::Success)
341 {
342 // SelfAdjointEigenSolver returns sorted eigenvalues, no
343 // need to reorder the eigenvectors.
344 assert(eigensolver.eigenvalues()(0) <= eigensolver.eigenvalues()(1));
345 assert(eigensolver.eigenvalues()(1) <= eigensolver.eigenvalues()(2));
346 VectorType v1 = eigensolver.eigenvectors().col(0);
347 VectorType v2 = eigensolver.eigenvectors().col(1);
348 return std::make_tuple(-eigensolver.eigenvalues()(0), -eigensolver.eigenvalues()(1), v1, v2);
349 }
350 else
351 {
352 VectorType v1, v2;
353 return std::make_tuple(Scalar(0.0), Scalar(0.0), v1, v2);
354 }
355 }
356
358 }; // struct CNCEigen
359
360} // namespace Ponca::internal
Aggregator class used to declare specialized structures using CRTP.
Definition basket.h:318
Copyright (c) 2022 Jacques-Olivier Lachaud (jacques-olivier.lachaud@univ-savoie.fr) Laboratory of Mat...
Represents a triangle on a sphere of radius one.
static void polarTriangle(const VectorType &a, const VectorType &b, const VectorType &c, VectorType &Ap, VectorType &Bp, VectorType &Cp)
static Scalar area(const VectorType &a, const VectorType &b, const VectorType &c)
static Scalar algebraicArea(const VectorType &a, const VectorType &b, const VectorType &c)
static bool isDegenerate(const VectorType &a, const VectorType &b, const VectorType &c)
Spherical point data type.
static void interiorAngles(const VectorType &a, const VectorType &b, const VectorType &c, Scalar &alpha, Scalar &beta, Scalar &gamma)
Returns the interior angles of the spherical triangle ABC.
This class contains some stand-alone CorrectedNormalCurrent formulas for triangles,...
static Scalar mu2InterpolatedU(const VectorType &a, const VectorType &b, const VectorType &c, const VectorType &ua, const VectorType &ub, const VectorType &uc, bool unit_u=false)
Computes mu2 measure (Gaussian curvature) of triangle abc given an interpolated corrected normal vect...
static Scalar mu0InterpolatedU(const VectorType &a, const VectorType &b, const VectorType &c, const VectorType &ua, const VectorType &ub, const VectorType &uc, bool unit_u=false)
Computes mu0 measure (area) of triangle abc given an interpolated corrected normal vector ua,...
static MatrixType muXYInterpolatedU(const VectorType &a, const VectorType &b, const VectorType &c, const VectorType &ua, const VectorType &ub, const VectorType &uc, bool unit_u=false)
Computes muXY measure (anisotropic curvature) of triangle abc given an interpolated corrected normal ...
static std::tuple< Scalar, Scalar, VectorType, VectorType > curvaturesFromTensor(const MatrixType &tensor, const Scalar area, const VectorType &N)
Computing principal curvatures k1 and k2 from tensor.
static Scalar mu1InterpolatedU(const VectorType &a, const VectorType &b, const VectorType &c, const VectorType &ua, const VectorType &ub, const VectorType &uc, bool unit_u=false)
Computes mu1 measure (mean curvature) of triangle abc given an interpolated corrected normal vector u...
static constexpr Scalar epsilon
Small constant used to approximate zero.
static std::pair< VectorType, VectorType > curvDirFromTensor(const MatrixType &tensor, const Scalar area, const VectorType &N)
Computing principal curvatures k1 and k2 from tensor.