00001 /*---------------------------------------------------------------------* 00002 | Library QgarLib, graphics analysis and recognition | 00003 | Copyright (C) 2004 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 license. | 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 #ifndef __GENCONVEXHULL_H_INCLUDED__ 00029 #define __GENCONVEXHULL_H_INCLUDED__ 00030 00031 00032 /** 00033 * @file GenConvexHull.H 00034 * @brief Header file of class qgar::GenConvexHull. 00035 * 00036 * @author <a href="mailto:qgar-develop@loria.fr?subject=Qgar fwd Gérald Masini">Gérald Masini</a> 00037 * @date March 24, 2004 11:24 00038 * @since Qgar 2.1.1 00039 */ 00040 00041 00042 // For RCS/CVS use: Do not delete. 00043 /* $Id: GenConvexHull.H,v 1.21 2005/10/14 17:05:46 masini Exp $ */ 00044 00045 00046 00047 // STD 00048 #include <iosfwd> // Avoid including classes when not necessary 00049 #include <list> 00050 #include <set> 00051 // QGAR 00052 #include <qgarlib/ISerializable.H> 00053 #include <qgarlib/primitives.H> 00054 00055 00056 00057 namespace qgar 00058 { 00059 00060 00061 /** 00062 * @class GenConvexHull GenConvexHull.H "qgarlib/GenConvexHull.H" 00063 * @ingroup TOOL_HULL 00064 * @brief A convex hull represented by a series of points with 00065 * coordinates of type <b>T</b>. 00066 * 00067 * The hull is constructed from a set of points using Graham's scan 00068 * <a href="Bibliography.html#Graham-1972">[Graham, 1972]</a>. 00069 * This algorithm works in three steps: 00070 * <ol> 00071 * <li> 00072 * Find an extreme point, the so-called <i>pivot</i>, which is guaranteed 00073 * to be on the hull: Here, it is chosen as the point with the minimum Y 00074 * coordinate. In case of equality, the point with the minimum X coordinate is 00075 * selected. 00076 * </li> 00077 * <li> 00078 * Sort the points in order of increasing angles about the pivot. 00079 * The result is a star-shaped polygon, in which the pivot can <i>see</i> 00080 * the whole polygon. 00081 * </li> 00082 * <li> 00083 * Build the hull by marching around the star-shaped polygon, adding edges 00084 * at right turns, and backtracking at left turns. 00085 * </li> 00086 * </ol> 00087 * 00088 * Such a hull may be empty. 00089 * It is implemented by: 00090 * - a point representing the pivot (qgar::GenConvexHull::_pivot), 00091 * - a STL list of the vertices of the polygon constituting the hull 00092 * (qgar::GenConvexHull::_vertices). The first vertex of the list is 00093 * always the pivot, 00094 * - a STL multiset including STL pairs associating each vertex with its angle 00095 * about the pivot (qgar::GenConvexHull::_hull). The pivot does not belong to 00096 * the multiset. The pairs are sorted according to increasing angles. 00097 * 00098 * <b>The GenConvexHull class is not supposed to be derived: No function member 00099 * (destructor or whatever else) is virtual.</b> 00100 * Predefined instances of the class are 00101 * qgar::ConvexHull, 00102 * qgar::IConvexHull, 00103 * qgar::FConvexHull, 00104 * and qgar::DConvexHull. 00105 * 00106 * @warning <b>The hull is not guaranteed to be valid when constructed 00107 * from an initial set of points including duplicates.</b> 00108 * 00109 * @todo Class to be completed: In particular, insertion and removal 00110 * of points are not implemented. 00111 * 00112 * @author <a href="mailto:qgar-develop@loria.fr?subject=Qgar fwd Gérald Masini">Gérald Masini</a> 00113 * @date March 24, 2004 11:24 00114 * @since Qgar 2.1.1 00115 */ 00116 template <class T> class GenConvexHull 00117 00118 : public ISerializable 00119 00120 { 00121 // ------------------------------------------------------------------- 00122 // T Y P E D E F I N I T I O N S 00123 // ------------------------------------------------------------------- 00124 public: 00125 00126 /** @name Types */ 00127 // ===== 00128 //@{ 00129 00130 /** 00131 * @brief Type of the points. 00132 */ 00133 typedef T value_type; 00134 00135 /** 00136 * @brief Reference to qgar::GenConvexHull::value_type. 00137 */ 00138 typedef value_type& reference; 00139 00140 /** 00141 * @brief Constant reference to qgar::GenConvexHull::value_type. 00142 */ 00143 typedef const value_type& const_reference; 00144 00145 /** 00146 * @brief Pointer to qgar::GenConvexHull::value_type. 00147 */ 00148 typedef value_type* pointer; 00149 00150 /** 00151 * @brief Constant pointer to qgar::GenConvexHull::value_type. 00152 */ 00153 typedef const value_type* const_pointer; 00154 00155 //@} 00156 00157 // ------------------------------------------------------------------- 00158 // P U B L I C M E M B E R S 00159 // ------------------------------------------------------------------- 00160 public: 00161 00162 /** @name Constructors */ 00163 // ============ 00164 //@{ 00165 00166 /** 00167 * @brief Default constructor. 00168 * 00169 * Construct an empty hull. 00170 */ 00171 GenConvexHull(); 00172 00173 /** 00174 * @brief Copy constructor. 00175 * @param aCHull a convex hull 00176 */ 00177 GenConvexHull(const GenConvexHull<value_type>& aCHull); 00178 00179 /** 00180 * @brief Construct from a STL list of points. 00181 * @param aPtList a STL list of points 00182 * 00183 * The convex hull is constructed using <i>Graham's scan</i>. 00184 * <b>Duplicate points are eliminated.</b> 00185 */ 00186 GenConvexHull(const std::list< GenPoint<value_type> >& aPtList); 00187 00188 //@} 00189 00190 00191 /** @name Destructor */ 00192 // ========== 00193 //@{ 00194 00195 /** 00196 * @brief Non-virtual destructor: The class is not supposed to be derived. 00197 */ 00198 ~GenConvexHull(); 00199 00200 //@} 00201 00202 00203 /** @name Access to characteristics */ 00204 // ========================= 00205 //@{ 00206 00207 /** 00208 * @brief Is hull empty? 00209 */ 00210 inline bool empty() const; 00211 00212 /** 00213 * @brief Get number of vertices. 00214 */ 00215 inline int size() const; 00216 00217 //@} 00218 00219 00220 /** @name Access to vertices */ 00221 // ================== 00222 //@{ 00223 00224 /** 00225 * @brief Get vertices. 00226 */ 00227 const std::list< GenPoint<value_type> >& accessVertices() const; 00228 00229 /** 00230 * @brief Get a copy of the vertices. 00231 */ 00232 std::list< GenPoint<value_type> > vertices() const; 00233 00234 /** 00235 * @brief Get pivot. 00236 */ 00237 const GenPoint<value_type>& accessPivot() const; 00238 00239 /** 00240 * @brief Get a copy of the pivot. 00241 */ 00242 GenPoint<value_type> pivot() const; 00243 00244 //@} 00245 00246 00247 /** @name Operators */ 00248 // ========= 00249 //@{ 00250 00251 /** 00252 * @brief Assignment operator. 00253 * @param aCHull a hull 00254 */ 00255 GenConvexHull<value_type>& operator=(const GenConvexHull<value_type>& aCHull); 00256 00257 //@} 00258 00259 00260 /** @name Serialization/deserialization */ 00261 // ============================= 00262 //@{ 00263 00264 /** 00265 * @brief Deserializes the current hull from an input stream. 00266 * @param anInStream the input stream 00267 * 00268 * A serialized hull is represented by: 00269 @verbatim 00270 ConvexHull(<VERTICES COUNT>)(<VERTICE 1>)...(<VERTICE n>) 00271 @endverbatim 00272 */ 00273 virtual std::istream& read(std::istream& anInStream); 00274 00275 /** 00276 * @brief Serializes the current hull to an input stream. 00277 * @param anOutStream the output stream 00278 * 00279 * A serialized hull is represented by: 00280 @verbatim 00281 ConvexHull(<VERTICES COUNT>)(<VERTICE 1>)...(<VERTICE n>) 00282 @endverbatim 00283 */ 00284 virtual std::ostream& write(std::ostream& anOutStream) const; 00285 00286 //@} 00287 00288 // ------------------------------------------------------------------- 00289 // P R O T E C T E D M E M B E R S 00290 // ------------------------------------------------------------------- 00291 protected: 00292 00293 /** @name Type definitions */ 00294 // ================ 00295 //@{ 00296 00297 /** 00298 * @brief Pair associating a vertex with its angle about the pivot. 00299 */ 00300 typedef std::pair< double, GenPoint<value_type> > QGDpair; 00301 00302 //@} 00303 00304 00305 /** @name Auxiliary structure */ 00306 // =================== 00307 //@{ 00308 00309 /** 00310 * @brief To compare angles about the pivot when sorting points 00311 * to construct their hull. 00312 */ 00313 struct _sortPred 00314 { 00315 /** 00316 * @brief Compares angles about the pivot when sorting points to 00317 * construct their hull. 00318 * 00319 * When angles are equal, pairs are sorted according to decreasing 00320 * Y coordinates of the corresponding points, and, when Y coordinates 00321 * are equal, according to increasing X coordinates: 00322 * <b>The pivot is thus guaranteed to be the leftmost point of minimum 00323 * Y coordinate.</b> 00324 * 00325 * @param aPair1 The lhs parameter of the comparison. 00326 * @param aPair2 The rhs parameter of the comparison. 00327 */ 00328 bool operator()(const std::pair< double, GenPoint<T> >& aPair1, 00329 const std::pair< double, GenPoint<T> >& aPair2) 00330 { 00331 return 00332 // increasing angles... 00333 ( (aPair1.first) < (aPair2.first) ) 00334 || 00335 // ...OR, if angles are equal... 00336 ( ( (aPair1.first) == (aPair2.first) ) 00337 && 00338 // ...decreasing Y coordinates... 00339 ( ( (aPair1.second.y()) > (aPair2.second.y()) ) 00340 || 00341 // ...OR, if y coordinates are equal... 00342 ( ( (aPair1.second.y()) == (aPair2.second.y()) ) 00343 && 00344 // ...increasing X coordinates 00345 ( (aPair1.second.x()) < (aPair2.second.x()) ) 00346 ) 00347 ) 00348 ); 00349 } 00350 }; 00351 00352 //@} 00353 00354 00355 /** @name The hull */ 00356 // ======== 00357 //@{ 00358 00359 /** 00360 * @brief The list of the vertices of the hull. 00361 * 00362 * The first point of the list is the pivot. 00363 */ 00364 std::list< GenPoint<value_type> > _vertices; 00365 00366 /** 00367 * @brief Sorted STL multiset of STL pairs associating a vertex (of the hull) 00368 * with the angle between the X axis and the vector joining the pivot 00369 * and the vertex. 00370 * 00371 * Pairs are sorted in order of increasing angles. 00372 */ 00373 std::multiset<QGDpair, _sortPred> _hull; 00374 00375 /** 00376 * @brief The pivot. 00377 * 00378 * It is the initial given point of minimum ordinate, 00379 * which is guaranteed to belong to the hull. 00380 */ 00381 GenPoint<value_type> _pivot; 00382 00383 //@} 00384 00385 // ------------------------------------------------------------------- 00386 // P R I V A T E M E M B E R S 00387 // ------------------------------------------------------------------- 00388 private: 00389 00390 /** @name Auxiliary functions */ 00391 // =================== 00392 //@{ 00393 00394 /** 00395 * @brief Perfom Graham's scan to construct the convex hull from 00396 * a given list of points. 00397 * 00398 * @param aPtList the initial list of points, from which to construct 00399 * the convex hull 00400 */ 00401 void PRIVATEgraham_sScan(const std::list< GenPoint<value_type> >& aPtList); 00402 00403 //@} 00404 00405 // ------------------------------------------------------------------- 00406 00407 }; // class GenConvexHull 00408 00409 00410 } // namespace qgar 00411 00412 00413 00414 00415 // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 00416 // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 00417 // I M P L E M E N T A T I O N 00418 // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 00419 // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 00420 00421 #include <qgarlib/GenConvexHull.TCC> 00422 00423 // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 00424 // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 00425 00426 00427 00428 00429 // TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT 00430 // TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT 00431 // P R E D E F I N E D H U L L T Y P E S 00432 // TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT 00433 // TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT 00434 00435 00436 namespace qgar 00437 { 00438 00439 00440 /** 00441 * @name Predefined Convex Hulls Types 00442 * @ingroup TOOL_HULL 00443 */ 00444 //{@ 00445 00446 /** 00447 * @brief Hull with integer coordinates. 00448 * 00449 * @see qgar::IConvexHull 00450 */ 00451 typedef GenConvexHull<int> ConvexHull; 00452 00453 /** 00454 * @brief Hull with integer coordinates. 00455 * 00456 * @see qgar::ConvexHull 00457 */ 00458 typedef GenConvexHull<int> IConvexHull; 00459 00460 /** 00461 * @brief Hull with <b>float</b> coordinates. 00462 */ 00463 typedef GenConvexHull<float> FConvexHull; 00464 00465 /** 00466 * @brief Hull with <b>double</b> coordinates. 00467 */ 00468 typedef GenConvexHull<double> DConvexHull; 00469 00470 //@} 00471 00472 00473 } // namespace qgar 00474 00475 00476 // TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT 00477 // TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT 00478 00479 00480 #endif /* __GENCONVEXHULL_H_INCLUDED__ */ 00481