Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

RWArcVector.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------+
00002  | Library QgarLib, graphics analysis and recognition                  |
00003  | Copyright (C) 2002  Qgar Project, LORIA                             |
00004  |                                                                     |
00005  | This library is free software; you can redistribute it and/or       |
00006  | modify it under the terms of the GNU Lesser General Public          |
00007  | License version 2.1, as published by the Free Software Foundation.  |
00008  |                                                                     |
00009  | This library is distributed in the hope that it will be useful,     |
00010  | but WITHOUT ANY WARRANTY; without even the implied warranty of      |
00011  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                |
00012  | See the GNU Lesser General Public License for more details.         |
00013  |                                                                     |
00014  | The GNU Lesser General Public License is included in the file       |
00015  | LICENSE.LGPL, in the root directory of the Qgar packaging. See      |
00016  | http://www.gnu.org/licenses/lgpl.html for the terms of the licence. |
00017  | To receive a paper copy, write to the Free Software Foundation,     |
00018  | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.       |
00019  |                                                                     |
00020  | Contact Project Qgar for any information:                           |
00021  |   LORIA - équipe Qgar                                               |
00022  |   B.P. 239, 54506 Vandoeuvre-lès-Nancy Cedex, France                |
00023  |   email: qgar-contact@loria.fr                                      |
00024  |   http://www.qgar.org/                                              |
00025  *---------------------------------------------------------------------*/
00026 
00027 
00028 /**
00029  * @file  RWArcVector.C
00030  * @brief Implementation of class qgar::RWArcVector.
00031  *
00032  *        See file RWArcVector.H for the interface.
00033  *
00034  * @author  <a href="mailto:qgar-develop@loria.fr?subject=Qgar fwd Christian Ah-Soon">Christian Ah-Soon</a>
00035  * @date    July 3, 2001  16:29
00036  * @since   Qgar 1.0
00037  */
00038 
00039 
00040 
00041 // STL
00042 #include <algorithm>
00043 // QGAR
00044 #include <qgarlib/math.H>
00045 #include <qgarlib/primitives.H>
00046 #include <qgarlib/RWArcVector.H>
00047 #include <qgarlib/RWSegmentVector.H>
00048 
00049 
00050 
00051 using namespace std;
00052 
00053 
00054 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00055 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00056 // L O C A L    F U N C T I O N S
00057 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00058 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00059 
00060 namespace
00061 {
00062 
00063 using namespace qgar;
00064 
00065 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00066 
00067 double
00068 RWARCVECTOR_squareError(Point& aCenter,
00069                         vector<Point>& thePoints,
00070                         int firstIdx,
00071                         int lastIdx)
00072 {
00073   double deviation;
00074   double sum = 0.0;
00075   double radius = qgDist(aCenter, thePoints[firstIdx]);
00076 
00077   for (int i = firstIdx + 1 ; i < lastIdx ; ++i)
00078     {
00079       deviation = qgDist(aCenter, thePoints[i]) - radius;
00080       sum += deviation * deviation;
00081     }
00082 
00083   return sum;
00084 }
00085 
00086 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00087 
00088 double
00089 RWARCVECTOR_maxDeviation(Point& aCenter,
00090                          vector<Point>& thePoints,
00091                          int firstIdx,
00092                          int lastIdx,
00093                          int dir)
00094 {
00095   double deviation;
00096   double deviationMax = 0;
00097   double radius = qgDist(aCenter, thePoints[firstIdx]);
00098 
00099   for (int l2 = firstIdx; l2 < lastIdx; ++l2)
00100     {
00101       double dx = (thePoints[l2+1].x() - thePoints[l2].x()) / 10.;
00102       double dy = (thePoints[l2+1].y() - thePoints[l2].y()) / 10.;
00103       int l3 = 1;
00104       while (l3 < 10)
00105         {
00106           Point pt((int) (thePoints[l2].x() + dx * (l3 - 1)),
00107                    (int) (thePoints[l2].y() + dy * (l3 - 1)));
00108           deviation = radius - qgDist(aCenter, pt);
00109 
00110           if (deviation < 0)
00111             {
00112               deviation = -deviation; 
00113             }
00114           if (deviation > deviationMax)
00115             {
00116               deviationMax = deviation;
00117             }
00118 
00119           ++l3;
00120         }
00121     } // END for l2
00122 
00123   return deviationMax; 
00124 }
00125 
00126 
00127 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00128 
00129 QgarArc*
00130 RWARCVECTOR_bestAttributes(vector<Point>& thePoints,
00131                            int firstIdx,
00132                            int lastIdx,
00133                            double& dev,
00134                            int potRadius)
00135 {
00136   Point intersection((thePoints[firstIdx].x() + thePoints[lastIdx].x()) / 2,
00137                      (thePoints[firstIdx].y() + thePoints[lastIdx].y()) / 2);
00138 
00139   int xIntersection =  intersection.x();
00140   int yIntersection =  intersection.y();
00141   
00142   // On which side of the segment does the center lie?
00143   int xNormalVector = thePoints[firstIdx].y() - thePoints[lastIdx].y();
00144   int yNormalVector = thePoints[lastIdx].x() - thePoints[firstIdx].x();
00145   int sum = 0;
00146   int maxAbs = 0;
00147   int xVectorI;
00148   int yVectorI;
00149   int projection; 
00150 
00151   for (int i = firstIdx + 1; i < lastIdx; ++i)
00152     {
00153       xVectorI = thePoints[i].x() - xIntersection;
00154       yVectorI = thePoints[i].y() - yIntersection;
00155       projection = xNormalVector * xVectorI + yNormalVector * yVectorI;
00156       sum += projection;
00157       projection = abs(projection);
00158       maxAbs = max(maxAbs, projection);      
00159     }
00160 
00161   maxAbs = (int)
00162     (maxAbs / hypot((double) xNormalVector, (double) yNormalVector));
00163 
00164   int sameSide = (sum > 0);
00165 
00166   double angle;
00167   if (yNormalVector == 0)
00168     {
00169       angle = (xNormalVector > 0) ? Math::QG_PI_2 : - Math::QG_PI_2; // ????
00170     }
00171   else
00172     {
00173       angle = atan( (double)xNormalVector / (double)yNormalVector );
00174     }
00175 
00176   double alphaX = sin(angle);
00177   double alphaY = cos(angle);
00178 
00179   // Small angle ou large angle?  
00180   int alphaXSign = (xNormalVector > 0) ? -1 : 1;
00181   int alphaYSign = (yNormalVector > 0) ? -1 : 1;
00182 
00183   if (alphaX < 0)
00184     {
00185       alphaX = - alphaX ;
00186     }
00187   alphaX =  alphaXSign * alphaX;
00188   if (alphaY < 0)
00189     {
00190       alphaY = - alphaY ;
00191     }
00192   alphaY =  alphaYSign * alphaY;
00193 
00194   Point center(xIntersection + int (alphaX * maxAbs / 2),
00195                yIntersection + int (alphaY * maxAbs / 2));
00196   
00197   /**
00198   double toto1 = 1 / alphaX;
00199   double toto2 = 1 / alphaY;
00200   double toto = max (toto1, toto2) + 1;
00201   Point center (xIntersection + int (alphaX * toto),
00202                 yIntersection + int (alphaY * toto));
00203   **/
00204 
00205   double deviationOtherSide =
00206     RWARCVECTOR_squareError(center, thePoints, firstIdx, lastIdx);
00207   center.setXY(xIntersection - int(alphaX * maxAbs / 2),
00208                yIntersection - int(alphaY * maxAbs / 2));
00209   
00210   /**
00211   center.setXY(xIntersection - int (alphaX * toto),
00212                yIntersection - int (alphaY * toto));
00213   **/
00214   double deviationSameSide =
00215     RWARCVECTOR_squareError(center, thePoints, firstIdx, lastIdx);
00216 
00217   int smallArc;
00218   if (deviationSameSide < deviationOtherSide)
00219     {
00220       smallArc = sameSide;
00221     }
00222   else
00223     {
00224       smallArc = !sameSide;
00225     }
00226 
00227   // Compute radius by dichotomy (step 5)
00228   int power2;
00229  
00230   if (potRadius != -1)
00231     {
00232       power2 = int(log((double)potRadius) / log(2.0)) + 1;
00233     }
00234   else
00235     {
00236       if (smallArc)
00237         {
00238           // power2 = int(log(maxAbs) / log(2));
00239           power2 = int(log((double)maxAbs) / log(2.0)) + 1;
00240           if (power2 > 14)
00241             power2 = 14;
00242         }
00243       else
00244         {
00245           power2 =  14; 
00246         }
00247     }
00248 
00249   if (smallArc)
00250     {
00251       /**
00252       power2 = int(log(maxAbs) / log(2));
00253       power2 = int(log(maxAbs) / log(2)) + 1;
00254       if (power2 > 14)
00255         power2 = 14;
00256       **/
00257       if (sameSide)
00258         {
00259           alphaX = -alphaX;
00260           alphaY = -alphaY;
00261         }
00262     }
00263   else
00264     { 
00265       /**
00266       power2 = 14;
00267       **/
00268       if (!sameSide)
00269         {
00270           alphaX = -alphaX;
00271           alphaY = -alphaY;
00272         }
00273     }
00274   /**
00275   else                    // if large arc
00276     power2 = power2Large; // static
00277   **/
00278 
00279   long int devInf = 1;
00280   long int devSup = 1 << power2;
00281   long int devMid = devSup >> 1;  // == devSup / 2 
00282   long int iteration  = devMid;
00283   long int saveDevInf; 
00284   long int saveDevSup;
00285   long int saveDevMid;
00286   long int saveIteration;
00287   int directionIter; 
00288   
00289   center.setXY(xIntersection + int(alphaX * devSup),
00290                yIntersection + int(alphaY * devSup));
00291   
00292   double lastErrorSup =
00293     RWARCVECTOR_squareError(center, thePoints, firstIdx, lastIdx);
00294   double errorMid;
00295 
00296   bool proceed = false;
00297 
00298   do { ////////////////////////////////////////////////
00299 
00300     directionIter = 0;
00301     saveIteration = 0;
00302     for (; iteration != 1;)
00303       {
00304         iteration = iteration / 2;
00305         center.setXY(xIntersection + int(alphaX * devMid),
00306                      yIntersection + int(alphaY * devMid));      
00307         errorMid =
00308           RWARCVECTOR_squareError(center, thePoints, firstIdx, lastIdx);
00309       
00310         /**
00311         cout << "center " << center.x() <<" " << center.y()  <<"\n";
00312         cout << "errorMid " << errorMid << "devMid " 
00313              << devMid  << "it " << iteration << "\n";
00314         **/
00315         if (errorMid > lastErrorSup) 
00316           {
00317             if (directionIter == 0)
00318               {
00319                 directionIter = 1;
00320               }
00321             else if (directionIter == - 1) 
00322               {
00323                 saveDevInf = devMid; 
00324                 saveDevMid = devSup ;
00325                 saveDevSup = devSup + iteration * 4;
00326                 saveIteration = iteration * 2 ;
00327                 directionIter = 1;
00328                 /**
00329                 cout << "\n je save inf " << saveDevInf << "mil " 
00330                      << saveDevMid << "sup " << saveDevSup 
00331                      << "it " << saveIteration << "\n";
00332                 **/
00333               }
00334             devInf = devMid;
00335             devMid = devMid + iteration ;
00336           }
00337         else if (errorMid < lastErrorSup ) 
00338           {
00339             if (directionIter == 0)
00340               {
00341                 directionIter = -1;
00342               }
00343             else if (directionIter == 1) 
00344               {
00345                 saveDevSup = devMid ;
00346                 saveDevMid = devInf;
00347                 saveDevInf = devInf - iteration * 4;
00348                 saveIteration = iteration * 2;
00349                 directionIter = -1;
00350               }
00351             devSup = devMid;
00352             devMid = devMid - iteration ;
00353             lastErrorSup = errorMid;
00354           }
00355       } // for (;iteration;): 2^(nb iterations + 1) == devSup
00356         
00357     if ((directionIter == 0) || (devMid == 1) || (saveIteration == 0))
00358       {
00359         /**
00360         if ((directionIter != 0) && (saveIteration == 0))
00361           double min_error; 
00362         **/
00363         break;
00364       }
00365     
00366     center.setXY 
00367       (xIntersection + int(alphaX * (devMid + directionIter)), 
00368        yIntersection + int(alphaY * (devMid + directionIter)));
00369     
00370     double newError =
00371       RWARCVECTOR_squareError(center, thePoints, firstIdx, lastIdx);
00372     if (errorMid > newError)
00373       {
00374         devMid = saveDevMid;
00375         devSup = saveDevSup;
00376         devInf = saveDevInf;
00377         iteration = saveIteration;
00378         center.setXY(xIntersection + int(alphaX * devMid),
00379                      yIntersection + int(alphaY * devMid));
00380         errorMid =
00381           RWARCVECTOR_squareError(center, thePoints, firstIdx, lastIdx); 
00382         center.setXY(xIntersection + int(alphaX * devSup),
00383                      yIntersection + int(alphaY * devSup));
00384         lastErrorSup =
00385           RWARCVECTOR_squareError(center, thePoints, firstIdx, lastIdx); 
00386 
00387         if (directionIter == 1)
00388           {
00389             devInf = devMid;
00390             devMid = devMid + iteration ;
00391           }
00392         else
00393           {     
00394             devSup = devMid;
00395             devMid = devMid - iteration ;
00396             lastErrorSup = errorMid;
00397           }
00398         proceed = true;
00399       }
00400     else
00401       {
00402         proceed = false;
00403       }
00404 
00405   } while (proceed); ////////////////////////////////////////////////
00406 
00407 
00408   double min = errorMid + 100;
00409   for (int i = devMid - 10 ; i < devMid + 10 ; ++i)
00410     {
00411       center.setXY(xIntersection + int(alphaX * i), 
00412                    yIntersection + int(alphaY * i));
00413       errorMid =
00414         RWARCVECTOR_squareError(center, thePoints, firstIdx, lastIdx);
00415       if (min > errorMid)
00416         {
00417           min = errorMid;
00418           devMid = i;
00419         }
00420     } // END for i
00421 
00422   center.setXY(xIntersection + int(alphaX * devMid), 
00423                yIntersection + int(alphaY * devMid));
00424   double radius = qgDist(center, thePoints[firstIdx]);
00425 
00426   // Arc direction
00427   xNormalVector = thePoints[firstIdx].y() - yIntersection;
00428   yNormalVector = xIntersection - thePoints[firstIdx].x(); 
00429   
00430   double proj = xNormalVector * (thePoints[firstIdx].x() - xIntersection);
00431   proj += yNormalVector * (thePoints[firstIdx].y() - yIntersection);
00432   
00433   int dir; 
00434   if (smallArc)
00435     {
00436       if (proj > 0)
00437         {
00438           dir = (deviationSameSide < deviationOtherSide); 
00439         }
00440       else
00441         {
00442           dir = (deviationSameSide > deviationOtherSide); 
00443         }
00444     }
00445   else
00446     {
00447       if (proj > 0)
00448         {
00449           dir = (deviationSameSide > deviationOtherSide); 
00450         }
00451       else
00452         {
00453           dir = (deviationSameSide < deviationOtherSide); 
00454         }
00455     }
00456 
00457   // Arc significance
00458   double sinAng =
00459     qgDist(thePoints[firstIdx], thePoints[lastIdx]) / (2*radius);
00460 
00461   if (sinAng > 1)
00462     {
00463       sinAng = 1; // To eliminate roundness errors
00464     }
00465   angle = asin(sinAng);
00466 
00467   if (!smallArc)
00468     {
00469       angle = Math::QG_2PI - angle;
00470     }
00471 
00472   double arcLength  = angle * radius;
00473   double polyLength = 0.;
00474   for (int i = firstIdx; i < lastIdx; ++i)
00475     {
00476       polyLength += qgDist(thePoints[i], thePoints[i+1]);
00477     }
00478 
00479   double ratio;
00480   if (arcLength > polyLength)
00481     {
00482       ratio = arcLength / polyLength;
00483     }
00484   else
00485     {
00486       ratio = polyLength / arcLength ;
00487     }
00488 
00489   dev = RWARCVECTOR_maxDeviation(center, thePoints, firstIdx, lastIdx, dir);
00490   
00491   // double angDeb = center.angle(thePoints[firstIdx]);
00492   // double angFin = center.angle(thePoints[firstIdx]);
00493   // cout << qgDist(center, thePoints[firstIdx]) << "\n";
00494   
00495   if (dir)
00496     {
00497       return new QgarArc(thePoints[firstIdx], thePoints[lastIdx], center);
00498     }
00499   else
00500     {
00501       return new QgarArc(thePoints[lastIdx], thePoints[firstIdx], center);
00502     }
00503 }
00504 
00505 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00506 
00507 int
00508 RWARCVECTOR_thirdPoint(vector<Point>& thePoints,
00509                        int firstIdx,
00510                        int lastIdx,
00511                        Point& firstPoint,
00512                        Point& lastPoint,
00513                        Point& third)
00514 {
00515   Point middlePt((firstPoint.x() + lastPoint.x()) / 2,
00516                  (firstPoint.y() + lastPoint.y()) / 2);
00517 
00518   Point bisectPt(middlePt.x() - lastPoint.y() + firstPoint.y(),
00519                  middlePt.y() + lastPoint.x() - firstPoint.x());
00520 
00521   for (int i = firstIdx ; i < lastIdx ; ++i)
00522     {
00523       double q = (bisectPt.x() - middlePt.x()) * 
00524                  (thePoints[i+1].y() - thePoints[i].y());
00525 
00526       q -= (bisectPt.y() - middlePt.y()) * 
00527            (thePoints[i+1].x() - thePoints[i].x());
00528 
00529       // A = middlePt, B = bisectPt, C = pt[i], D = pt[i+1]
00530       //
00531       //     (YA-YC)(XB-XA)-(XA-XC)(YB-YA)
00532       // s = -----------------------------
00533       //     (XB-XA)(YD-YC)-(YB-YA)(XD-XC)
00534 
00535       double s = (middlePt.y() - thePoints[i].y()) *  
00536                  (bisectPt.x() - middlePt.x());
00537 
00538       s -= (middlePt.x() - thePoints[i].x()) *
00539            (bisectPt.y() - middlePt.y());
00540 
00541       double sq = s / q;
00542       if ((0 <= sq) && (sq <= 1))
00543         {
00544           third.setXY((int) (s * (thePoints[i+1].x() - thePoints[i].x())
00545                              / q + thePoints[i].x()),
00546                       (int) (s * (thePoints[i+1].y() - thePoints[i].y())
00547                              / q + thePoints[i].y()));
00548           return i; 
00549         }
00550     }
00551 
00552   return -1;
00553 }
00554 
00555 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00556 
00557 int
00558 RWARCVECTOR_meanRadius(vector<Point>& thePoints,
00559                        int firstIdx,
00560                        int lastIdx,
00561                        int threshold)
00562 {
00563   Point thirdPt; 
00564   DPoint center;
00565   int thirdIdx = RWARCVECTOR_thirdPoint(thePoints, firstIdx,
00566                                         lastIdx,
00567                                         thePoints[firstIdx],
00568                                         thePoints[lastIdx],
00569                                         thirdPt);
00570 
00571   if (!qgCircleCenter(thePoints[firstIdx], thirdPt, thePoints[lastIdx], center))
00572     {
00573       return -1;
00574     }
00575 
00576   Point thirdPt1;
00577   RWARCVECTOR_thirdPoint(thePoints,
00578                          firstIdx,
00579                          thirdIdx + 1, 
00580                          thePoints[firstIdx],
00581                          thirdPt,
00582                          thirdPt1);
00583   DPoint center1;
00584   if (!qgCircleCenter(thePoints[firstIdx], thirdPt1, thirdPt, center1))
00585     {
00586       return -1;
00587     }
00588 
00589   Point thirdPt2;
00590   RWARCVECTOR_thirdPoint(thePoints,
00591                          thirdIdx,
00592                          lastIdx,
00593                          thirdPt,
00594                          thePoints[lastIdx],
00595                          thirdPt2);
00596   DPoint center2;
00597   if (!qgCircleCenter(thirdPt, thirdPt2, thePoints[lastIdx], center2))
00598     {
00599       return -1;
00600     }
00601 
00602   if ((qgDist(center,  center1) > threshold) ||
00603       (qgDist(center1, center2) > threshold) ||
00604       (qgDist(center2, center)  > threshold)   )
00605     {  
00606       return -1;
00607     }
00608   else
00609     {
00610       return (int) ( (  qgDist(DPoint(thirdPt),  center)
00611                       + qgDist(DPoint(thirdPt1), center1)
00612                       + qgDist(DPoint(thirdPt2), center2)) / 3);
00613     }
00614 }
00615 
00616 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00617 
00618 // Cross-recursivity between arcs3 and arcsInLoop
00619 void
00620 RWARCVECTOR_arcs3(RWArcVector* aRWvector,
00621                 vector<Point>& thePoints,
00622                 int firstIdx, int lastIdx, int thres);
00623 
00624 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00625 
00626 void
00627 RWARCVECTOR_arcsInLoop(RWArcVector* aRWvector,
00628                        vector<Point>& thePoints,
00629                        int firstIdx, int lastIdx, int thres)
00630 {
00631   RWARCVECTOR_arcs3(aRWvector, thePoints, firstIdx, lastIdx - 1, thres);
00632   if (aRWvector->size() == 0)
00633     {
00634       return;
00635     }
00636 
00637   QgarArc& lastArc = (*aRWvector)[aRWvector->size() - 1 ];
00638  
00639   if ((lastArc.source() == thePoints[firstIdx]) && 
00640       (lastArc.target() == thePoints[lastIdx-1])   )
00641     {
00642       QgarArc anArc(thePoints[firstIdx],
00643                     thePoints[firstIdx],
00644                     lastArc.center());
00645 
00646       // Delete last but one arc
00647       vector<QgarArc>::iterator thisIdx = aRWvector->begin();      
00648       for (int i = 0; i < (int)aRWvector->size() - 1; ++i)
00649         {
00650           ++thisIdx;
00651         }
00652 
00653       aRWvector->erase(thisIdx);
00654       // Insert new arc
00655       aRWvector->push_back(anArc);
00656     }
00657 }
00658 
00659 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00660 
00661 void
00662 RWARCVECTOR_arcs3(RWArcVector* aRWvector,
00663                   vector<Point>& thePoints,
00664                   int firstIdx, int lastIdx, int thres)
00665 {
00666   if ((lastIdx - firstIdx) < 3) return;
00667 
00668   const int maxDeviation = 15;
00669 
00670   if (thePoints[firstIdx] == thePoints[lastIdx])
00671     {
00672       RWARCVECTOR_arcsInLoop(aRWvector, thePoints, firstIdx, lastIdx, thres);
00673       return;
00674     }
00675 
00676   int radius =
00677     RWARCVECTOR_meanRadius(thePoints, firstIdx, lastIdx, thres);
00678   double deviation;
00679   QgarArc* anArc;
00680   if (radius != -1)
00681     {
00682       anArc = RWARCVECTOR_bestAttributes
00683                 (thePoints, firstIdx, lastIdx, deviation, radius);
00684       if (deviation < maxDeviation)
00685         {
00686           aRWvector->push_back(*anArc);
00687           return;
00688         }
00689       delete anArc;
00690     }  
00691 
00692   for (int nbPoints = (lastIdx - firstIdx); nbPoints > 4; --nbPoints)
00693     {
00694       for (int i = firstIdx; (i + nbPoints - 1) <= lastIdx; ++i)
00695         {
00696           radius = RWARCVECTOR_meanRadius(thePoints, i, i+nbPoints-1, thres);
00697           if (radius != -1)
00698             {
00699               anArc = RWARCVECTOR_bestAttributes(thePoints,
00700                                                i,
00701                                                (i + nbPoints - 1), 
00702                                                deviation, radius);
00703               if (deviation < maxDeviation)
00704                 {
00705                   aRWvector->push_back(*anArc);
00706                 }
00707               delete anArc;
00708 
00709               if (i - firstIdx > 2)
00710                 {
00711                   RWARCVECTOR_arcs3(aRWvector, thePoints, firstIdx, i, thres);
00712                 }
00713               if (lastIdx - (i + nbPoints - 1) > 2)
00714                 {
00715                   RWARCVECTOR_arcs3(aRWvector,
00716                                     thePoints,
00717                                     (i + nbPoints - 1),
00718                                     lastIdx,
00719                                     thres);
00720                 }
00721               return;
00722             } // if
00723         }  // END for i
00724     } // END for nbpoints
00725 }
00726 
00727 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00728 
00729 } // unnamed namespace
00730 
00731 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00732 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00733 
00734 
00735 
00736 
00737 namespace qgar
00738 {
00739 
00740 
00741 // -------------------------------------------------------------------
00742 // C O N S T R U C T O R S
00743 // -------------------------------------------------------------------
00744 
00745 RWArcVector::RWArcVector(RWSegmentVector &aRWvector, int thres)
00746 
00747   : _centerDispersionThreshold(thres)
00748 
00749 {
00750   // Get points from the polygonal approximation.
00751   vector<Point> pointVector;
00752   vector<Segment>::iterator seg = aRWvector.begin();
00753   while (seg != aRWvector.end())
00754     {
00755       pointVector.push_back(seg->source());
00756       ++seg;
00757     }
00758   pointVector.push_back(aRWvector[aRWvector.size() - 1].target());
00759 
00760   // Follow segments, keeping the same orientation
00761   int initIdx = 0;
00762 
00763   Point point1 = pointVector[0];
00764   Point point2 = pointVector[1];
00765   Point point3 = pointVector[2];
00766 
00767   for (int i = 2 ; i < (int)pointVector.size() ; ++i)
00768     {
00769       int angleSign = ((qgAngle(point2, point1, point3) < Math::QG_PI) ? 1 : 0);
00770       int newSign;
00771 
00772       do  // Do while angles have the same sign
00773         {
00774           ++i;
00775           if (i >= (int)pointVector.size())
00776             {
00777               break;
00778             }
00779           point1 = point2;
00780           point2 = point3;
00781           point3 = pointVector[i];
00782           newSign = ((qgAngle(point2, point1, point3) < Math::QG_PI) ? 1 : 0);
00783         }
00784       while (angleSign == newSign); // do while
00785 
00786       --i;
00787       RWARCVECTOR_arcs3(this,
00788                         pointVector,
00789                         initIdx ,
00790                         i,
00791                         _centerDispersionThreshold);
00792       initIdx = i - 1;
00793     } // END for i
00794 }
00795 
00796 // -------------------------------------------------------------------
00797 
00798 RWArcVector::RWArcVector(RWSegmentVector &aRWvector1,
00799                          RWSegmentVector &aRWvector2,
00800                          int thres)
00801 
00802   : _centerDispersionThreshold(thres)
00803 
00804 {
00805   // Get points from the first polygonal approximation
00806   vector<Point> pointVector; 
00807   const Point& pt1 = aRWvector1[0].source();
00808   const Point& pt2 = aRWvector1[aRWvector1.size()-1].target();
00809   const Point& pt3 = aRWvector2[0].source();
00810   const Point& pt4 = aRWvector2[aRWvector2.size()-1].target();
00811   
00812   if ((pt2 == pt3) || (pt2 == pt4))
00813     {
00814       vector<Segment>::iterator seg = aRWvector1.begin();
00815       while (seg != aRWvector1.end())
00816         {
00817           pointVector.push_back(seg->source());
00818           ++seg;
00819         }
00820       pointVector.push_back(pt2);
00821     } 
00822   else
00823     {
00824       vector<Segment>::reverse_iterator seg = aRWvector1.rbegin();
00825       while (seg != aRWvector1.rend())
00826         {
00827           pointVector.push_back(seg->target());
00828           ++seg;
00829         }
00830       pointVector.push_back (pt1);
00831     }
00832 
00833   int cutIdx = pointVector.size() - 1;
00834 
00835   // Get points from the second polygonal approximation
00836   if (pointVector[cutIdx] == pt3)
00837     {
00838       vector<Segment>::iterator seg = aRWvector2.begin();
00839       pointVector.push_back(seg->target());
00840       ++seg;
00841       while (seg != aRWvector2.end())
00842         {
00843           pointVector.push_back(seg->target());
00844           ++seg;
00845         }
00846     }
00847   else
00848     {
00849       vector<Segment>::reverse_iterator seg = aRWvector2.rbegin();
00850       while (seg != aRWvector2.rend())
00851         {
00852           pointVector.push_back(seg->source());
00853           ++seg;
00854         }
00855     }
00856 
00857   // Follow segments, keeping the same orientation
00858   int initIdx;
00859   int idx;
00860 
00861   Point point1 = pointVector[0];
00862   Point point2 = pointVector[1];
00863   Point point3 = pointVector[2];
00864 
00865   for (idx = 2, initIdx = 0; idx < (int)pointVector.size(); ++idx)
00866     {
00867       int angleSign = ((qgAngle(point2, point1, point3) < Math::QG_PI) ? 1 : 0);
00868       int newSign;
00869 
00870       do  // Do while angles have the same sign
00871         {
00872           ++idx;
00873           if (idx >= (int)pointVector.size())
00874             {
00875               break;
00876             }
00877           point1 = point2;
00878           point2 = point3;
00879           point3 = pointVector[idx];
00880           newSign = ((qgAngle(point2, point1, point3) < Math::QG_PI) ? 1 : 0);
00881         }
00882       while (newSign == angleSign); // do while
00883 
00884       --idx;
00885 
00886       if (idx > cutIdx)
00887         {
00888           RWARCVECTOR_arcs3(this,
00889                             pointVector, initIdx,
00890                             idx,
00891                             _centerDispersionThreshold);
00892         }
00893 
00894       initIdx = idx - 1;
00895       if (initIdx >= cutIdx)
00896         {
00897           break;
00898         }
00899     }
00900 }
00901 
00902 
00903 // -------------------------------------------------------------------
00904 // D E S T R U C T O R 
00905 // -------------------------------------------------------------------
00906 
00907 
00908 // NON-VIRTUAL DESTRUCTOR
00909 
00910 RWArcVector::~RWArcVector()
00911 {
00912   // VOID
00913 }
00914 
00915 
00916 // -------------------------------------------------------------------
00917 
00918 } // namespace qgar