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 std::vector<Quantity> lastInnerMoments(nbMoments );
322 std::vector<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 std::vector<Quantity> lastInnerMoments( nbMoments );
375 std::vector<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 * sum(x*y) sum(y*y) sum(x*x)
459 A.setComponent( 0, 0, aMomentMatrix[ 5 ] );
460 A.setComponent( 0, 1, aMomentMatrix[ 3 ] );
461 A.setComponent( 1, 0, aMomentMatrix[ 3 ] );
462 A.setComponent( 1, 1, aMomentMatrix[ 4 ] );
464 B = 1.0 / aMomentMatrix[ 0 ];
466 C.setComponent( 0, 0, aMomentMatrix[ 2 ] * aMomentMatrix[ 2 ] );
467 C.setComponent( 0, 1, aMomentMatrix[ 2 ] * aMomentMatrix[ 1 ] );
468 C.setComponent( 1, 0, aMomentMatrix[ 1 ] * aMomentMatrix[ 2 ] );
469 C.setComponent( 1, 1, aMomentMatrix[ 1 ] * aMomentMatrix[ 1 ] );
471 aCovarianceMatrix = A - C * B;
475// For Visual Studio, to be defined as a static const, it has to be intialized into the header file
476template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
478DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::nbMoments = 6;
481template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
482typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Spel
483DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultInnerSpel = Spel();
485template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
486typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Spel
487DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultOuterSpel = Spel();
489template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
490typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Quantity
491DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultInnerMoments[ 6 ] = {Quantity(0)};
493template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
494typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Quantity
495DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultOuterMoments[ 6 ] = {Quantity(0)};
497template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
498typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Quantity
499DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultInnerSum = Quantity(0);
501template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
502typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Quantity
503DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultOuterSum = Quantity(0);
505template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
506template< typename SurfelIterator >
508DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::core_eval
509( const SurfelIterator & it,
513 Spel & lastInnerSpel,
514 Spel & lastOuterSpel,
515 Quantity & lastInnerSum,
516 Quantity & lastOuterSum ) const
518 boost::ignore_unused_variable_warning( it );
519 boost::ignore_unused_variable_warning( innerSum );
520 boost::ignore_unused_variable_warning( outerSum);
521 boost::ignore_unused_variable_warning(useLastResults);
522 boost::ignore_unused_variable_warning(lastInnerSum);
523 boost::ignore_unused_variable_warning(lastOuterSum);
524 boost::ignore_unused_variable_warning(lastInnerSpel);
525 boost::ignore_unused_variable_warning(lastOuterSpel);
526 trace.error() << "Unavailable yet." << std::endl;
531template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
532template< typename SurfelIterator >
534DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::core_evalCovarianceMatrix
535( const SurfelIterator & it,
536 CovarianceMatrix & innerMatrix,
537 CovarianceMatrix & outerMatrix,
539 Spel & lastInnerSpel,
540 Spel & lastOuterSpel,
541 Quantity * lastInnerMoments,
542 Quantity * lastOuterMoments ) const
544 boost::ignore_unused_variable_warning(it);
545 boost::ignore_unused_variable_warning(innerMatrix);
546 boost::ignore_unused_variable_warning(outerMatrix);
547 boost::ignore_unused_variable_warning(useLastResults);
548 boost::ignore_unused_variable_warning(lastOuterMoments);
549 boost::ignore_unused_variable_warning(lastInnerMoments);
550 boost::ignore_unused_variable_warning(lastInnerSpel);
551 boost::ignore_unused_variable_warning(lastOuterSpel);
552 trace.error() << "Unavailable yet." << std::endl;
558//////////////////////////////////////////////////////////////////////////////////////////////////////////////
559///////////////////////////////////////////////////// 2D /////////////////////////////////////////////////////
560//////////////////////////////////////////////////////////////////////////////////////////////////////////////
562template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
564DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >
565::DigitalSurfaceConvolver( ConstAlias< Functor > f,
566 ConstAlias< KernelFunctor > g,
567 ConstAlias< KSpace > space)
572 isInitFullMasks( false ),
573 isInitKernelAndMasks( false )
575 myEmbedder = Embedder( myKSpace );
578template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel>
580DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >
581::DigitalSurfaceConvolver( const DigitalSurfaceConvolver& other )
583 myFFunctor( other.myFFunctor ),
584 myGFunctor( other.myGFunctor ),
585 myKSpace( other.myKSpace ),
586 myEmbedder( other.myEmbedder ),
587 isInitFullMasks( other.isInitFullMasks ),
588 isInitKernelAndMasks( other.isInitKernelAndMasks ),
589 myMasks( other.myMasks ),
590 myKernel( other.myKernel ),
591 myKernelMask( other.myKernelMask ),
592 myKernelSpelOrigin( other.myKernelSpelOrigin )
596template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
599DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::init
600( const Point & pOrigin,
601 ConstAlias< PairIterators > fullKernel,
602 ConstAlias< std::vector< PairIterators > > masks )
604 myKernelSpelOrigin = myKSpace.sSpel( pOrigin );
605 myKernelMask = &fullKernel;
608 ASSERT ( myMasks->size () == 9 );
610 isInitFullMasks = true;
611 isInitKernelAndMasks = false;
614template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
617DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::init
618( const Point & pOrigin,
619 ConstAlias< DigitalKernel > fullKernel,
620 ConstAlias< std::vector< PairIterators > > masks )
622 myKernelSpelOrigin = myKSpace.sSpel( pOrigin );
623 myKernel = &fullKernel;
626 ASSERT ( myMasks->size () == 9 );
628 isInitFullMasks = false;
629 isInitKernelAndMasks = true;
632template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
633template< typename SurfelIterator >
635typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Quantity
636DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::eval
637( const SurfelIterator & it ) const
639 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
641 Quantity innerSum, outerSum;
643 core_eval( it, innerSum, outerSum, false );
646 return ( innerSum * lambda + outerSum * ( 1.0 - lambda ));
649template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
650template< typename SurfelIterator, typename EvalFunctor >
652typename EvalFunctor::Value
653DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::eval
654( const SurfelIterator & it,
655 EvalFunctor functor ) const
657 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
659 Quantity innerSum, outerSum;
660 Quantity resultQuantity;
662 core_eval( it, innerSum, outerSum, false );
665 resultQuantity = innerSum * lambda + outerSum * ( 1.0 - lambda );
666 return functor( resultQuantity );
669template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
670template< typename SurfelIterator, typename OutputIterator >
673DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::eval
674( const SurfelIterator & itbegin,
675 const SurfelIterator & itend,
676 OutputIterator & result ) const
678 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
682 Dimension recount = 0;
685 Quantity lastInnerSum;
686 Quantity lastOuterSum;
688 Quantity innerSum, outerSum;
690 Spel lastInnerSpel, lastOuterSpel;
692 /// Iterate on all cells
693 for( SurfelIterator it = itbegin; it != itend; ++it )
698 bool hasJumped = core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
699 recount = ( hasJumped ) ? recount + 1 : recount;
701 core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
706 core_eval( it, innerSum, outerSum, false, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
710 *result++ = ( innerSum * lambda + outerSum * ( 1.0 - lambda ));
716 std::cout << "#total cells = " << total << std::endl;
717 std::cout << "#recount = " << recount << std::endl;
721template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
722template< typename SurfelIterator, typename OutputIterator, typename EvalFunctor >
725DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::eval
726( const SurfelIterator & itbegin,
727 const SurfelIterator & itend,
728 OutputIterator & result,
729 EvalFunctor functor ) const
731 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
735 Dimension recount = 0;
738 Quantity lastInnerSum;
739 Quantity lastOuterSum;
741 Quantity innerSum, outerSum;
742 Quantity resultQuantity;
744 Spel lastInnerSpel, lastOuterSpel;
746 /// Iterate on all cells
747 for( SurfelIterator it = itbegin; it != itend; ++it )
752 bool hasJumped = core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
753 recount = ( hasJumped ) ? recount + 1 : recount;
755 core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
760 core_eval( it, innerSum, outerSum, false, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
764 resultQuantity = innerSum * lambda + outerSum * ( 1.0 - lambda );
765 *result++ = functor( resultQuantity );
771 std::cout << "#total cells = " << total << std::endl;
772 std::cout << "#recount = " << recount << std::endl;
780template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
781template< typename SurfelIterator >
783typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::CovarianceMatrix
784DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::evalCovarianceMatrix
785( const SurfelIterator & it ) const
787 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
789 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
791 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false );
794 return ( innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda ));
797template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
798template< typename SurfelIterator, typename EvalFunctor >
800typename EvalFunctor::Value
801DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::evalCovarianceMatrix
802( const SurfelIterator & it,
803 EvalFunctor functor ) const
805 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
807 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
808 CovarianceMatrix resultCovarianceMatrix;
810 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false );
813 resultCovarianceMatrix = innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda );
814 return functor( resultCovarianceMatrix );
817template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
818template< typename SurfelIterator, typename OutputIterator >
821DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::evalCovarianceMatrix
822( const SurfelIterator & itbegin,
823 const SurfelIterator & itend,
824 OutputIterator & result ) const
826 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
830 Dimension recount = 0;
833 std::vector<Quantity> lastInnerMoments( nbMoments );
834 std::vector<Quantity> lastOuterMoments( nbMoments );
836 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
838 Spel lastInnerSpel, lastOuterSpel;
840 /// Iterate on all cells
841 for( SurfelIterator it = itbegin; it != itend; ++it )
846 bool hasJumped = core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
847 recount = ( hasJumped ) ? recount + 1 : recount;
849 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
854 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
858 *result++ = ( innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda ));
864 std::cout << "#total cells = " << total << std::endl;
865 std::cout << "#recount = " << recount << std::endl;
869template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
870template< typename SurfelIterator, typename OutputIterator, typename EvalFunctor >
873DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::evalCovarianceMatrix
874( const SurfelIterator & itbegin,
875 const SurfelIterator & itend,
876 OutputIterator & result,
877 EvalFunctor functor ) const
879 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
883 Dimension recount = 0;
886 std::vector<Quantity> lastInnerMoments( nbMoments );
887 std::vector<Quantity> lastOuterMoments( nbMoments );
889 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
890 CovarianceMatrix resultCovarianceMatrix;
892 Spel lastInnerSpel, lastOuterSpel;
894 /// Iterate on all cells
895 for( SurfelIterator it = itbegin; it != itend; ++it )
900 bool hasJumped = core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
901 recount = ( hasJumped ) ? recount + 1 : recount;
903 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
908 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
912 resultCovarianceMatrix = innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda );
913 *result++ = functor( resultCovarianceMatrix );
919 std::cout << "#total cells = " << total << std::endl;
920 std::cout << "#recount = " << recount << std::endl;
927template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
930DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::isValid() const
935template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
937DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::fillMoments
938( Quantity * aMomentMatrix,
940 double direction ) const
942 RealPoint current = myEmbedder( aSpel );
943 double x = current[ 0 ];
944 double y = current[ 1 ];
946 aMomentMatrix[ 0 ] += direction * 1;
947 aMomentMatrix[ 1 ] += direction * y;
948 aMomentMatrix[ 2 ] += direction * x;
949 aMomentMatrix[ 3 ] += direction * x * y;
950 aMomentMatrix[ 4 ] += direction * y * y;
951 aMomentMatrix[ 5 ] += direction * x * x;
954template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
956DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::computeCovarianceMatrix
957( const Quantity * aMomentMatrix,
958 CovarianceMatrix & aCovarianceMatrix ) const
964 A.setComponent( 0, 0, aMomentMatrix[ 5 ] );
965 A.setComponent( 0, 1, aMomentMatrix[ 3 ] );
966 A.setComponent( 1, 0, aMomentMatrix[ 3 ] );
967 A.setComponent( 1, 1, aMomentMatrix[ 4 ] );
969 B = 1.0 / aMomentMatrix[ 0 ];
971 C.setComponent( 0, 0, aMomentMatrix[ 2 ] * aMomentMatrix[ 2 ] );
972 C.setComponent( 0, 1, aMomentMatrix[ 2 ] * aMomentMatrix[ 1 ] );
973 C.setComponent( 1, 0, aMomentMatrix[ 1 ] * aMomentMatrix[ 2 ] );
974 C.setComponent( 1, 1, aMomentMatrix[ 1 ] * aMomentMatrix[ 1 ] );
976 aCovarianceMatrix = A - C * B;
980// For Visual Studio, to be defined as a static const, it has to be intialized into the header file
981template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
983DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::nbMoments = 6;
986template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
987typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Spel
988DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::defaultInnerSpel = Spel();
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 >::defaultOuterSpel = Spel();
994template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
995typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Quantity
996DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::defaultInnerMoments[ 6 ] = {Quantity(0)};
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 >::defaultOuterMoments[ 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 >::defaultInnerSum = 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 >::defaultOuterSum = Quantity(0);
1010template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1011template< typename SurfelIterator >
1013DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::core_eval
1014( const SurfelIterator & it,
1015 Quantity & innerSum,
1016 Quantity & outerSum,
1017 bool useLastResults,
1018 Spel & lastInnerSpel,
1019 Spel & lastOuterSpel,
1020 Quantity & lastInnerSum,
1021 Quantity & lastOuterSum ) const
1023 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1025 using KPS = typename KSpace::PreCellularGridSpace;
1028 Dimension recount = false;
1031 typedef typename Functor::Quantity FQuantity;
1032 DGtal::Dimension nbMasks =static_cast<DGtal::Dimension>( (long)myMasks->size() - 1);
1033 DGtal::Dimension positionOfFullKernel = 4;
1035 Quantity m = NumberTraits< Quantity >::ZERO;
1037 Spel currentInnerSpel, currentOuterSpel;
1039 Point shiftInnerSpel, shiftOuterSpel;
1042 bool bComputed = false; /// <! if the cell has already been computed, continue to the next
1044 int x, y, x2, y2, x2y2;
1045 unsigned int offset;
1049 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
1050 currentInnerSpel = myKSpace.sDirectIncident( *it, kDim ); /// Spel on the border, but inside the shape
1051 shiftInnerSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( myKernelSpelOrigin );
1053 /// Check if we can use previous results
1054 if( useLastResults )
1058 if( currentInnerSpel == lastInnerSpel )
1065 else if( currentInnerSpel == lastOuterSpel )
1074 diffSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( lastInnerSpel );
1082 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 );
1084 if( x2y2 != 4 && x2y2 != 8 ) /// Previous and current cells aren't adjacent. Compute on the full kernel
1086 useLastResults = false;
1091 else if( offset == positionOfFullKernel ) /// Full kernel in 2D. Never reached because case already considered before. It's a honeypot.
1093 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
1097 useLastResults = true;
1104 if( !useLastResults ) /// Computation on full kernel, we have no previous results
1106 m = NumberTraits< Quantity >::ZERO;
1108 if( isInitFullMasks )
1110 for( KernelConstIterator itm = myKernelMask->first; itm != myKernelMask->second; ++itm )
1112 auto preShiftedSpel = KPS::sSpel( *itm );
1113 preShiftedSpel.coordinates += shiftInnerSpel;
1115 if( myKSpace.sIsInside( preShiftedSpel ) )
1117 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1119 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1120 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1122 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1129 else if( isInitKernelAndMasks )
1131 Domain domain = myKernel->getDomain();
1132 for( typename Domain::ConstIterator itm = domain.begin(), itend = domain.end(); itm != itend; ++itm )
1134 if( myKernel->operator()( *itm ))
1136 auto preShiftedSpel = KPS::sSpel( *itm );
1137 preShiftedSpel.coordinates += shiftInnerSpel;
1139 if( myKSpace.sIsInside( preShiftedSpel ) )
1141 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1143 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1144 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1146 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1156 trace.error() << "DigitalSurfaceConvolver: You need to init the convolver first." << std::endl;
1161 else /// Using lastInnerMoments
1165 /// Part to substract from previous result.
1166 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
1168 auto preShiftedSpel = KPS::sSpel( *itm );
1169 preShiftedSpel.coordinates += shiftInnerSpel - diffSpel;
1171 if( myKSpace.sIsInside( preShiftedSpel ) )
1173 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1175 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1176 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1178 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1185 /// Part to add from previous result.
1186 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
1188 auto preShiftedSpel = KPS::sSpel( *itm );
1189 preShiftedSpel.coordinates += shiftInnerSpel;
1191 if( myKSpace.sIsInside( preShiftedSpel ) )
1193 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1195 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1196 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1198 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1206 /// Computation of covariance Matrix
1214 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
1215 currentOuterSpel = myKSpace.sIndirectIncident( *it, kDim );
1216 shiftOuterSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( myKernelSpelOrigin );
1218 ASSERT( currentInnerSpel != currentOuterSpel );
1220 diffSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( currentInnerSpel );
1228 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 );
1230 if( x2y2 != 4 && x2y2 != 8 ) /// Inside and outside cells aren't adjacent, but should be. It's a honeypot.
1232 trace.error() << "Error - Found that inside and outside cells aren't adjacent. That's not logic.\n";
1234 else if( offset == positionOfFullKernel ) /// Full kernel in 2D. Never reached because case already considered before. It's a honeypot.
1236 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
1240 /// Part to substract from previous result.
1241 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
1243 auto preShiftedSpel = KPS::sSpel( *itm );
1244 preShiftedSpel.coordinates += shiftOuterSpel - diffSpel;
1246 if( myKSpace.sIsInside( preShiftedSpel ) )
1248 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1250 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1251 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1253 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1260 /// Part to add from previous result.
1261 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
1263 auto preShiftedSpel = KPS::sSpel( *itm );
1264 preShiftedSpel.coordinates += shiftOuterSpel;
1266 if( myKSpace.sIsInside( preShiftedSpel ) )
1268 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1270 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1271 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1273 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1281 /// Computation of covariance Matrix
1286 ASSERT (( lastInnerSum != 0 )); // Maybe a problem here. Can be normal ... but needs to check twice.
1288 lastInnerSpel = currentInnerSpel;
1289 lastOuterSpel = currentOuterSpel;
1299template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1300template< typename SurfelIterator >
1302DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::core_evalCovarianceMatrix
1303( const SurfelIterator & it,
1304 CovarianceMatrix & innerMatrix,
1305 CovarianceMatrix & outerMatrix,
1306 bool useLastResults,
1307 Spel & lastInnerSpel,
1308 Spel & lastOuterSpel,
1309 Quantity * lastInnerMoments,
1310 Quantity * lastOuterMoments ) const
1312 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1314 using KPS = typename KSpace::PreCellularGridSpace;
1317 Dimension recount = false;
1320 typedef typename Functor::Quantity FQuantity;
1321 DGtal::Dimension nbMasks = myMasks->size() - 1;
1322 DGtal::Dimension positionOfFullKernel = 4;
1324 Quantity m[ nbMoments ]; /// <! [ m00, m01, m10, m11, m02, m20 ]
1325 std::fill( m, m + nbMoments, NumberTraits< Quantity >::ZERO ); /// <! clear array
1327 Spel currentInnerSpel, currentOuterSpel;
1329 Point shiftInnerSpel, shiftOuterSpel;
1332 bool bComputed = false; /// <! if the cell has already been computed, continue to the next
1334 int x, y, x2, y2, x2y2;
1335 unsigned int offset;
1339 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
1340 currentInnerSpel = myKSpace.sDirectIncident( *it, kDim ); /// Spel on the border, but inside the shape
1341 shiftInnerSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( myKernelSpelOrigin );
1343 /// Check if we can use previous results
1344 if( useLastResults )
1348 if( currentInnerSpel == lastInnerSpel )
1350 memcpy( m, lastInnerMoments, nbMoments * sizeof( Quantity ));
1351 computeCovarianceMatrix( m, innerMatrix );
1355 else if( currentInnerSpel == lastOuterSpel )
1357 memcpy( m, lastOuterMoments, nbMoments * sizeof( Quantity ));
1358 computeCovarianceMatrix( m, outerMatrix );
1364 diffSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( lastInnerSpel );
1372 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 );
1374 if( x2y2 != 4 && x2y2 != 8 ) /// Previous and current cells aren't adjacent. Compute on the full kernel
1376 useLastResults = false;
1381 else if( offset == positionOfFullKernel ) /// Full kernel in 2D. Never reached because case already considered before. It's a honeypot.
1383 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
1387 useLastResults = true;
1394 if( !useLastResults ) /// Computation on full kernel, we have no previous results
1396 std::fill( m, m + nbMoments, NumberTraits< Quantity >::ZERO ); /// <! clear array
1398 if( isInitFullMasks )
1400 for( KernelConstIterator itm = myKernelMask->first; itm != myKernelMask->second; ++itm )
1402 auto preShiftedSpel = KPS::sSpel( *itm );
1403 preShiftedSpel.coordinates += shiftInnerSpel;
1405 if( myKSpace.sIsInside( preShiftedSpel ) )
1407 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1409 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1410 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1412 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1414 fillMoments( m, shiftedSpel, 1.0 );
1419 else if( isInitKernelAndMasks )
1421 Domain domain = myKernel->getDomain();
1422 for( typename Domain::ConstIterator itm = domain.begin(), itend = domain.end(); itm != itend; ++itm )
1424 if( myKernel->operator()( *itm ))
1426 auto preShiftedSpel = KPS::sSpel( *itm );
1427 preShiftedSpel.coordinates += shiftInnerSpel;
1429 if( myKSpace.sIsInside( preShiftedSpel ) )
1431 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1433 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1434 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1436 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1438 fillMoments( m, shiftedSpel, 1.0 );
1446 trace.error() << "DigitalSurfaceConvolver: You need to init the convolver first." << std::endl;
1450 else /// Using lastInnerMoments
1452 memcpy( m, lastInnerMoments, nbMoments * sizeof( Quantity ));
1454 /// Part to substract from previous result.
1455 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
1457 auto preShiftedSpel = KPS::sSpel( *itm );
1458 preShiftedSpel.coordinates += shiftInnerSpel - diffSpel;
1460 if( myKSpace.sIsInside( preShiftedSpel ) )
1462 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1464 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1465 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1467 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1469 fillMoments( m, shiftedSpel, -1.0 );
1474 /// Part to add from previous result.
1475 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
1477 auto preShiftedSpel = KPS::sSpel( *itm );
1478 preShiftedSpel.coordinates += shiftInnerSpel;
1480 if( myKSpace.sIsInside( preShiftedSpel ) )
1482 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1484 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1485 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1487 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1489 fillMoments( m, shiftedSpel, 1.0 );
1495 /// Computation of covariance Matrix
1496 computeCovarianceMatrix( m, innerMatrix );
1497 memcpy( lastInnerMoments, m, nbMoments * sizeof( Quantity ));
1503 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
1504 currentOuterSpel = myKSpace.sIndirectIncident( *it, kDim );
1505 shiftOuterSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( myKernelSpelOrigin );
1507 ASSERT( currentInnerSpel != currentOuterSpel );
1509 diffSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( currentInnerSpel );
1517 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 );
1519 if( x2y2 != 4 && x2y2 != 8 ) /// Inside and outside cells aren't adjacent, but should be. It's a honeypot.
1521 trace.error() << "Error - Found that inside and outside cells aren't adjacent. That's not logic.\n";
1523 else if( offset == positionOfFullKernel ) /// Full kernel in 2D. Never reached because case already considered before. It's a honeypot.
1525 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
1529 /// Part to substract from previous result.
1530 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
1532 auto preShiftedSpel = KPS::sSpel( *itm );
1533 preShiftedSpel.coordinates += shiftOuterSpel - diffSpel;
1534 if( myKSpace.sIsInside( preShiftedSpel ) )
1536 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1538 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1539 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1541 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1543 fillMoments( m, shiftedSpel, -1.0 );
1548 /// Part to add from previous result.
1549 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
1551 auto preShiftedSpel = KPS::sSpel( *itm );
1552 preShiftedSpel.coordinates += shiftOuterSpel;
1554 if( myKSpace.sIsInside( preShiftedSpel ) )
1556 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1558 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1559 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1561 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1563 fillMoments( m, shiftedSpel, 1.0 );
1569 /// Computation of covariance Matrix
1570 computeCovarianceMatrix( m, outerMatrix );
1571 memcpy( lastOuterMoments, m, nbMoments * sizeof( Quantity ));
1574 ASSERT (( lastInnerMoments[ 0 ] != 0 )); // Maybe a problem here. Can be normal ... but needs to check twice.
1576 lastInnerSpel = currentInnerSpel;
1577 lastOuterSpel = currentOuterSpel;
1589//////////////////////////////////////////////////////////////////////////////////////////////////////////////
1590///////////////////////////////////////////////////// 3D /////////////////////////////////////////////////////
1591//////////////////////////////////////////////////////////////////////////////////////////////////////////////
1593template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1595DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >
1596::DigitalSurfaceConvolver( ConstAlias< Functor > f,
1597 ConstAlias< KernelFunctor > g,
1598 ConstAlias< KSpace > space)
1603 isInitFullMasks( false ),
1604 isInitKernelAndMasks( false )
1606 myEmbedder = Embedder( myKSpace );
1609template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel>
1611DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >
1612::DigitalSurfaceConvolver( const DigitalSurfaceConvolver& other )
1614 myFFunctor( other.myFFunctor ),
1615 myGFunctor( other.myGFunctor ),
1616 myKSpace( other.myKSpace ),
1617 myEmbedder( other.myEmbedder ),
1618 isInitFullMasks( other.isInitFullMasks ),
1619 isInitKernelAndMasks( other.isInitKernelAndMasks ),
1620 myMasks( other.myMasks ),
1621 myKernel( other.myKernel ),
1622 myKernelMask( other.myKernelMask ),
1623 myKernelSpelOrigin( other.myKernelSpelOrigin )
1627template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1630DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::init
1631( const Point & pOrigin,
1632 ConstAlias< PairIterators > fullKernel,
1633 ConstAlias< std::vector< PairIterators > > masks )
1635 myKernelSpelOrigin = myKSpace.sSpel( pOrigin );
1636 myKernelMask = &fullKernel;
1639 ASSERT ( myMasks->size () == 27 );
1641 isInitFullMasks = true;
1642 isInitKernelAndMasks = false;
1645template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1648DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::init
1649( const Point & pOrigin,
1650 ConstAlias< DigitalKernel > fullKernel,
1651 ConstAlias< std::vector< PairIterators > > masks )
1653 myKernelSpelOrigin = myKSpace.sSpel( pOrigin );
1654 myKernel = &fullKernel;
1657 ASSERT ( myMasks->size () == 27 );
1659 isInitFullMasks = false;
1660 isInitKernelAndMasks = true;
1666template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1667template< typename SurfelIterator >
1669typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Quantity
1670DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::eval
1671( const SurfelIterator & it ) const
1673 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1675 Quantity innerSum, outerSum;
1677 core_eval( it, innerSum, outerSum, false );
1679 double lambda = 0.5;
1680 return ( innerSum * lambda + outerSum * ( 1.0 - lambda ));
1683template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1684template< typename SurfelIterator, typename EvalFunctor >
1686typename EvalFunctor::Value
1687DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::eval
1688( const SurfelIterator & it,
1689 EvalFunctor functor ) const
1691 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1693 Quantity innerSum, outerSum;
1694 Quantity resultQuantity;
1696 core_eval( it, innerSum, outerSum, false );
1698 double lambda = 0.5;
1699 resultQuantity = innerSum * lambda + outerSum * ( 1.0 - lambda );
1700 return functor( resultQuantity );
1703template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1704template< typename SurfelIterator, typename OutputIterator >
1707DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::eval
1708( const SurfelIterator & itbegin,
1709 const SurfelIterator & itend,
1710 OutputIterator & result ) const
1712 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1714 Dimension total = 0;
1716 Dimension recount = 0;
1719 Quantity lastInnerSum;
1720 Quantity lastOuterSum;
1722 Quantity innerSum, outerSum;
1724 Spel lastInnerSpel, lastOuterSpel;
1726 /// Iterate on all cells
1727 for( SurfelIterator it = itbegin; it != itend; ++it )
1732 bool hasJumped = core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
1733 recount = ( hasJumped ) ? recount + 1 : recount;
1735 core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
1740 core_eval( it, innerSum, outerSum, false, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
1743 double lambda = 0.5;
1744 *result++ = ( innerSum * lambda + outerSum * ( 1.0 - lambda ));
1750 std::cout << "#total cells = " << total << std::endl;
1751 std::cout << "#recount = " << recount << std::endl;
1755template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1756template< typename SurfelIterator, typename OutputIterator, typename EvalFunctor >
1759DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::eval
1760( const SurfelIterator & itbegin,
1761 const SurfelIterator & itend,
1762 OutputIterator & result,
1763 EvalFunctor functor ) const
1765 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1767 Dimension total = 0;
1769 Dimension recount = 0;
1772 Quantity lastInnerSum;
1773 Quantity lastOuterSum;
1775 Quantity innerSum, outerSum;
1776 Quantity resultQuantity;
1778 Spel lastInnerSpel, lastOuterSpel;
1780 /// Iterate on all cells
1781 for( SurfelIterator it = itbegin; it != itend; ++it )
1786 bool hasJumped = core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
1787 recount = ( hasJumped ) ? recount + 1 : recount;
1789 core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
1794 core_eval( it, innerSum, outerSum, false, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
1797 double lambda = 0.5;
1798 resultQuantity = innerSum * lambda + outerSum * ( 1.0 - lambda );
1799 *result++ = functor( resultQuantity );
1805 std::cout << "#total cells = " << total << std::endl;
1806 std::cout << "#recount = " << recount << std::endl;
1812template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1813template< typename SurfelIterator >
1815typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::CovarianceMatrix
1816DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::evalCovarianceMatrix
1817( const SurfelIterator & it ) const
1819 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1821 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
1823 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false );
1825 double lambda = 0.5;
1826 return ( innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda ));
1829template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1830template< typename SurfelIterator, typename EvalFunctor >
1832typename EvalFunctor::Value
1833DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::evalCovarianceMatrix
1834( const SurfelIterator & it,
1835 EvalFunctor functor ) const
1837 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1839 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
1840 CovarianceMatrix resultCovarianceMatrix;
1842 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false );
1844 double lambda = 0.5;
1845 resultCovarianceMatrix = innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda );
1846 return functor( resultCovarianceMatrix );
1849template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1850template< typename SurfelIterator, typename OutputIterator >
1853DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::evalCovarianceMatrix
1854( const SurfelIterator & itbegin,
1855 const SurfelIterator & itend,
1856 OutputIterator & result ) const
1858 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1860 Dimension total = 0;
1862 Dimension recount = 0;
1865 std::vector<Quantity> lastInnerMoments( nbMoments );
1866 std::vector<Quantity> lastOuterMoments( nbMoments );
1868 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
1870 Spel lastInnerSpel, lastOuterSpel;
1872 /// Iterate on all cells
1873 for( SurfelIterator it = itbegin; it != itend; ++it )
1878 bool hasJumped = core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
1879 recount = ( hasJumped ) ? recount + 1 : recount;
1881 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
1886 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
1889 double lambda = 0.5;
1890 *result++ = ( innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda ));
1896 std::cout << "#total cells = " << total << std::endl;
1897 std::cout << "#recount = " << recount << std::endl;
1901template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1902template< typename SurfelIterator, typename OutputIterator, typename EvalFunctor >
1905DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::evalCovarianceMatrix
1906( const SurfelIterator & itbegin,
1907 const SurfelIterator & itend,
1908 OutputIterator & result,
1909 EvalFunctor functor ) const
1911 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1913 Dimension total = 0;
1915 Dimension recount = 0;
1918 Quantity *lastInnerMoments = new Quantity[ nbMoments ];
1919 Quantity *lastOuterMoments = new Quantity[ nbMoments ];
1921 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
1922 CovarianceMatrix resultCovarianceMatrix;
1924 Spel lastInnerSpel, lastOuterSpel;
1926 /// Iterate on all cells
1927 for( SurfelIterator it = itbegin; it != itend; ++it )
1932 bool hasJumped = core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
1933 recount = ( hasJumped ) ? recount + 1 : recount;
1935 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
1940 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
1943 double lambda = 0.5;
1944 resultCovarianceMatrix = innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda );
1945 *result++ = functor( resultCovarianceMatrix );
1951 std::cout << "#total cells = " << total << std::endl;
1952 std::cout << "#recount = " << recount << std::endl;
1958template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1961DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::isValid() const
1966template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1968DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::fillMoments
1969( Quantity * aMomentMatrix,
1971 double direction ) const
1973 RealPoint current = myEmbedder( aSpel );
1974 double x = current[ 0 ];
1975 double y = current[ 1 ];
1976 double z = current[ 2 ];
1978 aMomentMatrix[ 0 ] += direction * 1;
1979 aMomentMatrix[ 1 ] += direction * z;
1980 aMomentMatrix[ 2 ] += direction * y;
1981 aMomentMatrix[ 3 ] += direction * x;
1982 aMomentMatrix[ 4 ] += direction * y * z;
1983 aMomentMatrix[ 5 ] += direction * x * z;
1984 aMomentMatrix[ 6 ] += direction * x * y;
1985 aMomentMatrix[ 7 ] += direction * z * z;
1986 aMomentMatrix[ 8 ] += direction * y * y;
1987 aMomentMatrix[ 9 ] += direction * x * x;
1992template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1994DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::computeCovarianceMatrix
1995( const Quantity * aMomentMatrix,
1996 CovarianceMatrix & aCovarianceMatrix ) const
2002 A.setComponent( 0, 0, aMomentMatrix[ 9 ] );
2003 A.setComponent( 0, 1, aMomentMatrix[ 6 ] );
2004 A.setComponent( 0, 2, aMomentMatrix[ 5 ] );
2005 A.setComponent( 1, 0, aMomentMatrix[ 6 ] );
2006 A.setComponent( 1, 1, aMomentMatrix[ 8 ] );
2007 A.setComponent( 1, 2, aMomentMatrix[ 4 ] );
2008 A.setComponent( 2, 0, aMomentMatrix[ 5 ] );
2009 A.setComponent( 2, 1, aMomentMatrix[ 4 ] );
2010 A.setComponent( 2, 2, aMomentMatrix[ 7 ] );
2012 B = 1.0 / aMomentMatrix[ 0 ];
2014 C.setComponent( 0, 0, aMomentMatrix[ 3 ] * aMomentMatrix[ 3 ] );
2015 C.setComponent( 0, 1, aMomentMatrix[ 3 ] * aMomentMatrix[ 2 ] );
2016 C.setComponent( 0, 2, aMomentMatrix[ 3 ] * aMomentMatrix[ 1 ] );
2017 C.setComponent( 1, 0, aMomentMatrix[ 2 ] * aMomentMatrix[ 3 ] );
2018 C.setComponent( 1, 1, aMomentMatrix[ 2 ] * aMomentMatrix[ 2 ] );
2019 C.setComponent( 1, 2, aMomentMatrix[ 2 ] * aMomentMatrix[ 1 ] );
2020 C.setComponent( 2, 0, aMomentMatrix[ 1 ] * aMomentMatrix[ 3 ] );
2021 C.setComponent( 2, 1, aMomentMatrix[ 1 ] * aMomentMatrix[ 2 ] );
2022 C.setComponent( 2, 2, aMomentMatrix[ 1 ] * aMomentMatrix[ 1 ] );
2024 aCovarianceMatrix = A - C * B;
2028// For Visual Studio, to be defined as a static const, it has to be intialized into the header file
2029template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2031DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::nbMoments = 10;
2034template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2035typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Spel
2036DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::defaultInnerSpel = Spel();
2038template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2039typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Spel
2040DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::defaultOuterSpel = Spel();
2042template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2043typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Quantity
2044DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::defaultInnerMoments[ 10 ] = {Quantity(0)};
2046template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2047typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Quantity
2048DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::defaultOuterMoments[ 10 ] = {Quantity(0)};
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 >::defaultInnerSum = 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 >::defaultOuterSum = Quantity(0);
2058template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2059template< typename SurfelIterator >
2061DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::core_eval
2062( const SurfelIterator & it,
2063 Quantity & innerSum,
2064 Quantity & outerSum,
2065 bool useLastResults,
2066 Spel & lastInnerSpel,
2067 Spel & lastOuterSpel,
2068 Quantity & lastInnerSum,
2069 Quantity & lastOuterSum ) const
2071 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
2073 using KPS = typename KSpace::PreCellularGridSpace;
2076 Dimension recount = false;
2079 typedef typename Functor::Quantity FQuantity;
2080 DGtal::Dimension nbMasks = static_cast<DGtal::Dimension>(myMasks->size()) - 1;
2081 DGtal::Dimension positionOfFullKernel = 13;
2083 Quantity m = NumberTraits< Quantity >::ZERO;
2085 Spel currentInnerSpel, currentOuterSpel;
2087 Point shiftInnerSpel, shiftOuterSpel;
2090 bool bComputed = false; /// <! if the cell has already been computed, continue to the next
2092 int x, y, z, x2, y2, z2, x2y2z2;
2093 unsigned int offset;
2097 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
2098 currentInnerSpel = myKSpace.sDirectIncident( *it, kDim ); /// Spel on the border, but inside the shape
2099 shiftInnerSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( myKernelSpelOrigin );
2101 /// Check if we can use previous results
2102 if( useLastResults )
2106 if( currentInnerSpel == lastInnerSpel )
2113 else if( currentInnerSpel == lastOuterSpel )
2122 diffSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( lastInnerSpel );
2130 x2y2z2 = x2 + y2 + z2;
2132 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 ) + ((( z / 2 ) + 1 ) * 9 );
2134 if( x2y2z2 != 4 && x2y2z2 != 8 && !( x2 == 4 && y2 == 4 && z2 == 4 )) /// Previous and current cells aren't adjacent. Compute on the full kernel
2136 useLastResults = false;
2141 else if( offset == positionOfFullKernel ) /// Full kernel in 3D. Never reached because case already considered before. It's a honeypot.
2143 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
2147 useLastResults = true;
2154 if( !useLastResults ) /// Computation on full kernel, we have no previous results
2156 m = NumberTraits< Quantity >::ZERO;
2158 if( isInitFullMasks )
2160 for( KernelConstIterator itm = myKernelMask->first; itm != myKernelMask->second; ++itm )
2162 auto preShiftedSpel = KPS::sSpel( *itm );
2163 preShiftedSpel.coordinates += shiftInnerSpel;
2165 if( myKSpace.sIsInside( preShiftedSpel ) )
2167 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2169 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2170 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2171 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2173 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2180 else if( isInitKernelAndMasks )
2182 Domain domain = myKernel->getDomain();
2183 for( typename Domain::ConstIterator itm = domain.begin(), itend = domain.end(); itm != itend; ++itm )
2185 if( myKernel->operator()( *itm ))
2187 auto preShiftedSpel = KPS::sSpel( *itm );
2188 preShiftedSpel.coordinates += shiftInnerSpel;
2190 if( myKSpace.sIsInside( preShiftedSpel ) )
2192 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2194 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2195 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2196 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2198 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2208 trace.error() << "DigitalSurfaceConvolver: You need to init the convolver first." << std::endl;
2212 else /// Using lastInnerMoments
2216 /// Part to substract from previous result.
2217 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
2219 auto preShiftedSpel = KPS::sSpel( *itm );
2220 preShiftedSpel.coordinates += shiftInnerSpel - diffSpel;
2222 if( myKSpace.sIsInside( preShiftedSpel ) )
2224 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2226 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2227 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2228 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2230 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2237 /// Part to add from previous result.
2238 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
2240 auto preShiftedSpel = KPS::sSpel( *itm );
2241 preShiftedSpel.coordinates += shiftInnerSpel;
2243 if( myKSpace.sIsInside( preShiftedSpel ) )
2245 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2247 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2248 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2249 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2251 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2259 /// Computation of covariance Matrix
2267 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
2268 currentOuterSpel = myKSpace.sIndirectIncident( *it, kDim );
2269 shiftOuterSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( myKernelSpelOrigin );
2271 ASSERT( currentInnerSpel != currentOuterSpel );
2273 diffSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( currentInnerSpel );
2281 x2y2z2 = x2 + y2 + z2;
2283 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 ) + ((( z / 2 ) + 1) * 9 );
2285 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.
2287 trace.error() << "Error - Found that inside and outside cells aren't adjacent. That's not logic.\n";
2289 else if( offset == positionOfFullKernel ) /// Full kernel in 3D. Never reached because case already considered before. It's a honeypot.
2291 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
2295 /// Part to substract from previous result.
2296 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
2298 auto preShiftedSpel = KPS::sSpel( *itm );
2299 preShiftedSpel.coordinates += shiftOuterSpel - diffSpel;
2301 if( myKSpace.sIsInside( preShiftedSpel ) )
2303 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates
2306 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2307 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2308 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2310 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2317 /// Part to add from previous result.
2318 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
2320 auto preShiftedSpel = KPS::sSpel( *itm );
2321 preShiftedSpel.coordinates += shiftOuterSpel;
2323 if( myKSpace.sIsInside( preShiftedSpel ) )
2325 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2327 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2328 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2329 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2331 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2339 /// Computation of covariance Matrix
2344 ASSERT (( lastInnerSum != 0 )); // Maybe a problem here. Can be normal ... but needs to check twice.
2346 lastInnerSpel = currentInnerSpel;
2347 lastOuterSpel = currentOuterSpel;
2357template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2358template< typename SurfelIterator >
2360DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::core_evalCovarianceMatrix
2361( const SurfelIterator & it,
2362 CovarianceMatrix & innerMatrix,
2363 CovarianceMatrix & outerMatrix,
2364 bool useLastResults,
2365 Spel & lastInnerSpel,
2366 Spel & lastOuterSpel,
2367 Quantity * lastInnerMoments,
2368 Quantity * lastOuterMoments ) const
2370 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
2372 using KPS = typename KSpace::PreCellularGridSpace;
2375 Dimension recount = false;
2378 typedef typename Functor::Quantity FQuantity;
2379 DGtal::Dimension nbMasks = static_cast<Dimension>(myMasks->size()) - 1;
2380 DGtal::Dimension positionOfFullKernel = 13;
2382 Quantity m[ nbMoments ]; /// <! [ m000, m001, m010, m100, m011, m101, m110, m002, m020, m200 ]
2383 std::fill( m, m + nbMoments, NumberTraits< Quantity >::ZERO ); /// <! clear array
2385 Spel currentInnerSpel, currentOuterSpel;
2387 Point shiftInnerSpel, shiftOuterSpel;
2390 bool bComputed = false; /// <! if the cell has already been computed, continue to the next
2392 int x, y, z, x2, y2, z2, x2y2z2;
2393 unsigned int offset;
2397 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
2398 currentInnerSpel = myKSpace.sDirectIncident( *it, kDim ); /// Spel on the border, but inside the shape
2399 shiftInnerSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( myKernelSpelOrigin );
2401 /// Check if we can use previous results
2402 if( useLastResults )
2406 if( currentInnerSpel == lastInnerSpel )
2408 memcpy( m, lastInnerMoments, nbMoments * sizeof( Quantity ));
2409 computeCovarianceMatrix( m, innerMatrix );
2413 else if( currentInnerSpel == lastOuterSpel )
2415 memcpy( m, lastOuterMoments, nbMoments * sizeof( Quantity ));
2416 computeCovarianceMatrix( m, outerMatrix );
2422 diffSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( lastInnerSpel );
2430 x2y2z2 = x2 + y2 + z2;
2432 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 ) + ((( z / 2 ) + 1 ) * 9 );
2434 if( x2y2z2 != 4 && x2y2z2 != 8 && !( x2 == 4 && y2 == 4 && z2 == 4 )) /// Previous and current cells aren't adjacent. Compute on the full kernel
2436 useLastResults = false;
2441 else if( offset == positionOfFullKernel ) /// Full kernel in 3D. Never reached because case already considered before. It's a honeypot.
2443 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
2447 useLastResults = true;
2454 if( !useLastResults ) /// Computation on full kernel, we have no previous results
2456 std::fill( m, m + nbMoments, NumberTraits< Quantity >::ZERO ); /// <! clear array
2458 if( isInitFullMasks )
2460 for( KernelConstIterator itm = myKernelMask->first; itm != myKernelMask->second; ++itm )
2462 auto preShiftedSpel = KPS::sSpel( *itm );
2463 preShiftedSpel.coordinates += shiftInnerSpel;
2465 if( myKSpace.sIsInside( preShiftedSpel ) )
2467 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2469 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2470 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2471 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2473 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2475 fillMoments( m, shiftedSpel, 1.0 );
2480 else if( isInitKernelAndMasks )
2482 Domain domain = myKernel->getDomain();
2483 for( typename Domain::ConstIterator itm = domain.begin(), itend = domain.end(); itm != itend; ++itm )
2485 if( myKernel->operator()( *itm ))
2487 auto preShiftedSpel = KPS::sSpel( *itm );
2488 preShiftedSpel.coordinates += shiftInnerSpel;
2490 if( myKSpace.sIsInside( preShiftedSpel ) )
2492 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2494 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2495 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2496 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2498 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2500 fillMoments( m, shiftedSpel, 1.0 );
2508 trace.error() << "DigitalSurfaceConvolver: You need to init the convolver first." << std::endl;
2512 else /// Using lastInnerMoments
2514 memcpy( m, lastInnerMoments, nbMoments * sizeof( Quantity ));
2516 /// Part to substract from previous result.
2517 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
2519 auto preShiftedSpel = KPS::sSpel( *itm );
2520 preShiftedSpel.coordinates += shiftInnerSpel - diffSpel;
2522 if( myKSpace.sIsInside( preShiftedSpel ) )
2524 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2526 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2527 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2528 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2530 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2532 fillMoments( m, shiftedSpel, -1.0 );
2537 /// Part to add from previous result.
2538 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
2540 auto preShiftedSpel = KPS::sSpel( *itm );
2541 preShiftedSpel.coordinates += shiftInnerSpel;
2543 if( myKSpace.sIsInside( preShiftedSpel ) )
2545 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2547 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2548 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2549 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2551 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2553 fillMoments( m, shiftedSpel, 1.0 );
2559 /// Computation of covariance Matrix
2560 computeCovarianceMatrix( m, innerMatrix );
2561 memcpy( lastInnerMoments, m, nbMoments * sizeof( Quantity ));
2567 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
2568 currentOuterSpel = myKSpace.sIndirectIncident( *it, kDim );
2569 shiftOuterSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( myKernelSpelOrigin );
2571 ASSERT( currentInnerSpel != currentOuterSpel );
2573 diffSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( currentInnerSpel );
2581 x2y2z2 = x2 + y2 + z2;
2583 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 ) + ((( z / 2 ) + 1) * 9 );
2585 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.
2587 trace.error() << "Error - Found that inside and outside cells aren't adjacent. That's not logic.\n";
2589 else if( offset == positionOfFullKernel ) /// Full kernel in 3D. Never reached because case already considered before. It's a honeypot.
2591 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
2595 /// Part to substract from previous result.
2596 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
2598 auto preShiftedSpel = KPS::sSpel( *itm );
2599 preShiftedSpel.coordinates += shiftOuterSpel - diffSpel;
2601 if( myKSpace.sIsInside( preShiftedSpel ) )
2603 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2605 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2606 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2607 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2609 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2611 fillMoments( m, shiftedSpel, -1.0 );
2616 /// Part to add from previous result.
2617 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
2619 auto preShiftedSpel = KPS::sSpel( *itm );
2620 preShiftedSpel.coordinates += shiftOuterSpel;
2622 if( myKSpace.sIsInside( preShiftedSpel ) )
2624 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2626 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2627 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2628 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2630 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2632 fillMoments( m, shiftedSpel, 1.0 );
2638 /// Computation of covariance Matrix
2639 computeCovarianceMatrix( m, outerMatrix );
2640 memcpy( lastOuterMoments, m, nbMoments * sizeof( Quantity ));
2643 ASSERT (( lastInnerMoments[ 0 ] != 0 )); // Maybe a problem here. Can be normal ... but needs to check twice.
2645 lastInnerSpel = currentInnerSpel;
2646 lastOuterSpel = currentOuterSpel;