2 * This program is free software: you can redistribute it and/or modify
3 * it under the terms of the GNU Lesser General Public License as
4 * published by the Free Software Foundation, either version 3 of the
5 * License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 * @file DigitalSurfaceConvolver.ih
19 * @author Jeremy Levallois (\c jeremy.levallois@liris.cnrs.fr )
20 * Laboratoire d'InfoRmatique en Image et Systèmes d'information - LIRIS (CNRS, UMR 5205), INSA-Lyon, France
21 * LAboratoire de MAthématiques - LAMA (CNRS, UMR 5127), Université de Savoie, France
25 * Implementation of inline methods defined in DigitalSurfaceConvolver.h
27 * This file is part of the DGtal library.
30///////////////////////////////////////////////////////////////////////////////
31// IMPLEMENTATION of inline methods.
32///////////////////////////////////////////////////////////////////////////////
34//////////////////////////////////////////////////////////////////////////////
36//////////////////////////////////////////////////////////////////////////////
39///////////////////////////////////////////////////////////////////////////////
40// IMPLEMENTATION of inline methods.
41///////////////////////////////////////////////////////////////////////////////
42#include "DGtal/geometry/surfaces/DigitalSurfaceConvolver.h"
43#include "DGtal/kernel/NumberTraits.h"
44///////////////////////////////////////////////////////////////////////////////
45// ----------------------- Standard services ------------------------------
48//////////////////////////////////////////////////////////////////////////////////////////////////////////////
49///////////////////////////////////////////////////// nD /////////////////////////////////////////////////////
50//////////////////////////////////////////////////////////////////////////////////////////////////////////////
52template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
54DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >
55::DigitalSurfaceConvolver( ConstAlias< Functor > f,
56 ConstAlias< KernelFunctor > g,
57 ConstAlias< KSpace > space)
61 isInitFullMasks( false ),
62 isInitKernelAndMasks( false )
64 myEmbedder = Embedder( myKSpace );
67template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
69DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >
70::DigitalSurfaceConvolver( const DigitalSurfaceConvolver& other )
71 : myFFunctor( other.myFFunctor ),
72 myGFunctor( other.myGFunctor ),
73 myKSpace( other.myKSpace ),
74 myEmbedder( other.myEmbedder ),
75 isInitFullMasks( other.isInitFullMasks ),
76 isInitKernelAndMasks( other.isInitKernelAndMasks ),
77 myMasks( other.myMasks ),
78 myKernel( other.myKernel ),
79 myKernelMask( other.myKernelMask ),
80 myKernelKCoordsOrigin( other.myKernelKCoordsOrigin )
84template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
87DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::init
88( const Point & pOrigin,
89 ConstAlias< PairIterators > fullKernel,
90 ConstAlias< std::vector< PairIterators > > masks )
92 KhalimskySpaceND<dimension, typename KSpace::Integer> preK;
93 myKernelKCoordsOrigin = preK.sKCoords(preK.sSpel( pOrigin ));
94 myKernelMask = &fullKernel;
97 // ASSERT ( myMasks->size () == 9 );
99 isInitFullMasks = true;
100 isInitKernelAndMasks = false;
103template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
106DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::init
107( const Point & pOrigin,
108 ConstAlias< DigitalKernel > fullKernel,
109 ConstAlias< std::vector< PairIterators > > masks )
111 KhalimskySpaceND<dimension, typename KSpace::Integer> preK;
112 myKernelKCoordsOrigin = preK.sKCoords(preK.sSpel( pOrigin ));
113 myKernel = &fullKernel;
116 // ASSERT ( myMasks->size () == 9 );
118 isInitFullMasks = false;
119 isInitKernelAndMasks = true;
122template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
123template< typename SurfelIterator >
125typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Quantity
126DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::eval
127( const SurfelIterator & it ) const
129 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
131 Quantity innerSum, outerSum;
133 core_eval( it, innerSum, outerSum, false );
136 return ( innerSum * lambda + outerSum * ( 1.0 - lambda ));
139template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
140template< typename SurfelIterator, typename EvalFunctor >
142typename EvalFunctor::Value
143DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::eval
144( const SurfelIterator & it,
145 EvalFunctor functor ) const
147 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
149 Quantity innerSum, outerSum;
150 Quantity resultQuantity;
152 core_eval( it, innerSum, outerSum, false );
155 resultQuantity = innerSum * lambda + outerSum * ( 1.0 - lambda );
156 return functor( resultQuantity );
159template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
160template< typename SurfelIterator, typename OutputIterator >
163DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::eval
164( const SurfelIterator & itbegin,
165 const SurfelIterator & itend,
166 OutputIterator & result ) const
168 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
171#ifdef DGTAL_DEBUG_VERBOSE
172 Dimension recount = 0;
175 Quantity lastInnerSum;
176 Quantity lastOuterSum;
178 Quantity innerSum, outerSum;
180 Spel lastInnerSpel, lastOuterSpel;
182 /// Iterate on all cells
183 for( SurfelIterator it = itbegin; it != itend; ++it )
187#ifdef DGTAL_DEBUG_VERBOSE
188 bool hasJumped = core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
189 recount = ( hasJumped ) ? recount + 1 : recount;
191 core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
196 core_eval( it, innerSum, outerSum, false, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
200 *result++ = ( innerSum * lambda + outerSum * ( 1.0 - lambda ));
205#ifdef DGTAL_DEBUG_VERBOSE
206 std::cout << "#total cells = " << total << std::endl;
207 std::cout << "#recount = " << recount << std::endl;
211template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
212template< typename SurfelIterator, typename OutputIterator, typename EvalFunctor >
215DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::eval
216( const SurfelIterator & itbegin,
217 const SurfelIterator & itend,
218 OutputIterator & result,
219 EvalFunctor functor ) const
221 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
224#ifdef DGTAL_DEBUG_VERBOSE
225 Dimension recount = 0;
228 Quantity lastInnerSum;
229 Quantity lastOuterSum;
231 Quantity innerSum, outerSum;
232 Quantity resultQuantity;
234 Spel lastInnerSpel, lastOuterSpel;
236 /// Iterate on all cells
237 for( SurfelIterator it = itbegin; it != itend; ++it )
241#ifdef DGTAL_DEBUG_VERBOSE
242 bool hasJumped = core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
243 recount = ( hasJumped ) ? recount + 1 : recount;
245 core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
250 core_eval( it, innerSum, outerSum, false, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
254 resultQuantity = innerSum * lambda + outerSum * ( 1.0 - lambda );
255 *result++ = functor( resultQuantity );
260#ifdef DGTAL_DEBUG_VERBOSE
261 std::cout << "#total cells = " << total << std::endl;
262 std::cout << "#recount = " << recount << std::endl;
270template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
271template< typename SurfelIterator >
273typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::CovarianceMatrix
274DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::evalCovarianceMatrix
275( const SurfelIterator & it ) const
277 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
279 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
281 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false );
284 return ( innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda ));
287template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
288template< typename SurfelIterator, typename EvalFunctor >
290typename EvalFunctor::Value
291DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::evalCovarianceMatrix
292( const SurfelIterator & it,
293 EvalFunctor functor ) const
295 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
297 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
298 CovarianceMatrix resultCovarianceMatrix;
300 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false );
303 resultCovarianceMatrix = innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda );
304 return functor( resultCovarianceMatrix );
307template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
308template< typename SurfelIterator, typename OutputIterator >
311DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::evalCovarianceMatrix
312( const SurfelIterator & itbegin,
313 const SurfelIterator & itend,
314 OutputIterator & result ) const
316 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
319#ifdef DGTAL_DEBUG_VERBOSE
320 Dimension recount = 0;
323 std::vector<Quantity> lastInnerMoments(nbMoments );
324 std::vector<Quantity> lastOuterMoments(nbMoments );
326 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
328 Spel lastInnerSpel, lastOuterSpel;
330 /// Iterate on all cells
331 for( SurfelIterator it = itbegin; it != itend; ++it )
335#ifdef DGTAL_DEBUG_VERBOSE
336 bool hasJumped = core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
337 recount = ( hasJumped ) ? recount + 1 : recount;
339 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
344 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
348 *result++ = ( innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda ));
353#ifdef DGTAL_DEBUG_VERBOSE
354 std::cout << "#total cells = " << total << std::endl;
355 std::cout << "#recount = " << recount << std::endl;
359template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
360template< typename SurfelIterator, typename OutputIterator, typename EvalFunctor >
363DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::evalCovarianceMatrix
364( const SurfelIterator & itbegin,
365 const SurfelIterator & itend,
366 OutputIterator & result,
367 EvalFunctor functor ) const
369 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
372#ifdef DGTAL_DEBUG_VERBOSE
373 Dimension recount = 0;
376 std::vector<Quantity> lastInnerMoments( nbMoments );
377 std::vector<Quantity> lastOuterMoments( nbMoments );
379 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
380 CovarianceMatrix resultCovarianceMatrix;
382 Spel lastInnerSpel, lastOuterSpel;
384 /// Iterate on all cells
385 for( SurfelIterator it = itbegin; it != itend; ++it )
389#ifdef DGTAL_DEBUG_VERBOSE
390 bool hasJumped = core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
391 recount = ( hasJumped ) ? recount + 1 : recount;
393 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
398 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
402 resultCovarianceMatrix = innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda );
403 *result++ = functor( resultCovarianceMatrix );
408#ifdef DGTAL_DEBUG_VERBOSE
409 std::cout << "#total cells = " << total << std::endl;
410 std::cout << "#recount = " << recount << std::endl;
417template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
420DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::isValid() const
425template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
427DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::fillMoments
428( Quantity * aMomentMatrix,
430 double direction ) const
432 RealPoint current = myEmbedder( aSpel );
433 double x = current[ 0 ];
434 double y = current[ 1 ];
436 aMomentMatrix[ 0 ] += direction * 1;
437 aMomentMatrix[ 1 ] += direction * y;
438 aMomentMatrix[ 2 ] += direction * x;
439 aMomentMatrix[ 3 ] += direction * x * y;
440 aMomentMatrix[ 4 ] += direction * y * y;
441 aMomentMatrix[ 5 ] += direction * x * x;
444template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
446DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::computeCovarianceMatrix
447( const Quantity * aMomentMatrix,
448 CovarianceMatrix & aCovarianceMatrix ) const
454 * sum(x*y) sum(y*y) sum(x*x)
461 A.setComponent( 0, 0, aMomentMatrix[ 5 ] );
462 A.setComponent( 0, 1, aMomentMatrix[ 3 ] );
463 A.setComponent( 1, 0, aMomentMatrix[ 3 ] );
464 A.setComponent( 1, 1, aMomentMatrix[ 4 ] );
466 B = 1.0 / aMomentMatrix[ 0 ];
468 C.setComponent( 0, 0, aMomentMatrix[ 2 ] * aMomentMatrix[ 2 ] );
469 C.setComponent( 0, 1, aMomentMatrix[ 2 ] * aMomentMatrix[ 1 ] );
470 C.setComponent( 1, 0, aMomentMatrix[ 1 ] * aMomentMatrix[ 2 ] );
471 C.setComponent( 1, 1, aMomentMatrix[ 1 ] * aMomentMatrix[ 1 ] );
473 aCovarianceMatrix = A - C * B;
477// For Visual Studio, to be defined as a static const, it has to be initialized into the header file
478template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
480DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::nbMoments = 6;
483template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
484typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Spel
485DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultInnerSpel = Spel();
487template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
488typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Spel
489DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultOuterSpel = Spel();
491template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
492typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Quantity
493DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultInnerMoments[ 6 ] = {Quantity(0)};
495template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
496typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Quantity
497DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultOuterMoments[ 6 ] = {Quantity(0)};
499template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
500typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Quantity
501DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultInnerSum = Quantity(0);
503template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
504typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Quantity
505DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultOuterSum = Quantity(0);
507template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
508template< typename SurfelIterator >
510DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::core_eval
511( const SurfelIterator & it,
515 Spel & lastInnerSpel,
516 Spel & lastOuterSpel,
517 Quantity & lastInnerSum,
518 Quantity & lastOuterSum ) const
520 boost::ignore_unused_variable_warning( it );
521 boost::ignore_unused_variable_warning( innerSum );
522 boost::ignore_unused_variable_warning( outerSum);
523 boost::ignore_unused_variable_warning(useLastResults);
524 boost::ignore_unused_variable_warning(lastInnerSum);
525 boost::ignore_unused_variable_warning(lastOuterSum);
526 boost::ignore_unused_variable_warning(lastInnerSpel);
527 boost::ignore_unused_variable_warning(lastOuterSpel);
528 trace.error() << "Unavailable yet." << std::endl;
533template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
534template< typename SurfelIterator >
536DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::core_evalCovarianceMatrix
537( const SurfelIterator & it,
538 CovarianceMatrix & innerMatrix,
539 CovarianceMatrix & outerMatrix,
541 Spel & lastInnerSpel,
542 Spel & lastOuterSpel,
543 Quantity * lastInnerMoments,
544 Quantity * lastOuterMoments ) const
546 boost::ignore_unused_variable_warning(it);
547 boost::ignore_unused_variable_warning(innerMatrix);
548 boost::ignore_unused_variable_warning(outerMatrix);
549 boost::ignore_unused_variable_warning(useLastResults);
550 boost::ignore_unused_variable_warning(lastOuterMoments);
551 boost::ignore_unused_variable_warning(lastInnerMoments);
552 boost::ignore_unused_variable_warning(lastInnerSpel);
553 boost::ignore_unused_variable_warning(lastOuterSpel);
554 trace.error() << "Unavailable yet." << std::endl;
560//////////////////////////////////////////////////////////////////////////////////////////////////////////////
561///////////////////////////////////////////////////// 2D /////////////////////////////////////////////////////
562//////////////////////////////////////////////////////////////////////////////////////////////////////////////
564template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
566DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >
567::DigitalSurfaceConvolver( ConstAlias< Functor > f,
568 ConstAlias< KernelFunctor > g,
569 ConstAlias< KSpace > space)
574 isInitFullMasks( false ),
575 isInitKernelAndMasks( false )
577 myEmbedder = Embedder( myKSpace );
580template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel>
582DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >
583::DigitalSurfaceConvolver( const DigitalSurfaceConvolver& other )
585 myFFunctor( other.myFFunctor ),
586 myGFunctor( other.myGFunctor ),
587 myKSpace( other.myKSpace ),
588 myEmbedder( other.myEmbedder ),
589 isInitFullMasks( other.isInitFullMasks ),
590 isInitKernelAndMasks( other.isInitKernelAndMasks ),
591 myMasks( other.myMasks ),
592 myKernel( other.myKernel ),
593 myKernelMask( other.myKernelMask ),
594 myKernelKCoordsOrigin( other.myKernelKCoordsOrigin )
598template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
601DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::init
602( const Point & pOrigin,
603 ConstAlias< PairIterators > fullKernel,
604 ConstAlias< std::vector< PairIterators > > masks )
606 KhalimskySpaceND<2,typename KSpace::Integer> preK;
607 myKernelKCoordsOrigin = preK.sKCoords(preK.sSpel( pOrigin ));
608 myKernelMask = &fullKernel;
611 ASSERT ( myMasks->size () == 9 );
613 isInitFullMasks = true;
614 isInitKernelAndMasks = false;
617template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
620DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::init
621( const Point & pOrigin,
622 ConstAlias< DigitalKernel > fullKernel,
623 ConstAlias< std::vector< PairIterators > > masks )
625 KhalimskySpaceND<2,typename KSpace::Integer> preK;
626 myKernelKCoordsOrigin = preK.sKCoords(preK.sSpel( pOrigin ));
627 myKernel = &fullKernel;
630 ASSERT ( myMasks->size () == 9 );
632 isInitFullMasks = false;
633 isInitKernelAndMasks = true;
636template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
637template< typename SurfelIterator >
639typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Quantity
640DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::eval
641( const SurfelIterator & it ) const
643 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
645 Quantity innerSum, outerSum;
647 core_eval( it, innerSum, outerSum, false );
650 return ( innerSum * lambda + outerSum * ( 1.0 - lambda ));
653template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
654template< typename SurfelIterator, typename EvalFunctor >
656typename EvalFunctor::Value
657DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::eval
658( const SurfelIterator & it,
659 EvalFunctor functor ) const
661 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
663 Quantity innerSum, outerSum;
664 Quantity resultQuantity;
666 core_eval( it, innerSum, outerSum, false );
669 resultQuantity = innerSum * lambda + outerSum * ( 1.0 - lambda );
670 return functor( resultQuantity );
673template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
674template< typename SurfelIterator, typename OutputIterator >
677DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::eval
678( const SurfelIterator & itbegin,
679 const SurfelIterator & itend,
680 OutputIterator & result ) const
682 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
685#ifdef DGTAL_DEBUG_VERBOSE
686 Dimension recount = 0;
689 Quantity lastInnerSum;
690 Quantity lastOuterSum;
692 Quantity innerSum, outerSum;
694 Spel lastInnerSpel, lastOuterSpel;
696 /// Iterate on all cells
697 for( SurfelIterator it = itbegin; it != itend; ++it )
701#ifdef DGTAL_DEBUG_VERBOSE
702 bool hasJumped = core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
703 recount = ( hasJumped ) ? recount + 1 : recount;
705 core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
710 core_eval( it, innerSum, outerSum, false, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
714 *result++ = ( innerSum * lambda + outerSum * ( 1.0 - lambda ));
719#ifdef DGTAL_DEBUG_VERBOSE
720 std::cout << "#total cells = " << total << std::endl;
721 std::cout << "#recount = " << recount << std::endl;
725template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
726template< typename SurfelIterator, typename OutputIterator, typename EvalFunctor >
729DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::eval
730( const SurfelIterator & itbegin,
731 const SurfelIterator & itend,
732 OutputIterator & result,
733 EvalFunctor functor ) const
735 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
738#ifdef DGTAL_DEBUG_VERBOSE
739 Dimension recount = 0;
742 Quantity lastInnerSum;
743 Quantity lastOuterSum;
745 Quantity innerSum, outerSum;
746 Quantity resultQuantity;
748 Spel lastInnerSpel, lastOuterSpel;
750 /// Iterate on all cells
751 for( SurfelIterator it = itbegin; it != itend; ++it )
755#ifdef DGTAL_DEBUG_VERBOSE
756 bool hasJumped = core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
757 recount = ( hasJumped ) ? recount + 1 : recount;
759 core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
764 core_eval( it, innerSum, outerSum, false, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
768 resultQuantity = innerSum * lambda + outerSum * ( 1.0 - lambda );
769 *result++ = functor( resultQuantity );
774#ifdef DGTAL_DEBUG_VERBOSE
775 std::cout << "#total cells = " << total << std::endl;
776 std::cout << "#recount = " << recount << std::endl;
784template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
785template< typename SurfelIterator >
787typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::CovarianceMatrix
788DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::evalCovarianceMatrix
789( const SurfelIterator & it ) const
791 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
793 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
795 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false );
798 return ( innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda ));
801template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
802template< typename SurfelIterator, typename EvalFunctor >
804typename EvalFunctor::Value
805DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::evalCovarianceMatrix
806( const SurfelIterator & it,
807 EvalFunctor functor ) const
809 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
811 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
812 CovarianceMatrix resultCovarianceMatrix;
814 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false );
817 resultCovarianceMatrix = innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda );
818 return functor( resultCovarianceMatrix );
821template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
822template< typename SurfelIterator, typename OutputIterator >
825DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::evalCovarianceMatrix
826( const SurfelIterator & itbegin,
827 const SurfelIterator & itend,
828 OutputIterator & result ) const
830 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
833#ifdef DGTAL_DEBUG_VERBOSE
834 Dimension recount = 0;
837 std::vector<Quantity> lastInnerMoments( nbMoments );
838 std::vector<Quantity> lastOuterMoments( nbMoments );
840 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
842 Spel lastInnerSpel, lastOuterSpel;
844 /// Iterate on all cells
845 for( SurfelIterator it = itbegin; it != itend; ++it )
849#ifdef DGTAL_DEBUG_VERBOSE
850 bool hasJumped = core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
851 recount = ( hasJumped ) ? recount + 1 : recount;
853 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
858 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
862 *result++ = ( innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda ));
867#ifdef DGTAL_DEBUG_VERBOSE
868 std::cout << "#total cells = " << total << std::endl;
869 std::cout << "#recount = " << recount << std::endl;
873template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
874template< typename SurfelIterator, typename OutputIterator, typename EvalFunctor >
877DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::evalCovarianceMatrix
878( const SurfelIterator & itbegin,
879 const SurfelIterator & itend,
880 OutputIterator & result,
881 EvalFunctor functor ) const
883 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
886#ifdef DGTAL_DEBUG_VERBOSE
887 Dimension recount = 0;
890 std::vector<Quantity> lastInnerMoments( nbMoments );
891 std::vector<Quantity> lastOuterMoments( nbMoments );
893 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
894 CovarianceMatrix resultCovarianceMatrix;
896 Spel lastInnerSpel, lastOuterSpel;
898 /// Iterate on all cells
899 for( SurfelIterator it = itbegin; it != itend; ++it )
903#ifdef DGTAL_DEBUG_VERBOSE
904 bool hasJumped = core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
905 recount = ( hasJumped ) ? recount + 1 : recount;
907 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
912 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
916 resultCovarianceMatrix = innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda );
917 *result++ = functor( resultCovarianceMatrix );
922#ifdef DGTAL_DEBUG_VERBOSE
923 std::cout << "#total cells = " << total << std::endl;
924 std::cout << "#recount = " << recount << std::endl;
931template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
934DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::isValid() const
939template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
941DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::fillMoments
942( Quantity * aMomentMatrix,
944 double direction ) const
946 RealPoint current = myEmbedder( aSpel );
947 double x = current[ 0 ];
948 double y = current[ 1 ];
950 aMomentMatrix[ 0 ] += direction * 1;
951 aMomentMatrix[ 1 ] += direction * y;
952 aMomentMatrix[ 2 ] += direction * x;
953 aMomentMatrix[ 3 ] += direction * x * y;
954 aMomentMatrix[ 4 ] += direction * y * y;
955 aMomentMatrix[ 5 ] += direction * x * x;
958template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
960DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::computeCovarianceMatrix
961( const Quantity * aMomentMatrix,
962 CovarianceMatrix & aCovarianceMatrix ) const
968 A.setComponent( 0, 0, aMomentMatrix[ 5 ] );
969 A.setComponent( 0, 1, aMomentMatrix[ 3 ] );
970 A.setComponent( 1, 0, aMomentMatrix[ 3 ] );
971 A.setComponent( 1, 1, aMomentMatrix[ 4 ] );
973 B = 1.0 / aMomentMatrix[ 0 ];
975 C.setComponent( 0, 0, aMomentMatrix[ 2 ] * aMomentMatrix[ 2 ] );
976 C.setComponent( 0, 1, aMomentMatrix[ 2 ] * aMomentMatrix[ 1 ] );
977 C.setComponent( 1, 0, aMomentMatrix[ 1 ] * aMomentMatrix[ 2 ] );
978 C.setComponent( 1, 1, aMomentMatrix[ 1 ] * aMomentMatrix[ 1 ] );
980 aCovarianceMatrix = A - C * B;
984// For Visual Studio, to be defined as a static const, it has to be initialized into the header file
985template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
987DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::nbMoments = 6;
990template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
991typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Spel
992DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::defaultInnerSpel = Spel();
994template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
995typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Spel
996DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::defaultOuterSpel = Spel();
998template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
999typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Quantity
1000DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::defaultInnerMoments[ 6 ] = {Quantity(0)};
1002template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1003typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Quantity
1004DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::defaultOuterMoments[ 6 ] = {Quantity(0)};
1006template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1007typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Quantity
1008DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::defaultInnerSum = Quantity(0);
1010template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1011typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Quantity
1012DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::defaultOuterSum = Quantity(0);
1014template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1015template< typename SurfelIterator >
1017DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::core_eval
1018( const SurfelIterator & it,
1019 Quantity & innerSum,
1020 Quantity & outerSum,
1021 bool useLastResults,
1022 Spel & lastInnerSpel,
1023 Spel & lastOuterSpel,
1024 Quantity & lastInnerSum,
1025 Quantity & lastOuterSum ) const
1027 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1029 using KPS = typename KSpace::PreCellularGridSpace;
1031#ifdef DGTAL_DEBUG_VERBOSE
1032 Dimension recount = false;
1035 typedef typename Functor::Quantity FQuantity;
1036 DGtal::Dimension nbMasks =static_cast<DGtal::Dimension>( (long)myMasks->size() - 1);
1037 DGtal::Dimension positionOfFullKernel = 4;
1039 Quantity m = NumberTraits< Quantity >::ZERO;
1041 Spel currentInnerSpel, currentOuterSpel;
1043 Point shiftInnerSpel, shiftOuterSpel;
1046 bool bComputed = false; /// <! if the cell has already been computed, continue to the next
1048 int x, y, x2, y2, x2y2;
1049 unsigned int offset;
1053 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
1054 currentInnerSpel = myKSpace.sDirectIncident( *it, kDim ); /// Spel on the border, but inside the shape
1055 shiftInnerSpel = myKSpace.sKCoords( currentInnerSpel ) - myKernelKCoordsOrigin;
1057 /// Check if we can use previous results
1058 if( useLastResults )
1062 if( currentInnerSpel == lastInnerSpel )
1068 else if( currentInnerSpel == lastOuterSpel )
1077 diffSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( lastInnerSpel );
1085 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 );
1087 if( x2y2 != 4 && x2y2 != 8 ) /// Previous and current cells aren't adjacent. Compute on the full kernel
1089 useLastResults = false;
1090#ifdef DGTAL_DEBUG_VERBOSE
1094 else if( offset == positionOfFullKernel ) /// Full kernel in 2D. Never reached because case already considered before. It's a honeypot.
1096 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
1100 useLastResults = true;
1107 if( !useLastResults ) /// Computation on full kernel, we have no previous results
1109 m = NumberTraits< Quantity >::ZERO;
1111 if( isInitFullMasks )
1113 for( KernelConstIterator itm = myKernelMask->first; itm != myKernelMask->second; ++itm )
1115 auto preShiftedSpel = KPS::sSpel( *itm );
1116 preShiftedSpel.coordinates += shiftInnerSpel;
1118 if( myKSpace.sIsInside( preShiftedSpel ) )
1120 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1122 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1123 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1125 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1132 else if( isInitKernelAndMasks )
1134 Domain domain = myKernel->getDomain();
1135 for( typename Domain::ConstIterator itm = domain.begin(), itend = domain.end(); itm != itend; ++itm )
1137 if( myKernel->operator()( *itm ))
1139 auto preShiftedSpel = KPS::sSpel( *itm );
1140 preShiftedSpel.coordinates += shiftInnerSpel;
1142 if( myKSpace.sIsInside( preShiftedSpel ) )
1144 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1146 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1147 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1149 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1159 trace.error() << "DigitalSurfaceConvolver: You need to init the convolver first." << std::endl;
1164 else /// Using lastInnerMoments
1168 /// Part to subtract from previous result.
1169 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
1171 auto preShiftedSpel = KPS::sSpel( *itm );
1172 preShiftedSpel.coordinates += shiftInnerSpel - diffSpel;
1174 if( myKSpace.sIsInside( preShiftedSpel ) )
1176 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1178 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1179 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1181 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1188 /// Part to add from previous result.
1189 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
1191 auto preShiftedSpel = KPS::sSpel( *itm );
1192 preShiftedSpel.coordinates += shiftInnerSpel;
1194 if( myKSpace.sIsInside( preShiftedSpel ) )
1196 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1198 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1199 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1201 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1209 /// Computation of covariance Matrix
1217 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
1218 currentOuterSpel = myKSpace.sIndirectIncident( *it, kDim );
1219 shiftOuterSpel = myKSpace.sKCoords( currentOuterSpel ) - myKernelKCoordsOrigin;
1221 ASSERT( currentInnerSpel != currentOuterSpel );
1223 diffSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( currentInnerSpel );
1231 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 );
1233 if( x2y2 != 4 && x2y2 != 8 ) /// Inside and outside cells aren't adjacent, but should be. It's a honeypot.
1235 trace.error() << "Error - Found that inside and outside cells aren't adjacent. That's not logic.\n";
1237 else if( offset == positionOfFullKernel ) /// Full kernel in 2D. Never reached because case already considered before. It's a honeypot.
1239 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
1243 /// Part to subtract from previous result.
1244 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
1246 auto preShiftedSpel = KPS::sSpel( *itm );
1247 preShiftedSpel.coordinates += shiftOuterSpel - diffSpel;
1249 if( myKSpace.sIsInside( preShiftedSpel ) )
1251 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1253 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1254 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1256 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1263 /// Part to add from previous result.
1264 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
1266 auto preShiftedSpel = KPS::sSpel( *itm );
1267 preShiftedSpel.coordinates += shiftOuterSpel;
1269 if( myKSpace.sIsInside( preShiftedSpel ) )
1271 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1273 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1274 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1276 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1284 /// Computation of covariance Matrix
1289 ASSERT (( lastInnerSum != 0 )); // Maybe a problem here. Can be normal ... but needs to check twice.
1291 lastInnerSpel = currentInnerSpel;
1292 lastOuterSpel = currentOuterSpel;
1294#ifdef DGTAL_DEBUG_VERBOSE
1302template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1303template< typename SurfelIterator >
1305DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::core_evalCovarianceMatrix
1306( const SurfelIterator & it,
1307 CovarianceMatrix & innerMatrix,
1308 CovarianceMatrix & outerMatrix,
1309 bool useLastResults,
1310 Spel & lastInnerSpel,
1311 Spel & lastOuterSpel,
1312 Quantity * lastInnerMoments,
1313 Quantity * lastOuterMoments ) const
1315 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1317 using KPS = typename KSpace::PreCellularGridSpace;
1319#ifdef DGTAL_DEBUG_VERBOSE
1320 Dimension recount = false;
1323 typedef typename Functor::Quantity FQuantity;
1324 DGtal::Dimension nbMasks = myMasks->size() - 1;
1325 DGtal::Dimension positionOfFullKernel = 4;
1327 Quantity m[ nbMoments ]; /// <! [ m00, m01, m10, m11, m02, m20 ]
1328 std::fill( m, m + nbMoments, NumberTraits< Quantity >::ZERO ); /// <! clear array
1330 Spel currentInnerSpel, currentOuterSpel;
1332 Point shiftInnerSpel, shiftOuterSpel;
1335 bool bComputed = false; /// <! if the cell has already been computed, continue to the next
1337 int x, y, x2, y2, x2y2;
1338 unsigned int offset;
1342 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
1343 currentInnerSpel = myKSpace.sDirectIncident( *it, kDim ); /// Spel on the border, but inside the shape
1344 shiftInnerSpel = myKSpace.sKCoords( currentInnerSpel ) - myKernelKCoordsOrigin;
1346 /// Check if we can use previous results
1347 if( useLastResults )
1351 if( currentInnerSpel == lastInnerSpel )
1353 memcpy( m, lastInnerMoments, nbMoments * sizeof( Quantity ));
1354 computeCovarianceMatrix( m, innerMatrix );
1358 else if( currentInnerSpel == lastOuterSpel )
1360 memcpy( m, lastOuterMoments, nbMoments * sizeof( Quantity ));
1361 computeCovarianceMatrix( m, innerMatrix );
1362 memcpy( lastInnerMoments, m, nbMoments * sizeof( Quantity ));
1368 diffSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( lastInnerSpel );
1376 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 );
1378 if( x2y2 != 4 && x2y2 != 8 ) /// Previous and current cells aren't adjacent. Compute on the full kernel
1380 useLastResults = false;
1381#ifdef DGTAL_DEBUG_VERBOSE
1385 else if( offset == positionOfFullKernel ) /// Full kernel in 2D. Never reached because case already considered before. It's a honeypot.
1387 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
1391 useLastResults = true;
1398 if( !useLastResults ) /// Computation on full kernel, we have no previous results
1400 std::fill( m, m + nbMoments, NumberTraits< Quantity >::ZERO ); /// <! clear array
1402 if( isInitFullMasks )
1404 for( KernelConstIterator itm = myKernelMask->first; itm != myKernelMask->second; ++itm )
1406 auto preShiftedSpel = KPS::sSpel( *itm );
1407 preShiftedSpel.coordinates += shiftInnerSpel;
1409 if( myKSpace.sIsInside( preShiftedSpel ) )
1411 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1413 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1414 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1416 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1418 fillMoments( m, shiftedSpel, 1.0 );
1423 else if( isInitKernelAndMasks )
1425 Domain domain = myKernel->getDomain();
1426 for( typename Domain::ConstIterator itm = domain.begin(), itend = domain.end(); itm != itend; ++itm )
1428 if( myKernel->operator()( *itm ))
1430 auto preShiftedSpel = KPS::sSpel( *itm );
1431 preShiftedSpel.coordinates += shiftInnerSpel;
1433 if( myKSpace.sIsInside( preShiftedSpel ) )
1435 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1437 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1438 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1440 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1442 fillMoments( m, shiftedSpel, 1.0 );
1450 trace.error() << "DigitalSurfaceConvolver: You need to init the convolver first." << std::endl;
1454 else /// Using lastInnerMoments
1456 memcpy( m, lastInnerMoments, nbMoments * sizeof( Quantity ));
1458 /// Part to subtract from previous result.
1459 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
1461 auto preShiftedSpel = KPS::sSpel( *itm );
1462 preShiftedSpel.coordinates += shiftInnerSpel - diffSpel;
1464 if( myKSpace.sIsInside( preShiftedSpel ) )
1466 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1468 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1469 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1471 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1473 fillMoments( m, shiftedSpel, -1.0 );
1478 /// Part to add from previous result.
1479 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
1481 auto preShiftedSpel = KPS::sSpel( *itm );
1482 preShiftedSpel.coordinates += shiftInnerSpel;
1484 if( myKSpace.sIsInside( preShiftedSpel ) )
1486 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1488 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1489 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1491 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1493 fillMoments( m, shiftedSpel, 1.0 );
1499 /// Computation of covariance Matrix
1500 computeCovarianceMatrix( m, innerMatrix );
1501 memcpy( lastInnerMoments, m, nbMoments * sizeof( Quantity ));
1507 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
1508 currentOuterSpel = myKSpace.sIndirectIncident( *it, kDim );
1509 shiftOuterSpel = myKSpace.sKCoords( currentOuterSpel ) - myKernelKCoordsOrigin;
1511 ASSERT( currentInnerSpel != currentOuterSpel );
1513 diffSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( currentInnerSpel );
1521 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 );
1523 if( x2y2 != 4 && x2y2 != 8 ) /// Inside and outside cells aren't adjacent, but should be. It's a honeypot.
1525 trace.error() << "Error - Found that inside and outside cells aren't adjacent. That's not logic.\n";
1527 else if( offset == positionOfFullKernel ) /// Full kernel in 2D. Never reached because case already considered before. It's a honeypot.
1529 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
1533 /// Part to subtract from previous result.
1534 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
1536 auto preShiftedSpel = KPS::sSpel( *itm );
1537 preShiftedSpel.coordinates += shiftOuterSpel - diffSpel;
1538 if( myKSpace.sIsInside( preShiftedSpel ) )
1540 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1542 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1543 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1545 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1547 fillMoments( m, shiftedSpel, -1.0 );
1552 /// Part to add from previous result.
1553 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
1555 auto preShiftedSpel = KPS::sSpel( *itm );
1556 preShiftedSpel.coordinates += shiftOuterSpel;
1558 if( myKSpace.sIsInside( preShiftedSpel ) )
1560 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
1562 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
1563 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
1565 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
1567 fillMoments( m, shiftedSpel, 1.0 );
1573 /// Computation of covariance Matrix
1574 computeCovarianceMatrix( m, outerMatrix );
1575 memcpy( lastOuterMoments, m, nbMoments * sizeof( Quantity ));
1578 ASSERT (( lastInnerMoments[ 0 ] != 0 )); // Maybe a problem here. Can be normal ... but needs to check twice.
1580 lastInnerSpel = currentInnerSpel;
1581 lastOuterSpel = currentOuterSpel;
1583#ifdef DGTAL_DEBUG_VERBOSE
1593//////////////////////////////////////////////////////////////////////////////////////////////////////////////
1594///////////////////////////////////////////////////// 3D /////////////////////////////////////////////////////
1595//////////////////////////////////////////////////////////////////////////////////////////////////////////////
1597template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1599DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >
1600::DigitalSurfaceConvolver( ConstAlias< Functor > f,
1601 ConstAlias< KernelFunctor > g,
1602 ConstAlias< KSpace > space)
1607 isInitFullMasks( false ),
1608 isInitKernelAndMasks( false )
1610 myEmbedder = Embedder( myKSpace );
1613template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel>
1615DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >
1616::DigitalSurfaceConvolver( const DigitalSurfaceConvolver& other )
1618 myFFunctor( other.myFFunctor ),
1619 myGFunctor( other.myGFunctor ),
1620 myKSpace( other.myKSpace ),
1621 myEmbedder( other.myEmbedder ),
1622 isInitFullMasks( other.isInitFullMasks ),
1623 isInitKernelAndMasks( other.isInitKernelAndMasks ),
1624 myMasks( other.myMasks ),
1625 myKernel( other.myKernel ),
1626 myKernelMask( other.myKernelMask ),
1627 myKernelKCoordsOrigin( other.myKernelKCoordsOrigin )
1631template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1634DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::init
1635( const Point & pOrigin,
1636 ConstAlias< PairIterators > fullKernel,
1637 ConstAlias< std::vector< PairIterators > > masks )
1639 KhalimskySpaceND<3,typename KSpace::Integer> preK;
1640 myKernelKCoordsOrigin = preK.sKCoords(preK.sSpel( pOrigin ));
1641 myKernelMask = &fullKernel;
1644 ASSERT ( myMasks->size () == 27 );
1646 isInitFullMasks = true;
1647 isInitKernelAndMasks = false;
1650template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1653DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::init
1654( const Point & pOrigin,
1655 ConstAlias< DigitalKernel > fullKernel,
1656 ConstAlias< std::vector< PairIterators > > masks )
1658 KhalimskySpaceND<3,typename KSpace::Integer> preK;
1659 myKernelKCoordsOrigin = preK.sKCoords(preK.sSpel( pOrigin ));
1660 myKernel = &fullKernel;
1662 ASSERT ( myMasks->size () == 27 );
1664 isInitFullMasks = false;
1665 isInitKernelAndMasks = true;
1671template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1672template< typename SurfelIterator >
1674typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Quantity
1675DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::eval
1676( const SurfelIterator & it ) const
1678 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1680 Quantity innerSum, outerSum;
1682 core_eval( it, innerSum, outerSum, false );
1684 double lambda = 0.5;
1685 return ( innerSum * lambda + outerSum * ( 1.0 - lambda ));
1688template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1689template< typename SurfelIterator, typename EvalFunctor >
1691typename EvalFunctor::Value
1692DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::eval
1693( const SurfelIterator & it,
1694 EvalFunctor functor ) const
1696 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1698 Quantity innerSum, outerSum;
1699 Quantity resultQuantity;
1701 core_eval( it, innerSum, outerSum, false );
1703 double lambda = 0.5;
1704 resultQuantity = innerSum * lambda + outerSum * ( 1.0 - lambda );
1705 return functor( resultQuantity );
1708template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1709template< typename SurfelIterator, typename OutputIterator >
1712DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::eval
1713( const SurfelIterator & itbegin,
1714 const SurfelIterator & itend,
1715 OutputIterator & result ) const
1717 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1719 Dimension total = 0;
1720#ifdef DGTAL_DEBUG_VERBOSE
1721 Dimension recount = 0;
1724 Quantity lastInnerSum;
1725 Quantity lastOuterSum;
1727 Quantity innerSum, outerSum;
1729 Spel lastInnerSpel, lastOuterSpel;
1731 /// Iterate on all cells
1732 for( SurfelIterator it = itbegin; it != itend; ++it )
1736#ifdef DGTAL_DEBUG_VERBOSE
1737 bool hasJumped = core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
1738 recount = ( hasJumped ) ? recount + 1 : recount;
1740 core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
1745 core_eval( it, innerSum, outerSum, false, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
1748 double lambda = 0.5;
1749 *result++ = ( innerSum * lambda + outerSum * ( 1.0 - lambda ));
1754#ifdef DGTAL_DEBUG_VERBOSE
1755 std::cout << "#total cells = " << total << std::endl;
1756 std::cout << "#recount = " << recount << std::endl;
1760template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1761template< typename SurfelIterator, typename OutputIterator, typename EvalFunctor >
1764DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::eval
1765( const SurfelIterator & itbegin,
1766 const SurfelIterator & itend,
1767 OutputIterator & result,
1768 EvalFunctor functor ) const
1770 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1772 Dimension total = 0;
1773#ifdef DGTAL_DEBUG_VERBOSE
1774 Dimension recount = 0;
1777 Quantity lastInnerSum;
1778 Quantity lastOuterSum;
1780 Quantity innerSum, outerSum;
1781 Quantity resultQuantity;
1783 Spel lastInnerSpel, lastOuterSpel;
1785 /// Iterate on all cells
1786 for( SurfelIterator it = itbegin; it != itend; ++it )
1790#ifdef DGTAL_DEBUG_VERBOSE
1791 bool hasJumped = core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
1792 recount = ( hasJumped ) ? recount + 1 : recount;
1794 core_eval( it, innerSum, outerSum, true, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
1799 core_eval( it, innerSum, outerSum, false, lastInnerSpel, lastOuterSpel, lastInnerSum, lastOuterSum );
1802 double lambda = 0.5;
1803 resultQuantity = innerSum * lambda + outerSum * ( 1.0 - lambda );
1804 *result++ = functor( resultQuantity );
1809#ifdef DGTAL_DEBUG_VERBOSE
1810 std::cout << "#total cells = " << total << std::endl;
1811 std::cout << "#recount = " << recount << std::endl;
1817template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1818template< typename SurfelIterator >
1820typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::CovarianceMatrix
1821DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::evalCovarianceMatrix
1822( const SurfelIterator & it ) const
1824 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1826 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
1828 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false );
1830 double lambda = 0.5;
1831 return ( innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda ));
1834template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1835template< typename SurfelIterator, typename EvalFunctor >
1837typename EvalFunctor::Value
1838DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::evalCovarianceMatrix
1839( const SurfelIterator & it,
1840 EvalFunctor functor ) const
1842 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1844 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
1845 CovarianceMatrix resultCovarianceMatrix;
1847 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false );
1849 double lambda = 0.5;
1850 resultCovarianceMatrix = innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda );
1851 return functor( resultCovarianceMatrix );
1854template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1855template< typename SurfelIterator, typename OutputIterator >
1858DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::evalCovarianceMatrix
1859( const SurfelIterator & itbegin,
1860 const SurfelIterator & itend,
1861 OutputIterator & result ) const
1863 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1865 Dimension total = 0;
1866#ifdef DGTAL_DEBUG_VERBOSE
1867 Dimension recount = 0;
1870 std::vector<Quantity> lastInnerMoments( nbMoments );
1871 std::vector<Quantity> lastOuterMoments( nbMoments );
1873 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
1875 Spel lastInnerSpel, lastOuterSpel;
1877 /// Iterate on all cells
1878 for( SurfelIterator it = itbegin; it != itend; ++it )
1882#ifdef DGTAL_DEBUG_VERBOSE
1883 bool hasJumped = core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
1884 recount = ( hasJumped ) ? recount + 1 : recount;
1886 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
1891 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
1894 double lambda = 0.5;
1895 *result++ = ( innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda ));
1900#ifdef DGTAL_DEBUG_VERBOSE
1901 std::cout << "#total cells = " << total << std::endl;
1902 std::cout << "#recount = " << recount << std::endl;
1906template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1907template< typename SurfelIterator, typename OutputIterator, typename EvalFunctor >
1910DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::evalCovarianceMatrix
1911( const SurfelIterator & itbegin,
1912 const SurfelIterator & itend,
1913 OutputIterator & result,
1914 EvalFunctor functor ) const
1916 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
1918 Dimension total = 0;
1919#ifdef DGTAL_DEBUG_VERBOSE
1920 Dimension recount = 0;
1923 Quantity *lastInnerMoments = new Quantity[ nbMoments ];
1924 Quantity *lastOuterMoments = new Quantity[ nbMoments ];
1926 CovarianceMatrix innerCovarianceMatrix, outerCovarianceMatrix;
1927 CovarianceMatrix resultCovarianceMatrix;
1929 Spel lastInnerSpel, lastOuterSpel;
1931 /// Iterate on all cells
1932 for( SurfelIterator it = itbegin; it != itend; ++it )
1936#ifdef DGTAL_DEBUG_VERBOSE
1937 bool hasJumped = core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
1938 recount = ( hasJumped ) ? recount + 1 : recount;
1940 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, true, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
1945 core_evalCovarianceMatrix( it, innerCovarianceMatrix, outerCovarianceMatrix, false, lastInnerSpel, lastOuterSpel, lastInnerMoments, lastOuterMoments );
1948 double lambda = 0.5;
1949 resultCovarianceMatrix = innerCovarianceMatrix * lambda + outerCovarianceMatrix * ( 1.0 - lambda );
1950 *result++ = functor( resultCovarianceMatrix );
1955#ifdef DGTAL_DEBUG_VERBOSE
1956 std::cout << "#total cells = " << total << std::endl;
1957 std::cout << "#recount = " << recount << std::endl;
1960 delete[] lastOuterMoments;
1961 delete[] lastInnerMoments;
1966template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1969DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::isValid() const
1974template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1976DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::fillMoments
1977( Quantity * aMomentMatrix,
1979 double direction ) const
1981 RealPoint current = myEmbedder( aSpel );
1982 double x = current[ 0 ];
1983 double y = current[ 1 ];
1984 double z = current[ 2 ];
1986 aMomentMatrix[ 0 ] += direction * 1;
1987 aMomentMatrix[ 1 ] += direction * z;
1988 aMomentMatrix[ 2 ] += direction * y;
1989 aMomentMatrix[ 3 ] += direction * x;
1990 aMomentMatrix[ 4 ] += direction * y * z;
1991 aMomentMatrix[ 5 ] += direction * x * z;
1992 aMomentMatrix[ 6 ] += direction * x * y;
1993 aMomentMatrix[ 7 ] += direction * z * z;
1994 aMomentMatrix[ 8 ] += direction * y * y;
1995 aMomentMatrix[ 9 ] += direction * x * x;
2000template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2002DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::computeCovarianceMatrix
2003( const Quantity * aMomentMatrix,
2004 CovarianceMatrix & aCovarianceMatrix ) const
2010 A.setComponent( 0, 0, aMomentMatrix[ 9 ] );
2011 A.setComponent( 0, 1, aMomentMatrix[ 6 ] );
2012 A.setComponent( 0, 2, aMomentMatrix[ 5 ] );
2013 A.setComponent( 1, 0, aMomentMatrix[ 6 ] );
2014 A.setComponent( 1, 1, aMomentMatrix[ 8 ] );
2015 A.setComponent( 1, 2, aMomentMatrix[ 4 ] );
2016 A.setComponent( 2, 0, aMomentMatrix[ 5 ] );
2017 A.setComponent( 2, 1, aMomentMatrix[ 4 ] );
2018 A.setComponent( 2, 2, aMomentMatrix[ 7 ] );
2020 B = 1.0 / aMomentMatrix[ 0 ];
2022 C.setComponent( 0, 0, aMomentMatrix[ 3 ] * aMomentMatrix[ 3 ] );
2023 C.setComponent( 0, 1, aMomentMatrix[ 3 ] * aMomentMatrix[ 2 ] );
2024 C.setComponent( 0, 2, aMomentMatrix[ 3 ] * aMomentMatrix[ 1 ] );
2025 C.setComponent( 1, 0, aMomentMatrix[ 2 ] * aMomentMatrix[ 3 ] );
2026 C.setComponent( 1, 1, aMomentMatrix[ 2 ] * aMomentMatrix[ 2 ] );
2027 C.setComponent( 1, 2, aMomentMatrix[ 2 ] * aMomentMatrix[ 1 ] );
2028 C.setComponent( 2, 0, aMomentMatrix[ 1 ] * aMomentMatrix[ 3 ] );
2029 C.setComponent( 2, 1, aMomentMatrix[ 1 ] * aMomentMatrix[ 2 ] );
2030 C.setComponent( 2, 2, aMomentMatrix[ 1 ] * aMomentMatrix[ 1 ] );
2032 aCovarianceMatrix = A - C * B;
2036// For Visual Studio, to be defined as a static const, it has to be initialized into the header file
2037template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2039DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::nbMoments = 10;
2042template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2043typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Spel
2044DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::defaultInnerSpel = Spel();
2046template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2047typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Spel
2048DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::defaultOuterSpel = Spel();
2050template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2051typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Quantity
2052DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::defaultInnerMoments[ 10 ] = {Quantity(0)};
2054template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2055typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Quantity
2056DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::defaultOuterMoments[ 10 ] = {Quantity(0)};
2058template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2059typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Quantity
2060DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::defaultInnerSum = Quantity(0);
2062template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2063typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Quantity
2064DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::defaultOuterSum = Quantity(0);
2066template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2067template< typename SurfelIterator >
2069DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::core_eval
2070( const SurfelIterator & it,
2071 Quantity & innerSum,
2072 Quantity & outerSum,
2073 bool useLastResults,
2074 Spel & lastInnerSpel,
2075 Spel & lastOuterSpel,
2076 Quantity & lastInnerSum,
2077 Quantity & lastOuterSum ) const
2079 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
2081 using KPS = typename KSpace::PreCellularGridSpace;
2083#ifdef DGTAL_DEBUG_VERBOSE
2084 Dimension recount = false;
2087 typedef typename Functor::Quantity FQuantity;
2088 DGtal::Dimension nbMasks = static_cast<DGtal::Dimension>(myMasks->size()) - 1;
2089 DGtal::Dimension positionOfFullKernel = 13;
2091 Quantity m = NumberTraits< Quantity >::ZERO;
2093 Spel currentInnerSpel, currentOuterSpel;
2095 Point shiftInnerSpel, shiftOuterSpel;
2098 bool bComputed = false; /// <! if the cell has already been computed, continue to the next
2100 int x, y, z, x2, y2, z2, x2y2z2;
2101 unsigned int offset;
2105 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
2106 currentInnerSpel = myKSpace.sDirectIncident( *it, kDim ); /// Spel on the border, but inside the shape
2107 shiftInnerSpel = myKSpace.sKCoords( currentInnerSpel ) - myKernelKCoordsOrigin;
2109 /// Check if we can use previous results
2110 if( useLastResults )
2114 if( currentInnerSpel == lastInnerSpel )
2121 else if( currentInnerSpel == lastOuterSpel )
2131 diffSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( lastInnerSpel );
2139 x2y2z2 = x2 + y2 + z2;
2141 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 ) + ((( z / 2 ) + 1 ) * 9 );
2143 if( x2y2z2 != 4 && x2y2z2 != 8 && !( x2 == 4 && y2 == 4 && z2 == 4 )) /// Previous and current cells aren't adjacent. Compute on the full kernel
2145 useLastResults = false;
2146#ifdef DGTAL_DEBUG_VERBOSE
2150 else if( offset == positionOfFullKernel ) /// Full kernel in 3D. Never reached because case already considered before. It's a honeypot.
2152 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
2156 useLastResults = true;
2163 if( !useLastResults ) /// Computation on full kernel, we have no previous results
2165 m = NumberTraits< Quantity >::ZERO;
2167 if( isInitFullMasks )
2169 for( KernelConstIterator itm = myKernelMask->first; itm != myKernelMask->second; ++itm )
2171 auto preShiftedSpel = KPS::sSpel( *itm );
2172 preShiftedSpel.coordinates += shiftInnerSpel;
2174 if( myKSpace.sIsInside( preShiftedSpel ) )
2176 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2178 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2179 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2180 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2182 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2189 else if( isInitKernelAndMasks )
2191 Domain domain = myKernel->getDomain();
2192 for( typename Domain::ConstIterator itm = domain.begin(), itend = domain.end(); itm != itend; ++itm )
2194 if( myKernel->operator()( *itm ))
2196 auto preShiftedSpel = KPS::sSpel( *itm );
2197 preShiftedSpel.coordinates += shiftInnerSpel;
2199 if( myKSpace.sIsInside( preShiftedSpel ) )
2201 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2203 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2204 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2205 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2207 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2217 trace.error() << "DigitalSurfaceConvolver: You need to init the convolver first." << std::endl;
2221 else /// Using lastInnerMoments
2225 /// Part to subtract from previous result.
2226 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
2228 auto preShiftedSpel = KPS::sSpel( *itm );
2229 preShiftedSpel.coordinates += shiftInnerSpel - diffSpel;
2231 if( myKSpace.sIsInside( preShiftedSpel ) )
2233 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2235 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2236 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2237 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2239 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2246 /// Part to add from previous result.
2247 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
2249 auto preShiftedSpel = KPS::sSpel( *itm );
2250 preShiftedSpel.coordinates += shiftInnerSpel;
2252 if( myKSpace.sIsInside( preShiftedSpel ) )
2254 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2256 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2257 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2258 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2260 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2268 /// Computation of covariance Matrix
2276 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
2277 currentOuterSpel = myKSpace.sIndirectIncident( *it, kDim );
2278 shiftOuterSpel = myKSpace.sKCoords( currentOuterSpel ) - myKernelKCoordsOrigin;
2280 ASSERT( currentInnerSpel != currentOuterSpel );
2282 diffSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( currentInnerSpel );
2290 x2y2z2 = x2 + y2 + z2;
2292 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 ) + ((( z / 2 ) + 1) * 9 );
2294 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.
2296 trace.error() << "Error - Found that inside and outside cells aren't adjacent. That's not logic.\n";
2298 else if( offset == positionOfFullKernel ) /// Full kernel in 3D. Never reached because case already considered before. It's a honeypot.
2300 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
2304 /// Part to subtract from previous result.
2305 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
2307 auto preShiftedSpel = KPS::sSpel( *itm );
2308 preShiftedSpel.coordinates += shiftOuterSpel - diffSpel;
2310 if( myKSpace.sIsInside( preShiftedSpel ) )
2312 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates
2315 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2316 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2317 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2319 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2326 /// Part to add from previous result.
2327 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
2329 auto preShiftedSpel = KPS::sSpel( *itm );
2330 preShiftedSpel.coordinates += shiftOuterSpel;
2332 if( myKSpace.sIsInside( preShiftedSpel ) )
2334 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2336 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2337 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2338 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2340 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2348 /// Computation of covariance Matrix
2353 ASSERT (( lastInnerSum != 0 )); // Maybe a problem here. Can be normal ... but needs to check twice.
2355 lastInnerSpel = currentInnerSpel;
2356 lastOuterSpel = currentOuterSpel;
2358#ifdef DGTAL_DEBUG_VERBOSE
2366template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2367template< typename SurfelIterator >
2369DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::core_evalCovarianceMatrix
2370( const SurfelIterator & it,
2371 CovarianceMatrix & innerMatrix,
2372 CovarianceMatrix & outerMatrix,
2373 bool useLastResults,
2374 Spel & lastInnerSpel,
2375 Spel & lastOuterSpel,
2376 Quantity * lastInnerMoments,
2377 Quantity * lastOuterMoments ) const
2379 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
2381 using KPS = typename KSpace::PreCellularGridSpace;
2383#ifdef DGTAL_DEBUG_VERBOSE
2384 Dimension recount = false;
2387 typedef typename Functor::Quantity FQuantity;
2388 DGtal::Dimension nbMasks = static_cast<Dimension>(myMasks->size()) - 1;
2389 DGtal::Dimension positionOfFullKernel = 13;
2391 Quantity m[ nbMoments ]; /// <! [ m000, m001, m010, m100, m011, m101, m110, m002, m020, m200 ]
2392 std::fill( m, m + nbMoments, NumberTraits< Quantity >::ZERO ); /// <! clear array
2394 Spel currentInnerSpel, currentOuterSpel;
2396 Point shiftInnerSpel, shiftOuterSpel;
2399 bool bComputed = false; /// <! if the cell has already been computed, continue to the next
2401 int x, y, z, x2, y2, z2, x2y2z2;
2402 unsigned int offset;
2406 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
2407 currentInnerSpel = myKSpace.sDirectIncident( *it, kDim ); /// Spel on the border, but inside the shape
2408 shiftInnerSpel = myKSpace.sKCoords( currentInnerSpel ) - myKernelKCoordsOrigin;
2410 /// Check if we can use previous results
2411 if( useLastResults )
2415 if( currentInnerSpel == lastInnerSpel )
2417 memcpy( m, lastInnerMoments, nbMoments * sizeof( Quantity ));
2418 computeCovarianceMatrix( m, innerMatrix );
2422 else if( currentInnerSpel == lastOuterSpel )
2424 memcpy( m, lastOuterMoments, nbMoments * sizeof( Quantity ));
2425 computeCovarianceMatrix( m, innerMatrix );
2426 memcpy( lastInnerMoments, m, nbMoments * sizeof( Quantity ));
2432 diffSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( lastInnerSpel );
2440 x2y2z2 = x2 + y2 + z2;
2442 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 ) + ((( z / 2 ) + 1 ) * 9 );
2444 if( x2y2z2 != 4 && x2y2z2 != 8 && !( x2 == 4 && y2 == 4 && z2 == 4 )) /// Previous and current cells aren't adjacent. Compute on the full kernel
2446 useLastResults = false;
2447#ifdef DGTAL_DEBUG_VERBOSE
2451 else if( offset == positionOfFullKernel ) /// Full kernel in 3D. Never reached because case already considered before. It's a honeypot.
2453 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
2457 useLastResults = true;
2464 if( !useLastResults ) /// Computation on full kernel, we have no previous results
2466 std::fill( m, m + nbMoments, NumberTraits< Quantity >::ZERO ); /// <! clear array
2468 if( isInitFullMasks )
2470 for( KernelConstIterator itm = myKernelMask->first; itm != myKernelMask->second; ++itm )
2472 auto preShiftedSpel = KPS::sSpel( *itm );
2473 preShiftedSpel.coordinates += shiftInnerSpel;
2475 if( myKSpace.sIsInside( preShiftedSpel ) )
2477 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2479 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2480 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2481 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2483 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2485 fillMoments( m, shiftedSpel, 1.0 );
2490 else if( isInitKernelAndMasks )
2492 Domain domain = myKernel->getDomain();
2493 for( typename Domain::ConstIterator itm = domain.begin(), itend = domain.end(); itm != itend; ++itm )
2495 if( myKernel->operator()( *itm ))
2497 auto preShiftedSpel = KPS::sSpel( *itm );
2498 preShiftedSpel.coordinates += shiftInnerSpel;
2500 if( myKSpace.sIsInside( preShiftedSpel ) )
2502 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2504 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2505 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2506 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2508 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2510 fillMoments( m, shiftedSpel, 1.0 );
2518 trace.error() << "DigitalSurfaceConvolver: You need to init the convolver first." << std::endl;
2522 else /// Using lastInnerMoments
2524 memcpy( m, lastInnerMoments, nbMoments * sizeof( Quantity ));
2526 /// Part to subtract from previous result.
2527 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
2529 auto preShiftedSpel = KPS::sSpel( *itm );
2530 preShiftedSpel.coordinates += shiftInnerSpel - diffSpel;
2532 if( myKSpace.sIsInside( preShiftedSpel ) )
2534 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2536 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2537 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2538 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2540 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2542 fillMoments( m, shiftedSpel, -1.0 );
2547 /// Part to add from previous result.
2548 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
2550 auto preShiftedSpel = KPS::sSpel( *itm );
2551 preShiftedSpel.coordinates += shiftInnerSpel;
2553 if( myKSpace.sIsInside( preShiftedSpel ) )
2555 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2557 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2558 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2559 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2561 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2563 fillMoments( m, shiftedSpel, 1.0 );
2569 /// Computation of covariance Matrix
2570 computeCovarianceMatrix( m, innerMatrix );
2571 memcpy( lastInnerMoments, m, nbMoments * sizeof( Quantity ));
2577 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
2578 currentOuterSpel = myKSpace.sIndirectIncident( *it, kDim );
2579 shiftOuterSpel = myKSpace.sKCoords( currentOuterSpel ) - myKernelKCoordsOrigin;
2581 ASSERT( currentInnerSpel != currentOuterSpel );
2583 diffSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( currentInnerSpel );
2591 x2y2z2 = x2 + y2 + z2;
2593 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 ) + ((( z / 2 ) + 1) * 9 );
2595 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.
2597 trace.error() << "Error - Found that inside and outside cells aren't adjacent. That's not logic.\n";
2599 else if( offset == positionOfFullKernel ) /// Full kernel in 3D. Never reached because case already considered before. It's a honeypot.
2601 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
2605 /// Part to subtract from previous result.
2606 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
2608 auto preShiftedSpel = KPS::sSpel( *itm );
2609 preShiftedSpel.coordinates += shiftOuterSpel - diffSpel;
2611 if( myKSpace.sIsInside( preShiftedSpel ) )
2613 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2615 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2616 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2617 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2619 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2621 fillMoments( m, shiftedSpel, -1.0 );
2626 /// Part to add from previous result.
2627 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
2629 auto preShiftedSpel = KPS::sSpel( *itm );
2630 preShiftedSpel.coordinates += shiftOuterSpel;
2632 if( myKSpace.sIsInside( preShiftedSpel ) )
2634 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2636 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2637 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2638 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2640 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2642 fillMoments( m, shiftedSpel, 1.0 );
2648 /// Computation of covariance Matrix
2649 computeCovarianceMatrix( m, outerMatrix );
2650 memcpy( lastOuterMoments, m, nbMoments * sizeof( Quantity ));
2653 ASSERT (( lastInnerMoments[ 0 ] != 0 )); // Maybe a problem here. Can be normal ... but needs to check twice.
2655 lastInnerSpel = currentInnerSpel;
2656 lastOuterSpel = currentOuterSpel;
2658#ifdef DGTAL_DEBUG_VERBOSE