00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00024
00025 #include <QVPolyline>
00026 #include <QVPolylineF>
00027
00028 #include <qvmath.h>
00029 #include <qvdefines.h>
00030 #include <qvmatrixalgebra.h>
00031
00032 #include <iostream>
00033 #include <float.h>
00034
00035
00036 #ifndef DOXYGEN_IGNORE_THIS
00037 class ClassAuxIPE_F
00038 {
00039 public:
00040 double cost;
00041 int index;
00042 ClassAuxIPE_F *prev,*next;
00043 };
00044
00045 bool costLessThan(ClassAuxIPE_F* &s1,ClassAuxIPE_F* &s2)
00046 {
00047 return s1->cost < s2->cost;
00048 }
00049
00050 bool indexLessThan(ClassAuxIPE_F* &s1,ClassAuxIPE_F* &s2)
00051 {
00052 return s1->index < s2->index;
00053 }
00054
00055 inline double costElimination(const QVPolylineF &polyline,int ia, int ib, int ic)
00056 {
00057 double xA,yA,xB,yB,xC,yC;
00058 xA = polyline[ia].x(); yA=polyline[ia].y();
00059 xB = polyline[ib].x(); yB=polyline[ib].y();
00060 xC = polyline[ic].x(); yC=polyline[ic].y();
00061 if((xA != xC) or (yA != yC))
00062 return ABS(xA*(yC-yB) + xB*(yA-yC) + xC*(yB-yA)) / sqrt((xA-xC)*(xA-xC)+(yA-yC)*(yA-yC));
00063 else
00064 return sqrt((xB-xC)*(xB-xC)+(yB-yC)*(yB-yC));
00065 }
00066
00067 class auxLine_F {
00068 public:
00069 auxLine_F(double l1,double l2,double l3,bool ok) : l1(l1),l2(l2),l3(l3),ok(ok) {};
00070 double l1,l2,l3;
00071 bool ok;
00072 };
00073 #endif
00074
00075 double IterativePointElimination(const QVPolylineF &polyline, QVPolylineF &result,
00076 const double param, bool maxNumberOfPointsMethod,bool intersectLines,
00077 double *max_removed_cost)
00078 {
00079 const uInt tot_siz = polyline.size();
00080 QList<ClassAuxIPE_F*> list;
00081
00082
00083 result.clear();
00084
00085
00086 if(max_removed_cost != NULL) *max_removed_cost = 0.0;
00087
00088
00089
00090 if(polyline.size()<3)
00091 {
00092 result = polyline;
00093 return FLT_MAX;
00094 }
00095
00096
00097 for(uInt i=0;i<tot_siz;i++)
00098 list.push_back(new ClassAuxIPE_F);
00099
00100 for(uInt i=0;i<tot_siz;i++)
00101 {
00102 int ia = (i==0)?tot_siz-1:i-1, ib = i, ic = (i==tot_siz-1)?0:i+1;
00103 list[i]->cost = costElimination(polyline,ia,ib,ic);
00104 list[i]->index = ib;
00105 list[i]->prev = list[ia];
00106 list[i]->next = list[ic];
00107 }
00108 if(not polyline.closed)
00109 {
00110 list[0]->cost = FLT_MAX;
00111 list[tot_siz-1]->cost = FLT_MAX;
00112 }
00113 qSort(list.begin(),list.end(),costLessThan);
00114
00115
00116 while(TRUE)
00117 {
00118
00119 if( (list.size() == 3) or
00120 ((not maxNumberOfPointsMethod) and (list[0]->cost > param)) or
00121 ((maxNumberOfPointsMethod) and
00122 (list.size() <= static_cast<int>(param))) )
00123 break;
00124
00125
00126 ClassAuxIPE_F *elem = list.takeAt(0),
00127 *elemPrev = list.takeAt(list.indexOf(elem->prev)),
00128 *elemNext = list.takeAt(list.indexOf(elem->next));
00129 elemPrev->next = elem->next;
00130 elemNext->prev = elem->prev;
00131 if(elemPrev->cost != FLT_MAX)
00132 elemPrev->cost = costElimination(polyline,elemPrev->prev->index,
00133 elemPrev->index,
00134 elemPrev->next->index);
00135 if(elemNext->cost != FLT_MAX)
00136 elemNext->cost = costElimination(polyline,elemNext->prev->index,
00137 elemNext->index,
00138 elemNext->next->index);
00139
00140
00141 int here;
00142 for(int i=0;i<2;i++)
00143 {
00144 ClassAuxIPE_F* newelem = ((i==0)?elemNext:elemPrev);
00145 int first=0,last=list.size()-1;
00146 while (first <= last) {
00147 int mid = (first + last) / 2;
00148 if (newelem->cost > list[mid]->cost)
00149 first = mid + 1;
00150 else if (newelem->cost < list[mid]->cost)
00151 last = mid - 1;
00152 else
00153 {
00154 here = mid;
00155 break;
00156 }
00157 }
00158 if(first>last)
00159 here=first;
00160 list.insert(here,newelem);
00161
00162 }
00163
00164 if(max_removed_cost != NULL)
00165 if(elem->cost > *max_removed_cost)
00166 *max_removed_cost = elem->cost;
00167 delete elem;
00168 }
00169
00170
00171 double return_value = list.first()->cost;
00172
00173
00174 qSort(list.begin(),list.end(),indexLessThan);
00175
00176
00177 QList<ClassAuxIPE_F*>::iterator it = list.begin();
00178 if(intersectLines)
00179 {
00180
00181 double ratio_eig=1.0;
00182 QList<auxLine_F> lines;
00183 for(int i=0;i<list.size();i++)
00184 {
00185
00186 if((not polyline.closed) and (i==list.size()-1))
00187 break;
00188 int i1 = list[i]->index;
00189 int i2 = list[(i+1)%list.size()]->index;
00190 if(i2<i1) i2 += tot_siz;
00191 int dist = i2-i1+1;
00192 #define MIN_PIXELS_IPE_LINE 15
00193 if(dist >= MIN_PIXELS_IPE_LINE)
00194 {
00195 i1 = (i1+dist/5)%tot_siz;
00196 i2 = (i2-dist/5)%tot_siz;
00197 dist = dist-2*(dist/5);
00198 }
00199 else
00200 {
00201 dist = i2-i1+1;
00202 i1 = i1%tot_siz;
00203 i2 = i2%tot_siz;
00204 }
00205
00206 double x=0,y=0,xx=0,xy=0,yy=0;
00207 uInt j=i1;
00208 do
00209 {
00210 x += polyline[j].x();
00211 y += polyline[j].y();
00212 xx += polyline[j].x()*polyline[j].x();
00213 xy += polyline[j].x()*polyline[j].y();
00214 yy += polyline[j].y()*polyline[j].y();
00215 j = (j+1)%tot_siz;
00216 } while(j!=(i2+1)%tot_siz);
00217 double l1,l2,l3;
00218 x /= dist; y /= dist; xx /= dist; xy /= dist; yy /= dist;
00219
00220 ratio_eig = homogLineFromMoments(x,y,xx,xy,yy,l1,l2,l3);
00221 lines.push_back(auxLine_F(l1,l2,l3,ratio_eig < 0.1));
00222 }
00223
00224 for(int i=0;i<list.size();i++)
00225 {
00226 QPointF oldPoint = polyline[list[i]->index];
00227 if( (not polyline.closed) and ((i==0) or (i==list.size()-1)))
00228 {
00229
00230 result.append(oldPoint);
00231 continue;
00232 }
00233 int ant = (i-1+list.size())%list.size();
00234 int post = (i+1)%list.size();
00235 double newx = (lines[i].l2)*(lines[ant].l3) - (lines[i].l3)*(lines[ant].l2);
00236 double newy = -(lines[i].l1)*(lines[ant].l3) + (lines[i].l3)*(lines[ant].l1);
00237 double newz = (lines[i].l1)*(lines[ant].l2) - (lines[i].l2)*(lines[ant].l1);
00238 if ( (not lines[i].ok) or (not lines[ant].ok) or
00239 (fabs(newz) < EPSILON) )
00240 result.append(oldPoint);
00241 else
00242 {
00243 int nx = qRound(newx/newz);
00244 int ny = qRound(newy/newz);
00245
00246
00247
00248
00249 double dist =
00250 sqrt((nx-oldPoint.x())*(nx-oldPoint.x()) +
00251 (ny-oldPoint.y())*(ny-oldPoint.y()));
00252 QPointF prevPoint = polyline[list[ant]->index],
00253 nextPoint = polyline[list[post]->index];
00254 double minDist =
00255 qMin(
00256 sqrt((prevPoint.x()-oldPoint.x())*(prevPoint.x()-oldPoint.x()) +
00257 (prevPoint.y()-oldPoint.y())*(prevPoint.y()-oldPoint.y())),
00258 sqrt((nextPoint.x()-oldPoint.x())*(nextPoint.x()-oldPoint.x()) +
00259 (nextPoint.y()-oldPoint.y())*(nextPoint.y()-oldPoint.y()))
00260 );
00261 if(dist < 0.2*minDist)
00262 result.append(QPoint(nx,ny));
00263 else
00264 result.append(oldPoint);
00265 }
00266 }
00267 }
00268 else
00269 {
00270
00271 it = list.begin();
00272 while(it != list.end())
00273 {
00274 result.append(polyline.at((*it)->index));
00275 it++;
00276 }
00277 }
00278
00279
00280 while (!list.isEmpty())
00281 delete list.takeFirst();
00282
00283
00284 result.closed = polyline.closed;
00285 result.direction = polyline.direction;
00286
00287
00288 return return_value;
00289 }
00290
00291
00292 QVPolylineF::QVPolylineF(): QList<QPointF>(),
00293 closed(false), direction(false)
00294 {
00295 qDebug() << "QVPolylineF()";
00296 qDebug() << "QVPolylineF() <~ return";
00297 };
00298
00299 QVPolylineF::QVPolylineF(const QVPolyline &polyline): QList<QPointF>(),
00300 closed(polyline.closed), direction(polyline.direction)
00301 {
00302 foreach(QPoint point, polyline)
00303 {
00304 append(QPointF(point));
00305 }
00306 qDebug() << "QVPolylineF(const QVPolylineF &)";
00307 qDebug() << "QVPolylineF(const QVPolylineF &) <~ return";
00308 };
00309
00310 QVPolylineF::QVPolylineF(const QVPolylineF &polyline): QList<QPointF>(polyline),
00311 closed(polyline.closed), direction(polyline.direction)
00312 {
00313 qDebug() << "QVPolylineF(const QVPolylineF &)";
00314 qDebug() << "QVPolylineF(const QVPolylineF &) <~ return";
00315 };
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00341
00342 QVPolylineF QVPolylineF::ellipse(uInt n, float x, float y, float maxRadio, float minRadio, float ang)
00343 {
00344 QVPolylineF ellipse;
00345 float w = 2*PI/(n-1);
00346 float maxArg = (maxRadio+minRadio)/2;
00347 float minArg = (maxRadio-minRadio)/2;
00348
00349 for (uInt t = 0; t < n; t++)
00350 ellipse.append(QPointF ( (uInt) (x + maxArg*cos(ang+w*t) + minArg*cos(ang-w*t)),
00351 (uInt) (y + maxArg*sin(ang+w*t) + minArg*sin(ang-w*t))
00352 ));
00353 return ellipse;
00354 }
00355
00356 QVPolylineF QVPolylineF::rectangle(float x1, float y1, float x2, float y2)
00357 {
00358 QVPolylineF rectangle;
00359 rectangle.append(QPointF( x1, y1 ));
00360 rectangle.append(QPointF( x1, y2 ));
00361 rectangle.append(QPointF( x2, y2 ));
00362 rectangle.append(QPointF( x2, y1 ));
00363 rectangle.append(QPointF( x1, y1 ));
00364 return rectangle;
00365 }
00366
00367 QVPolylineF::operator QVPolyline() const
00368 {
00369 QVPolyline polyline;
00370 foreach(QPointF pointf, *this)
00371 {
00372 polyline.append( QPoint(pointf.toPoint()) );
00373 }
00374 return polyline;
00375 }
00376