DGtal  1.2.0
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 bool
456 DGtal::KhalimskySpaceND< dim, TInteger>::
457 init( const Point & lower,
458  const Point & upper,
459  bool isClosed )
460 {
461  std::array<Closure, dimension> closure;
462  for ( DGtal::Dimension i = 0; i < dimension; ++i )
463  closure[ i ] = isClosed ? CLOSED : OPEN;
464 
465  return init( lower, upper, closure );
466 }
467 //-----------------------------------------------------------------------------
468 template < DGtal::Dimension dim, typename TInteger>
469 inline
470 bool
471 DGtal::KhalimskySpaceND< dim, TInteger>::
472 init( const Point & lower,
473  const Point & upper,
474  Closure closure )
475 {
476  std::array<Closure, dimension> dimClosure;
477  dimClosure.fill( closure );
478 
479  return init( lower, upper, dimClosure );
480 }
481 
482 //-----------------------------------------------------------------------------
483 template < DGtal::Dimension dim, typename TInteger>
484 inline
485 bool
486 DGtal::KhalimskySpaceND< dim, TInteger>::
487 init( const Point & lower,
488  const Point & upper,
489  const std::array<Closure, dim> & closure )
490 {
491  myLower = lower;
492  myUpper = upper;
493  myClosure = closure;
494 
495  if ( NumberTraits< Integer >::isBounded() == BOUNDED )
496  {
497  for ( DGtal::Dimension i = 0; i < dimension; ++i )
498  {
499  if ( ( lower[ i ] <= ( NumberTraits< Integer >::min() / 2 ) )
500  || ( upper[ i ] >= ( NumberTraits< Integer >::max() / 2 ) ) )
501  return false;
502  }
503  }
504 
505  for ( DGtal::Dimension i = 0; i < dimension; ++i )
506  {
507  PreCellularGridSpace::uSetKCoord( myCellLower.myPreCell, i, ( lower[ i ] * 2 ) + ( closure[ i ] != OPEN ? 0 : 1 ) );
508  PreCellularGridSpace::uSetKCoord( myCellUpper.myPreCell, i, ( upper[ i ] * 2 ) + ( closure[ i ] == CLOSED ? 2 : 1 ) );
509 
510  }
511 
512  return this->initHelper();
513 }
514 //-----------------------------------------------------------------------------
515 template < DGtal::Dimension dim, typename TInteger>
516 inline
517 typename DGtal::KhalimskySpaceND< dim, TInteger>::Size
518 DGtal::KhalimskySpaceND< dim, TInteger>::
519 size( DGtal::Dimension k ) const
520 {
521  ASSERT( k < dimension );
522  return myUpper[ k ] + NumberTraits<Integer>::ONE - myLower[ k ];
523 }
524 //-----------------------------------------------------------------------------
525 template < DGtal::Dimension dim, typename TInteger>
526 inline
527 TInteger
528 DGtal::KhalimskySpaceND< dim, TInteger>::
529 min( DGtal::Dimension k ) const
530 {
531  return myLower[ k ];
532 }
533 //-----------------------------------------------------------------------------
534 template < DGtal::Dimension dim, typename TInteger>
535 inline
536 TInteger
537 DGtal::KhalimskySpaceND< dim, TInteger>::
538 max( DGtal::Dimension k ) const
539 {
540  return myUpper[ k ];
541 }
542 //-----------------------------------------------------------------------------
543 template < DGtal::Dimension dim, typename TInteger>
544 inline
545 const typename DGtal::KhalimskySpaceND< dim, TInteger>::Point &
546 DGtal::KhalimskySpaceND< dim, TInteger>::
547 lowerBound() const
548 {
549  return myLower;
550 }
551 //-----------------------------------------------------------------------------
552 template < DGtal::Dimension dim, typename TInteger>
553 inline
554 const typename DGtal::KhalimskySpaceND< dim, TInteger>::Point &
555 DGtal::KhalimskySpaceND< dim, TInteger>::
556 upperBound() const
557 {
558  return myUpper;
559 }
560 //-----------------------------------------------------------------------------
561 template < DGtal::Dimension dim, typename TInteger>
562 inline
563 const typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell &
564 DGtal::KhalimskySpaceND< dim, TInteger>::
565 lowerCell() const
566 {
567  return myCellLower;
568 }
569 //-----------------------------------------------------------------------------
570 template < DGtal::Dimension dim, typename TInteger>
571 inline
572 const typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell &
573 DGtal::KhalimskySpaceND< dim, TInteger>::
574 upperCell() const
575 {
576  return myCellUpper;
577 }
578 //-----------------------------------------------------------------------------
579 template < DGtal::Dimension dim, typename TInteger>
580 inline
581 bool
582 DGtal::KhalimskySpaceND< dim, TInteger>::
583 uIsValid( const PreCell & p, Dimension k ) const
584 {
585  return cIsValid( p.coordinates, k );
586 }
587 //-----------------------------------------------------------------------------
588 template < DGtal::Dimension dim, typename TInteger>
589 inline
590 bool
591 DGtal::KhalimskySpaceND< dim, TInteger>::
592 uIsValid( const PreCell & p ) const
593 {
594  return cIsValid( p.coordinates );
595 }
596 //-----------------------------------------------------------------------------
597 template < DGtal::Dimension dim, typename TInteger>
598 inline
599 bool
600 DGtal::KhalimskySpaceND< dim, TInteger>::
601 cIsValid( const Point & p, Dimension k ) const
602 {
603  return p[ k ] <= PreCellularGridSpace::uKCoord( myCellUpper, k )
604  && p[ k ] >= PreCellularGridSpace::uKCoord( myCellLower, k );
605 }
606 //-----------------------------------------------------------------------------
607 template < DGtal::Dimension dim, typename TInteger>
608 inline
609 bool
610 DGtal::KhalimskySpaceND< dim, TInteger>::
611 cIsValid( const Point & p ) const
612 {
613  for ( Dimension k = 0; k < DIM; ++ k )
614  if ( ! cIsValid( p, k ) )
615  return false;
616 
617  return true;
618 }
619 //-----------------------------------------------------------------------------
620 template < DGtal::Dimension dim, typename TInteger>
621 inline
622 bool
623 DGtal::KhalimskySpaceND< dim, TInteger>::
624 sIsValid( const SPreCell & p, Dimension k ) const
625 {
626  return cIsValid( p.coordinates, k );
627 }
628 //-----------------------------------------------------------------------------
629 template < DGtal::Dimension dim, typename TInteger>
630 inline
631 bool
632 DGtal::KhalimskySpaceND< dim, TInteger>::
633 sIsValid( const SPreCell & p ) const
634 {
635  return cIsValid( p.coordinates );
636 }
637 //-----------------------------------------------------------------------------
638 template < DGtal::Dimension dim, typename TInteger>
639 inline
640 bool
641 DGtal::KhalimskySpaceND< dim, TInteger>::
642 isSpaceClosed() const
643 {
644  for ( Dimension i = 0; i < dimension; ++i )
645  if ( myClosure[ i ] == OPEN )
646  return false;
647 
648  return true;
649 }
650 //-----------------------------------------------------------------------------
651 template < DGtal::Dimension dim, typename TInteger>
652 inline
653 bool
654 DGtal::KhalimskySpaceND< dim, TInteger>::
655 isSpaceClosed( Dimension k ) const
656 {
657  return myClosure[ k ] != OPEN;
658 }
659 //-----------------------------------------------------------------------------
660 template < DGtal::Dimension dim, typename TInteger>
661 inline
662 bool
663 DGtal::KhalimskySpaceND< dim, TInteger>::
664 isSpacePeriodic() const
665 {
666  for ( Dimension i = 0; i < dimension; ++i )
667  if ( myClosure[ i ] != PERIODIC )
668  return false;
669 
670  return true;
671 }
672 //-----------------------------------------------------------------------------
673 template < DGtal::Dimension dim, typename TInteger>
674 inline
675 bool
676 DGtal::KhalimskySpaceND< dim, TInteger>::
677 isSpacePeriodic( Dimension k ) const
678 {
679  return myClosure[ k ] == PERIODIC;
680 }
681 //-----------------------------------------------------------------------------
682 template < DGtal::Dimension dim, typename TInteger>
683 inline
684 bool
685 DGtal::KhalimskySpaceND< dim, TInteger>::
686 isAnyDimensionPeriodic() const
687 {
688  return this->isAnyDimensionPeriodicHelper();
689 }
690 //-----------------------------------------------------------------------------
691 template < DGtal::Dimension dim, typename TInteger>
692 inline
693 typename DGtal::KhalimskySpaceND< dim, TInteger>::Closure
694 DGtal::KhalimskySpaceND< dim, TInteger>::
695 getClosure(Dimension k) const
696 {
697  return myClosure[k];
698 }
699 //-----------------------------------------------------------------------------
700 template < DGtal::Dimension dim, typename TInteger>
701 inline
702 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
703 DGtal::KhalimskySpaceND< dim, TInteger>::
704 uCell( const PreCell & c ) const
705 {
706  return uCell( c.coordinates );
707 }
708 //-----------------------------------------------------------------------------
709 template < DGtal::Dimension dim, typename TInteger>
710 inline
711 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
712 DGtal::KhalimskySpaceND< dim, TInteger>::
713 uCell( const Point & kp ) const
714 {
715  ASSERT( cIsInside( kp ) );
716  return Cell( this->returnKCoordsHelper( kp ) );
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( Point p, const PreCell & c ) const
724 {
725  return uCell( PreCellularGridSpace::uCell( p, c ) );
726 }
727 //-----------------------------------------------------------------------------
728 template < DGtal::Dimension dim, typename TInteger>
729 inline
730 typename DGtal::KhalimskySpaceND< dim, TInteger>::SCell
731 DGtal::KhalimskySpaceND< dim, TInteger>::
732 sCell( const SPreCell & c ) const
733 {
734  return sCell( c.coordinates, c.positive ? POS : NEG );
735 }
736 //-----------------------------------------------------------------------------
737 template < DGtal::Dimension dim, typename TInteger>
738 inline
739 typename DGtal::KhalimskySpaceND< dim, TInteger>::SCell
740 DGtal::KhalimskySpaceND< dim, TInteger>::
741 sCell( const Point & kp, Sign sign ) const
742 {
743  ASSERT( cIsInside( kp ) );
744  return SCell( this->returnKCoordsHelper( kp ), sign == POS );
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( Point p, const SPreCell & c ) const
752 {
753  return sCell( PreCellularGridSpace::sCell( p, c ) );
754 }
755 //-----------------------------------------------------------------------------
756 template < DGtal::Dimension dim, typename TInteger>
757 inline
758 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
759 DGtal::KhalimskySpaceND< dim, TInteger>::
760 uSpel( Point p ) const
761 {
762  return uCell( PreCellularGridSpace::uSpel( p ) );
763 }
764 //-----------------------------------------------------------------------------
765 template < DGtal::Dimension dim, typename TInteger>
766 inline
767 typename DGtal::KhalimskySpaceND< dim, TInteger>::SCell
768 DGtal::KhalimskySpaceND< dim, TInteger>::
769 sSpel( Point p, Sign sign ) const
770 {
771  return sCell( PreCellularGridSpace::sSpel( p, sign ) );
772 }
773 //-----------------------------------------------------------------------------
774 template < DGtal::Dimension dim, typename TInteger>
775 inline
776 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
777 DGtal::KhalimskySpaceND< dim, TInteger>::
778 uPointel( Point p ) const
779 {
780  return uCell( PreCellularGridSpace::uPointel( p ) );
781 }
782 //-----------------------------------------------------------------------------
783 template < DGtal::Dimension dim, typename TInteger>
784 inline
785 typename DGtal::KhalimskySpaceND< dim, TInteger>::SCell
786 DGtal::KhalimskySpaceND< dim, TInteger>::
787 sPointel( Point p, Sign sign ) const
788 {
789  return sCell( PreCellularGridSpace::sPointel( p, sign ) );
790 }
791 //-----------------------------------------------------------------------------
792 ///////////////////////////////////////////////////////////////////////////////
793 //-----------------------------------------------------------------------------
794 template < DGtal::Dimension dim, typename TInteger>
795 inline
796 typename DGtal::KhalimskySpaceND< dim, TInteger>::Integer
797 DGtal::KhalimskySpaceND< dim, TInteger>::
798 uKCoord( const Cell & c, DGtal::Dimension k ) const
799 {
800  ASSERT( uIsValid(c) );
801  return PreCellularGridSpace::uKCoord( c, k );
802 }
803 //-----------------------------------------------------------------------------
804 template < DGtal::Dimension dim, typename TInteger>
805 inline
806 typename DGtal::KhalimskySpaceND< dim, TInteger>::Integer
807 DGtal::KhalimskySpaceND< dim, TInteger>::
808 uCoord( const Cell & c, DGtal::Dimension k ) const
809 {
810  ASSERT( uIsValid(c) );
811  return PreCellularGridSpace::uCoord( c, k );
812 }
813 //-----------------------------------------------------------------------------
814 template < DGtal::Dimension dim, typename TInteger>
815 inline
816 typename DGtal::KhalimskySpaceND< dim, TInteger>::Point const &
817 DGtal::KhalimskySpaceND< dim, TInteger>::
818 uKCoords( const Cell & c ) const
819 {
820  ASSERT( uIsValid(c) );
821  return PreCellularGridSpace::uKCoords( c );
822 }
823 //-----------------------------------------------------------------------------
824 template < DGtal::Dimension dim, typename TInteger>
825 inline
826 typename DGtal::KhalimskySpaceND< dim, TInteger>::Point
827 DGtal::KhalimskySpaceND< dim, TInteger>::
828 uCoords( const Cell & c ) const
829 {
830  ASSERT( uIsValid(c) );
831  return PreCellularGridSpace::uCoords( c );
832 }
833 //-----------------------------------------------------------------------------
834 template < DGtal::Dimension dim, typename TInteger>
835 inline
836 typename DGtal::KhalimskySpaceND< dim, TInteger>::Integer
837 DGtal::KhalimskySpaceND< dim, TInteger>::
838 sKCoord( const SCell & c, DGtal::Dimension k ) const
839 {
840  ASSERT( sIsValid(c) );
841  return PreCellularGridSpace::sKCoord( c, k );
842 }
843 //-----------------------------------------------------------------------------
844 template < DGtal::Dimension dim, typename TInteger>
845 inline
846 typename DGtal::KhalimskySpaceND< dim, TInteger>::Integer
847 DGtal::KhalimskySpaceND< dim, TInteger>::
848 sCoord( const SCell & c, DGtal::Dimension k ) const
849 {
850  ASSERT( sIsValid(c) );
851  return PreCellularGridSpace::sCoord( c, k );
852 }
853 //-----------------------------------------------------------------------------
854 template < DGtal::Dimension dim, typename TInteger>
855 inline
856 typename DGtal::KhalimskySpaceND< dim, TInteger>::Point const &
857 DGtal::KhalimskySpaceND< dim, TInteger>::
858 sKCoords( const SCell & c ) const
859 {
860  ASSERT( sIsValid(c) );
861  return PreCellularGridSpace::sKCoords( c );
862 }
863 //-----------------------------------------------------------------------------
864 template < DGtal::Dimension dim, typename TInteger>
865 inline
866 typename DGtal::KhalimskySpaceND< dim, TInteger>::Point
867 DGtal::KhalimskySpaceND< dim, TInteger>::
868 sCoords( const SCell & c ) const
869 {
870  ASSERT( sIsValid(c) );
871  return PreCellularGridSpace::sCoords( c );
872 }
873 //-----------------------------------------------------------------------------
874 template < DGtal::Dimension dim, typename TInteger>
875 inline
876 typename DGtal::KhalimskySpaceND< dim, TInteger>::Sign
877 DGtal::KhalimskySpaceND< dim, TInteger>::
878 sSign( const SCell & c ) const
879 {
880  ASSERT( sIsValid(c) );
881  return PreCellularGridSpace::sSign( c );
882 }
883 //-----------------------------------------------------------------------------
884 template < DGtal::Dimension dim, typename TInteger>
885 inline
886 typename DGtal::KhalimskySpaceND< dim, TInteger>::SCell
887 DGtal::KhalimskySpaceND< dim, TInteger>::
888 signs( const Cell & p, Sign s ) const
889 {
890  return sCell( PreCellularGridSpace::signs( p, s ) );
891 }
892 //-----------------------------------------------------------------------------
893 template < DGtal::Dimension dim, typename TInteger>
894 inline
895 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
896 DGtal::KhalimskySpaceND< dim, TInteger>::
897 unsigns( const SCell & p ) const
898 {
899  return uCell( PreCellularGridSpace::unsigns( p ) );
900 }
901 //-----------------------------------------------------------------------------
902 template < DGtal::Dimension dim, typename TInteger>
903 inline
904 typename DGtal::KhalimskySpaceND< dim, TInteger>::SCell
905 DGtal::KhalimskySpaceND< dim, TInteger>::
906 sOpp( const SCell & p ) const
907 {
908  return sCell( PreCellularGridSpace::sOpp( p ) );
909 }
910 //-----------------------------------------------------------------------------
911 template < DGtal::Dimension dim, typename TInteger>
912 inline
913 void
914 DGtal::KhalimskySpaceND< dim, TInteger>::
915 uSetKCoord( Cell & c, DGtal::Dimension k, Integer i ) const
916 {
917  PreCellularGridSpace::uSetKCoord( c.myPreCell, k, i );
918  this->updateCellHelper( c, k );
919  ASSERT( uIsValid(c) );
920 }
921 //-----------------------------------------------------------------------------
922 template < DGtal::Dimension dim, typename TInteger>
923 inline
924 void
925 DGtal::KhalimskySpaceND< dim, TInteger>::
926 sSetKCoord( SCell & c, DGtal::Dimension k, Integer i ) const
927 {
928  PreCellularGridSpace::sSetKCoord( c.mySPreCell, k, i );
929  this->updateSCellHelper( c, k );
930  ASSERT( sIsValid(c) );
931 }
932 //-----------------------------------------------------------------------------
933 template < DGtal::Dimension dim, typename TInteger>
934 inline
935 void
936 DGtal::KhalimskySpaceND< dim, TInteger>::
937 uSetCoord( Cell & c, DGtal::Dimension k, Integer i ) const
938 {
939  PreCellularGridSpace::uSetCoord( c.myPreCell, k, i );
940  this->updateCellHelper( c, k );
941  ASSERT( uIsValid(c) );
942 }
943 //-----------------------------------------------------------------------------
944 template < DGtal::Dimension dim, typename TInteger>
945 inline
946 void
947 DGtal::KhalimskySpaceND< dim, TInteger>::
948 sSetCoord( SCell & c, DGtal::Dimension k, Integer i ) const
949 {
950  PreCellularGridSpace::sSetCoord( c.mySPreCell, k, i );
951  this->updateSCellHelper( c, k );
952  ASSERT( sIsValid(c) );
953 }
954 //-----------------------------------------------------------------------------
955 template < DGtal::Dimension dim, typename TInteger>
956 inline
957 void
958 DGtal::KhalimskySpaceND< dim, TInteger>::
959 uSetKCoords( Cell & c, const Point & kp ) const
960 {
961  PreCellularGridSpace::uSetKCoords( c.myPreCell, kp );
962  this->updateCellHelper( c );
963  ASSERT( uIsValid(c) );
964 }
965 //-----------------------------------------------------------------------------
966 template < DGtal::Dimension dim, typename TInteger>
967 inline
968 void
969 DGtal::KhalimskySpaceND< dim, TInteger>::
970 sSetKCoords( SCell & c, const Point & kp ) const
971 {
972  PreCellularGridSpace::sSetKCoords( c.mySPreCell, kp );
973  this->updateSCellHelper( c );
974  ASSERT( sIsValid(c) );
975 }
976 //-----------------------------------------------------------------------------
977 template < DGtal::Dimension dim, typename TInteger>
978 inline
979 void
980 DGtal::KhalimskySpaceND< dim, TInteger>::
981 uSetCoords( Cell & c, const Point & p ) const
982 {
983  PreCellularGridSpace::uSetCoords( c.myPreCell, p );
984  this->updateCellHelper( c );
985  ASSERT( uIsValid(c) );
986 }
987 //-----------------------------------------------------------------------------
988 template < DGtal::Dimension dim, typename TInteger>
989 inline
990 void
991 DGtal::KhalimskySpaceND< dim, TInteger>::
992 sSetCoords( SCell & c, const Point & p ) const
993 {
994  PreCellularGridSpace::sSetCoords( c.mySPreCell, p );
995  this->updateSCellHelper( c );
996  ASSERT( sIsValid(c) );
997 }
998 //-----------------------------------------------------------------------------
999 template < DGtal::Dimension dim, typename TInteger>
1000 inline
1001 void
1002 DGtal::KhalimskySpaceND< dim, TInteger>::
1003 sSetSign( SCell & c, Sign s ) const
1004 {
1005  PreCellularGridSpace::sSetSign( c.mySPreCell, s );
1006 }
1007 //-----------------------------------------------------------------------------
1008 // ------------------------- Cell topology services -----------------------
1009 //-----------------------------------------------------------------------------
1010 template < DGtal::Dimension dim, typename TInteger>
1011 inline
1012 TInteger
1013 DGtal::KhalimskySpaceND< dim, TInteger>::
1014 uTopology( const Cell & p ) const
1015 {
1016  return PreCellularGridSpace::uTopology( p );
1017 }
1018 //-----------------------------------------------------------------------------
1019 template < DGtal::Dimension dim, typename TInteger>
1020 inline
1021 TInteger
1022 DGtal::KhalimskySpaceND< dim, TInteger>::
1023 sTopology( const SCell & p ) const
1024 {
1025  return PreCellularGridSpace::sTopology( p );
1026 }
1027 //-----------------------------------------------------------------------------
1028 template < DGtal::Dimension dim, typename TInteger>
1029 inline
1030 DGtal::Dimension
1031 DGtal::KhalimskySpaceND< dim, TInteger>::
1032 uDim( const Cell & p ) const
1033 {
1034  return PreCellularGridSpace::uDim( p );
1035 }
1036 //-----------------------------------------------------------------------------
1037 template < DGtal::Dimension dim, typename TInteger>
1038 inline
1039 DGtal::Dimension
1040 DGtal::KhalimskySpaceND< dim, TInteger>::
1041 sDim( const SCell & p ) const
1042 {
1043  return PreCellularGridSpace::sDim( p );
1044 }
1045 //-----------------------------------------------------------------------------
1046 template < DGtal::Dimension dim, typename TInteger>
1047 inline
1048 bool
1049 DGtal::KhalimskySpaceND< dim, TInteger>::
1050 uIsSurfel( const Cell & b ) const
1051 {
1052  return PreCellularGridSpace::uIsSurfel( b );
1053 }
1054 //-----------------------------------------------------------------------------
1055 template < DGtal::Dimension dim, typename TInteger>
1056 inline
1057 bool
1058 DGtal::KhalimskySpaceND< dim, TInteger>::
1059 sIsSurfel( const SCell & b ) const
1060 {
1061  return PreCellularGridSpace::sIsSurfel( b );
1062 }
1063 //-----------------------------------------------------------------------------
1064 template < DGtal::Dimension dim, typename TInteger>
1065 inline
1066 bool
1067 DGtal::KhalimskySpaceND< dim, TInteger>::
1068 uIsOpen( const Cell & p, DGtal::Dimension k ) const
1069 {
1070  return PreCellularGridSpace::uIsOpen( p, k );
1071 }
1072 //-----------------------------------------------------------------------------
1073 template < DGtal::Dimension dim, typename TInteger>
1074 inline
1075 bool
1076 DGtal::KhalimskySpaceND< dim, TInteger>::
1077 sIsOpen( const SCell & p, DGtal::Dimension k ) const
1078 {
1079  return PreCellularGridSpace::sIsOpen( p, k );
1080 }
1081 
1082 //-----------------------------------------------------------------------------
1083 ///////////////////////////////////////////////////////////////////////////////
1084 //-----------------------------------------------------------------------------
1085 template < DGtal::Dimension dim, typename TInteger>
1086 inline
1087 typename DGtal::KhalimskySpaceND< dim, TInteger>::DirIterator
1088 DGtal::KhalimskySpaceND< dim, TInteger>::
1089 uDirs( const Cell & p ) const
1090 {
1091  return PreCellularGridSpace::uDirs( p );
1092 }
1093 //-----------------------------------------------------------------------------
1094 template < DGtal::Dimension dim, typename TInteger>
1095 inline
1096 typename DGtal::KhalimskySpaceND< dim, TInteger>::DirIterator
1097 DGtal::KhalimskySpaceND< dim, TInteger>::
1098 sDirs( const SCell & p ) const
1099 {
1100  return PreCellularGridSpace::sDirs( p );
1101 }
1102 //-----------------------------------------------------------------------------
1103 template < DGtal::Dimension dim, typename TInteger>
1104 inline
1105 typename DGtal::KhalimskySpaceND< dim, TInteger>::DirIterator
1106 DGtal::KhalimskySpaceND< dim, TInteger>::
1107 uOrthDirs( const Cell & p ) const
1108 {
1109  return PreCellularGridSpace::uOrthDirs( p );
1110 }
1111 //-----------------------------------------------------------------------------
1112 template < DGtal::Dimension dim, typename TInteger>
1113 inline
1114 typename DGtal::KhalimskySpaceND< dim, TInteger>::DirIterator
1115 DGtal::KhalimskySpaceND< dim, TInteger>::
1116 sOrthDirs( const SCell & p ) const
1117 {
1118  return PreCellularGridSpace::sOrthDirs( p );
1119 }
1120 //-----------------------------------------------------------------------------
1121 template < DGtal::Dimension dim, typename TInteger>
1122 inline
1123 DGtal::Dimension
1124 DGtal::KhalimskySpaceND< dim, TInteger>::
1125 uOrthDir( const Cell & s ) const
1126 {
1127  return PreCellularGridSpace::uOrthDir( s );
1128 }
1129 //-----------------------------------------------------------------------------
1130 template < DGtal::Dimension dim, typename TInteger>
1131 inline
1132 DGtal::Dimension
1133 DGtal::KhalimskySpaceND< dim, TInteger>::
1134 sOrthDir( const SCell & s ) const
1135 {
1136  return PreCellularGridSpace::sOrthDir( s );
1137 }
1138 //-----------------------------------------------------------------------------
1139 ///////////////////////////////////////////////////////////////////////////////
1140 //-----------------------------------------------------------------------------
1141 //-----------------------------------------------------------------------------
1142 template < DGtal::Dimension dim, typename TInteger>
1143 inline
1144 typename DGtal::KhalimskySpaceND< dim, TInteger>::Integer
1145 DGtal::KhalimskySpaceND< dim, TInteger>::
1146 uFirst( const PreCell & p, DGtal::Dimension k ) const
1147 {
1148  ASSERT( k < DIM );
1149 
1150  return myClosure[ k ] == OPEN ?
1151  2 * myLower[ k ] + ( NumberTraits<Integer>::odd( p.coordinates[ k ] ) ? 1 : 2 )
1152  : 2 * myLower[ k ] + ( NumberTraits<Integer>::odd( p.coordinates[ k ] ) ? 1 : 0 );
1153 }
1154 //-----------------------------------------------------------------------------
1155 template < DGtal::Dimension dim, typename TInteger>
1156 inline
1157 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
1158 DGtal::KhalimskySpaceND< dim, TInteger>::
1159 uFirst( const PreCell & p ) const
1160 {
1161  Cell cell;
1162  for ( Dimension k = 0; k < dimension; ++k )
1163  PreCellularGridSpace::uSetKCoord( cell.myPreCell, k, uFirst( p, k ) );
1164 
1165  return cell;
1166 }
1167 //-----------------------------------------------------------------------------
1168 template < DGtal::Dimension dim, typename TInteger>
1169 inline
1170 typename DGtal::KhalimskySpaceND< dim, TInteger>::Integer
1171 DGtal::KhalimskySpaceND< dim, TInteger>::
1172 uLast( const PreCell & p, DGtal::Dimension k ) const
1173 {
1174  ASSERT( k < DIM );
1175 
1176  return myClosure[ k ] == CLOSED ?
1177  2 * myUpper[ k ] + ( NumberTraits<Integer>::odd( p.coordinates[ k ] ) ? 1 : 2 )
1178  : 2 * myUpper[ k ] + ( NumberTraits<Integer>::odd( p.coordinates[ k ] ) ? 1 : 0 );
1179 }
1180 //-----------------------------------------------------------------------------
1181 template < DGtal::Dimension dim, typename TInteger>
1182 inline
1183 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
1184 DGtal::KhalimskySpaceND< dim, TInteger>::
1185 uLast( const PreCell & p ) const
1186 {
1187  Cell cell;
1188  for ( Dimension k = 0; k < dimension; ++k )
1189  PreCellularGridSpace::uSetKCoord( cell.myPreCell, k, uLast( p, k ) );
1190 
1191  return cell;
1192 }
1193 //-----------------------------------------------------------------------------
1194 template < DGtal::Dimension dim, typename TInteger>
1195 inline
1196 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
1197 DGtal::KhalimskySpaceND< dim, TInteger>::
1198 uGetIncr( const Cell & p, DGtal::Dimension k ) const
1199 {
1200  Cell cell( PreCellularGridSpace::uGetIncr( p, k ) );
1201  this->updateCellHelper( cell, k );
1202  ASSERT( uIsValid(cell) );
1203  return cell;
1204 }
1205 //-----------------------------------------------------------------------------
1206 template < DGtal::Dimension dim, typename TInteger>
1207 inline
1208 bool
1209 DGtal::KhalimskySpaceND< dim, TInteger>::
1210 uIsMax( const Cell & p, DGtal::Dimension k ) const
1211 {
1212  ASSERT( k < DIM );
1213  ASSERT( uIsInside(p) );
1214  return
1215  ! this->isDimensionPeriodicHelper( k )
1216  && PreCellularGridSpace::uKCoord( p, k ) >= uLast( p, k );
1217 }
1218 //-----------------------------------------------------------------------------
1219 template < DGtal::Dimension dim, typename TInteger>
1220 inline
1221 bool
1222 DGtal::KhalimskySpaceND< dim, TInteger>::
1223 uIsInside( const PreCell & p, DGtal::Dimension k ) const
1224 {
1225  return cIsInside( p.coordinates, k );
1226 }
1227 //-----------------------------------------------------------------------------
1228 template < DGtal::Dimension dim, typename TInteger>
1229 inline
1230 bool
1231 DGtal::KhalimskySpaceND< dim, TInteger>::
1232 uIsInside( const PreCell & p ) const
1233 {
1234  return cIsInside( p.coordinates );
1235 }
1236 //-----------------------------------------------------------------------------
1237 template < DGtal::Dimension dim, typename TInteger>
1238 inline
1239 bool
1240 DGtal::KhalimskySpaceND< dim, TInteger>::
1241 cIsInside( const Point & p, DGtal::Dimension k ) const
1242 {
1243  ASSERT( k < DIM );
1244  return this->isDimensionPeriodicHelper( k )
1245  || cIsValid( p, k );
1246 }
1247 //-----------------------------------------------------------------------------
1248 template < DGtal::Dimension dim, typename TInteger>
1249 inline
1250 bool
1251 DGtal::KhalimskySpaceND< dim, TInteger>::
1252 cIsInside( const Point & p ) const
1253 {
1254  for ( Dimension k = 0; k < DIM; ++k )
1255  if ( ! cIsInside( p, k ) )
1256  return false;
1257 
1258  return true;
1259 }
1260 //-----------------------------------------------------------------------------
1261 template < DGtal::Dimension dim, typename TInteger>
1262 inline
1263 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
1264 DGtal::KhalimskySpaceND< dim, TInteger>::
1265 uGetMax( Cell p, DGtal::Dimension k ) const
1266 {
1267  PreCellularGridSpace::uSetKCoord( p.myPreCell, k, uLast( p, k ) );
1268  ASSERT( uIsValid( p ) );
1269  return p;
1270 }
1271 //-----------------------------------------------------------------------------
1272 template < DGtal::Dimension dim, typename TInteger>
1273 inline
1274 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
1275 DGtal::KhalimskySpaceND< dim, TInteger>::
1276 uGetDecr( const Cell & p, DGtal::Dimension k ) const
1277 {
1278  Cell cell( PreCellularGridSpace::uGetDecr( p, k ) );
1279  this->updateCellHelper( cell, k );
1280  ASSERT( uIsValid( cell ) );
1281  return cell;
1282 }
1283 //-----------------------------------------------------------------------------
1284 template < DGtal::Dimension dim, typename TInteger>
1285 inline
1286 bool
1287 DGtal::KhalimskySpaceND< dim, TInteger>::
1288 uIsMin( const Cell & p, DGtal::Dimension k ) const
1289 {
1290  ASSERT( uIsInside(p) );
1291  return
1292  ! this->isDimensionPeriodicHelper( k )
1293  && PreCellularGridSpace::uKCoord( p, k ) <= uFirst( p, k );
1294 }
1295 //-----------------------------------------------------------------------------
1296 template < DGtal::Dimension dim, typename TInteger>
1297 inline
1298 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
1299 DGtal::KhalimskySpaceND< dim, TInteger>::
1300 uGetMin( Cell p, DGtal::Dimension k ) const
1301 {
1302  PreCellularGridSpace::uSetKCoord( p.myPreCell, k, uFirst( p, k ) );
1303  ASSERT( uIsValid(p) );
1304  return p;
1305 }
1306 //-----------------------------------------------------------------------------
1307 template < DGtal::Dimension dim, typename TInteger>
1308 inline
1309 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
1310 DGtal::KhalimskySpaceND< dim, TInteger>::
1311 uGetAdd( const Cell & p, DGtal::Dimension k, Integer x ) const
1312 {
1313  Cell cell( PreCellularGridSpace::uGetAdd( p, k, x ) );
1314  this->updateCellHelper( cell, k );
1315  ASSERT( uIsValid( cell ) );
1316  return cell;
1317 }
1318 //-----------------------------------------------------------------------------
1319 template < DGtal::Dimension dim, typename TInteger>
1320 inline
1321 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
1322 DGtal::KhalimskySpaceND< dim, TInteger>::
1323 uGetSub( const Cell & p, DGtal::Dimension k, Integer x ) const
1324 {
1325  Cell cell( PreCellularGridSpace::uGetSub( p, k, x ) );
1326  this->updateCellHelper( cell, k );
1327  ASSERT( uIsValid( cell ) );
1328  return cell;
1329 }
1330 //-----------------------------------------------------------------------------
1331 template < DGtal::Dimension dim, typename TInteger>
1332 inline
1333 TInteger
1334 DGtal::KhalimskySpaceND< dim, TInteger>::
1335 uDistanceToMax( const Cell & p, DGtal::Dimension k ) const
1336 {
1337  using KPS = PreCellularGridSpace;
1338  ASSERT( k < DIM );
1339  ASSERT( uIsValid(p) );
1340  return ( KPS::uKCoord( myCellUpper, k ) - KPS::uKCoord( p, k ) ) >> 1;
1341 }
1342 //-----------------------------------------------------------------------------
1343 template < DGtal::Dimension dim, typename TInteger>
1344 inline
1345 TInteger
1346 DGtal::KhalimskySpaceND< dim, TInteger>::
1347 uDistanceToMin( const Cell & p, DGtal::Dimension k ) const
1348 {
1349  using KPS = PreCellularGridSpace;
1350  ASSERT( k < DIM );
1351  ASSERT( uIsValid(p) );
1352  return ( KPS::uKCoord( p, k ) - KPS::uKCoord( myCellLower, k ) ) >> 1;
1353 }
1354 //-----------------------------------------------------------------------------
1355 template < DGtal::Dimension dim, typename TInteger>
1356 inline
1357 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
1358 DGtal::KhalimskySpaceND< dim, TInteger>::
1359 uTranslation( const Cell & p, const Vector & vec ) const
1360 {
1361  Cell cell( PreCellularGridSpace::uTranslation( p, vec ) );
1362  this->updateCellHelper( cell );
1363  ASSERT( uIsValid( cell ) );
1364  return cell;
1365 }
1366 //-----------------------------------------------------------------------------
1367 template < DGtal::Dimension dim, typename TInteger>
1368 inline
1369 typename DGtal::KhalimskySpaceND< dim, TInteger>::Cell
1370 DGtal::KhalimskySpaceND< dim, TInteger>::
1371 uProjection( const Cell & p, const Cell & bound, DGtal::Dimension k ) const
1372 {
1373  Cell cell( PreCellularGridSpace::uProjection( p, bound, k ) );
1374  ASSERT( uIsValid( cell ) );
1375  return cell;
1376 }
1377 //-----------------------------------------------------------------------------
1378 template < DGtal::Dimension dim, typename TInteger>
1379 inline
1380 void
1381 DGtal::KhalimskySpaceND< dim, TInteger>::
1382 uProject( Cell & p, const Cell & bound, DGtal::Dimension k ) const
1383 {
1384  PreCellularGridSpace::uProject( p.myPreCell, bound, k );
1385  ASSERT( uIsValid( p ) );
1386 }
1387 //-----------------------------------------------------------------------------
1388 template < DGtal::Dimension dim, typename TInteger>
1389 inline
1390 bool
1391 DGtal::KhalimskySpaceND< dim, TInteger>::
1392 uNext( Cell & p, const Cell & lower, const Cell & upper ) const
1393 {
1394  ASSERT( uIsValid(p) );
1395  ASSERT( uIsValid(lower) );
1396  ASSERT( uIsValid(upper) );
1397  ASSERT( uTopology(p) == uTopology(lower)
1398  && uTopology(p) == uTopology(upper) );
1399 
1400  using KPS = PreCellularGridSpace;
1401 
1402  DGtal::Dimension k = NumberTraits<Dimension>::ZERO;
1403  if ( KPS::uKCoord( p, k ) == KPS::uKCoord( upper, k ) )
1404  {
1405  if ( p == upper ) return false;
1406  KPS::uProject( p.myPreCell, lower, k );
1407 
1408  for ( k = 1; k < DIM; ++k )
1409  {
1410  if ( KPS::uKCoord( p, k ) == KPS::uKCoord( upper, k ) )
1411  KPS::uProject( p.myPreCell, lower, k );
1412  else
1413  {
1414  KPS::uSetKCoord( p.myPreCell, k, this->returnKCoordHelper( KPS::uKCoord( p, k ) + 2, k ) );
1415  break;
1416  }
1417  }
1418  return true;
1419  }
1420 
1421  KPS::uSetKCoord( p.myPreCell, k, this->returnKCoordHelper( KPS::uKCoord( p, k ) + 2, k ) );
1422  return true;
1423 }
1424 
1425 //-----------------------------------------------------------------------------
1426 ///////////////////////////////////////////////////////////////////////////////
1427 //-----------------------------------------------------------------------------
1428 //-----------------------------------------------------------------------------
1429 template < DGtal::Dimension dim, typename TInteger>
1430 inline
1431 typename DGtal::KhalimskySpaceND< dim, TInteger>::Integer
1432 DGtal::KhalimskySpaceND< dim, TInteger>::
1433 sFirst( const SPreCell & p, DGtal::Dimension k ) const
1434 {
1435  ASSERT( k < DIM );
1436 
1437  return myClosure[ k ] == OPEN ?
1438  2 * myLower[ k ] + ( NumberTraits<Integer>::odd( p.coordinates[ k ] ) ? 1 : 2 )
1439  : 2 * myLower[ k ] + ( NumberTraits<Integer>::odd( p.coordinates[ k ] ) ? 1 : 0 );
1440 }
1441 //-----------------------------------------------------------------------------
1442 template < DGtal::Dimension dim, typename TInteger>
1443 inline
1444 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCell
1445 DGtal::KhalimskySpaceND< dim, TInteger >::
1446 sFirst( const SPreCell & p ) const
1447 {
1448  SCell cell;
1449  for ( Dimension k = 0; k < dimension; ++k )
1450  PreCellularGridSpace::sSetKCoord( cell.mySPreCell, k, sFirst( p, k ) );
1451 
1452  PreCellularGridSpace::sSetSign( cell.mySPreCell, PreCellularGridSpace::sSign( p ) );
1453 
1454  return cell;
1455 }
1456 //-----------------------------------------------------------------------------
1457 template < DGtal::Dimension dim, typename TInteger>
1458 inline
1459 typename DGtal::KhalimskySpaceND< dim, TInteger>::Integer
1460 DGtal::KhalimskySpaceND< dim, TInteger>::
1461 sLast( const SPreCell & p, DGtal::Dimension k ) const
1462 {
1463  ASSERT( k < DIM );
1464  return myClosure[ k ] == CLOSED ?
1465  2 * myUpper[ k ] + ( NumberTraits<Integer>::odd( p.coordinates[ k ] ) ? 1 : 2 )
1466  : 2 * myUpper[ k ] + ( NumberTraits<Integer>::odd( p.coordinates[ k ] ) ? 1 : 0 );
1467 }
1468 //-----------------------------------------------------------------------------
1469 template < DGtal::Dimension dim, typename TInteger>
1470 inline
1471 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCell
1472 DGtal::KhalimskySpaceND< dim, TInteger >::
1473 sLast( const SPreCell & p ) const
1474 {
1475  SCell cell;
1476  for ( Dimension k = 0; k < dimension; ++k )
1477  PreCellularGridSpace::sSetKCoord( cell.mySPreCell, k, sLast( p, k ) );
1478 
1479  PreCellularGridSpace::sSetSign( cell.mySPreCell, PreCellularGridSpace::sSign( p ) );
1480 
1481  return cell;
1482 }
1483 //-----------------------------------------------------------------------------
1484 template < DGtal::Dimension dim, typename TInteger>
1485 inline
1486 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCell
1487 DGtal::KhalimskySpaceND< dim, TInteger >::
1488 sGetIncr( const SCell & p, DGtal::Dimension k ) const
1489 {
1490  SCell cell( PreCellularGridSpace::sGetIncr( p, k ) );
1491  this->updateSCellHelper( cell, k );
1492  ASSERT( sIsValid( cell ) );
1493  return cell;
1494 }
1495 //-----------------------------------------------------------------------------
1496 template < DGtal::Dimension dim, typename TInteger>
1497 inline
1498 bool
1499 DGtal::KhalimskySpaceND< dim, TInteger >::
1500 sIsMax( const SCell & p, DGtal::Dimension k ) const
1501 {
1502  ASSERT( k < DIM );
1503  ASSERT( sIsInside(p) );
1504  return
1505  ! this->isDimensionPeriodicHelper( k )
1506  && PreCellularGridSpace::sKCoord( p, k ) >= sLast( p, k );
1507 }
1508 //-----------------------------------------------------------------------------
1509 template < DGtal::Dimension dim, typename TInteger>
1510 inline
1511 bool
1512 DGtal::KhalimskySpaceND< dim, TInteger>::
1513 sIsInside( const SPreCell & p, DGtal::Dimension k ) const
1514 {
1515  return cIsInside( p.coordinates, k );
1516 }
1517 //-----------------------------------------------------------------------------
1518 template < DGtal::Dimension dim, typename TInteger>
1519 inline
1520 bool
1521 DGtal::KhalimskySpaceND< dim, TInteger>::
1522 sIsInside( const SPreCell & p ) const
1523 {
1524  return cIsInside( p.coordinates );
1525 }
1526 //-----------------------------------------------------------------------------
1527 template < DGtal::Dimension dim, typename TInteger>
1528 inline
1529 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCell
1530 DGtal::KhalimskySpaceND< dim, TInteger >::
1531 sGetMax( SCell p, DGtal::Dimension k ) const
1532 {
1533  PreCellularGridSpace::sSetKCoord( p.mySPreCell, k, sLast( p, k ) );
1534  ASSERT( sIsValid( p ) );
1535  return p;
1536 }
1537 //-----------------------------------------------------------------------------
1538 template < DGtal::Dimension dim, typename TInteger>
1539 inline
1540 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCell
1541 DGtal::KhalimskySpaceND< dim, TInteger >::
1542 sGetDecr( const SCell & p, DGtal::Dimension k ) const
1543 {
1544  SCell cell( PreCellularGridSpace::sGetDecr( p, k ) );
1545  this->updateSCellHelper( cell, k );
1546  ASSERT( sIsValid( cell ) );
1547  return cell;
1548 }
1549 //-----------------------------------------------------------------------------
1550 template < DGtal::Dimension dim, typename TInteger>
1551 inline
1552 bool
1553 DGtal::KhalimskySpaceND< dim, TInteger >::
1554 sIsMin( const SCell & p, DGtal::Dimension k ) const
1555 {
1556  ASSERT( k < DIM );
1557  ASSERT( sIsInside(p) );
1558  return
1559  ! this->isDimensionPeriodicHelper( k )
1560  && PreCellularGridSpace::sKCoord( p, k ) <= sFirst( p, k );
1561 }
1562 //-----------------------------------------------------------------------------
1563 template < DGtal::Dimension dim, typename TInteger>
1564 inline
1565 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCell
1566 DGtal::KhalimskySpaceND< dim, TInteger >::
1567 sGetMin( SCell p, DGtal::Dimension k ) const
1568 {
1569  PreCellularGridSpace::sSetKCoord( p.mySPreCell, k, sFirst( p, k ) );
1570  ASSERT( sIsValid( p ) );
1571  return p;
1572 }
1573 //-----------------------------------------------------------------------------
1574 template < DGtal::Dimension dim, typename TInteger>
1575 inline
1576 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCell
1577 DGtal::KhalimskySpaceND< dim, TInteger >::
1578 sGetAdd( const SCell & p, DGtal::Dimension k, Integer x ) const
1579 {
1580  SCell cell( PreCellularGridSpace::sGetAdd( p, k, x ) );
1581  this->updateSCellHelper( cell, k );
1582  ASSERT( sIsValid( cell ) );
1583  return cell;
1584 }
1585 //-----------------------------------------------------------------------------
1586 template < DGtal::Dimension dim, typename TInteger>
1587 inline
1588 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCell
1589 DGtal::KhalimskySpaceND< dim, TInteger >::
1590 sGetSub( const SCell & p, DGtal::Dimension k, Integer x ) const
1591 {
1592  SCell cell( PreCellularGridSpace::sGetSub( p, k, x ) );
1593  this->updateSCellHelper( cell, k );
1594  ASSERT( sIsValid( cell ) );
1595  return cell;
1596 }
1597 //-----------------------------------------------------------------------------
1598 template < DGtal::Dimension dim, typename TInteger>
1599 inline
1600 TInteger
1601 DGtal::KhalimskySpaceND< dim, TInteger >::
1602 sDistanceToMax( const SCell & p, DGtal::Dimension k ) const
1603 {
1604  using KPS = PreCellularGridSpace;
1605  ASSERT( k < DIM );
1606  ASSERT( sIsValid( p ) );
1607  return ( KPS::uKCoord( myCellUpper, k ) - KPS::sKCoord( p, k ) ) >> 1;
1608 }
1609 //-----------------------------------------------------------------------------
1610 template < DGtal::Dimension dim, typename TInteger>
1611 inline
1612 TInteger
1613 DGtal::KhalimskySpaceND< dim, TInteger >::
1614 sDistanceToMin( const SCell & p, DGtal::Dimension k ) const
1615 {
1616  using KPS = PreCellularGridSpace;
1617  ASSERT( k < DIM );
1618  ASSERT( sIsValid( p ) );
1619  return ( KPS::sKCoord( p, k ) - KPS::uKCoord( myCellLower, k ) ) >> 1;
1620 }
1621 //-----------------------------------------------------------------------------
1622 template < DGtal::Dimension dim, typename TInteger>
1623 inline
1624 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCell
1625 DGtal::KhalimskySpaceND< dim, TInteger >::
1626 sTranslation( const SCell & p, const Vector & vec ) const
1627 {
1628  SCell cell( PreCellularGridSpace::sTranslation( p, vec ) );
1629  this->updateSCellHelper( cell );
1630  ASSERT( sIsValid( cell ) );
1631  return cell;
1632 }
1633 //-----------------------------------------------------------------------------
1634 template < DGtal::Dimension dim, typename TInteger>
1635 inline
1636 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCell
1637 DGtal::KhalimskySpaceND< dim, TInteger >::
1638 sProjection( const SCell & p, const SCell & bound, DGtal::Dimension k ) const
1639 {
1640  SCell cell( PreCellularGridSpace::sProjection( p, bound, k ) );
1641  ASSERT( sIsValid( cell ) );
1642  return cell;
1643 }
1644 //-----------------------------------------------------------------------------
1645 template < DGtal::Dimension dim, typename TInteger>
1646 inline
1647 void
1648 DGtal::KhalimskySpaceND< dim, TInteger >::
1649 sProject( SCell & p, const SCell & bound, DGtal::Dimension k ) const
1650 {
1651  PreCellularGridSpace::sProject( p.mySPreCell, bound, k );
1652  ASSERT( sIsValid( p ) );
1653 }
1654 //-----------------------------------------------------------------------------
1655 template < DGtal::Dimension dim, typename TInteger>
1656 inline
1657 bool
1658 DGtal::KhalimskySpaceND< dim, TInteger >::
1659 sNext( SCell & p, const SCell & lower, const SCell & upper ) const
1660 {
1661  ASSERT( sIsValid(p) );
1662  ASSERT( sIsValid(lower) );
1663  ASSERT( sIsValid(upper) );
1664  ASSERT( sTopology(p) == sTopology(lower)
1665  && sTopology(p) == sTopology(upper) );
1666 
1667  using KPS = PreCellularGridSpace;
1668 
1669  DGtal::Dimension k = NumberTraits<Dimension>::ZERO;
1670  if ( KPS::sKCoord( p, k ) == KPS::sKCoord( upper, k ) )
1671  {
1672  if ( p == upper ) return false;
1673  KPS::sProject( p.mySPreCell, lower, k );
1674 
1675  for ( k = 1; k < DIM; ++k )
1676  {
1677  if ( KPS::sKCoord( p, k ) == KPS::sKCoord( upper, k ) )
1678  KPS::sProject( p.mySPreCell, lower, k );
1679  else
1680  {
1681  KPS::sSetKCoord( p.mySPreCell, k, this->returnKCoordHelper( KPS::sKCoord( p, k ) + 2, k ) );
1682  break;
1683  }
1684  }
1685  return true;
1686  }
1687 
1688  KPS::sSetKCoord( p.mySPreCell, k, this->returnKCoordHelper( KPS::sKCoord( p, k ) + 2, k ) );
1689  return true;
1690 }
1691 
1692 //-----------------------------------------------------------------------------
1693 // ----------------------- Neighborhood services --------------------------
1694 //-----------------------------------------------------------------------------
1695 template < DGtal::Dimension dim, typename TInteger>
1696 inline
1697 typename DGtal::KhalimskySpaceND< dim, TInteger >::Cells
1698 DGtal::KhalimskySpaceND< dim, TInteger >::
1699 uNeighborhood( const Cell & c ) const
1700 {
1701  ASSERT( uIsValid(c) );
1702 
1703  Cells N;
1704  N.push_back( c );
1705  for ( DGtal::Dimension k = 0; k < DIM; ++k )
1706  {
1707  if ( ! uIsMin( c, k ) )
1708  N.push_back( uGetDecr( c, k ) );
1709  if ( ! uIsMax( c, k ) )
1710  N.push_back( uGetIncr( c, k ) );
1711  }
1712  return N;
1713 }
1714 //-----------------------------------------------------------------------------
1715 template < DGtal::Dimension dim, typename TInteger>
1716 inline
1717 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCells
1718 DGtal::KhalimskySpaceND< dim, TInteger >::
1719 sNeighborhood( const SCell & c ) const
1720 {
1721  ASSERT( sIsValid(c) );
1722 
1723  SCells N;
1724  N.push_back( c );
1725  for ( DGtal::Dimension k = 0; k < DIM; ++k )
1726  {
1727  if ( ! sIsMin( c, k ) )
1728  N.push_back( sGetDecr( c, k ) );
1729  if ( ! sIsMax( c, k ) )
1730  N.push_back( sGetIncr( c, k ) );
1731  }
1732  return N;
1733 }
1734 //-----------------------------------------------------------------------------
1735 template < DGtal::Dimension dim, typename TInteger>
1736 inline
1737 typename DGtal::KhalimskySpaceND< dim, TInteger >::Cells
1738 DGtal::KhalimskySpaceND< dim, TInteger >::
1739 uProperNeighborhood( const Cell & c ) const
1740 {
1741  ASSERT( uIsValid(c) );
1742 
1743  Cells N;
1744  for ( DGtal::Dimension k = 0; k < DIM; ++k )
1745  {
1746  if ( ! uIsMin( c, k ) )
1747  N.push_back( uGetDecr( c, k ) );
1748  if ( ! uIsMax( c, k ) )
1749  N.push_back( uGetIncr( c, k ) );
1750  }
1751  return N;
1752 }
1753 //-----------------------------------------------------------------------------
1754 template < DGtal::Dimension dim, typename TInteger>
1755 inline
1756 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCells
1757 DGtal::KhalimskySpaceND< dim, TInteger >::
1758 sProperNeighborhood( const SCell & c ) const
1759 {
1760  ASSERT( sIsValid(c) );
1761 
1762  SCells N;
1763  for ( DGtal::Dimension k = 0; k < DIM; ++k )
1764  {
1765  if ( ! sIsMin( c, k ) )
1766  N.push_back( sGetDecr( c, k ) );
1767  if ( ! sIsMax( c, k ) )
1768  N.push_back( sGetIncr( c, k ) );
1769  }
1770  return N;
1771 }
1772 //-----------------------------------------------------------------------------
1773 template < DGtal::Dimension dim, typename TInteger>
1774 inline
1775 typename DGtal::KhalimskySpaceND< dim, TInteger >::Cell
1776 DGtal::KhalimskySpaceND< dim, TInteger >::
1777 uAdjacent( const Cell & p, DGtal::Dimension k, bool up ) const
1778 {
1779  ASSERT( k < DIM );
1780  ASSERT( uIsValid(p) );
1781  ASSERT( ( up && !uIsMax(p, k) ) || ( !up && !uIsMin(p, k) ) );
1782  return up ? uGetIncr( p, k ) : uGetDecr( p, k );
1783 }
1784 //-----------------------------------------------------------------------------
1785 template < DGtal::Dimension dim, typename TInteger>
1786 inline
1787 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCell
1788 DGtal::KhalimskySpaceND< dim, TInteger >::
1789 sAdjacent( const SCell & p, DGtal::Dimension k, bool up ) const
1790 {
1791  ASSERT( k < DIM );
1792  ASSERT( sIsValid(p) );
1793  ASSERT( ( up && !sIsMax(p, k) ) || ( !up && !sIsMin(p, k) ) );
1794  return up ? sGetIncr( p, k ) : sGetDecr( p, k );
1795 }
1796 
1797 // ----------------------- Incidence services --------------------------
1798 //-----------------------------------------------------------------------------
1799 template < DGtal::Dimension dim, typename TInteger>
1800 inline
1801 typename DGtal::KhalimskySpaceND< dim, TInteger >::Cell
1802 DGtal::KhalimskySpaceND< dim, TInteger >::
1803 uIncident( const Cell & c, DGtal::Dimension k, bool up ) const
1804 {
1805  ASSERT( k < dim );
1806  ASSERT( uIsValid(c) );
1807  ASSERT( this->isDimensionPeriodicHelper( k ) || ( ! up ) || ( uKCoord( c, k ) < uKCoord( myCellUpper, k ) ) );
1808  ASSERT( this->isDimensionPeriodicHelper( k ) || ( up ) || ( uKCoord( myCellLower, k ) < uKCoord( c, k ) ) );
1809 
1810  Cell cell( PreCellularGridSpace::uIncident( c, k, up ) );
1811  this->updateCellHelper( cell, k );
1812 
1813  return cell;
1814 }
1815 //-----------------------------------------------------------------------------
1816 template < DGtal::Dimension dim, typename TInteger>
1817 inline
1818 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCell
1819 DGtal::KhalimskySpaceND< dim, TInteger >::
1820 sIncident( const SCell & c, DGtal::Dimension k, bool up ) const
1821 {
1822  ASSERT( k < dim );
1823  ASSERT( sIsValid(c) );
1824  ASSERT( this->isDimensionPeriodicHelper( k ) || ( ! up ) || ( sKCoord( c, k ) < uKCoord( myCellUpper, k ) ) );
1825  ASSERT( this->isDimensionPeriodicHelper( k ) || ( up ) || ( uKCoord( myCellLower, k ) < sKCoord( c, k ) ) );
1826 
1827  SCell cell( PreCellularGridSpace::sIncident( c, k, up ) );
1828  this->updateSCellHelper( cell, k );
1829 
1830  return cell;
1831 }
1832 //-----------------------------------------------------------------------------
1833 template < DGtal::Dimension dim, typename TInteger>
1834 inline
1835 typename DGtal::KhalimskySpaceND< dim, TInteger >::Cells
1836 DGtal::KhalimskySpaceND< dim, TInteger >::
1837 uLowerIncident( const Cell & c ) const
1838 {
1839  ASSERT( uIsValid(c) );
1840 
1841  Cells N;
1842  for ( DirIterator q = uDirs( c ); q != 0; ++q )
1843  {
1844  const DGtal::Dimension k = *q;
1845  if ( this->isDimensionPeriodicHelper( k ) )
1846  {
1847  N.push_back( uIncident( c, k, false ) );
1848  N.push_back( uIncident( c, k, true ) );
1849  }
1850  else
1851  {
1852  const Integer x = uKCoord( c, k );
1853  if ( PreCellularGridSpace::uKCoord( myCellLower, k ) < x )
1854  N.push_back( uIncident( c, k, false ) );
1855  if ( x < PreCellularGridSpace::uKCoord( myCellUpper, k ) )
1856  N.push_back( uIncident( c, k, true ) );
1857  }
1858  }
1859  return N;
1860 }
1861 //-----------------------------------------------------------------------------
1862 template < DGtal::Dimension dim, typename TInteger>
1863 inline
1864 typename DGtal::KhalimskySpaceND< dim, TInteger >::Cells
1865 DGtal::KhalimskySpaceND< dim, TInteger >::
1866 uUpperIncident( const Cell & c ) const
1867 {
1868  ASSERT( uIsValid(c) );
1869 
1870  Cells N;
1871  for ( DirIterator q = uOrthDirs( c ); q != 0; ++q )
1872  {
1873  const DGtal::Dimension k = *q;
1874  if ( this->isDimensionPeriodicHelper( k ) )
1875  {
1876  N.push_back( uIncident( c, k, false ) );
1877  N.push_back( uIncident( c, k, true ) );
1878  }
1879  else
1880  {
1881  const Integer x = uKCoord( c, k );
1882  if ( PreCellularGridSpace::uKCoord( myCellLower, k ) < x )
1883  N.push_back( uIncident( c, k, false ) );
1884  if ( x < PreCellularGridSpace::uKCoord( myCellUpper, k ) )
1885  N.push_back( uIncident( c, k, true ) );
1886  }
1887  }
1888  return N;
1889 }
1890 //-----------------------------------------------------------------------------
1891 template < DGtal::Dimension dim, typename TInteger>
1892 inline
1893 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCells
1894 DGtal::KhalimskySpaceND< dim, TInteger >::
1895 sLowerIncident( const SCell & c ) const
1896 {
1897  ASSERT( sIsValid(c) );
1898 
1899  SCells N;
1900  for ( DirIterator q = sDirs( c ); q != 0; ++q )
1901  {
1902  const DGtal::Dimension k = *q;
1903  if ( this->isDimensionPeriodicHelper( k ) )
1904  {
1905  N.push_back( sIncident( c, k, false ) );
1906  N.push_back( sIncident( c, k, true ) );
1907  }
1908  else
1909  {
1910  const Integer x = sKCoord( c, k );
1911  if ( PreCellularGridSpace::uKCoord( myCellLower, k ) < x )
1912  N.push_back( sIncident( c, k, false ) );
1913  if ( x < PreCellularGridSpace::uKCoord( myCellUpper, k ) )
1914  N.push_back( sIncident( c, k, true ) );
1915  }
1916  }
1917  return N;
1918 }
1919 //-----------------------------------------------------------------------------
1920 template < DGtal::Dimension dim, typename TInteger>
1921 inline
1922 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCells
1923 DGtal::KhalimskySpaceND< dim, TInteger >::
1924 sUpperIncident( const SCell & c ) const
1925 {
1926  ASSERT( sIsValid(c) );
1927 
1928  SCells N;
1929  for ( DirIterator q = sOrthDirs( c ); q != 0; ++q )
1930  {
1931  const DGtal::Dimension k = *q;
1932  if ( this->isDimensionPeriodicHelper( k ) )
1933  {
1934  N.push_back( sIncident( c, k, false ) );
1935  N.push_back( sIncident( c, k, true ) );
1936  }
1937  else
1938  {
1939  const Integer x = sKCoord( c, k );
1940  if ( PreCellularGridSpace::uKCoord( myCellLower, k ) < x )
1941  N.push_back( sIncident( c, k, false ) );
1942  if ( x < PreCellularGridSpace::uKCoord( myCellUpper, k ) )
1943  N.push_back( sIncident( c, k, true ) );
1944  }
1945  }
1946  return N;
1947 }
1948 //-----------------------------------------------------------------------------
1949 template < DGtal::Dimension dim, typename TInteger>
1950 inline
1951 void
1952 DGtal::KhalimskySpaceND< dim, TInteger >::
1953 uAddFaces( Cells& faces, const Cell& c, Dimension axis ) const
1954 {
1955  using KPS = PreCellularGridSpace;
1956 
1957  const DGtal::Dimension dim_of_c = uDim( c );
1958  if ( axis >= dim_of_c ) return;
1959 
1960  DirIterator q = uDirs( c );
1961  for ( Dimension i = 0; i < axis; ++i ) ++q;
1962 
1963  // We test incident cells existence within the current Khalimsky space.
1964  const Integer x = KPS::uKCoord( c, *q );
1965  bool has_f1 = this->isDimensionPeriodicHelper( *q ) || KPS::uKCoord( myCellLower, *q ) < x ;
1966  bool has_f2 = this->isDimensionPeriodicHelper( *q ) || x < KPS::uKCoord( myCellUpper, *q ) ;
1967 
1968  Cell f1, f2;
1969  if ( has_f1 ) f1 = uIncident( c, *q, false );
1970  if ( has_f2 ) f2 = uIncident( c, *q, true );
1971 
1972  if ( has_f1 ) faces.push_back( f1 );
1973  if ( has_f2 ) faces.push_back( f2 );
1974 
1975  if ( has_f1 ) uAddFaces( faces, f1, axis );
1976  if ( has_f2 ) uAddFaces( faces, f2, axis );
1977 
1978  uAddFaces( faces, c, axis+1 );
1979 }
1980 //-----------------------------------------------------------------------------
1981 template < DGtal::Dimension dim, typename TInteger>
1982 inline
1983 void
1984 DGtal::KhalimskySpaceND< dim, TInteger >::
1985 uAddCoFaces( Cells& cofaces, const Cell& c, Dimension axis ) const
1986 {
1987  using KPS = PreCellularGridSpace;
1988 
1989  const DGtal::Dimension dim_of_c = uDim( c );
1990  if ( axis >= dimension - dim_of_c ) return;
1991 
1992  DirIterator q = uOrthDirs( c );
1993  for ( Dimension i = 0; i < axis; ++i ) ++q;
1994 
1995  // We test incident cells existence within the current Khalimsky space.
1996  const Integer x = KPS::uKCoord( c, *q );
1997  bool has_f1 = this->isDimensionPeriodicHelper( *q ) || KPS::uKCoord( myCellLower, *q ) < x ;
1998  bool has_f2 = this->isDimensionPeriodicHelper( *q ) || x < KPS::uKCoord( myCellUpper, *q ) ;
1999 
2000  Cell f1, f2;
2001  if ( has_f1 ) f1 = uIncident( c, *q, false );
2002  if ( has_f2 ) f2 = uIncident( c, *q, true );
2003 
2004  if ( has_f1 ) cofaces.push_back( f1 );
2005  if ( has_f2 ) cofaces.push_back( f2 );
2006 
2007  if ( has_f1 ) uAddCoFaces( cofaces, f1, axis );
2008  if ( has_f2 ) uAddCoFaces( cofaces, f2, axis );
2009 
2010  uAddCoFaces( cofaces, c, axis+1 );
2011 }
2012 //-----------------------------------------------------------------------------
2013 template < DGtal::Dimension dim, typename TInteger>
2014 inline
2015 typename DGtal::KhalimskySpaceND< dim, TInteger >::Cells
2016 DGtal::KhalimskySpaceND< dim, TInteger >::
2017 uFaces( const Cell & c ) const
2018 {
2019  ASSERT( uIsValid(c) );
2020 
2021  Cells N;
2022  uAddFaces( N, c, 0 );
2023  return N;
2024 }
2025 //-----------------------------------------------------------------------------
2026 template < DGtal::Dimension dim, typename TInteger>
2027 inline
2028 typename DGtal::KhalimskySpaceND< dim, TInteger >::Cells
2029 DGtal::KhalimskySpaceND< dim, TInteger >::
2030 uCoFaces( const Cell & c ) const
2031 {
2032  ASSERT( uIsValid(c) );
2033 
2034  Cells N;
2035  uAddCoFaces( N, c, 0 );
2036  return N;
2037 }
2038 //-----------------------------------------------------------------------------
2039 template < DGtal::Dimension dim, typename TInteger>
2040 inline
2041 bool
2042 DGtal::KhalimskySpaceND< dim, TInteger >::
2043 sDirect( const SCell & p, DGtal::Dimension k ) const
2044 {
2045  return PreCellularGridSpace::sDirect( p, k );
2046 }
2047 //-----------------------------------------------------------------------------
2048 template < DGtal::Dimension dim, typename TInteger>
2049 inline
2050 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCell
2051 DGtal::KhalimskySpaceND< dim, TInteger >::
2052 sDirectIncident( const SCell & p, DGtal::Dimension k ) const
2053 {
2054  using KPS = PreCellularGridSpace;
2055 
2056  ASSERT( k < dim );
2057  ASSERT( sIsValid(p) );
2058  ASSERT( this->isDimensionPeriodicHelper( k ) || ( ! KPS::sDirect( p, k ) ) || ( KPS::sKCoord( p, k ) < KPS::uKCoord( myCellUpper, k ) ) );
2059  ASSERT( this->isDimensionPeriodicHelper( k ) || ( KPS::sDirect( p, k ) ) || ( KPS::uKCoord( myCellLower, k ) < KPS::sKCoord( p, k ) ) );
2060 
2061  SCell cell( KPS::sDirectIncident( p, k ) );
2062  this->updateSCellHelper( cell, k );
2063 
2064  return cell;
2065 }
2066 //-----------------------------------------------------------------------------
2067 template < DGtal::Dimension dim, typename TInteger>
2068 inline
2069 typename DGtal::KhalimskySpaceND< dim, TInteger >::SCell
2070 DGtal::KhalimskySpaceND< dim, TInteger >::
2071 sIndirectIncident( const SCell & p, DGtal::Dimension k ) const
2072 {
2073  using KPS = PreCellularGridSpace;
2074 
2075  ASSERT( k < dim );
2076  ASSERT( sIsValid(p) );
2077  ASSERT( this->isDimensionPeriodicHelper( k ) || ( KPS::sDirect( p, k ) ) || ( KPS::sKCoord( p, k ) < KPS::uKCoord( myCellUpper, k ) ) );
2078  ASSERT( this->isDimensionPeriodicHelper( k ) || ( ! KPS::sDirect( p, k ) ) || ( KPS::uKCoord( myCellLower, k ) < KPS::sKCoord( p, k ) ) );
2079 
2080  SCell cell( KPS::sIndirectIncident( p, k ) );
2081  this->updateSCellHelper( cell, k );
2082 
2083  return cell;
2084 }
2085 
2086 
2087 
2088 
2089 //-----------------------------------------------------------------------------
2090 template < DGtal::Dimension dim, typename TInteger>
2091 inline
2092 void
2093 DGtal::KhalimskySpaceND< dim, TInteger>::
2094 selfDisplay ( std::ostream & out ) const
2095 {
2096  out << "[KhalimskySpaceND<" << dimension << ">] { ";
2097  out << "{ ";
2098  for ( Dimension i = 0; i < dimension; ++i )
2099  out << ( myClosure[i] == OPEN ? "OPEN " : ( myClosure[i] == CLOSED ? "CLOSED " : "PERIODIC " ) );
2100  out << "}, ";
2101  out << "lower = " << myLower << ", ";
2102  out << "upper = " << myUpper;
2103  out << " }";
2104 
2105 }
2106 //-----------------------------------------------------------------------------
2107 template < DGtal::Dimension dim, typename TInteger>
2108 inline
2109 bool
2110 DGtal::KhalimskySpaceND< dim, TInteger>::
2111 isValid() const
2112 {
2113  return true;
2114 }
2115 
2116 
2117 
2118 ///////////////////////////////////////////////////////////////////////////////
2119 // Implementation of inline functions //
2120 template < DGtal::Dimension dim, typename TInteger>
2121 inline
2122 std::ostream&
2123 DGtal::operator<< ( std::ostream & out,
2124  const KhalimskySpaceND< dim, TInteger> & object )
2125 {
2126  object.selfDisplay( out );
2127  return out;
2128 }
2129 
2130 // //
2131 ///////////////////////////////////////////////////////////////////////////////