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

_QGAR_GenPolygon.TCC

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   _QGAR_GenPolygon.TCC
00030  * @brief  Implementation of function members
00031  *         of class qgar::GenPolygon.
00032  *
00033  * @author <a href="mailto:qgar-develop@loria.fr?subject=Qgar fwd Gérald Masini">Gérald Masini</a>
00034  * @date   December 14, 2004  16:16
00035  * @since  Qgar 2.2
00036  */
00037 
00038 
00039 
00040 // STD
00041 #include <cmath>
00042 #include <deque>
00043 #include <iostream>
00044 #include <list>
00045 #include <vector>
00046 // QGAR
00047 #include <qgarlib/ISerializable.H>
00048 
00049 
00050 
00051 namespace qgar
00052 {
00053 
00054 
00055 // -------------------------------------------------------------------
00056 // C O N S T R U C T O R S
00057 // -------------------------------------------------------------------
00058 
00059 
00060 // DEFAULT CONSTRUCTOR
00061 
00062 template <class T>
00063 GenPolygon<T>::GenPolygon()
00064 
00065   : AbstractGenPrimitive<T>(0, 0, 0, 0)
00066 
00067 {
00068   // VOID
00069 }
00070 
00071 
00072 // COPY CONSTRUCTOR
00073 
00074 template <class T>
00075 GenPolygon<T>::GenPolygon(const GenPolygon<T>& aPoly)
00076 
00077   : AbstractGenPrimitive<T>(aPoly._source, aPoly._target),
00078     _vertices(aPoly._vertices)
00079 
00080 {
00081   // VOID
00082 }
00083 
00084 
00085 // INITIALIZE FROM A Qgar POLYGON
00086 
00087 template <class T>
00088 GenPolygon<T>::GenPolygon(const GenQgarPolygon<T>& aQPoly)
00089 
00090   : AbstractGenPrimitive<T>(aQPoly.accessSource(),
00091                             aQPoly.accessTarget()),
00092     _vertices(aQPoly.accessVertices())
00093 
00094 {
00095   // VOID
00096 }
00097 
00098 
00099 // INITIALIZE FROM A STL LIST OF AT LEAST 3 POINTS
00100 
00101 template <class T>
00102 GenPolygon<T>::GenPolygon(const std::list< GenPoint<T> >& aPtList)
00103 
00104   throw(QgarErrorUser)
00105 
00106 {
00107   if (aPtList.size() < 3)
00108     {
00109       throw QgarErrorUser(__FILE__, __LINE__,
00110                           "template <class T> qgar::GenPolygon<T>::GenPolygon(const std::list< qgar::GenPoint<T> >&)",
00111                           "Cannot create a polygon including less than 3 vertices");
00112     }
00113 
00114   // Create vertices by copying the given list
00115   for (typename std::list< GenPoint<T> >::const_iterator itPL = aPtList.begin() ;
00116        itPL != aPtList.end() ;
00117        ++itPL)
00118     {
00119       _vertices.push_back(*itPL);
00120     }
00121 
00122   // Update source and target.
00123   this->_source = aPtList.front();
00124   this->_target = aPtList.back();
00125 }
00126 
00127 
00128 // -------------------------------------------------------------------
00129 // D E S T R U C T O R 
00130 // -------------------------------------------------------------------
00131 
00132 
00133 template <class T>
00134 GenPolygon<T>::~GenPolygon()
00135 {
00136   // VOID
00137 }
00138 
00139 
00140 // -------------------------------------------------------------------
00141 // C O P Y 
00142 // -------------------------------------------------------------------
00143 
00144 
00145 // DEEP COPY
00146 
00147 template <class T>
00148 GenPolygon<T>*
00149 GenPolygon<T>::clone() const
00150 {
00151   return new GenPolygon<T>(*this);
00152 }
00153 
00154 
00155 // -------------------------------------------------------------------
00156 // O P E R A T O R S 
00157 // -------------------------------------------------------------------
00158 
00159 
00160 // ASSIGNMENT
00161 
00162 template <class T>
00163 GenPolygon<T>&
00164 GenPolygon<T>::operator=(const GenPolygon<T>& aPoly)
00165 {
00166   // Are left hand side and right hand side different objects?
00167   if (this != &aPoly)
00168     {
00169       AbstractGenPrimitive<T>::operator=(aPoly);
00170       _vertices = aPoly._vertices;
00171     }
00172 
00173   return *this;
00174 }
00175 
00176 
00177 // -------------------------------------------------------------------
00178 // A R E A
00179 // -------------------------------------------------------------------
00180 
00181 
00182 // GET SIGNED AREA
00183 
00184 template <class T>
00185 double
00186 GenPolygon<T>::signedArea()
00187 {
00188   typename std::deque< GenPoint<T> >::iterator itDP = _vertices.begin();
00189 
00190   // First vertex
00191   double x1 = (double) (*itDP).x();
00192   double y1 = (double) (*itDP).y();
00193   // Previous vertex (in loop)
00194   double xp = x1;
00195   double yp = y1;
00196   ++itDP;
00197 
00198   // The area
00199   double area = 0.;
00200 
00201   while (itDP != _vertices.end())
00202     {
00203       // Current vertice
00204       double xc = (double) (*itDP).x();
00205       double yc = (double) (*itDP).y();
00206 
00207       // Update area
00208       area += (xp * yc) - (yp * xc);
00209 
00210       // Current vertex becomes previous vertex
00211       xp = xc;
00212       yp = yc;
00213 
00214       // Next vertex
00215       ++itDP;
00216     }
00217 
00218   // Last vertex and first vertex to complete computation
00219   area += (xp * y1) - (yp * x1);
00220 
00221   return area / 2.;
00222 }
00223 
00224 
00225 // GET AREA
00226 
00227 template <class T>
00228 inline double
00229 GenPolygon<T>::area()
00230 {
00231   return std::fabs(signedArea());
00232 }
00233 
00234 
00235 // -------------------------------------------------------------------
00236 // A C C E S S   T O   V E R T I C E S
00237 // -------------------------------------------------------------------
00238 
00239 
00240 // GET NUMBER OF VERTICES
00241 
00242 template <class T>
00243 inline int
00244 GenPolygon<T>::size() const
00245 {
00246   return _vertices.size();
00247 }
00248 
00249 
00250 // GET VERTICES
00251 
00252 template <class T>
00253 inline const std::deque< GenPoint<T> >&
00254 GenPolygon<T>::accessVertices() const
00255 {
00256   return this->_vertices;
00257 }
00258 
00259 
00260 // GIVE NON-PROTECTED ACCESS TO THE VERTICES
00261 
00262 template <class T>
00263 inline std::deque< GenPoint<T> >&
00264 GenPolygon<T>::getVertices()
00265 {
00266   return this->_vertices;
00267 }
00268 
00269 
00270 // GET A COPY OF VERTICES
00271 
00272 template <class T>
00273 inline std::deque< GenPoint<T> >
00274 GenPolygon<T>::vertices() const
00275 {
00276   return this->_vertices;
00277 }
00278 
00279 
00280 // -------------------------------------------------------------------
00281 // I N S E R T   V E R T I C E S
00282 // -------------------------------------------------------------------
00283 
00284 
00285 // INSERT A POINT AS NEW SOURCE
00286 
00287 template <class T>
00288 GenPolygon<T>&
00289 GenPolygon<T>::appendSource(const GenPoint<T>& aPt)
00290 {
00291   this->_source = aPt;
00292   this->_vertices.push_front(aPt);   
00293   return *this;
00294 }
00295  
00296 
00297 // INSERT A POINT AS NEW TARGET
00298 
00299 template <class T>
00300 GenPolygon<T>&
00301 GenPolygon<T>::appendTarget(const GenPoint<T>& aPt)
00302 {
00303   this->_target = aPt;
00304   this->_vertices.push_back(aPt);
00305   return *this;
00306 }
00307 
00308 
00309 // APPEND A STL VECTOR OF POINTS
00310 
00311 template<class T>
00312 GenPolygon<T>&
00313 GenPolygon<T>::append(const std::vector<GenPoint<T> >& aPtVector)
00314 {
00315   std::copy(aPtVector.begin(),
00316             aPtVector.end(),
00317             back_inserter(this->_vertices));
00318   
00319   // Update target: New target is the last point of the given list
00320   this->_target = aPtVector.back();
00321 
00322   return *this;
00323 }
00324 
00325 
00326 // -------------------------------------------------------------------
00327 // R E M O V E   V E R T I C E S
00328 // -------------------------------------------------------------------
00329 
00330 
00331 // REMOVE A VERTICE FROM THE POLYGON
00332 
00333 template <class T>
00334 GenPolygon<T>&
00335 GenPolygon<T>::remove(const GenPoint<T>& aPt)
00336 
00337   throw(QgarErrorUser)
00338 
00339 {
00340   // The polygon must always be provided with at least 3 vertices
00341   if (this->_vertices.size() == 3)
00342     {
00343       throw QgarErrorUser(__FILE__, __LINE__,
00344                           "template <class T> qgar::GenPolygon<T>& qgar::GenPolygon<T>::remove(const qgar::GenPoint<T>&)",
00345                           "Cannot remove a vertex from a polygon including 3 vertices");
00346     }
00347 
00348   if (aPt == (this->_vertices).front())
00349     {
00350       // Remove first element
00351       (this->_vertices).pop_front();
00352 
00353       // New first element becomes the source of the polygon
00354       this->_source = this->_vertices.front();
00355     }
00356   else if (aPt == (this->_vertices).back())
00357     {
00358       // Remove last element
00359       _vertices.pop_back();
00360 
00361       // New last element becomes the source of the polygon
00362       this->_target = _vertices.back();
00363     }
00364   else
00365     {
00366       typename std::deque<GenPoint<T> >::iterator it =
00367         find((this->_vertices).begin(), (this->_vertices).end(), aPt);
00368   
00369       // Remove vertex if found
00370       if (it != (this->_vertices).end())
00371         {
00372           (this->_vertices).erase(it);
00373         }
00374     }
00375 
00376   return *this;
00377 }
00378 
00379 
00380 // -------------------------------------------------------------------
00381 // CONVERSIONS OF THE SERIES OF VERTICES
00382 // -------------------------------------------------------------------
00383 
00384 
00385 // GET A VECTOR OF POINTS FROM THE LIST OF VERTICES
00386 
00387 template <class T>
00388 std::vector< GenPoint<T> >
00389 GenPolygon<T>::toPointVector()
00390 {
00391   std::vector< GenPoint<T> > ptVector;
00392 
00393   // Copy all vertices in the vector created above
00394   std::copy(_vertices.begin(),
00395             _vertices.end(), 
00396             std::back_inserter(ptVector));
00397   
00398   return ptVector;
00399 }
00400 
00401 
00402 // GET A STL LIST OF (GEOMETRICAL) SEGMENTS FROM THE VERTICES
00403 
00404 template <class T>
00405 std::list<GenSegment<T> >
00406 GenPolygon<T>::toSegList()
00407 {
00408   std::list< GenSegment<T> > segList;
00409 
00410   // Iterators on current and previous vertices
00411   typename std::deque< GenPoint<T> >::iterator itDP = _vertices.begin();
00412   typename std::deque< GenPoint<T> >::iterator itDPP = itDP;
00413   ++itDP;
00414 
00415   for ( ; itDP != _vertices.end() ; ++itDP)
00416     {
00417       // Create current segment
00418       segList.push_back(GenSegment<T>(*itDPP, *itDP));
00419 
00420       // Update previous vertex
00421       itDPP = itDP;
00422     }
00423 
00424   // Create last segment
00425   segList.push_back(GenSegment<T>(*itDPP, _vertices[0]));
00426 
00427   return segList;
00428 }
00429 
00430 
00431 // GET A STL LIST OF Qgar SEGMENTS FROM THE VERTICES
00432 
00433 template <class T>
00434 std::list<GenQgarSegment<T> >
00435 GenPolygon<T>::toQgarSegList(int aThickness,
00436                              QGEcolor aColor,
00437                              QGEoutline anOutline)
00438 {
00439   std::list< GenQgarSegment<T> > segList;
00440 
00441   // Iterators on current and previous vertices
00442   typename std::deque< GenPoint<T> >::iterator itDP = _vertices.begin();
00443   typename std::deque< GenPoint<T> >::iterator itDPP = itDP;
00444   ++itDP;
00445 
00446   for ( ; itDP != _vertices.end() ; ++itDP)
00447     {
00448       // Create current segment
00449       segList.push_back(GenQgarSegment<T>(*itDPP,
00450                                           *itDP,
00451                                           aThickness,
00452                                           aColor,
00453                                           anOutline));
00454 
00455       // Update previous vertex
00456       itDPP = itDP;
00457     }
00458 
00459   // Create last segment
00460   segList.push_back(GenQgarSegment<T>(*itDPP,
00461                                       _vertices[0],
00462                                       aThickness,
00463                                       aColor,
00464                                       anOutline));
00465 
00466   return segList;
00467 }
00468 
00469 
00470 // -------------------------------------------------------------------
00471 // S E R I A L I Z A T I O N / D E S E R I A L I Z A T I O N 
00472 // -------------------------------------------------------------------
00473 
00474 
00475 template <class T>
00476 std::istream& 
00477 GenPolygon<T>::read(std::istream& anInStream)
00478 {
00479   // Skip name
00480   qgReadObjName(anInStream, "Polygon");
00481 
00482   // Source and target
00483   qgReadObjData(anInStream, this->_source);
00484   qgReadObjData(anInStream, this->_target);
00485 
00486   // Remove possible stored vertices
00487   (this->_vertices).clear();
00488 
00489   // Get vertices number
00490   int pointCnt;
00491   qgReadObjData(anInStream, pointCnt);
00492   
00493   // Get vertices, conforming to their initial ordering
00494   for(int iCnt = 0 ; iCnt < pointCnt ; ++iCnt)
00495     {
00496       GenPoint<T> point;
00497       qgReadObjData(anInStream, point);
00498       (this->_vertices).push_back(point);
00499     }
00500 
00501   return anInStream;
00502 }
00503 
00504 
00505 template <class T>
00506 std::ostream& 
00507 GenPolygon<T>::write(std::ostream& anOutStream) const
00508 {
00509   // Source, target and vertices number
00510 
00511   anOutStream << "Polygon("
00512               << this->source()
00513               << ")("
00514               << this->target()
00515               << ")("
00516               << (this->accessVertices()).size()
00517               << ')';
00518 
00519   // Vertices
00520 
00521   for(typename std::deque< GenPoint<T> >::const_iterator itDP
00522         = (this->accessVertices()).begin();
00523       itDP != (this->accessVertices()).end();
00524       ++itDP)
00525     {
00526       anOutStream << '('
00527                   << *itDP
00528                   << ')';
00529     }
00530 
00531   return anOutStream;
00532 }
00533 
00534 
00535 // VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
00536 // V                                                                 V
00537 // V            IMPLEMENTATION OF PURE VIRTUAL FUNCTIONS             V
00538 // V              INHERITED FROM AbstractGenPrimitive                V
00539 // V                                                                 V
00540 // VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
00541 
00542 
00543 // -------------------------------------------------------------------
00544 // G E O M E T R I C A L   S T R U C T U R E   U P D A T E S
00545 // -------------------------------------------------------------------
00546 
00547 
00548 // THE SOURCE HAS BEEN CHANGED
00549 
00550 template <class T>
00551 void
00552 GenPolygon<T>::updateSource()
00553 {
00554   (_vertices.front()).setXY(this->_source.x(), this->_source.y());
00555 }
00556 
00557 
00558 // THE TARGET HAS BEEN CHANGED
00559 
00560 template <class T>
00561 void
00562 GenPolygon<T>::updateTarget()
00563 {
00564   (_vertices.back()).setXY(this->_target.x(), this->_target.y());
00565 }
00566 
00567 
00568 // BOTH SOURCE AND TARGET HAVE BEEN CHANGED
00569 
00570 template <class T>
00571 void
00572 GenPolygon<T>::updateSourceTarget()
00573 {
00574   this->updateSource();
00575   this->updateTarget();
00576 }
00577 
00578 
00579 // -------------------------------------------------------------------
00580 // G E O M E T R Y :   T R A N S L A T I O N 
00581 // -------------------------------------------------------------------
00582 
00583 
00584 template <class T>
00585 void
00586 GenPolygon<T>::translate(T aTransX, T aTransY)
00587 {
00588   // Translate source and target
00589   this->setSourceTarget(this->xSource() + aTransX,
00590                         this->ySource() + aTransY,
00591                         this->xTarget() + aTransX,
00592                         this->yTarget() + aTransY);
00593 
00594   // Translate vertices
00595   for(typename std::deque< GenPoint<T> >::iterator itDP = _vertices.begin();
00596       itDP < _vertices.end();
00597       ++itDP)
00598     {
00599       (*itDP).translate(aTransX, aTransY);
00600     }
00601 }
00602 
00603 
00604 // VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
00605 // V                                                                 V
00606 // VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
00607 
00608 
00609 } // namespace qgar