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