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