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
00041
00042 #include <cmath>
00043 #include <limits>
00044 #include <list>
00045
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
00060
00061
00062
00063
00064
00065
00066 Maer::Maer(const std::list<DPoint>& aPtList)
00067 {
00068 PRIVATEcomputeMaer(aPtList);
00069 }
00070
00071
00072
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
00088
00089 Maer::Maer(const FreemanChain& aCh)
00090 {
00091 PRIVATEcomputeMaer(aCh.toDPointList());
00092 }
00093
00094
00095
00096 Maer::Maer(const Maer& aMaer)
00097
00098 : _vertices(aMaer._vertices),
00099 _area(aMaer._area)
00100
00101 {
00102
00103 }
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 Maer::~Maer()
00116 {
00117
00118 }
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 const std::list<DPoint>&
00130 Maer::accessVertices() const
00131 {
00132 return _vertices;
00133 }
00134
00135
00136
00137 std::list<DPoint>
00138 Maer::vertices() const
00139 {
00140 return _vertices;
00141 }
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 Maer&
00154 Maer::operator=(const Maer& aMaer)
00155 {
00156
00157 if (this != &aMaer)
00158 {
00159 _vertices = aMaer._vertices;
00160 _area = aMaer._area;
00161 }
00162
00163 return *this;
00164 }
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174 void
00175 Maer::PRIVATEcomputeMaer(const std::list<DPoint>& aPtList)
00176 {
00177
00178
00179
00180 DConvexHull hull(aPtList);
00181
00182
00183
00184
00185 if (hull.size() == 1)
00186 {
00187
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
00198
00199
00200
00201 const std::list<DPoint>& vList = hull.accessVertices();
00202
00203
00204 std::list<DPoint>::const_iterator itPrev = vList.begin();
00205 std::list<DPoint>::const_iterator itCurr = itPrev;
00206 itCurr++;
00207
00208
00209 _area = std::numeric_limits<double>::max();
00210
00211
00212
00213
00214
00215 do
00216
00217 {
00218
00219
00220 double xPrev = itPrev->x();
00221 double yPrev = itPrev->y();
00222
00223
00224 double theta = atan2(itCurr->y() - yPrev, itCurr->x() - xPrev);
00225 if (theta < 0.)
00226 {
00227 theta += Math::QG_2PI;
00228 }
00229
00230
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
00237 for (std::list<DPoint>::const_iterator itV = vList.begin() ;
00238 itV != vList.end() ;
00239 itV++)
00240 {
00241
00242 double xTmp = itV->x() - xPrev;
00243 double yTmp = itV->y() - yPrev;
00244
00245
00246 double x = ( xTmp * cos(theta) ) + ( yTmp * sin(theta) );
00247 double y = ( -xTmp * sin(theta) ) + ( yTmp * cos(theta) );
00248
00249
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
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
00285 if (currArea < _area)
00286 {
00287
00288 _area = currArea;
00289
00290
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
00299
00300 itPrev = itCurr;
00301 itCurr++;
00302 if (itCurr == vList.end())
00303 {
00304 itCurr = vList.begin();
00305 }
00306
00307 }
00308
00309
00310 while (itPrev != vList.begin());
00311
00312 }
00313
00314
00315
00316 }