2 * This program is free software: you can redistribute it and/or modify
3 * it under the terms of the GNU Lesser General Public License as
4 * published by the Free Software Foundation, either version 3 of the
5 * License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 * @file DigitalSurfaceConvolver.ih
19 * @author Jeremy Levallois (\c jeremy.levallois@liris.cnrs.fr )
20 * Laboratoire d'InfoRmatique en Image et Systèmes d'information - LIRIS (CNRS, UMR 5205), INSA-Lyon, France
21 * LAboratoire de MAthématiques - LAMA (CNRS, UMR 5127), Université de Savoie, France
25 * Implementation of inline methods defined in DigitalSurfaceConvolver.h
27 * This file is part of the DGtal library.
30///////////////////////////////////////////////////////////////////////////////
31// IMPLEMENTATION of inline methods.
32///////////////////////////////////////////////////////////////////////////////
34//////////////////////////////////////////////////////////////////////////////
36//////////////////////////////////////////////////////////////////////////////
39///////////////////////////////////////////////////////////////////////////////
40// IMPLEMENTATION of inline methods.
41///////////////////////////////////////////////////////////////////////////////
42#include "DGtal/geometry/surfaces/DigitalSurfaceConvolver.h"
43#include "DGtal/kernel/NumberTraits.h"
44///////////////////////////////////////////////////////////////////////////////
45// ----------------------- Standard services ------------------------------
48//////////////////////////////////////////////////////////////////////////////////////////////////////////////
49///////////////////////////////////////////////////// nD /////////////////////////////////////////////////////
50//////////////////////////////////////////////////////////////////////////////////////////////////////////////
52template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
54DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >
55::DigitalSurfaceConvolver( ConstAlias< Functor > f,
56 ConstAlias< KernelFunctor > g,
57 ConstAlias< KSpace > space)
61 isInitFullMasks( false ),
62 isInitKernelAndMasks( false )
64 myEmbedder = Embedder( myKSpace );
67template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
69DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >
70::DigitalSurfaceConvolver( const DigitalSurfaceConvolver& other )
71 : myFFunctor( other.myFFunctor ),
72 myGFunctor( other.myGFunctor ),
73 myKSpace( other.myKSpace ),
74 myEmbedder( other.myEmbedder ),
75 isInitFullMasks( other.isInitFullMasks ),
76 isInitKernelAndMasks( other.isInitKernelAndMasks ),
77 myMasks( other.myMasks ),
78 myKernel( other.myKernel ),
79 myKernelMask( other.myKernelMask ),
80 myKernelKCoordsOrigin( other.myKernelKCoordsOrigin )
84template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
87DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::init
88( const Point & pOrigin,
89 ConstAlias< PairIterators > fullKernel,
90 ConstAlias< std::vector< PairIterators > > masks )
92 KhalimskySpaceND<dimension, typename KSpace::Integer> preK;
93 myKernelKCoordsOrigin = preK.sKCoords(preK.sSpel( pOrigin ));
94 myKernelMask = &fullKernel;
97 // ASSERT ( myMasks->size () == 9 );
99 isInitFullMasks = true;
100 isInitKernelAndMasks = false;
103template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
106DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::init
107( const Point & pOrigin,
108 ConstAlias< DigitalKernel > fullKernel,
109 ConstAlias< std::vector< PairIterators > > masks )
111 KhalimskySpaceND<dimension, typename KSpace::Integer> preK;
112 myKernelKCoordsOrigin = preK.sKCoords(preK.sSpel( pOrigin ));
113 myKernel = &fullKernel;
116 // ASSERT ( myMasks->size () == 9 );
118 isInitFullMasks = false;
119 isInitKernelAndMasks = true;
122template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
123template< typename SurfelIterator >
125typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Quantity
126DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::eval
127( const SurfelIterator & it ) const
129 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
131 Quantity innerSum, outerSum;
133 core_eval( it, innerSum, outerSum, false );
136 return ( innerSum * lambda + outerSum * ( 1.0 - lambda ));
139template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
140template< typename SurfelIterator, typename EvalFunctor >
142typename EvalFunctor::Value
143DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::eval
144( const SurfelIterator & it,
145 EvalFunctor functor ) const
147 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
149 Quantity innerSum, outerSum;
150 Quantity resultQuantity;
152 core_eval( it, innerSum, outerSum, false );
155 resultQuantity = innerSum * lambda + outerSum * ( 1.0 - lambda );
156 return functor( resultQuantity );
159template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
160template< typename SurfelIterator, typename OutputIterator >
163DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::eval
164( const SurfelIterator & itbegin,
165 const SurfelIterator & itend,
166 OutputIterator & result ) const
168 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
171#ifdef DGTAL_DEBUG_VERBOSE
172 Dimension recount = 0;
175 Quantity lastInnerSum;
176 Quantity lastOuterSum;
178 Quantity innerSum, outerSum;
180 Spel lastInnerSpel, lastOuterSpel;
182 /// Iterate on all cells
183 for( SurfelIterator it = itbegin; it != itend; ++it )
187#ifdef DGTAL_DEBUG_VERBOSE
188 bool hasJumped = core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
189 recount = ( hasJumped ) ? recount + 1 : recount;
191 core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
196 core_eval( it, innerSum, outerSum, false, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
200 *result++ = ( innerSum * lambda + outerSum * ( 1.0 - lambda ));
205#ifdef DGTAL_DEBUG_VERBOSE
206 std::cout << "#total cells = " << total << std::endl;
207 std::cout << "#recount = " << recount << std::endl;
211template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
212template< typename SurfelIterator, typename OutputIterator, typename EvalFunctor >
215DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::eval
216( const SurfelIterator & itbegin,
217 const SurfelIterator & itend,
218 OutputIterator & result,
219 EvalFunctor functor ) const
221 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
224#ifdef DGTAL_DEBUG_VERBOSE
225 Dimension recount = 0;
228 Quantity lastInnerSum;
229 Quantity lastOuterSum;
231 Quantity innerSum, outerSum;
232 Quantity resultQuantity;
234 Spel lastInnerSpel, lastOuterSpel;
236 /// Iterate on all cells
237 for( SurfelIterator it = itbegin; it != itend; ++it )
241#ifdef DGTAL_DEBUG_VERBOSE
242 bool hasJumped = core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
243 recount = ( hasJumped ) ? recount + 1 : recount;
245 core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
250 core_eval( it, innerSum, outerSum, false, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
254 resultQuantity = innerSum * lambda + outerSum * ( 1.0 - lambda );
255 *result++ = functor( resultQuantity );
260#ifdef DGTAL_DEBUG_VERBOSE
261 std::cout << "#total cells = " << total << std::endl;
262 std::cout << "#recount = " << recount << std::endl;
270template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
271template< typename SurfelIterator >
273typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::CovarianceMatrix
274DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::evalCovarianceMatrix
275( const SurfelIterator & it ) const
277 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
279 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
281 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false );
284 return ( innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda ));
287template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
288template< typename SurfelIterator, typename EvalFunctor >
290typename EvalFunctor::Value
291DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::evalCovarianceMatrix
292( const SurfelIterator & it,
293 EvalFunctor functor ) const
295 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
297 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
298 CovarianceMatrix resultCovarianceMatrix;
300 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false );
303 resultCovarianceMatrix = innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda );
304 return functor( resultCovarianceMatrix );
307template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
308template< typename SurfelIterator, typename OutputIterator >
311DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::evalCovarianceMatrix
312( const SurfelIterator & itbegin,
313 const SurfelIterator & itend,
314 OutputIterator & result ) const
316 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
319#ifdef DGTAL_DEBUG_VERBOSE
320 Dimension recount = 0;
323 std::vector<Quantity> lastInnerMoments(nbMoments );
324 std::vector<Quantity> lastOuterMoments(nbMoments );
326 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
328 Spel lastInnerSpel, lastOuterSpel;
330 /// Iterate on all cells
331 for( SurfelIterator it = itbegin; it != itend; ++it )
335#ifdef DGTAL_DEBUG_VERBOSE
336 bool hasJumped = core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
337 recount = ( hasJumped ) ? recount + 1 : recount;
339 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
344 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
348 *result++ = ( innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda ));
353#ifdef DGTAL_DEBUG_VERBOSE
354 std::cout << "#total cells = " << total << std::endl;
355 std::cout << "#recount = " << recount << std::endl;
359template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
360template< typename SurfelIterator, typename OutputIterator, typename EvalFunctor >
363DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::evalCovarianceMatrix
364( const SurfelIterator & itbegin,
365 const SurfelIterator & itend,
366 OutputIterator & result,
367 EvalFunctor functor ) const
369 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
372#ifdef DGTAL_DEBUG_VERBOSE
373 Dimension recount = 0;
376 std::vector<Quantity> lastInnerMoments( nbMoments );
377 std::vector<Quantity> lastOuterMoments( nbMoments );
379 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
380 CovarianceMatrix resultCovarianceMatrix;
382 Spel lastInnerSpel, lastOuterSpel;
384 /// Iterate on all cells
385 for( SurfelIterator it = itbegin; it != itend; ++it )
389#ifdef DGTAL_DEBUG_VERBOSE
390 bool hasJumped = core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
391 recount = ( hasJumped ) ? recount + 1 : recount;
393 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
398 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
402 resultCovarianceMatrix = innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda );
403 *result++ = functor( resultCovarianceMatrix );
408#ifdef DGTAL_DEBUG_VERBOSE
409 std::cout << "#total cells = " << total << std::endl;
410 std::cout << "#recount = " << recount << std::endl;
417template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
420DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::isValid() const
425template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
427DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::fillMoments
428( Quantity * aMomentMatrix,
430 double direction ) const
432 RealPoint current = myEmbedder( aSpel );
433 double x = current[ 0 ];
434 double y = current[ 1 ];
436 aMomentMatrix[ 0 ] += direction * 1;
437 aMomentMatrix[ 1 ] += direction * y;
438 aMomentMatrix[ 2 ] += direction * x;
439 aMomentMatrix[ 3 ] += direction * x * y;
440 aMomentMatrix[ 4 ] += direction * y * y;
441 aMomentMatrix[ 5 ] += direction * x * x;
444template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
446DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::computeCovarianceMatrix
447( const Quantity * aMomentMatrix,
448 CovarianceMatrix & aCovarianceMatrix ) const
454 * sum(x*y) sum(y*y) sum(x*x)
461 A.setComponent( 0, 0, aMomentMatrix[ 5 ] );
462 A.setComponent( 0, 1, aMomentMatrix[ 3 ] );
463 A.setComponent( 1, 0, aMomentMatrix[ 3 ] );
464 A.setComponent( 1, 1, aMomentMatrix[ 4 ] );
466 B = 1.0 / aMomentMatrix[ 0 ];
468 C.setComponent( 0, 0, aMomentMatrix[ 2 ] * aMomentMatrix[ 2 ] );
469 C.setComponent( 0, 1, aMomentMatrix[ 2 ] * aMomentMatrix[ 1 ] );
470 C.setComponent( 1, 0, aMomentMatrix[ 1 ] * aMomentMatrix[ 2 ] );
471 C.setComponent( 1, 1, aMomentMatrix[ 1 ] * aMomentMatrix[ 1 ] );
473 aCovarianceMatrix = A - C * B;
477// For Visual Studio, to be defined as a static const, it has to be initialized into the header file
478template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
480DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::nbMoments = 6;
483template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
484typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Spel
485DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultInnerSpel = Spel();
487template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
488typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Spel
489DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultOuterSpel = Spel();
491template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
492typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Quantity
493DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultInnerMoments[ 6 ] = {Quantity(0)};
495template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
496typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Quantity
497DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultOuterMoments[ 6 ] = {Quantity(0)};
499template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
500typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Quantity
501DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultInnerSum = Quantity(0);
503template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
504typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Quantity
505DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultOuterSum = Quantity(0);
507template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
508template< typename SurfelIterator >
510DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::core_eval
511( const SurfelIterator & it,
515 Spel & lastInnerSpel,
516 Spel & lastOuterSpel,
517 Quantity & lastInnerSum,
518 Quantity & lastOuterSum ) const
520 boost::ignore_unused_variable_warning( it );
521 boost::ignore_unused_variable_warning( innerSum );
522 boost::ignore_unused_variable_warning( outerSum);
523 boost::ignore_unused_variable_warning(useLastResults);
524 boost::ignore_unused_variable_warning(lastInnerSum);
525 boost::ignore_unused_variable_warning(lastOuterSum);
526 boost::ignore_unused_variable_warning(lastInnerSpel);
527 boost::ignore_unused_variable_warning(lastOuterSpel);
528 trace.error() << "Unavailable yet." << std::endl;
533template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
534template< typename SurfelIterator >
536DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::core_evalCovarianceMatrix
537( const SurfelIterator & it,
538 CovarianceMatrix & innerMatrix,
539 CovarianceMatrix & outerMatrix,
541 Spel & lastInnerSpel,
542 Spel & lastOuterSpel,
543 Quantity * lastInnerMoments,
544 Quantity * lastOuterMoments ) const
546 boost::ignore_unused_variable_warning(it);
547 boost::ignore_unused_variable_warning(innerMatrix);
548 boost::ignore_unused_variable_warning(outerMatrix);
549 boost::ignore_unused_variable_warning(useLastResults);
550 boost::ignore_unused_variable_warning(lastOuterMoments);
551 boost::ignore_unused_variable_warning(lastInnerMoments);
552 boost::ignore_unused_variable_warning(lastInnerSpel);
553 boost::ignore_unused_variable_warning(lastOuterSpel);
554 trace.error() << "Unavailable yet." << std::endl;
560//////////////////////////////////////////////////////////////////////////////////////////////////////////////
561///////////////////////////////////////////////////// 2D /////////////////////////////////////////////////////
562//////////////////////////////////////////////////////////////////////////////////////////////////////////////
564template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
566DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >
567::DigitalSurfaceConvolver( ConstAlias< Functor > f,
568 ConstAlias< KernelFunctor > g,
569 ConstAlias< KSpace > space)
574 isInitFullMasks( false ),
575 isInitKernelAndMasks( false )
577 myEmbedder = Embedder( myKSpace );
580template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel>
582DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >
583::DigitalSurfaceConvolver( const DigitalSurfaceConvolver& other )
585 myFFunctor( other.myFFunctor ),
586 myGFunctor( other.myGFunctor ),
587 myKSpace( other.myKSpace ),
588 myEmbedder( other.myEmbedder ),
589 isInitFullMasks( other.isInitFullMasks ),
590 isInitKernelAndMasks( other.isInitKernelAndMasks ),
591 myMasks( other.myMasks ),
592 myKernel( other.myKernel ),
593 myKernelMask( other.myKernelMask ),
594 myKernelKCoordsOrigin( other.myKernelKCoordsOrigin )
598template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
601DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::init
602( const Point & pOrigin,
603 ConstAlias< PairIterators > fullKernel,
604 ConstAlias< std::vector< PairIterators > > masks )
606 KhalimskySpaceND<2,typename KSpace::Integer> preK;
607 myKernelKCoordsOrigin = preK.sKCoords(preK.sSpel( pOrigin ));
608 myKernelMask = &fullKernel;
611 ASSERT ( myMasks->size () == 9 );
613 isInitFullMasks = true;
614 isInitKernelAndMasks = false;
617template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
620DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::init
621( const Point & pOrigin,
622 ConstAlias< DigitalKernel > fullKernel,
623 ConstAlias< std::vector< PairIterators > > masks )
625 KhalimskySpaceND<2,typename KSpace::Integer> preK;
626 myKernelKCoordsOrigin = preK.sKCoords(preK.sSpel( pOrigin ));
627 myKernel = &fullKernel;
630 ASSERT ( myMasks->size () == 9 );
632 isInitFullMasks = false;
633 isInitKernelAndMasks = true;
636template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
637template< typename SurfelIterator >
639typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Quantity
640DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::eval
641( const SurfelIterator & it ) const
643 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
645 Quantity innerSum, outerSum;
647 core_eval( it, innerSum, outerSum, false );
650 return ( innerSum * lambda + outerSum * ( 1.0 - lambda ));
653template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
654template< typename SurfelIterator, typename EvalFunctor >
656typename EvalFunctor::Value
657DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::eval
658( const SurfelIterator & it,
659 EvalFunctor functor ) const
661 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
663 Quantity innerSum, outerSum;
664 Quantity resultQuantity;
666 core_eval( it, innerSum, outerSum, false );
669 resultQuantity = innerSum * lambda + outerSum * ( 1.0 - lambda );
670 return functor( resultQuantity );
673template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
674template< typename SurfelIterator, typename OutputIterator >
677DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::eval
678( const SurfelIterator & itbegin,
679 const SurfelIterator & itend,
680 OutputIterator & result ) const
682 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
685#ifdef DGTAL_DEBUG_VERBOSE
686 Dimension recount = 0;
689 Quantity lastInnerSum;
690 Quantity lastOuterSum;
692 Quantity innerSum, outerSum;
694 Spel lastInnerSpel, lastOuterSpel;
696 /// Iterate on all cells
697 for( SurfelIterator it = itbegin; it != itend; ++it )
701#ifdef DGTAL_DEBUG_VERBOSE
702 bool hasJumped = core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
703 recount = ( hasJumped ) ? recount + 1 : recount;
705 core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
710 core_eval( it, innerSum, outerSum, false, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
714 *result++ = ( innerSum * lambda + outerSum * ( 1.0 - lambda ));
719#ifdef DGTAL_DEBUG_VERBOSE
720 std::cout << "#total cells = " << total << std::endl;
721 std::cout << "#recount = " << recount << std::endl;
725template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
726template< typename SurfelIterator, typename OutputIterator, typename EvalFunctor >
729DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::eval
730( const SurfelIterator & itbegin,
731 const SurfelIterator & itend,
732 OutputIterator & result,
733 EvalFunctor functor ) const
735 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
738#ifdef DGTAL_DEBUG_VERBOSE
739 Dimension recount = 0;
742 Quantity lastInnerSum;
743 Quantity lastOuterSum;
745 Quantity innerSum, outerSum;
746 Quantity resultQuantity;
748 Spel lastInnerSpel, lastOuterSpel;
750 /// Iterate on all cells
751 for( SurfelIterator it = itbegin; it != itend; ++it )
755#ifdef DGTAL_DEBUG_VERBOSE
756 bool hasJumped = core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
757 recount = ( hasJumped ) ? recount + 1 : recount;
759 core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
764 core_eval( it, innerSum, outerSum, false, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
768 resultQuantity = innerSum * lambda + outerSum * ( 1.0 - lambda );
769 *result++ = functor( resultQuantity );
774#ifdef DGTAL_DEBUG_VERBOSE
775 std::cout << "#total cells = " << total << std::endl;
776 std::cout << "#recount = " << recount << std::endl;
784template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
785template< typename SurfelIterator >
787typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::CovarianceMatrix
788DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::evalCovarianceMatrix
789( const SurfelIterator & it ) const
791 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
793 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
795 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false );
798 return ( innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda ));
801template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
802template< typename SurfelIterator, typename EvalFunctor >
804typename EvalFunctor::Value
805DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::evalCovarianceMatrix
806( const SurfelIterator & it,
807 EvalFunctor functor ) const
809 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
811 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
812 CovarianceMatrix resultCovarianceMatrix;
814 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false );
817 resultCovarianceMatrix = innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda );
818 return functor( resultCovarianceMatrix );
821template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
822template< typename SurfelIterator, typename OutputIterator >
825DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::evalCovarianceMatrix
826( const SurfelIterator & itbegin,
827 const SurfelIterator & itend,
828 OutputIterator & result ) const
830 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
833#ifdef DGTAL_DEBUG_VERBOSE
834 Dimension recount = 0;
837 std::vector<Quantity> lastInnerMoments( nbMoments );
838 std::vector<Quantity> lastOuterMoments( nbMoments );
840 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
842 Spel lastInnerSpel, lastOuterSpel;
844 /// Iterate on all cells
845 for( SurfelIterator it = itbegin; it != itend; ++it )
849#ifdef DGTAL_DEBUG_VERBOSE
850 bool hasJumped = core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
851 recount = ( hasJumped ) ? recount + 1 : recount;
853 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
858 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
862 *result++ = ( innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda ));
867#ifdef DGTAL_DEBUG_VERBOSE
868 std::cout << "#total cells = " << total << std::endl;
869 std::cout << "#recount = " << recount << std::endl;
873template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
874template< typename SurfelIterator, typename OutputIterator, typename EvalFunctor >
877DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::evalCovarianceMatrix
878( const SurfelIterator & itbegin,
879 const SurfelIterator & itend,
880 OutputIterator & result,
881 EvalFunctor functor ) const
883 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
886#ifdef DGTAL_DEBUG_VERBOSE
887 Dimension recount = 0;
890 std::vector<Quantity> lastInnerMoments( nbMoments );
891 std::vector<Quantity> lastOuterMoments( nbMoments );
893 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
894 CovarianceMatrix resultCovarianceMatrix;
896 Spel lastInnerSpel, lastOuterSpel;
898 /// Iterate on all cells
899 for( SurfelIterator it = itbegin; it != itend; ++it )
903#ifdef DGTAL_DEBUG_VERBOSE
904 bool hasJumped = core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
905 recount = ( hasJumped ) ? recount + 1 : recount;
907 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
912 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
916 resultCovarianceMatrix = innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda );
917 *result++ = functor( resultCovarianceMatrix );
922#ifdef DGTAL_DEBUG_VERBOSE
923 std::cout << "#total cells = " << total << std::endl;
924 std::cout << "#recount = " << recount << std::endl;
931template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
934DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::isValid() const
939template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
941DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::fillMoments
942( Quantity * aMomentMatrix,
944 double direction ) const
946 RealPoint current = myEmbedder( aSpel );
947 double x = current[ 0 ];
948 double y = current[ 1 ];
950 aMomentMatrix[ 0 ] += direction * 1;
951 aMomentMatrix[ 1 ] += direction * y;
952 aMomentMatrix[ 2 ] += direction * x;
953 aMomentMatrix[ 3 ] += direction * x * y;
954 aMomentMatrix[ 4 ] += direction * y * y;
955 aMomentMatrix[ 5 ] += direction * x * x;
958template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
960DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::computeCovarianceMatrix
961( const Quantity * aMomentMatrix,
962 CovarianceMatrix & aCovarianceMatrix ) const
968 A.setComponent( 0, 0, aMomentMatrix[ 5 ] );
969 A.setComponent( 0, 1, aMomentMatrix[ 3 ] );
970 A.setComponent( 1, 0, aMomentMatrix[ 3 ] );
971 A.setComponent( 1, 1, aMomentMatrix[ 4 ] );
973 B = 1.0 / aMomentMatrix[ 0 ];
975 C.setComponent( 0, 0, aMomentMatrix[ 2 ] * aMomentMatrix[ 2 ] );
976 C.setComponent( 0, 1, aMomentMatrix[ 2 ] * aMomentMatrix[ 1 ] );
977 C.setComponent( 1, 0, aMomentMatrix[ 1 ] * aMomentMatrix[ 2 ] );
978 C.setComponent( 1, 1, aMomentMatrix[ 1 ] * aMomentMatrix[ 1 ] );
980 aCovarianceMatrix = A - C * B;
984// For Visual Studio, to be defined as a static const, it has to be initialized into the header file
985template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
987DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::nbMoments = 6;
990template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
991typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Spel
992DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::defaultInnerSpel = Spel();
994template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
995typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Spel
996DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::defaultOuterSpel = Spel();
998template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
999typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Quantity
1000DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::defaultInnerMoments[ 6 ] = {Quantity(0)};
1002template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1003typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Quantity
1004DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::defaultOuterMoments[ 6 ] = {Quantity(0)};
1006template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1007typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Quantity
1008DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::defaultInnerSum = Quantity(0);
1010template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1011typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Quantity
1012DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::defaultOuterSum = Quantity(0);
1014template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1015template< typename SurfelIterator >
1017DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::core_eval
1018( const SurfelIterator & it,
1019 Quantity & innerSum,
1020 Quantity & outerSum,
1021 bool useLastResults,
1022 Spel & lastInnerSpel,
1023 Spel & lastOuterSpel,
1024 Quantity & lastInnerSum,
1025 Quantity & lastOuterSum ) const
1027 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1029 using KPS = typename KSpace::PreCellularGridSpace;
1031#ifdef DGTAL_DEBUG_VERBOSE
1032 Dimension recount = false;
1035 typedef typename Functor::Quantity FQuantity;
1036 DGtal::Dimension nbMasks =static_cast<DGtal::Dimension>( (long)myMasks->size() - 1);
1037 DGtal::Dimension positionOfFullKernel = 4;
1039 Quantity m = NumberTraits< Quantity >::ZERO;
1041 Spel currentInnerSpel, currentOuterSpel;
1043 Point shiftInnerSpel, shiftOuterSpel;
1046 bool bComputed = false; /// <! if the cell has already been computed, continue to the next
1048 int x, y, x2, y2, x2y2;
1049 unsigned int offset;
1053 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
1054 currentInnerSpel = myKSpace.sDirectIncident( *it, kDim ); /// Spel on the border, but inside the shape
1055 shiftInnerSpel = myKSpace.sKCoords( currentInnerSpel ) - myKernelKCoordsOrigin;
1057 /// Check if we can use previous results
1058 if( useLastResults )
1062 if( currentInnerSpel == lastInnerSpel )
1069 else if( currentInnerSpel == lastOuterSpel )
1078 diffSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( lastInnerSpel );
1086 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 );
1088 if( x2y2 != 4 && x2y2 != 8 ) /// Previous and current cells aren't adjacent. Compute on the full kernel
1090 useLastResults = false;
1091#ifdef DGTAL_DEBUG_VERBOSE
1095 else if( offset == positionOfFullKernel ) /// Full kernel in 2D. Never reached because case already considered before. It's a honeypot.
1097 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
1101 useLastResults = true;
1108 if( !useLastResults ) /// Computation on full kernel, we have no previous results
1110 m = NumberTraits< Quantity >::ZERO;
1112 if( isInitFullMasks )
1114 for( KernelConstIterator itm = myKernelMask->first; itm != myKernelMask->second; ++itm )
1116 auto preShiftedSpel = KPS::sSpel( *itm );
1117 preShiftedSpel.coordinates += shiftInnerSpel;
1119 if( myKSpace.sIsInside( preShiftedSpel ) )
1121 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1123 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1124 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1126 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1133 else if( isInitKernelAndMasks )
1135 Domain domain = myKernel->getDomain();
1136 for( typename Domain::ConstIterator itm = domain.begin(), itend = domain.end(); itm != itend; ++itm )
1138 if( myKernel->operator()( *itm ))
1140 auto preShiftedSpel = KPS::sSpel( *itm );
1141 preShiftedSpel.coordinates += shiftInnerSpel;
1143 if( myKSpace.sIsInside( preShiftedSpel ) )
1145 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1147 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1148 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1150 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1160 trace.error() << "DigitalSurfaceConvolver: You need to init the convolver first." << std::endl;
1165 else /// Using lastInnerMoments
1169 /// Part to subtract from previous result.
1170 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
1172 auto preShiftedSpel = KPS::sSpel( *itm );
1173 preShiftedSpel.coordinates += shiftInnerSpel - diffSpel;
1175 if( myKSpace.sIsInside( preShiftedSpel ) )
1177 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1179 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1180 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1182 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1189 /// Part to add from previous result.
1190 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
1192 auto preShiftedSpel = KPS::sSpel( *itm );
1193 preShiftedSpel.coordinates += shiftInnerSpel;
1195 if( myKSpace.sIsInside( preShiftedSpel ) )
1197 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1199 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1200 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1202 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1210 /// Computation of covariance Matrix
1218 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
1219 currentOuterSpel = myKSpace.sIndirectIncident( *it, kDim );
1220 shiftOuterSpel = myKSpace.sKCoords( currentOuterSpel ) - myKernelKCoordsOrigin;
1222 ASSERT( currentInnerSpel != currentOuterSpel );
1224 diffSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( currentInnerSpel );
1232 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 );
1234 if( x2y2 != 4 && x2y2 != 8 ) /// Inside and outside cells aren't adjacent, but should be. It's a honeypot.
1236 trace.error() << "Error - Found that inside and outside cells aren't adjacent. That's not logic.\n";
1238 else if( offset == positionOfFullKernel ) /// Full kernel in 2D. Never reached because case already considered before. It's a honeypot.
1240 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
1244 /// Part to subtract from previous result.
1245 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
1247 auto preShiftedSpel = KPS::sSpel( *itm );
1248 preShiftedSpel.coordinates += shiftOuterSpel - diffSpel;
1250 if( myKSpace.sIsInside( preShiftedSpel ) )
1252 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1254 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1255 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1257 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1264 /// Part to add from previous result.
1265 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
1267 auto preShiftedSpel = KPS::sSpel( *itm );
1268 preShiftedSpel.coordinates += shiftOuterSpel;
1270 if( myKSpace.sIsInside( preShiftedSpel ) )
1272 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1274 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1275 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1277 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1285 /// Computation of covariance Matrix
1290 ASSERT (( lastInnerSum != 0 )); // Maybe a problem here. Can be normal ... but needs to check twice.
1292 lastInnerSpel = currentInnerSpel;
1293 lastOuterSpel = currentOuterSpel;
1295#ifdef DGTAL_DEBUG_VERBOSE
1303template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1304template< typename SurfelIterator >
1306DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::core_evalCovarianceMatrix
1307( const SurfelIterator & it,
1308 CovarianceMatrix & innerMatrix,
1309 CovarianceMatrix & outerMatrix,
1310 bool useLastResults,
1311 Spel & lastInnerSpel,
1312 Spel & lastOuterSpel,
1313 Quantity * lastInnerMoments,
1314 Quantity * lastOuterMoments ) const
1316 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1318 using KPS = typename KSpace::PreCellularGridSpace;
1320#ifdef DGTAL_DEBUG_VERBOSE
1321 Dimension recount = false;
1324 typedef typename Functor::Quantity FQuantity;
1325 DGtal::Dimension nbMasks = myMasks->size() - 1;
1326 DGtal::Dimension positionOfFullKernel = 4;
1328 Quantity m[ nbMoments ]; /// <! [ m00, m01, m10, m11, m02, m20 ]
1329 std::fill( m, m + nbMoments, NumberTraits< Quantity >::ZERO ); /// <! clear array
1331 Spel currentInnerSpel, currentOuterSpel;
1333 Point shiftInnerSpel, shiftOuterSpel;
1336 bool bComputed = false; /// <! if the cell has already been computed, continue to the next
1338 int x, y, x2, y2, x2y2;
1339 unsigned int offset;
1343 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
1344 currentInnerSpel = myKSpace.sDirectIncident( *it, kDim ); /// Spel on the border, but inside the shape
1345 shiftInnerSpel = myKSpace.sKCoords( currentInnerSpel ) - myKernelKCoordsOrigin;
1347 /// Check if we can use previous results
1348 if( useLastResults )
1352 if( currentInnerSpel == lastInnerSpel )
1354 memcpy( m, lastInnerMoments, nbMoments * sizeof( Quantity ));
1355 computeCovarianceMatrix( m, innerMatrix );
1359 else if( currentInnerSpel == lastOuterSpel )
1361 memcpy( m, lastOuterMoments, nbMoments * sizeof( Quantity ));
1362 computeCovarianceMatrix( m, outerMatrix );
1368 diffSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( lastInnerSpel );
1376 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 );
1378 if( x2y2 != 4 && x2y2 != 8 ) /// Previous and current cells aren't adjacent. Compute on the full kernel
1380 useLastResults = false;
1381#ifdef DGTAL_DEBUG_VERBOSE
1385 else if( offset == positionOfFullKernel ) /// Full kernel in 2D. Never reached because case already considered before. It's a honeypot.
1387 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
1391 useLastResults = true;
1398 if( !useLastResults ) /// Computation on full kernel, we have no previous results
1400 std::fill( m, m + nbMoments, NumberTraits< Quantity >::ZERO ); /// <! clear array
1402 if( isInitFullMasks )
1404 for( KernelConstIterator itm = myKernelMask->first; itm != myKernelMask->second; ++itm )
1406 auto preShiftedSpel = KPS::sSpel( *itm );
1407 preShiftedSpel.coordinates += shiftInnerSpel;
1409 if( myKSpace.sIsInside( preShiftedSpel ) )
1411 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1413 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1414 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1416 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1418 fillMoments( m, shiftedSpel, 1.0 );
1423 else if( isInitKernelAndMasks )
1425 Domain domain = myKernel->getDomain();
1426 for( typename Domain::ConstIterator itm = domain.begin(), itend = domain.end(); itm != itend; ++itm )
1428 if( myKernel->operator()( *itm ))
1430 auto preShiftedSpel = KPS::sSpel( *itm );
1431 preShiftedSpel.coordinates += shiftInnerSpel;
1433 if( myKSpace.sIsInside( preShiftedSpel ) )
1435 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1437 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1438 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1440 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1442 fillMoments( m, shiftedSpel, 1.0 );
1450 trace.error() << "DigitalSurfaceConvolver: You need to init the convolver first." << std::endl;
1454 else /// Using lastInnerMoments
1456 memcpy( m, lastInnerMoments, nbMoments * sizeof( Quantity ));
1458 /// Part to subtract from previous result.
1459 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
1461 auto preShiftedSpel = KPS::sSpel( *itm );
1462 preShiftedSpel.coordinates += shiftInnerSpel - diffSpel;
1464 if( myKSpace.sIsInside( preShiftedSpel ) )
1466 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1468 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1469 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1471 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1473 fillMoments( m, shiftedSpel, -1.0 );
1478 /// Part to add from previous result.
1479 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
1481 auto preShiftedSpel = KPS::sSpel( *itm );
1482 preShiftedSpel.coordinates += shiftInnerSpel;
1484 if( myKSpace.sIsInside( preShiftedSpel ) )
1486 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1488 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1489 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1491 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1493 fillMoments( m, shiftedSpel, 1.0 );
1499 /// Computation of covariance Matrix
1500 computeCovarianceMatrix( m, innerMatrix );
1501 memcpy( lastInnerMoments, m, nbMoments * sizeof( Quantity ));
1507 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
1508 currentOuterSpel = myKSpace.sIndirectIncident( *it, kDim );
1509 shiftOuterSpel = myKSpace.sKCoords( currentOuterSpel ) - myKernelKCoordsOrigin;
1511 ASSERT( currentInnerSpel != currentOuterSpel );
1513 diffSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( currentInnerSpel );
1521 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 );
1523 if( x2y2 != 4 && x2y2 != 8 ) /// Inside and outside cells aren't adjacent, but should be. It's a honeypot.
1525 trace.error() << "Error - Found that inside and outside cells aren't adjacent. That's not logic.\n";
1527 else if( offset == positionOfFullKernel ) /// Full kernel in 2D. Never reached because case already considered before. It's a honeypot.
1529 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
1533 /// Part to subtract from previous result.
1534 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
1536 auto preShiftedSpel = KPS::sSpel( *itm );
1537 preShiftedSpel.coordinates += shiftOuterSpel - diffSpel;
1538 if( myKSpace.sIsInside( preShiftedSpel ) )
1540 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1542 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1543 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1545 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1547 fillMoments( m, shiftedSpel, -1.0 );
1552 /// Part to add from previous result.
1553 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
1555 auto preShiftedSpel = KPS::sSpel( *itm );
1556 preShiftedSpel.coordinates += shiftOuterSpel;
1558 if( myKSpace.sIsInside( preShiftedSpel ) )
1560 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1562 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1563 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1565 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1567 fillMoments( m, shiftedSpel, 1.0 );
1573 /// Computation of covariance Matrix
1574 computeCovarianceMatrix( m, outerMatrix );
1575 memcpy( lastOuterMoments, m, nbMoments * sizeof( Quantity ));
1578 ASSERT (( lastInnerMoments[ 0 ] != 0 )); // Maybe a problem here. Can be normal ... but needs to check twice.
1580 lastInnerSpel = currentInnerSpel;
1581 lastOuterSpel = currentOuterSpel;
1583#ifdef DGTAL_DEBUG_VERBOSE
1593//////////////////////////////////////////////////////////////////////////////////////////////////////////////
1594///////////////////////////////////////////////////// 3D /////////////////////////////////////////////////////
1595//////////////////////////////////////////////////////////////////////////////////////////////////////////////
1597template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1599DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >
1600::DigitalSurfaceConvolver( ConstAlias< Functor > f,
1601 ConstAlias< KernelFunctor > g,
1602 ConstAlias< KSpace > space)
1607 isInitFullMasks( false ),
1608 isInitKernelAndMasks( false )
1610 myEmbedder = Embedder( myKSpace );
1613template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel>
1615DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >
1616::DigitalSurfaceConvolver( const DigitalSurfaceConvolver& other )
1618 myFFunctor( other.myFFunctor ),
1619 myGFunctor( other.myGFunctor ),
1620 myKSpace( other.myKSpace ),
1621 myEmbedder( other.myEmbedder ),
1622 isInitFullMasks( other.isInitFullMasks ),
1623 isInitKernelAndMasks( other.isInitKernelAndMasks ),
1624 myMasks( other.myMasks ),
1625 myKernel( other.myKernel ),
1626 myKernelMask( other.myKernelMask ),
1627 myKernelKCoordsOrigin( other.myKernelKCoordsOrigin )
1631template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1634DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::init
1635( const Point & pOrigin,
1636 ConstAlias< PairIterators > fullKernel,
1637 ConstAlias< std::vector< PairIterators > > masks )
1639 KhalimskySpaceND<3,typename KSpace::Integer> preK;
1640 myKernelKCoordsOrigin = preK.sKCoords(preK.sSpel( pOrigin ));
1641 myKernelMask = &fullKernel;
1644 ASSERT ( myMasks->size () == 27 );
1646 isInitFullMasks = true;
1647 isInitKernelAndMasks = false;
1650template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1653DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::init
1654( const Point & pOrigin,
1655 ConstAlias< DigitalKernel > fullKernel,
1656 ConstAlias< std::vector< PairIterators > > masks )
1658 KhalimskySpaceND<3,typename KSpace::Integer> preK;
1659 myKernelKCoordsOrigin = preK.sKCoords(preK.sSpel( pOrigin ));
1660 myKernel = &fullKernel;
1662 ASSERT ( myMasks->size () == 27 );
1664 isInitFullMasks = false;
1665 isInitKernelAndMasks = true;
1671template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1672template< typename SurfelIterator >
1674typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Quantity
1675DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::eval
1676( const SurfelIterator & it ) const
1678 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1680 Quantity innerSum, outerSum;
1682 core_eval( it, innerSum, outerSum, false );
1684 double lambda = 0.5;
1685 return ( innerSum * lambda + outerSum * ( 1.0 - lambda ));
1688template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1689template< typename SurfelIterator, typename EvalFunctor >
1691typename EvalFunctor::Value
1692DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::eval
1693( const SurfelIterator & it,
1694 EvalFunctor functor ) const
1696 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1698 Quantity innerSum, outerSum;
1699 Quantity resultQuantity;
1701 core_eval( it, innerSum, outerSum, false );
1703 double lambda = 0.5;
1704 resultQuantity = innerSum * lambda + outerSum * ( 1.0 - lambda );
1705 return functor( resultQuantity );
1708template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1709template< typename SurfelIterator, typename OutputIterator >
1712DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::eval
1713( const SurfelIterator & itbegin,
1714 const SurfelIterator & itend,
1715 OutputIterator & result ) const
1717 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1719 Dimension total = 0;
1720#ifdef DGTAL_DEBUG_VERBOSE
1721 Dimension recount = 0;
1724 Quantity lastInnerSum;
1725 Quantity lastOuterSum;
1727 Quantity innerSum, outerSum;
1729 Spel lastInnerSpel, lastOuterSpel;
1731 /// Iterate on all cells
1732 for( SurfelIterator it = itbegin; it != itend; ++it )
1736#ifdef DGTAL_DEBUG_VERBOSE
1737 bool hasJumped = core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
1738 recount = ( hasJumped ) ? recount + 1 : recount;
1740 core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
1745 core_eval( it, innerSum, outerSum, false, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
1748 double lambda = 0.5;
1749 *result++ = ( innerSum * lambda + outerSum * ( 1.0 - lambda ));
1754#ifdef DGTAL_DEBUG_VERBOSE
1755 std::cout << "#total cells = " << total << std::endl;
1756 std::cout << "#recount = " << recount << std::endl;
1760template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1761template< typename SurfelIterator, typename OutputIterator, typename EvalFunctor >
1764DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::eval
1765( const SurfelIterator & itbegin,
1766 const SurfelIterator & itend,
1767 OutputIterator & result,
1768 EvalFunctor functor ) const
1770 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1772 Dimension total = 0;
1773#ifdef DGTAL_DEBUG_VERBOSE
1774 Dimension recount = 0;
1777 Quantity lastInnerSum;
1778 Quantity lastOuterSum;
1780 Quantity innerSum, outerSum;
1781 Quantity resultQuantity;
1783 Spel lastInnerSpel, lastOuterSpel;
1785 /// Iterate on all cells
1786 for( SurfelIterator it = itbegin; it != itend; ++it )
1790#ifdef DGTAL_DEBUG_VERBOSE
1791 bool hasJumped = core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
1792 recount = ( hasJumped ) ? recount + 1 : recount;
1794 core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
1799 core_eval( it, innerSum, outerSum, false, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
1802 double lambda = 0.5;
1803 resultQuantity = innerSum * lambda + outerSum * ( 1.0 - lambda );
1804 *result++ = functor( resultQuantity );
1809#ifdef DGTAL_DEBUG_VERBOSE
1810 std::cout << "#total cells = " << total << std::endl;
1811 std::cout << "#recount = " << recount << std::endl;
1817template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1818template< typename SurfelIterator >
1820typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::CovarianceMatrix
1821DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::evalCovarianceMatrix
1822( const SurfelIterator & it ) const
1824 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1826 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
1828 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false );
1830 double lambda = 0.5;
1831 return ( innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda ));
1834template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1835template< typename SurfelIterator, typename EvalFunctor >
1837typename EvalFunctor::Value
1838DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::evalCovarianceMatrix
1839( const SurfelIterator & it,
1840 EvalFunctor functor ) const
1842 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1844 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
1845 CovarianceMatrix resultCovarianceMatrix;
1847 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false );
1849 double lambda = 0.5;
1850 resultCovarianceMatrix = innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda );
1851 return functor( resultCovarianceMatrix );
1854template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1855template< typename SurfelIterator, typename OutputIterator >
1858DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::evalCovarianceMatrix
1859( const SurfelIterator & itbegin,
1860 const SurfelIterator & itend,
1861 OutputIterator & result ) const
1863 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1865 Dimension total = 0;
1866#ifdef DGTAL_DEBUG_VERBOSE
1867 Dimension recount = 0;
1870 std::vector<Quantity> lastInnerMoments( nbMoments );
1871 std::vector<Quantity> lastOuterMoments( nbMoments );
1873 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
1875 Spel lastInnerSpel, lastOuterSpel;
1877 /// Iterate on all cells
1878 for( SurfelIterator it = itbegin; it != itend; ++it )
1882#ifdef DGTAL_DEBUG_VERBOSE
1883 bool hasJumped = core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
1884 recount = ( hasJumped ) ? recount + 1 : recount;
1886 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
1891 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
1894 double lambda = 0.5;
1895 *result++ = ( innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda ));
1900#ifdef DGTAL_DEBUG_VERBOSE
1901 std::cout << "#total cells = " << total << std::endl;
1902 std::cout << "#recount = " << recount << std::endl;
1906template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1907template< typename SurfelIterator, typename OutputIterator, typename EvalFunctor >
1910DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::evalCovarianceMatrix
1911( const SurfelIterator & itbegin,
1912 const SurfelIterator & itend,
1913 OutputIterator & result,
1914 EvalFunctor functor ) const
1916 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1918 Dimension total = 0;
1919#ifdef DGTAL_DEBUG_VERBOSE
1920 Dimension recount = 0;
1923 Quantity *lastInnerMoments = new Quantity[ nbMoments ];
1924 Quantity *lastOuterMoments = new Quantity[ nbMoments ];
1926 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
1927 CovarianceMatrix resultCovarianceMatrix;
1929 Spel lastInnerSpel, lastOuterSpel;
1931 /// Iterate on all cells
1932 for( SurfelIterator it = itbegin; it != itend; ++it )
1936#ifdef DGTAL_DEBUG_VERBOSE
1937 bool hasJumped = core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
1938 recount = ( hasJumped ) ? recount + 1 : recount;
1940 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
1945 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
1948 double lambda = 0.5;
1949 resultCovarianceMatrix = innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda );
1950 *result++ = functor( resultCovarianceMatrix );
1955#ifdef DGTAL_DEBUG_VERBOSE
1956 std::cout << "#total cells = " << total << std::endl;
1957 std::cout << "#recount = " << recount << std::endl;
1960 delete[] lastOuterMoments;
1961 delete[] lastInnerMoments;
1966template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1969DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::isValid() const
1974template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1976DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::fillMoments
1977( Quantity * aMomentMatrix,
1979 double direction ) const
1981 RealPoint current = myEmbedder( aSpel );
1982 double x = current[ 0 ];
1983 double y = current[ 1 ];
1984 double z = current[ 2 ];
1986 aMomentMatrix[ 0 ] += direction * 1;
1987 aMomentMatrix[ 1 ] += direction * z;
1988 aMomentMatrix[ 2 ] += direction * y;
1989 aMomentMatrix[ 3 ] += direction * x;
1990 aMomentMatrix[ 4 ] += direction * y * z;
1991 aMomentMatrix[ 5 ] += direction * x * z;
1992 aMomentMatrix[ 6 ] += direction * x * y;
1993 aMomentMatrix[ 7 ] += direction * z * z;
1994 aMomentMatrix[ 8 ] += direction * y * y;
1995 aMomentMatrix[ 9 ] += direction * x * x;
2000template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2002DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::computeCovarianceMatrix
2003( const Quantity * aMomentMatrix,
2004 CovarianceMatrix & aCovarianceMatrix ) const
2010 A.setComponent( 0, 0, aMomentMatrix[ 9 ] );
2011 A.setComponent( 0, 1, aMomentMatrix[ 6 ] );
2012 A.setComponent( 0, 2, aMomentMatrix[ 5 ] );
2013 A.setComponent( 1, 0, aMomentMatrix[ 6 ] );
2014 A.setComponent( 1, 1, aMomentMatrix[ 8 ] );
2015 A.setComponent( 1, 2, aMomentMatrix[ 4 ] );
2016 A.setComponent( 2, 0, aMomentMatrix[ 5 ] );
2017 A.setComponent( 2, 1, aMomentMatrix[ 4 ] );
2018 A.setComponent( 2, 2, aMomentMatrix[ 7 ] );
2020 B = 1.0 / aMomentMatrix[ 0 ];
2022 C.setComponent( 0, 0, aMomentMatrix[ 3 ] * aMomentMatrix[ 3 ] );
2023 C.setComponent( 0, 1, aMomentMatrix[ 3 ] * aMomentMatrix[ 2 ] );
2024 C.setComponent( 0, 2, aMomentMatrix[ 3 ] * aMomentMatrix[ 1 ] );
2025 C.setComponent( 1, 0, aMomentMatrix[ 2 ] * aMomentMatrix[ 3 ] );
2026 C.setComponent( 1, 1, aMomentMatrix[ 2 ] * aMomentMatrix[ 2 ] );
2027 C.setComponent( 1, 2, aMomentMatrix[ 2 ] * aMomentMatrix[ 1 ] );
2028 C.setComponent( 2, 0, aMomentMatrix[ 1 ] * aMomentMatrix[ 3 ] );
2029 C.setComponent( 2, 1, aMomentMatrix[ 1 ] * aMomentMatrix[ 2 ] );
2030 C.setComponent( 2, 2, aMomentMatrix[ 1 ] * aMomentMatrix[ 1 ] );
2032 aCovarianceMatrix = A - C * B;
2036// For Visual Studio, to be defined as a static const, it has to be initialized into the header file
2037template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2039DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::nbMoments = 10;
2042template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2043typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Spel
2044DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::defaultInnerSpel = Spel();
2046template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2047typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Spel
2048DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::defaultOuterSpel = Spel();
2050template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2051typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Quantity
2052DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::defaultInnerMoments[ 10 ] = {Quantity(0)};
2054template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2055typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Quantity
2056DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::defaultOuterMoments[ 10 ] = {Quantity(0)};
2058template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2059typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Quantity
2060DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::defaultInnerSum = Quantity(0);
2062template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2063typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Quantity
2064DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::defaultOuterSum = Quantity(0);
2066template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2067template< typename SurfelIterator >
2069DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::core_eval
2070( const SurfelIterator & it,
2071 Quantity & innerSum,
2072 Quantity & outerSum,
2073 bool useLastResults,
2074 Spel & lastInnerSpel,
2075 Spel & lastOuterSpel,
2076 Quantity & lastInnerSum,
2077 Quantity & lastOuterSum ) const
2079 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
2081 using KPS = typename KSpace::PreCellularGridSpace;
2083#ifdef DGTAL_DEBUG_VERBOSE
2084 Dimension recount = false;
2087 typedef typename Functor::Quantity FQuantity;
2088 DGtal::Dimension nbMasks = static_cast<DGtal::Dimension>(myMasks->size()) - 1;
2089 DGtal::Dimension positionOfFullKernel = 13;
2091 Quantity m = NumberTraits< Quantity >::ZERO;
2093 Spel currentInnerSpel, currentOuterSpel;
2095 Point shiftInnerSpel, shiftOuterSpel;
2098 bool bComputed = false; /// <! if the cell has already been computed, continue to the next
2100 int x, y, z, x2, y2, z2, x2y2z2;
2101 unsigned int offset;
2105 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
2106 currentInnerSpel = myKSpace.sDirectIncident( *it, kDim ); /// Spel on the border, but inside the shape
2107 shiftInnerSpel = myKSpace.sKCoords( currentInnerSpel ) - myKernelKCoordsOrigin;
2109 /// Check if we can use previous results
2110 if( useLastResults )
2114 if( currentInnerSpel == lastInnerSpel )
2121 else if( currentInnerSpel == lastOuterSpel )
2130 diffSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( lastInnerSpel );
2138 x2y2z2 = x2 + y2 + z2;
2140 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 ) + ((( z / 2 ) + 1 ) * 9 );
2142 if( x2y2z2 != 4 && x2y2z2 != 8 && !( x2 == 4 && y2 == 4 && z2 == 4 )) /// Previous and current cells aren't adjacent. Compute on the full kernel
2144 useLastResults = false;
2145#ifdef DGTAL_DEBUG_VERBOSE
2149 else if( offset == positionOfFullKernel ) /// Full kernel in 3D. Never reached because case already considered before. It's a honeypot.
2151 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
2155 useLastResults = true;
2162 if( !useLastResults ) /// Computation on full kernel, we have no previous results
2164 m = NumberTraits< Quantity >::ZERO;
2166 if( isInitFullMasks )
2168 for( KernelConstIterator itm = myKernelMask->first; itm != myKernelMask->second; ++itm )
2170 auto preShiftedSpel = KPS::sSpel( *itm );
2171 preShiftedSpel.coordinates += shiftInnerSpel;
2173 if( myKSpace.sIsInside( preShiftedSpel ) )
2175 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2177 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2178 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2179 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2181 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2188 else if( isInitKernelAndMasks )
2190 Domain domain = myKernel->getDomain();
2191 for( typename Domain::ConstIterator itm = domain.begin(), itend = domain.end(); itm != itend; ++itm )
2193 if( myKernel->operator()( *itm ))
2195 auto preShiftedSpel = KPS::sSpel( *itm );
2196 preShiftedSpel.coordinates += shiftInnerSpel;
2198 if( myKSpace.sIsInside( preShiftedSpel ) )
2200 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2202 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2203 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2204 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2206 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2216 trace.error() << "DigitalSurfaceConvolver: You need to init the convolver first." << std::endl;
2220 else /// Using lastInnerMoments
2224 /// Part to subtract from previous result.
2225 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
2227 auto preShiftedSpel = KPS::sSpel( *itm );
2228 preShiftedSpel.coordinates += shiftInnerSpel - diffSpel;
2230 if( myKSpace.sIsInside( preShiftedSpel ) )
2232 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2234 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2235 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2236 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2238 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2245 /// Part to add from previous result.
2246 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
2248 auto preShiftedSpel = KPS::sSpel( *itm );
2249 preShiftedSpel.coordinates += shiftInnerSpel;
2251 if( myKSpace.sIsInside( preShiftedSpel ) )
2253 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2255 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2256 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2257 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2259 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2267 /// Computation of covariance Matrix
2275 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
2276 currentOuterSpel = myKSpace.sIndirectIncident( *it, kDim );
2277 shiftOuterSpel = myKSpace.sKCoords( currentOuterSpel ) - myKernelKCoordsOrigin;
2279 ASSERT( currentInnerSpel != currentOuterSpel );
2281 diffSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( currentInnerSpel );
2289 x2y2z2 = x2 + y2 + z2;
2291 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 ) + ((( z / 2 ) + 1) * 9 );
2293 if( x2y2z2 != 4 && x2y2z2 != 8 && !( x2 == 4 && y2 == 4 && z2 == 4 )) /// Inside and outside cells aren't adjacent, but should be. It's a honeypot.
2295 trace.error() << "Error - Found that inside and outside cells aren't adjacent. That's not logic.\n";
2297 else if( offset == positionOfFullKernel ) /// Full kernel in 3D. Never reached because case already considered before. It's a honeypot.
2299 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
2303 /// Part to subtract from previous result.
2304 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
2306 auto preShiftedSpel = KPS::sSpel( *itm );
2307 preShiftedSpel.coordinates += shiftOuterSpel - diffSpel;
2309 if( myKSpace.sIsInside( preShiftedSpel ) )
2311 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates
2314 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2315 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2316 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2318 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2325 /// Part to add from previous result.
2326 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
2328 auto preShiftedSpel = KPS::sSpel( *itm );
2329 preShiftedSpel.coordinates += shiftOuterSpel;
2331 if( myKSpace.sIsInside( preShiftedSpel ) )
2333 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2335 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2336 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2337 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2339 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2347 /// Computation of covariance Matrix
2352 ASSERT (( lastInnerSum != 0 )); // Maybe a problem here. Can be normal ... but needs to check twice.
2354 lastInnerSpel = currentInnerSpel;
2355 lastOuterSpel = currentOuterSpel;
2357#ifdef DGTAL_DEBUG_VERBOSE
2365template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2366template< typename SurfelIterator >
2368DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::core_evalCovarianceMatrix
2369( const SurfelIterator & it,
2370 CovarianceMatrix & innerMatrix,
2371 CovarianceMatrix & outerMatrix,
2372 bool useLastResults,
2373 Spel & lastInnerSpel,
2374 Spel & lastOuterSpel,
2375 Quantity * lastInnerMoments,
2376 Quantity * lastOuterMoments ) const
2378 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
2380 using KPS = typename KSpace::PreCellularGridSpace;
2382#ifdef DGTAL_DEBUG_VERBOSE
2383 Dimension recount = false;
2386 typedef typename Functor::Quantity FQuantity;
2387 DGtal::Dimension nbMasks = static_cast<Dimension>(myMasks->size()) - 1;
2388 DGtal::Dimension positionOfFullKernel = 13;
2390 Quantity m[ nbMoments ]; /// <! [ m000, m001, m010, m100, m011, m101, m110, m002, m020, m200 ]
2391 std::fill( m, m + nbMoments, NumberTraits< Quantity >::ZERO ); /// <! clear array
2393 Spel currentInnerSpel, currentOuterSpel;
2395 Point shiftInnerSpel, shiftOuterSpel;
2398 bool bComputed = false; /// <! if the cell has already been computed, continue to the next
2400 int x, y, z, x2, y2, z2, x2y2z2;
2401 unsigned int offset;
2405 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
2406 currentInnerSpel = myKSpace.sDirectIncident( *it, kDim ); /// Spel on the border, but inside the shape
2407 shiftInnerSpel = myKSpace.sKCoords( currentInnerSpel ) - myKernelKCoordsOrigin;
2409 /// Check if we can use previous results
2410 if( useLastResults )
2414 if( currentInnerSpel == lastInnerSpel )
2416 memcpy( m, lastInnerMoments, nbMoments * sizeof( Quantity ));
2417 computeCovarianceMatrix( m, innerMatrix );
2421 else if( currentInnerSpel == lastOuterSpel )
2423 memcpy( m, lastOuterMoments, nbMoments * sizeof( Quantity ));
2424 computeCovarianceMatrix( m, outerMatrix );
2430 diffSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( lastInnerSpel );
2438 x2y2z2 = x2 + y2 + z2;
2440 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 ) + ((( z / 2 ) + 1 ) * 9 );
2442 if( x2y2z2 != 4 && x2y2z2 != 8 && !( x2 == 4 && y2 == 4 && z2 == 4 )) /// Previous and current cells aren't adjacent. Compute on the full kernel
2444 useLastResults = false;
2445#ifdef DGTAL_DEBUG_VERBOSE
2449 else if( offset == positionOfFullKernel ) /// Full kernel in 3D. Never reached because case already considered before. It's a honeypot.
2451 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
2455 useLastResults = true;
2462 if( !useLastResults ) /// Computation on full kernel, we have no previous results
2464 std::fill( m, m + nbMoments, NumberTraits< Quantity >::ZERO ); /// <! clear array
2466 if( isInitFullMasks )
2468 for( KernelConstIterator itm = myKernelMask->first; itm != myKernelMask->second; ++itm )
2470 auto preShiftedSpel = KPS::sSpel( *itm );
2471 preShiftedSpel.coordinates += shiftInnerSpel;
2473 if( myKSpace.sIsInside( preShiftedSpel ) )
2475 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2477 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2478 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2479 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2481 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2483 fillMoments( m, shiftedSpel, 1.0 );
2488 else if( isInitKernelAndMasks )
2490 Domain domain = myKernel->getDomain();
2491 for( typename Domain::ConstIterator itm = domain.begin(), itend = domain.end(); itm != itend; ++itm )
2493 if( myKernel->operator()( *itm ))
2495 auto preShiftedSpel = KPS::sSpel( *itm );
2496 preShiftedSpel.coordinates += shiftInnerSpel;
2498 if( myKSpace.sIsInside( preShiftedSpel ) )
2500 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2502 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2503 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2504 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2506 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2508 fillMoments( m, shiftedSpel, 1.0 );
2516 trace.error() << "DigitalSurfaceConvolver: You need to init the convolver first." << std::endl;
2520 else /// Using lastInnerMoments
2522 memcpy( m, lastInnerMoments, nbMoments * sizeof( Quantity ));
2524 /// Part to subtract from previous result.
2525 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
2527 auto preShiftedSpel = KPS::sSpel( *itm );
2528 preShiftedSpel.coordinates += shiftInnerSpel - diffSpel;
2530 if( myKSpace.sIsInside( preShiftedSpel ) )
2532 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2534 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2535 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2536 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2538 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2540 fillMoments( m, shiftedSpel, -1.0 );
2545 /// Part to add from previous result.
2546 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
2548 auto preShiftedSpel = KPS::sSpel( *itm );
2549 preShiftedSpel.coordinates += shiftInnerSpel;
2551 if( myKSpace.sIsInside( preShiftedSpel ) )
2553 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2555 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2556 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2557 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2559 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2561 fillMoments( m, shiftedSpel, 1.0 );
2567 /// Computation of covariance Matrix
2568 computeCovarianceMatrix( m, innerMatrix );
2569 memcpy( lastInnerMoments, m, nbMoments * sizeof( Quantity ));
2575 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
2576 currentOuterSpel = myKSpace.sIndirectIncident( *it, kDim );
2577 shiftOuterSpel = myKSpace.sKCoords( currentOuterSpel ) - myKernelKCoordsOrigin;
2579 ASSERT( currentInnerSpel != currentOuterSpel );
2581 diffSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( currentInnerSpel );
2589 x2y2z2 = x2 + y2 + z2;
2591 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 ) + ((( z / 2 ) + 1) * 9 );
2593 if( x2y2z2 != 4 && x2y2z2 != 8 && !( x2 == 4 && y2 == 4 && z2 == 4 )) /// Inside and outside cells aren't adjacent, but should be. It's a honeypot.
2595 trace.error() << "Error - Found that inside and outside cells aren't adjacent. That's not logic.\n";
2597 else if( offset == positionOfFullKernel ) /// Full kernel in 3D. Never reached because case already considered before. It's a honeypot.
2599 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
2603 /// Part to subtract from previous result.
2604 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
2606 auto preShiftedSpel = KPS::sSpel( *itm );
2607 preShiftedSpel.coordinates += shiftOuterSpel - diffSpel;
2609 if( myKSpace.sIsInside( preShiftedSpel ) )
2611 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2613 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2614 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2615 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2617 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2619 fillMoments( m, shiftedSpel, -1.0 );
2624 /// Part to add from previous result.
2625 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
2627 auto preShiftedSpel = KPS::sSpel( *itm );
2628 preShiftedSpel.coordinates += shiftOuterSpel;
2630 if( myKSpace.sIsInside( preShiftedSpel ) )
2632 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2634 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2635 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2636 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2638 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2640 fillMoments( m, shiftedSpel, 1.0 );
2646 /// Computation of covariance Matrix
2647 computeCovarianceMatrix( m, outerMatrix );
2648 memcpy( lastOuterMoments, m, nbMoments * sizeof( Quantity ));
2651 ASSERT (( lastInnerMoments[ 0 ] != 0 )); // Maybe a problem here. Can be normal ... but needs to check twice.
2653 lastInnerSpel = currentInnerSpel;
2654 lastOuterSpel = currentOuterSpel;
2656#ifdef DGTAL_DEBUG_VERBOSE