48 template <
typename TInteger>
52 : myFc( &aChain ), myPos( 0 )
54 if ( n < myFc->
chain.size() )
73 template <
typename TInteger>
88 template <
typename TInteger>
92 if ( myPos < myFc->
chain.size() )
94 switch ( myFc->code( myPos ) )
96 case '0': (myXY.at(0))++;
break;
97 case '1': (myXY.at(1))++;
break;
98 case '2': (myXY.at(0))--;
break;
99 case '3': (myXY.at(1))--;
break;
108 template <
typename TInteger>
112 if ( myPos < myFc->
chain.size() )
114 switch ( myFc->code( myPos ) )
116 case '0': (myXY.at(0))++;
break;
117 case '1': (myXY.at(1))++;
break;
118 case '2': (myXY.at(0))--;
break;
119 case '3': (myXY.at(1))--;
break;
121 myPos = ( myPos + 1 ) % myFc->
chain.size();
126 template <
typename TInteger>
130 if ( myPos == myFc->chain.size() + 1 )
132 myXY = myFc->lastPoint();
139 if ( myPos < myFc->
chain.size() )
141 switch ( myFc->code( myPos ) )
143 case '0': (myXY.at(0))--;
break;
144 case '1': (myXY.at(1))--;
break;
145 case '2': (myXY.at(0))++;
break;
146 case '3': (myXY.at(1))++;
break;
153 template <
typename TInteger>
159 switch ( myFc->code( myPos ) )
161 case '0': (myXY.at(0))--;
break;
162 case '1': (myXY.at(1))--;
break;
163 case '2': (myXY.at(0))++;
break;
164 case '3': (myXY.at(1))++;
break;
181 template <
typename TInteger>
192 template <
typename TInteger>
196 readFromPointsRange(vectPoints.begin(), vectPoints.end(), *
this);
205 template <
typename TInteger>
216 template <
typename TInteger>
218 : chain( aOther.chain ), x0( aOther.x0 ), y0( aOther.y0 ),
219 xn( aOther.xn), yn( aOther.yn)
230 template <
typename TInteger>
234 if (
this != &aOther )
236 chain = aOther.
chain;
253 template <
typename TInteger>
261 template <
typename TInteger>
274 template <
typename TInteger>
279 if ( aPos >= chain.size() )
288 template <
typename TInteger>
292 if ( aPos == 0 ) aPos = chain.
size() - 1;
301 template <
typename TInteger>
305 ASSERT( aPos < chain.size() );
307 return chain[ aPos ];
314 template <
typename TInteger>
323 template <
typename TInteger>
326 TInteger& min_y, TInteger& max_x, TInteger& max_y )
const
335 if ( p.
at(0) < min_x )
338 if ( p.
at(0) > max_x )
340 if ( p.
at(1) < min_y )
343 if ( p.
at(1) > max_y )
349 template <
typename TInteger>
359 while ( ( it != it_end ) && ( it.
getCode() == code1 ) )
361 ASSERT( ( it != it_end )
362 &&
"[DGtal::FreemanChain::findQuadrantChange( OrderedAlphabet & A ) const] 1-letter freeman chain." );
365 while ( ( it != it_end ) && ( ( it.
getCode() == code1 )
366 || ( it.
getCode() == code2 ) ) )
368 ASSERT( ( it != it_end )
369 &&
"[DGtal::FreemanChain::findQuadrantChange( OrderedAlphabet & A ) const] 2-letters Freeman chain." );
373 swap( code1, code2 );
379 while ( it.
getCode() == code2 );
385 while ( A.
order( b_char ) != 1 )
387 if ( A.
order( a_char ) == 0 )
390 while ( A.
order( b_char ) != 1 )
393 ASSERT( ( A.
order( b_char ) == 1 )
394 && ( A.
order( a_char ) == 2 )
395 &&
"[DGtal::FreemanChain::findQuadrantChange( OrderedAlphabet & A ) const] Internal error: invalid Quadrant change found." );
400 template <
typename TInteger>
410 while ( ( it != it_end ) && ( it.
getCode() == code1 ) )
412 ASSERT( ( it != it_end )
413 &&
"[DGtal::FreemanChain::findQuadrantChange( OrderedAlphabet & A ) const] 1-letter freeman chain." );
416 while ( ( it != it_end ) && ( ( it.
getCode() == code1 )
417 || ( it.
getCode() == code2 ) ) )
419 ASSERT( ( it != it_end )
420 &&
"[DGtal::FreemanChain::findQuadrantChange( OrderedAlphabet & A ) const] 2-letters Freeman chain." );
423 while ( ( it != it_end ) && ( ( it.
getCode() == code1 )
425 || ( it.
getCode() == code3 ) ) )
427 ASSERT( ( it != it_end )
428 &&
"[DGtal::FreemanChain::findQuadrantChange( OrderedAlphabet & A ) const] 3-letters Freeman chain." );
437 while ( it.
getCode() == code3 );
443 while ( A.
order( b_char ) != 1 )
445 if ( A.
order( a_char ) == 0 )
448 while ( A.
order( b_char ) != 1 )
451 ASSERT( ( A.
order( b_char ) == 1 )
452 && ( A.
order( a_char ) == 2 )
453 &&
"[DGtal::FreemanChain::findQuadrantChange( OrderedAlphabet & A ) const] Internal error: invalid Quadrant change found." );
458 template <
typename TInteger>
462 return (x0 == xn) && (y0 == yn);
466 template <
typename TInteger>
475 int nb_ccw_turns = 0;
476 while ( it != it_end )
481 char diff = ( code2 - code1 + 4 ) % 4;
492 if ( spos == *it_suiv )
493 return nb_ccw_turns / 4;
499 template <
typename TInteger>
505 Point startPoint = getPoint(pos);
506 Point endPoint = getPoint(pos+n);
507 newChain.
chain = chain.substr(pos,n);
508 newChain.
x0 = startPoint.
at(0);
509 newChain.
y0 = startPoint.
at(1);
510 newChain.
xn = endPoint.
at(0);
511 newChain.
yn = endPoint.
at(1);
516 template <
typename TInteger>
526 newChain.
xn = newLastPoint.
at(0);
527 newChain.
yn = newLastPoint.
at(1);
532 template <
typename TInteger>
537 chain += aOther.
chain;
539 xn = newLastPoint.
at(0);
540 yn = newLastPoint.
at(1);
545 template <
typename TInteger>
551 Size n = this->size();
552 if ( aPos < n / 2 ) {
554 for (
unsigned int i=0; i<aPos; ++i)
562 for (
unsigned int i=0; i<n; ++i) {
571 template <
typename TInteger>
576 chain += std::string( &aCode, 1);
579 displacement( dx, dy, aCode );
589 template <
typename TInteger>
595 for (
unsigned int i=0; i<=n; ++i)
599 Size mySize = size();
600 ASSERT( (n <= mySize) &&
"Tried to shorten a FreemanChain by more then its length");
601 chain.resize( mySize - n );
611 template <
typename TInteger>
615 out << x0 <<
" " << y0 <<
" " << chain;
623 template <
typename TInteger>
642 template <
typename TInteger>
652 if ( ( str.size() > 0 ) && ( str[ 0 ] !=
'#' ) )
654 istringstream str_in( str );
661 template <
typename TInteger>
662 template <
typename TConstIterator>
666 TConstIterator it( itBegin );
670 Point startingPt( *it );
676 Point pt( startingPt );
681 Integer dx = ptSuiv[0] - pt[0];
682 Integer dy = ptSuiv[1] - pt[1];
683 short number = ( dx != 0 ? (1 - dx) : (2 - dy) );
684 if ( (number < 0) || (number > 3) )
686 std::cerr <<
"not connected points (method readFromPointsRange of FreemanChain)" << std::endl;
693 }
while ( it != itEnd );
706 template <
typename TInteger>
707 template <
typename TRange>
712 readFromPointsRange( aRange.begin(), aRange.end(), c );
715 template <
typename TInteger>
718 const FreemanChain & fc, std::vector<Point> & aVContour)
725 aVContour.push_back(*it);
731 template <
typename TInteger>
736 case '0': aPoint.
at(0)++;
break;
737 case '1': aPoint.
at(1)++;
break;
738 case '2': aPoint.
at(0)--;
break;
739 case '3': aPoint.
at(1)--;
break;
773 template <
typename TInteger>
776 char aCode2,
bool ccw )
778 unsigned int cfg = ( ccw ? 0 : 16 ) + ( (aCode1 -
'0') << 2 ) + (aCode2 -
'0');
779 static const char tbl[ 32 ] =
781 '2',
'1',
'0',
'3',
'3',
'2',
'1',
'0',
782 '0',
'3',
'2',
'1',
'1',
'0',
'3',
'2',
783 '2',
'3',
'0',
'1',
'1',
'2',
'3',
'0',
784 '0',
'1',
'2',
'3',
'3',
'0',
'1',
'2'
791 template <
typename TInteger>
795 return '0' + ( ( (code -
'0' ) + n ) & 3 );
802 template <
typename TInteger>
809 case '0': dx = 1; dy = 0;
break;
810 case '1': dx = 0; dy = 1;
break;
811 case '2': dx = -1; dy = 0;
break;
812 case '3': dx = 0; dy = -1;
break;
817 template <
typename TInteger>
822 #ifdef CPP11_INITIALIZER_LIST
825 case '0':
return Point({1,0});
826 case '1':
return Point({0,1});
827 case '2':
return Point({-1,0});
828 case '3':
return Point({0,-1});
836 case '0': t[0]++;
return Point( t );
837 case '1': t[1]++;
return Point( t );
838 case '2': t[0]--;
return Point( t );
839 case '3': t[1]--;
return Point( t );
842 #endif //CPP11_INITIALIZER_LIST
847 template <
typename TInteger>
852 if ( ccw )
return ( aCode ==
'3' ) ?
'0' : ( aCode + 1 );
853 else return ( aCode ==
'0' ) ?
'3' : ( aCode - 1 );
867 template <
typename TInteger>
870 std::vector<unsigned int> & aOuter2inner,
871 std::vector<unsigned int> & aInner2outer,
875 unsigned int nb = (
unsigned int)aOuterChain.
chain.size();
877 aOuter2inner.clear();
878 aOuter2inner.reserve( nb );
880 aInnerChain.
chain =
"";
881 aInner2outer.clear();
882 aInner2outer.reserve( nb + ( ccw ? 4 : -4 ) );
886 int turn = ccw ? 1 : 3;
891 aInnerChain.
x0 = dx0 > 0 ? aOuterChain.
x0 : aOuterChain.
x0 - 1;
892 aInnerChain.
y0 = dy0 > 0 ? aOuterChain.
y0 : aOuterChain.
y0 - 1;
897 for (
unsigned int i = 0; i < nb; ++i )
901 switch ( movement( aOuterChain.
code( i ), aOuterChain.
code( ( i + 1 ) % nb ), ccw ) )
909 aInnerChain.
chain += addToCode ( aOuterChain.
chain[ i ], (ccw) ? 3 : 1 );
910 aInnerChain.
chain += aOuterChain.
chain[ ( i + 1 ) % nb ];
911 aOuter2inner.push_back( j );
912 aInner2outer.push_back( i );
913 aInner2outer.push_back( i + 1 );
914 aInner2outer.push_back( i + 1 );
920 aOuter2inner.push_back( j );
926 aOuter2inner.push_back( j );
927 aInner2outer.push_back( i );
934 aInnerChain.
chain += aOuterChain.
chain[ ( i + 1 ) % nb ];
935 aOuter2inner.push_back( j );
936 aInner2outer.push_back( i );
937 aInner2outer.push_back( i + 1 );
945 && ( *it_begin != *it ) )
949 aOuter2inner.push_back( j );
950 aInner2outer.push_back( i );
961 template <
typename TInteger>
964 std::vector<unsigned int> & aC2clean,
965 std::vector<unsigned int> & aClean2c,
969 unsigned int nb = (
unsigned int)c.
chain.size();
972 cerr <<
"[DGtal::FreemanChain::cleanOuterSpikes]"
973 <<
" cleanOuterSpikes: Empty input chain"
981 vector<unsigned int> c2cleanTMP;
982 aCleanC.
chain.reserve( nb );
986 aC2clean.reserve( nb );
987 aClean2c.reserve( nb );
988 c2cleanTMP.reserve( nb );
994 unsigned int size_spike = 0;
995 for ( n = 0; n < nb; ++n )
1004 if ( size_spike >= nb )
1006 cerr <<
"[DGtal::FreemanChain::cleanOuterSpikes]"
1007 <<
" Spike is longer than contour !"
1008 <<
" size_spike=" << size_spike
1017 if ( size_spike > 0 )
1025 aCleanC.
x0 = P.
at(0);
1026 aCleanC.
y0 = P.
at(1);
1027 aCleanC.
xn = P.
at(0);
1028 aCleanC.
yn = P.
at(1);
1031 ASSERT( ( n < nb ) || ( i == 0 ) );
1035 for (
unsigned int ni = 0; ni < nb; ++ni )
1037 aC2clean.push_back( ni );
1038 aClean2c.push_back( ni );
1040 if ( size_spike != 0 )
1041 cerr <<
"[DGtal::FreemanChain::cleanOuterSpikes]"
1042 <<
"No starting point found (only spikes !)" << endl;
1044 return size_spike == 0;
1048 deque<unsigned int> clean_code;
1049 deque<unsigned int> clean_idx;
1050 vector<unsigned int> begin_outer_spike;
1051 vector<unsigned int> end_outer_spike;
1055 clean_code.push_back( it.
getCode() );
1056 clean_idx.push_back( i );
1063 unsigned int last_spike_idx = end_outer_spike.empty() ?
1065 end_outer_spike.back();
1067 while ( ( ! clean_code.empty() )
1068 && ( j != last_spike_idx )
1069 && ( movement( clean_code.back(), it.
getCode(), ccw ) ==
'0' )
1070 && ( it != it_begin ) )
1072 clean_code.pop_back();
1073 clean_idx.pop_back();
1083 if ( size_spike != 0 )
1086 unsigned int previous_code = itn.
getCode();
1097 unsigned int move1 = movement( previous_code, addToCode ( itn.
getCode() , 2 ), ccw );
1098 unsigned int move2 = movement( itn.
getCode(), it.
getCode() , ccw );
1099 bool return_spike = ( move1 ==
'0' ) || ( move2 ==
'0' );
1100 bool outer_spike = ( move1 ==
'3' ) || ( move2 ==
'3' );
1118 if ( outer_spike || return_spike )
1120 begin_outer_spike.push_back( mc.
next( previous_idx ) );
1121 end_outer_spike.push_back( i );
1127 while ( it != it_begin );
1130 aC2clean.resize( nb );
1133 unsigned int nb_spikes = (
unsigned int)begin_outer_spike.size();
1138 if ( ( k == nb_spikes ) || ( i != begin_outer_spike[ k ] ) )
1142 aClean2c.push_back( i );
1149 while ( i != end_outer_spike[ k ] )
1158 for (
unsigned int ii = 0; ii < nb; ++ii )
1159 if ( aC2clean[ ii ] >= aCleanC.
chain.size() )
1161 if ( aC2clean[ ii ] == aCleanC.
chain.size() )
1165 cerr <<
"[DGtal::FreemanChain::cleanOuterSpikes]"
1166 <<
"Bad correspondence for aC2clean[" << ii <<
"]"
1167 <<
" = " << aC2clean[ ii ] <<
" >= " << aCleanC.
chain.size()
1169 aC2clean[ ii ] = aC2clean[ ii ] % aCleanC.
chain.size();
1173 for (
unsigned int jj = 0; j < aCleanC.
chain.size(); ++jj )
1174 if ( aClean2c[ jj ] >= nb )
1176 cerr <<
"[DGtal::FreemanChain::cleanOuterSpikes]"
1177 <<
"Bad correspondence for aClean2c[" << jj <<
"]"
1178 <<
" = " << aClean2c[ jj ] <<
" >= " << nb
1180 aClean2c[ jj ] = aClean2c[ jj ] % nb;
1301 template <
typename TInteger>
1306 return "FreemanChain";
1309 template <
typename TInteger>
1315 for (
unsigned int i=0; i < chain.size(); ++i)
1335 template <
typename TInteger>