30 #ifndef GRALE_POLYGON2D_H
32 #define GRALE_POLYGON2D_H
34 #include "graleconfig.h"
39 #include "constants.h"
40 #include "Wm5ConvexHull2.h"
41 #include "Wm5ContMinBox2.h"
54 Polygon2D() { m_numCoords = 0; m_isConvexHull =
false; }
58 void init(
const Vector2D<T> *pPoints,
int numPoints,
bool calcConvexHull);
59 void init(
const std::list<
Vector2D<T> > &points,
bool calcConvexHull);
64 bool isConvexHull()
const {
return m_isConvexHull; }
65 const Vector2D<T> *getPoints()
const {
return &(m_xyCoords[0]); }
66 int getNumberOfPoints()
const {
return m_numCoords; }
67 void scale(T scaleFactor);
71 void operator=(
const Polygon2D<T> &p) { copyFieldsFrom(p); }
75 template<
class Iterator>
void calculateHull(Iterator startIt,
int numPoints);
79 std::vector<Vector2D<T> > m_xyCoords;
89 int intersections = 0;
91 for (
int i = 0 ; i < m_numCoords ; i++)
93 T y1 = m_xyCoords[i].getY();
94 T y2 = m_xyCoords[i+1].getY();
95 T Y1 = MIN(m_xyCoords[i].getY(), m_xyCoords[i+1].getY());
96 T Y2 = MAX(m_xyCoords[i].getY(), m_xyCoords[i+1].getY());
98 if (Y1 < y && y <= Y2)
100 T x1 = m_xyCoords[i].getX();
101 T x2 = m_xyCoords[i+1].getX();
103 if (x <= MAX(x1, x2))
109 T x0 = ((y - y1)*(x2 - x1))/(y2 - y1) + x1;
117 return (intersections&1)?
true:
false;
121 inline T Polygon2D<T>::getDistanceSquared(Vector2D<T> p)
const
123 if (m_numCoords == 0)
125 if (m_numCoords == 1)
127 Vector2D<T> p2 = m_xyCoords[0];
129 return p2.getLengthSquared();
132 T minDist2 = calcDist2(m_xyCoords[0], m_xyCoords[1], p);
134 for (
int i = 1 ; i < m_numCoords ; i++)
136 T d2 = calcDist2(m_xyCoords[i], m_xyCoords[i+1], p);
145 inline T Polygon2D<T>::calcDist2(Vector2D<T> p1, Vector2D<T> p2, Vector2D<T> P)
const
148 T dx = p2.getX() - p1.getX();
149 T dy = p2.getY() - p1.getY();
150 T denom = dx*dx + dy*dy;
156 T l = ((P.getX() - p1.getX())*dx + (P.getY() - p1.getY())*dy)/denom;
163 Q = Vector2D<T>(p1.getX() + l*dx, p1.getY() + l*dy);
167 return Q.getLengthSquared();
171 inline void Polygon2D<T>::copyFieldsFrom(
const Polygon2D<T> &p)
173 m_numCoords = p.m_numCoords;
174 m_isConvexHull = p.m_isConvexHull;
175 m_xyCoords = p.m_xyCoords;
179 inline T Polygon2D<T>::getArea()
const
183 for (
int i = 0 ; i < m_numCoords ; i++)
185 T areaPart = m_xyCoords[i].getX()*m_xyCoords[i+1].getY() - m_xyCoords[i+1].getX()*m_xyCoords[i].getY();
196 inline void Polygon2D<T>::scale(T scaleFactor)
199 Vector2D<T> center(0, 0);
200 for (
int i = 0 ; i < m_numCoords ; i++)
201 center += m_pXYCoords[i];
202 center /= (T)m_numCoords;
209 for (
int i = 0 ; i < m_numCoords ; i++)
211 T areaPart = m_xyCoords[i].getX()*m_xyCoords[i+1].getY() - m_xyCoords[i+1].getX()*m_xyCoords[i].getY();
214 cx += (m_xyCoords[i].getX() + m_xyCoords[i+1].getX())*areaPart;
215 cy += (m_xyCoords[i].getY() + m_xyCoords[i+1].getY())*areaPart;
223 Vector2D<T> center(cx, cy);
225 for (
int i = 0 ; i < m_numCoords ; i++)
227 Vector2D<T> diff = m_xyCoords[i] - center;
229 m_xyCoords[i] = center + diff;
235 void Polygon2D<T>::init(
const Vector2D<T> *pPoints,
int numPoints,
bool calcConvexHull)
240 m_isConvexHull =
false;
241 m_xyCoords.resize(0);
248 init(pPoints, numPoints,
false);
250 calculateHull(pPoints, numPoints);
251 m_isConvexHull =
true;
255 m_isConvexHull =
false;
257 m_xyCoords.resize(numPoints+1);
258 m_numCoords = numPoints;
260 const Vector2D<T> *pPtr;
265 m_xyCoords[m_numCoords] = *pPtr;
266 for (i = 0 ; i < m_numCoords ; pPtr++, i++)
267 m_xyCoords[i] = *pPtr;
271 void Polygon2D<T>::init(
const std::list<Vector2D<T> > &points,
bool calcConvexHull)
273 if (points.size() == 0)
276 m_isConvexHull =
false;
277 m_xyCoords.resize(0);
283 if (points.size() <= 3)
286 calculateHull(points.begin(), points.size());
287 m_isConvexHull =
true;
291 m_isConvexHull =
false;
293 m_xyCoords.resize(points.size() + 1);
294 m_numCoords = points.size();
296 typename std::list< Vector2D<T> >::const_iterator it;
301 m_xyCoords[m_numCoords] = (*it);
302 for (i = 0 ; i < m_numCoords ; it++, i++)
303 m_xyCoords[i] = (*it);
307 template<
class Iterator>
308 void Polygon2D<T>::calculateHull(Iterator startIt,
int numPoints)
310 std::vector<Wm5::Vector2<T> > points(numPoints);
312 Iterator it = startIt;
314 for (
int i = 0 ; i < numPoints ; i++, it++)
315 points[i] = Wm5::Vector2<T>((*it).getX(), (*it).getY());
317 m_xyCoords.resize(0);
319 Wm5::ConvexHull2<T> hull(numPoints, &(points[0]), 0,
false, Wm5::Query::QT_INTEGER);
321 int numIndices = hull.GetNumSimplices();
322 const int *pIndices = hull.GetIndices();
324 m_numCoords = numIndices;
325 m_xyCoords.resize(m_numCoords+1);
327 m_xyCoords[m_numCoords] = Vector2D<T>(points[pIndices[0]].X(), points[pIndices[0]].Y());
328 for (
int i = 0 ; i < m_numCoords ; i++)
329 m_xyCoords[i] = Vector2D<T>(points[pIndices[i]].X(), points[pIndices[i]].Y());
333 bool Polygon2D<T>::getMinimalAreaRectangle(Rectangle2D<T> &r)
const
335 if (!m_isConvexHull || m_numCoords < 3)
338 std::vector<Wm5::Vector2<T> > points(m_numCoords);
340 for (
int i = 0 ; i < m_numCoords ; i++)
341 points[i] = Wm5::Vector2<T>(m_xyCoords[i].getX(), m_xyCoords[i].getY());
343 Wm5::MinBox2<T> box(m_numCoords, &(points[0]), 0, Wm5::Query::QT_INTEGER,
true);
344 Wm5::Vector2<T> rectPoints[4];
346 Wm5::Box2<T> rectBox = box;
347 rectBox.ComputeVertices(rectPoints);
349 Vector2D<T> graleRectPoints[4];
351 graleRectPoints[0] = Vector2D<T>(rectPoints[0].X(), rectPoints[0].Y());
352 graleRectPoints[1] = Vector2D<T>(rectPoints[1].X(), rectPoints[1].Y());
353 graleRectPoints[2] = Vector2D<T>(rectPoints[2].X(), rectPoints[2].Y());
354 graleRectPoints[3] = Vector2D<T>(rectPoints[3].X(), rectPoints[3].Y());
355 r.init(graleRectPoints);
361 #endif // GRALE_POLYGON2D_H