Mobile API Reference  MicroStrategy 2019
Point2D.h
Go to the documentation of this file.
1 //==============================================================================================
2 // FILENAME : Point2D.h
3 // AUTHOR : Liang Liu
4 // CREATION : 2008-09-25
5 // Copyright (C) MicroStrategy Incorporated 2008
6 // All Rights Reserved
7 //==============================================================================================
8 
9 #ifndef MsiChart_Point2D_h
10 #define MsiChart_Point2D_h
11 
12 #include "PDCHeader/PDCvector"
13 #include "PDCHeader/PDCcmath"
14 
15 #ifdef _VE_CE
16 #pragma warning(disable : 4244)
17 #pragma warning(disable : 4305)
18 #endif
19 
20 namespace MsiChart
21 {
25  template <typename T = double>
26  class Point
27  {
28  public:
34  Point(T iX = T(), T iY = T()): x(iX), y(iY){}
39  Point(const Point<T>& irPoint):x(irPoint.x), y(irPoint.y){}
44  template <typename U>
45  Point(const Point<U>& irPoint);
46 
52  void Reset(T iX, T iY);
53 
59  double DistanceSquared(const Point<T>& irPoint) const;
65  double Distance(const Point<T>& irPoint) const;
66 
73  bool IsInPolygon(const std::vector<Point<T> >& irPolygon) const;
74 
81  bool IsStrictlyInPolygon(const std::vector<Point<T> >& irPolygon) const;
89  bool operator != (const Point<T>& irPoint) const;
90  bool operator == (const Point<T>& irPoint) const;
95  Point<T> operator - () const;
96 
102  void Rotate(const Point<T>& irAnchor, double iRadian);
103 
110  Point<T> RotateAndClone(const Point<T>& irAnchor, double iRadian);
111 
117  Point<T> MiddleTo(const Point<T>& irPoint) const;
118 
124  Point<T> Shifted(const Point<T>& irOffset) const;
125 
129  void Swap();
130 
134  void Swap(Point<T>& iorPoint);
135 
141  bool IsOnSegment(const Point<T>& irSegmentStart, const Point<T>& irSegmentEnd, bool iExclude) const;
142 
148  bool IsOnVerOrHorSegment(const Point<T>& irSegmentStart, const Point<T>& irSegmentEnd) const;
149 
150 #ifndef _VE_CE
151 
155  CGPoint GetCGPoint() const;
156 #endif
157 
164  double DistanceToPolygon(const std::vector<Point<T> >& irPolygon) const;
165 
171  double DistanceToLine(const Point<T>& irLineStart, const Point<T>& irLineEnd) const;
172 
173 
174  T x;
175  T y;
176  };
177 
178 
179  template<typename T>
180  template<typename U> Point<T>::Point(const Point<U>& iPoint)
181  {
182  x = static_cast<T>(iPoint.x);
183  y = static_cast<T>(iPoint.y);
184  }
185 
186  template<typename T>
187  inline void Point<T>::Reset(T iX, T iY)
188  {
189  x = iX;
190  y = iY;
191  }
192 
193  template<typename T>
194  double Point<T>::DistanceSquared(const Point<T>& irPoint) const
195  {
196  return (x - irPoint.x) * (x - irPoint.x)
197  + (y - irPoint.y) * (y - irPoint.y);
198  }
199 
200  template<typename T>
201  double Point<T>::Distance(const Point<T>& irPoint) const
202  {
203  return std::sqrt(DistanceSquared(irPoint));
204  }
205 
206  template<typename T>
207  bool Point<T>::operator != (const Point<T>& irPoint) const
208  {
209  return ((x != irPoint.x) || (y != irPoint.y));
210  }
211 
212  template<typename T>
213  bool Point<T>::operator == (const Point<T>& irPoint) const
214  {
215  return ((x == irPoint.x) && (y == irPoint.y));
216  }
217 
218  template<typename T>
220  {
221  return Point<T>(-x, -y);
222  }
223 
224  // Reference: http://local.wasp.uwa.edu.au/~pbourke/geometry/insidepoly/
225  template<typename T>
226  bool Point<T>::IsInPolygon(const std::vector<Point<T> >& irPolygon) const
227  {
228  unsigned Int32 lNumberOfEdges = (Int32)irPolygon.size();
229  if (lNumberOfEdges < 3) // A polygon should have at least 3 edges.
230  return false;
231 
232  //[consider to do] Li en: special case, across at the end point of the edge.
233  bool lResult = false;
234  for (unsigned Int32 i = 0, j = lNumberOfEdges - 1; i < lNumberOfEdges; j = i++)
235  {
236  if (((irPolygon[i].y <= y && y < irPolygon[j].y) ||
237  (irPolygon[j].y <= y && y < irPolygon[i].y)) &&
238  x <= (irPolygon[j].x - irPolygon[i].x) * (y - irPolygon[i].y) * 1.0 / (irPolygon[j].y - irPolygon[i].y) + irPolygon[i].x)
239  {
240  lResult = !lResult;
241  }
242  }
243  return lResult;
244  }
245 
246  template<typename T>
247  bool Point<T>::IsStrictlyInPolygon(const std::vector<Point<T> >& irPolygon) const
248  {
249  if (!Point<T>(x + 0.1f, y).IsInPolygon(irPolygon))
250  return false;
251  if (!Point<T>(x - 0.1f, y).IsInPolygon(irPolygon))
252  return false;
253  if (!Point<T>(x, y + 0.1f).IsInPolygon(irPolygon))
254  return false;
255  if (!Point<T>(x, y - 0.1f).IsInPolygon(irPolygon))
256  return false;
257  return true;
258  }
259 
260  template<typename T>
261  void Point<T>::Rotate(const Point<T>& irAnchor, double iRadian)
262  {
263  double lXDist = x - irAnchor.x;
264  double lYDist = y - irAnchor.y;
265 
266  x = static_cast<T>(irAnchor.x + cos(iRadian) * lXDist - sin(iRadian) * lYDist);
267  y = static_cast<T>(irAnchor.y + sin(iRadian) * lXDist + cos(iRadian) * lYDist);
268  }
269 
270  template<typename T>
271  Point<T> Point<T>::RotateAndClone(const Point<T>& irAnchor, double iRadian)
272  {
273  Rotate(irAnchor, iRadian);
274  return *this;
275  }
276 
277  // specialize for Int32
278  template<>
279  void Point<Int32>::Rotate(const Point<Int32>& irAnchor, double iRadian);
280 
281  //template<>
282  //Point<Int32> Point<Int32>::RotateAndClone(const Point<Int32>& irAnchor, double iRadian);
283 
284  template<typename T>
285  Point<T> Point<T>::MiddleTo(const Point<T> &irPoint) const
286  {
287  return Point<T>((x + irPoint.x) / 2, (y + irPoint.y) / 2);
288  }
289 
290  template<typename T>
291  Point<T> Point<T>::Shifted(const Point<T>& irOffset) const
292  {
293  return Point<T>(x + irOffset.x, y + irOffset.y);
294  }
295 
296  template<typename T>
298  {
299  std::swap(x, y);
300  }
301 
302  template<typename T>
303  void Point<T>::Swap(Point<T>& iorPoint)
304  {
305  std::swap(x, iorPoint.x);
306  std::swap(y, iorPoint.y);
307  }
308 
309  template<typename T>
310  bool Point<T>::IsOnSegment(const Point<T>& iSegmentStart, const Point<T>& iSegmentEnd, bool iExclude) const
311  {
312  const float lTolerance = iExclude ? 0.01f : -0.01f;
313  if(fabs(iSegmentStart.x - iSegmentEnd.x) < 0.01f)//vertical segment, so compare Y
314  {
315  if((y - iSegmentStart.y) > lTolerance && (iSegmentEnd.y - y) > lTolerance)
316  return true;
317  if((y - iSegmentEnd.y) > lTolerance && (iSegmentStart.y - y) > lTolerance)
318  return true;
319  }
320  else//not vertical, so compare X
321  {
322  if((x - iSegmentStart.x) > lTolerance && (iSegmentEnd.x - x) > lTolerance)
323  return true;
324  if((x - iSegmentEnd.x) > lTolerance && (iSegmentStart.x - x) > lTolerance)
325  return true;
326  }
327  return false;
328  }
329 
330  template<typename T>
331  bool Point<T>::IsOnVerOrHorSegment(const Point<T>& irSegmentStart, const Point<T>& irSegmentEnd) const
332  {
333  if (y == irSegmentStart.y && y == irSegmentEnd.y)
334  {
335  return ((x - irSegmentStart.x) >= 0 && (irSegmentEnd.x - x) >= 0) ||
336  ((x - irSegmentStart.x) <= 0 && (irSegmentEnd.x - x) <= 0);
337  }
338 
339  if (x == irSegmentStart.x && x == irSegmentEnd.x)
340  {
341  return ((y - irSegmentStart.y) >= 0 && (irSegmentEnd.y - y) >= 0) ||
342  ((y - irSegmentStart.y) <= 0 && (irSegmentEnd.y - y) <= 0);
343  }
344  return false;
345  }
346 
347 #ifndef _VE_CE
348  template<typename T>
349  CGPoint Point<T>::GetCGPoint() const
350  {
351  return CGPointMake(x, y);
352  }
353 #endif
354 
355  template<typename T>
356  double Point<T>::DistanceToPolygon(const std::vector<Point<T> >& irPolygon) const
357  {
358  if (IsInPolygon(irPolygon))
359  return 0;
360 
361  const size_t lNumOfEdges = irPolygon.size();
362  double lDistance = DistanceToLine(irPolygon[0], irPolygon[lNumOfEdges - 1]);
363  for (size_t i = 0; i + 1 < lNumOfEdges; ++i)
364  {
365  double lNewDistance = DistanceToLine(irPolygon[i], irPolygon[i + 1]);
366  if (lDistance > lNewDistance)
367  {
368  lDistance = lNewDistance;
369  }
370  }
371  return lDistance;
372  }
373 
374  template<typename T>
375  double Point<T>::DistanceToLine(const Point<T>& irLineStart, const Point<T>& irLineEnd) const
376  {
377  double lPointToStart2 = DistanceSquared(irLineStart);
378  double lPointToEnd2 = DistanceSquared(irLineEnd);
379  double lStartToEnd2 = irLineStart.DistanceSquared(irLineEnd);
380 
381  const float lTolerance = 0.01;
382  if (lPointToStart2 < lTolerance || lPointToEnd2 < lTolerance)
383  return 0;
384  if (lStartToEnd2 < lTolerance)
385  return std::sqrt(lPointToStart2);
386 
387  if (lPointToStart2 >= lPointToEnd2 + lStartToEnd2)
388  return std::sqrt(lPointToEnd2);
389 
390  if (lPointToEnd2 >= lPointToStart2 + lStartToEnd2)
391  return std::sqrt(lPointToStart2);
392 
393  Point<T> lStartToPoint(x - irLineStart.x, y - irLineStart.y);
394  Point<T> lStartToEnd(irLineEnd.x - irLineStart.x, irLineEnd.y - irLineStart.y);
395  double lCrossProduct = lStartToPoint.x * lStartToEnd.y - lStartToPoint.y * lStartToEnd.x;
396  return (lCrossProduct < 0 ? -lCrossProduct : lCrossProduct) / std::sqrt(lStartToEnd2);
397 
398  }
399 
401 
404 #ifdef _VE_CE
405  typedef Point<double> DPoint2D;
406 #endif
407 }
408 
409 #endif
Point< float > FPoint2D
Definition: Point2D.h:403
CGPoint GetCGPoint() const
Definition: Point2D.h:349
Point< T > MiddleTo(const Point< T > &irPoint) const
Definition: Point2D.h:285
Point< Int32 > Point2D
Definition: Point2D.h:402
void Rotate(const Point< T > &irAnchor, double iRadian)
Definition: Point2D.h:261
Point(const Point< T > &irPoint)
Definition: Point2D.h:39
Point< T > RotateAndClone(const Point< T > &irAnchor, double iRadian)
Definition: Point2D.h:271
bool IsOnSegment(const Point< T > &irSegmentStart, const Point< T > &irSegmentEnd, bool iExclude) const
Definition: Point2D.h:310
double DistanceSquared(const Point< T > &irPoint) const
Definition: Point2D.h:194
Point< T > operator-() const
Definition: Point2D.h:219
Point(T iX=T(), T iY=T())
Definition: Point2D.h:34
T y
Y-coordinate of current point.
Definition: Point2D.h:175
Point< T > Shifted(const Point< T > &irOffset) const
Definition: Point2D.h:291
double DistanceToPolygon(const std::vector< Point< T > > &irPolygon) const
Definition: Point2D.h:356
#define Int32
Definition: BasicTypes.h:20
void Reset(T iX, T iY)
Definition: Point2D.h:187
bool IsInPolygon(const std::vector< Point< T > > &irPolygon) const
Definition: Point2D.h:226
T x
X-coordinate of current point.
Definition: Point2D.h:174
void Swap()
Definition: Point2D.h:297
double DistanceToLine(const Point< T > &irLineStart, const Point< T > &irLineEnd) const
Definition: Point2D.h:375
Definition: ABLPlot.h:21
bool operator==(const Point< T > &irPoint) const
Definition: Point2D.h:213
Definition: Point2D.h:26
bool IsOnVerOrHorSegment(const Point< T > &irSegmentStart, const Point< T > &irSegmentEnd) const
Definition: Point2D.h:331
double Distance(const Point< T > &irPoint) const
Definition: Point2D.h:201
bool IsStrictlyInPolygon(const std::vector< Point< T > > &irPolygon) const
Definition: Point2D.h:247
bool operator!=(const Point< T > &irPoint) const
Definition: Point2D.h:207