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

Maer.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   Maer.C
00030  * @brief  Implementation of class qgar::Maer.
00031  *
00032  * See file Maer.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   May 13, 2004  11:30
00036  * @since  Qgar 2.1
00037  */
00038 
00039 
00040 
00041 // STD
00042 #include <cmath>
00043 #include <limits>
00044 #include <list>
00045 // QGAR
00046 #include <qgarlib/FreemanChain.H>
00047 #include <qgarlib/GenConvexHull.H>
00048 #include <qgarlib/Maer.H>
00049 #include <qgarlib/math.H>
00050 #include <qgarlib/primitives.H>
00051 
00052 
00053 
00054 namespace qgar
00055 {
00056 
00057 // -------------------------------------------------------------------
00058 // -------------------------------------------------------------------
00059 // C O N S T R U C T O R S
00060 // -------------------------------------------------------------------
00061 // -------------------------------------------------------------------
00062 
00063 
00064 // CREATE FROM A LIST OF POINTS HAVING double COORDINATES
00065 
00066 Maer::Maer(const std::list<DPoint>& aPtList)
00067 {
00068   PRIVATEcomputeMaer(aPtList);
00069 }
00070 
00071 // CREATE FROM A LIST OF POINTS HAVING COORDINATES TYPE
00072 // DIFFERENT FROM double
00073 
00074 template <class T>
00075 Maer::Maer(const std::list< GenPoint<T> >& aPtList)
00076 {
00077   std::list<DPoint> dList;
00078 
00079   transform(aPtList.begin(),
00080             aPtList.end(),
00081             PRIVATEtoDPoint(),
00082             back_inserter(dList));
00083 
00084   PRIVATEcomputeMaer(dList);
00085 }
00086 
00087 // CREATE FROM A FREEMAN CHAIN
00088 
00089 Maer::Maer(const FreemanChain& aCh)
00090 {
00091   PRIVATEcomputeMaer(aCh.toDPointList());
00092 }
00093 
00094 // COPY CONSTRUCTOR
00095 
00096 Maer::Maer(const Maer& aMaer)
00097 
00098   : _vertices(aMaer._vertices),
00099     _area(aMaer._area)
00100 
00101 {
00102   // VOID
00103 }
00104 
00105 
00106 // -------------------------------------------------------------------
00107 // -------------------------------------------------------------------
00108 // D E S T R U C T O R
00109 // -------------------------------------------------------------------
00110 // -------------------------------------------------------------------
00111 
00112 
00113 // NON-VIRTUAL DESTRUCTOR
00114 
00115 Maer::~Maer()
00116 {
00117   // VOID
00118 }
00119 
00120 
00121 // -------------------------------------------------------------------
00122 // -------------------------------------------------------------------
00123 // A C C E S S   T O   C O R N E R S
00124 // -------------------------------------------------------------------
00125 // -------------------------------------------------------------------
00126 
00127 // GET THE LIST INCLUDING THE 4 CORNERS OF THE MAER
00128 
00129 const std::list<DPoint>&
00130 Maer::accessVertices() const
00131 {
00132   return _vertices;
00133 }
00134   
00135 // GET A COPY OF THE LIST INCLUDING THE 4 CORNERS OF THE MAER
00136 
00137 std::list<DPoint>
00138 Maer::vertices() const
00139 {
00140   return _vertices;
00141 }
00142 
00143 
00144 // -------------------------------------------------------------------
00145 // -------------------------------------------------------------------
00146 // O P E R A T O R S
00147 // -------------------------------------------------------------------
00148 // -------------------------------------------------------------------
00149 
00150 
00151 // ASSIGNMENT
00152 
00153 Maer&
00154 Maer::operator=(const Maer& aMaer)
00155 {
00156   // Are left hand side and right hand side different objects?
00157   if (this != &aMaer)
00158     {
00159       _vertices = aMaer._vertices;
00160       _area     = aMaer._area;
00161     }
00162 
00163   return *this;
00164 }
00165 
00166 
00167 // -------------------------------------------------------------------
00168 // -------------------------------------------------------------------
00169 // C O N S T R U C T I O N   O F   T H E   M A E R   (PRIVATE)
00170 // -------------------------------------------------------------------
00171 // -------------------------------------------------------------------
00172 
00173 
00174 void
00175 Maer::PRIVATEcomputeMaer(const std::list<DPoint>& aPtList)
00176 {
00177   // THE CONVEX HULL OF THE GIVEN POINTS
00178   // ===================================
00179 
00180   DConvexHull hull(aPtList);
00181 
00182   // THE COMPONENT IS A SINGLE POINT: DEGENERATED MAER
00183   // =================================================
00184 
00185   if (hull.size() == 1)
00186     {
00187       // 4 same corners and null area
00188       _vertices.push_back(hull.accessPivot());
00189       _vertices.push_back(hull.accessPivot());
00190       _vertices.push_back(hull.accessPivot());
00191       _vertices.push_back(hull.accessPivot());
00192       _area = 0.;
00193 
00194       return;
00195     }
00196 
00197   // COMPUTE THE DIFFERENT RECTANGLES AND SELECT THE MINIMAL ONE
00198   // ===========================================================
00199 
00200   // List of the vertices of the hull
00201   const std::list<DPoint>& vList = hull.accessVertices();
00202 
00203   // 2 consecutive points of the hull
00204   std::list<DPoint>::const_iterator itPrev = vList.begin();
00205   std::list<DPoint>::const_iterator itCurr = itPrev;
00206   itCurr++;
00207 
00208   // Current minimum area
00209   _area = std::numeric_limits<double>::max();
00210 
00211   // Consider each consecutive pair of hull vertices
00212   // and compute the corresponding rectangle
00213   // WARNING: The last pair includes the last and first vertices
00214 
00215   do
00216     // DO WHILE BLOCK  WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
00217     {
00218 
00219       // Coordinates of previous point
00220       double xPrev = itPrev->x();
00221       double yPrev = itPrev->y();
00222 
00223       // Direction of the vector joining previous and current points 
00224       double theta = atan2(itCurr->y() - yPrev, itCurr->x() - xPrev);
00225       if (theta < 0.)
00226         {
00227            theta += Math::QG_2PI;
00228         }
00229 
00230       // Initializations
00231       double minX = std::numeric_limits<double>::max();
00232       double maxX = std::numeric_limits<double>::min();
00233       double minY = std::numeric_limits<double>::max();
00234       double maxY = std::numeric_limits<double>::min();
00235       
00236       // Minimum and maximum X and Y
00237       for (std::list<DPoint>::const_iterator itV  = vList.begin() ;
00238            itV != vList.end() ;
00239            itV++)
00240         { 
00241           // Translation
00242           double xTmp = itV->x() - xPrev;
00243           double yTmp = itV->y() - yPrev;
00244           
00245           // Rotation
00246           double x = (  xTmp * cos(theta) ) + ( yTmp * sin(theta) );
00247           double y = ( -xTmp * sin(theta) ) + ( yTmp * cos(theta) );
00248           
00249           // Update coordinates min's and max's
00250           if (x < minX)
00251             {
00252               minX = x;
00253             }
00254           if (x > maxX)
00255             {
00256               maxX = x;
00257             }
00258           if (y < minY)
00259             {
00260               minY = y;
00261             }
00262           if (y > maxY)
00263             {
00264               maxY = y;
00265             }
00266         }
00267       
00268       // The four corners of the corresponding rectangle
00269        double xTopL = minX * cos(theta) - minY * sin(theta) + xPrev;
00270        double yTopL = minX * sin(theta) + minY * cos(theta) + yPrev;
00271       
00272        double xTopR = minX * cos(theta) - maxY * sin(theta) + xPrev;
00273        double yTopR = minX * sin(theta) + maxY * cos(theta) + yPrev;
00274       
00275        double xBotR = maxX * cos(theta) - maxY * sin(theta) + xPrev;
00276        double yBotR = maxX * sin(theta) + maxY * cos(theta) + yPrev;
00277       
00278        double xBotL = maxX * cos(theta) - minY * sin(theta) + xPrev;
00279        double yBotL = maxX * sin(theta) + minY * cos(theta) + yPrev;
00280 
00281        double currArea =   hypot(xTopL - xTopR, yTopL - yTopR)
00282                          * hypot(xTopR - xBotR, yTopR - yBotR);
00283              
00284       // Update minimum area
00285       if (currArea < _area)
00286         {
00287           // Current rectangle is the minimum one up to now
00288           _area = currArea;
00289 
00290           // Save new maer
00291           _vertices.clear();
00292           _vertices.push_back(DPoint(xTopL, yTopL));
00293           _vertices.push_back(DPoint(xTopR, yTopR));
00294           _vertices.push_back(DPoint(xBotR, yBotR));
00295           _vertices.push_back(DPoint(xBotL, yBotL));
00296         }
00297 
00298       // Next vertices pair
00299       // WARNING: The last pair includes the last and first vertices
00300       itPrev = itCurr;
00301       itCurr++;
00302       if (itCurr == vList.end())
00303         {
00304           itCurr = vList.begin();
00305         }
00306 
00307     }
00308     // END OF DO WHILE BLOCK  WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
00309 
00310   while (itPrev != vList.begin());
00311 
00312 }
00313 
00314 // -------------------------------------------------------------------
00315 
00316 } // namespace qgar