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 myKernelSpelOrigin( other.myKernelSpelOrigin )
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 myKernelSpelOrigin = myKSpace.sSpel( pOrigin );
93 myKernelMask = &fullKernel;
96 // ASSERT ( myMasks->size () == 9 );
98 isInitFullMasks = true;
99 isInitKernelAndMasks = false;
102template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
105DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::init
106( const Point & pOrigin,
107 ConstAlias< DigitalKernel > fullKernel,
108 ConstAlias< std::vector< PairIterators > > masks )
110 myKernelSpelOrigin = myKSpace.sSpel( pOrigin );
111 myKernel = &fullKernel;
114 // ASSERT ( myMasks->size () == 9 );
116 isInitFullMasks = false;
117 isInitKernelAndMasks = true;
120template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
121template< typename SurfelIterator >
123typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Quantity
124DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::eval
125( const SurfelIterator & it ) const
127 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
129 Quantity innerSum, outerSum;
131 core_eval( it, innerSum, outerSum, false );
134 return ( innerSum * lambda + outerSum * ( 1.0 - lambda ));
137template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
138template< typename SurfelIterator, typename EvalFunctor >
140typename EvalFunctor::Value
141DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::eval
142( const SurfelIterator & it,
143 EvalFunctor functor ) const
145 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
147 Quantity innerSum, outerSum;
148 Quantity resultQuantity;
150 core_eval( it, innerSum, outerSum, false );
153 resultQuantity = innerSum * lambda + outerSum * ( 1.0 - lambda );
154 return functor( resultQuantity );
157template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
158template< typename SurfelIterator, typename OutputIterator >
161DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::eval
162( const SurfelIterator & itbegin,
163 const SurfelIterator & itend,
164 OutputIterator & result ) const
166 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
170 Dimension recount = 0;
173 Quantity lastInnerSum;
174 Quantity lastOuterSum;
176 Quantity innerSum, outerSum;
178 Spel lastInnerSpel, lastOuterSpel;
180 /// Iterate on all cells
181 for( SurfelIterator it = itbegin; it != itend; ++it )
186 bool hasJumped = core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
187 recount = ( hasJumped ) ? recount + 1 : recount;
189 core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
194 core_eval( it, innerSum, outerSum, false, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
198 *result++ = ( innerSum * lambda + outerSum * ( 1.0 - lambda ));
204 std::cout << "#total cells = " << total << std::endl;
205 std::cout << "#recount = " << recount << std::endl;
209template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
210template< typename SurfelIterator, typename OutputIterator, typename EvalFunctor >
213DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::eval
214( const SurfelIterator & itbegin,
215 const SurfelIterator & itend,
216 OutputIterator & result,
217 EvalFunctor functor ) const
219 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
223 Dimension recount = 0;
226 Quantity lastInnerSum;
227 Quantity lastOuterSum;
229 Quantity innerSum, outerSum;
230 Quantity resultQuantity;
232 Spel lastInnerSpel, lastOuterSpel;
234 /// Iterate on all cells
235 for( SurfelIterator it = itbegin; it != itend; ++it )
240 bool hasJumped = core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
241 recount = ( hasJumped ) ? recount + 1 : recount;
243 core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
248 core_eval( it, innerSum, outerSum, false, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
252 resultQuantity = innerSum * lambda + outerSum * ( 1.0 - lambda );
253 *result++ = functor( resultQuantity );
259 std::cout << "#total cells = " << total << std::endl;
260 std::cout << "#recount = " << recount << std::endl;
268template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
269template< typename SurfelIterator >
271typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::CovarianceMatrix
272DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::evalCovarianceMatrix
273( const SurfelIterator & it ) const
275 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
277 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
279 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false );
282 return ( innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda ));
285template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
286template< typename SurfelIterator, typename EvalFunctor >
288typename EvalFunctor::Value
289DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::evalCovarianceMatrix
290( const SurfelIterator & it,
291 EvalFunctor functor ) const
293 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
295 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
296 CovarianceMatrix resultCovarianceMatrix;
298 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false );
301 resultCovarianceMatrix = innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda );
302 return functor( resultCovarianceMatrix );
305template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
306template< typename SurfelIterator, typename OutputIterator >
309DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::evalCovarianceMatrix
310( const SurfelIterator & itbegin,
311 const SurfelIterator & itend,
312 OutputIterator & result ) const
314 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
318 Dimension recount = 0;
321 Quantity lastInnerMoments[ nbMoments ];
322 Quantity lastOuterMoments[ nbMoments ];
324 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
326 Spel lastInnerSpel, lastOuterSpel;
328 /// Iterate on all cells
329 for( SurfelIterator it = itbegin; it != itend; ++it )
334 bool hasJumped = core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
335 recount = ( hasJumped ) ? recount + 1 : recount;
337 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
342 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
346 *result++ = ( innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda ));
352 std::cout << "#total cells = " << total << std::endl;
353 std::cout << "#recount = " << recount << std::endl;
357template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
358template< typename SurfelIterator, typename OutputIterator, typename EvalFunctor >
361DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::evalCovarianceMatrix
362( const SurfelIterator & itbegin,
363 const SurfelIterator & itend,
364 OutputIterator & result,
365 EvalFunctor functor ) const
367 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
371 Dimension recount = 0;
374 Quantity lastInnerMoments[ nbMoments ];
375 Quantity lastOuterMoments[ nbMoments ];
377 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
378 CovarianceMatrix resultCovarianceMatrix;
380 Spel lastInnerSpel, lastOuterSpel;
382 /// Iterate on all cells
383 for( SurfelIterator it = itbegin; it != itend; ++it )
388 bool hasJumped = core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
389 recount = ( hasJumped ) ? recount + 1 : recount;
391 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
396 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
400 resultCovarianceMatrix = innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda );
401 *result++ = functor( resultCovarianceMatrix );
407 std::cout << "#total cells = " << total << std::endl;
408 std::cout << "#recount = " << recount << std::endl;
415template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
418DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::isValid() const
423template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
425DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::fillMoments
426( Quantity * aMomentMatrix,
428 double direction ) const
430 RealPoint current = myEmbedder( aSpel );
431 double x = current[ 0 ];
432 double y = current[ 1 ];
434 aMomentMatrix[ 0 ] += direction * 1;
435 aMomentMatrix[ 1 ] += direction * y;
436 aMomentMatrix[ 2 ] += direction * x;
437 aMomentMatrix[ 3 ] += direction * x * y;
438 aMomentMatrix[ 4 ] += direction * y * y;
439 aMomentMatrix[ 5 ] += direction * x * x;
442template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
444DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::computeCovarianceMatrix
445( const Quantity * aMomentMatrix,
446 CovarianceMatrix & aCovarianceMatrix ) const
452 A.setComponent( 0, 0, aMomentMatrix[ 5 ] );
453 A.setComponent( 0, 1, aMomentMatrix[ 3 ] );
454 A.setComponent( 1, 0, aMomentMatrix[ 3 ] );
455 A.setComponent( 1, 1, aMomentMatrix[ 4 ] );
457 B = 1.0 / aMomentMatrix[ 0 ];
459 C.setComponent( 0, 0, aMomentMatrix[ 2 ] * aMomentMatrix[ 2 ] );
460 C.setComponent( 0, 1, aMomentMatrix[ 2 ] * aMomentMatrix[ 1 ] );
461 C.setComponent( 1, 0, aMomentMatrix[ 1 ] * aMomentMatrix[ 2 ] );
462 C.setComponent( 1, 1, aMomentMatrix[ 1 ] * aMomentMatrix[ 1 ] );
464 aCovarianceMatrix = A - C * B;
468// For Visual Studio, to be defined as a static const, it has to be intialized into the header file
469template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
471DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::nbMoments = 6;
474template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
475typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Spel
476DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultInnerSpel = Spel();
478template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
479typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Spel
480DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultOuterSpel = Spel();
482template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
483typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Quantity
484DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultInnerMoments[ 6 ] = {Quantity(0)};
486template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
487typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Quantity
488DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultOuterMoments[ 6 ] = {Quantity(0)};
490template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
491typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Quantity
492DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultInnerSum = Quantity(0);
494template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
495typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Quantity
496DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultOuterSum = Quantity(0);
498template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
499template< typename SurfelIterator >
501DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::core_eval
502( const SurfelIterator & it,
506 Spel & lastInnerSpel,
507 Spel & lastOuterSpel,
508 Quantity & lastInnerSum,
509 Quantity & lastOuterSum ) const
511 boost::ignore_unused_variable_warning( it );
512 boost::ignore_unused_variable_warning( innerSum );
513 boost::ignore_unused_variable_warning( outerSum);
514 boost::ignore_unused_variable_warning(useLastResults);
515 boost::ignore_unused_variable_warning(lastInnerSum);
516 boost::ignore_unused_variable_warning(lastOuterSum);
517 boost::ignore_unused_variable_warning(lastInnerSpel);
518 boost::ignore_unused_variable_warning(lastOuterSpel);
519 trace.error() << "Unavailable yet." << std::endl;
524template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
525template< typename SurfelIterator >
527DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::core_evalCovarianceMatrix
528( const SurfelIterator & it,
529 CovarianceMatrix & innerMatrix,
530 CovarianceMatrix & outerMatrix,
532 Spel & lastInnerSpel,
533 Spel & lastOuterSpel,
534 Quantity * lastInnerMoments,
535 Quantity * lastOuterMoments ) const
537 boost::ignore_unused_variable_warning(it);
538 boost::ignore_unused_variable_warning(innerMatrix);
539 boost::ignore_unused_variable_warning(outerMatrix);
540 boost::ignore_unused_variable_warning(useLastResults);
541 boost::ignore_unused_variable_warning(lastOuterMoments);
542 boost::ignore_unused_variable_warning(lastInnerMoments);
543 boost::ignore_unused_variable_warning(lastInnerSpel);
544 boost::ignore_unused_variable_warning(lastOuterSpel);
545 trace.error() << "Unavailable yet." << std::endl;
551//////////////////////////////////////////////////////////////////////////////////////////////////////////////
552///////////////////////////////////////////////////// 2D /////////////////////////////////////////////////////
553//////////////////////////////////////////////////////////////////////////////////////////////////////////////
555template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
557DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >
558::DigitalSurfaceConvolver( ConstAlias< Functor > f,
559 ConstAlias< KernelFunctor > g,
560 ConstAlias< KSpace > space)
565 isInitFullMasks( false ),
566 isInitKernelAndMasks( false )
568 myEmbedder = Embedder( myKSpace );
571template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel>
573DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >
574::DigitalSurfaceConvolver( const DigitalSurfaceConvolver& other )
576 myFFunctor( other.myFFunctor ),
577 myGFunctor( other.myGFunctor ),
578 myKSpace( other.myKSpace ),
579 myEmbedder( other.myEmbedder ),
580 isInitFullMasks( other.isInitFullMasks ),
581 isInitKernelAndMasks( other.isInitKernelAndMasks ),
582 myMasks( other.myMasks ),
583 myKernel( other.myKernel ),
584 myKernelMask( other.myKernelMask ),
585 myKernelSpelOrigin( other.myKernelSpelOrigin )
589template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
592DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::init
593( const Point & pOrigin,
594 ConstAlias< PairIterators > fullKernel,
595 ConstAlias< std::vector< PairIterators > > masks )
597 myKernelSpelOrigin = myKSpace.sSpel( pOrigin );
598 myKernelMask = &fullKernel;
601 ASSERT ( myMasks->size () == 9 );
603 isInitFullMasks = true;
604 isInitKernelAndMasks = false;
607template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
610DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::init
611( const Point & pOrigin,
612 ConstAlias< DigitalKernel > fullKernel,
613 ConstAlias< std::vector< PairIterators > > masks )
615 myKernelSpelOrigin = myKSpace.sSpel( pOrigin );
616 myKernel = &fullKernel;
619 ASSERT ( myMasks->size () == 9 );
621 isInitFullMasks = false;
622 isInitKernelAndMasks = true;
625template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
626template< typename SurfelIterator >
628typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Quantity
629DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::eval
630( const SurfelIterator & it ) const
632 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
634 Quantity innerSum, outerSum;
636 core_eval( it, innerSum, outerSum, false );
639 return ( innerSum * lambda + outerSum * ( 1.0 - lambda ));
642template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
643template< typename SurfelIterator, typename EvalFunctor >
645typename EvalFunctor::Value
646DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::eval
647( const SurfelIterator & it,
648 EvalFunctor functor ) const
650 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
652 Quantity innerSum, outerSum;
653 Quantity resultQuantity;
655 core_eval( it, innerSum, outerSum, false );
658 resultQuantity = innerSum * lambda + outerSum * ( 1.0 - lambda );
659 return functor( resultQuantity );
662template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
663template< typename SurfelIterator, typename OutputIterator >
666DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::eval
667( const SurfelIterator & itbegin,
668 const SurfelIterator & itend,
669 OutputIterator & result ) const
671 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
675 Dimension recount = 0;
678 Quantity lastInnerSum;
679 Quantity lastOuterSum;
681 Quantity innerSum, outerSum;
683 Spel lastInnerSpel, lastOuterSpel;
685 /// Iterate on all cells
686 for( SurfelIterator it = itbegin; it != itend; ++it )
691 bool hasJumped = core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
692 recount = ( hasJumped ) ? recount + 1 : recount;
694 core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
699 core_eval( it, innerSum, outerSum, false, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
703 *result++ = ( innerSum * lambda + outerSum * ( 1.0 - lambda ));
709 std::cout << "#total cells = " << total << std::endl;
710 std::cout << "#recount = " << recount << std::endl;
714template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
715template< typename SurfelIterator, typename OutputIterator, typename EvalFunctor >
718DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::eval
719( const SurfelIterator & itbegin,
720 const SurfelIterator & itend,
721 OutputIterator & result,
722 EvalFunctor functor ) const
724 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
728 Dimension recount = 0;
731 Quantity lastInnerSum;
732 Quantity lastOuterSum;
734 Quantity innerSum, outerSum;
735 Quantity resultQuantity;
737 Spel lastInnerSpel, lastOuterSpel;
739 /// Iterate on all cells
740 for( SurfelIterator it = itbegin; it != itend; ++it )
745 bool hasJumped = core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
746 recount = ( hasJumped ) ? recount + 1 : recount;
748 core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
753 core_eval( it, innerSum, outerSum, false, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
757 resultQuantity = innerSum * lambda + outerSum * ( 1.0 - lambda );
758 *result++ = functor( resultQuantity );
764 std::cout << "#total cells = " << total << std::endl;
765 std::cout << "#recount = " << recount << std::endl;
773template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
774template< typename SurfelIterator >
776typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::CovarianceMatrix
777DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::evalCovarianceMatrix
778( const SurfelIterator & it ) const
780 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
782 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
784 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false );
787 return ( innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda ));
790template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
791template< typename SurfelIterator, typename EvalFunctor >
793typename EvalFunctor::Value
794DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::evalCovarianceMatrix
795( const SurfelIterator & it,
796 EvalFunctor functor ) const
798 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
800 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
801 CovarianceMatrix resultCovarianceMatrix;
803 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false );
806 resultCovarianceMatrix = innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda );
807 return functor( resultCovarianceMatrix );
810template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
811template< typename SurfelIterator, typename OutputIterator >
814DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::evalCovarianceMatrix
815( const SurfelIterator & itbegin,
816 const SurfelIterator & itend,
817 OutputIterator & result ) const
819 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
823 Dimension recount = 0;
826 Quantity lastInnerMoments[ nbMoments ];
827 Quantity lastOuterMoments[ nbMoments ];
829 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
831 Spel lastInnerSpel, lastOuterSpel;
833 /// Iterate on all cells
834 for( SurfelIterator it = itbegin; it != itend; ++it )
839 bool hasJumped = core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
840 recount = ( hasJumped ) ? recount + 1 : recount;
842 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
847 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
851 *result++ = ( innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda ));
857 std::cout << "#total cells = " << total << std::endl;
858 std::cout << "#recount = " << recount << std::endl;
862template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
863template< typename SurfelIterator, typename OutputIterator, typename EvalFunctor >
866DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::evalCovarianceMatrix
867( const SurfelIterator & itbegin,
868 const SurfelIterator & itend,
869 OutputIterator & result,
870 EvalFunctor functor ) const
872 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
876 Dimension recount = 0;
879 Quantity lastInnerMoments[ nbMoments ];
880 Quantity lastOuterMoments[ nbMoments ];
882 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
883 CovarianceMatrix resultCovarianceMatrix;
885 Spel lastInnerSpel, lastOuterSpel;
887 /// Iterate on all cells
888 for( SurfelIterator it = itbegin; it != itend; ++it )
893 bool hasJumped = core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
894 recount = ( hasJumped ) ? recount + 1 : recount;
896 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
901 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
905 resultCovarianceMatrix = innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda );
906 *result++ = functor( resultCovarianceMatrix );
912 std::cout << "#total cells = " << total << std::endl;
913 std::cout << "#recount = " << recount << std::endl;
920template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
923DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::isValid() const
928template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
930DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::fillMoments
931( Quantity * aMomentMatrix,
933 double direction ) const
935 RealPoint current = myEmbedder( aSpel );
936 double x = current[ 0 ];
937 double y = current[ 1 ];
939 aMomentMatrix[ 0 ] += direction * 1;
940 aMomentMatrix[ 1 ] += direction * y;
941 aMomentMatrix[ 2 ] += direction * x;
942 aMomentMatrix[ 3 ] += direction * x * y;
943 aMomentMatrix[ 4 ] += direction * y * y;
944 aMomentMatrix[ 5 ] += direction * x * x;
947template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
949DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::computeCovarianceMatrix
950( const Quantity * aMomentMatrix,
951 CovarianceMatrix & aCovarianceMatrix ) const
957 A.setComponent( 0, 0, aMomentMatrix[ 5 ] );
958 A.setComponent( 0, 1, aMomentMatrix[ 3 ] );
959 A.setComponent( 1, 0, aMomentMatrix[ 3 ] );
960 A.setComponent( 1, 1, aMomentMatrix[ 4 ] );
962 B = 1.0 / aMomentMatrix[ 0 ];
964 C.setComponent( 0, 0, aMomentMatrix[ 2 ] * aMomentMatrix[ 2 ] );
965 C.setComponent( 0, 1, aMomentMatrix[ 2 ] * aMomentMatrix[ 1 ] );
966 C.setComponent( 1, 0, aMomentMatrix[ 1 ] * aMomentMatrix[ 2 ] );
967 C.setComponent( 1, 1, aMomentMatrix[ 1 ] * aMomentMatrix[ 1 ] );
969 aCovarianceMatrix = A - C * B;
973// For Visual Studio, to be defined as a static const, it has to be intialized into the header file
974template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
976DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::nbMoments = 6;
979template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
980typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Spel
981DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::defaultInnerSpel = Spel();
983template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
984typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Spel
985DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::defaultOuterSpel = Spel();
987template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
988typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Quantity
989DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::defaultInnerMoments[ 6 ] = {Quantity(0)};
991template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
992typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Quantity
993DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::defaultOuterMoments[ 6 ] = {Quantity(0)};
995template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
996typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Quantity
997DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::defaultInnerSum = Quantity(0);
999template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1000typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Quantity
1001DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::defaultOuterSum = Quantity(0);
1003template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1004template< typename SurfelIterator >
1006DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::core_eval
1007( const SurfelIterator & it,
1008 Quantity & innerSum,
1009 Quantity & outerSum,
1010 bool useLastResults,
1011 Spel & lastInnerSpel,
1012 Spel & lastOuterSpel,
1013 Quantity & lastInnerSum,
1014 Quantity & lastOuterSum ) const
1016 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1018 using KPS = typename KSpace::PreCellularGridSpace;
1021 Dimension recount = false;
1024 typedef typename Functor::Quantity FQuantity;
1025 DGtal::Dimension nbMasks =static_cast<DGtal::Dimension>( (long)myMasks->size() - 1);
1026 DGtal::Dimension positionOfFullKernel = 4;
1028 Quantity m = NumberTraits< Quantity >::ZERO;
1030 Spel currentInnerSpel, currentOuterSpel;
1032 Point shiftInnerSpel, shiftOuterSpel;
1035 bool bComputed = false; /// <! if the cell has already been computed, continue to the next
1037 int x, y, x2, y2, x2y2;
1038 unsigned int offset;
1042 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
1043 currentInnerSpel = myKSpace.sDirectIncident( *it, kDim ); /// Spel on the border, but inside the shape
1044 shiftInnerSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( myKernelSpelOrigin );
1046 /// Check if we can use previous results
1047 if( useLastResults )
1051 if( currentInnerSpel == lastInnerSpel )
1058 else if( currentInnerSpel == lastOuterSpel )
1067 diffSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( lastInnerSpel );
1075 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 );
1077 if( x2y2 != 4 && x2y2 != 8 ) /// Previous and current cells aren't adjacent. Compute on the full kernel
1079 useLastResults = false;
1084 else if( offset == positionOfFullKernel ) /// Full kernel in 2D. Never reached because case already considered before. It's a honeypot.
1086 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
1090 useLastResults = true;
1097 if( !useLastResults ) /// Computation on full kernel, we have no previous results
1099 m = NumberTraits< Quantity >::ZERO;
1101 if( isInitFullMasks )
1103 for( KernelConstIterator itm = myKernelMask->first; itm != myKernelMask->second; ++itm )
1105 auto preShiftedSpel = KPS::sSpel( *itm );
1106 preShiftedSpel.coordinates += shiftInnerSpel;
1108 if( myKSpace.sIsInside( preShiftedSpel ) )
1110 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1112 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1113 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1115 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1122 else if( isInitKernelAndMasks )
1124 Domain domain = myKernel->getDomain();
1125 for( typename Domain::ConstIterator itm = domain.begin(), itend = domain.end(); itm != itend; ++itm )
1127 if( myKernel->operator()( *itm ))
1129 auto preShiftedSpel = KPS::sSpel( *itm );
1130 preShiftedSpel.coordinates += shiftInnerSpel;
1132 if( myKSpace.sIsInside( preShiftedSpel ) )
1134 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1136 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1137 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1139 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1149 trace.error() << "DigitalSurfaceConvolver: You need to init the convolver first." << std::endl;
1154 else /// Using lastInnerMoments
1158 /// Part to substract from previous result.
1159 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
1161 auto preShiftedSpel = KPS::sSpel( *itm );
1162 preShiftedSpel.coordinates += shiftInnerSpel - diffSpel;
1164 if( myKSpace.sIsInside( preShiftedSpel ) )
1166 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1168 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1169 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1171 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1178 /// Part to add from previous result.
1179 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
1181 auto preShiftedSpel = KPS::sSpel( *itm );
1182 preShiftedSpel.coordinates += shiftInnerSpel;
1184 if( myKSpace.sIsInside( preShiftedSpel ) )
1186 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1188 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1189 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1191 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1199 /// Computation of covariance Matrix
1207 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
1208 currentOuterSpel = myKSpace.sIndirectIncident( *it, kDim );
1209 shiftOuterSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( myKernelSpelOrigin );
1211 ASSERT( currentInnerSpel != currentOuterSpel );
1213 diffSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( currentInnerSpel );
1221 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 );
1223 if( x2y2 != 4 && x2y2 != 8 ) /// Inside and outside cells aren't adjacent, but should be. It's a honeypot.
1225 trace.error() << "Error - Found that inside and outside cells aren't adjacent. That's not logic.\n";
1227 else if( offset == positionOfFullKernel ) /// Full kernel in 2D. Never reached because case already considered before. It's a honeypot.
1229 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
1233 /// Part to substract from previous result.
1234 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
1236 auto preShiftedSpel = KPS::sSpel( *itm );
1237 preShiftedSpel.coordinates += shiftOuterSpel - diffSpel;
1239 if( myKSpace.sIsInside( preShiftedSpel ) )
1241 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1243 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1244 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1246 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1253 /// Part to add from previous result.
1254 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
1256 auto preShiftedSpel = KPS::sSpel( *itm );
1257 preShiftedSpel.coordinates += shiftOuterSpel;
1259 if( myKSpace.sIsInside( preShiftedSpel ) )
1261 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1263 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1264 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1266 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1274 /// Computation of covariance Matrix
1279 ASSERT (( lastInnerSum != 0 )); // Maybe a problem here. Can be normal ... but needs to check twice.
1281 lastInnerSpel = currentInnerSpel;
1282 lastOuterSpel = currentOuterSpel;
1292template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1293template< typename SurfelIterator >
1295DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::core_evalCovarianceMatrix
1296( const SurfelIterator & it,
1297 CovarianceMatrix & innerMatrix,
1298 CovarianceMatrix & outerMatrix,
1299 bool useLastResults,
1300 Spel & lastInnerSpel,
1301 Spel & lastOuterSpel,
1302 Quantity * lastInnerMoments,
1303 Quantity * lastOuterMoments ) const
1305 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1307 using KPS = typename KSpace::PreCellularGridSpace;
1310 Dimension recount = false;
1313 typedef typename Functor::Quantity FQuantity;
1314 DGtal::Dimension nbMasks = myMasks->size() - 1;
1315 DGtal::Dimension positionOfFullKernel = 4;
1317 Quantity m[ nbMoments ]; /// <! [ m00, m01, m10, m11, m02, m20 ]
1318 std::fill( m, m + nbMoments, NumberTraits< Quantity >::ZERO ); /// <! clear array
1320 Spel currentInnerSpel, currentOuterSpel;
1322 Point shiftInnerSpel, shiftOuterSpel;
1325 bool bComputed = false; /// <! if the cell has already been computed, continue to the next
1327 int x, y, x2, y2, x2y2;
1328 unsigned int offset;
1332 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
1333 currentInnerSpel = myKSpace.sDirectIncident( *it, kDim ); /// Spel on the border, but inside the shape
1334 shiftInnerSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( myKernelSpelOrigin );
1336 /// Check if we can use previous results
1337 if( useLastResults )
1341 if( currentInnerSpel == lastInnerSpel )
1343 memcpy( m, lastInnerMoments, nbMoments * sizeof( Quantity ));
1344 computeCovarianceMatrix( m, innerMatrix );
1348 else if( currentInnerSpel == lastOuterSpel )
1350 memcpy( m, lastOuterMoments, nbMoments * sizeof( Quantity ));
1351 computeCovarianceMatrix( m, outerMatrix );
1357 diffSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( lastInnerSpel );
1365 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 );
1367 if( x2y2 != 4 && x2y2 != 8 ) /// Previous and current cells aren't adjacent. Compute on the full kernel
1369 useLastResults = false;
1374 else if( offset == positionOfFullKernel ) /// Full kernel in 2D. Never reached because case already considered before. It's a honeypot.
1376 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
1380 useLastResults = true;
1387 if( !useLastResults ) /// Computation on full kernel, we have no previous results
1389 std::fill( m, m + nbMoments, NumberTraits< Quantity >::ZERO ); /// <! clear array
1391 if( isInitFullMasks )
1393 for( KernelConstIterator itm = myKernelMask->first; itm != myKernelMask->second; ++itm )
1395 auto preShiftedSpel = KPS::sSpel( *itm );
1396 preShiftedSpel.coordinates += shiftInnerSpel;
1398 if( myKSpace.sIsInside( preShiftedSpel ) )
1400 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1402 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1403 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1405 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1407 fillMoments( m, shiftedSpel, 1.0 );
1412 else if( isInitKernelAndMasks )
1414 Domain domain = myKernel->getDomain();
1415 for( typename Domain::ConstIterator itm = domain.begin(), itend = domain.end(); itm != itend; ++itm )
1417 if( myKernel->operator()( *itm ))
1419 auto preShiftedSpel = KPS::sSpel( *itm );
1420 preShiftedSpel.coordinates += shiftInnerSpel;
1422 if( myKSpace.sIsInside( preShiftedSpel ) )
1424 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1426 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1427 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1429 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1431 fillMoments( m, shiftedSpel, 1.0 );
1439 trace.error() << "DigitalSurfaceConvolver: You need to init the convolver first." << std::endl;
1443 else /// Using lastInnerMoments
1445 memcpy( m, lastInnerMoments, nbMoments * sizeof( Quantity ));
1447 /// Part to substract from previous result.
1448 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
1450 auto preShiftedSpel = KPS::sSpel( *itm );
1451 preShiftedSpel.coordinates += shiftInnerSpel - diffSpel;
1453 if( myKSpace.sIsInside( preShiftedSpel ) )
1455 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1457 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1458 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1460 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1462 fillMoments( m, shiftedSpel, -1.0 );
1467 /// Part to add from previous result.
1468 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
1470 auto preShiftedSpel = KPS::sSpel( *itm );
1471 preShiftedSpel.coordinates += shiftInnerSpel;
1473 if( myKSpace.sIsInside( preShiftedSpel ) )
1475 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1477 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1478 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1480 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1482 fillMoments( m, shiftedSpel, 1.0 );
1488 /// Computation of covariance Matrix
1489 computeCovarianceMatrix( m, innerMatrix );
1490 memcpy( lastInnerMoments, m, nbMoments * sizeof( Quantity ));
1496 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
1497 currentOuterSpel = myKSpace.sIndirectIncident( *it, kDim );
1498 shiftOuterSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( myKernelSpelOrigin );
1500 ASSERT( currentInnerSpel != currentOuterSpel );
1502 diffSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( currentInnerSpel );
1510 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 );
1512 if( x2y2 != 4 && x2y2 != 8 ) /// Inside and outside cells aren't adjacent, but should be. It's a honeypot.
1514 trace.error() << "Error - Found that inside and outside cells aren't adjacent. That's not logic.\n";
1516 else if( offset == positionOfFullKernel ) /// Full kernel in 2D. Never reached because case already considered before. It's a honeypot.
1518 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
1522 /// Part to substract from previous result.
1523 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
1525 auto preShiftedSpel = KPS::sSpel( *itm );
1526 preShiftedSpel.coordinates += shiftOuterSpel - diffSpel;
1527 if( myKSpace.sIsInside( preShiftedSpel ) )
1529 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1531 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1532 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1534 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1536 fillMoments( m, shiftedSpel, -1.0 );
1541 /// Part to add from previous result.
1542 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
1544 auto preShiftedSpel = KPS::sSpel( *itm );
1545 preShiftedSpel.coordinates += shiftOuterSpel;
1547 if( myKSpace.sIsInside( preShiftedSpel ) )
1549 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1551 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1552 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1554 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1556 fillMoments( m, shiftedSpel, 1.0 );
1562 /// Computation of covariance Matrix
1563 computeCovarianceMatrix( m, outerMatrix );
1564 memcpy( lastOuterMoments, m, nbMoments * sizeof( Quantity ));
1567 ASSERT (( lastInnerMoments[ 0 ] != 0 )); // Maybe a problem here. Can be normal ... but needs to check twice.
1569 lastInnerSpel = currentInnerSpel;
1570 lastOuterSpel = currentOuterSpel;
1582//////////////////////////////////////////////////////////////////////////////////////////////////////////////
1583///////////////////////////////////////////////////// 3D /////////////////////////////////////////////////////
1584//////////////////////////////////////////////////////////////////////////////////////////////////////////////
1586template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1588DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >
1589::DigitalSurfaceConvolver( ConstAlias< Functor > f,
1590 ConstAlias< KernelFunctor > g,
1591 ConstAlias< KSpace > space)
1596 isInitFullMasks( false ),
1597 isInitKernelAndMasks( false )
1599 myEmbedder = Embedder( myKSpace );
1602template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel>
1604DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >
1605::DigitalSurfaceConvolver( const DigitalSurfaceConvolver& other )
1607 myFFunctor( other.myFFunctor ),
1608 myGFunctor( other.myGFunctor ),
1609 myKSpace( other.myKSpace ),
1610 myEmbedder( other.myEmbedder ),
1611 isInitFullMasks( other.isInitFullMasks ),
1612 isInitKernelAndMasks( other.isInitKernelAndMasks ),
1613 myMasks( other.myMasks ),
1614 myKernel( other.myKernel ),
1615 myKernelMask( other.myKernelMask ),
1616 myKernelSpelOrigin( other.myKernelSpelOrigin )
1620template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1623DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::init
1624( const Point & pOrigin,
1625 ConstAlias< PairIterators > fullKernel,
1626 ConstAlias< std::vector< PairIterators > > masks )
1628 myKernelSpelOrigin = myKSpace.sSpel( pOrigin );
1629 myKernelMask = &fullKernel;
1632 ASSERT ( myMasks->size () == 27 );
1634 isInitFullMasks = true;
1635 isInitKernelAndMasks = false;
1638template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1641DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::init
1642( const Point & pOrigin,
1643 ConstAlias< DigitalKernel > fullKernel,
1644 ConstAlias< std::vector< PairIterators > > masks )
1646 myKernelSpelOrigin = myKSpace.sSpel( pOrigin );
1647 myKernel = &fullKernel;
1650 ASSERT ( myMasks->size () == 27 );
1652 isInitFullMasks = false;
1653 isInitKernelAndMasks = true;
1659template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1660template< typename SurfelIterator >
1662typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Quantity
1663DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::eval
1664( const SurfelIterator & it ) const
1666 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1668 Quantity innerSum, outerSum;
1670 core_eval( it, innerSum, outerSum, false );
1672 double lambda = 0.5;
1673 return ( innerSum * lambda + outerSum * ( 1.0 - lambda ));
1676template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1677template< typename SurfelIterator, typename EvalFunctor >
1679typename EvalFunctor::Value
1680DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::eval
1681( const SurfelIterator & it,
1682 EvalFunctor functor ) const
1684 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1686 Quantity innerSum, outerSum;
1687 Quantity resultQuantity;
1689 core_eval( it, innerSum, outerSum, false );
1691 double lambda = 0.5;
1692 resultQuantity = innerSum * lambda + outerSum * ( 1.0 - lambda );
1693 return functor( resultQuantity );
1696template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1697template< typename SurfelIterator, typename OutputIterator >
1700DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::eval
1701( const SurfelIterator & itbegin,
1702 const SurfelIterator & itend,
1703 OutputIterator & result ) const
1705 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1707 Dimension total = 0;
1709 Dimension recount = 0;
1712 Quantity lastInnerSum;
1713 Quantity lastOuterSum;
1715 Quantity innerSum, outerSum;
1717 Spel lastInnerSpel, lastOuterSpel;
1719 /// Iterate on all cells
1720 for( SurfelIterator it = itbegin; it != itend; ++it )
1725 bool hasJumped = core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
1726 recount = ( hasJumped ) ? recount + 1 : recount;
1728 core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
1733 core_eval( it, innerSum, outerSum, false, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
1736 double lambda = 0.5;
1737 *result++ = ( innerSum * lambda + outerSum * ( 1.0 - lambda ));
1743 std::cout << "#total cells = " << total << std::endl;
1744 std::cout << "#recount = " << recount << std::endl;
1748template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1749template< typename SurfelIterator, typename OutputIterator, typename EvalFunctor >
1752DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::eval
1753( const SurfelIterator & itbegin,
1754 const SurfelIterator & itend,
1755 OutputIterator & result,
1756 EvalFunctor functor ) const
1758 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1760 Dimension total = 0;
1762 Dimension recount = 0;
1765 Quantity lastInnerSum;
1766 Quantity lastOuterSum;
1768 Quantity innerSum, outerSum;
1769 Quantity resultQuantity;
1771 Spel lastInnerSpel, lastOuterSpel;
1773 /// Iterate on all cells
1774 for( SurfelIterator it = itbegin; it != itend; ++it )
1779 bool hasJumped = core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
1780 recount = ( hasJumped ) ? recount + 1 : recount;
1782 core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
1787 core_eval( it, innerSum, outerSum, false, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
1790 double lambda = 0.5;
1791 resultQuantity = innerSum * lambda + outerSum * ( 1.0 - lambda );
1792 *result++ = functor( resultQuantity );
1798 std::cout << "#total cells = " << total << std::endl;
1799 std::cout << "#recount = " << recount << std::endl;
1805template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1806template< typename SurfelIterator >
1808typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::CovarianceMatrix
1809DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::evalCovarianceMatrix
1810( const SurfelIterator & it ) const
1812 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1814 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
1816 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false );
1818 double lambda = 0.5;
1819 return ( innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda ));
1822template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1823template< typename SurfelIterator, typename EvalFunctor >
1825typename EvalFunctor::Value
1826DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::evalCovarianceMatrix
1827( const SurfelIterator & it,
1828 EvalFunctor functor ) const
1830 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1832 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
1833 CovarianceMatrix resultCovarianceMatrix;
1835 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false );
1837 double lambda = 0.5;
1838 resultCovarianceMatrix = innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda );
1839 return functor( resultCovarianceMatrix );
1842template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1843template< typename SurfelIterator, typename OutputIterator >
1846DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::evalCovarianceMatrix
1847( const SurfelIterator & itbegin,
1848 const SurfelIterator & itend,
1849 OutputIterator & result ) const
1851 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1853 Dimension total = 0;
1855 Dimension recount = 0;
1858 Quantity lastInnerMoments[ nbMoments ];
1859 Quantity lastOuterMoments[ nbMoments ];
1861 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
1863 Spel lastInnerSpel, lastOuterSpel;
1865 /// Iterate on all cells
1866 for( SurfelIterator it = itbegin; it != itend; ++it )
1871 bool hasJumped = core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
1872 recount = ( hasJumped ) ? recount + 1 : recount;
1874 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
1879 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
1882 double lambda = 0.5;
1883 *result++ = ( innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda ));
1889 std::cout << "#total cells = " << total << std::endl;
1890 std::cout << "#recount = " << recount << std::endl;
1894template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1895template< typename SurfelIterator, typename OutputIterator, typename EvalFunctor >
1898DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::evalCovarianceMatrix
1899( const SurfelIterator & itbegin,
1900 const SurfelIterator & itend,
1901 OutputIterator & result,
1902 EvalFunctor functor ) const
1904 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1906 Dimension total = 0;
1908 Dimension recount = 0;
1911 Quantity *lastInnerMoments = new Quantity[ nbMoments ];
1912 Quantity *lastOuterMoments = new Quantity[ nbMoments ];
1914 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
1915 CovarianceMatrix resultCovarianceMatrix;
1917 Spel lastInnerSpel, lastOuterSpel;
1919 /// Iterate on all cells
1920 for( SurfelIterator it = itbegin; it != itend; ++it )
1925 bool hasJumped = core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
1926 recount = ( hasJumped ) ? recount + 1 : recount;
1928 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
1933 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
1936 double lambda = 0.5;
1937 resultCovarianceMatrix = innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda );
1938 *result++ = functor( resultCovarianceMatrix );
1944 std::cout << "#total cells = " << total << std::endl;
1945 std::cout << "#recount = " << recount << std::endl;
1951template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1954DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::isValid() const
1959template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1961DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::fillMoments
1962( Quantity * aMomentMatrix,
1964 double direction ) const
1966 RealPoint current = myEmbedder( aSpel );
1967 double x = current[ 0 ];
1968 double y = current[ 1 ];
1969 double z = current[ 2 ];
1971 aMomentMatrix[ 0 ] += direction * 1;
1972 aMomentMatrix[ 1 ] += direction * z;
1973 aMomentMatrix[ 2 ] += direction * y;
1974 aMomentMatrix[ 3 ] += direction * x;
1975 aMomentMatrix[ 4 ] += direction * y * z;
1976 aMomentMatrix[ 5 ] += direction * x * z;
1977 aMomentMatrix[ 6 ] += direction * x * y;
1978 aMomentMatrix[ 7 ] += direction * z * z;
1979 aMomentMatrix[ 8 ] += direction * y * y;
1980 aMomentMatrix[ 9 ] += direction * x * x;
1985template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1987DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::computeCovarianceMatrix
1988( const Quantity * aMomentMatrix,
1989 CovarianceMatrix & aCovarianceMatrix ) const
1995 A.setComponent( 0, 0, aMomentMatrix[ 9 ] );
1996 A.setComponent( 0, 1, aMomentMatrix[ 6 ] );
1997 A.setComponent( 0, 2, aMomentMatrix[ 5 ] );
1998 A.setComponent( 1, 0, aMomentMatrix[ 6 ] );
1999 A.setComponent( 1, 1, aMomentMatrix[ 8 ] );
2000 A.setComponent( 1, 2, aMomentMatrix[ 4 ] );
2001 A.setComponent( 2, 0, aMomentMatrix[ 5 ] );
2002 A.setComponent( 2, 1, aMomentMatrix[ 4 ] );
2003 A.setComponent( 2, 2, aMomentMatrix[ 7 ] );
2005 B = 1.0 / aMomentMatrix[ 0 ];
2007 C.setComponent( 0, 0, aMomentMatrix[ 3 ] * aMomentMatrix[ 3 ] );
2008 C.setComponent( 0, 1, aMomentMatrix[ 3 ] * aMomentMatrix[ 2 ] );
2009 C.setComponent( 0, 2, aMomentMatrix[ 3 ] * aMomentMatrix[ 1 ] );
2010 C.setComponent( 1, 0, aMomentMatrix[ 2 ] * aMomentMatrix[ 3 ] );
2011 C.setComponent( 1, 1, aMomentMatrix[ 2 ] * aMomentMatrix[ 2 ] );
2012 C.setComponent( 1, 2, aMomentMatrix[ 2 ] * aMomentMatrix[ 1 ] );
2013 C.setComponent( 2, 0, aMomentMatrix[ 1 ] * aMomentMatrix[ 3 ] );
2014 C.setComponent( 2, 1, aMomentMatrix[ 1 ] * aMomentMatrix[ 2 ] );
2015 C.setComponent( 2, 2, aMomentMatrix[ 1 ] * aMomentMatrix[ 1 ] );
2017 aCovarianceMatrix = A - C * B;
2021// For Visual Studio, to be defined as a static const, it has to be intialized into the header file
2022template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2024DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::nbMoments = 10;
2027template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2028typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Spel
2029DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::defaultInnerSpel = Spel();
2031template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2032typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Spel
2033DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::defaultOuterSpel = Spel();
2035template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2036typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Quantity
2037DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::defaultInnerMoments[ 10 ] = {Quantity(0)};
2039template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2040typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Quantity
2041DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::defaultOuterMoments[ 10 ] = {Quantity(0)};
2043template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2044typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Quantity
2045DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::defaultInnerSum = Quantity(0);
2047template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2048typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Quantity
2049DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::defaultOuterSum = Quantity(0);
2051template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2052template< typename SurfelIterator >
2054DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::core_eval
2055( const SurfelIterator & it,
2056 Quantity & innerSum,
2057 Quantity & outerSum,
2058 bool useLastResults,
2059 Spel & lastInnerSpel,
2060 Spel & lastOuterSpel,
2061 Quantity & lastInnerSum,
2062 Quantity & lastOuterSum ) const
2064 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
2066 using KPS = typename KSpace::PreCellularGridSpace;
2069 Dimension recount = false;
2072 typedef typename Functor::Quantity FQuantity;
2073 DGtal::Dimension nbMasks = static_cast<DGtal::Dimension>(myMasks->size()) - 1;
2074 DGtal::Dimension positionOfFullKernel = 13;
2076 Quantity m = NumberTraits< Quantity >::ZERO;
2078 Spel currentInnerSpel, currentOuterSpel;
2080 Point shiftInnerSpel, shiftOuterSpel;
2083 bool bComputed = false; /// <! if the cell has already been computed, continue to the next
2085 int x, y, z, x2, y2, z2, x2y2z2;
2086 unsigned int offset;
2090 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
2091 currentInnerSpel = myKSpace.sDirectIncident( *it, kDim ); /// Spel on the border, but inside the shape
2092 shiftInnerSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( myKernelSpelOrigin );
2094 /// Check if we can use previous results
2095 if( useLastResults )
2099 if( currentInnerSpel == lastInnerSpel )
2106 else if( currentInnerSpel == lastOuterSpel )
2115 diffSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( lastInnerSpel );
2123 x2y2z2 = x2 + y2 + z2;
2125 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 ) + ((( z / 2 ) + 1 ) * 9 );
2127 if( x2y2z2 != 4 && x2y2z2 != 8 && !( x2 == 4 && y2 == 4 && z2 == 4 )) /// Previous and current cells aren't adjacent. Compute on the full kernel
2129 useLastResults = false;
2134 else if( offset == positionOfFullKernel ) /// Full kernel in 3D. Never reached because case already considered before. It's a honeypot.
2136 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
2140 useLastResults = true;
2147 if( !useLastResults ) /// Computation on full kernel, we have no previous results
2149 m = NumberTraits< Quantity >::ZERO;
2151 if( isInitFullMasks )
2153 for( KernelConstIterator itm = myKernelMask->first; itm != myKernelMask->second; ++itm )
2155 auto preShiftedSpel = KPS::sSpel( *itm );
2156 preShiftedSpel.coordinates += shiftInnerSpel;
2158 if( myKSpace.sIsInside( preShiftedSpel ) )
2160 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2162 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2163 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2164 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2166 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2173 else if( isInitKernelAndMasks )
2175 Domain domain = myKernel->getDomain();
2176 for( typename Domain::ConstIterator itm = domain.begin(), itend = domain.end(); itm != itend; ++itm )
2178 if( myKernel->operator()( *itm ))
2180 auto preShiftedSpel = KPS::sSpel( *itm );
2181 preShiftedSpel.coordinates += shiftInnerSpel;
2183 if( myKSpace.sIsInside( preShiftedSpel ) )
2185 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2187 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2188 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2189 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2191 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2201 trace.error() << "DigitalSurfaceConvolver: You need to init the convolver first." << std::endl;
2205 else /// Using lastInnerMoments
2209 /// Part to substract from previous result.
2210 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
2212 auto preShiftedSpel = KPS::sSpel( *itm );
2213 preShiftedSpel.coordinates += shiftInnerSpel - diffSpel;
2215 if( myKSpace.sIsInside( preShiftedSpel ) )
2217 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2219 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2220 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2221 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2223 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2230 /// Part to add from previous result.
2231 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
2233 auto preShiftedSpel = KPS::sSpel( *itm );
2234 preShiftedSpel.coordinates += shiftInnerSpel;
2236 if( myKSpace.sIsInside( preShiftedSpel ) )
2238 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2240 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2241 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2242 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2244 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2252 /// Computation of covariance Matrix
2260 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
2261 currentOuterSpel = myKSpace.sIndirectIncident( *it, kDim );
2262 shiftOuterSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( myKernelSpelOrigin );
2264 ASSERT( currentInnerSpel != currentOuterSpel );
2266 diffSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( currentInnerSpel );
2274 x2y2z2 = x2 + y2 + z2;
2276 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 ) + ((( z / 2 ) + 1) * 9 );
2278 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.
2280 trace.error() << "Error - Found that inside and outside cells aren't adjacent. That's not logic.\n";
2282 else if( offset == positionOfFullKernel ) /// Full kernel in 3D. Never reached because case already considered before. It's a honeypot.
2284 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
2288 /// Part to substract from previous result.
2289 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
2291 auto preShiftedSpel = KPS::sSpel( *itm );
2292 preShiftedSpel.coordinates += shiftOuterSpel - diffSpel;
2294 if( myKSpace.sIsInside( preShiftedSpel ) )
2296 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates
2299 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2300 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2301 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2303 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2310 /// Part to add from previous result.
2311 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
2313 auto preShiftedSpel = KPS::sSpel( *itm );
2314 preShiftedSpel.coordinates += shiftOuterSpel;
2316 if( myKSpace.sIsInside( preShiftedSpel ) )
2318 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2320 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2321 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2322 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2324 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2332 /// Computation of covariance Matrix
2337 ASSERT (( lastInnerSum != 0 )); // Maybe a problem here. Can be normal ... but needs to check twice.
2339 lastInnerSpel = currentInnerSpel;
2340 lastOuterSpel = currentOuterSpel;
2350template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2351template< typename SurfelIterator >
2353DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::core_evalCovarianceMatrix
2354( const SurfelIterator & it,
2355 CovarianceMatrix & innerMatrix,
2356 CovarianceMatrix & outerMatrix,
2357 bool useLastResults,
2358 Spel & lastInnerSpel,
2359 Spel & lastOuterSpel,
2360 Quantity * lastInnerMoments,
2361 Quantity * lastOuterMoments ) const
2363 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
2365 using KPS = typename KSpace::PreCellularGridSpace;
2368 Dimension recount = false;
2371 typedef typename Functor::Quantity FQuantity;
2372 DGtal::Dimension nbMasks = static_cast<Dimension>(myMasks->size()) - 1;
2373 DGtal::Dimension positionOfFullKernel = 13;
2375 Quantity m[ nbMoments ]; /// <! [ m000, m001, m010, m100, m011, m101, m110, m002, m020, m200 ]
2376 std::fill( m, m + nbMoments, NumberTraits< Quantity >::ZERO ); /// <! clear array
2378 Spel currentInnerSpel, currentOuterSpel;
2380 Point shiftInnerSpel, shiftOuterSpel;
2383 bool bComputed = false; /// <! if the cell has already been computed, continue to the next
2385 int x, y, z, x2, y2, z2, x2y2z2;
2386 unsigned int offset;
2390 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
2391 currentInnerSpel = myKSpace.sDirectIncident( *it, kDim ); /// Spel on the border, but inside the shape
2392 shiftInnerSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( myKernelSpelOrigin );
2394 /// Check if we can use previous results
2395 if( useLastResults )
2399 if( currentInnerSpel == lastInnerSpel )
2401 memcpy( m, lastInnerMoments, nbMoments * sizeof( Quantity ));
2402 computeCovarianceMatrix( m, innerMatrix );
2406 else if( currentInnerSpel == lastOuterSpel )
2408 memcpy( m, lastOuterMoments, nbMoments * sizeof( Quantity ));
2409 computeCovarianceMatrix( m, outerMatrix );
2415 diffSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( lastInnerSpel );
2423 x2y2z2 = x2 + y2 + z2;
2425 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 ) + ((( z / 2 ) + 1 ) * 9 );
2427 if( x2y2z2 != 4 && x2y2z2 != 8 && !( x2 == 4 && y2 == 4 && z2 == 4 )) /// Previous and current cells aren't adjacent. Compute on the full kernel
2429 useLastResults = false;
2434 else if( offset == positionOfFullKernel ) /// Full kernel in 3D. Never reached because case already considered before. It's a honeypot.
2436 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
2440 useLastResults = true;
2447 if( !useLastResults ) /// Computation on full kernel, we have no previous results
2449 std::fill( m, m + nbMoments, NumberTraits< Quantity >::ZERO ); /// <! clear array
2451 if( isInitFullMasks )
2453 for( KernelConstIterator itm = myKernelMask->first; itm != myKernelMask->second; ++itm )
2455 auto preShiftedSpel = KPS::sSpel( *itm );
2456 preShiftedSpel.coordinates += shiftInnerSpel;
2458 if( myKSpace.sIsInside( preShiftedSpel ) )
2460 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2462 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2463 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2464 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2466 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2468 fillMoments( m, shiftedSpel, 1.0 );
2473 else if( isInitKernelAndMasks )
2475 Domain domain = myKernel->getDomain();
2476 for( typename Domain::ConstIterator itm = domain.begin(), itend = domain.end(); itm != itend; ++itm )
2478 if( myKernel->operator()( *itm ))
2480 auto preShiftedSpel = KPS::sSpel( *itm );
2481 preShiftedSpel.coordinates += shiftInnerSpel;
2483 if( myKSpace.sIsInside( preShiftedSpel ) )
2485 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2487 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2488 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2489 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2491 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2493 fillMoments( m, shiftedSpel, 1.0 );
2501 trace.error() << "DigitalSurfaceConvolver: You need to init the convolver first." << std::endl;
2505 else /// Using lastInnerMoments
2507 memcpy( m, lastInnerMoments, nbMoments * sizeof( Quantity ));
2509 /// Part to substract from previous result.
2510 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
2512 auto preShiftedSpel = KPS::sSpel( *itm );
2513 preShiftedSpel.coordinates += shiftInnerSpel - diffSpel;
2515 if( myKSpace.sIsInside( preShiftedSpel ) )
2517 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2519 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2520 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2521 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2523 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2525 fillMoments( m, shiftedSpel, -1.0 );
2530 /// Part to add from previous result.
2531 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
2533 auto preShiftedSpel = KPS::sSpel( *itm );
2534 preShiftedSpel.coordinates += shiftInnerSpel;
2536 if( myKSpace.sIsInside( preShiftedSpel ) )
2538 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2540 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2541 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2542 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2544 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2546 fillMoments( m, shiftedSpel, 1.0 );
2552 /// Computation of covariance Matrix
2553 computeCovarianceMatrix( m, innerMatrix );
2554 memcpy( lastInnerMoments, m, nbMoments * sizeof( Quantity ));
2560 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
2561 currentOuterSpel = myKSpace.sIndirectIncident( *it, kDim );
2562 shiftOuterSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( myKernelSpelOrigin );
2564 ASSERT( currentInnerSpel != currentOuterSpel );
2566 diffSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( currentInnerSpel );
2574 x2y2z2 = x2 + y2 + z2;
2576 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 ) + ((( z / 2 ) + 1) * 9 );
2578 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.
2580 trace.error() << "Error - Found that inside and outside cells aren't adjacent. That's not logic.\n";
2582 else if( offset == positionOfFullKernel ) /// Full kernel in 3D. Never reached because case already considered before. It's a honeypot.
2584 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
2588 /// Part to substract from previous result.
2589 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
2591 auto preShiftedSpel = KPS::sSpel( *itm );
2592 preShiftedSpel.coordinates += shiftOuterSpel - diffSpel;
2594 if( myKSpace.sIsInside( preShiftedSpel ) )
2596 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2598 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2599 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2600 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2602 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2604 fillMoments( m, shiftedSpel, -1.0 );
2609 /// Part to add from previous result.
2610 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
2612 auto preShiftedSpel = KPS::sSpel( *itm );
2613 preShiftedSpel.coordinates += shiftOuterSpel;
2615 if( myKSpace.sIsInside( preShiftedSpel ) )
2617 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2619 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2620 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2621 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2623 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2625 fillMoments( m, shiftedSpel, 1.0 );
2631 /// Computation of covariance Matrix
2632 computeCovarianceMatrix( m, outerMatrix );
2633 memcpy( lastOuterMoments, m, nbMoments * sizeof( Quantity ));
2636 ASSERT (( lastInnerMoments[ 0 ] != 0 )); // Maybe a problem here. Can be normal ... but needs to check twice.
2638 lastInnerSpel = currentInnerSpel;
2639 lastOuterSpel = currentOuterSpel;