DGtal 1.3.0
Loading...
Searching...
No Matches
CorrectedNormalCurrentFormula.h
1
17#pragma once
18
31#if defined(CorrectedNormalCurrentFormula_RECURSES)
32#error Recursive header files inclusion detected in CorrectedNormalCurrentFormula.h
33#else // defined(CorrectedNormalCurrentFormula_RECURSES)
35#define CorrectedNormalCurrentFormula_RECURSES
36
37#if !defined CorrectedNormalCurrentFormula_h
39#define CorrectedNormalCurrentFormula_h
40
42// Inclusions
43#include <iostream>
44#include <map>
45#include "DGtal/base/Common.h"
46#include "DGtal/math/linalg/SimpleMatrix.h"
47#include "DGtal/geometry/tools/SphericalTriangle.h"
48
50
51namespace DGtal
52{
53
55 // class CorrectedNormalCurrentFormula
98 template < typename TRealPoint, typename TRealVector >
100 {
101 typedef TRealPoint RealPoint;
102 typedef TRealVector RealVector;
104 typedef std::vector< RealPoint > RealPoints;
105 typedef std::vector< RealVector > RealVectors;
107 typedef std::size_t Index;
109
110 //-------------------------------------------------------------------------
111 public:
114
122 static
124 ( const RealPoint& a, const RealPoint& b, const RealPoint& c,
125 const RealVector& u )
126 {
127 return 0.5 * ( b - a ).crossProduct( c - a ).dot( u );
128 }
129
142 static
144 ( const RealPoint& a, const RealPoint& b, const RealPoint& c,
145 const RealVector& ua, const RealVector& ub, const RealVector& uc,
146 bool unit_u = false )
147 {
148 // MU0=1/2*det( uM, B-A, C-A )
149 // = 1/2 < ( (u_A + u_B + u_C)/3.0 ) | (AB x AC ) >
150 RealVector uM = ( ua+ub+uc ) / 3.0;
151 if ( unit_u )
152 {
153 auto uM_norm = uM.norm();
154 uM = uM_norm == 0.0 ? uM : uM / uM_norm;
155 }
156 return 0.5 * ( b - a ).crossProduct( c - a ).dot( uM );
157 }
158
164 static
165 Scalar mu0ConstantU( const RealPoints& pts, const RealVector& u )
166 {
167 if ( pts.size() < 3 ) return 0.0;
168 if ( pts.size() == 3 )
169 return mu0ConstantU( pts[ 0 ], pts[ 1 ], pts[ 2 ], u );
170 const RealPoint b = barycenter( pts );
171 Scalar a = 0.0;
172 for ( Index i = 0; i < pts.size(); i++ )
173 a += mu0ConstantU( b, pts[ i ], pts[ (i+1)%pts.size() ], u );
174 return a;
175 }
176
185 static
187 bool unit_u = false )
188 {
189 ASSERT( pts.size() == u.size() );
190 if ( pts.size() < 3 ) return 0.0;
191 if ( pts.size() == 3 )
192 return mu0InterpolatedU( pts[ 0 ], pts[ 1 ], pts[ 2 ],
193 u[ 0 ], u[ 1 ], u[ 2 ], unit_u );
194 const RealPoint b = barycenter( pts );
195 const RealVector ub = averageUnitVector( u );
196 Scalar a = 0.0;
197 for ( Index i = 0; i < pts.size(); i++ )
198 a += mu0InterpolatedU( b, pts[ i ], pts[ (i+1)%pts.size() ],
199 ub, u[ i ], u[ (i+1)%pts.size() ], unit_u );
200 return a;
201 }
202
204
205 //-------------------------------------------------------------------------
206 public:
209
225 static
227 ( const RealPoint& a, const RealPoint& b,
228 const RealVector& ur, const RealVector& ul )
229 {
230 RealVector e = b - a;
231 RealVector e1 = ur.crossProduct( ul );
232 const Scalar l1 = std::min( e1.norm(), 1.0 );
233 if ( l1 < 1e-10 ) return 0.0;
234 e1 /= l1;
235 const Scalar Psi = asin( l1 );
236 return -Psi * e.dot( e1 );
237 }
238
247 static
249 ( const RealPoint& a, const RealPoint& b, const RealPoint& c,
250 const RealVector& u )
251 {
252 (void)a; (void)b; (void)c; (void)u;
253 return 0.0;
254 }
255
270 static
272 ( const RealPoint& a, const RealPoint& b, const RealPoint& c,
273 const RealVector& ua, const RealVector& ub, const RealVector& uc,
274 bool unit_u = false )
275 {
276 // MU1=1/2( | uM u_C-u_B A | + | uM u_A-u_C B | + | uM u_B-u_A C |
277 RealVector uM = ( ua+ub+uc ) / 3.0;
278 if ( unit_u ) uM /= uM.norm();
279 return 0.5 * ( uM.crossProduct( uc - ub ).dot( a )
280 + uM.crossProduct( ua - uc ).dot( b )
281 + uM.crossProduct( ub - ua ).dot( c ) );
282 }
283
290 static
291 Scalar mu1ConstantU( const RealPoints& pts, const RealVector& u )
292 {
293 return 0.0;
294 }
295
304 static
306 bool unit_u = false )
307 {
308 ASSERT( pts.size() == u.size() );
309 if ( pts.size() < 3 ) return 0.0;
310 if ( pts.size() == 3 )
311 return mu1InterpolatedU( pts[ 0 ], pts[ 1 ], pts[ 2 ],
312 u[ 0 ], u[ 1 ], u[ 2 ], unit_u );
313 const RealPoint b = barycenter( pts );
314 const RealVector ub = averageUnitVector( u );
315 Scalar a = 0.0;
316 for ( Index i = 0; i < pts.size(); i++ )
317 a += mu1InterpolatedU( b, pts[ i ], pts[ (i+1)%pts.size() ],
318 ub, u[ i ], u[ (i+1)%pts.size() ], unit_u );
319 return a;
320 }
321
323
324 //-------------------------------------------------------------------------
325 public:
328
336 static
338 ( const RealPoint& a, const RealPoint& b, const RealPoint& c,
339 const RealVector& u )
340 {
341 (void)a; (void)b; (void)c; (void)u;
342 return 0.0;
343 }
344
357 static
359 ( const RealPoint& a, const RealVectors& vu )
360 {
362 typedef SphericalTriangle<Space> ST;
363 RealVector avg_u;
364 for ( const auto& u : vu ) avg_u += u;
365 const Scalar l = avg_u.norm();
366 if ( l < 1e-10 )
367 {
368 trace.warning() << "[CorrectedNormalCurrentFormula::mu2ConstantUAtVertex]"
369 << " Invalid surrounding normal vectors at vertex "
370 << a << "."
371 << " Unit normal vectors should lie strictly in the same"
372 << " hemisphere." << std::endl;
373 return 0.0;
374 }
375 avg_u /= l;
376 Scalar mu2 = 0.0;
377 const auto n = vu.size();
378 for ( auto i = 0; i < n; ++i )
379 {
380 ST st( avg_u, vu[ i ], vu[ (i+1) % n ] );
381 mu2 += st.algebraicArea();
382 }
383 return mu2;
384 }
385
400 static
402 ( const RealPoint& a, const RealPoint& b, const RealPoint& c,
403 const RealVector& ua, const RealVector& ub, const RealVector& uc,
404 bool unit_u = false )
405 {
406 // Using non unitary interpolated normals give
407 // MU2=1/2*det( uA, uB, uC )
408 // When normals are unitary, it is the area of a spherical triangle.
409 if ( unit_u )
410 {
412 SphericalTriangle<Space> ST( ua, ub, uc ); // check order.
413 return ST.algebraicArea();
414 }
415 else
416 return 0.5 * ( ua.crossProduct( ub ).dot( uc ) );
417 }
418
424 static
425 Scalar mu2ConstantU( const RealPoints& pts, const RealVector& u )
426 {
427 (void) pts; (void) u;
428 return 0.0;
429 }
430
439 static
441 bool unit_u = false )
442 {
443 ASSERT( pts.size() == u.size() );
444 if ( pts.size() < 3 ) return 0.0;
445 if ( pts.size() == 3 )
446 return mu2InterpolatedU( pts[ 0 ], pts[ 1 ], pts[ 2 ],
447 u[ 0 ], u[ 1 ], u[ 2 ], unit_u );
448 const RealPoint b = barycenter( pts );
449 const RealVector ub = averageUnitVector( u );
450 Scalar a = 0.0;
451 for ( Index i = 0; i < pts.size(); i++ )
452 a += mu2InterpolatedU( b, pts[ i ], pts[ (i+1)%pts.size() ],
453 ub, u[ i ], u[ (i+1)%pts.size() ], unit_u );
454 return a;
455 }
456
458
459 //-------------------------------------------------------------------------
460 public:
463
471 static
473 ( const RealPoint& a, const RealPoint& b, const RealPoint& c,
474 const RealVector& u )
475 {
476 (void)a; (void)b; (void)c; (void)u;
477 return RealTensor { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
478 }
479
495 static
497 ( const RealPoint& a, const RealPoint& b,
498 const RealVector& ur, const RealVector& ul )
499 {
500 RealTensor M { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
501 RealVector e = b - a;
502 RealVector e1 = ur.crossProduct( ul );
503 const Scalar l1 = std::min( e1.norm(), 1.0 );
504 if ( l1 < 1e-10 ) return M;
505 e1 /= l1;
506 const Scalar psi = asin( l1 );
507 const Scalar sin_psi = sin( psi );
508 const Scalar sin_2psi = sin( 2.0 * psi );
509 const RealVector e_x_ur = e. crossProduct( ur );
510 const RealVector e1_x_ur = e1.crossProduct( ur );
511 const RealVector e_x_e1_x_ur = e. crossProduct( e1_x_ur );
512 for ( Dimension i = 0; i < 3; i++ )
513 for ( Dimension j = 0; j < 3; j++ )
514 {
515 Scalar v = (-psi - 0.5*sin_2psi) * e_x_ur[ i ] * e1_x_ur[ j ]
516 + (sin_psi*sin_psi) * ( e_x_ur[ i ] * ur[ j ]
517 - e_x_e1_x_ur[ i ] * e1_x_ur[ j ] )
518 + (psi - 0.5*sin_2psi) * e_x_e1_x_ur[ i ] * ur[ j ];
519 M.setComponent( i, j, -0.5 * v );
520 }
521 return M;
522 }
523
536 static
538 ( const RealPoint& a, const RealPoint& b, const RealPoint& c,
539 const RealVector& ua, const RealVector& ub, const RealVector& uc,
540 bool unit_u = false )
541 {
542 RealTensor T;
543 // MUXY = 1/2 < uM | < Y | uc-ua > X x (b-a) - < Y | ub-ua > X x (c-a) >
544 // MUXY = 1/2 ( < Y | ub-ua > | X uM (c-a) | - < Y | uc-ua > | X uM (b-a) | )
545 RealVector uM = ( ua+ub+uc ) / 3.0;
546 if ( unit_u ) uM /= uM.norm();
547 const RealVector uac = uc - ua;
548 const RealVector uab = ub - ua;
549 const RealVector ab = b - a;
550 const RealVector ac = c - a;
551 for ( Dimension i = 0; i < 3; ++i ) {
552 RealVector X = RealVector::base( i, 1.0 );
553 for ( Dimension j = 0; j < 3; ++j ) {
554 // Since RealVector Y = RealVector::base( j, 1.0 );
555 // < Y | uac > = uac[ j ]
556 const Scalar tij =
557 0.5 * uM.dot( uac[ j ] * X.crossProduct( ab )
558 - uab[ j ] * X.crossProduct( ac ) );
559 T.setComponent( i, j, tij );
560 }
561 }
562 return T;
563 }
564
570 static
572 {
573 (void)pts; (void)u;
574 return RealTensor { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
575 }
576
585 static
587 bool unit_u = false )
588 {
589 ASSERT( pts.size() == u.size() );
590 if ( pts.size() < 3 ) return RealTensor { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
591 if ( pts.size() == 3 )
592 return muXYInterpolatedU( pts[ 0 ], pts[ 1 ], pts[ 2 ],
593 u[ 0 ], u[ 1 ], u[ 2 ], unit_u );
594 const RealPoint b = barycenter( pts );
595 const RealVector ub = averageUnitVector( u );
596 RealTensor T = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
597 for ( Index i = 0; i < pts.size(); i++ )
598 T += muXYInterpolatedU( b, pts[ i ], pts[ (i+1)%pts.size() ],
599 ub, u[ i ], u[ (i+1)%pts.size() ], unit_u );
600 return T;
601 }
602
604
605
606 //-------------------------------------------------------------------------
607 public:
610
614 static
616 {
617 RealPoint b;
618 for ( auto p : pts ) b += p;
619 b /= pts.size();
620 return b;
621 }
622
626 static
628 {
629 RealVector avg;
630 for ( auto v : vecs ) avg += v;
631 auto avg_norm = avg.norm();
632 return avg_norm != 0.0 ? avg / avg_norm : avg;
633 }
634
636
637 };
638
639} // namespace DGtal
640
641
643// Includes inline functions.
644//#include "CorrectedNormalCurrentFormula.ih"
645
646// //
648
649#endif // !defined CorrectedNormalCurrentFormula_h
650
651#undef CorrectedNormalCurrentFormula_RECURSES
652#endif // else defined(CorrectedNormalCurrentFormula_RECURSES)
653
static Self base(Dimension k, Component val=1)
TEuclideanRing Component
Type for Vector elements.
Definition: PointVector.h:614
static const Dimension dimension
Copy of the static dimension of the Point/Vector.
Definition: PointVector.h:626
Aim: implements basic MxN Matrix services (M,N>=1).
Definition: SimpleMatrix.h:76
void setComponent(const DGtal::Dimension i, const DGtal::Dimension j, const Component &aValue)
Aim: Represent a triangle drawn onto a sphere of radius 1.
std::ostream & warning()
DGtal is the top-level namespace which contains all DGtal functions and types.
auto crossProduct(PointVector< 3, LeftEuclideanRing, LeftContainer > const &lhs, PointVector< 3, RightEuclideanRing, RightContainer > const &rhs) -> decltype(DGtal::constructFromArithmeticConversion(lhs, rhs))
Cross product of two 3D Points/Vectors.
DGtal::uint32_t Dimension
Definition: Common.h:137
Trace trace
Definition: Common.h:154
Aim: A helper class that provides static methods to compute corrected normal current formulas of curv...
static RealVector averageUnitVector(const RealVectors &vecs)
static RealTensor muXYInterpolatedU(const RealPoint &a, const RealPoint &b, const RealPoint &c, const RealVector &ua, const RealVector &ub, const RealVector &uc, bool unit_u=false)
static Scalar mu2InterpolatedU(const RealPoints &pts, const RealVectors &u, bool unit_u=false)
static Scalar mu2InterpolatedU(const RealPoint &a, const RealPoint &b, const RealPoint &c, const RealVector &ua, const RealVector &ub, const RealVector &uc, bool unit_u=false)
static Scalar mu1InterpolatedU(const RealPoints &pts, const RealVectors &u, bool unit_u=false)
static Scalar mu1ConstantU(const RealPoints &pts, const RealVector &u)
static Scalar mu2ConstantU(const RealPoint &a, const RealPoint &b, const RealPoint &c, const RealVector &u)
static RealPoint barycenter(const RealPoints &pts)
static RealTensor muXYInterpolatedU(const RealPoints &pts, const RealVectors &u, bool unit_u=false)
static Scalar mu2ConstantU(const RealPoints &pts, const RealVector &u)
static Scalar mu1ConstantUAtEdge(const RealPoint &a, const RealPoint &b, const RealVector &ur, const RealVector &ul)
static Scalar mu1InterpolatedU(const RealPoint &a, const RealPoint &b, const RealPoint &c, const RealVector &ua, const RealVector &ub, const RealVector &uc, bool unit_u=false)
static RealTensor muXYConstantUAtEdge(const RealPoint &a, const RealPoint &b, const RealVector &ur, const RealVector &ul)
static RealTensor muXYConstantU(const RealPoint &a, const RealPoint &b, const RealPoint &c, const RealVector &u)
static Scalar mu2ConstantUAtVertex(const RealPoint &a, const RealVectors &vu)
static Scalar mu0InterpolatedU(const RealPoints &pts, const RealVectors &u, bool unit_u=false)
static Scalar mu1ConstantU(const RealPoint &a, const RealPoint &b, const RealPoint &c, const RealVector &u)
static Scalar mu0ConstantU(const RealPoints &pts, const RealVector &u)
static RealTensor muXYConstantU(const RealPoints &pts, const RealVector &u)
static Scalar mu0InterpolatedU(const RealPoint &a, const RealPoint &b, const RealPoint &c, const RealVector &ua, const RealVector &ub, const RealVector &uc, bool unit_u=false)
static Scalar mu0ConstantU(const RealPoint &a, const RealPoint &b, const RealPoint &c, const RealVector &u)