00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include <iostream>
00041 #include <list>
00042 #include <set>
00043 #include <utility>
00044
00045 #include <qgarlib/ISerializable.H>
00046 #include <qgarlib/math.H>
00047 #include <qgarlib/primitives.H>
00048
00049
00050
00051
00052 namespace qgar
00053 {
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 template <class T>
00064 GenConvexHull<T>::GenConvexHull()
00065 {
00066
00067 }
00068
00069
00070
00071
00072 template <class T>
00073 GenConvexHull<T>::GenConvexHull(const std::list< GenPoint<T> >& aPtList)
00074 {
00075 PRIVATEgraham_sScan(aPtList);
00076 }
00077
00078
00079
00080
00081 template <class T>
00082 GenConvexHull<T>::GenConvexHull(const GenConvexHull<T>& aCHull)
00083 : _vertices(aCHull._vertices),
00084 _hull(aCHull._hull),
00085 _pivot(aCHull._pivot)
00086 {
00087
00088 }
00089
00090
00091
00092
00093
00094
00095
00096 template <class T>
00097 GenConvexHull<T>::~GenConvexHull()
00098 {
00099
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 template <class T>
00111 bool GenConvexHull<T>::empty() const
00112 {
00113 return _vertices.empty();
00114 }
00115
00116
00117
00118 template <class T>
00119 int
00120 GenConvexHull<T>::size() const
00121 {
00122 return (int) _vertices.size();
00123 }
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 template <class T>
00134 const std::list< GenPoint<T> >&
00135 GenConvexHull<T>::accessVertices() const
00136 {
00137 return _vertices;
00138 }
00139
00140
00141
00142
00143 template <class T>
00144 std::list< GenPoint<T> >
00145 GenConvexHull<T>::vertices() const
00146 {
00147 return _vertices;
00148 }
00149
00150
00151
00152 template <class T>
00153 const GenPoint<T>&
00154 GenConvexHull<T>::accessPivot() const
00155 {
00156 return _pivot;
00157 }
00158
00159
00160
00161 template <class T>
00162 GenPoint<T>
00163 GenConvexHull<T>::pivot() const
00164 {
00165 return _pivot;
00166 }
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176 template <class T>
00177 GenConvexHull<T>&
00178 GenConvexHull<T>::operator=(const GenConvexHull<T>& aCHull)
00179 {
00180
00181 if (this != &aCHull)
00182 {
00183 _vertices = aCHull._vertices;
00184 _hull = aCHull._hull;
00185 _pivot = aCHull._pivot;
00186 }
00187
00188 return *this;
00189 }
00190
00191
00192
00193
00194
00195
00196
00197 template <class T>
00198 std::istream&
00199 GenConvexHull<T>::read(std::istream& anInStream)
00200 {
00201 qgReadObjName(anInStream, "ConvexHull");
00202
00203
00204
00205 std::list< GenPoint<T> > ptList;
00206
00207 int pointCnt;
00208 qgReadObjData(anInStream, pointCnt);
00209
00210 for(int iCnt = 0 ; iCnt < pointCnt ; ++iCnt)
00211 {
00212 GenPoint<T> point;
00213 qgReadObjData(anInStream, point);
00214
00215 ptList.push_back(point);
00216 }
00217
00218
00219 PRIVATEgraham_sScan(ptList);
00220
00221 return anInStream;
00222 }
00223
00224
00225 template <class T>
00226 std::ostream&
00227 GenConvexHull<T>::write(std::ostream& anOutStream) const
00228 {
00229 anOutStream << "ConvexHull("
00230 << _vertices.size()
00231 << ')';
00232
00233
00234
00235 for(typename std::list< GenPoint<T> >::const_iterator
00236 itLP = _vertices.begin();
00237 itLP != _vertices.end();
00238 ++itLP)
00239 {
00240 anOutStream << '('
00241 << *itLP
00242 << ')';
00243 }
00244
00245 return anOutStream;
00246 }
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 template <class T>
00257 void
00258 GenConvexHull<T>::PRIVATEgraham_sScan(const std::list< GenPoint<T> >& aPtList)
00259 {
00260 if (aPtList.empty())
00261 {
00262
00263 return;
00264 }
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 typename std::list< qgar::GenPoint<T> >::const_iterator
00278 itPL = aPtList.begin();
00279
00280
00281 typename std::list< qgar::GenPoint<T> >::const_iterator
00282 itPivot = itPL;
00283
00284
00285
00286 for (++itPL ; itPL != aPtList.end() ; ++itPL)
00287 {
00288 T yCurr = itPL->y();
00289 T yPiv = itPivot->y();
00290
00291 if (yCurr < yPiv)
00292 {
00293 itPivot = itPL;
00294 }
00295 else if (yCurr == yPiv)
00296 {
00297 if ((itPL->x()) < (itPivot->x()))
00298 {
00299 itPivot = itPL;
00300 }
00301 }
00302 }
00303
00304
00305 _pivot = *itPivot;
00306
00307
00308
00309
00310
00311
00312
00313
00314 for (itPL = aPtList.begin() ; itPL != aPtList.end() ; ++itPL)
00315 {
00316
00317 if (itPL != itPivot)
00318 {
00319 typename std::pair< double, GenPoint<T> > p(qgAngle(_pivot, *itPL), *itPL);
00320 _hull.insert(p);
00321 }
00322 }
00323
00324
00325
00326 if(_hull.size() < 3)
00327 {
00328
00329 _vertices.push_back(_pivot);
00330
00331 for(typename std::multiset<QGDpair, _sortPred>::iterator itH = _hull.begin();
00332 itH != _hull.end();
00333 ++itH)
00334 {
00335 _vertices.push_back(itH->second);
00336 }
00337 return;
00338 }
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349 typename std::multiset<QGDpair, _sortPred>::iterator itPrev = _hull.begin();
00350
00351
00352 typename std::multiset<QGDpair, _sortPred>::iterator itCurr = itPrev;
00353 ++itCurr;
00354
00355
00356 typename std::multiset<QGDpair, _sortPred>::iterator itNext = itCurr;
00357 ++itNext;
00358
00359 for ( ; itNext != _hull.end() ; ++itNext)
00360 {
00361
00362
00363 if ( qgAngle(itPrev->second, itCurr->second, itNext->second)
00364 >
00365 Math::QG_PI )
00366 {
00367
00368
00369 _hull.erase(itCurr);
00370
00371
00372 if (itPrev != _hull.begin())
00373 {
00374 --itPrev;
00375 }
00376 }
00377 else
00378 {
00379
00380
00381 ++itPrev;
00382 }
00383
00384
00385 itCurr = itPrev;
00386 ++itCurr;
00387 itNext = itCurr;
00388
00389 }
00390
00391
00392
00393 for (itCurr = _hull.begin() ; itCurr != _hull.end() ; ++itCurr)
00394 {
00395 _vertices.push_back(itCurr->second);
00396 }
00397
00398
00399 _vertices.push_front(_pivot);
00400
00401 }
00402
00403
00404
00405
00406
00407 }