DGtal  0.9.2
KhalimskySpaceND.ih
1 /**
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.
6  *
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.
11  *
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/>.
14  *
15  **/
16 
17 /**
18  * @file KhalimskySpaceND.ih
19  * @author Jacques-Olivier Lachaud (\c jacques-olivier.lachaud@univ-savoie.fr )
20  * Laboratory of Mathematics (CNRS, UMR 5807), University of Savoie, France
21  *
22  * @date 2011/02/08
23  *
24  * Implementation of inline methods defined in KhalimskySpaceND.h
25  *
26  * This file is part of the DGtal library.
27  */
28 
29 
30 //////////////////////////////////////////////////////////////////////////////
31 #include <DGtal/io/Color.h>
32 #include <DGtal/kernel/NumberTraits.h>
33 //////////////////////////////////////////////////////////////////////////////
34 
35 ///////////////////////////////////////////////////////////////////////////////
36 // IMPLEMENTATION of inline methods.
37 ///////////////////////////////////////////////////////////////////////////////
38 
39 ///////////////////////////////////////////////////////////////////////////////
40 // KhalimskyCell
41 ///////////////////////////////////////////////////////////////////////////////
42 //-----------------------------------------------------------------------------
43 template < DGtal::Dimension dim, typename TInteger >
44 inline
45 DGtal::KhalimskyCell< dim, TInteger >::
46 KhalimskyCell( Integer )
47  : myPreCell()
48 {
49 }
50 //-----------------------------------------------------------------------------
51 template < DGtal::Dimension dim, typename TInteger >
52 inline
53 DGtal::KhalimskyCell< dim, TInteger >::
54 KhalimskyCell( const Point & p )
55  : myPreCell( p )
56 {
57 }
58 //-----------------------------------------------------------------------------
59 template < DGtal::Dimension dim, typename TInteger >
60 inline
61 DGtal::KhalimskyCell< dim, TInteger >::
62 KhalimskyCell( const PreCell & aCell )
63  : myPreCell( aCell )
64 {
65 }
66 //-----------------------------------------------------------------------------
67 template < DGtal::Dimension dim, typename TInteger >
68 inline
69 DGtal::KhalimskyCell< dim, TInteger >::
70 operator DGtal::KhalimskyPreCell< dim, TInteger > const& () const
71 {
72  return myPreCell;
73 }
74 //-----------------------------------------------------------------------------
75 template < DGtal::Dimension dim, typename TInteger >
76 inline
77 DGtal::KhalimskyPreCell< dim, TInteger > const &
78 DGtal::KhalimskyCell< dim, TInteger >::
79 preCell () const
80 {
81  return myPreCell;
82 }
83 //-----------------------------------------------------------------------------
84 template < DGtal::Dimension dim, typename TInteger >
85 inline
86 DGtal::KhalimskyCell< dim, TInteger >::
87 operator DGtal::KhalimskyPreCell< dim, TInteger > & ()
88 {
89  return myPreCell;
90 }
91 //-----------------------------------------------------------------------------
92 template < DGtal::Dimension dim, typename TInteger >
93 inline
94 bool
95 DGtal::KhalimskyCell< dim, TInteger >::
96 operator==( const KhalimskyCell & other ) const
97 {
98  return myPreCell == other.myPreCell;
99 }
100 //-----------------------------------------------------------------------------
101 template < DGtal::Dimension dim, typename TInteger >
102 inline
103 bool
104 DGtal::KhalimskyCell< dim, TInteger >::
105 operator!=( const KhalimskyCell & other ) const
106 {
107  return myPreCell != other.myPreCell;
108 }
109 //-----------------------------------------------------------------------------
110 template < DGtal::Dimension dim, typename TInteger >
111 inline
112 bool
113 DGtal::KhalimskyCell< dim, TInteger >::
114 operator<( const KhalimskyCell & other ) const
115 {
116  return myPreCell < other.myPreCell;
117 }
118 //-----------------------------------------------------------------------------
119 template < DGtal::Dimension dim, typename TInteger >
120 inline
121 std::ostream &
122 DGtal::operator<<( std::ostream & out,
123  const KhalimskyCell< dim, TInteger > & object )
124 {
125  out << static_cast< const KhalimskyPreCell<dim, TInteger> & >(object);
126  return out;
127 }
128 
129 //------------------------------------------------------------------------------
130 template < DGtal::Dimension dim, typename TInteger >
131 inline
132 std::string
133 DGtal::KhalimskyCell<dim, TInteger>::
134 className() const
135 {
136  return "KhalimskyCell";
137 }
138 
139 ///////////////////////////////////////////////////////////////////////////////
140 // SignedKhalimskyCell
141 ///////////////////////////////////////////////////////////////////////////////
142 //-----------------------------------------------------------------------------
143 template < DGtal::Dimension dim, typename TInteger >
144 inline
145 DGtal::SignedKhalimskyCell< dim, TInteger >::
146 SignedKhalimskyCell( Integer )
147  : mySPreCell()
148 {
149 }
150 //-----------------------------------------------------------------------------
151 template < DGtal::Dimension dim, typename TInteger >
152 inline
153 DGtal::SignedKhalimskyCell< dim, TInteger >::
154 SignedKhalimskyCell( const Point & p, bool positive )
155  : mySPreCell( p, positive )
156 {
157 }
158 //-----------------------------------------------------------------------------
159 template < DGtal::Dimension dim, typename TInteger >
160 inline
161 DGtal::SignedKhalimskyCell< dim, TInteger >::
162 SignedKhalimskyCell( const SPreCell & aCell )
163  : mySPreCell( aCell )
164 {
165 }
166 //-----------------------------------------------------------------------------
167 template < DGtal::Dimension dim, typename TInteger >
168 inline
169 DGtal::SignedKhalimskyCell< dim, TInteger >::
170 operator DGtal::SignedKhalimskyPreCell< dim, TInteger > const& () const
171 {
172  return mySPreCell;
173 }
174 //-----------------------------------------------------------------------------
175 template < DGtal::Dimension dim, typename TInteger >
176 inline
177 DGtal::SignedKhalimskyPreCell< dim, TInteger > const &
178 DGtal::SignedKhalimskyCell< dim, TInteger >::
179 preCell() const
180 {
181  return mySPreCell;
182 }
183 //-----------------------------------------------------------------------------
184 template < DGtal::Dimension dim, typename TInteger >
185 inline
186 DGtal::SignedKhalimskyCell< dim, TInteger >::
187 operator DGtal::SignedKhalimskyPreCell< dim, TInteger > & ()
188 {
189  return mySPreCell;
190 }
191 //-----------------------------------------------------------------------------
192 template < DGtal::Dimension dim, typename TInteger >
193 inline
194 bool
195 DGtal::SignedKhalimskyCell< dim, TInteger >::
196 operator==( const SignedKhalimskyCell & other ) const
197 {
198  return mySPreCell == other.mySPreCell;
199 }
200 //-----------------------------------------------------------------------------
201 template < DGtal::Dimension dim, typename TInteger >
202 inline
203 bool
204 DGtal::SignedKhalimskyCell< dim, TInteger >::
205 operator!=( const SignedKhalimskyCell & other ) const
206 {
207  return mySPreCell != other.mySPreCell;
208 }
209 //-----------------------------------------------------------------------------
210 template < DGtal::Dimension dim, typename TInteger >
211 inline
212 bool
213 DGtal::SignedKhalimskyCell< dim, TInteger >::
214 operator<( const SignedKhalimskyCell & other ) const
215 {
216  return mySPreCell < other.mySPreCell;
217 }
218 //-----------------------------------------------------------------------------
219 template < DGtal::Dimension dim,
220  typename TInteger >
221 inline
222 std::ostream &
223 DGtal::operator<<( std::ostream & out,
224  const SignedKhalimskyCell< dim, TInteger > & object )
225 {
226  out << static_cast< const SignedKhalimskyPreCell<dim, TInteger> & >(object);
227  return out;
228 }
229 
230 //------------------------------------------------------------------------------
231 template < DGtal::Dimension dim, typename TInteger >
232 inline
233 std::string
234 DGtal::SignedKhalimskyCell<dim, TInteger>::
235 className() const
236 {
237  return "SignedKhalimskyCell";
238 }
239 
240 ///////////////////////////////////////////////////////////////////////////////
241 // KhalimskySpaceNDHelper
242 ///////////////////////////////////////////////////////////////////////////////
243 namespace DGtal
244 {
245 
246 template <
247  DGtal::Dimension dim,
248  typename TInteger
249 >
250 class KhalimskySpaceNDHelper< KhalimskySpaceND< dim, TInteger > >
251 {
252 private:
253  // Private typedefs
254  using KhalimskySpace = KhalimskySpaceND< dim, TInteger >;
255  using Point = PointVector< dim, TInteger >;
256  using Cell = KhalimskyCell< dim, TInteger >;
257  using SCell = SignedKhalimskyCell< dim, TInteger >;
258 
259  /// Returns derived mutable instance
260  KhalimskySpace& derived()
261  {
262  return *static_cast<KhalimskySpace*>(this);
263  }
264 
265  /// Returns derived constant instance
266  KhalimskySpace const & derived() const
267  {
268  return *static_cast<KhalimskySpace const*>(this);
269  }
270 
271 
272 public:
273  // Provided helpers
274 
275  /// @return true is the specified dimension is periodic
276  inline
277  bool isDimensionPeriodicHelper( DGtal::Dimension d ) const
278  {
279  return derived().myClosure[ d ] == KhalimskySpace::PERIODIC;
280  }
281 
282  /// @return true is there is at least one periodic dimension.
283  inline
284  bool isAnyDimensionPeriodicHelper() const
285  {
286  return myIsAnyDimensionPeriodic;
287  }
288 
289  /** Modifies a khalimsky coordinate according to the dimension periodicity.
290  * @param[in,out] aKCoord the coordinate to modify.
291  * @param d the coordinate dimension.
292  */
293  inline
294  void updateKCoordHelper( typename Point::Coordinate & aKCoord, DGtal::Dimension d ) const
295  {
296  if ( isDimensionPeriodicHelper( d ) )
297  {
298  aKCoord = ( aKCoord - derived().myCellLower.myPreCell.coordinates[ d ] ) % myCellExtent[ d ];
299  aKCoord += ( ( aKCoord < 0 ) ?
300  derived().myCellUpper.myPreCell.coordinates[ d ] + 1
301  : derived().myCellLower.myPreCell.coordinates[ d ]
302  );
303  }
304  }
305 
306  /** Returns a given khalimsky coordinate modified according to the dimension periodicity.
307  * @param[in] aKCoord the coordinate to modify.
308  * @param d the coordinate dimension.
309  * @returns the modified coordinate.
310  */
311  inline
312  typename Point::Coordinate returnKCoordHelper( typename Point::Coordinate aKCoord, DGtal::Dimension d ) const
313  {
314  updateKCoordHelper( aKCoord, d );
315  return aKCoord;
316  }
317 
318  /** Modifies khalimsky coordinates of a point according to the dimension periodicity.
319  * @param[in,out] aKCoords the khalimksy coordinates.
320  */
321  inline
322  void updateKCoordsHelper( Point & aKCoords ) const
323  {
324  if ( isAnyDimensionPeriodicHelper() )
325  {
326  for ( DGtal::Dimension i = 0; i < dim; ++i )
327  updateKCoordHelper( aKCoords[ i ], i );
328  }
329  }
330 
331  /** Returns given khalimsky coordinates of a point modified according to the dimension periodicity.
332  * @param[in] aKCoords the khalimksy coordinates.
333  */
334  inline
335  Point returnKCoordsHelper( Point aKCoords ) const
336  {
337  updateKCoordsHelper( aKCoords );
338  return aKCoords;
339  }
340 
341  /** Modifies a cell's khalimsky coordinate according to the dimension periodicity.
342  * @param[in,out] aCell an unsigned cell.
343  * @param d the coordinate dimension.
344  */
345  inline
346  void updateCellHelper( Cell & aCell, DGtal::Dimension d ) const
347  {
348  updateKCoordHelper( aCell.myPreCell.coordinates[ d ], d );
349  }
350 
351  /** Modifies a cell's khalimsky coordinates according to the dimension periodicity.
352  * @param[in,out] aCell an unsigned cell.
353  */
354  inline
355  void updateCellHelper( Cell & aCell ) const
356  {
357  updateKCoordsHelper( aCell.myPreCell.coordinates );
358  }
359 
360  /** Modifies a cell's khalimsky coordinate according to the dimension periodicity.
361  * @param[in,out] aCell a signed cell.
362  * @param d the coordinate dimension.
363  */
364  inline
365  void updateSCellHelper( SCell & aCell, DGtal::Dimension d ) const
366  {
367  updateKCoordHelper( aCell.mySPreCell.coordinates[ d ], d );
368  }
369 
370  /** Modifies a cell's khalimsky coordinates according to the dimension periodicity.
371  * @param[in,out] aCell a signed cell.
372  */
373  inline
374  void updateSCellHelper( SCell & aCell ) const
375  {
376  updateKCoordsHelper( aCell.mySPreCell.coordinates );
377  }
378 
379 public:
380  /// Initialization
381  bool initHelper()
382  {
383  myIsAnyDimensionPeriodic = false;
384  for ( DGtal::Dimension i = 0; i < dim; ++i )
385  {
386  myIsAnyDimensionPeriodic |= isDimensionPeriodicHelper( i );
387  myCellExtent[ i ] = derived().myCellUpper.myPreCell.coordinates[ i ] - derived().myCellLower.myPreCell.coordinates[ i ] + 1;
388  }
389 
390  return true;
391  }
392 
393 
394 private:
395  // Optimization data
396  Point myCellExtent; ///< Extent between the extremal cells.
397  bool myIsAnyDimensionPeriodic; ///< true if there is at least one periodic dimension.
398 };
399 
400 } // namespace DGtal
401 
402 ///////////////////////////////////////////////////////////////////////////////
403 // KhalimskySpaceND
404 ///////////////////////////////////////////////////////////////////////////////
405 ///////////////////////////////////////////////////////////////////////////////
406 // ----------------------- Standard services ------------------------------
407 //-----------------------------------------------------------------------------
408 template < DGtal::Dimension dim, typename TInteger>
409 inline
410 DGtal::KhalimskySpaceND< dim, TInteger>::
411 ~KhalimskySpaceND()
412 {
413 }
414 //-----------------------------------------------------------------------------
415 template < DGtal::Dimension dim, typename TInteger>
416 inline
417 DGtal::KhalimskySpaceND< dim, TInteger>::
418 KhalimskySpaceND()
419 {
420  Point low, high;
421  for ( DGtal::Dimension i = 0; i < dimension; ++i )
422  {
423  low[ i ] = NumberTraits< Integer >::min() / 2 + 1;
424  high[ i ] = NumberTraits< Integer >::max() / 2 - 1;
425  }
426  init( low, high, true );
427 }
428 //-----------------------------------------------------------------------------
429 template < DGtal::Dimension dim, typename TInteger>
430 inline
431 bool
432 DGtal::KhalimskySpaceND< dim, TInteger>::
433 init( const Point & lower,
434  const Point & upper,
435  bool isClosed )
436 {
437  std::array<Closure, dimension> closure;
438  for ( DGtal::Dimension i = 0; i < dimension; ++i )
439  closure[ i ] = isClosed ? CLOSED : OPEN;
440 
441  return init( lower, upper, closure );
442 }
443 //-----------------------------------------------------------------------------
444 template < DGtal::Dimension dim, typename TInteger>
445 inline
446 bool
447 DGtal::KhalimskySpaceND< dim, TInteger>::
448 init( const Point & lower,
449  const Point & upper,
450  Closure closure )
451 {
452  std::array<Closure, dimension> dimClosure;
453  dimClosure.fill( closure );
454 
455  return init( lower, upper, dimClosure );
456 }
457 
458 //-----------------------------------------------------------------------------
459 template < DGtal::Dimension dim, typename TInteger>
460 inline
461 bool
462 DGtal::KhalimskySpaceND< dim, TInteger>::
463 init( const Point & lower,
464  const Point & upper,
465  const std::array<Closure, dim> & closure )
466 {
467  myLower = lower;
468  myUpper = upper;
469  myClosure = closure;
470 
471  if ( NumberTraits< Integer >::isBounded() == BOUNDED )
472  {
473  for ( DGtal::Dimension i = 0; i < dimension; ++i )
474  {
475  if ( ( lower[ i ] <= ( NumberTraits< Integer >::min() / 2 ) )
476  || ( upper[ i ] >= ( NumberTraits< Integer >::max() / 2 ) ) )
477  return false;
478  }
479  }
480 
481  for ( DGtal::Dimension i = 0; i < dimension; ++i )
482  {
483  PreCellularGridSpace::uSetKCoord( myCellLower.myPreCell, i, ( lower[ i ] * 2 ) + ( closure[ i ] != OPEN ? 0 : 1 ) );
484  PreCellularGridSpace::uSetKCoord( myCellUpper.myPreCell, i, ( upper[ i ] * 2 ) + ( closure[ i ] == CLOSED ? 2 : 1 ) );
485 
486  }
487 
488  return this->initHelper();
489 }
490 //-----------------------------------------------------------------------------
491 template < DGtal::Dimension dim, typename TInteger>
492 inline
493 typename DGtal::KhalimskySpaceND< dim, TInteger>::Size
494 DGtal::KhalimskySpaceND< dim, TInteger>::
495 size( DGtal::Dimension k ) const
496 {
497  ASSERT( k < dimension );
498  return myUpper[ k ] + NumberTraits<Integer>::ONE - myLower[ k ];
499 }
500 //-----------------------------------------------------------------------------
501 template < DGtal::Dimension dim, typename TInteger>
502 inline
503 TInteger
504 DGtal::KhalimskySpaceND< dim, TInteger>::
505 min( DGtal::Dimension k ) const
506 {
507  return myLower[ k ];
508 }
509 //-----------------------------------------------------------------------------
510 template < DGtal::Dimension dim, typename TInteger>
511 inline
512 TInteger
513 DGtal::KhalimskySpaceND< dim, TInteger>::
514 max( DGtal::Dimension k ) const
515 {
516  return myUpper[ k ];
517 }
518 //-----------------------------------------------------------------------------
519 template < DGtal::Dimension dim, typename TInteger>
520 inline
521 const typename DGtal::KhalimskySpaceND< dim, TInteger>::Point &
522 DGtal::KhalimskySpaceND< dim, TInteger>::
523 lowerBound() const
524 {
525  return myLower;
526 }
527 //-----------------------------------------------------------------------------
528 template < DGtal::Dimension dim, typename TInteger>
529 inline
530 const typename DGtal::KhalimskySpaceND< dim, TInteger>::Point &
531 DGtal::KhalimskySpaceND< dim, TInteger>::
532 upperBound() const
533 {
534  return myUpper;
535 }
536 //-----------------------------------------------------------------------------
537 template < DGtal::Dimension dim, typename TInteger>
538 inline
539 const typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell &
540 DGtal::KhalimskySpaceND< dim, TInteger>::
541 lowerCell() const
542 {
543  return myCellLower;
544 }
545 //-----------------------------------------------------------------------------
546 template < DGtal::Dimension dim, typename TInteger>
547 inline
548 const typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell &
549 DGtal::KhalimskySpaceND< dim, TInteger>::
550 upperCell() const
551 {
552  return myCellUpper;
553 }
554 //-----------------------------------------------------------------------------
555 template < DGtal::Dimension dim, typename TInteger>
556 inline
557 bool
558 DGtal::KhalimskySpaceND< dim, TInteger>::
559 uIsValid( const PreCell & p, Dimension k ) const
560 {
561  return cIsValid( p.coordinates, k );
562 }
563 //-----------------------------------------------------------------------------
564 template < DGtal::Dimension dim, typename TInteger>
565 inline
566 bool
567 DGtal::KhalimskySpaceND< dim, TInteger>::
568 uIsValid( const PreCell & p ) const
569 {
570  return cIsValid( p.coordinates );
571 }
572 //-----------------------------------------------------------------------------
573 template < DGtal::Dimension dim, typename TInteger>
574 inline
575 bool
576 DGtal::KhalimskySpaceND< dim, TInteger>::
577 cIsValid( const Point & p, Dimension k ) const
578 {
579  return p[ k ] <= PreCellularGridSpace::uKCoord( myCellUpper, k )
580  && p[ k ] >= PreCellularGridSpace::uKCoord( myCellLower, k );
581 }
582 //-----------------------------------------------------------------------------
583 template < DGtal::Dimension dim, typename TInteger>
584 inline
585 bool
586 DGtal::KhalimskySpaceND< dim, TInteger>::
587 cIsValid( const Point & p ) const
588 {
589  for ( Dimension k = 0; k < DIM; ++ k )
590  if ( ! cIsValid( p, k ) )
591  return false;
592 
593  return true;
594 }
595 //-----------------------------------------------------------------------------
596 template < DGtal::Dimension dim, typename TInteger>
597 inline
598 bool
599 DGtal::KhalimskySpaceND< dim, TInteger>::
600 sIsValid( const SPreCell & p, Dimension k ) const
601 {
602  return cIsValid( p.coordinates, k );
603 }
604 //-----------------------------------------------------------------------------
605 template < DGtal::Dimension dim, typename TInteger>
606 inline
607 bool
608 DGtal::KhalimskySpaceND< dim, TInteger>::
609 sIsValid( const SPreCell & p ) const
610 {
611  return cIsValid( p.coordinates );
612 }
613 //-----------------------------------------------------------------------------
614 template < DGtal::Dimension dim, typename TInteger>
615 inline
616 bool
617 DGtal::KhalimskySpaceND< dim, TInteger>::
618 isSpaceClosed() const
619 {
620  for ( Dimension i = 0; i < dimension; ++i )
621  if ( myClosure[ i ] == OPEN )
622  return false;
623 
624  return true;
625 }
626 //-----------------------------------------------------------------------------
627 template < DGtal::Dimension dim, typename TInteger>
628 inline
629 bool
630 DGtal::KhalimskySpaceND< dim, TInteger>::
631 isSpaceClosed( Dimension k ) const
632 {
633  return myClosure[ k ] != OPEN;
634 }
635 //-----------------------------------------------------------------------------
636 template < DGtal::Dimension dim, typename TInteger>
637 inline
638 bool
639 DGtal::KhalimskySpaceND< dim, TInteger>::
640 isSpacePeriodic() const
641 {
642  for ( Dimension i = 0; i < dimension; ++i )
643  if ( myClosure[ i ] != PERIODIC )
644  return false;
645 
646  return true;
647 }
648 //-----------------------------------------------------------------------------
649 template < DGtal::Dimension dim, typename TInteger>
650 inline
651 bool
652 DGtal::KhalimskySpaceND< dim, TInteger>::
653 isSpacePeriodic( Dimension k ) const
654 {
655  return myClosure[ k ] == PERIODIC;
656 }
657 //-----------------------------------------------------------------------------
658 template < DGtal::Dimension dim, typename TInteger>
659 inline
660 bool
661 DGtal::KhalimskySpaceND< dim, TInteger>::
662 isAnyDimensionPeriodic() const
663 {
664  return this->isAnyDimensionPeriodicHelper();
665 }
666 //-----------------------------------------------------------------------------
667 template < DGtal::Dimension dim, typename TInteger>
668 inline
669 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
670 DGtal::KhalimskySpaceND< dim, TInteger>::
671 uCell( const PreCell & c ) const
672 {
673  return uCell( c.coordinates );
674 }
675 //-----------------------------------------------------------------------------
676 template < DGtal::Dimension dim, typename TInteger>
677 inline
678 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
679 DGtal::KhalimskySpaceND< dim, TInteger>::
680 uCell( const Point & kp ) const
681 {
682  ASSERT( cIsInside( kp ) );
683  return Cell( this->returnKCoordsHelper( kp ) );
684 }
685 //-----------------------------------------------------------------------------
686 template < DGtal::Dimension dim, typename TInteger>
687 inline
688 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
689 DGtal::KhalimskySpaceND< dim, TInteger>::
690 uCell( Point p, const PreCell & c ) const
691 {
692  return uCell( PreCellularGridSpace::uCell( p, c ) );
693 }
694 //-----------------------------------------------------------------------------
695 template < DGtal::Dimension dim, typename TInteger>
696 inline
697 typename DGtal::KhalimskySpaceND< dim, TInteger>::SCell
698 DGtal::KhalimskySpaceND< dim, TInteger>::
699 sCell( const SPreCell & c ) const
700 {
701  return sCell( c.coordinates, c.positive ? POS : NEG );
702 }
703 //-----------------------------------------------------------------------------
704 template < DGtal::Dimension dim, typename TInteger>
705 inline
706 typename DGtal::KhalimskySpaceND< dim, TInteger>::SCell
707 DGtal::KhalimskySpaceND< dim, TInteger>::
708 sCell( const Point & kp, Sign sign ) const
709 {
710  ASSERT( cIsInside( kp ) );
711  return SCell( this->returnKCoordsHelper( kp ), sign == POS );
712 }
713 //-----------------------------------------------------------------------------
714 template < DGtal::Dimension dim, typename TInteger>
715 inline
716 typename DGtal::KhalimskySpaceND< dim, TInteger>::SCell
717 DGtal::KhalimskySpaceND< dim, TInteger>::
718 sCell( Point p, const SPreCell & c ) const
719 {
720  return sCell( PreCellularGridSpace::sCell( p, c ) );
721 }
722 //-----------------------------------------------------------------------------
723 template < DGtal::Dimension dim, typename TInteger>
724 inline
725 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
726 DGtal::KhalimskySpaceND< dim, TInteger>::
727 uSpel( Point p ) const
728 {
729  return uCell( PreCellularGridSpace::uSpel( p ) );
730 }
731 //-----------------------------------------------------------------------------
732 template < DGtal::Dimension dim, typename TInteger>
733 inline
734 typename DGtal::KhalimskySpaceND< dim, TInteger>::SCell
735 DGtal::KhalimskySpaceND< dim, TInteger>::
736 sSpel( Point p, Sign sign ) const
737 {
738  return sCell( PreCellularGridSpace::sSpel( p, sign ) );
739 }
740 //-----------------------------------------------------------------------------
741 template < DGtal::Dimension dim, typename TInteger>
742 inline
743 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
744 DGtal::KhalimskySpaceND< dim, TInteger>::
745 uPointel( Point p ) const
746 {
747  return uCell( PreCellularGridSpace::uPointel( p ) );
748 }
749 //-----------------------------------------------------------------------------
750 template < DGtal::Dimension dim, typename TInteger>
751 inline
752 typename DGtal::KhalimskySpaceND< dim, TInteger>::SCell
753 DGtal::KhalimskySpaceND< dim, TInteger>::
754 sPointel( Point p, Sign sign ) const
755 {
756  return sCell( PreCellularGridSpace::sPointel( p, sign ) );
757 }
758 //-----------------------------------------------------------------------------
759 ///////////////////////////////////////////////////////////////////////////////
760 //-----------------------------------------------------------------------------
761 template < DGtal::Dimension dim, typename TInteger>
762 inline
763 typename DGtal::KhalimskySpaceND< dim, TInteger>::Integer
764 DGtal::KhalimskySpaceND< dim, TInteger>::
765 uKCoord( const Cell & c, DGtal::Dimension k ) const
766 {
767  ASSERT( uIsValid(c) );
768  return PreCellularGridSpace::uKCoord( c, k );
769 }
770 //-----------------------------------------------------------------------------
771 template < DGtal::Dimension dim, typename TInteger>
772 inline
773 typename DGtal::KhalimskySpaceND< dim, TInteger>::Integer
774 DGtal::KhalimskySpaceND< dim, TInteger>::
775 uCoord( const Cell & c, DGtal::Dimension k ) const
776 {
777  ASSERT( uIsValid(c) );
778  return PreCellularGridSpace::uCoord( c, k );
779 }
780 //-----------------------------------------------------------------------------
781 template < DGtal::Dimension dim, typename TInteger>
782 inline
783 typename DGtal::KhalimskySpaceND< dim, TInteger>::Point const &
784 DGtal::KhalimskySpaceND< dim, TInteger>::
785 uKCoords( const Cell & c ) const
786 {
787  ASSERT( uIsValid(c) );
788  return PreCellularGridSpace::uKCoords( c );
789 }
790 //-----------------------------------------------------------------------------
791 template < DGtal::Dimension dim, typename TInteger>
792 inline
793 typename DGtal::KhalimskySpaceND< dim, TInteger>::Point
794 DGtal::KhalimskySpaceND< dim, TInteger>::
795 uCoords( const Cell & c ) const
796 {
797  ASSERT( uIsValid(c) );
798  return PreCellularGridSpace::uCoords( c );
799 }
800 //-----------------------------------------------------------------------------
801 template < DGtal::Dimension dim, typename TInteger>
802 inline
803 typename DGtal::KhalimskySpaceND< dim, TInteger>::Integer
804 DGtal::KhalimskySpaceND< dim, TInteger>::
805 sKCoord( const SCell & c, DGtal::Dimension k ) const
806 {
807  ASSERT( sIsValid(c) );
808  return PreCellularGridSpace::sKCoord( c, k );
809 }
810 //-----------------------------------------------------------------------------
811 template < DGtal::Dimension dim, typename TInteger>
812 inline
813 typename DGtal::KhalimskySpaceND< dim, TInteger>::Integer
814 DGtal::KhalimskySpaceND< dim, TInteger>::
815 sCoord( const SCell & c, DGtal::Dimension k ) const
816 {
817  ASSERT( sIsValid(c) );
818  return PreCellularGridSpace::sCoord( c, k );
819 }
820 //-----------------------------------------------------------------------------
821 template < DGtal::Dimension dim, typename TInteger>
822 inline
823 typename DGtal::KhalimskySpaceND< dim, TInteger>::Point const &
824 DGtal::KhalimskySpaceND< dim, TInteger>::
825 sKCoords( const SCell & c ) const
826 {
827  ASSERT( sIsValid(c) );
828  return PreCellularGridSpace::sKCoords( c );
829 }
830 //-----------------------------------------------------------------------------
831 template < DGtal::Dimension dim, typename TInteger>
832 inline
833 typename DGtal::KhalimskySpaceND< dim, TInteger>::Point
834 DGtal::KhalimskySpaceND< dim, TInteger>::
835 sCoords( const SCell & c ) const
836 {
837  ASSERT( sIsValid(c) );
838  return PreCellularGridSpace::sCoords( c );
839 }
840 //-----------------------------------------------------------------------------
841 template < DGtal::Dimension dim, typename TInteger>
842 inline
843 typename DGtal::KhalimskySpaceND< dim, TInteger>::Sign
844 DGtal::KhalimskySpaceND< dim, TInteger>::
845 sSign( const SCell & c ) const
846 {
847  ASSERT( sIsValid(c) );
848  return PreCellularGridSpace::sSign( c );
849 }
850 //-----------------------------------------------------------------------------
851 template < DGtal::Dimension dim, typename TInteger>
852 inline
853 typename DGtal::KhalimskySpaceND< dim, TInteger>::SCell
854 DGtal::KhalimskySpaceND< dim, TInteger>::
855 signs( const Cell & p, Sign s ) const
856 {
857  return sCell( PreCellularGridSpace::signs( p, s ) );
858 }
859 //-----------------------------------------------------------------------------
860 template < DGtal::Dimension dim, typename TInteger>
861 inline
862 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
863 DGtal::KhalimskySpaceND< dim, TInteger>::
864 unsigns( const SCell & p ) const
865 {
866  return uCell( PreCellularGridSpace::unsigns( p ) );
867 }
868 //-----------------------------------------------------------------------------
869 template < DGtal::Dimension dim, typename TInteger>
870 inline
871 typename DGtal::KhalimskySpaceND< dim, TInteger>::SCell
872 DGtal::KhalimskySpaceND< dim, TInteger>::
873 sOpp( const SCell & p ) const
874 {
875  return sCell( PreCellularGridSpace::sOpp( p ) );
876 }
877 //-----------------------------------------------------------------------------
878 template < DGtal::Dimension dim, typename TInteger>
879 inline
880 void
881 DGtal::KhalimskySpaceND< dim, TInteger>::
882 uSetKCoord( Cell & c, DGtal::Dimension k, Integer i ) const
883 {
884  PreCellularGridSpace::uSetKCoord( c.myPreCell, k, i );
885  this->updateCellHelper( c, k );
886  ASSERT( uIsValid(c) );
887 }
888 //-----------------------------------------------------------------------------
889 template < DGtal::Dimension dim, typename TInteger>
890 inline
891 void
892 DGtal::KhalimskySpaceND< dim, TInteger>::
893 sSetKCoord( SCell & c, DGtal::Dimension k, Integer i ) const
894 {
895  PreCellularGridSpace::sSetKCoord( c.mySPreCell, k, i );
896  this->updateSCellHelper( c, k );
897  ASSERT( sIsValid(c) );
898 }
899 //-----------------------------------------------------------------------------
900 template < DGtal::Dimension dim, typename TInteger>
901 inline
902 void
903 DGtal::KhalimskySpaceND< dim, TInteger>::
904 uSetCoord( Cell & c, DGtal::Dimension k, Integer i ) const
905 {
906  PreCellularGridSpace::uSetCoord( c.myPreCell, k, i );
907  this->updateCellHelper( c, k );
908  ASSERT( uIsValid(c) );
909 }
910 //-----------------------------------------------------------------------------
911 template < DGtal::Dimension dim, typename TInteger>
912 inline
913 void
914 DGtal::KhalimskySpaceND< dim, TInteger>::
915 sSetCoord( SCell & c, DGtal::Dimension k, Integer i ) const
916 {
917  PreCellularGridSpace::sSetCoord( c.mySPreCell, k, i );
918  this->updateSCellHelper( c, k );
919  ASSERT( sIsValid(c) );
920 }
921 //-----------------------------------------------------------------------------
922 template < DGtal::Dimension dim, typename TInteger>
923 inline
924 void
925 DGtal::KhalimskySpaceND< dim, TInteger>::
926 uSetKCoords( Cell & c, const Point & kp ) const
927 {
928  PreCellularGridSpace::uSetKCoords( c.myPreCell, kp );
929  this->updateCellHelper( c );
930  ASSERT( uIsValid(c) );
931 }
932 //-----------------------------------------------------------------------------
933 template < DGtal::Dimension dim, typename TInteger>
934 inline
935 void
936 DGtal::KhalimskySpaceND< dim, TInteger>::
937 sSetKCoords( SCell & c, const Point & kp ) const
938 {
939  PreCellularGridSpace::sSetKCoords( c.mySPreCell, kp );
940  this->updateSCellHelper( c );
941  ASSERT( sIsValid(c) );
942 }
943 //-----------------------------------------------------------------------------
944 template < DGtal::Dimension dim, typename TInteger>
945 inline
946 void
947 DGtal::KhalimskySpaceND< dim, TInteger>::
948 uSetCoords( Cell & c, const Point & p ) const
949 {
950  PreCellularGridSpace::uSetCoords( c.myPreCell, p );
951  this->updateCellHelper( c );
952  ASSERT( uIsValid(c) );
953 }
954 //-----------------------------------------------------------------------------
955 template < DGtal::Dimension dim, typename TInteger>
956 inline
957 void
958 DGtal::KhalimskySpaceND< dim, TInteger>::
959 sSetCoords( SCell & c, const Point & p ) const
960 {
961  PreCellularGridSpace::sSetCoords( c.mySPreCell, p );
962  this->updateSCellHelper( c );
963  ASSERT( sIsValid(c) );
964 }
965 //-----------------------------------------------------------------------------
966 template < DGtal::Dimension dim, typename TInteger>
967 inline
968 void
969 DGtal::KhalimskySpaceND< dim, TInteger>::
970 sSetSign( SCell & c, Sign s ) const
971 {
972  PreCellularGridSpace::sSetSign( c.mySPreCell, s );
973 }
974 //-----------------------------------------------------------------------------
975 // ------------------------- Cell topology services -----------------------
976 //-----------------------------------------------------------------------------
977 template < DGtal::Dimension dim, typename TInteger>
978 inline
979 TInteger
980 DGtal::KhalimskySpaceND< dim, TInteger>::
981 uTopology( const Cell & p ) const
982 {
983  return PreCellularGridSpace::uTopology( p );
984 }
985 //-----------------------------------------------------------------------------
986 template < DGtal::Dimension dim, typename TInteger>
987 inline
988 TInteger
989 DGtal::KhalimskySpaceND< dim, TInteger>::
990 sTopology( const SCell & p ) const
991 {
992  return PreCellularGridSpace::sTopology( p );
993 }
994 //-----------------------------------------------------------------------------
995 template < DGtal::Dimension dim, typename TInteger>
996 inline
997 DGtal::Dimension
998 DGtal::KhalimskySpaceND< dim, TInteger>::
999 uDim( const Cell & p ) const
1000 {
1001  return PreCellularGridSpace::uDim( p );
1002 }
1003 //-----------------------------------------------------------------------------
1004 template < DGtal::Dimension dim, typename TInteger>
1005 inline
1006 DGtal::Dimension
1007 DGtal::KhalimskySpaceND< dim, TInteger>::
1008 sDim( const SCell & p ) const
1009 {
1010  return PreCellularGridSpace::sDim( p );
1011 }
1012 //-----------------------------------------------------------------------------
1013 template < DGtal::Dimension dim, typename TInteger>
1014 inline
1015 bool
1016 DGtal::KhalimskySpaceND< dim, TInteger>::
1017 uIsSurfel( const Cell & b ) const
1018 {
1019  return PreCellularGridSpace::uIsSurfel( b );
1020 }
1021 //-----------------------------------------------------------------------------
1022 template < DGtal::Dimension dim, typename TInteger>
1023 inline
1024 bool
1025 DGtal::KhalimskySpaceND< dim, TInteger>::
1026 sIsSurfel( const SCell & b ) const
1027 {
1028  return PreCellularGridSpace::sIsSurfel( b );
1029 }
1030 //-----------------------------------------------------------------------------
1031 template < DGtal::Dimension dim, typename TInteger>
1032 inline
1033 bool
1034 DGtal::KhalimskySpaceND< dim, TInteger>::
1035 uIsOpen( const Cell & p, DGtal::Dimension k ) const
1036 {
1037  return PreCellularGridSpace::uIsOpen( p, k );
1038 }
1039 //-----------------------------------------------------------------------------
1040 template < DGtal::Dimension dim, typename TInteger>
1041 inline
1042 bool
1043 DGtal::KhalimskySpaceND< dim, TInteger>::
1044 sIsOpen( const SCell & p, DGtal::Dimension k ) const
1045 {
1046  return PreCellularGridSpace::sIsOpen( p, k );
1047 }
1048 
1049 //-----------------------------------------------------------------------------
1050 ///////////////////////////////////////////////////////////////////////////////
1051 //-----------------------------------------------------------------------------
1052 template < DGtal::Dimension dim, typename TInteger>
1053 inline
1054 typename DGtal::KhalimskySpaceND< dim, TInteger>::DirIterator
1055 DGtal::KhalimskySpaceND< dim, TInteger>::
1056 uDirs( const Cell & p ) const
1057 {
1058  return PreCellularGridSpace::uDirs( p );
1059 }
1060 //-----------------------------------------------------------------------------
1061 template < DGtal::Dimension dim, typename TInteger>
1062 inline
1063 typename DGtal::KhalimskySpaceND< dim, TInteger>::DirIterator
1064 DGtal::KhalimskySpaceND< dim, TInteger>::
1065 sDirs( const SCell & p ) const
1066 {
1067  return PreCellularGridSpace::sDirs( p );
1068 }
1069 //-----------------------------------------------------------------------------
1070 template < DGtal::Dimension dim, typename TInteger>
1071 inline
1072 typename DGtal::KhalimskySpaceND< dim, TInteger>::DirIterator
1073 DGtal::KhalimskySpaceND< dim, TInteger>::
1074 uOrthDirs( const Cell & p ) const
1075 {
1076  return PreCellularGridSpace::uOrthDirs( p );
1077 }
1078 //-----------------------------------------------------------------------------
1079 template < DGtal::Dimension dim, typename TInteger>
1080 inline
1081 typename DGtal::KhalimskySpaceND< dim, TInteger>::DirIterator
1082 DGtal::KhalimskySpaceND< dim, TInteger>::
1083 sOrthDirs( const SCell & p ) const
1084 {
1085  return PreCellularGridSpace::sOrthDirs( p );
1086 }
1087 //-----------------------------------------------------------------------------
1088 template < DGtal::Dimension dim, typename TInteger>
1089 inline
1090 DGtal::Dimension
1091 DGtal::KhalimskySpaceND< dim, TInteger>::
1092 uOrthDir( const Cell & s ) const
1093 {
1094  return PreCellularGridSpace::uOrthDir( s );
1095 }
1096 //-----------------------------------------------------------------------------
1097 template < DGtal::Dimension dim, typename TInteger>
1098 inline
1099 DGtal::Dimension
1100 DGtal::KhalimskySpaceND< dim, TInteger>::
1101 sOrthDir( const SCell & s ) const
1102 {
1103  return PreCellularGridSpace::sOrthDir( s );
1104 }
1105 //-----------------------------------------------------------------------------
1106 ///////////////////////////////////////////////////////////////////////////////
1107 //-----------------------------------------------------------------------------
1108 //-----------------------------------------------------------------------------
1109 template < DGtal::Dimension dim, typename TInteger>
1110 inline
1111 typename DGtal::KhalimskySpaceND< dim, TInteger>::Integer
1112 DGtal::KhalimskySpaceND< dim, TInteger>::
1113 uFirst( const PreCell & p, DGtal::Dimension k ) const
1114 {
1115  ASSERT( k < DIM );
1116 
1117  return myClosure[ k ] == OPEN ?
1118  2 * myLower[ k ] + ( NumberTraits<Integer>::odd( p.coordinates[ k ] ) ? 1 : 2 )
1119  : 2 * myLower[ k ] + ( NumberTraits<Integer>::odd( p.coordinates[ k ] ) ? 1 : 0 );
1120 }
1121 //-----------------------------------------------------------------------------
1122 template < DGtal::Dimension dim, typename TInteger>
1123 inline
1124 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
1125 DGtal::KhalimskySpaceND< dim, TInteger>::
1126 uFirst( const PreCell & p ) const
1127 {
1128  Cell cell;
1129  for ( Dimension k = 0; k < dimension; ++k )
1130  PreCellularGridSpace::uSetKCoord( cell.myPreCell, k, uFirst( p, k ) );
1131 
1132  return cell;
1133 }
1134 //-----------------------------------------------------------------------------
1135 template < DGtal::Dimension dim, typename TInteger>
1136 inline
1137 typename DGtal::KhalimskySpaceND< dim, TInteger>::Integer
1138 DGtal::KhalimskySpaceND< dim, TInteger>::
1139 uLast( const PreCell & p, DGtal::Dimension k ) const
1140 {
1141  ASSERT( k < DIM );
1142 
1143  return myClosure[ k ] == CLOSED ?
1144  2 * myUpper[ k ] + ( NumberTraits<Integer>::odd( p.coordinates[ k ] ) ? 1 : 2 )
1145  : 2 * myUpper[ k ] + ( NumberTraits<Integer>::odd( p.coordinates[ k ] ) ? 1 : 0 );
1146 }
1147 //-----------------------------------------------------------------------------
1148 template < DGtal::Dimension dim, typename TInteger>
1149 inline
1150 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
1151 DGtal::KhalimskySpaceND< dim, TInteger>::
1152 uLast( const PreCell & p ) const
1153 {
1154  Cell cell;
1155  for ( Dimension k = 0; k < dimension; ++k )
1156  PreCellularGridSpace::uSetKCoord( cell.myPreCell, k, uLast( p, k ) );
1157 
1158  return cell;
1159 }
1160 //-----------------------------------------------------------------------------
1161 template < DGtal::Dimension dim, typename TInteger>
1162 inline
1163 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
1164 DGtal::KhalimskySpaceND< dim, TInteger>::
1165 uGetIncr( const Cell & p, DGtal::Dimension k ) const
1166 {
1167  Cell cell( PreCellularGridSpace::uGetIncr( p, k ) );
1168  this->updateCellHelper( cell, k );
1169  ASSERT( uIsValid(cell) );
1170  return cell;
1171 }
1172 //-----------------------------------------------------------------------------
1173 template < DGtal::Dimension dim, typename TInteger>
1174 inline
1175 bool
1176 DGtal::KhalimskySpaceND< dim, TInteger>::
1177 uIsMax( const Cell & p, DGtal::Dimension k ) const
1178 {
1179  ASSERT( k < DIM );
1180  ASSERT( uIsInside(p) );
1181  return
1182  ! this->isDimensionPeriodicHelper( k )
1183  && PreCellularGridSpace::uKCoord( p, k ) >= uLast( p, k );
1184 }
1185 //-----------------------------------------------------------------------------
1186 template < DGtal::Dimension dim, typename TInteger>
1187 inline
1188 bool
1189 DGtal::KhalimskySpaceND< dim, TInteger>::
1190 uIsInside( const PreCell & p, DGtal::Dimension k ) const
1191 {
1192  return cIsInside( p.coordinates, k );
1193 }
1194 //-----------------------------------------------------------------------------
1195 template < DGtal::Dimension dim, typename TInteger>
1196 inline
1197 bool
1198 DGtal::KhalimskySpaceND< dim, TInteger>::
1199 uIsInside( const PreCell & p ) const
1200 {
1201  return cIsInside( p.coordinates );
1202 }
1203 //-----------------------------------------------------------------------------
1204 template < DGtal::Dimension dim, typename TInteger>
1205 inline
1206 bool
1207 DGtal::KhalimskySpaceND< dim, TInteger>::
1208 cIsInside( const Point & p, DGtal::Dimension k ) const
1209 {
1210  ASSERT( k < DIM );
1211  return this->isDimensionPeriodicHelper( k )
1212  || cIsValid( p, k );
1213 }
1214 //-----------------------------------------------------------------------------
1215 template < DGtal::Dimension dim, typename TInteger>
1216 inline
1217 bool
1218 DGtal::KhalimskySpaceND< dim, TInteger>::
1219 cIsInside( const Point & p ) const
1220 {
1221  for ( Dimension k = 0; k < DIM; ++k )
1222  if ( ! cIsInside( p, k ) )
1223  return false;
1224 
1225  return true;
1226 }
1227 //-----------------------------------------------------------------------------
1228 template < DGtal::Dimension dim, typename TInteger>
1229 inline
1230 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
1231 DGtal::KhalimskySpaceND< dim, TInteger>::
1232 uGetMax( Cell p, DGtal::Dimension k ) const
1233 {
1234  PreCellularGridSpace::uSetKCoord( p.myPreCell, k, uLast( p, k ) );
1235  ASSERT( uIsValid( p ) );
1236  return p;
1237 }
1238 //-----------------------------------------------------------------------------
1239 template < DGtal::Dimension dim, typename TInteger>
1240 inline
1241 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
1242 DGtal::KhalimskySpaceND< dim, TInteger>::
1243 uGetDecr( const Cell & p, DGtal::Dimension k ) const
1244 {
1245  Cell cell( PreCellularGridSpace::uGetDecr( p, k ) );
1246  this->updateCellHelper( cell, k );
1247  ASSERT( uIsValid( cell ) );
1248  return cell;
1249 }
1250 //-----------------------------------------------------------------------------
1251 template < DGtal::Dimension dim, typename TInteger>
1252 inline
1253 bool
1254 DGtal::KhalimskySpaceND< dim, TInteger>::
1255 uIsMin( const Cell & p, DGtal::Dimension k ) const
1256 {
1257  ASSERT( uIsInside(p) );
1258  return
1259  ! this->isDimensionPeriodicHelper( k )
1260  && PreCellularGridSpace::uKCoord( p, k ) <= uFirst( p, k );
1261 }
1262 //-----------------------------------------------------------------------------
1263 template < DGtal::Dimension dim, typename TInteger>
1264 inline
1265 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
1266 DGtal::KhalimskySpaceND< dim, TInteger>::
1267 uGetMin( Cell p, DGtal::Dimension k ) const
1268 {
1269  PreCellularGridSpace::uSetKCoord( p.myPreCell, k, uFirst( p, k ) );
1270  ASSERT( uIsValid(p) );
1271  return p;
1272 }
1273 //-----------------------------------------------------------------------------
1274 template < DGtal::Dimension dim, typename TInteger>
1275 inline
1276 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
1277 DGtal::KhalimskySpaceND< dim, TInteger>::
1278 uGetAdd( const Cell & p, DGtal::Dimension k, Integer x ) const
1279 {
1280  Cell cell( PreCellularGridSpace::uGetAdd( p, k, x ) );
1281  this->updateCellHelper( cell, k );
1282  ASSERT( uIsValid( cell ) );
1283  return cell;
1284 }
1285 //-----------------------------------------------------------------------------
1286 template < DGtal::Dimension dim, typename TInteger>
1287 inline
1288 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
1289 DGtal::KhalimskySpaceND< dim, TInteger>::
1290 uGetSub( const Cell & p, DGtal::Dimension k, Integer x ) const
1291 {
1292  Cell cell( PreCellularGridSpace::uGetSub( p, k, x ) );
1293  this->updateCellHelper( cell, k );
1294  ASSERT( uIsValid( cell ) );
1295  return cell;
1296 }
1297 //-----------------------------------------------------------------------------
1298 template < DGtal::Dimension dim, typename TInteger>
1299 inline
1300 TInteger
1301 DGtal::KhalimskySpaceND< dim, TInteger>::
1302 uDistanceToMax( const Cell & p, DGtal::Dimension k ) const
1303 {
1304  using KPS = PreCellularGridSpace;
1305  ASSERT( k < DIM );
1306  ASSERT( uIsValid(p) );
1307  return ( KPS::uKCoord( myCellUpper, k ) - KPS::uKCoord( p, k ) ) >> 1;
1308 }
1309 //-----------------------------------------------------------------------------
1310 template < DGtal::Dimension dim, typename TInteger>
1311 inline
1312 TInteger
1313 DGtal::KhalimskySpaceND< dim, TInteger>::
1314 uDistanceToMin( const Cell & p, DGtal::Dimension k ) const
1315 {
1316  using KPS = PreCellularGridSpace;
1317  ASSERT( k < DIM );
1318  ASSERT( uIsValid(p) );
1319  return ( KPS::uKCoord( p, k ) - KPS::uKCoord( myCellLower, k ) ) >> 1;
1320 }
1321 //-----------------------------------------------------------------------------
1322 template < DGtal::Dimension dim, typename TInteger>
1323 inline
1324 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
1325 DGtal::KhalimskySpaceND< dim, TInteger>::
1326 uTranslation( const Cell & p, const Vector & vec ) const
1327 {
1328  Cell cell( PreCellularGridSpace::uTranslation( p, vec ) );
1329  this->updateCellHelper( cell );
1330  ASSERT( uIsValid( cell ) );
1331  return cell;
1332 }
1333 //-----------------------------------------------------------------------------
1334 template < DGtal::Dimension dim, typename TInteger>
1335 inline
1336 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
1337 DGtal::KhalimskySpaceND< dim, TInteger>::
1338 uProjection( const Cell & p, const Cell & bound, DGtal::Dimension k ) const
1339 {
1340  Cell cell( PreCellularGridSpace::uProjection( p, bound, k ) );
1341  ASSERT( uIsValid( cell ) );
1342  return cell;
1343 }
1344 //-----------------------------------------------------------------------------
1345 template < DGtal::Dimension dim, typename TInteger>
1346 inline
1347 void
1348 DGtal::KhalimskySpaceND< dim, TInteger>::
1349 uProject( Cell & p, const Cell & bound, DGtal::Dimension k ) const
1350 {
1351  PreCellularGridSpace::uProject( p.myPreCell, bound, k );
1352  ASSERT( uIsValid( p ) );
1353 }
1354 //-----------------------------------------------------------------------------
1355 template < DGtal::Dimension dim, typename TInteger>
1356 inline
1357 bool
1358 DGtal::KhalimskySpaceND< dim, TInteger>::
1359 uNext( Cell & p, const Cell & lower, const Cell & upper ) const
1360 {
1361  ASSERT( uIsValid(p) );
1362  ASSERT( uIsValid(lower) );
1363  ASSERT( uIsValid(upper) );
1364  ASSERT( uTopology(p) == uTopology(lower)
1365  && uTopology(p) == uTopology(upper) );
1366 
1367  using KPS = PreCellularGridSpace;
1368 
1369  DGtal::Dimension k = NumberTraits<Dimension>::ZERO;
1370  if ( KPS::uKCoord( p, k ) == KPS::uKCoord( upper, k ) )
1371  {
1372  if ( p == upper ) return false;
1373  KPS::uProject( p.myPreCell, lower, k );
1374 
1375  for ( k = 1; k < DIM; ++k )
1376  {
1377  if ( KPS::uKCoord( p, k ) == KPS::uKCoord( upper, k ) )
1378  KPS::uProject( p.myPreCell, lower, k );
1379  else
1380  {
1381  KPS::uSetKCoord( p.myPreCell, k, this->returnKCoordHelper( KPS::uKCoord( p, k ) + 2, k ) );
1382  break;
1383  }
1384  }
1385  return true;
1386  }
1387 
1388  KPS::uSetKCoord( p.myPreCell, k, this->returnKCoordHelper( KPS::uKCoord( p, k ) + 2, k ) );
1389  return true;
1390 }
1391 
1392 //-----------------------------------------------------------------------------
1393 ///////////////////////////////////////////////////////////////////////////////
1394 //-----------------------------------------------------------------------------
1395 //-----------------------------------------------------------------------------
1396 template < DGtal::Dimension dim, typename TInteger>
1397 inline
1398 typename DGtal::KhalimskySpaceND< dim, TInteger>::Integer
1399 DGtal::KhalimskySpaceND< dim, TInteger>::
1400 sFirst( const SPreCell & p, DGtal::Dimension k ) const
1401 {
1402  ASSERT( k < DIM );
1403 
1404  return myClosure[ k ] == OPEN ?
1405  2 * myLower[ k ] + ( NumberTraits<Integer>::odd( p.coordinates[ k ] ) ? 1 : 2 )
1406  : 2 * myLower[ k ] + ( NumberTraits<Integer>::odd( p.coordinates[ k ] ) ? 1 : 0 );
1407 }
1408 //-----------------------------------------------------------------------------
1409 template < DGtal::Dimension dim, typename TInteger>
1410 inline
1411 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCell
1412 DGtal::KhalimskySpaceND< dim, TInteger >::
1413 sFirst( const SPreCell & p ) const
1414 {
1415  SCell cell;
1416  for ( Dimension k = 0; k < dimension; ++k )
1417  PreCellularGridSpace::sSetKCoord( cell.mySPreCell, k, sFirst( p, k ) );
1418 
1419  PreCellularGridSpace::sSetSign( cell.mySPreCell, PreCellularGridSpace::sSign( p ) );
1420 
1421  return cell;
1422 }
1423 //-----------------------------------------------------------------------------
1424 template < DGtal::Dimension dim, typename TInteger>
1425 inline
1426 typename DGtal::KhalimskySpaceND< dim, TInteger>::Integer
1427 DGtal::KhalimskySpaceND< dim, TInteger>::
1428 sLast( const SPreCell & p, DGtal::Dimension k ) const
1429 {
1430  ASSERT( k < DIM );
1431  return myClosure[ k ] == CLOSED ?
1432  2 * myUpper[ k ] + ( NumberTraits<Integer>::odd( p.coordinates[ k ] ) ? 1 : 2 )
1433  : 2 * myUpper[ k ] + ( NumberTraits<Integer>::odd( p.coordinates[ k ] ) ? 1 : 0 );
1434 }
1435 //-----------------------------------------------------------------------------
1436 template < DGtal::Dimension dim, typename TInteger>
1437 inline
1438 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCell
1439 DGtal::KhalimskySpaceND< dim, TInteger >::
1440 sLast( const SPreCell & p ) const
1441 {
1442  SCell cell;
1443  for ( Dimension k = 0; k < dimension; ++k )
1444  PreCellularGridSpace::sSetKCoord( cell.mySPreCell, k, sLast( p, k ) );
1445 
1446  PreCellularGridSpace::sSetSign( cell.mySPreCell, PreCellularGridSpace::sSign( p ) );
1447 
1448  return cell;
1449 }
1450 //-----------------------------------------------------------------------------
1451 template < DGtal::Dimension dim, typename TInteger>
1452 inline
1453 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCell
1454 DGtal::KhalimskySpaceND< dim, TInteger >::
1455 sGetIncr( const SCell & p, DGtal::Dimension k ) const
1456 {
1457  SCell cell( PreCellularGridSpace::sGetIncr( p, k ) );
1458  this->updateSCellHelper( cell, k );
1459  ASSERT( sIsValid( cell ) );
1460  return cell;
1461 }
1462 //-----------------------------------------------------------------------------
1463 template < DGtal::Dimension dim, typename TInteger>
1464 inline
1465 bool
1466 DGtal::KhalimskySpaceND< dim, TInteger >::
1467 sIsMax( const SCell & p, DGtal::Dimension k ) const
1468 {
1469  ASSERT( k < DIM );
1470  ASSERT( sIsInside(p) );
1471  return
1472  ! this->isDimensionPeriodicHelper( k )
1473  && PreCellularGridSpace::sKCoord( p, k ) >= sLast( p, k );
1474 }
1475 //-----------------------------------------------------------------------------
1476 template < DGtal::Dimension dim, typename TInteger>
1477 inline
1478 bool
1479 DGtal::KhalimskySpaceND< dim, TInteger>::
1480 sIsInside( const SPreCell & p, DGtal::Dimension k ) const
1481 {
1482  return cIsInside( p.coordinates, k );
1483 }
1484 //-----------------------------------------------------------------------------
1485 template < DGtal::Dimension dim, typename TInteger>
1486 inline
1487 bool
1488 DGtal::KhalimskySpaceND< dim, TInteger>::
1489 sIsInside( const SPreCell & p ) const
1490 {
1491  return cIsInside( p.coordinates );
1492 }
1493 //-----------------------------------------------------------------------------
1494 template < DGtal::Dimension dim, typename TInteger>
1495 inline
1496 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCell
1497 DGtal::KhalimskySpaceND< dim, TInteger >::
1498 sGetMax( SCell p, DGtal::Dimension k ) const
1499 {
1500  PreCellularGridSpace::sSetKCoord( p.mySPreCell, k, sLast( p, k ) );
1501  ASSERT( sIsValid( p ) );
1502  return p;
1503 }
1504 //-----------------------------------------------------------------------------
1505 template < DGtal::Dimension dim, typename TInteger>
1506 inline
1507 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCell
1508 DGtal::KhalimskySpaceND< dim, TInteger >::
1509 sGetDecr( const SCell & p, DGtal::Dimension k ) const
1510 {
1511  SCell cell( PreCellularGridSpace::sGetDecr( p, k ) );
1512  this->updateSCellHelper( cell, k );
1513  ASSERT( sIsValid( cell ) );
1514  return cell;
1515 }
1516 //-----------------------------------------------------------------------------
1517 template < DGtal::Dimension dim, typename TInteger>
1518 inline
1519 bool
1520 DGtal::KhalimskySpaceND< dim, TInteger >::
1521 sIsMin( const SCell & p, DGtal::Dimension k ) const
1522 {
1523  ASSERT( k < DIM );
1524  ASSERT( sIsInside(p) );
1525  return
1526  ! this->isDimensionPeriodicHelper( k )
1527  && PreCellularGridSpace::sKCoord( p, k ) <= sFirst( p, k );
1528 }
1529 //-----------------------------------------------------------------------------
1530 template < DGtal::Dimension dim, typename TInteger>
1531 inline
1532 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCell
1533 DGtal::KhalimskySpaceND< dim, TInteger >::
1534 sGetMin( SCell p, DGtal::Dimension k ) const
1535 {
1536  PreCellularGridSpace::sSetKCoord( p.mySPreCell, k, sFirst( p, k ) );
1537  ASSERT( sIsValid( p ) );
1538  return p;
1539 }
1540 //-----------------------------------------------------------------------------
1541 template < DGtal::Dimension dim, typename TInteger>
1542 inline
1543 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCell
1544 DGtal::KhalimskySpaceND< dim, TInteger >::
1545 sGetAdd( const SCell & p, DGtal::Dimension k, Integer x ) const
1546 {
1547  SCell cell( PreCellularGridSpace::sGetAdd( p, k, x ) );
1548  this->updateSCellHelper( cell, k );
1549  ASSERT( sIsValid( cell ) );
1550  return cell;
1551 }
1552 //-----------------------------------------------------------------------------
1553 template < DGtal::Dimension dim, typename TInteger>
1554 inline
1555 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCell
1556 DGtal::KhalimskySpaceND< dim, TInteger >::
1557 sGetSub( const SCell & p, DGtal::Dimension k, Integer x ) const
1558 {
1559  SCell cell( PreCellularGridSpace::sGetSub( p, k, x ) );
1560  this->updateSCellHelper( cell, k );
1561  ASSERT( sIsValid( cell ) );
1562  return cell;
1563 }
1564 //-----------------------------------------------------------------------------
1565 template < DGtal::Dimension dim, typename TInteger>
1566 inline
1567 TInteger
1568 DGtal::KhalimskySpaceND< dim, TInteger >::
1569 sDistanceToMax( const SCell & p, DGtal::Dimension k ) const
1570 {
1571  using KPS = PreCellularGridSpace;
1572  ASSERT( k < DIM );
1573  ASSERT( sIsValid( p ) );
1574  return ( KPS::uKCoord( myCellUpper, k ) - KPS::sKCoord( p, k ) ) >> 1;
1575 }
1576 //-----------------------------------------------------------------------------
1577 template < DGtal::Dimension dim, typename TInteger>
1578 inline
1579 TInteger
1580 DGtal::KhalimskySpaceND< dim, TInteger >::
1581 sDistanceToMin( const SCell & p, DGtal::Dimension k ) const
1582 {
1583  using KPS = PreCellularGridSpace;
1584  ASSERT( k < DIM );
1585  ASSERT( sIsValid( p ) );
1586  return ( KPS::sKCoord( p, k ) - KPS::uKCoord( myCellLower, k ) ) >> 1;
1587 }
1588 //-----------------------------------------------------------------------------
1589 template < DGtal::Dimension dim, typename TInteger>
1590 inline
1591 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCell
1592 DGtal::KhalimskySpaceND< dim, TInteger >::
1593 sTranslation( const SCell & p, const Vector & vec ) const
1594 {
1595  SCell cell( PreCellularGridSpace::sTranslation( p, vec ) );
1596  this->updateSCellHelper( cell );
1597  ASSERT( sIsValid( cell ) );
1598  return cell;
1599 }
1600 //-----------------------------------------------------------------------------
1601 template < DGtal::Dimension dim, typename TInteger>
1602 inline
1603 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCell
1604 DGtal::KhalimskySpaceND< dim, TInteger >::
1605 sProjection( const SCell & p, const SCell & bound, DGtal::Dimension k ) const
1606 {
1607  SCell cell( PreCellularGridSpace::sProjection( p, bound, k ) );
1608  ASSERT( sIsValid( cell ) );
1609  return cell;
1610 }
1611 //-----------------------------------------------------------------------------
1612 template < DGtal::Dimension dim, typename TInteger>
1613 inline
1614 void
1615 DGtal::KhalimskySpaceND< dim, TInteger >::
1616 sProject( SCell & p, const SCell & bound, DGtal::Dimension k ) const
1617 {
1618  PreCellularGridSpace::sProject( p.mySPreCell, bound, k );
1619  ASSERT( sIsValid( p ) );
1620 }
1621 //-----------------------------------------------------------------------------
1622 template < DGtal::Dimension dim, typename TInteger>
1623 inline
1624 bool
1625 DGtal::KhalimskySpaceND< dim, TInteger >::
1626 sNext( SCell & p, const SCell & lower, const SCell & upper ) const
1627 {
1628  ASSERT( sIsValid(p) );
1629  ASSERT( sIsValid(lower) );
1630  ASSERT( sIsValid(upper) );
1631  ASSERT( sTopology(p) == sTopology(lower)
1632  && sTopology(p) == sTopology(upper) );
1633 
1634  using KPS = PreCellularGridSpace;
1635 
1636  DGtal::Dimension k = NumberTraits<Dimension>::ZERO;
1637  if ( KPS::sKCoord( p, k ) == KPS::sKCoord( upper, k ) )
1638  {
1639  if ( p == upper ) return false;
1640  KPS::sProject( p.mySPreCell, lower, k );
1641 
1642  for ( k = 1; k < DIM; ++k )
1643  {
1644  if ( KPS::sKCoord( p, k ) == KPS::sKCoord( upper, k ) )
1645  KPS::sProject( p.mySPreCell, lower, k );
1646  else
1647  {
1648  KPS::sSetKCoord( p.mySPreCell, k, this->returnKCoordHelper( KPS::sKCoord( p, k ) + 2, k ) );
1649  break;
1650  }
1651  }
1652  return true;
1653  }
1654 
1655  KPS::sSetKCoord( p.mySPreCell, k, this->returnKCoordHelper( KPS::sKCoord( p, k ) + 2, k ) );
1656  return true;
1657 }
1658 
1659 //-----------------------------------------------------------------------------
1660 // ----------------------- Neighborhood services --------------------------
1661 //-----------------------------------------------------------------------------
1662 template < DGtal::Dimension dim, typename TInteger>
1663 inline
1664 typename DGtal::KhalimskySpaceND< dim, TInteger >::Cells
1665 DGtal::KhalimskySpaceND< dim, TInteger >::
1666 uNeighborhood( const Cell & c ) const
1667 {
1668  ASSERT( uIsValid(c) );
1669 
1670  Cells N;
1671  N.push_back( c );
1672  for ( DGtal::Dimension k = 0; k < DIM; ++k )
1673  {
1674  if ( ! uIsMin( c, k ) )
1675  N.push_back( uGetDecr( c, k ) );
1676  if ( ! uIsMax( c, k ) )
1677  N.push_back( uGetIncr( c, k ) );
1678  }
1679  return N;
1680 }
1681 //-----------------------------------------------------------------------------
1682 template < DGtal::Dimension dim, typename TInteger>
1683 inline
1684 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCells
1685 DGtal::KhalimskySpaceND< dim, TInteger >::
1686 sNeighborhood( const SCell & c ) const
1687 {
1688  ASSERT( sIsValid(c) );
1689 
1690  SCells N;
1691  N.push_back( c );
1692  for ( DGtal::Dimension k = 0; k < DIM; ++k )
1693  {
1694  if ( ! sIsMin( c, k ) )
1695  N.push_back( sGetDecr( c, k ) );
1696  if ( ! sIsMax( c, k ) )
1697  N.push_back( sGetIncr( c, k ) );
1698  }
1699  return N;
1700 }
1701 //-----------------------------------------------------------------------------
1702 template < DGtal::Dimension dim, typename TInteger>
1703 inline
1704 typename DGtal::KhalimskySpaceND< dim, TInteger >::Cells
1705 DGtal::KhalimskySpaceND< dim, TInteger >::
1706 uProperNeighborhood( const Cell & c ) const
1707 {
1708  ASSERT( uIsValid(c) );
1709 
1710  Cells N;
1711  for ( DGtal::Dimension k = 0; k < DIM; ++k )
1712  {
1713  if ( ! uIsMin( c, k ) )
1714  N.push_back( uGetDecr( c, k ) );
1715  if ( ! uIsMax( c, k ) )
1716  N.push_back( uGetIncr( c, k ) );
1717  }
1718  return N;
1719 }
1720 //-----------------------------------------------------------------------------
1721 template < DGtal::Dimension dim, typename TInteger>
1722 inline
1723 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCells
1724 DGtal::KhalimskySpaceND< dim, TInteger >::
1725 sProperNeighborhood( const SCell & c ) const
1726 {
1727  ASSERT( sIsValid(c) );
1728 
1729  SCells N;
1730  for ( DGtal::Dimension k = 0; k < DIM; ++k )
1731  {
1732  if ( ! sIsMin( c, k ) )
1733  N.push_back( sGetDecr( c, k ) );
1734  if ( ! sIsMax( c, k ) )
1735  N.push_back( sGetIncr( c, k ) );
1736  }
1737  return N;
1738 }
1739 //-----------------------------------------------------------------------------
1740 template < DGtal::Dimension dim, typename TInteger>
1741 inline
1742 typename DGtal::KhalimskySpaceND< dim, TInteger >::Cell
1743 DGtal::KhalimskySpaceND< dim, TInteger >::
1744 uAdjacent( const Cell & p, DGtal::Dimension k, bool up ) const
1745 {
1746  ASSERT( k < DIM );
1747  ASSERT( uIsValid(p) );
1748  ASSERT( ( up && !uIsMax(p, k) ) || ( !up && !uIsMin(p, k) ) );
1749  return up ? uGetIncr( p, k ) : uGetDecr( p, k );
1750 }
1751 //-----------------------------------------------------------------------------
1752 template < DGtal::Dimension dim, typename TInteger>
1753 inline
1754 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCell
1755 DGtal::KhalimskySpaceND< dim, TInteger >::
1756 sAdjacent( const SCell & p, DGtal::Dimension k, bool up ) const
1757 {
1758  ASSERT( k < DIM );
1759  ASSERT( sIsValid(p) );
1760  ASSERT( ( up && !sIsMax(p, k) ) || ( !up && !sIsMin(p, k) ) );
1761  return up ? sGetIncr( p, k ) : sGetDecr( p, k );
1762 }
1763 
1764 // ----------------------- Incidence services --------------------------
1765 //-----------------------------------------------------------------------------
1766 template < DGtal::Dimension dim, typename TInteger>
1767 inline
1768 typename DGtal::KhalimskySpaceND< dim, TInteger >::Cell
1769 DGtal::KhalimskySpaceND< dim, TInteger >::
1770 uIncident( const Cell & c, DGtal::Dimension k, bool up ) const
1771 {
1772  ASSERT( k < dim );
1773  ASSERT( uIsValid(c) );
1774  ASSERT( this->isDimensionPeriodicHelper( k ) || ( ! up ) || ( uKCoord( c, k ) < uKCoord( myCellUpper, k ) ) );
1775  ASSERT( this->isDimensionPeriodicHelper( k ) || ( up ) || ( uKCoord( myCellLower, k ) < uKCoord( c, k ) ) );
1776 
1777  Cell cell( PreCellularGridSpace::uIncident( c, k, up ) );
1778  this->updateCellHelper( cell, k );
1779 
1780  return cell;
1781 }
1782 //-----------------------------------------------------------------------------
1783 template < DGtal::Dimension dim, typename TInteger>
1784 inline
1785 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCell
1786 DGtal::KhalimskySpaceND< dim, TInteger >::
1787 sIncident( const SCell & c, DGtal::Dimension k, bool up ) const
1788 {
1789  ASSERT( k < dim );
1790  ASSERT( sIsValid(c) );
1791  ASSERT( this->isDimensionPeriodicHelper( k ) || ( ! up ) || ( sKCoord( c, k ) < uKCoord( myCellUpper, k ) ) );
1792  ASSERT( this->isDimensionPeriodicHelper( k ) || ( up ) || ( uKCoord( myCellLower, k ) < sKCoord( c, k ) ) );
1793 
1794  SCell cell( PreCellularGridSpace::sIncident( c, k, up ) );
1795  this->updateSCellHelper( cell, k );
1796 
1797  return cell;
1798 }
1799 //-----------------------------------------------------------------------------
1800 template < DGtal::Dimension dim, typename TInteger>
1801 inline
1802 typename DGtal::KhalimskySpaceND< dim, TInteger >::Cells
1803 DGtal::KhalimskySpaceND< dim, TInteger >::
1804 uLowerIncident( const Cell & c ) const
1805 {
1806  ASSERT( uIsValid(c) );
1807 
1808  Cells N;
1809  for ( DirIterator q = uDirs( c ); q != 0; ++q )
1810  {
1811  const DGtal::Dimension k = *q;
1812  if ( this->isDimensionPeriodicHelper( k ) )
1813  {
1814  N.push_back( uIncident( c, k, false ) );
1815  N.push_back( uIncident( c, k, true ) );
1816  }
1817  else
1818  {
1819  const Integer x = uKCoord( c, k );
1820  if ( PreCellularGridSpace::uKCoord( myCellLower, k ) < x )
1821  N.push_back( uIncident( c, k, false ) );
1822  if ( x < PreCellularGridSpace::uKCoord( myCellUpper, k ) )
1823  N.push_back( uIncident( c, k, true ) );
1824  }
1825  }
1826  return N;
1827 }
1828 //-----------------------------------------------------------------------------
1829 template < DGtal::Dimension dim, typename TInteger>
1830 inline
1831 typename DGtal::KhalimskySpaceND< dim, TInteger >::Cells
1832 DGtal::KhalimskySpaceND< dim, TInteger >::
1833 uUpperIncident( const Cell & c ) const
1834 {
1835  ASSERT( uIsValid(c) );
1836 
1837  Cells N;
1838  for ( DirIterator q = uOrthDirs( c ); q != 0; ++q )
1839  {
1840  const DGtal::Dimension k = *q;
1841  if ( this->isDimensionPeriodicHelper( k ) )
1842  {
1843  N.push_back( uIncident( c, k, false ) );
1844  N.push_back( uIncident( c, k, true ) );
1845  }
1846  else
1847  {
1848  const Integer x = uKCoord( c, k );
1849  if ( PreCellularGridSpace::uKCoord( myCellLower, k ) < x )
1850  N.push_back( uIncident( c, k, false ) );
1851  if ( x < PreCellularGridSpace::uKCoord( myCellUpper, k ) )
1852  N.push_back( uIncident( c, k, true ) );
1853  }
1854  }
1855  return N;
1856 }
1857 //-----------------------------------------------------------------------------
1858 template < DGtal::Dimension dim, typename TInteger>
1859 inline
1860 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCells
1861 DGtal::KhalimskySpaceND< dim, TInteger >::
1862 sLowerIncident( const SCell & c ) const
1863 {
1864  ASSERT( sIsValid(c) );
1865 
1866  SCells N;
1867  for ( DirIterator q = sDirs( c ); q != 0; ++q )
1868  {
1869  const DGtal::Dimension k = *q;
1870  if ( this->isDimensionPeriodicHelper( k ) )
1871  {
1872  N.push_back( sIncident( c, k, false ) );
1873  N.push_back( sIncident( c, k, true ) );
1874  }
1875  else
1876  {
1877  const Integer x = sKCoord( c, k );
1878  if ( PreCellularGridSpace::uKCoord( myCellLower, k ) < x )
1879  N.push_back( sIncident( c, k, false ) );
1880  if ( x < PreCellularGridSpace::uKCoord( myCellUpper, k ) )
1881  N.push_back( sIncident( c, k, true ) );
1882  }
1883  }
1884  return N;
1885 }
1886 //-----------------------------------------------------------------------------
1887 template < DGtal::Dimension dim, typename TInteger>
1888 inline
1889 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCells
1890 DGtal::KhalimskySpaceND< dim, TInteger >::
1891 sUpperIncident( const SCell & c ) const
1892 {
1893  ASSERT( sIsValid(c) );
1894 
1895  SCells N;
1896  for ( DirIterator q = sOrthDirs( c ); q != 0; ++q )
1897  {
1898  const DGtal::Dimension k = *q;
1899  if ( this->isDimensionPeriodicHelper( k ) )
1900  {
1901  N.push_back( sIncident( c, k, false ) );
1902  N.push_back( sIncident( c, k, true ) );
1903  }
1904  else
1905  {
1906  const Integer x = sKCoord( c, k );
1907  if ( PreCellularGridSpace::uKCoord( myCellLower, k ) < x )
1908  N.push_back( sIncident( c, k, false ) );
1909  if ( x < PreCellularGridSpace::uKCoord( myCellUpper, k ) )
1910  N.push_back( sIncident( c, k, true ) );
1911  }
1912  }
1913  return N;
1914 }
1915 //-----------------------------------------------------------------------------
1916 template < DGtal::Dimension dim, typename TInteger>
1917 inline
1918 void
1919 DGtal::KhalimskySpaceND< dim, TInteger >::
1920 uAddFaces( Cells& faces, const Cell& c, Dimension axis ) const
1921 {
1922  using KPS = PreCellularGridSpace;
1923 
1924  const DGtal::Dimension dim_of_c = uDim( c );
1925  if ( axis >= dim_of_c ) return;
1926 
1927  DirIterator q = uDirs( c );
1928  for ( Dimension i = 0; i < axis; ++i ) ++q;
1929 
1930  // We test incident cells existence within the current Khalimsky space.
1931  const Integer x = KPS::uKCoord( c, *q );
1932  bool has_f1 = this->isDimensionPeriodicHelper( *q ) || KPS::uKCoord( myCellLower, *q ) < x ;
1933  bool has_f2 = this->isDimensionPeriodicHelper( *q ) || x < KPS::uKCoord( myCellUpper, *q ) ;
1934 
1935  Cell f1, f2;
1936  if ( has_f1 ) f1 = uIncident( c, *q, false );
1937  if ( has_f2 ) f2 = uIncident( c, *q, true );
1938 
1939  if ( has_f1 ) faces.push_back( f1 );
1940  if ( has_f2 ) faces.push_back( f2 );
1941 
1942  if ( has_f1 ) uAddFaces( faces, f1, axis );
1943  if ( has_f2 ) uAddFaces( faces, f2, axis );
1944 
1945  uAddFaces( faces, c, axis+1 );
1946 }
1947 //-----------------------------------------------------------------------------
1948 template < DGtal::Dimension dim, typename TInteger>
1949 inline
1950 void
1951 DGtal::KhalimskySpaceND< dim, TInteger >::
1952 uAddCoFaces( Cells& cofaces, const Cell& c, Dimension axis ) const
1953 {
1954  using KPS = PreCellularGridSpace;
1955 
1956  const DGtal::Dimension dim_of_c = uDim( c );
1957  if ( axis >= dimension - dim_of_c ) return;
1958 
1959  DirIterator q = uOrthDirs( c );
1960  for ( Dimension i = 0; i < axis; ++i ) ++q;
1961 
1962  // We test incident cells existence within the current Khalimsky space.
1963  const Integer x = KPS::uKCoord( c, *q );
1964  bool has_f1 = this->isDimensionPeriodicHelper( *q ) || KPS::uKCoord( myCellLower, *q ) < x ;
1965  bool has_f2 = this->isDimensionPeriodicHelper( *q ) || x < KPS::uKCoord( myCellUpper, *q ) ;
1966 
1967  Cell f1, f2;
1968  if ( has_f1 ) f1 = uIncident( c, *q, false );
1969  if ( has_f2 ) f2 = uIncident( c, *q, true );
1970 
1971  if ( has_f1 ) cofaces.push_back( f1 );
1972  if ( has_f2 ) cofaces.push_back( f2 );
1973 
1974  if ( has_f1 ) uAddCoFaces( cofaces, f1, axis );
1975  if ( has_f2 ) uAddCoFaces( cofaces, f2, axis );
1976 
1977  uAddCoFaces( cofaces, c, axis+1 );
1978 }
1979 //-----------------------------------------------------------------------------
1980 template < DGtal::Dimension dim, typename TInteger>
1981 inline
1982 typename DGtal::KhalimskySpaceND< dim, TInteger >::Cells
1983 DGtal::KhalimskySpaceND< dim, TInteger >::
1984 uFaces( const Cell & c ) const
1985 {
1986  ASSERT( uIsValid(c) );
1987 
1988  Cells N;
1989  uAddFaces( N, c, 0 );
1990  return N;
1991 }
1992 //-----------------------------------------------------------------------------
1993 template < DGtal::Dimension dim, typename TInteger>
1994 inline
1995 typename DGtal::KhalimskySpaceND< dim, TInteger >::Cells
1996 DGtal::KhalimskySpaceND< dim, TInteger >::
1997 uCoFaces( const Cell & c ) const
1998 {
1999  ASSERT( uIsValid(c) );
2000 
2001  Cells N;
2002  uAddCoFaces( N, c, 0 );
2003  return N;
2004 }
2005 //-----------------------------------------------------------------------------
2006 template < DGtal::Dimension dim, typename TInteger>
2007 inline
2008 bool
2009 DGtal::KhalimskySpaceND< dim, TInteger >::
2010 sDirect( const SCell & p, DGtal::Dimension k ) const
2011 {
2012  return PreCellularGridSpace::sDirect( p, k );
2013 }
2014 //-----------------------------------------------------------------------------
2015 template < DGtal::Dimension dim, typename TInteger>
2016 inline
2017 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCell
2018 DGtal::KhalimskySpaceND< dim, TInteger >::
2019 sDirectIncident( const SCell & p, DGtal::Dimension k ) const
2020 {
2021  using KPS = PreCellularGridSpace;
2022 
2023  ASSERT( k < dim );
2024  ASSERT( sIsValid(p) );
2025  ASSERT( this->isDimensionPeriodicHelper( k ) || ( ! KPS::sDirect( p, k ) ) || ( KPS::sKCoord( p, k ) < KPS::uKCoord( myCellUpper, k ) ) );
2026  ASSERT( this->isDimensionPeriodicHelper( k ) || ( KPS::sDirect( p, k ) ) || ( KPS::uKCoord( myCellLower, k ) < KPS::sKCoord( p, k ) ) );
2027 
2028  SCell cell( KPS::sDirectIncident( p, k ) );
2029  this->updateSCellHelper( cell, k );
2030 
2031  return cell;
2032 }
2033 //-----------------------------------------------------------------------------
2034 template < DGtal::Dimension dim, typename TInteger>
2035 inline
2036 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCell
2037 DGtal::KhalimskySpaceND< dim, TInteger >::
2038 sIndirectIncident( const SCell & p, DGtal::Dimension k ) const
2039 {
2040  using KPS = PreCellularGridSpace;
2041 
2042  ASSERT( k < dim );
2043  ASSERT( sIsValid(p) );
2044  ASSERT( this->isDimensionPeriodicHelper( k ) || ( KPS::sDirect( p, k ) ) || ( KPS::sKCoord( p, k ) < KPS::uKCoord( myCellUpper, k ) ) );
2045  ASSERT( this->isDimensionPeriodicHelper( k ) || ( ! KPS::sDirect( p, k ) ) || ( KPS::uKCoord( myCellLower, k ) < KPS::sKCoord( p, k ) ) );
2046 
2047  SCell cell( KPS::sIndirectIncident( p, k ) );
2048  this->updateSCellHelper( cell, k );
2049 
2050  return cell;
2051 }
2052 
2053 
2054 
2055 
2056 //-----------------------------------------------------------------------------
2057 template < DGtal::Dimension dim, typename TInteger>
2058 inline
2059 void
2060 DGtal::KhalimskySpaceND< dim, TInteger>::
2061 selfDisplay ( std::ostream & out ) const
2062 {
2063  out << "[KhalimskySpaceND<" << dimension << ">] { ";
2064  out << "{ ";
2065  for ( Dimension i = 0; i < dimension; ++i )
2066  out << ( myClosure[i] == OPEN ? "OPEN " : ( myClosure[i] == CLOSED ? "CLOSED " : "PERIODIC " ) );
2067  out << "}, ";
2068  out << "lower = " << myLower << ", ";
2069  out << "upper = " << myUpper;
2070  out << " }";
2071 
2072 }
2073 //-----------------------------------------------------------------------------
2074 template < DGtal::Dimension dim, typename TInteger>
2075 inline
2076 bool
2077 DGtal::KhalimskySpaceND< dim, TInteger>::
2078 isValid() const
2079 {
2080  return true;
2081 }
2082 
2083 
2084 
2085 ///////////////////////////////////////////////////////////////////////////////
2086 // Implementation of inline functions //
2087 template < DGtal::Dimension dim, typename TInteger>
2088 inline
2089 std::ostream&
2090 DGtal::operator<< ( std::ostream & out,
2091  const KhalimskySpaceND< dim, TInteger> & object )
2092 {
2093  object.selfDisplay( out );
2094  return out;
2095 }
2096 
2097 // //
2098 ///////////////////////////////////////////////////////////////////////////////