DGtal  0.6.devel
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
KhalimskySpaceND.ih
1 
30 
31 #include "DGtal/io/Color.h"
33 
35 // IMPLEMENTATION of static constants
37 
38 #if (!defined(WIN32))
39 /*template < Dimension dim, typename TInteger >
40 const Dimension
41 DGtal::KhalimskySpaceND< dim, TInteger >::dimension = dim;
42 */
43 template < Dimension dim, typename TInteger >
44 const Dimension
46 
47 template < Dimension dim, typename TInteger >
50 
51 template < Dimension dim, typename TInteger >
54 #endif
55 
57 // IMPLEMENTATION of inline methods.
59 
61 // KhalimskyCell
63 //-----------------------------------------------------------------------------
64 template < Dimension dim, typename TInteger >
65 inline
67 {
68 }
69 //-----------------------------------------------------------------------------
70 template < Dimension dim, typename TInteger >
71 inline
73 KhalimskyCell( const KhalimskyCell & other )
74  : myCoordinates( other.myCoordinates )
75 {
76 }
77 //-----------------------------------------------------------------------------
78 template < Dimension dim, typename TInteger >
79 inline
81 KhalimskyCell( const Point & p )
82  : myCoordinates( p )
83 {
84 }
85 //-----------------------------------------------------------------------------
86 template < Dimension dim, typename TInteger >
87 inline
90 operator=( const KhalimskyCell & other )
91 {
92  if ( this != &other )
93  myCoordinates = other.myCoordinates;
94  return *this;
95 }
96 //-----------------------------------------------------------------------------
97 template < Dimension dim, typename TInteger >
98 inline
99 bool
101 operator==( const KhalimskyCell & other ) const
102 {
103  return myCoordinates == other.myCoordinates;
104 }
105 //-----------------------------------------------------------------------------
106 template < Dimension dim, typename TInteger >
107 inline
108 bool
110 operator!=( const KhalimskyCell & other ) const
111 {
112  return myCoordinates != other.myCoordinates;
113 }
114 //-----------------------------------------------------------------------------
115 template < Dimension dim, typename TInteger >
116 inline
117 bool
119 operator<( const KhalimskyCell & other ) const
120 {
121  return myCoordinates < other.myCoordinates;
122 }
123 //-----------------------------------------------------------------------------
124 template < Dimension dim, typename TInteger >
125 inline
126 std::ostream &
127 DGtal::operator<<( std::ostream & out,
128  const KhalimskyCell< dim, TInteger > & object )
129 {
130  out << "(" << object.myCoordinates[ 0 ];
131  for ( Dimension i = 1; i < dim; ++i )
132  out << "," << object.myCoordinates[ i ];
133  out << ")";
134  return out;
135 }
136 
137 //------------------------------------------------------------------------------
138 template < Dimension dim, typename TInteger >
139 inline
140 std::string
142 className() const
143 {
144  return "KhalimskyCell";
145 }
146 
148 // SignedKhalimskyCell
150 //-----------------------------------------------------------------------------
151 template < Dimension dim, typename TInteger >
152 inline
154 {
155 }
156 //-----------------------------------------------------------------------------
157 template < Dimension dim, typename TInteger >
158 inline
161  : myCoordinates( other.myCoordinates), myPositive( other.myPositive )
162 {
163 }
164 //-----------------------------------------------------------------------------
165 template < Dimension dim, typename TInteger >
166 inline
168 SignedKhalimskyCell( const Point & p, bool positive )
169  : myCoordinates( p ), myPositive( positive )
170 {
171 }
172 //-----------------------------------------------------------------------------
173 template < Dimension dim, typename TInteger >
174 inline
178 {
179  if ( this != &other )
180  {
181  myCoordinates = other.myCoordinates;
182  myPositive = other.myPositive;
183  }
184  return *this;
185 }
186 //-----------------------------------------------------------------------------
187 template < Dimension dim, typename TInteger >
188 inline
189 bool
191 operator==( const SignedKhalimskyCell & other ) const
192 {
193  return ( myPositive == other.myPositive )
194  && ( myCoordinates == other.myCoordinates );
195 }
196 //-----------------------------------------------------------------------------
197 template < Dimension dim, typename TInteger >
198 inline
199 bool
201 operator!=( const SignedKhalimskyCell & other ) const
202 {
203  return ( myPositive != other.myPositive )
204  || ( myCoordinates != other.myCoordinates );
205 }
206 //-----------------------------------------------------------------------------
207 template < Dimension dim, typename TInteger >
208 inline
209 bool
211 operator<( const SignedKhalimskyCell & other ) const
212 {
213  return ( myPositive < other.myPositive )
214  || ( ( myPositive == other.myPositive )
215  && ( myCoordinates < other.myCoordinates ) );
216 }
217 //-----------------------------------------------------------------------------
218 template < Dimension dim,
219  typename TInteger >
220 inline
221 std::ostream &
222 DGtal::operator<<( std::ostream & out,
223  const SignedKhalimskyCell< dim, TInteger > & object )
224 {
225  out << "(" << object.myCoordinates[ 0 ];
226  for ( Dimension i = 1; i < dim; ++i )
227  out << "," << object.myCoordinates[ i ];
228  out << "," << ( object.myPositive ? '+' : '-' );
229  out << ")";
230  return out;
231 }
232 
233 //------------------------------------------------------------------------------
234 template < Dimension dim, typename TInteger >
235 inline
236 std::string
238 className() const
239 {
240  return "SignedKhalimskyCell";
241 }
242 
244 // CellDirectionIterator
246 //-----------------------------------------------------------------------------
247 template < Dimension dim, typename TInteger >
248 inline
250 CellDirectionIterator( Cell cell, bool open )
251  : myDir( 0 ), myCell( cell ), myOpen( open )
252 {
253  find();
254 }
255 //-----------------------------------------------------------------------------
256 template < Dimension dim, typename TInteger >
257 inline
259 CellDirectionIterator( SCell scell, bool open )
260  : myDir( 0 ), myCell( scell.myCoordinates ), myOpen( open )
261 {
262  find();
263 }
264 //-----------------------------------------------------------------------------
265 template < Dimension dim, typename TInteger >
266 inline
269 operator*() const
270 {
271  return myDir;
272 }
273 //-----------------------------------------------------------------------------
274 template < Dimension dim, typename TInteger >
275 inline
279 {
280  ++myDir;
281  find();
282  return *this;
283 }
284 //-----------------------------------------------------------------------------
285 template < Dimension dim, typename TInteger >
286 inline
287 bool
289 operator!=( const Integer ) const
290 {
291  return myDir < dim;
292 }
293 //-----------------------------------------------------------------------------
294 template < Dimension dim, typename TInteger >
295 inline
296 bool
298 end() const
299 {
300  return myDir >= dim;
301 }
302 //-----------------------------------------------------------------------------
303 template < Dimension dim, typename TInteger >
304 inline
305 bool
307 operator!=( const CellDirectionIterator & other ) const
308 {
309  return myDir != other.myDir;
310 }
311 //-----------------------------------------------------------------------------
312 template < Dimension dim, typename TInteger >
313 inline
314 bool
316 operator==( const CellDirectionIterator & other ) const
317 {
318  return myDir == other.myDir;
319 }
320 //-----------------------------------------------------------------------------
321 template < Dimension dim, typename TInteger >
322 inline
323 void
326 {
327  if ( myOpen ) // loop on open coordinates
328  while ( ( myDir != dim )
329  && ( ( myCell.myCoordinates[ myDir ] & 0x1 ) == 0 ) )
330  ++myDir;
331  else // myOpen is false, loop on closed coordinates
332  while ( ( myDir != dim )
333  && ( myCell.myCoordinates[ myDir ] & 0x1 ) )
334  ++myDir;
335 }
336 
337 
339 // KhalimskySpaceND
342 // ----------------------- Standard services ------------------------------
343 //-----------------------------------------------------------------------------
344 template < Dimension dim, typename TInteger>
345 inline
348 {
349 }
350 //-----------------------------------------------------------------------------
351 template < Dimension dim, typename TInteger>
352 inline
355 {
356  Point low, high;
357  for ( Dimension i = 0; i < dimension; ++i )
358  {
359  low[ i ] = NumberTraits< Integer >::min() / 2 + 1;
360  high[ i ] = NumberTraits< Integer >::max() / 2 - 1;
361  }
362  init( low, high, true );
363 }
364 //-----------------------------------------------------------------------------
365 template < Dimension dim, typename TInteger>
366 inline
369  : myLower(other.myLower), myUpper(other.myUpper),
370  myCellLower(other.myCellLower), myCellUpper(other.myCellUpper),
371  myIsClosed(other.myIsClosed) { }
372 //-----------------------------------------------------------------------------
373 template < Dimension dim, typename TInteger>
374 inline
377 operator= ( const KhalimskySpaceND & other )
378 {
379  if ( this != &other )
380  {
381  myLower = other.myLower;
382  myUpper = other.myUpper;
383  myCellLower = other.myCellLower;
384  myCellUpper = other.myCellUpper;
385  myIsClosed = other.myIsClosed;
386  }
387  return *this;
388 }
389 //-----------------------------------------------------------------------------
390 template < Dimension dim, typename TInteger>
391 inline
392 bool
394 init( const Point & lower,
395  const Point & upper,
396  bool closed )
397 {
398  myIsClosed = closed;
399  myLower = lower;
400  myUpper = upper;
402  {
403  for ( Dimension i = 0; i < dimension; ++i )
404  {
405  if ( ( lower[ i ]
406  <= ( NumberTraits< Integer >::min() / 2 ) )
407  || ( upper[ i ]
408  >= ( NumberTraits< Integer >::max() / 2 ) ) )
409  return false;
410  }
411  }
412  for ( Dimension i = 0; i < dimension; ++i )
413  {
414  myCellLower.myCoordinates[ i ] = ( lower[ i ] * 2 )
415  + ( closed ? 0 : 1 );
416  myCellUpper.myCoordinates[ i ] = ( upper[ i ] * 2 )
417  + ( closed ? 2 : 1 );
418  }
419  return true;
420 }
421 //-----------------------------------------------------------------------------
422 template < Dimension dim, typename TInteger>
423 inline
426 size( Dimension k ) const
427 {
428  ASSERT( k < dimension );
429  return myUpper[ k ] + NumberTraits<Integer>::ONE - myLower[ k ];
430 }
431 //-----------------------------------------------------------------------------
432 template < Dimension dim, typename TInteger>
433 inline
434 TInteger
436 min( Dimension k ) const
437 {
438  return myLower[ k ];
439 }
440 //-----------------------------------------------------------------------------
441 template < Dimension dim, typename TInteger>
442 inline
443 TInteger
445 max( Dimension k ) const
446 {
447  return myUpper[ k ];
448 }
449 //-----------------------------------------------------------------------------
450 template < Dimension dim, typename TInteger>
451 inline
454 lowerBound() const
455 {
456  return myLower;
457 }
458 //-----------------------------------------------------------------------------
459 template < Dimension dim, typename TInteger>
460 inline
463 upperBound() const
464 {
465  return myUpper;
466 }
467 //-----------------------------------------------------------------------------
468 template < Dimension dim, typename TInteger>
469 inline
472 lowerCell() const
473 {
474  return myCellLower;
475 }
476 //-----------------------------------------------------------------------------
477 template < Dimension dim, typename TInteger>
478 inline
481 upperCell() const
482 {
483  return myCellUpper;
484 }
485 //-----------------------------------------------------------------------------
486 template < Dimension dim, typename TInteger>
487 inline
488 bool
491 {
492  return myIsClosed;
493 }
494 
495 //-----------------------------------------------------------------------------
496 template < Dimension dim, typename TInteger>
497 inline
500 uCell( const Point & kp ) const
501 {
502  return Cell( kp );
503 }
504 //-----------------------------------------------------------------------------
505 template < Dimension dim, typename TInteger>
506 inline
509 uCell( const Point & p, const Cell & c ) const
510 {
511  Cell nc( p );
512  for ( Dimension i = 0; i < DIM; ++i )
513  nc.myCoordinates[ i ] += p[ i ] + ( c.myCoordinates[ i ] & 0x1 );
514  return nc;
515 }
516 //-----------------------------------------------------------------------------
517 template < Dimension dim, typename TInteger>
518 inline
521 sCell( const Point & kp, Sign sign ) const
522 {
523  return SCell( kp, sign == POS );
524 }
525 //-----------------------------------------------------------------------------
526 template < Dimension dim, typename TInteger>
527 inline
530 sCell( const Point & p, const SCell & c ) const
531 {
532  SCell nc( p, c.myPositive );
533  for ( Dimension i = 0; i < DIM; ++i )
534  nc.myCoordinates[ i ] += p[ i ] + ( c.myCoordinates[ i ] & 0x1 );
535  return nc;
536 }
537 //-----------------------------------------------------------------------------
538 template < Dimension dim, typename TInteger>
539 inline
542 uSpel( const Point & p ) const
543 {
544  Cell nc( p );
545  for ( Dimension i = 0; i < DIM; ++i )
546  nc.myCoordinates[ i ] += p[ i ] + 1;
547  return nc;
548 }
549 //-----------------------------------------------------------------------------
550 template < Dimension dim, typename TInteger>
551 inline
554 sSpel( const Point & p, Sign sign ) const
555 {
556  SCell nc( p, sign );
557  for ( Dimension i = 0; i < DIM; ++i )
558  nc.myCoordinates[ i ] += p[ i ] + 1;
559  return nc;
560 }
561 //-----------------------------------------------------------------------------
562 template < Dimension dim, typename TInteger>
563 inline
566 uPointel( const Point & p ) const
567 {
568  Cell nc( p );
569  for ( Dimension i = 0; i < DIM; ++i )
570  nc.myCoordinates[ i ] += p[ i ];
571  return nc;
572 }
573 //-----------------------------------------------------------------------------
574 template < Dimension dim, typename TInteger>
575 inline
578 sPointel( const Point & p, Sign sign ) const
579 {
580  SCell nc( p, sign );
581  for ( Dimension i = 0; i < DIM; ++i )
582  nc.myCoordinates[ i ] += p[ i ];
583  return nc;
584 }
585 //-----------------------------------------------------------------------------
587 //-----------------------------------------------------------------------------
588 template < Dimension dim, typename TInteger>
589 inline
592 uKCoord( const Cell & c, Dimension k ) const
593 {
594  ASSERT( k < DIM );
595  return c.myCoordinates[ k ];
596 }
597 //-----------------------------------------------------------------------------
598 template < Dimension dim, typename TInteger>
599 inline
602 uCoord( const Cell & c, Dimension k ) const
603 {
604  ASSERT( k < DIM );
605  return c.myCoordinates[ k ] >> 1;
606 }
607 //-----------------------------------------------------------------------------
608 template < Dimension dim, typename TInteger>
609 inline
612 uKCoords( const Cell & c ) const
613 {
614  return c.myCoordinates;
615 }
616 //-----------------------------------------------------------------------------
617 template < Dimension dim, typename TInteger>
618 inline
621 uCoords( const Cell & c ) const
622 {
623  Point dp;
624  for ( Dimension i = 0; i < DIM; ++i )
625  dp[ i ] = c.myCoordinates[ i ] >> 1;
626  return dp;
627 }
628 //-----------------------------------------------------------------------------
629 template < Dimension dim, typename TInteger>
630 inline
633 sKCoord( const SCell & c, Dimension k ) const
634 {
635  ASSERT( k < DIM );
636  return c.myCoordinates[ k ];
637 }
638 //-----------------------------------------------------------------------------
639 template < Dimension dim, typename TInteger>
640 inline
643 sCoord( const SCell & c, Dimension k ) const
644 {
645  ASSERT( k < DIM );
646  return c.myCoordinates[ k ] >> 1;
647 }
648 //-----------------------------------------------------------------------------
649 template < Dimension dim, typename TInteger>
650 inline
653 sKCoords( const SCell & c ) const
654 {
655  return c.myCoordinates;
656 }
657 //-----------------------------------------------------------------------------
658 template < Dimension dim, typename TInteger>
659 inline
662 sCoords( const SCell & c ) const
663 {
664  Point dp;
665  for ( Dimension i = 0; i < DIM; ++i )
666  dp[ i ] = c.myCoordinates[ i ] >> 1;
667  return dp;
668 }
669 //-----------------------------------------------------------------------------
670 template < Dimension dim, typename TInteger>
671 inline
674 sSign( const SCell & c ) const
675 {
676  return c.myPositive ? POS : NEG;
677 }
678 //-----------------------------------------------------------------------------
679 template < Dimension dim, typename TInteger>
680 inline
683 signs( const Cell & p, Sign s ) const
684 {
685  return sCell( p.myCoordinates, s );
686 }
687 //-----------------------------------------------------------------------------
688 template < Dimension dim, typename TInteger>
689 inline
692 unsigns( const SCell & p ) const
693 {
694  return uCell( p.myCoordinates );
695 }
696 //-----------------------------------------------------------------------------
697 template < Dimension dim, typename TInteger>
698 inline
701 sOpp( const SCell & p ) const
702 {
703  return sCell( p.myCoordinates, ! p.myPositive );
704 }
705 //-----------------------------------------------------------------------------
706 template < Dimension dim, typename TInteger>
707 inline
708 void
710 uSetKCoord( Cell & c, Dimension k, const Integer & i ) const
711 {
712  ASSERT( k < DIM
713  && myCellLower.myCoordinates[ k ] <= i
714  && i <= myCellUpper.myCoordinates[ k ] );
715  c.myCoordinates[ k ] = i;
716 }
717 //-----------------------------------------------------------------------------
718 template < Dimension dim, typename TInteger>
719 inline
720 void
722 sSetKCoord( SCell & c, Dimension k, const Integer & i ) const
723 {
724  ASSERT( k < DIM
725  && myCellLower.myCoordinates[ k ] <= i
726  && i <= myCellUpper.myCoordinates[ k ] );
727  c.myCoordinates[ k ] = i;
728 }
729 //-----------------------------------------------------------------------------
730 template < Dimension dim, typename TInteger>
731 inline
732 void
734 uSetCoord( Cell & c, Dimension k, Integer i ) const
735 {
736  ASSERT( k < DIM );
737  i = ( i << 1 ) + ( c.myCoordinates[ k ] & 1 );
738  ASSERT( myCellLower.myCoordinates[ k ] <= i
739  && i <= myCellUpper.myCoordinates[ k ] );
740  c.myCoordinates[ k ] = i;
741 }
742 //-----------------------------------------------------------------------------
743 template < Dimension dim, typename TInteger>
744 inline
745 void
747 sSetCoord( SCell & c, Dimension k, Integer i ) const
748 {
749  ASSERT( k < DIM );
750  i = ( i << 1 ) + ( c.myCoordinates[ k ] & 1 );
751  ASSERT( myCellLower.myCoordinates[ k ] <= i
752  && i <= myCellUpper.myCoordinates[ k ] );
753  c.myCoordinates[ k ] = i;
754 }
755 //-----------------------------------------------------------------------------
756 template < Dimension dim, typename TInteger>
757 inline
758 void
760 uSetKCoords( Cell & c, const Point & kp ) const
761 {
762  c.myCoordinates = kp;
763 }
764 //-----------------------------------------------------------------------------
765 template < Dimension dim, typename TInteger>
766 inline
767 void
769 sSetKCoords( SCell & c, const Point & kp ) const
770 {
771  c.myCoordinates = kp;
772 }
773 //-----------------------------------------------------------------------------
774 template < Dimension dim, typename TInteger>
775 inline
776 void
778 uSetCoords( Cell & c, const Point & p ) const
779 {
780  Integer i;
781  for ( Dimension k = 0; k < DIM; ++k )
782  {
783  i = ( p[ k ] << 1 ) + ( c.myCoordinates[ k ] & 1 );
784  ASSERT( myCellLower.myCoordinates[ k ] <= i
785  && i <= myCellUpper.myCoordinates[ k ] );
786  c.myCoordinates[ k ] = i;
787  }
788 }
789 //-----------------------------------------------------------------------------
790 template < Dimension dim, typename TInteger>
791 inline
792 void
794 sSetCoords( SCell & c, const Point & p ) const
795 {
796  Integer i;
797  for ( Dimension k = 0; k < DIM; ++k )
798  {
799  i = ( p[ k ] << 1 ) + ( c.myCoordinates[ k ] & 1 );
800  ASSERT( myCellLower.myCoordinates[ k ] <= i
801  && i <= myCellUpper.myCoordinates[ k ] );
802  c.myCoordinates[ k ] = i;
803  }
804 }
805 //-----------------------------------------------------------------------------
806 template < Dimension dim, typename TInteger>
807 inline
808 void
810 sSetSign( SCell & c, Sign s ) const
811 {
812  c.myPositive = ( s == POS );
813 }
814 //-----------------------------------------------------------------------------
815 // ------------------------- Cell topology services -----------------------
816 //-----------------------------------------------------------------------------
817 template < Dimension dim, typename TInteger>
818 inline
819 TInteger
821 uTopology( const Cell & p ) const
822 {
825  for ( Dimension k = 0; k < DIM; ++k )
826  {
828  i |= j;
829  j <<= 1;
830  }
831  return i;
832 }
833 //-----------------------------------------------------------------------------
834 template < Dimension dim, typename TInteger>
835 inline
836 TInteger
838 sTopology( const SCell & p ) const
839 {
842  for ( Dimension k = 0; k < DIM; ++k )
843  {
845  i |= j;
846  j <<= 1;
847  }
848  return i;
849 }
850 //-----------------------------------------------------------------------------
851 template < Dimension dim, typename TInteger>
852 inline
853 Dimension
855 uDim( const Cell & p ) const
856 {
858  for ( Dimension k = 0; k < DIM; ++k )
860  ++i;
861  return i;
862 }
863 //-----------------------------------------------------------------------------
864 template < Dimension dim, typename TInteger>
865 inline
866 Dimension
868 sDim( const SCell & p ) const
869 {
871  for ( Dimension k = 0; k < DIM; ++k )
873  ++i;
874  return i;
875 }
876 //-----------------------------------------------------------------------------
877 template < Dimension dim, typename TInteger>
878 inline
879 bool
881 uIsSurfel( const Cell & b ) const
882 {
883  return uDim( b ) == ( DIM - 1 );
884 }
885 //-----------------------------------------------------------------------------
886 template < Dimension dim, typename TInteger>
887 inline
888 bool
890 sIsSurfel( const SCell & b ) const
891 {
892  return sDim( b ) == ( DIM - 1 );
893 }
894 //-----------------------------------------------------------------------------
895 template < Dimension dim, typename TInteger>
896 inline
897 bool
899 uIsOpen( const Cell & p, Dimension k ) const
900 {
902 }
903 //-----------------------------------------------------------------------------
904 template < Dimension dim, typename TInteger>
905 inline
906 bool
908 sIsOpen( const SCell & p, Dimension k ) const
909 {
911 }
912 
913 //-----------------------------------------------------------------------------
915 //-----------------------------------------------------------------------------
916 template < Dimension dim, typename TInteger>
917 inline
920 uDirs( const Cell & p ) const
921 {
922  return DirIterator( p, true );
923 }
924 //-----------------------------------------------------------------------------
925 template < Dimension dim, typename TInteger>
926 inline
929 sDirs( const SCell & p ) const
930 {
931  return DirIterator( p, true );
932 }
933 //-----------------------------------------------------------------------------
934 template < Dimension dim, typename TInteger>
935 inline
938 uOrthDirs( const Cell & p ) const
939 {
940  return DirIterator( p, false );
941 }
942 //-----------------------------------------------------------------------------
943 template < Dimension dim, typename TInteger>
944 inline
947 sOrthDirs( const SCell & p ) const
948 {
949  return DirIterator( p, false );
950 }
951 //-----------------------------------------------------------------------------
952 template < Dimension dim, typename TInteger>
953 inline
954 Dimension
956 uOrthDir( const Cell & s ) const
957 {
958  DirIterator it( s, false );
959  ASSERT( ! it.end() );
960  return *it;
961 }
962 //-----------------------------------------------------------------------------
963 template < Dimension dim, typename TInteger>
964 inline
965 Dimension
967 sOrthDir( const SCell & s ) const
968 {
969  DirIterator it( s, false );
970  ASSERT( ! it.end() );
971  return *it;
972 }
973 //-----------------------------------------------------------------------------
975 //-----------------------------------------------------------------------------
976 //-----------------------------------------------------------------------------
977 template < Dimension dim, typename TInteger>
978 inline
981 uFirst( const Cell & p ) const
982 {
983  return uCell( myLower, p );
984 }
985 //-----------------------------------------------------------------------------
986 template < Dimension dim, typename TInteger>
987 inline
990 uLast( const Cell & p ) const
991 {
992  return uCell( myUpper, p );
993 }
994 //-----------------------------------------------------------------------------
995 template < Dimension dim, typename TInteger>
996 inline
999 uGetIncr( const Cell & p, Dimension k ) const
1000 {
1001  Cell q = p;
1002  q.myCoordinates[ k ] += 2;
1003  return q;
1004 }
1005 //-----------------------------------------------------------------------------
1006 template < Dimension dim, typename TInteger>
1007 inline
1008 bool
1010 uIsMax( const Cell & p, Dimension k ) const
1011 {
1012  return p.myCoordinates[ k ] >= myCellUpper.myCoordinates[ k ];
1013 }
1014 //-----------------------------------------------------------------------------
1015 template < Dimension dim, typename TInteger>
1016 inline
1017 bool
1019 uIsInside( const Cell & p, Dimension k ) const
1020 {
1021  return (p.myCoordinates[ k ] <= uLast(p).myCoordinates[ k ]) &&
1022  (p.myCoordinates[ k ] >= uFirst(p).myCoordinates[ k ]);
1023 }
1024 //-----------------------------------------------------------------------------
1025 template < Dimension dim, typename TInteger>
1026 inline
1029 uGetMax( const Cell & p, Dimension k ) const
1030 {
1031  return uProjection( p, uLast(p), k );
1032  // return uProjection( p, myCellUpper, k );
1033 }
1034 //-----------------------------------------------------------------------------
1035 template < Dimension dim, typename TInteger>
1036 inline
1039 uGetDecr( const Cell & p, Dimension k ) const
1040 {
1041  Cell q = p;
1042  q.myCoordinates[ k ] -= 2;
1043  return q;
1044 }
1045 //-----------------------------------------------------------------------------
1046 template < Dimension dim, typename TInteger>
1047 inline
1048 bool
1050 uIsMin( const Cell & p, Dimension k ) const
1051 {
1052  return p.myCoordinates[ k ] <= myCellLower.myCoordinates[ k ];
1053 }
1054 //-----------------------------------------------------------------------------
1055 template < Dimension dim, typename TInteger>
1056 inline
1059 uGetMin( const Cell & p, Dimension k ) const
1060 {
1061  return uProjection( p, uFirst(p), k );
1062  //return uProjection( p, myCellLower, k );
1063 }
1064 //-----------------------------------------------------------------------------
1065 template < Dimension dim, typename TInteger>
1066 inline
1069 uGetAdd( const Cell & p, Dimension k, const Integer & x ) const
1070 {
1071  Cell q = p;
1072  q.myCoordinates[ k ] += 2*x;
1073  return q;
1074 }
1075 //-----------------------------------------------------------------------------
1076 template < Dimension dim, typename TInteger>
1077 inline
1080 uGetSub( const Cell & p, Dimension k, const Integer & x ) const
1081 {
1082  Cell q = p;
1083  q.myCoordinates[ k ] -= 2*x;
1084  return q;
1085 }
1086 //-----------------------------------------------------------------------------
1087 template < Dimension dim, typename TInteger>
1088 inline
1089 TInteger
1091 uDistanceToMax( const Cell & p, Dimension k ) const
1092 {
1093  return ( myCellUpper.myCoordinates[ k ] - p.myCoordinates[ k ] ) >> 1;
1094 }
1095 //-----------------------------------------------------------------------------
1096 template < Dimension dim, typename TInteger>
1097 inline
1098 TInteger
1100 uDistanceToMin( const Cell & p, Dimension k ) const
1101 {
1102  return ( p.myCoordinates[ k ] - myCellLower.myCoordinates[ k ] ) >> 1;
1103 }
1104 //-----------------------------------------------------------------------------
1105 template < Dimension dim, typename TInteger>
1106 inline
1109 uTranslation( const Cell & p, const Vector & vec ) const
1110 {
1111  Cell q = p;
1112  for ( Dimension k = 0; k < DIM; ++k )
1113  q.myCoordinates[ k ] += ( vec[ k ] << 1 );
1114  return q;
1115 }
1116 //-----------------------------------------------------------------------------
1117 template < Dimension dim, typename TInteger>
1118 inline
1121 uProjection( const Cell & p, const Cell & bound, Dimension k ) const
1122 {
1123  Cell q = p;
1124  q.myCoordinates[ k ] = bound.myCoordinates[ k ];
1125  return q;
1126 }
1127 //-----------------------------------------------------------------------------
1128 template < Dimension dim, typename TInteger>
1129 inline
1130 void
1132 uProject( Cell & p, const Cell & bound, Dimension k ) const
1133 {
1134  p.myCoordinates[ k ] = bound.myCoordinates[ k ];
1135 }
1136 //-----------------------------------------------------------------------------
1137 template < Dimension dim, typename TInteger>
1138 inline
1139 bool
1141 uNext( Cell & p, const Cell & lower, const Cell & upper ) const
1142 {
1144  if ( uCoord( p, k ) == uCoord( upper, k ) )
1145  {
1146  if ( p == upper ) return false;
1147  uProject( p, lower, k );
1148  for ( k = 1; k < DIM; ++k )
1149  {
1150  if ( uCoord( p, k ) == uCoord( upper, k ) )
1151  uProject( p, lower, k );
1152  else
1153  {
1154  p.myCoordinates[ k ] += 2;
1155  break;
1156  }
1157  }
1158  return true;
1159  }
1160  p.myCoordinates[ k ] += 2;
1161  return true;
1162 }
1163 
1164 //-----------------------------------------------------------------------------
1166 //-----------------------------------------------------------------------------
1167 //-----------------------------------------------------------------------------
1168 template < Dimension dim, typename TInteger>
1169 inline
1172 sFirst( const SCell & p ) const
1173 {
1174  return sCell( myLower, p );
1175 }
1176 //-----------------------------------------------------------------------------
1177 template < Dimension dim, typename TInteger>
1178 inline
1181 sLast( const SCell & p ) const
1182 {
1183  return sCell( myUpper, p );
1184 }
1185 //-----------------------------------------------------------------------------
1186 template < Dimension dim, typename TInteger>
1187 inline
1190 sGetIncr( const SCell & p, Dimension k ) const
1191 {
1192  SCell q = p;
1193  q.myCoordinates[ k ] += 2;
1194  return q;
1195 }
1196 //-----------------------------------------------------------------------------
1197 template < Dimension dim, typename TInteger>
1198 inline
1199 bool
1201 sIsMax( const SCell & p, Dimension k ) const
1202 {
1203  return p.myCoordinates[ k ] >= myCellUpper.myCoordinates[ k ];
1204 }
1205 //-----------------------------------------------------------------------------
1206 template < Dimension dim, typename TInteger>
1207 inline
1208 bool
1210 sIsInside( const SCell & p, Dimension k ) const
1211 {
1212  return (p.myCoordinates[ k ] <= sLast(p).myCoordinates[ k ]) &&
1213  (p.myCoordinates[ k ] >= sFirst(p).myCoordinates[ k ]);
1214 }
1215 //-----------------------------------------------------------------------------
1216 template < Dimension dim, typename TInteger>
1217 inline
1220 sGetMax( const SCell & p, Dimension k ) const
1221 {
1222  return sProjection( p, sLast(p), k );
1223  // return sProjection( p, myCellUpper, k );
1224 }
1225 //-----------------------------------------------------------------------------
1226 template < Dimension dim, typename TInteger>
1227 inline
1230 sGetDecr( const SCell & p, Dimension k ) const
1231 {
1232  SCell q = p;
1233  q.myCoordinates[ k ] -= 2;
1234  return q;
1235 }
1236 //-----------------------------------------------------------------------------
1237 template < Dimension dim, typename TInteger>
1238 inline
1239 bool
1241 sIsMin( const SCell & p, Dimension k ) const
1242 {
1243  return p.myCoordinates[ k ] <= myCellLower.myCoordinates[ k ];
1244 }
1245 //-----------------------------------------------------------------------------
1246 template < Dimension dim, typename TInteger>
1247 inline
1250 sGetMin( const SCell & p, Dimension k ) const
1251 {
1252  return sProjection( p, sFirst(p), k );
1253  // return sProjection( p, myCellLower, k );
1254 }
1255 //-----------------------------------------------------------------------------
1256 template < Dimension dim, typename TInteger>
1257 inline
1260 sGetAdd( const SCell & p, Dimension k, const Integer & x ) const
1261 {
1262  SCell q = p;
1263  q.myCoordinates[ k ] += 2*x;
1264  return q;
1265 }
1266 //-----------------------------------------------------------------------------
1267 template < Dimension dim, typename TInteger>
1268 inline
1271 sGetSub( const SCell & p, Dimension k, const Integer & x ) const
1272 {
1273  SCell q = p;
1274  q.myCoordinates[ k ] -= 2*x;
1275  return q;
1276 }
1277 //-----------------------------------------------------------------------------
1278 template < Dimension dim, typename TInteger>
1279 inline
1280 TInteger
1282 sDistanceToMax( const SCell & p, Dimension k ) const
1283 {
1284  return ( myCellUpper.myCoordinates[ k ] - p.myCoordinates[ k ] ) >> 1;
1285 }
1286 //-----------------------------------------------------------------------------
1287 template < Dimension dim, typename TInteger>
1288 inline
1289 TInteger
1291 sDistanceToMin( const SCell & p, Dimension k ) const
1292 {
1293  return ( p.myCoordinates[ k ] - myCellLower.myCoordinates[ k ] ) >> 1;
1294 }
1295 //-----------------------------------------------------------------------------
1296 template < Dimension dim, typename TInteger>
1297 inline
1300 sTranslation( const SCell & p, const Vector & vec ) const
1301 {
1302  SCell q = p;
1303  for ( Dimension k = 0; k < DIM; ++k )
1304  q.myCoordinates[ k ] += ( vec[ k ] << 1 );
1305  return q;
1306 }
1307 //-----------------------------------------------------------------------------
1308 template < Dimension dim, typename TInteger>
1309 inline
1312 sProjection( const SCell & p, const SCell & bound, Dimension k ) const
1313 {
1314  SCell q = p;
1315  q.myCoordinates[ k ] = bound.myCoordinates[ k ];
1316  return q;
1317 }
1318 //-----------------------------------------------------------------------------
1319 template < Dimension dim, typename TInteger>
1320 inline
1321 void
1323 sProject( SCell & p, const SCell & bound, Dimension k ) const
1324 {
1325  p.myCoordinates[ k ] = bound.myCoordinates[ k ];
1326 }
1327 //-----------------------------------------------------------------------------
1328 template < Dimension dim, typename TInteger>
1329 inline
1330 bool
1332 sNext( SCell & p, const SCell & lower, const SCell & upper ) const
1333 {
1335  if ( sCoord( p, k ) == sCoord( upper, k ) )
1336  {
1337  if ( p == upper ) return false;
1338  sProject( p, lower, k );
1339  for ( k = 1; k < DIM; ++k )
1340  {
1341  if ( sCoord( p, k ) == sCoord( upper, k ) )
1342  sProject( p, lower, k );
1343  else
1344  {
1345  p.myCoordinates[ k ] += 2;
1346  break;
1347  }
1348  }
1349  return true;
1350  }
1351  p.myCoordinates[ k ] += 2;
1352  return true;
1353 }
1354 
1355 //-----------------------------------------------------------------------------
1356 // ----------------------- Neighborhood services --------------------------
1357 //-----------------------------------------------------------------------------
1358 template < Dimension dim, typename TInteger>
1359 inline
1362 uNeighborhood( const Cell & c ) const
1363 {
1364  Cells N;
1365  N.push_back( c );
1366  for ( Dimension k = 0; k < DIM; ++k )
1367  {
1368  if ( ! uIsMin( c, k ) )
1369  N.push_back( uGetDecr( c, k ) );
1370  if ( ! uIsMax( c, k ) )
1371  N.push_back( uGetIncr( c, k ) );
1372  }
1373  return N;
1374 }
1375 //-----------------------------------------------------------------------------
1376 template < Dimension dim, typename TInteger>
1377 inline
1380 sNeighborhood( const SCell & c ) const
1381 {
1382  SCells N;
1383  N.push_back( c );
1384  for ( Dimension k = 0; k < DIM; ++k )
1385  {
1386  if ( ! sIsMin( c, k ) )
1387  N.push_back( sGetDecr( c, k ) );
1388  if ( ! sIsMax( c, k ) )
1389  N.push_back( sGetIncr( c, k ) );
1390  }
1391  return N;
1392 }
1393 //-----------------------------------------------------------------------------
1394 template < Dimension dim, typename TInteger>
1395 inline
1398 uProperNeighborhood( const Cell & c ) const
1399 {
1400  Cells N;
1401  for ( Dimension k = 0; k < DIM; ++k )
1402  {
1403  if ( ! uIsMin( c, k ) )
1404  N.push_back( uGetDecr( c, k ) );
1405  if ( ! uIsMax( c, k ) )
1406  N.push_back( uGetIncr( c, k ) );
1407  }
1408  return N;
1409 }
1410 //-----------------------------------------------------------------------------
1411 template < Dimension dim, typename TInteger>
1412 inline
1415 sProperNeighborhood( const SCell & c ) const
1416 {
1417  SCells N;
1418  for ( Dimension k = 0; k < DIM; ++k )
1419  {
1420  if ( ! sIsMin( c, k ) )
1421  N.push_back( sGetDecr( c, k ) );
1422  if ( ! sIsMax( c, k ) )
1423  N.push_back( sGetIncr( c, k ) );
1424  }
1425  return N;
1426 }
1427 //-----------------------------------------------------------------------------
1428 template < Dimension dim, typename TInteger>
1429 inline
1432 uAdjacent( const Cell & p, Dimension k, bool up ) const
1433 {
1434  return up ? uGetIncr( p, k ) : uGetDecr( p, k );
1435 }
1436 //-----------------------------------------------------------------------------
1437 template < Dimension dim, typename TInteger>
1438 inline
1441 sAdjacent( const SCell & p, Dimension k, bool up ) const
1442 {
1443  return up ? sGetIncr( p, k ) : sGetDecr( p, k );
1444 }
1445 
1446 // ----------------------- Incidence services --------------------------
1447 //-----------------------------------------------------------------------------
1448 template < Dimension dim, typename TInteger>
1449 inline
1452 uIncident( const Cell & c, Dimension k, bool up ) const
1453 {
1454  ASSERT( k < dim );
1455  ASSERT( ( ! up ) || ( uKCoord( c, k ) < uKCoord( myCellUpper, k ) ) );
1456  ASSERT( ( up ) || ( uKCoord( myCellLower, k ) < uKCoord( c, k ) ) );
1457  Cell d( c );
1458  if ( up ) ++d.myCoordinates[ k ];
1459  else --d.myCoordinates[ k ];
1460  return d;
1461 }
1462 //-----------------------------------------------------------------------------
1463 template < Dimension dim, typename TInteger>
1464 inline
1467 sIncident( const SCell & c, Dimension k, bool up ) const
1468 {
1469  ASSERT( k < dim );
1470  ASSERT( ( ! up ) || ( sKCoord( c, k ) < uKCoord( myCellUpper, k ) ) );
1471  ASSERT( ( up ) || ( uKCoord( myCellLower, k ) < sKCoord( c, k ) ) );
1472  SCell d( c );
1473  bool sign = up ? d.myPositive : ! d.myPositive;
1474  for ( Dimension i = 0; i <= k; ++i )
1475  if ( sIsOpen( d, i ) )
1476  sign = ! sign;
1477  d.myPositive = sign;
1478  if ( up ) ++d.myCoordinates[ k ];
1479  else --d.myCoordinates[ k ];
1480  return d;
1481 }
1482 //-----------------------------------------------------------------------------
1483 template < Dimension dim, typename TInteger>
1484 inline
1487 uLowerIncident( const Cell & c ) const
1488 {
1489  Cells N;
1490  for ( DirIterator q = uDirs( c ); q != 0; ++q )
1491  {
1492  Dimension k = *q;
1493  Integer x = uKCoord( c, k );
1494  if ( uKCoord( myCellLower, k ) < x )
1495  N.push_back( uIncident( c, k, false ) );
1496  if ( x < uKCoord( myCellUpper, k ) )
1497  N.push_back( uIncident( c, k, true ) );
1498  }
1499  return N;
1500 }
1501 //-----------------------------------------------------------------------------
1502 template < Dimension dim, typename TInteger>
1503 inline
1506 uUpperIncident( const Cell & c ) const
1507 {
1508  Cells N;
1509  for ( DirIterator q = uOrthDirs( c ); q != 0; ++q )
1510  {
1511  Dimension k = *q;
1512  Integer x = uKCoord( c, k );
1513  if ( uKCoord( myCellLower, k ) < x )
1514  N.push_back( uIncident( c, k, false ) );
1515  if ( x < uKCoord( myCellUpper, k ) )
1516  N.push_back( uIncident( c, k, true ) );
1517  }
1518  return N;
1519 }
1520 //-----------------------------------------------------------------------------
1521 template < Dimension dim, typename TInteger>
1522 inline
1525 sLowerIncident( const SCell & c ) const
1526 {
1527  SCells N;
1528  for ( DirIterator q = sDirs( c ); q != 0; ++q )
1529  {
1530  Dimension k = *q;
1531  Integer x = sKCoord( c, k );
1532  if ( uKCoord( myCellLower, k ) < x )
1533  N.push_back( sIncident( c, k, false ) );
1534  if ( x < uKCoord( myCellUpper, k ) )
1535  N.push_back( sIncident( c, k, true ) );
1536  }
1537  return N;
1538 }
1539 //-----------------------------------------------------------------------------
1540 template < Dimension dim, typename TInteger>
1541 inline
1544 sUpperIncident( const SCell & c ) const
1545 {
1546  SCells N;
1547  for ( DirIterator q = sOrthDirs( c ); q != 0; ++q )
1548  {
1549  Dimension k = *q;
1550  Integer x = sKCoord( c, k );
1551  if ( uKCoord( myCellLower, k ) < x )
1552  N.push_back( sIncident( c, k, false ) );
1553  if ( x < uKCoord( myCellUpper, k ) )
1554  N.push_back( sIncident( c, k, true ) );
1555  }
1556  return N;
1557 }
1558 //-----------------------------------------------------------------------------
1559 template < Dimension dim, typename TInteger>
1560 inline
1563 uFaces( const Cell & c ) const
1564 {
1565  Dimension dim_of_c = uDim( c );
1566  Cells N;
1567  Cells P;
1568  std::deque<Dimension> Q;
1569  P.push_back( c );
1570  Q.push_back( dim_of_c );
1571  while ( ! P.empty() )
1572  {
1573  Cell d = P.front(); P.pop_front();
1574  Dimension k = Q.front(); Q.pop_front();
1575  if ( k != dim_of_c ) N.push_back( d );
1576  // the use of k induces that incident faces are not duplicated.
1577  for ( DirIterator q = uDirs( d ); ( q != 0 ) && ( k > 0 ); ++q, --k )
1578  {
1579  P.push_back( uIncident( d, *q, false ) );
1580  Q.push_back( k - 1 );
1581  P.push_back( uIncident( d, *q, true ) );
1582  Q.push_back( k - 1 );
1583  }
1584  }
1585  return N;
1586 }
1587 //-----------------------------------------------------------------------------
1588 template < Dimension dim, typename TInteger>
1589 inline
1592 uCoFaces( const Cell & c ) const
1593 {
1594  Dimension dim_of_c = uDim( c );
1595  Cells N;
1596  Cells P;
1597  std::deque<Dimension> Q;
1598  P.push_back( c );
1599  Q.push_back( dimension - dim_of_c );
1600  while ( ! P.empty() )
1601  {
1602  Cell d = P.front(); P.pop_front();
1603  Dimension k = Q.front(); Q.pop_front();
1604  if ( k != dim_of_c ) N.push_back( d );
1605  // the use of k induces that incident faces are not duplicated.
1606  for ( DirIterator q = uOrthDirs( d ); ( q != 0 ) && ( k > 0 ); ++q, --k )
1607  {
1608  P.push_back( uIncident( d, *q, false ) );
1609  Q.push_back( k - 1 );
1610  P.push_back( uIncident( d, *q, true ) );
1611  Q.push_back( k - 1 );
1612  }
1613  }
1614  return N;
1615 }
1616 //-----------------------------------------------------------------------------
1617 template < Dimension dim, typename TInteger>
1618 inline
1619 bool
1621 sDirect( const SCell & p, Dimension k ) const
1622 {
1623  ASSERT( k < dim );
1624  bool sign = p.myPositive;
1625  for ( Dimension i = 0; i <= k; ++i )
1626  if ( sIsOpen( p, i ) )
1627  sign = ! sign;
1628  return sign;
1629 }
1630 //-----------------------------------------------------------------------------
1631 template < Dimension dim, typename TInteger>
1632 inline
1635 sDirectIncident( const SCell & p, Dimension k ) const
1636 {
1637  ASSERT( k < dim );
1638  SCell d( p );
1639  bool sign = d.myPositive;
1640  for ( Dimension i = 0; i <= k; ++i )
1641  if ( sIsOpen( d, i ) )
1642  sign = ! sign;
1643 
1644  bool up = sign;
1645  d.myPositive = POS;
1646  ASSERT( ( ! up ) || ( sKCoord( d, k ) < uKCoord( myCellUpper, k ) ) );
1647  ASSERT( ( up ) || ( uKCoord( myCellLower, k ) < sKCoord( d, k ) ) );
1648  if ( up ) ++d.myCoordinates[ k ];
1649  else --d.myCoordinates[ k ];
1650 
1651  return d;
1652 }
1653 //-----------------------------------------------------------------------------
1654 template < Dimension dim, typename TInteger>
1655 inline
1658 sIndirectIncident( const SCell & p, Dimension k ) const
1659 {
1660  ASSERT( k < dim );
1661  SCell d( p );
1662  bool sign = d.myPositive;
1663  for ( Dimension i = 0; i <= k; ++i )
1664  if ( sIsOpen( d, i ) )
1665  sign = ! sign;
1666 
1667  bool up = ! sign;
1668  d.myPositive = NEG;
1669  ASSERT( ( ! up ) || ( sKCoord( d, k ) < uKCoord( myCellUpper, k ) ) );
1670  ASSERT( ( up ) || ( uKCoord( myCellLower, k ) < sKCoord( d, k ) ) );
1671 
1672  if ( up ) ++d.myCoordinates[ k ];
1673  else --d.myCoordinates[ k ];
1674 
1675  return d;
1676 }
1677 
1678 
1679 
1680 
1681 //-----------------------------------------------------------------------------
1682 template < Dimension dim, typename TInteger>
1683 inline
1684 void
1686 selfDisplay ( std::ostream & out ) const
1687 {
1688  out << "[KhalimskySpaceND]";
1689 }
1690 //-----------------------------------------------------------------------------
1691 template < Dimension dim, typename TInteger>
1692 inline
1693 bool
1695 isValid() const
1696 {
1697  return true;
1698 }
1699 
1700 
1701 
1703 // Implementation of inline functions //
1704 template < Dimension dim, typename TInteger>
1705 inline
1706 std::ostream&
1707 DGtal::operator<< ( std::ostream & out,
1708  const KhalimskySpaceND< dim, TInteger> & object )
1709 {
1710  object.selfDisplay( out );
1711  return out;
1712 }
1713 
1714 // //
1716 
1717