DGtal 0.3.0

FreemanChain.h

Go to the documentation of this file.
00001 
00017 #pragma once
00018 
00033 #if defined(FreemanChain_RECURSES)
00034 #error Recursive header files inclusion detected in FreemanChain.h
00035 #else // defined(FreemanChain_RECURSES)
00036 
00037 #define FreemanChain_RECURSES
00038 
00039 #if !defined FreemanChain_h
00040 
00041 #define FreemanChain_h
00042 
00044 // Inclusions
00045 #include <iostream>
00046 #include <sstream>
00047 #include <vector>
00048 #include "DGtal/kernel/PointVector.h"
00049 #include "DGtal/base/OrderedAlphabet.h"
00050 #include "DGtal/base/BasicTypes.h"
00051 #include "DGtal/base/Common.h"
00052 #include "DGtal/math/arithmetic/ModuloComputer.h"
00053 #include "DGtal/io/DGtalBoard.h"
00054 #include "DGtal/kernel/IntegerTraits.h"
00056 
00057 
00058 namespace DGtal
00059 {
00060 
00062   // class FreemanChain
00064 
00097   template <typename TInteger>
00098   class FreemanChain
00099   {
00100 
00101   public :
00102 
00103 
00104     //BOOST_CONCEPT_ASSERT(( CInteger<TInteger> ) );
00105     typedef TInteger Integer;
00106     typedef PointVector<2, Integer> PointI2;
00107 
00108 
00109 
00110 
00111 
00112     // ------------------------- iterator ------------------------------
00113   public:
00114     
00116     // class FreemanChain::ConstIterator
00118         
00119     // ------------------------- Standard services -----------------------
00120     
00128     class ConstIterator
00129     {
00130       // ------------------------- data -----------------------
00131     private:
00135       const FreemanChain* myFc;
00136 
00140       unsigned int myPos;
00141 
00145       PointI2  myXY;
00146 
00147 
00148         
00149 
00150         
00151         
00152 
00153       // ------------------------- Standard services -----------------------
00154     public:
00155 
00161       ConstIterator()
00162         : myFc( 0 ), myPos( 0 )
00163       {
00164       }
00165         
00174       ConstIterator( const FreemanChain & aChain, unsigned int n =0)
00175         : myFc( &aChain ), myPos( 0 )
00176       {
00177         myXY.at(0)=aChain.x0;
00178         myXY.at(1)=aChain.y0;
00179           
00180         if ( n < myFc->chain.size() )
00181           while ( myPos < n )
00182             {
00183               this->next();
00184               // JOL !!!
00185               // ERROR: myPos is already incremented in next().
00186               // ++myPos;
00187             }
00188         else // iterator end() 
00189           myPos = myFc->chain.size();
00190       }
00191         
00192         
00193      
00194 
00200       ConstIterator( const ConstIterator & aOther )
00201         : myFc( aOther.myFc ), myPos( aOther.myPos ), myXY( aOther.myXY )
00202       {
00203       }
00204         
00205         
00206 
00207 
00208     
00215       ConstIterator& operator= ( const ConstIterator & other )
00216       {
00217         if ( this != &other )
00218           {
00219             myFc = other.myFc;
00220             myPos = other.myPos;
00221             myXY = other.myXY;
00222           }
00223         return *this;
00224       }
00225 
00226 
00227         
00232       ~ConstIterator(){
00233       }
00234         
00235         
00236         
00237 
00238       // ------------------------- iteration services -------------------------
00239     public:
00240 
00241               
00246       PointI2 operator*() const
00247       {
00248         return myXY;
00249       }
00250         
00255       PointI2 get() const
00256       {
00257         return myXY;
00258       }
00259         
00260                 
00261         
00267       ConstIterator& 
00268       operator++()
00269       {
00270         this->next();
00271         return *this;
00272       }
00273         
00274 
00275 
00276         
00281       void 
00282       next()
00283       {
00284         if ( myPos < myFc->chain.size() )
00285           {
00286             switch ( myFc->code( myPos ) )
00287               {
00288               case 0: myXY.at(0)++; break;
00289               case 1: myXY.at(1)++; break;
00290               case 2: myXY.at(0)--; break;
00291               case 3: myXY.at(1)--; break;
00292               }
00293             ++myPos;
00294           }
00295       }
00296                 
00297 
00298 
00303       void
00304       nextInLoop()
00305       {
00306         if ( myPos < myFc->chain.size() )
00307           {
00308             switch ( myFc->code( myPos ) )
00309               {
00310               case 0: myXY.at(0)++; break;
00311               case 1: myXY.at(1)++; break;
00312               case 2: myXY.at(0)--; break;
00313               case 3: myXY.at(1)--; break;
00314               }
00315             myPos = ( myPos + 1 ) % myFc->chain.size();
00316           }
00317       }
00318         
00319         
00320 
00325       unsigned int
00326       getPosition() const
00327       {
00328         return myPos;
00329       }
00330         
00331         
00336       FreemanChain * 
00337       getChain() const
00338       {
00339         return myFc;
00340       }
00341         
00342         
00343 
00344         
00345 
00351       unsigned int 
00352       getCode() const
00353       {
00354         ASSERT( myFc != 0 );
00355         return myFc->code( myPos );
00356       }
00357         
00358 
00364       ConstIterator&  operator--()
00365       {
00366         this->previous();
00367         return *this;
00368       }
00369 
00370 
00371         
00376       void
00377       previous()
00378       {
00379         if ( myPos > 0 )
00380           {
00381             --myPos;
00382             switch ( myFc->code( myPos ) )
00383               {
00384               case 0: myXY.at(0)--; break;
00385               case 1: myXY.at(1)--; break;
00386               case 2: myXY.at(0)++; break;
00387               case 3: myXY.at(1)++; break;
00388               }
00389           }
00390       }
00391         
00392 
00393 
00398       void
00399       previousInLoop()
00400       {
00401         if ( myPos == 0 ) myPos = myFc->chain.size() - 1;
00402         else --myPos;
00403         switch ( myFc->code( myPos ) )
00404           {
00405           case 0: myXY.at(0)--; break;
00406           case 1: myXY.at(1)--; break;
00407           case 2: myXY.at(0)++; break;
00408           case 3: myXY.at(1)++; break;
00409           }
00410       }
00411 
00412 
00413 
00414 
00415 
00416 
00417 
00418 
00428       bool 
00429       operator== ( const ConstIterator & aOther ) const
00430       {
00431         ASSERT( myFc == aOther.myFc );
00432         return myPos == aOther.myPos;
00433       }
00434 
00435 
00436 
00446       bool 
00447       operator!=
00448       ( const ConstIterator & aOther ) const
00449       {
00450         ASSERT( myFc == aOther.myFc );
00451         return myPos != aOther.myPos;
00452       }
00453 
00464       bool  operator<
00465       ( const ConstIterator & aOther ) const
00466       {
00467 
00468         ASSERT( myFc == aOther.myFc );
00469         return myPos < aOther.myPos;
00470       }
00471 
00472     };
00473 
00474 
00476     // class FreemanChain::ConstIterator
00478 
00479 
00480 
00481 
00482 
00483     // ------------------------- static services ------------------------------
00484   public:
00485 
00491     static void write( std::ostream & out, const FreemanChain & c )
00492     {
00493       out << c.x0 << " " << c.y0 << " " << c.chain << endl;
00494     }
00495 
00496 
00502     static void read( std::istream & in, FreemanChain & c )
00503     {
00504       string str;
00505       while ( true )
00506         {
00507           getline( in, str );
00508           if ( ! in.good() )
00509             return;
00510           if ( ( str.size() > 0 ) && ( str[ 0 ] != '#' ) )
00511             {
00512               istringstream str_in( str );
00513               str_in >> c.x0 >> c.y0 >> c.chain;
00514               return;
00515             }
00516         }
00517 
00518     };
00519 
00544     //static void create( std::string & chain,
00545     //                  std::string & qchain,
00546     //                  const C4CIterator & it,
00547     //                  unsigned int nb, unsigned int freeman, unsigned int quadrant,
00548     //                  unsigned int start_index = 0 );
00549 
00550 
00556     static void alphabet( char & aZero, char & aOne, char aQuadrant )
00557     {
00558       switch ( aQuadrant )
00559         {
00560         case '0':
00561           aZero = '0';
00562           aOne = '1';
00563           break;
00564         case '1':
00565           aZero = '1';
00566           aOne = '2';
00567           break;
00568         case '2':
00569           aZero = '2';
00570           aOne = '3';
00571           break;
00572         case '3':
00573           aZero = '3';
00574           aOne = '0';
00575           break;
00576         }
00577 
00578     };
00579 
00591     static unsigned int movement( unsigned int aCode1, unsigned int aCode2, bool ccw = true )
00592     {
00593       unsigned int cfg = ( ccw ? 0 : 16 ) + ( aCode1 << 2 ) + aCode2;
00594       static const unsigned int tbl[ 32 ] =
00595         {
00596           2, 1, 0, 3, 3, 2, 1, 0,
00597           0, 3, 2, 1, 1, 0, 3, 2,
00598           2, 3, 0, 1, 1, 2, 3, 0,
00599           0, 1, 2, 3, 3, 0, 1, 2
00600         };
00601       return tbl[ cfg ];
00602 
00603     }
00604 
00612     static void displacement( int & dx, int & dy, unsigned int aCode );
00613 
00618     static PointI2 displacement( unsigned int aCode );
00619 
00628     static unsigned int turnedCode( unsigned int aCode, bool ccw = true );
00629 
00651     static void pointel2pixel( FreemanChain & aPixChain,
00652                                std::vector<unsigned int> & aPl2pix,
00653                                std::vector<unsigned int> & aPix2pl,
00654                                const FreemanChain & aPlChain )
00655     {
00656       innerContour( aPixChain, aPl2pix, aPix2pl, aPlChain, true );
00657     };
00658 
00686     static void innerContour( FreemanChain & aInnerChain,
00687                               std::vector<unsigned int> & aOuter2inner,
00688                               std::vector<unsigned int> & aInner2outer,
00689                               const FreemanChain & aOuterChain,
00690                               bool ccw = true )
00691     {
00692 
00693       unsigned int nb = aOuterChain.chain.size();
00694       unsigned int j = 0;
00695       aOuter2inner.clear();
00696       aOuter2inner.reserve( nb );
00697       // aInnerChain.chain.reserve( nb + 4 );
00698       aInnerChain.chain = "";
00699       aInner2outer.clear();
00700       aInner2outer.reserve( nb + ( ccw ? 4 : -4 ) );
00701       int dx0, dy0;
00702       int dx1, dy1;
00703       FreemanChain<TInteger>::displacement( dx0, dy0, aOuterChain.code( 0 ) );
00704       int turn = ccw ? 1 : 3;
00705       FreemanChain<TInteger>::displacement( dx1, dy1, ( aOuterChain.code( 0 ) + turn ) % 4 );
00706       dx0 += dx1;
00707       dy0 += dy1;
00708       aInnerChain.x0 = dx0 > 0 ? aOuterChain.x0 : aOuterChain.x0 - 1;
00709       aInnerChain.y0 = dy0 > 0 ? aOuterChain.y0 : aOuterChain.y0 - 1;
00710 
00711       typename FreemanChain<TInteger>::ConstIterator it_begin = aOuterChain.begin();
00712       typename FreemanChain<TInteger>::ConstIterator it = it_begin;
00713       it.next();
00714       for ( unsigned int i = 0; i < nb; ++i )
00715         {
00716           // Check if contour is open.
00717           // cerr << "i=" << i << " code=" << aOuterChain.code( i ) << endl;
00718           switch ( movement( aOuterChain.code( i ),
00719                              aOuterChain.code( ( i + 1 ) % nb ),
00720                              ccw ) )
00721             {
00722             case 0:
00723               // contour going in then out.
00724               aInnerChain.chain += aOuterChain.chain[ i ];
00725               aInnerChain.chain += ( ( ( (unsigned int) ( aOuterChain.chain[ i ] - '0' )
00726                                          + ( ccw ? 3 : 1 ) ) )
00727                                      % 4 ) + '0';
00728               aInnerChain.chain += aOuterChain.chain[ ( i + 1 ) % nb ];
00729               aOuter2inner.push_back( j );
00730               aInner2outer.push_back( i );
00731               aInner2outer.push_back( i + 1 );
00732               aInner2outer.push_back( i + 1 );
00733               j += 3;
00734               break;
00735 
00736             case 1:
00737               // contour turning toward its inside.
00738               aOuter2inner.push_back( j );
00739               break;
00740 
00741             case 2:
00742               // contour going straight ahead
00743               aInnerChain.chain += aOuterChain.chain[ i ];
00744               aOuter2inner.push_back( j );
00745               aInner2outer.push_back( i );
00746               ++j;
00747               break;
00748 
00749             case 3:
00750               // contour turning toward its outside.
00751               aInnerChain.chain += aOuterChain.chain[ i ];
00752               aInnerChain.chain += aOuterChain.chain[ ( i + 1 ) % nb ];
00753               aOuter2inner.push_back( j );
00754               aInner2outer.push_back( i );
00755               aInner2outer.push_back( i + 1 );
00756               j += 2;
00757               break;
00758             }
00759 
00760 
00761           // Advances along contour and check if it is a closed contour.
00762           it.next();
00763           if ( ( i == nb - 1 )
00764                && ( *it_begin != *it ) )
00765             // freeman chain is *not* a closed loop.
00766             {
00767               aInnerChain.chain += aOuterChain.chain[ i ];
00768               aOuter2inner.push_back( j );
00769               aInner2outer.push_back( i );
00770               ++i;
00771               ++j;
00772               break;
00773             }
00774         }
00775 
00776 
00777     }
00778 
00805     static void cleanContour( std::vector<FreemanChain> & aCleanCs,
00806                               std::vector< std::pair<unsigned int, unsigned int> > & aC2clean,
00807                               std::vector< std::vector<unsigned int> > & aClean2c,
00808                               const FreemanChain & c,
00809                               bool ccw = true )
00810     {
00811 
00812     }
00835     static bool cleanOuterSpikes( FreemanChain & aCleanC,
00836                                   std::vector<unsigned int> & aC2clean,
00837                                   std::vector<unsigned int> & aClean2c,
00838                                   const FreemanChain & c,
00839                                   bool ccw = true )
00840     {
00841       unsigned int nb = c.chain.size();
00842       if ( nb == 0 )
00843         {
00844           cerr << "[DGtal::FreemanChain::cleanOuterSpikes]"
00845                << " cleanOuterSpikes: Empty input chain"
00846                << endl;
00847           return false;
00848         }
00849 
00850       ModuloComputer< DGtal::int32_t > mc( nb );
00851       ModuloComputer< DGtal::int32_t >::UnsignedInteger i = 0;
00852       ModuloComputer< DGtal::int32_t >::UnsignedInteger j = 0;
00853       vector<unsigned int> c2cleanTMP;
00854       aCleanC.chain.reserve( nb );
00855       aCleanC.chain = "";
00856       aC2clean.clear();
00857       aClean2c.clear();
00858       aC2clean.reserve( nb );
00859       aClean2c.reserve( nb );
00860       c2cleanTMP.reserve( nb );
00861       typename FreemanChain<TInteger>::ConstIterator it = c.begin();
00862       typename FreemanChain<TInteger>::ConstIterator itn = c.begin();
00863       itn.nextInLoop();
00864       // Find a consistent starting point.
00865       unsigned int n;
00866       unsigned int size_spike = 0;
00867       for ( n = 0; n < nb; ++n )
00868         {
00869           size_spike = 0;
00870           while ( movement( it.getCode(), itn.getCode(), ccw ) == 0 )
00871             {
00872               it.previousInLoop();
00873               itn.nextInLoop();
00874               mc.increment( i );
00875               size_spike += 2;
00876               if ( size_spike >= nb )
00877                 {
00878                   cerr << "[DGtal::FreemanChain::cleanOuterSpikes]"
00879                        << " Spike is longer than contour !"
00880                        << " size_spike=" << size_spike
00881                        << " nb=" << nb
00882                        << endl;
00883                   return false;
00884                 }
00885             }
00886           mc.increment( i );
00887           it = itn;
00888           itn.nextInLoop();
00889           if ( size_spike > 0 )
00890             break;
00891         }
00892       unsigned int start_idx = it.getPosition();
00893       i = start_idx;
00894       // JOL : 2009/07/7, added starting coordinates
00895       PointI2 P = *it;
00896       aCleanC.x0 = P.at(0);
00897       aCleanC.y0 = P.at(1);
00898 
00899       // cerr << "Starting point is " << i << endl;
00900       ASSERT( ( n < nb ) || ( i == 0 ) );
00901       if ( ( n == nb ) )
00902         { // do nothing
00903           aCleanC.chain = c.chain;
00904           for ( unsigned int ni = 0; ni < nb; ++ni )
00905             {
00906               aC2clean.push_back( ni );
00907               aClean2c.push_back( ni );
00908             }
00909           if ( size_spike != 0 )
00910             cerr << "[DGtal::FreemanChain::cleanOuterSpikes]"
00911                  << "No starting point found (only spikes !)" << endl;
00912 
00913           return size_spike == 0;
00914         }
00915       // Loops over all letters.
00916       typename FreemanChain<TInteger>::ConstIterator it_begin = it;
00917       deque<unsigned int> clean_code;
00918       deque<unsigned int> clean_idx;
00919       vector<unsigned int> begin_outer_spike;
00920       vector<unsigned int> end_outer_spike;
00921       // i follows iterator it.
00922       do
00923         {
00924           clean_code.push_back( it.getCode() );
00925           clean_idx.push_back( i );
00926           itn = it;
00927           it.nextInLoop();
00928           mc.increment( i );
00929           // cerr << "- i=" << i << " (" << clean_code.back()
00930           //       << it.getCode() << ") ";
00931           size_spike = 0;
00932           unsigned int last_spike_idx = end_outer_spike.empty() ?
00933             start_idx :
00934             end_outer_spike.back();
00935           j = i;
00936           while ( ( ! clean_code.empty() )
00937                   && ( j != last_spike_idx )
00938                   && ( movement( clean_code.back(), it.getCode(), ccw ) == 0 )
00939                   && ( it != it_begin ) )
00940             {
00941               clean_code.pop_back();
00942               clean_idx.pop_back();
00943               mc.increment( i );
00944               mc.decrement( j );
00945               it.nextInLoop();
00946               itn.previousInLoop();
00947               size_spike += 2;
00948             }
00949           // cerr << "i=" << i << " size_spike=" << size_spike
00950           //       << " last_spike_idx=" << last_spike_idx
00951           //       << endl;
00952           if ( size_spike != 0 )
00953             {
00954               // There is a spike. Is it an outer one ?
00955               unsigned int previous_code = itn.getCode();
00956               unsigned int previous_idx = itn.getPosition();
00957               // JOL : do not
00958               // consider any more "cleaned contour" since we cannot go
00959               // further than the last spike.
00960               // unsigned int previous_code =
00961               //   clean_code.empty() ? itn.getCode() : clean_code.back();
00962               // unsigned int previous_idx =
00963               //   clean_code.empty() ? itn.getPosition() : clean_idx.back();
00964               itn = it;
00965               itn.previousInLoop();
00966               unsigned int move1 = movement( previous_code,
00967                                              ( itn.getCode() + 2 ) % 4, ccw );
00968               unsigned int move2 = movement( itn.getCode(), it.getCode() , ccw );
00969               bool return_spike = ( move1 == 0 ) || ( move2 == 0 );
00970               bool outer_spike = ( move1 == 3 ) || ( move2 == 3 );
00971               //          if ( return_spike )
00972               //            cerr << "[DGtal::FreemanChain::cleanOuterSpikes] return spike."
00973               //                 << endl;
00974               //          if ( ! ( ( outer_spike && ( move1 != 1 ) && ( move2 != 1 ) )
00975               //                   || ( ! outer_spike && ( move1 != 3 ) && ( move2 != 3 ) ) ) )
00976               //            cerr << "[DGtal::FreemanChain::cleanOuterSpikes] "
00977               //                 << "Weird spike. Invalid contour (expected 3 3) ?"
00978               //                 << " move1=" << move1
00979               //                 << " move2=" << move2
00980               //                 << " ccw=" << ccw
00981               //                 << " start_idx=" << start_idx
00982               //                 << " size_spike=" << size_spike
00983               //                 << " it=" << it.getPosition()
00984               //                 << " itp=" << previous_idx
00985               //                 << endl
00986               //                 << c.chain << endl;
00987               // Process waiting steps.
00988               if ( outer_spike || return_spike )
00989                 {
00990                   begin_outer_spike.push_back( mc.next( previous_idx ) );
00991                   end_outer_spike.push_back( i );
00992                   // cout << " outer spike [" << begin_outer_spike.back()
00993                   //       << "," << end_outer_spike.back() << "[  " << endl;
00994                 }
00995             }
00996         }
00997       while ( it != it_begin );
00998 
00999       // Once outer spikes are known, we can create the new contour.
01000       aC2clean.resize( nb );
01001       i = start_idx % nb;
01002       j = 0;
01003       unsigned int nb_spikes = begin_outer_spike.size();
01004       unsigned int k = 0;
01005       n = 0;
01006       while ( n < nb )
01007         {
01008           if ( ( k == nb_spikes ) || ( i != begin_outer_spike[ k ] ) )
01009             {
01010               aCleanC.chain.push_back( c.chain[ i ] );
01011               aC2clean[ i ] = j;
01012               aClean2c.push_back( i );
01013               mc.increment( i );
01014               ++j;
01015               ++n;
01016             }
01017           else
01018             {
01019               while ( i != end_outer_spike[ k ] )
01020                 {
01021                   aC2clean[ i ] = j;
01022                   mc.increment( i );
01023                   ++n;
01024                 }
01025               ++k;
01026             }
01027         }
01028       for ( unsigned int ii = 0; ii < nb; ++ii )
01029         if ( aC2clean[ ii ] >= aCleanC.chain.size() )
01030           { 
01031             if ( aC2clean[ ii ] == aCleanC.chain.size() )
01032               aC2clean[ ii ] = 0;
01033             else
01034               {
01035                 cerr << "[DGtal::FreemanChain::cleanOuterSpikes]"
01036                      << "Bad correspondence for aC2clean[" << ii << "]"
01037                      << " = " << aC2clean[ ii ] << " >= " << aCleanC.chain.size()
01038                      << endl;
01039                 aC2clean[ ii ] = aC2clean[ ii ] % aCleanC.chain.size();
01040               }
01041           }
01042       
01043       for ( unsigned int jj = 0; j < aCleanC.chain.size(); ++jj )
01044         if ( aClean2c[ jj ] >= nb )
01045           {
01046             cerr << "[DGtal::FreemanChain::cleanOuterSpikes]"
01047                  << "Bad correspondence for aClean2c[" << jj << "]"
01048                  << " = " << aClean2c[ jj ] << " >= " << nb
01049                  << endl;
01050             aClean2c[ jj ] = aClean2c[ jj ] % nb;
01051           }
01052 
01053 
01054 
01055       return true;
01056     };
01057 
01058     //     /**
01059     //      * Given a Freeman chain [c] coding a 4-connected pixel loop, computes
01060     //      * its subsampling by the transformation:
01061     //      * X = ( x - x0 ) div h,
01062     //      * Y = ( y - y0 ) div v.
01063     //      *
01064     //      * @param aSubc (output) the subsampled Freeman chain code (may
01065     //      * contain spikes)
01066     //      *
01067     //      * @param aC2subc (output) the mapping associating an element to
01068     //      * its subsampled element.
01069     //      *
01070     //      * @param aSubc2c (output) the inverse mapping associating a
01071     //      * subsampled element to its element. More precisely, subc2c[ j ]
01072     //      * is the last pointel to be in j.
01073     //      *
01074     //      * @param c the input chain code.
01075     //      *
01076     //      * @param h the subsampling along x
01077     //      * @param v the subsampling along y
01078     //      * @param x0 the x-origin of the frame (X,Y) in (x,y)
01079     //      * @param y0 the y-origin of the frame (X,Y) in (x,y)
01080     //      *
01081     //      * @return 'false' if initial contour was empty or if [subc] is empty,
01082     //      * 'true' otherwise.
01083     //      */
01084     //     static bool subsample( FreemanChain & aSubc,
01085     //                     std::vector<unsigned int> & aC2subc,
01086     //                     std::vector<unsigned int> & aSubc2c,
01087     //                     const FreemanChain & c,
01088     //                     unsigned int h, unsigned int v,
01089     //                     int x0, int y0 ){
01090     //       if ( ( h == 0 ) || ( v == 0 ) ) return false;
01091     //       FreemanChain<TInteger>::ConstIterator it = c.begin();
01092     //   unsigned int j = 0;
01093     //   unsigned int nb = c.chain.size();
01094     //   if ( nb == 0 ) return false;
01095 
01096     //   PointI2 fxy( it.get() );
01097     //   PointI2 fXY;
01098     //   fXY.at(0)= ( fxy.at(0) - x0 ) / h;
01099     //   fXY.at(1)= ( fxy.at(1) - y0 ) / v;
01100 
01101 
01102     //   aSubc.x0 = fXY.at(0);
01103     //   aSubc.y0 = fXY.at(1);
01104     //   aC2subc.clear();
01105     //   aC2subc.reserve( nb );
01106     //   aSubc2c.clear();
01107     //   aSubc2c.reserve( nb );
01108 
01109     //   for ( unsigned int i = 0; i < nb; ++i )
01110     //     {
01111     //       aC2subc.push_back( j );
01112     //       it.nextInLoop();
01113     //       PointI2 nxy( it.get() );
01114     //       PointI2 nXY;
01115     //       nXY.at(0)= ( nxy.at(0) - x0 ) / h;
01116     //       nXY.at(1)= ( nxy.at(1) - y0 ) / v;
01117 
01118 
01119     //       if ( nXY != fXY )
01120     //  {
01121     //    aSubc2c.push_back( i );
01122     //    char code;
01123     //    if ( nXY.at(0) > fXY.at(0) )       code = '0';
01124     //    else if ( nXY.at(0) < fXY.at(0) )  code = '2';
01125     //    else if ( nXY.at(1) > fXY.at(1) )  code = '1';
01126     //    else                           code = '3';
01127     //    aSubc.chain += code;
01128     //    ++j;
01129     //    fXY = nXY;
01130     //  }
01131     //     }
01132     // //   aC2subc.push_back( j );
01133     // //   it.nextInLoop();
01134     // //   for ( unsigned int i = 1; i <= nb; ++i )
01135     // //     {
01136     // //       // JOL
01137     // //       //aC2subc.push_back( j );
01138     // //       Vector2i nxy( it.get() );
01139     // //       Vector2i nXY( ( nxy.x() - x0 ) / h, ( nxy.y() - y0 ) / v );
01140     // //       if ( nXY != fXY )
01141     // //       {
01142     // //         char code;
01143     // //         if ( nXY.x() > fXY.x() )       code = '0';
01144     // //         else if ( nXY.x() < fXY.x() )  code = '2';
01145     // //         else if ( nXY.y() > fXY.y() )  code = '1';
01146     // //         else                           code = '3';
01147     // //         aSubc.chain += code;
01148     // //         aSubc2c.push_back( i - 1 );
01149     // //         ++j;
01150     // //         fXY = nXY;
01151     // //       }
01152     // //       if ( i != nb ) aC2subc.push_back( j );
01153     // //       it.nextInLoop();
01154     // //     }
01155     // //   // TODO : enhance this.
01156     //   unsigned int nbsub =  aSubc.chain.size();
01157     //   // Last correspondence may be in fact to 0 instead of nbsub.
01158     //   if ( nbsub != 0 )
01159     //     for ( unsigned int i = 0; i < nb; ++i )
01160     //       if ( aC2subc[ i ] >= nbsub ) aC2subc[ i ] -= nbsub;
01161 
01162 
01163     //   ASSERT( aC2subc.size() == nb );
01164     //   return nbsub != 0;
01165 
01166     //     }
01167 
01168 
01169 
01176     static void getContourPoints(const FreemanChain & fc, std::vector<PointI2> & aVContour)
01177     {
01178       aVContour.clear();
01179       for ( typename FreemanChain<TInteger>::ConstIterator it = fc.begin();
01180             it != fc.end();
01181             ++it )
01182         {
01183           aVContour.push_back(*it);
01184         }
01185     }
01186 
01187 
01188 
01189 
01190 
01191     static void movePointFromFC(PointI2 & aPoint, unsigned int aCode );
01192 
01193 
01194 
01195     // ----------------------- Standard services ------------------------------
01196   public:
01197 
01198 
01199 
01200 
01201 
01202 
01206     ~FreemanChain()
01207     {
01208     };
01209 
01216     FreemanChain( const std::string & s = "", int x = 0, int y = 0 );
01217 
01218 
01223     FreemanChain(std::istream & in );
01224 
01225 
01230     FreemanChain( const FreemanChain & other );
01231 
01237     FreemanChain & operator=( const FreemanChain & other );
01238 
01239 
01244     ConstIterator begin() const;
01245 
01250     ConstIterator end() const;
01251 
01256     unsigned int code( unsigned int pos ) const;
01257 
01262     unsigned int next( unsigned int pos ) const;
01263 
01268     unsigned int previous( unsigned int pos ) const;
01269 
01273     unsigned int size() const;
01274 
01283     void computeBoundingBox( TInteger & min_x, TInteger& min_y,
01284                              TInteger& max_x, TInteger& max_y ) const
01285     {
01286 
01287       min_x = max_x = x0;
01288       min_y = max_y = y0;
01289       for ( typename FreemanChain<TInteger>::ConstIterator it = begin();
01290             it != end();
01291             ++it )
01292         {
01293           PointI2 p( *it );
01294           if ( p.at(0) < min_x )
01295             min_x = p.at(0);
01296           else
01297             if ( p.at(0) > max_x )
01298               max_x = p.at(0);
01299           if ( p.at(1) < min_y )
01300             min_y = p.at(1);
01301           else
01302             if ( p.at(1) > max_y )
01303               max_y = p.at(1);
01304         }
01305 
01306     }
01307 
01326     //BK
01327     typename FreemanChain<TInteger>::ConstIterator
01328     findQuadrantChange( OrderedAlphabet & A ) const
01329     {
01330       typename FreemanChain<TInteger>::ConstIterator it = begin();
01331       typename FreemanChain<TInteger>::ConstIterator it_end = end();
01332       // find first letters a and b.
01333       unsigned int code1 = it.getCode();
01334       it.next();
01335       while ( ( it != it_end ) && ( it.getCode() == code1 ) )
01336         it.next();
01337       ASSERT( ( it != it_end )
01338               && "[DGtal::FreemanChain::findQuadrantChange( OrderedAlphabet & A ) const] 1-letter freeman chain." );
01339       unsigned int  code2 = it.getCode();
01340       // find third letter c.
01341       while ( ( it != it_end ) && ( ( it.getCode() == code1 )
01342                                     || ( it.getCode() == code2 ) ) )
01343         it.next();
01344       ASSERT( ( it != it_end )
01345               && "[DGtal::FreemanChain::findQuadrantChange( OrderedAlphabet & A ) const] 2-letters Freeman chain." );
01346       unsigned int code3 = it.getCode();
01347       // reorder a and b.
01348       it.previous();
01349       if ( it.getCode() != code2 )
01350         swap( code1, code2 );
01351       // find first a.
01352       do
01353         {
01354           it.previous();
01355         }
01356       while ( it.getCode() == code2 );
01357       char a_char = chain[ it.getPosition() ];
01358       // the next is the first b.
01359       it.next();
01360       char b_char = chain[ it.getPosition() ];
01361       // Reorder the alphabet to match the quadrant change.
01362       while ( A.order( b_char ) != 1 )
01363         A.shiftLeft();
01364       if ( A.order( a_char ) == 0 )
01365         {
01366           A.reverse();
01367           while ( A.order( b_char ) != 1 )
01368             A.shiftLeft();
01369         }
01370       ASSERT( ( A.order( b_char ) == 1 )
01371               && ( A.order( a_char ) == 2 )
01372               && "[DGtal::FreemanChain::findQuadrantChange( OrderedAlphabet & A ) const] Internal error: invalid Quadrant change found." );
01373       return it;
01374 
01375 
01376     }
01377 
01398     //BK
01399     typename FreemanChain<TInteger>::ConstIterator
01400     findQuadrantChange4( OrderedAlphabet & A ) const
01401     {
01402       typename FreemanChain<TInteger>::ConstIterator it = begin();
01403       typename FreemanChain<TInteger>::ConstIterator it_end = end();
01404       // find first letters a and b.
01405       uint8_t code1 = it.getCode();
01406       it.next();
01407       while ( ( it != it_end ) && ( it.getCode() == code1 ) )
01408         it.next();
01409       ASSERT( ( it != it_end )
01410               && "[DGtal::FreemanChain::findQuadrantChange( OrderedAlphabet & A ) const] 1-letter freeman chain." );
01411       uint8_t code2 = it.getCode();
01412       // find third letter c.
01413       while ( ( it != it_end ) && ( ( it.getCode() == code1 )
01414                                     || ( it.getCode() == code2 ) ) )
01415         it.next();
01416       ASSERT( ( it != it_end )
01417               && "[DGtal::FreemanChain::findQuadrantChange( OrderedAlphabet & A ) const] 2-letters Freeman chain." );
01418       uint8_t code3 = it.getCode();
01419       // find fourth letter d.
01420       while ( ( it != it_end ) && ( ( it.getCode() == code1 )
01421                                     || ( it.getCode() == code2 )
01422                                     || ( it.getCode() == code3 ) ) )
01423         it.next();
01424       ASSERT( ( it != it_end )
01425               && "[DGtal::FreemanChain::findQuadrantChange( OrderedAlphabet & A ) const] 3-letters Freeman chain." );
01426       uint8_t  code4 = it.getCode();
01427       // define true c.
01428       it.previous();
01429       code3 = it.getCode();
01430       // find first b.
01431       do
01432         {
01433           it.previous();
01434         }
01435       while ( it.getCode() == code3 );
01436       char a_char = chain[ it.getPosition() ];
01437       // the next is the first c.
01438       it.next();
01439       char b_char = chain[ it.getPosition() ];
01440       // Reorder the alphabet to match the quadrant change.
01441       while ( A.order( b_char ) != 1 )
01442         A.shiftLeft();
01443       if ( A.order( a_char ) == 0 )
01444         {
01445           A.reverse();
01446           while ( A.order( b_char ) != 1 )
01447             A.shiftLeft();
01448         }
01449       ASSERT( ( A.order( b_char ) == 1 )
01450               && ( A.order( a_char ) == 2 )
01451               && "[DGtal::FreemanChain::findQuadrantChange( OrderedAlphabet & A ) const] Internal error: invalid Quadrant change found." );
01452       return it;
01453 
01454     }
01455 
01468     int isClosed() const
01469     {
01470       typename FreemanChain<TInteger>::ConstIterator it = this->begin();
01471       typename FreemanChain<TInteger>::ConstIterator it_end = this->end();
01472       typename FreemanChain<TInteger>::ConstIterator it_suiv = it;
01473       PointI2 spos = *it;
01474       int nb_ccw_turns = 0;
01475       while ( it != it_end )
01476         {
01477           int code1 = it.getCode();
01478           it_suiv.nextInLoop();
01479           int code2 = it_suiv.getCode();
01480           uint8_t diff = ( code2 - code1 + 4 ) % 4;
01481           if ( diff == 1 )
01482             ++nb_ccw_turns;
01483           else
01484             if ( diff == 3 )
01485               --nb_ccw_turns;
01486             else
01487               if ( diff == 2 )
01488                 return 0;
01489           ++it;
01490         }
01491       if ( spos == *it_suiv )
01492         return nb_ccw_turns / 4;
01493       else
01494         return 0;
01495 
01496 
01497     }
01498 
01499 
01500     // ----------------------- Interface --------------------------------------
01501   public:
01502 
01507     void selfDisplay ( std::ostream & out ) const
01508     {
01509       out << "[FreemanChain]";
01510     };
01511 
01516     bool isValid() const
01517     {
01518       return true;
01519     };
01520 
01521   public:
01522 
01523 
01528     DrawableWithDGtalBoard* defaultStyle( std::string mode = "" ) const;
01529     
01533     std::string styleName() const;
01534     
01540     template<typename Functor>
01541     void selfDraw(DGtalBoard & board ) const;
01542     
01547     void selfDraw(DGtalBoard & board ) const;
01548 
01549     // ------------------------- Public Datas ------------------------------
01550 
01551   public:
01555     std::string chain;
01556 
01560     int x0;
01561 
01565     int y0;
01566 
01567 
01568 
01569     // ------------------------- Protected Datas ------------------------------
01570   private:
01571     // ------------------------- Private Datas --------------------------------
01572   private:
01573 
01574     // ------------------------- Hidden services ------------------------------
01575   protected:
01576 
01581     //    FreemanChain();
01582 
01583   private:
01584 
01585 
01586     // ------------------------- Internals ------------------------------------
01587   private:
01588 
01595     struct SelfDrawStyle
01596     {
01597       SelfDrawStyle(DGtalBoard & aBoard)
01598       {
01599         aBoard.setFillColor(DGtalBoard::Color::None);
01600         aBoard.setPenColor(DGtalBoard::Color::Black);
01601       }
01602     };
01603 
01604     struct DefaultDrawStyle : public DrawableWithDGtalBoard
01605     {
01606       virtual void selfDraw( DGtalBoard & aBoard ) const
01607       {
01608         aBoard.setFillColor(DGtalBoard::Color::None);
01609         aBoard.setPenColor(DGtalBoard::Color::Black);
01610       }
01611     };
01612 
01613 
01614 
01615 
01616 
01617   }; // end of class FreemanChain
01618 
01619 
01620 
01621 
01628   template<typename TInteger>
01629   std::ostream&
01630   operator<< ( std::ostream & out, const FreemanChain<TInteger> & object );
01631 
01632 
01633 } // namespace DGtal
01634 
01635 
01637 // Includes inline functions/methods if necessary.
01638 #if defined(INLINE)
01639 #include "DGtal/geometry/2d/FreemanChain.ih"
01640 #endif
01641 
01642 //                                                                           //
01644 
01645 #endif // !defined FreemanChain_h
01646 
01647 #undef FreemanChain_RECURSES
01648 #endif // else defined(FreemanChain_RECURSES)
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines