Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

FreemanChain.C

Go to the documentation of this file.
00001  /*---------------------------------------------------------------------+
00002  | Library QgarLib, graphics analysis and recognition                  |
00003  | Copyright (C) 2002  Qgar Project, LORIA                             |
00004  |                                                                     |
00005  | This library is free software; you can redistribute it and/or       |
00006  | modify it under the terms of the GNU Lesser General Public          |
00007  | License version 2.1, as published by the Free Software Foundation.  |
00008  |                                                                     |
00009  | This library is distributed in the hope that it will be useful,     |
00010  | but WITHOUT ANY WARRANTY; without even the implied warranty of      |
00011  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                |
00012  | See the GNU Lesser General Public License for more details.         |
00013  |                                                                     |
00014  | The GNU Lesser General Public License is included in the file       |
00015  | LICENSE.LGPL, in the root directory of the Qgar packaging. See      |
00016  | http://www.gnu.org/licenses/lgpl.html for the terms of the licence. |
00017  | To receive a paper copy, write to the Free Software Foundation,     |
00018  | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.       |
00019  |                                                                     |
00020  | Contact Project Qgar for any information:                           |
00021  |   LORIA - équipe Qgar                                               |
00022  |   B.P. 239, 54506 Vandoeuvre-lès-Nancy Cedex, France                |
00023  |   email: qgar-contact@loria.fr                                      |
00024  |   http://www.qgar.org/                                              |
00025  *---------------------------------------------------------------------*/
00026 
00027 
00028 /**
00029  * @file  FreemanChain.C
00030  * @brief Implementation of class qgar::FreemanChain.
00031  *
00032  * See file FreemanChain.H for the interface.
00033  *
00034  * @author <a href="mailto:qgar-develop@loria.fr?subject=Qgar fwd Gérald Masini">Gérald Masini</a>
00035  * @date   December 19, 2003  17:30
00036  * @since  Qgar 2.1.1
00037  */
00038 
00039 
00040 
00041 // STD
00042 #include <cstdlib>
00043 // STL
00044 #include <list>
00045 // QGAR
00046 #include <qgarlib/FreemanChain.H>
00047 #include <qgarlib/FreemanCode.H>
00048 #include <qgarlib/image.H>
00049 #include <qgarlib/primitives.H>
00050 
00051 
00052 
00053 namespace qgar
00054 {
00055 
00056 
00057 // -------------------------------------------------------------------
00058 // C O N S T R U C T O R S 
00059 // -------------------------------------------------------------------
00060 
00061 
00062 // WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING
00063 //
00064 // THE DEFAULT CONSTRUCTOR BELONGS TO THE PRIVATE SECTION
00065 // SO THAT A CLIENT CANNOT USE IT
00066 
00067 FreemanChain::FreemanChain()
00068 {
00069   // VOID
00070 }
00071 
00072 //  : _chain(),
00073 //    _first  (GenPoint<int>(0,0)),
00074 //    _current(GenPoint<int>(0,0)),
00075 //    _last   (GenPoint<int>(0,0))
00076 //
00077 //{
00078 //  // Set iterator to begin of chain
00079 //  _iter = _chain.begin();
00080 //
00081 //}
00082 
00083 // WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING
00084 
00085 
00086 // COPY CONSTRUCTOR
00087 
00088 FreemanChain::FreemanChain(const FreemanChain& aFreemanCh)
00089 
00090   : _chain  (aFreemanCh._chain),
00091     _first  (aFreemanCh._first),
00092     _current(aFreemanCh._current),
00093     _last   (aFreemanCh._last)
00094 
00095 {
00096   // Set the iterator to the beginning of the chain
00097   _iter = _chain.begin();
00098 }
00099 
00100 
00101 // CONSTRUCT FROM A POINT
00102 
00103 FreemanChain::FreemanChain(const GenPoint<int>& aPt)
00104 
00105   : _chain  (1, FreemanCode(QGE_DIRECTION_N, 0)),
00106     _first  (aPt),
00107     _current(aPt),
00108     _last   (aPt)
00109 
00110 {
00111   // Set the iterator to the beginning of the chain
00112   _iter = _chain.begin();
00113 }
00114 
00115 
00116 // CONSTRUCT FROM A POINT, A DIRECTION AND A LENGTH
00117 
00118 FreemanChain::FreemanChain(const GenPoint<int>& aPt,
00119                            QGEdirection aDir,
00120                            unsigned int aLength)
00121 
00122   : _chain(1, FreemanCode(QGE_DIRECTION_N, 0)),
00123     _first(aPt)
00124 
00125 {
00126   // Set the iterator to the beginning of the chain
00127   _iter = _chain.begin();
00128 
00129   FreemanCode code(aDir, aLength);
00130   // Second point
00131   _chain.push_back(code);
00132   _current = code.toPoint(aPt);
00133   _last = _current;
00134   _iter++;
00135 }
00136 
00137 
00138 // -------------------------------------------------------------------
00139 // D E S T R U C T O R 
00140 // -------------------------------------------------------------------
00141 
00142 
00143 FreemanChain::~FreemanChain()
00144 {
00145   // VOID
00146 }
00147 
00148 
00149 // -------------------------------------------------------------------
00150 // A C C E S S   T O   C H A I N   C H A R A C T E R I S T I C S 
00151 // -------------------------------------------------------------------
00152 
00153 
00154 // IS CURRENT CHAIN EMPTY?
00155 
00156 bool
00157 FreemanChain::empty() const
00158 {
00159   return _chain.empty();
00160 }
00161 
00162 
00163 // CHAIN LENGTH (NUMBER OF POINTS)
00164 
00165 int
00166 FreemanChain::size() const
00167 {
00168   return _chain.size();
00169 }
00170 
00171 
00172 // -------------------------------------------------------------------
00173 // I T E R A T O R 
00174 // -------------------------------------------------------------------
00175 
00176 
00177 // MAKE THE INTERNAL ITERATOR POINT TO THE FIRST POINT OF THE CHAIN,
00178 // THAT BECOMES THE CURRENT POINT
00179 
00180 void
00181 FreemanChain::setToBegin()
00182 { 
00183   _iter = _chain.begin();
00184   _current = _first;
00185 }
00186 
00187 
00188 // MAKE THE INTERNAL ITERATOR POINT TO THE LAST POINT OF THE CHAIN,
00189 // THAT BECOMES THE CURRENT POINT
00190 
00191 void
00192 FreemanChain::setToEnd()
00193 {
00194   _iter = _chain.end();
00195   _iter--;
00196   _current = _last;
00197 }
00198 
00199 
00200 // DOES INTERNAL ITERATOR POINTS TO THE BEGINNING OF THE CHAIN?
00201 
00202 bool
00203 FreemanChain::isAtBegin() const
00204 {
00205   return _iter == _chain.begin();
00206 }
00207 
00208 
00209 // DOES INTERNAL ITERATOR POINTS TO THE END OF THE CHAIN?
00210 
00211 bool
00212 FreemanChain::isAtEnd() const
00213 {
00214   return _iter == _chain.end();
00215 }
00216 
00217 
00218 // IS THERE A POINT AFTER THE CURRENT POINT?
00219 
00220 bool
00221 FreemanChain::hasNext() const
00222 {
00223   std::list<FreemanCode>::iterator itAux = _iter;
00224   return (++itAux != _chain.end());
00225 }
00226 
00227 
00228 // IS THERE A POINT BEFORE THE CURRENT POINT?
00229 
00230 bool
00231 FreemanChain::hasPrevious() const
00232 {
00233   return (_iter != _chain.begin());
00234 }
00235 
00236 
00237 // MOVE TO NEXT POINT, THAT BECOMES THE CURRENT POINT
00238 
00239 void
00240 FreemanChain::moveNext()
00241 {
00242 
00243   _iter++;
00244   _current = _iter->toPoint(_current);
00245 }
00246 
00247 
00248 // MOVE TO PREVIOUS POINT, THAT BECOMES THE CURRENT POINT
00249 
00250 void
00251 FreemanChain::movePrevious()
00252 {
00253   _current = _iter->toOppositePoint(_current);
00254   _iter--;
00255 }
00256 
00257 
00258 // -------------------------------------------------------------------
00259 // A C C E S S   T O   F R E E M A N   C O D E S
00260 // -------------------------------------------------------------------
00261 
00262 
00263 // GET THE (STL) LIST OF FREEMAN CODES
00264 
00265 const std::list<FreemanCode>&
00266 FreemanChain::accessCodesList() const
00267 {
00268   return _chain;
00269 }
00270 
00271 
00272 // -------------------------------------------------------------------
00273 // A C C E S S   T O   P O I N T S 
00274 // -------------------------------------------------------------------
00275 
00276 
00277 // GET THE FIRST POINT
00278 
00279 const GenPoint<int>&
00280 FreemanChain::accessFront() const
00281 {
00282   return _first;
00283 }
00284 
00285 // GET A COPY OF THE FIRST POINT
00286 
00287 GenPoint<int>
00288 FreemanChain::front() const
00289 {
00290   return _first;
00291 }
00292 
00293 // GET THE LAST POINT
00294 
00295 const GenPoint<int>&
00296 FreemanChain::accessBack() const
00297 {
00298   return _last;
00299 }
00300 
00301 // GET A COPY OF THE LAST POINT
00302 
00303 GenPoint<int>
00304 FreemanChain::back() const
00305 {
00306   return _last;
00307 }
00308 
00309 // GET THE CURRENT POINT
00310 
00311 const GenPoint<int>&
00312 FreemanChain::accessCurrent() const
00313 {
00314   return _current;
00315 }
00316 
00317 // GET A COPY OF THE CURRENT POINT
00318 
00319 GenPoint<int>
00320 FreemanChain::current() const
00321 {
00322   return _current;
00323 }
00324 
00325 // GET THE SUCCESSOR OF THE CURRENT POINT
00326 
00327 const GenPoint<int>&
00328 FreemanChain::accessNext()
00329 {
00330   moveNext();
00331   return _current;
00332 }
00333 
00334 // GET A COPY OF THE SUCCESSOR OF THE CURRENT POINT
00335 
00336 GenPoint<int>
00337 FreemanChain::next()
00338 {
00339   moveNext();
00340   return _current;
00341 }
00342 
00343 // GET THE PREDECESSOR OF THE CURRENT POINT
00344 
00345 const GenPoint<int>&
00346 FreemanChain::accessPrevious()
00347 {
00348   movePrevious();
00349   return _current;
00350 }
00351 
00352 // GET A COPY OF THE PREDECESSOR OF THE CURRENT POINT
00353 
00354 GenPoint<int>
00355 FreemanChain::previous()
00356 {
00357   movePrevious();
00358   return _current;
00359 }
00360 
00361 
00362 // -------------------------------------------------------------------
00363 // I N S E R T I O N 
00364 // -------------------------------------------------------------------
00365 
00366 
00367 // INSERT A POINT AT THE BEGINNING OF THE CHAIN
00368 //
00369 // WARNING
00370 // - When the chain is not empty, the new point is supposed
00371 //   to be consistent with the coding of the chain: All the points
00372 //   of the segment joining the first point of the chain to the
00373 //   new point must be strictly aligned along one of the 8 Freeman
00374 //   directions.
00375 // - A new point is always inserted in the chain, even when
00376 //   the given point is the same as the first point of the chain
00377 //   or is aligned with the first segment of the chain.
00378 
00379 void
00380 FreemanChain::push_front(const GenPoint<int>& aPt)
00381 {
00382  if (_chain.empty())
00383     {
00384       // EMPTY CHAIN
00385       // -----------
00386 
00387       // Insert new point in chain
00388       _chain.push_back(FreemanCode(QGE_DIRECTION_N, 0));
00389       // Update first, current and last points in chain
00390       _first   = aPt;
00391       _current = aPt;
00392       _last    = aPt;
00393       // Set iterator to the beginning of chain
00394       _iter = _chain.begin();
00395     }
00396   else
00397     {
00398       // NON-EMPTY CHAIN
00399       // ---------------
00400       
00401       int dx = aPt.x() - _first.x();
00402       int dy = aPt.y() - _first.y();
00403 
00404       // Insert new point as the beginning of the chain
00405       FreemanCode& code = _chain.front();
00406       code.setDirLength(qgDirection(dx, dy), (dx == 0) ? abs(dy) : abs(dx));
00407 
00408       // New beginning of the list representing the chain
00409       _chain.push_front(FreemanCode(QGE_DIRECTION_N, 0));
00410       // Update first point in chain
00411       _first = aPt;
00412     }
00413 }
00414 
00415 
00416 // INSERT A POINT DEFINED BY A FREEMAN CODE
00417 // AT THE BEGINNING OF THE CHAIN
00418 //
00419 // WARNING
00420 // - The chain is supposed not to be empty.
00421 // - A new point is always inserted in the chain, even when
00422 //   the direction of the given Freeman code is the same as
00423 //   the direction of the first Freeman code of the chain, or when
00424 //   it is the opposite of the direction of the first Freeman code
00425 //   of the chain.
00426 
00427 void
00428 FreemanChain::push_front(const FreemanCode& aCode)
00429 {
00430   // Insert new point as the beginning of the chain
00431   FreemanCode& code = _chain.front();
00432   code.setDirLength(qgOpposite(aCode.direction()), aCode.length());
00433 
00434   // New beginning of the list representing the chain
00435   _chain.push_front(FreemanCode(QGE_DIRECTION_N, 0));
00436 
00437   // Update first point in chain
00438   _first = aCode.toPoint(_first);
00439 }
00440 
00441 
00442 // INSERT A POINT AT THE END OF THE CHAIN
00443 //
00444 // WARNING
00445 // - When the chain is not empty, the new point is supposed
00446 //   to be consistent with the coding of the chain: All the points
00447 //   of the segment joining the last point of the chain to the
00448 //   new point must be strictly aligned along one of the 8 Freeman
00449 //   directions.
00450 // - A new point is always inserted in the chain, even when
00451 //   the given point is the same as the last point of the chain
00452 //   or is aligned with the last segment of the chain.
00453 
00454 void
00455 FreemanChain::push_back(const GenPoint<int>& aPt)
00456 {
00457   if (_chain.empty())
00458     {
00459       // EMPTY CHAIN
00460       // -----------
00461       // Insert new point in chain
00462       _chain.push_back(FreemanCode(QGE_DIRECTION_N, 0));
00463       // Update first, current and last points in chain
00464       _first   = aPt;
00465       _current = aPt;
00466       _last    = aPt;
00467       // Update iterator
00468       _iter = _chain.begin();
00469     }
00470   else
00471     {
00472       // NON-EMPTY CHAIN
00473       // ---------------
00474       
00475       int dx = _last.x() - aPt.x();
00476       int dy = _last.y() - aPt.y();
00477 
00478       // Insert new point as the end of the chain
00479       _chain.push_back
00480         (FreemanCode(qgDirection(dx, dy), (dx == 0) ? abs(dy) : abs(dx)));
00481       // Update last point in chain
00482       _last = aPt;
00483     }
00484 }
00485 
00486 
00487 // INSERT A POINT DEFINED BY A FREEMAN CODE AT THE END OF THE CHAIN
00488 //
00489 // @warning
00490 // - The chain is supposed not to be empty.
00491 // - A new point is always inserted in the chain, when
00492 //   the direction of the given Freeman code is the same as
00493 //   the direction of the last Freeman code of the chain, or when
00494 //   it is the opposite of the direction of the last Freeman code
00495 //   of the chain.
00496 
00497 void
00498 FreemanChain::push_back(const FreemanCode& aCode)
00499 {
00500   _chain.push_back(aCode);
00501   // Update last point
00502   _last = aCode.toPoint(_last);
00503 }
00504 
00505 
00506 // -------------------------------------------------------------------
00507 // T R A N S F O R M A T I O N S 
00508 // -------------------------------------------------------------------
00509 
00510 
00511 // REVERSE ELEMENTS ORDER IN THE CHAIN
00512 // NOTHING TO DO IF THE CHAIN DOES NOT INCLUDE AT LEAST TWO POINTS
00513 
00514 void
00515 FreemanChain::reverse()
00516 {
00517   int chLg = _chain.size();
00518   if (chLg > 1)
00519     {
00520 // Starting from both ends of the chain (first element excepted),
00521 // swap elements after having changed each direction for its opposite.
00522 //
00523 //              +-----+    +----+    +----+     +----+    +----+
00524 // _first = P0  |North|    | D1 |    | D2 |     |Dn-1|    | Dn |
00525 // _last  = Pn  +-----+<==>+----+<==>+----+ ... +----+<==>+----+
00526 //              |  0  |    | L1 |    | L2 |     |Ln-1|    | Ln |
00527 //              +-----+    +----+    +----+     +----+    +----+
00528 //                           ^                               ^
00529 //                           |       dx = opposite(Dx)       |
00530 //                           |_______________________________|
00531 //                                           |
00532 //                                           V
00533 //              +-----+    +----+    +----+     +----+    +----+
00534 // _first = Pn  |North|    | dn |    |dn-1|     | d2 |    | d1 |
00535 // _last  = P0  +-----+<==>+----+<==>+----+ ... +----+<==>+----+
00536 //              |  0  |    | Ln |    |Ln-1|     | L2 |    | L1 |
00537 //              +-----+    +----+    +----+     +----+    +----+
00538 
00539       QGEdirection dir;
00540       int lg;
00541 
00542       int iCntEnd = (chLg - 1) / 2;
00543 
00544       std::list<FreemanCode>::iterator it = _chain.begin();
00545       it++;
00546       std::list<FreemanCode>::iterator itRev = _chain.end();
00547       itRev--;
00548 
00549       for (int iCnt = 1 ; iCnt <= iCntEnd ; iCnt++, it++, itRev--)
00550         {
00551           dir = qgOpposite(it->direction());
00552           lg  = it->length();
00553 
00554           it->setDirLength(qgOpposite(itRev->direction()), itRev->length());
00555           itRev->setDirLength(dir, lg);
00556         }
00557 
00558       // Invert direction of the last element if necessary
00559       if (((chLg + 1) % 2) == 1)
00560         {
00561           it->setDir(qgOpposite(it->direction()));
00562         }
00563 
00564       // Update first and last points
00565       int x = _last.x();
00566       int y = _last.y();
00567       _last = _first;
00568       _first.setXY(x, y);
00569 
00570       // Update current point
00571       _current = _first;
00572       it = _chain.begin();
00573       bool loop = true;
00574       while (loop)
00575         {
00576           _current = it->toPoint(_current);
00577 
00578           if (it == _iter)
00579             {
00580               loop = false;
00581             }
00582           else
00583             {
00584               it++;
00585             }
00586         } // END while
00587     }
00588 }
00589 
00590 
00591 // -------------------------------------------------------------------
00592 // C O N V E R S I O N S 
00593 // -------------------------------------------------------------------
00594 
00595 
00596 // CONVERT INTO A (STL) LIST OF POINTS HAVING INTEGER COORDINATES
00597 
00598 std::list< GenPoint<int> >
00599 FreemanChain::toPointList() const
00600 {
00601   std::list< GenPoint<int> > ptList;
00602   GenPoint<int> pt = _first;
00603 
00604   for (std::list<FreemanCode>::const_iterator itCh = _chain.begin();
00605        itCh != _chain.end();
00606        ++itCh)
00607     {
00608       pt = itCh->toPoint(pt);
00609       ptList.push_back(pt);
00610     }
00611 
00612   return ptList;
00613 }
00614 
00615 // CONVERT INTO A (STL) LIST OF POINTS HAVING FLOAT COORDINATES
00616 
00617 std::list< GenPoint<float> >
00618 FreemanChain::toFPointList() const
00619 {
00620   std::list< GenPoint<float> > ptList;
00621   GenPoint<float> pt = (GenPoint<float>)_first;
00622 
00623   for (std::list<FreemanCode>::const_iterator itCh = _chain.begin();
00624        itCh != _chain.end();
00625        ++itCh)
00626     {
00627       pt = itCh->toPoint(pt);  // Implicit conversion
00628       ptList.push_back(pt);
00629     }
00630 
00631   return ptList;
00632 }
00633 
00634 // CONVERT INTO A (STL) LIST OF POINTS HAVING DOUBLE COORDINATES
00635 
00636 std::list< GenPoint<double> >
00637 FreemanChain::toDPointList() const
00638 {
00639   std::list< GenPoint<double> > ptList;
00640   GenPoint<double> pt = (GenPoint<double>)_first;
00641 
00642   for (std::list<FreemanCode>::const_iterator itCh = _chain.begin();
00643        itCh != _chain.end();
00644        ++itCh)
00645     {
00646       pt = itCh->toPoint(pt);  // Implicit conversion
00647       ptList.push_back(pt);
00648     }
00649 
00650   return ptList;
00651 }
00652 
00653 
00654 // -------------------------------------------------------------------
00655 // O P E R A T O R S 
00656 // -------------------------------------------------------------------
00657 
00658 
00659 // ASSIGNMENT
00660 
00661 FreemanChain&
00662 FreemanChain::operator=(const FreemanChain& aFreemanCh)
00663 {
00664   // Are left hand side and right hand side different objects?
00665   if (this != &aFreemanCh)
00666     {
00667       _chain = aFreemanCh._chain;
00668       // Set iterator to the beginning of the chain
00669       _iter = _chain.begin();
00670 
00671       _first   = aFreemanCh._first;
00672       _current = aFreemanCh._current;
00673       _last    = aFreemanCh._last;
00674     }
00675 
00676   return *this;
00677 }
00678 
00679 
00680 // -------------------------------------------------------------------
00681 
00682 
00683 } // namespace qgar