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 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
52 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
54 DGtal::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 );
67 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
69 DGtal::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 )
84 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
87 DGtal::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;
102 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
105 DGtal::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;
120 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
121 template< typename SurfelIterator >
123 typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Quantity
124 DGtal::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 ));
137 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
138 template< typename SurfelIterator, typename EvalFunctor >
140 typename EvalFunctor::Value
141 DGtal::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 );
157 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
158 template< typename SurfelIterator, typename OutputIterator >
161 DGtal::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;
209 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
210 template< typename SurfelIterator, typename OutputIterator, typename EvalFunctor >
213 DGtal::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;
268 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
269 template< typename SurfelIterator >
271 typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::CovarianceMatrix
272 DGtal::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 ));
285 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
286 template< typename SurfelIterator, typename EvalFunctor >
288 typename EvalFunctor::Value
289 DGtal::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 );
305 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
306 template< typename SurfelIterator, typename OutputIterator >
309 DGtal::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;
357 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
358 template< typename SurfelIterator, typename OutputIterator, typename EvalFunctor >
361 DGtal::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;
415 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
418 DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::isValid() const
423 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
425 DGtal::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;
442 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
444 DGtal::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
476 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
478 DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::nbMoments = 6;
481 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
482 typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Spel
483 DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultInnerSpel = Spel();
485 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
486 typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Spel
487 DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultOuterSpel = Spel();
489 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
490 typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Quantity
491 DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultInnerMoments[ 6 ] = {Quantity(0)};
493 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
494 typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Quantity
495 DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultOuterMoments[ 6 ] = {Quantity(0)};
497 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
498 typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Quantity
499 DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultInnerSum = Quantity(0);
501 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
502 typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::Quantity
503 DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, dimension >::defaultOuterSum = Quantity(0);
505 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
506 template< typename SurfelIterator >
508 DGtal::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;
531 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel, DGtal::Dimension dimension >
532 template< typename SurfelIterator >
534 DGtal::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 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
562 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
564 DGtal::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 );
578 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel>
580 DGtal::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 )
596 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
599 DGtal::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;
614 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
617 DGtal::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;
632 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
633 template< typename SurfelIterator >
635 typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Quantity
636 DGtal::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 ));
649 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
650 template< typename SurfelIterator, typename EvalFunctor >
652 typename EvalFunctor::Value
653 DGtal::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 );
669 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
670 template< typename SurfelIterator, typename OutputIterator >
673 DGtal::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;
721 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
722 template< typename SurfelIterator, typename OutputIterator, typename EvalFunctor >
725 DGtal::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;
780 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
781 template< typename SurfelIterator >
783 typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::CovarianceMatrix
784 DGtal::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 ));
797 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
798 template< typename SurfelIterator, typename EvalFunctor >
800 typename EvalFunctor::Value
801 DGtal::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 );
817 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
818 template< typename SurfelIterator, typename OutputIterator >
821 DGtal::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;
869 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
870 template< typename SurfelIterator, typename OutputIterator, typename EvalFunctor >
873 DGtal::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;
927 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
930 DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::isValid() const
935 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
937 DGtal::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;
954 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
956 DGtal::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
981 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
983 DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::nbMoments = 6;
986 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
987 typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Spel
988 DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::defaultInnerSpel = Spel();
990 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
991 typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Spel
992 DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::defaultOuterSpel = Spel();
994 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
995 typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Quantity
996 DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::defaultInnerMoments[ 6 ] = {Quantity(0)};
998 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
999 typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Quantity
1000 DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::defaultOuterMoments[ 6 ] = {Quantity(0)};
1002 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1003 typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Quantity
1004 DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::defaultInnerSum = Quantity(0);
1006 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1007 typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::Quantity
1008 DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 2 >::defaultOuterSum = Quantity(0);
1010 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1011 template< typename SurfelIterator >
1013 DGtal::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;
1027 #ifdef DEBUG_VERBOSE
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;
1087 #ifdef DEBUG_VERBOSE
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;
1291 #ifdef DEBUG_VERBOSE
1299 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1300 template< typename SurfelIterator >
1302 DGtal::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;
1316 #ifdef DEBUG_VERBOSE
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;
1377 #ifdef DEBUG_VERBOSE
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;
1579 #ifdef DEBUG_VERBOSE
1589 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
1590 ///////////////////////////////////////////////////// 3D /////////////////////////////////////////////////////
1591 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
1593 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1595 DGtal::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 );
1609 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel>
1611 DGtal::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 )
1627 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1630 DGtal::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;
1645 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1648 DGtal::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;
1666 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1667 template< typename SurfelIterator >
1669 typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Quantity
1670 DGtal::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 ));
1683 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1684 template< typename SurfelIterator, typename EvalFunctor >
1686 typename EvalFunctor::Value
1687 DGtal::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 );
1703 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1704 template< typename SurfelIterator, typename OutputIterator >
1707 DGtal::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;
1715 #ifdef DEBUG_VERBOSE
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 )
1731 #ifdef DEBUG_VERBOSE
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 ));
1749 #ifdef DEBUG_VERBOSE
1750 std::cout << "#total cells = " << total << std::endl;
1751 std::cout << "#recount = " << recount << std::endl;
1755 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1756 template< typename SurfelIterator, typename OutputIterator, typename EvalFunctor >
1759 DGtal::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;
1768 #ifdef DEBUG_VERBOSE
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 )
1785 #ifdef DEBUG_VERBOSE
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 );
1804 #ifdef DEBUG_VERBOSE
1805 std::cout << "#total cells = " << total << std::endl;
1806 std::cout << "#recount = " << recount << std::endl;
1812 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1813 template< typename SurfelIterator >
1815 typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::CovarianceMatrix
1816 DGtal::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 ));
1829 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1830 template< typename SurfelIterator, typename EvalFunctor >
1832 typename EvalFunctor::Value
1833 DGtal::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 );
1849 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1850 template< typename SurfelIterator, typename OutputIterator >
1853 DGtal::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;
1861 #ifdef DEBUG_VERBOSE
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 )
1877 #ifdef DEBUG_VERBOSE
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 ));
1895 #ifdef DEBUG_VERBOSE
1896 std::cout << "#total cells = " << total << std::endl;
1897 std::cout << "#recount = " << recount << std::endl;
1901 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1902 template< typename SurfelIterator, typename OutputIterator, typename EvalFunctor >
1905 DGtal::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;
1914 #ifdef DEBUG_VERBOSE
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 )
1931 #ifdef DEBUG_VERBOSE
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 );
1950 #ifdef DEBUG_VERBOSE
1951 std::cout << "#total cells = " << total << std::endl;
1952 std::cout << "#recount = " << recount << std::endl;
1955 delete[] lastOuterMoments;
1956 delete[] lastInnerMoments;
1961 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1964 DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::isValid() const
1969 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1971 DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::fillMoments
1972 ( Quantity * aMomentMatrix,
1974 double direction ) const
1976 RealPoint current = myEmbedder( aSpel );
1977 double x = current[ 0 ];
1978 double y = current[ 1 ];
1979 double z = current[ 2 ];
1981 aMomentMatrix[ 0 ] += direction * 1;
1982 aMomentMatrix[ 1 ] += direction * z;
1983 aMomentMatrix[ 2 ] += direction * y;
1984 aMomentMatrix[ 3 ] += direction * x;
1985 aMomentMatrix[ 4 ] += direction * y * z;
1986 aMomentMatrix[ 5 ] += direction * x * z;
1987 aMomentMatrix[ 6 ] += direction * x * y;
1988 aMomentMatrix[ 7 ] += direction * z * z;
1989 aMomentMatrix[ 8 ] += direction * y * y;
1990 aMomentMatrix[ 9 ] += direction * x * x;
1995 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
1997 DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::computeCovarianceMatrix
1998 ( const Quantity * aMomentMatrix,
1999 CovarianceMatrix & aCovarianceMatrix ) const
2005 A.setComponent( 0, 0, aMomentMatrix[ 9 ] );
2006 A.setComponent( 0, 1, aMomentMatrix[ 6 ] );
2007 A.setComponent( 0, 2, aMomentMatrix[ 5 ] );
2008 A.setComponent( 1, 0, aMomentMatrix[ 6 ] );
2009 A.setComponent( 1, 1, aMomentMatrix[ 8 ] );
2010 A.setComponent( 1, 2, aMomentMatrix[ 4 ] );
2011 A.setComponent( 2, 0, aMomentMatrix[ 5 ] );
2012 A.setComponent( 2, 1, aMomentMatrix[ 4 ] );
2013 A.setComponent( 2, 2, aMomentMatrix[ 7 ] );
2015 B = 1.0 / aMomentMatrix[ 0 ];
2017 C.setComponent( 0, 0, aMomentMatrix[ 3 ] * aMomentMatrix[ 3 ] );
2018 C.setComponent( 0, 1, aMomentMatrix[ 3 ] * aMomentMatrix[ 2 ] );
2019 C.setComponent( 0, 2, aMomentMatrix[ 3 ] * aMomentMatrix[ 1 ] );
2020 C.setComponent( 1, 0, aMomentMatrix[ 2 ] * aMomentMatrix[ 3 ] );
2021 C.setComponent( 1, 1, aMomentMatrix[ 2 ] * aMomentMatrix[ 2 ] );
2022 C.setComponent( 1, 2, aMomentMatrix[ 2 ] * aMomentMatrix[ 1 ] );
2023 C.setComponent( 2, 0, aMomentMatrix[ 1 ] * aMomentMatrix[ 3 ] );
2024 C.setComponent( 2, 1, aMomentMatrix[ 1 ] * aMomentMatrix[ 2 ] );
2025 C.setComponent( 2, 2, aMomentMatrix[ 1 ] * aMomentMatrix[ 1 ] );
2027 aCovarianceMatrix = A - C * B;
2031 // For Visual Studio, to be defined as a static const, it has to be intialized into the header file
2032 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2034 DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::nbMoments = 10;
2037 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2038 typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Spel
2039 DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::defaultInnerSpel = Spel();
2041 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2042 typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Spel
2043 DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::defaultOuterSpel = Spel();
2045 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2046 typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Quantity
2047 DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::defaultInnerMoments[ 10 ] = {Quantity(0)};
2049 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2050 typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Quantity
2051 DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::defaultOuterMoments[ 10 ] = {Quantity(0)};
2053 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2054 typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Quantity
2055 DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::defaultInnerSum = Quantity(0);
2057 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2058 typename DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::Quantity
2059 DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::defaultOuterSum = Quantity(0);
2061 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2062 template< typename SurfelIterator >
2064 DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::core_eval
2065 ( const SurfelIterator & it,
2066 Quantity & innerSum,
2067 Quantity & outerSum,
2068 bool useLastResults,
2069 Spel & lastInnerSpel,
2070 Spel & lastOuterSpel,
2071 Quantity & lastInnerSum,
2072 Quantity & lastOuterSum ) const
2074 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
2076 using KPS = typename KSpace::PreCellularGridSpace;
2078 #ifdef DEBUG_VERBOSE
2079 Dimension recount = false;
2082 typedef typename Functor::Quantity FQuantity;
2083 DGtal::Dimension nbMasks = static_cast<DGtal::Dimension>(myMasks->size()) - 1;
2084 DGtal::Dimension positionOfFullKernel = 13;
2086 Quantity m = NumberTraits< Quantity >::ZERO;
2088 Spel currentInnerSpel, currentOuterSpel;
2090 Point shiftInnerSpel, shiftOuterSpel;
2093 bool bComputed = false; /// <! if the cell has already been computed, continue to the next
2095 int x, y, z, x2, y2, z2, x2y2z2;
2096 unsigned int offset;
2100 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
2101 currentInnerSpel = myKSpace.sDirectIncident( *it, kDim ); /// Spel on the border, but inside the shape
2102 shiftInnerSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( myKernelSpelOrigin );
2104 /// Check if we can use previous results
2105 if( useLastResults )
2109 if( currentInnerSpel == lastInnerSpel )
2116 else if( currentInnerSpel == lastOuterSpel )
2125 diffSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( lastInnerSpel );
2133 x2y2z2 = x2 + y2 + z2;
2135 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 ) + ((( z / 2 ) + 1 ) * 9 );
2137 if( x2y2z2 != 4 && x2y2z2 != 8 && !( x2 == 4 && y2 == 4 && z2 == 4 )) /// Previous and current cells aren't adjacent. Compute on the full kernel
2139 useLastResults = false;
2140 #ifdef DEBUG_VERBOSE
2144 else if( offset == positionOfFullKernel ) /// Full kernel in 3D. Never reached because case already considered before. It's a honeypot.
2146 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
2150 useLastResults = true;
2157 if( !useLastResults ) /// Computation on full kernel, we have no previous results
2159 m = NumberTraits< Quantity >::ZERO;
2161 if( isInitFullMasks )
2163 for( KernelConstIterator itm = myKernelMask->first; itm != myKernelMask->second; ++itm )
2165 auto preShiftedSpel = KPS::sSpel( *itm );
2166 preShiftedSpel.coordinates += shiftInnerSpel;
2168 if( myKSpace.sIsInside( preShiftedSpel ) )
2170 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2172 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2173 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2174 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2176 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2183 else if( isInitKernelAndMasks )
2185 Domain domain = myKernel->getDomain();
2186 for( typename Domain::ConstIterator itm = domain.begin(), itend = domain.end(); itm != itend; ++itm )
2188 if( myKernel->operator()( *itm ))
2190 auto preShiftedSpel = KPS::sSpel( *itm );
2191 preShiftedSpel.coordinates += shiftInnerSpel;
2193 if( myKSpace.sIsInside( preShiftedSpel ) )
2195 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2197 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2198 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2199 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2201 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2211 trace.error() << "DigitalSurfaceConvolver: You need to init the convolver first." << std::endl;
2215 else /// Using lastInnerMoments
2219 /// Part to substract from previous result.
2220 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
2222 auto preShiftedSpel = KPS::sSpel( *itm );
2223 preShiftedSpel.coordinates += shiftInnerSpel - diffSpel;
2225 if( myKSpace.sIsInside( preShiftedSpel ) )
2227 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2229 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2230 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2231 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2233 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2240 /// Part to add from previous result.
2241 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
2243 auto preShiftedSpel = KPS::sSpel( *itm );
2244 preShiftedSpel.coordinates += shiftInnerSpel;
2246 if( myKSpace.sIsInside( preShiftedSpel ) )
2248 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2250 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2251 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2252 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2254 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2262 /// Computation of covariance Matrix
2270 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
2271 currentOuterSpel = myKSpace.sIndirectIncident( *it, kDim );
2272 shiftOuterSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( myKernelSpelOrigin );
2274 ASSERT( currentInnerSpel != currentOuterSpel );
2276 diffSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( currentInnerSpel );
2284 x2y2z2 = x2 + y2 + z2;
2286 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 ) + ((( z / 2 ) + 1) * 9 );
2288 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.
2290 trace.error() << "Error - Found that inside and outside cells aren't adjacent. That's not logic.\n";
2292 else if( offset == positionOfFullKernel ) /// Full kernel in 3D. Never reached because case already considered before. It's a honeypot.
2294 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
2298 /// Part to substract from previous result.
2299 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
2301 auto preShiftedSpel = KPS::sSpel( *itm );
2302 preShiftedSpel.coordinates += shiftOuterSpel - diffSpel;
2304 if( myKSpace.sIsInside( preShiftedSpel ) )
2306 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates
2309 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2310 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2311 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2313 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2320 /// Part to add from previous result.
2321 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
2323 auto preShiftedSpel = KPS::sSpel( *itm );
2324 preShiftedSpel.coordinates += shiftOuterSpel;
2326 if( myKSpace.sIsInside( preShiftedSpel ) )
2328 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2330 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2331 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2332 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2334 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2342 /// Computation of covariance Matrix
2347 ASSERT (( lastInnerSum != 0 )); // Maybe a problem here. Can be normal ... but needs to check twice.
2349 lastInnerSpel = currentInnerSpel;
2350 lastOuterSpel = currentOuterSpel;
2352 #ifdef DEBUG_VERBOSE
2360 template< typename Functor, typename KernelFunctor, typename KSpace, typename DigitalKernel >
2361 template< typename SurfelIterator >
2363 DGtal::DigitalSurfaceConvolver< Functor, KernelFunctor, KSpace, DigitalKernel, 3 >::core_evalCovarianceMatrix
2364 ( const SurfelIterator & it,
2365 CovarianceMatrix & innerMatrix,
2366 CovarianceMatrix & outerMatrix,
2367 bool useLastResults,
2368 Spel & lastInnerSpel,
2369 Spel & lastOuterSpel,
2370 Quantity * lastInnerMoments,
2371 Quantity * lastOuterMoments ) const
2373 ASSERT ( isInitFullMasks == true || isInitKernelAndMasks == true );
2375 using KPS = typename KSpace::PreCellularGridSpace;
2377 #ifdef DEBUG_VERBOSE
2378 Dimension recount = false;
2381 typedef typename Functor::Quantity FQuantity;
2382 DGtal::Dimension nbMasks = static_cast<Dimension>(myMasks->size()) - 1;
2383 DGtal::Dimension positionOfFullKernel = 13;
2385 Quantity m[ nbMoments ]; /// <! [ m000, m001, m010, m100, m011, m101, m110, m002, m020, m200 ]
2386 std::fill( m, m + nbMoments, NumberTraits< Quantity >::ZERO ); /// <! clear array
2388 Spel currentInnerSpel, currentOuterSpel;
2390 Point shiftInnerSpel, shiftOuterSpel;
2393 bool bComputed = false; /// <! if the cell has already been computed, continue to the next
2395 int x, y, z, x2, y2, z2, x2y2z2;
2396 unsigned int offset;
2400 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
2401 currentInnerSpel = myKSpace.sDirectIncident( *it, kDim ); /// Spel on the border, but inside the shape
2402 shiftInnerSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( myKernelSpelOrigin );
2404 /// Check if we can use previous results
2405 if( useLastResults )
2409 if( currentInnerSpel == lastInnerSpel )
2411 memcpy( m, lastInnerMoments, nbMoments * sizeof( Quantity ));
2412 computeCovarianceMatrix( m, innerMatrix );
2416 else if( currentInnerSpel == lastOuterSpel )
2418 memcpy( m, lastOuterMoments, nbMoments * sizeof( Quantity ));
2419 computeCovarianceMatrix( m, outerMatrix );
2425 diffSpel = myKSpace.sKCoords( currentInnerSpel ) - myKSpace.sKCoords( lastInnerSpel );
2433 x2y2z2 = x2 + y2 + z2;
2435 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 ) + ((( z / 2 ) + 1 ) * 9 );
2437 if( x2y2z2 != 4 && x2y2z2 != 8 && !( x2 == 4 && y2 == 4 && z2 == 4 )) /// Previous and current cells aren't adjacent. Compute on the full kernel
2439 useLastResults = false;
2440 #ifdef DEBUG_VERBOSE
2444 else if( offset == positionOfFullKernel ) /// Full kernel in 3D. Never reached because case already considered before. It's a honeypot.
2446 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
2450 useLastResults = true;
2457 if( !useLastResults ) /// Computation on full kernel, we have no previous results
2459 std::fill( m, m + nbMoments, NumberTraits< Quantity >::ZERO ); /// <! clear array
2461 if( isInitFullMasks )
2463 for( KernelConstIterator itm = myKernelMask->first; itm != myKernelMask->second; ++itm )
2465 auto preShiftedSpel = KPS::sSpel( *itm );
2466 preShiftedSpel.coordinates += shiftInnerSpel;
2468 if( myKSpace.sIsInside( preShiftedSpel ) )
2470 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2472 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2473 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2474 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2476 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2478 fillMoments( m, shiftedSpel, 1.0 );
2483 else if( isInitKernelAndMasks )
2485 Domain domain = myKernel->getDomain();
2486 for( typename Domain::ConstIterator itm = domain.begin(), itend = domain.end(); itm != itend; ++itm )
2488 if( myKernel->operator()( *itm ))
2490 auto preShiftedSpel = KPS::sSpel( *itm );
2491 preShiftedSpel.coordinates += shiftInnerSpel;
2493 if( myKSpace.sIsInside( preShiftedSpel ) )
2495 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2497 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2498 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2499 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2501 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2503 fillMoments( m, shiftedSpel, 1.0 );
2511 trace.error() << "DigitalSurfaceConvolver: You need to init the convolver first." << std::endl;
2515 else /// Using lastInnerMoments
2517 memcpy( m, lastInnerMoments, nbMoments * sizeof( Quantity ));
2519 /// Part to substract from previous result.
2520 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
2522 auto preShiftedSpel = KPS::sSpel( *itm );
2523 preShiftedSpel.coordinates += shiftInnerSpel - diffSpel;
2525 if( myKSpace.sIsInside( preShiftedSpel ) )
2527 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2529 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2530 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2531 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2533 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2535 fillMoments( m, shiftedSpel, -1.0 );
2540 /// Part to add from previous result.
2541 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
2543 auto preShiftedSpel = KPS::sSpel( *itm );
2544 preShiftedSpel.coordinates += shiftInnerSpel;
2546 if( myKSpace.sIsInside( preShiftedSpel ) )
2548 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2550 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2551 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2552 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2554 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2556 fillMoments( m, shiftedSpel, 1.0 );
2562 /// Computation of covariance Matrix
2563 computeCovarianceMatrix( m, innerMatrix );
2564 memcpy( lastInnerMoments, m, nbMoments * sizeof( Quantity ));
2570 DGtal::Dimension kDim = myKSpace.sOrthDir( *it );
2571 currentOuterSpel = myKSpace.sIndirectIncident( *it, kDim );
2572 shiftOuterSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( myKernelSpelOrigin );
2574 ASSERT( currentInnerSpel != currentOuterSpel );
2576 diffSpel = myKSpace.sKCoords( currentOuterSpel ) - myKSpace.sKCoords( currentInnerSpel );
2584 x2y2z2 = x2 + y2 + z2;
2586 offset = (( x / 2 ) + 1 ) + ((( y / 2 ) + 1 ) * 3 ) + ((( z / 2 ) + 1) * 9 );
2588 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.
2590 trace.error() << "Error - Found that inside and outside cells aren't adjacent. That's not logic.\n";
2592 else if( offset == positionOfFullKernel ) /// Full kernel in 3D. Never reached because case already considered before. It's a honeypot.
2594 trace.error() << "Error - Ask to compute full kernel at the wrong moment. Maybe it's an offset computation bug ?\n";
2598 /// Part to substract from previous result.
2599 for( KernelConstIterator itm = (*myMasks)[ offset ].first, itend = (*myMasks)[ offset ].second; itm != itend; ++itm )
2601 auto preShiftedSpel = KPS::sSpel( *itm );
2602 preShiftedSpel.coordinates += shiftOuterSpel - diffSpel;
2604 if( myKSpace.sIsInside( preShiftedSpel ) )
2606 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2608 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2609 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2610 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2612 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2614 fillMoments( m, shiftedSpel, -1.0 );
2619 /// Part to add from previous result.
2620 for( KernelConstIterator itm = (*myMasks)[ nbMasks - offset ].first, itend = (*myMasks)[ nbMasks - offset ].second; itm != itend; ++itm )
2622 auto preShiftedSpel = KPS::sSpel( *itm );
2623 preShiftedSpel.coordinates += shiftOuterSpel;
2625 if( myKSpace.sIsInside( preShiftedSpel ) )
2627 myKSpace.sSetKCoords( shiftedSpel, preShiftedSpel.coordinates );
2629 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 0 ] & 0x1 );
2630 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 1 ] & 0x1 );
2631 ASSERT( myKSpace.sKCoords( shiftedSpel )[ 2 ] & 0x1 );
2633 if( myFFunctor( shiftedSpel ) != NumberTraits< FQuantity >::ZERO )
2635 fillMoments( m, shiftedSpel, 1.0 );
2641 /// Computation of covariance Matrix
2642 computeCovarianceMatrix( m, outerMatrix );
2643 memcpy( lastOuterMoments, m, nbMoments * sizeof( Quantity ));
2646 ASSERT (( lastInnerMoments[ 0 ] != 0 )); // Maybe a problem here. Can be normal ... but needs to check twice.
2648 lastInnerSpel = currentInnerSpel;
2649 lastOuterSpel = currentOuterSpel;
2651 #ifdef DEBUG_VERBOSE