Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

ShapeDetector.h

00001 #ifndef SHAPEDETECTOR_H
00002 #define SHAPEDETECTOR_H
00003 
00004 #include "PolyLine.h"
00005 #include "Ellipse.h"
00006 
00007 #include <vector>
00008 #include <algorithm>
00009 
00011 class VShapeDetector
00012 {
00013 public:
00014 
00016         static bool ShouldSimplify (VPolyLine *pLine)
00017         {
00018                 // (could put an algorithm here :)
00019                 return true;
00020         }
00021 
00023         static void Simplify (VPolyLine *pLine)
00024         {
00025                 if ( ShouldSimplify(pLine) ) // this isn't a natural curve
00026                 {
00027                         vector<unsigned int> vSimplifiedPoints; // will store the indices of the simplified points
00028                         
00029                         SimplifySegment(pLine, &vSimplifiedPoints, 4, pLine->PointCount() - 1); // will recurse to simplify whole thing
00030 
00031                         sort(vSimplifiedPoints.begin(), vSimplifiedPoints.end()); // sort the indices
00032 
00033 
00034 
00035                         unsigned int nLinePos       = pLine->PointCount()      - 2;
00036                         unsigned int nSimplifiedPos = vSimplifiedPoints.size() - 1;
00037 
00038                         if (nSimplifiedPos < 2) // no points
00039                         {
00040                                 unsigned int nLinePos = 5;
00041                                 while (nLinePos < pLine->PointCount() -1) // delete all but last + first point
00042                                         pLine->DeletePoint(nLinePos);
00043                         }
00044                         else
00045                         {
00046                                 for (; nLinePos >= 5; nLinePos--) // delete points that aren't needed in the simplified shape
00047                                 {
00048                                         while ( vSimplifiedPoints[nSimplifiedPos] != nLinePos  && nLinePos >=5) // get rid of unsimplified points
00049                                                 pLine->DeletePoint( nLinePos-- );
00050                                         
00051                                         nSimplifiedPos--;
00052                                 }
00053                         }
00054                 }
00055         }
00056 
00058         static void SimplifySegment(VPolyLine *pLine, vector<unsigned int> *pvPoints, unsigned int nStart, unsigned int nEnd)
00059         {
00060                 const int MINDISTANCE = ScreenState::PointMultiplier() * 2;
00061 
00062                 int nGreatestDistance=0, nGreatestDistanceIndex=0;
00063                 int nCurrentDistance;
00064                 
00065                 if (nStart >= nEnd)
00066                         return;
00067                         
00068 
00069                 for (unsigned int i=nStart + 1; i<nEnd; i++)
00070                 {
00071                         nCurrentDistance = pLine->GetPoint(i).DistanceToLine( pLine->GetPoint(nStart), pLine->GetPoint(nEnd) );
00072                         if ( nCurrentDistance > nGreatestDistance)
00073                         {
00074                                 nGreatestDistance      = nCurrentDistance;
00075                                 nGreatestDistanceIndex = i;
00076                         }
00077                 }
00078                 
00079 
00080                 if (nGreatestDistance >= MINDISTANCE)
00081                 {
00082                         pvPoints->push_back(nGreatestDistanceIndex);
00083 
00084                         // start simplifying subsegments
00085                         SimplifySegment(pLine, pvPoints, nStart, nGreatestDistanceIndex);
00086                         SimplifySegment(pLine, pvPoints, nGreatestDistanceIndex, nEnd);
00087                 }
00088         }
00089 
00090 
00092         static bool Parallelogram( VPolyLine* pLine )
00093         {
00094                 int nHalfWidth = (pLine->GetPoint(3).x - pLine->GetPoint(0).x)/2;
00095                 int nHalfHeight= (pLine->GetPoint(3).y - pLine->GetPoint(0).y)/2;
00096 
00097                 VPoint center((pLine->GetPoint(0) + pLine->GetPoint(3))/ 2);
00098 
00099                 int outcount = 0;
00100 
00101 
00102                 int left = 0,right = 0,top = 0,bottom = 0;
00103                 for ( unsigned int i=4; i < pLine->PointCount(); i++ )
00104                 {
00105                         VPoint pt(pLine->GetPoint(i) - center);
00106 
00107                         // must be along one line--top, left, right, or bottom
00108                         if (pt.x < -.8 * nHalfWidth  && pt.x > -1.3 * nHalfWidth)
00109                         {
00110                                 left++;
00111                         }
00112                         else if (pt.x >  .8 * nHalfWidth  && pt.x <  1.3 * nHalfWidth)
00113                         {
00114                                 right++;
00115                         }
00116                         else if (pt.y < -.8 * nHalfHeight && pt.y > -1.3 * nHalfHeight)
00117                         {
00118                                 top++;
00119                         }
00120                         else if (pt.y >  .8 * nHalfHeight && pt.y <  1.3 * nHalfHeight)
00121                         {
00122                                 bottom++;
00123                         }
00124                         else
00125                         {
00126                                 outcount++;
00127                         }
00128 
00129                 }
00130 
00131                 if (outcount < .2 * (pLine->PointCount() - 4) && // 20% of the points on lines
00132                         left  >= .15 * (pLine->PointCount() - 4) &&
00133                         right >= .15 * (pLine->PointCount() - 4) &&
00134                         bottom>= .15 * (pLine->PointCount() - 4) &&
00135                         top   >= .15 * (pLine->PointCount() - 4))
00136                         return true;
00137                 else
00138                         return false;
00139 
00140         }
00141 
00143         static bool Ellipse( VPolyLine* pLine )
00144         {
00145                 int nWidth = pLine->GetPoint(3).x - pLine->GetPoint(0).x;
00146                 int nHeight = pLine->GetPoint(3).y - pLine->GetPoint(0).y;
00147 
00148                 VPoint center((pLine->GetPoint(0) + pLine->GetPoint(3))/ 2);
00149 
00150                 float outcount = 0;
00151 
00152                 // find how far away points are from an ellipse of the same width + height of the polyline 
00153                 for ( unsigned int i=4; i < pLine->PointCount(); i++ )
00154                 {
00155                         VPoint pt(pLine->GetPoint(i) - center);
00156 
00157                         float value = (float) (pt.x * pt.x) / (nWidth * nWidth) + (float) (pt.y * pt.y) / (nHeight * nHeight);
00158 
00159                         outcount += (float) fabs( 1 - value*4 );
00160                 }
00161 
00162                 outcount /= (float) (pLine->PointCount()-4);
00163 
00164                 if (outcount < .18)
00165                         return true;
00166                 else
00167                         return false;
00168         }
00169 };
00170 
00171 #endif

Generated at Wed Aug 29 19:58:55 2001 for Pocket Animator by doxygen1.2.5 written by Dimitri van Heesch, © 1997-2001