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