00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00024
00025 #include <qvdta/qvpolyline.h>
00026
00027 #define CONST_PI ((double)3.14159)
00028 #define SIGN(X) (((X)>=0)?1:-1)
00029
00030 namespace qvdta
00031 {
00033
00034
00035
00036 #define xA(Index) (coorX[previous[Index]])
00037 #define yA(Index) (coorY[previous[Index]])
00038 #define xB(Index) (coorX[Index])
00039 #define yB(Index) (coorY[Index])
00040 #define xC(Index) (coorX[next[Index]])
00041 #define yC(Index) (coorY[next[Index]])
00042 #define ABS(X) (((X)>=0)?(X):-(X))
00043 #define TRIANGLE_AREA(I) ABS(xA(I)*yC(I) - xA(I)*yB(I) + xB(I)*yA(I) - xB(I)*yC(I) + xC(I)*yB(I) - xC(I)*yA(I))
00044
00045 void IterativePointElimination(const QVPolyline &polyline, QVPolyline &result, const double minAreaDiv2)
00046 {
00047
00048
00049 const uInt polylineSize = polyline.size(), minArea = minAreaDiv2 * 2;
00050
00051 if (polylineSize < 3) return;
00052
00053
00054
00055 uInt *previous = new uInt[polylineSize],
00056 *next = new uInt[polylineSize],
00057 *valid = new uInt[polylineSize],
00058 *area = new uInt[polylineSize],
00059 discartablePoints = 0,
00060 validPoints = polylineSize;
00061
00062 int *coorX = new int[polylineSize],
00063 *coorY = new int[polylineSize];
00064
00065 for (uInt i=0; i< polylineSize; i++)
00066 {
00067 previous[i] = i-1;
00068 next[i] = i+1;
00069 coorX[i] = polyline.at(i).x();
00070 coorY[i] = polyline.at(i).y();
00071 }
00072
00073 previous[0] = polylineSize-1;
00074 next[polylineSize-1] = 0;
00075
00076
00077 for (uInt i=0; i < polylineSize; i++)
00078 {
00079 valid[i] = true;
00080 area[i] = TRIANGLE_AREA(i);
00081 }
00082
00083
00084
00085
00086
00087 uInt index = 0, lastIndex = previous[index];
00088 bool cond = true;
00089
00090 while(cond && validPoints > 3)
00091 {
00092 Q_ASSERT(valid[index]);
00093 Q_ASSERT(valid[next[index]]);
00094 Q_ASSERT(valid[previous[index]]);
00095 if (area[index] < minArea)
00096 {
00097
00098 valid[index] = false;
00099 next[previous[index]] = next[index];
00100 previous[next[index]] = previous[index];
00101 lastIndex = previous[index];
00102 validPoints--;
00103
00104
00105 index = next[index];
00106 area[index] = TRIANGLE_AREA(index);
00107 area[previous[index]] = TRIANGLE_AREA(previous[index]);
00108 }
00109 else {
00110
00111
00112 if (index == lastIndex)
00113 cond = false;
00114
00115
00116 index = next[index];
00117 }
00118 }
00119
00120
00121
00122 if (validPoints == 3)
00123 {
00124 Q_ASSERT(valid[index]);
00125 Q_ASSERT(area[index] == area[next[index]]);
00126 Q_ASSERT(area[index] == area[previous[index]]);
00127 Q_ASSERT(index == previous[previous[index]]);
00128
00129 if (area[index] < minArea)
00130 return;
00131 }
00132
00133
00134 for (uInt n=0; n< polylineSize; n++)
00135 if (valid[n])
00136 result.append(polyline.at(n));
00137 result.closed = polyline.closed;
00138 result.direction = polyline.direction;
00139
00140 delete previous;
00141 delete next;
00142 delete valid;
00143 delete area;
00144 delete coorX;
00145 delete coorY;
00146 }
00147
00148
00149 QVPolyline::QVPolyline(): QList<QPoint>(),
00150 closed(false), direction(false)
00151 {
00152 qDebug() << "QVPolyline()";
00153 qDebug() << "QVPolyline() <~ return";
00154 };
00155
00156 QVPolyline::QVPolyline(const QVPolyline &polyline): QList<QPoint>(polyline),
00157 closed(polyline.closed), direction(polyline.direction)
00158 {
00159 qDebug() << "QVPolyline(const QVPolyline &)";
00160 qDebug() << "QVPolyline(const QVPolyline &) <~ return";
00161 };
00162
00163 QPoint linesIntersection(QPoint a, QPoint b, QPoint c, QPoint d)
00164
00165 {
00166 double x1 = a.rx(), x2 = b.rx(), x3 = c.rx(), x4 = d.rx();
00167 double y1 = a.ry(), y2 = b.ry(), y3 = c.ry(), y4 = d.ry();
00168
00169 double denominador = (y4 - y3)*(x2 - x1) - (x4 - x3)*(y2 - y1);
00170 if (denominador == 0)
00171 return QPoint( (int)(b.rx() + c.rx())/2, (int)(b.ry() + c.ry())/2 );
00172
00173 double ua = (x4 - x3)*(y1 - y3) - (y4 - y3)*(x1 - x3),
00174 ub = (x2 - x1)*(y1 - y3) - (y2 - y1)*(x1 - x3);
00175
00176 QPoint p = QPoint(
00177 (int) (x1 + ua*(x2 - x1) / denominador),
00178 (int) (y1 + ub*(y2 - y1) / denominador)
00179 );
00180 return p;
00181 }
00182
00184
00185 void drawPoints(const QList<QPoint> &hotPoints, QVImage<uChar,3> &dest)
00186 {
00187 QListIterator<QPoint> iterator(hotPoints);
00188 uChar pixel[3] = { 255,0,0 };
00189
00190 while(iterator.hasNext())
00191 {
00192 QPoint p = iterator.next();
00193 QVPolyline rectangle = QVPolyline::rectangle(p.x()-2, p.y()-2, p.x()+2, p.y()+2);
00194 draw(dest, rectangle, pixel,true,true);
00195 }
00196 }
00197
00198 void drawPoints(const QList<QPoint> &hotPoints, QVImage<uChar> &dest)
00199 {
00200 QListIterator<QPoint> iterator(hotPoints);
00201 while(iterator.hasNext())
00202 {
00203 QPoint p = iterator.next();
00204 QVPolyline rectangle = QVPolyline::rectangle(p.x()-2, p.y()-2, p.x()+2, p.y()+2);
00205 draw(dest, rectangle, 255,true,true);
00206 }
00207 }
00208
00209
00210 void draw(QVImage<uChar> &image, const QVPolyline &polyline, const uChar constant, bool linked, bool safe)
00211 {
00212 Q_ASSERT_X(polyline.size() > 0, "drawPolyline()", "polyline size equals zero");
00213
00214 QListIterator<QPoint> iterator(polyline);
00215 QRect roi = image.getROI();
00216
00217 QPoint previous;
00218
00219 if (linked)
00220 previous = iterator.next();
00221
00222 QVIMAGE_INIT_WRITE(uChar,image);
00223 while (iterator.hasNext())
00224 {
00225 QPoint actual = iterator.next();
00226 int x = actual.x(), y = actual.y();
00227 if (!linked && !safe)
00228 QVIMAGE_PIXEL(image, x, y,0) = constant;
00229 else if (linked)
00230 {
00231 QVPolyline line = QVPolyline::line(x, y, previous.rx(), previous.ry());
00232 draw(image, line, constant, false, safe);
00233 previous = actual;
00234 }
00235 else if (roi.contains(x, y))
00236 QVIMAGE_PIXEL(image, x, y,0) = constant;
00237 }
00238 }
00239
00240 void draw(QVImage<uChar,3> &image, const QVPolyline &polyline, const uChar constant[3], bool linked, bool safe)
00241 {
00242 Q_ASSERT_X(polyline.size() > 0, "drawPolyline()", "polyline size equals zero");
00243
00244
00245 QListIterator<QPoint> iterator(polyline);
00246 QRect roi = image.getROI();
00247
00248 QPoint previous;
00249
00250 if (linked)
00251 previous = iterator.next();
00252
00253 QVIMAGE_INIT_WRITE(uChar,image);
00254 while (iterator.hasNext())
00255 {
00256 QPoint actual = iterator.next();
00257 int x = actual.x(), y = actual.y();
00258 if (!linked && !safe)
00259 {
00260 QVIMAGE_PIXEL(image, x, y,0) = constant[0];
00261 QVIMAGE_PIXEL(image, x, y,1) = constant[1];
00262 QVIMAGE_PIXEL(image, x, y,2) = constant[2];
00263
00264
00265
00266 }
00267 else if (linked)
00268 {
00269 QVPolyline line = QVPolyline::line(actual.rx(), actual.ry(), previous.rx(), previous.ry());
00270 draw(image, line, constant, false, safe);
00271 previous = actual;
00272 }
00273 else if (roi.contains(actual.rx(), actual.ry()))
00274 {
00275 QVIMAGE_PIXEL(image, x, y,0) = constant[0];
00276 QVIMAGE_PIXEL(image, x, y,1) = constant[1];
00277 QVIMAGE_PIXEL(image, x, y,2) = constant[2];
00278
00279
00280
00281 }
00282 }
00283 }
00284
00285
00286 void draw(QVImage<uChar> &img, const QList< QVPolyline > &polylineList, const uChar constant, bool linked, bool safe)
00287 {
00288 QListIterator<QVPolyline> iterator(polylineList);
00289 while (iterator.hasNext())
00290 draw(img, iterator.next(), constant, linked, safe);
00291 }
00292
00293 void draw(QVImage<uChar,3> &img,const QList< QVPolyline > &polylineList, const uChar constant[3],bool linked,bool safe)
00294 {
00295 QListIterator<QVPolyline> iterator(polylineList);
00296 while (iterator.hasNext())
00297 draw(img, iterator.next(), constant, linked, safe);
00298 }
00299
00300
00301 QVPolyline QVPolyline::ellipse(uInt n, float x, float y, float maxRadio, float minRadio, float ang)
00302 {
00303 QVPolyline ellipse;
00304 float w = 2*CONST_PI/(n-1);
00305 float maxArg = (maxRadio+minRadio)/2;
00306 float minArg = (maxRadio-minRadio)/2;
00307
00308 for (uInt t = 0; t < n; t++)
00309 ellipse.append(QPoint ( (uInt) (x + maxArg*cos(ang+w*t) + minArg*cos(ang-w*t)),
00310 (uInt) (y + maxArg*sin(ang+w*t) + minArg*sin(ang-w*t))
00311 ));
00312 return ellipse;
00313 }
00314
00315 QVPolyline QVPolyline::rectangle(int x1, int y1, int x2, int y2)
00316 {
00317 QVPolyline rectangle;
00318 rectangle.append(QPoint( x1, y1 ));
00319 rectangle.append(QPoint( x1, y2 ));
00320 rectangle.append(QPoint( x2, y2 ));
00321 rectangle.append(QPoint( x2, y1 ));
00322 rectangle.append(QPoint( x1, y1 ));
00323 return rectangle;
00324 }
00325
00326 QVPolyline QVPolyline::line(int x1, int y1, int x2, int y2)
00327 {
00328 QVPolyline line;
00329
00330 line.append(QPoint( x1, y1 ));
00331
00332 if (x1 == x2 && y1 == y2)
00333 return line;
00334
00335 int i,dx,dy,sdx,sdy,dxabs,dyabs,x,y,px,py;
00336
00337 dx=x2-x1;
00338 dy=y2-y1;
00339 dxabs=abs(dx);
00340 dyabs=abs(dy);
00341 sdx=SIGN(dx);
00342 sdy=SIGN(dy);
00343 x=dyabs>>1;
00344 y=dxabs>>1;
00345 px=x1;
00346 py=y1;
00347
00348 if (dxabs>=dyabs)
00349 for(i=0;i<dxabs;i++)
00350 {
00351 y+=dyabs;
00352 if (y>=dxabs)
00353 {
00354 y-=dxabs;
00355 py+=sdy;
00356 }
00357 px+=sdx;
00358 line.append(QPoint( px, py ));
00359 }
00360 else
00361 for(i=0;i<dyabs;i++)
00362 {
00363 x+=dxabs;
00364 if (x>=dyabs)
00365 {
00366 x-=dyabs;
00367 px+=sdx;
00368 }
00369 py+=sdy;
00370 line.append(QPoint( px, py ));
00371 }
00372
00373 return line;
00374 }
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00522 #define dist2(A,B) (((A).rx() -(B).rx())*((A).rx() -(B).rx()) + ((A).ry() -(B).ry())*((A).ry() -(B).ry()))
00523 #define dot(A,B) ( (A).rx()*(B).rx() + (A).ry()*(B).ry() )
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638 }