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
00019 return true;
00020 }
00021
00023 static void Simplify (VPolyLine *pLine)
00024 {
00025 if ( ShouldSimplify(pLine) )
00026 {
00027 vector<unsigned int> vSimplifiedPoints;
00028
00029 SimplifySegment(pLine, &vSimplifiedPoints, 4, pLine->PointCount() - 1);
00030
00031 sort(vSimplifiedPoints.begin(), vSimplifiedPoints.end());
00032
00033
00034
00035 unsigned int nLinePos = pLine->PointCount() - 2;
00036 unsigned int nSimplifiedPos = vSimplifiedPoints.size() - 1;
00037
00038 if (nSimplifiedPos < 2)
00039 {
00040 unsigned int nLinePos = 5;
00041 while (nLinePos < pLine->PointCount() -1)
00042 pLine->DeletePoint(nLinePos);
00043 }
00044 else
00045 {
00046 for (; nLinePos >= 5; nLinePos--)
00047 {
00048 while ( vSimplifiedPoints[nSimplifiedPos] != nLinePos && nLinePos >=5)
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
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
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) &&
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
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