Gorgon Game Engine
Point.h
Go to the documentation of this file.
1 
3 #pragma once
4 
5 #include <iostream>
6 #include <string>
7 #include <iomanip>
8 #include <limits>
9 #include <cmath>
10 #include <sstream>
11 #include <type_traits>
12 
13 #include "../Types.h"
14 #include "../String.h"
15 
16 namespace Gorgon {
27  namespace Geometry {
28 
31  template <class T_>
32  class basic_Point {
33  public:
35  typedef T_ BaseType;
36 
39 
41  basic_Point(const T_ &X, const T_ &Y) : X(X), Y(Y) { }
42 
44  template <class O_>
45  basic_Point(const basic_Point<O_> &point) : X((T_)point.X), Y((T_)point.Y) { }
46 
48  explicit basic_Point(const std::string &str) : X(0), Y(0) {
49  T_ x = 0, y = 0;
50  auto s=str.begin();
51 
52  if(s==str.end())
53  return;
54 
55  while(*s==' ' || *s=='\t') s++;
56 
57  if(s==str.end())
58  return;
59 
60  if(*s=='(') s++;
61 
62  if(s==str.end())
63  return;
64 
65  x=String::To<T_>(&str[s-str.begin()]);
66 
67  while(s!=str.end() && *s!=',') s++;
68 
69  if(s==str.end())
70  return;
71 
72  if(*s==',') s++;
73 
74  if(s==str.end())
75  return;
76 
77  y=String::To<T_>(&str[s-str.begin()]);
78 
79  X = x;
80  Y = y;
81  }
82 
84  template <class O_>
86  X=T_(point.X);
87  Y=T_(point.Y);
88  return *this;
89  }
90 
92  explicit operator std::string() const {
93  std::string ret;
94  ret.push_back('(');
95  ret += String::From(X);
96  ret.push_back(',');
97  ret.push_back(' ');
98  ret += String::From(Y);
99  ret.push_back(')');
100 
101  return ret;
102  }
103 
108  template <class O_>
109  static basic_Point FromVector(Float magnitute, Float angle, const basic_Point<O_> &origin={0,0}) {
110  return{T_(origin.X+magnitute*std::cos(angle)), T_(origin.Y+magnitute*std::sin(angle))};
111  }
112 
125  static basic_Point Parse(const std::string &str, bool require_parenthesis=false) {
126  basic_Point p;
127 
128  auto s=str.begin();
129 
130  size_t par=-1;
131 
132  while(s!=str.end() && (*s==' ' || *s=='\t')) s++;
133 
134  if(s!=str.end() && *s=='(') {
135  par=s-str.begin();
136  s++;
137  }
138 
139  if(par==-1 && require_parenthesis) {
140  throw String::ParseError(110006, "Missing parenthesis");
141  }
142 
143  if(s==str.end()) {
144  throw String::ParseError(110007, std::string("Missing operand"));
145  }
146 
147  char *endptr;
148  p.X = T_(strtod(&*s, &endptr));
149  if(endptr==&*s) {
150  throw String::IllegalTokenError(0, 110001);
151  }
152  s+=endptr-&*s;
153 
154  while(s!=str.end() && (*s==' ' || *s=='\t')) s++;
155  if(s==str.end() || *s!=',') {
156  throw String::IllegalTokenError(s-str.begin(), 111002, std::string("Illegal token: ")+*s);
157  }
158  s++;
159 
160 
161  if(s==str.end()) {
162  throw String::ParseError(110007, std::string("Missing operand"));
163  }
164  p.Y=T_(strtod(&*s, &endptr));
165  if(endptr==&*s) {
166  throw String::IllegalTokenError(s-str.begin(), 111003);
167  }
168  s+=endptr-&*s;
169 
170  //eat white space + a single )
171  while(s!=str.end() && (*s==' ' || *s=='\t')) s++;
172  if(s!=str.end() && *s==')') {
173  if(par!=-1) {
174  s++;
175  par=-1;
176  }
177  else {
178  throw String::IllegalTokenError(s-str.begin(), 111005, "Unmatched parenthesis");
179  }
180  }
181  while(s!=str.end() && (*s==' ' || *s=='\t')) s++;
182 
183  if(s!=str.end()) {
184  throw String::IllegalTokenError(s-str.begin(), 111004, std::string("Illegal token: ")+*s);
185  }
186 
187  if(par>0) {
188  throw String::IllegalTokenError(par, 111005, "Unmatched parenthesis");
189  }
190 
191  return p;
192  }
193 
195  basic_Point operator - (const basic_Point &point) const {
196  return basic_Point(X-point.X, Y-point.Y);
197  }
198 
201  return{-X, -Y};
202  }
203 
205  basic_Point operator + (const basic_Point &point) const {
206  return{X+point.X, Y+point.Y};
207  }
208 
211  template <class O_>
212  basic_Point operator * (O_ value) const {
213  return{T_(X*value), T_(Y*value)};
214  }
215 
217  T_ operator *(const basic_Point<T_> &value) const {
218  return X*value.X + Y*value.Y;
219  }
220 
223  template <class O_>
224  basic_Point operator / (O_ value) const {
225  return{T_(X/value), T_(Y/value)};
226  }
227 
231  X-=point.X;
232  Y-=point.Y;
233 
234  return *this;
235  }
236 
240  X+=point.X;
241  Y+=point.Y;
242 
243  return *this;
244  }
245 
247  template <class O_>
249  X=T_(X*value);
250  Y=T_(Y*value);
251 
252  return *this;
253  }
254 
256  template <class O_>
258  X=T_(X/value);
259  Y=T_(Y/value);
260 
261  return *this;
262  }
263 
265  T_ CrossProduct(const basic_Point<T_> &value) const {
266  return X*value.Y - Y*value.X;
267  }
268 
270  T_ DotProduct(const basic_Point<T_> &value) const {
271  return X*value.X + Y*value.Y;
272  }
273 
274 
276  Float Distance(const basic_Point &target) const {
277  Float xdif = (Float)(X - target.X);
278  Float ydif = (Float)(Y - target.Y);
279  return std::sqrt((xdif*xdif) + (ydif*ydif));
280  }
282  Float EuclideanSquare(const basic_Point &target) const {
283  Float xdif = (Float)(target.X - X);
284  Float ydif = (Float)(target.Y - Y);
285  return (xdif * xdif) + (ydif * ydif);
286  }
288  Float Distance() const {
289  return std::sqrt( Float(X*X) + Float(Y*Y) );
290  }
291 
294  return Float(X * X) + Float(Y * Y);
295  }
297  Float ManhattanDistance(const basic_Point &target) const {
298  return (Float)(std::abs(X-target.X) + std::abs(Y-target.Y));
299  }
300 
303  return (Float)(std::abs(X) + std::abs(Y));
304  }
305 
308  return (*this)/Distance();
309  }
310 
313  return {-Y, X};
314  }
315 
320  Float Angle(const basic_Point &origin) const {
321  return (Float)atan2(Y-origin.Y, X-origin.X);
322  }
323 
327  Float Angle() const {
328  return (Float)atan2(Y, X);
329  }
330 
334  Float Slope(const basic_Point &point) const {
335  return (Float)(Y-point.Y)/(X-point.X);
336  }
337 
340  Float Slope() const {
341  return (Float)Y/X;
342  }
343 
345  bool Compare(const basic_Point &point) const {
346  return X==point.X && Y==point.Y;
347  }
348 
350  bool operator == (const basic_Point &point) const {
351  return Compare(point);
352  }
353 
355  bool operator !=(const basic_Point &point) const {
356  return !Compare(point);
357  }
358 
360  void Move(const T_ &x, const T_ &y) {
361  X=x;
362  Y=y;
363  }
364 
365  union {
366  struct {
368  T_ X;
369 
371  T_ Y;
372  };
373 
375  T_ Vector[2];
376  };
377 
378  };
379 
382  template <class T_>
383  std::ostream &operator << (std::ostream &out, const basic_Point<T_> &point) {
384  out<<"("<<point.X<<", "<<point.Y<<")";
385 
386  return out;
387  }
388 
389 
394  template <class T_>
395  std::istream &operator >> (std::istream &in, basic_Point<T_> &point) {
396  while(in.peek()==' ' || in.peek()=='\t')
397  in.ignore(1);
398 
399  bool par=false;
400  if(in.peek()=='(') {
401  par=true;
402  in.ignore(1);
403  }
404 
405  std::string s;
406 
407  while(in.peek()!=',' && !in.eof())
408  s.push_back((char)in.get());
409 
410  if(in.eof()) {
411  in.setstate(in.failbit);
412  return in;
413  }
414  in.ignore(1);
415 
416  auto x = String::To<T_>(s);
417 
418  s="";
419 
420  while(in.peek()==' ' || in.peek()=='\t')
421  in.ignore(1);
422 
423  while(in.peek()!=')' && in.peek()!=' ' && in.peek()!='\t' && in.peek()!='\n' && in.peek()!='\r' && !in.eof())
424  s.push_back(in.get());
425 
426  if(in.bad()) return in;
427 
428  point.X = x;
429  point.Y = String::To<T_>(s);
430 
431  if(par) {
432  while(in.peek()==' ' || in.peek()=='\t')
433  in.ignore(1);
434  }
435 
436  if(in.peek()==')')
437  in.ignore(1);
438 
439  return in;
440  }
441 
442 
444  template<class T_, class O_>
445  void Translate(basic_Point<T_> &point, O_ x, O_ y) {
446  point.X=T_(point.X+x);
447  point.Y=T_(point.Y+y);
448  }
449 
451  template<class T_>
452  void Translate(basic_Point<T_> &point, const basic_Point<T_> &other) {
453  point.X+=other.X;
454  point.Y+=other.Y;
455  }
456 
458  template <class T_, class O_>
459  void Scale(basic_Point<T_> &point, const O_ &size) {
460  point.X = T_(point.X*size);
461  point.Y = T_(point.Y*size);
462  }
463 
465  template <class T_, class O1_, class O2_>
466  void Scale(basic_Point<T_> &point, const O1_ &sizex, const O2_ &sizey) {
467  point.X = T_(point.X*sizex);
468  point.Y = T_(point.Y*sizey);
469  }
470 
473  template <class T_, class O_>
474  void Scale(basic_Point<T_> &point, const O_ &size, const basic_Point<T_> &origin) {
475  point.X = T_((point.X-origin.X)*size+origin.X);
476  point.Y = T_((point.Y-origin.Y)*size+origin.Y);
477  }
478 
481  template <class T_, class O1_, class O2_>
482  void Scale(basic_Point<T_> &point, const O1_ &sizex, const O2_ &sizey, const basic_Point<T_> &origin) {
483  point.X = T_((point.X-origin.X)*sizex+origin.X);
484  point.Y = T_((point.Y-origin.Y)*sizey+origin.Y);
485  }
486 
487 
491  template<class T_>
492  void Rotate(basic_Point<T_> &point, Float angle) {
493  T_ new_x;
494  Float cosa=std::cos(angle), sina=std::sin(angle);
495  new_x = T_(point.X*cosa - point.Y*sina);
496  point.Y = T_(point.X*sina + point.Y*cosa);
497 
498  point.X = new_x;
499  }
500 
505  template<class T_>
506  void Rotate(basic_Point<T_> &point, Float angle, const basic_Point<T_> &origin) {
507  Float cosa=std::cos(angle), sina=std::sin(angle);
508 
509  basic_Point<T_> temp=point-origin;
510 
511  point.X = T_(temp.X*cosa - temp.Y*sina);
512  point.Y = T_(temp.X*sina + temp.Y*cosa);
513 
514  point += origin;
515  }
516 
520  template <class T_, class O_>
521  void SkewX(basic_Point<T_> &point, const O_ &rate) {
522  point.X += T_(point.Y*rate);
523  }
524 
528  template <class T_, class O_>
529  void SkewY(basic_Point<T_> &point, const O_ &rate) {
530  point.Y += T_(point.X*rate);
531  }
532 
536  template <class T_, class O_>
537  void SkewX(basic_Point<T_> &point, const O_ &rate, const basic_Point<T_> &origin) {
538  point.X += T_((point.Y-origin.Y)*rate);
539  }
540 
544  template <class T_, class O_>
545  void SkewY(basic_Point<T_> &point, const O_ &rate, const basic_Point<T_> &origin) {
546  point.Y += T_((point.X-origin.X)*rate);
547  }
548 
550  template<class T_>
551  void ReflectX(basic_Point<T_> &point) {
552  point.Y = -point.Y;
553  }
554 
556  template<class T_>
557  void ReflectY(basic_Point<T_> &point) {
558  point.X = -point.X;
559  }
560 
562  template<class T_>
564  ReflectX(point);
565  }
566 
568  template<class T_>
570  ReflectY(point);
571  }
572 
574  template<class T_>
575  void ReflectX(basic_Point<T_> &point, const basic_Point<T_> &origin) {
576  point.Y = -point.Y+origin.Y*2;
577  }
578 
580  template<class T_>
581  void ReflectY(basic_Point<T_> &point, const basic_Point<T_> &origin) {
582  point.X = -point.X+origin.X*2;
583  }
584 
586  template<class T_>
587  void HorizontalMirror(basic_Point<T_> &point, const basic_Point<T_> &origin) {
588  ReflectX(point, origin);
589  }
590 
592  template<class T_>
593  void VerticalMirror(basic_Point<T_> &point, const basic_Point<T_> &origin) {
594  ReflectY(point, origin);
595  }
596 
599 
602 
604  inline Pointf Round(Pointf num) {
605  return{
606  std::floor(num.X+Float(0.5)),
607  std::floor(num.Y+Float(0.5))
608  };
609  }
610 
611  }
612 }
Gorgon::Geometry::basic_Point::Normalize
basic_Point Normalize() const
Normalizes the point as a unit vector.
Definition: Point.h:307
Gorgon::Geometry::SkewY
void SkewY(basic_Bounds< T_ > &bounds, const O_ &rate)
Skews the given bounds with the given rate along Y axis.
Definition: Bounds.h:675
Gorgon::String::From
std::enable_if< decltype(gorgon__enum_tr_loc(T_()))::isupgradedenum, std::string >::type From(const T_ &e)
Definition: Enum.h:303
Gorgon::Geometry::basic_Point::operator=
basic_Point & operator=(const basic_Point< O_ > &point)
Assignment from a different point type.
Definition: Point.h:85
Gorgon::Geometry::basic_Point::operator-=
basic_Point & operator-=(const basic_Point &point)
Subtracts another point from this point.
Definition: Point.h:230
Gorgon::Geometry::basic_Point::Angle
Float Angle() const
Calculates the angle of the line formed from the origin to this point.
Definition: Point.h:327
Gorgon::Geometry::Round
Pointf Round(Pointf num)
Performs a rounding operation over a floating point point.
Definition: Point.h:604
Gorgon::Geometry::ReflectX
void ReflectX(basic_Point< T_ > &point)
Reflects the given point along the X axis.
Definition: Point.h:551
Gorgon::Geometry::basic_Point::basic_Point
basic_Point()
Default constructor, does not zero initialize point.
Definition: Point.h:38
Gorgon::Geometry::basic_Point::X
T_ X
X coordinate.
Definition: Point.h:368
Gorgon::Geometry::basic_Point::basic_Point
basic_Point(const std::string &str)
Conversion from string.
Definition: Point.h:48
Gorgon::Geometry::basic_Point::Move
void Move(const T_ &x, const T_ &y)
Moves this point to the given coordinates.
Definition: Point.h:360
Gorgon::Geometry::basic_Point::Angle
Float Angle(const basic_Point &origin) const
Calculates the angle of the line formed from the given point to this point.
Definition: Point.h:320
Gorgon::Geometry::basic_Point::basic_Point
basic_Point(const basic_Point< O_ > &point)
Conversion from a different point type.
Definition: Point.h:45
Gorgon::Geometry::VerticalMirror
void VerticalMirror(basic_Point< T_ > &point)
Reflects the given point vertically.
Definition: Point.h:569
Gorgon::Geometry::basic_Point::operator/
basic_Point operator/(O_ value) const
Divides this point to a scalar value.
Definition: Point.h:224
Gorgon::Float
float Float
Represents floating point data type.
Definition: Types.h:16
Gorgon::Geometry::operator>>
std::istream & operator>>(std::istream &in, basic_Bounds< T_ > &bounds)
Stream extractor for bounds.
Definition: Bounds.h:423
Gorgon::Geometry::Scale
void Scale(basic_Bounds< T_ > &bounds, const O_ &size)
Scales the given bounds by the given factor. Center of the bounds is used as origin.
Definition: Bounds.h:544
Gorgon::Geometry::basic_Point::EuclideanSquare
Float EuclideanSquare(const basic_Point &target) const
Calculates EuclideanSquare distance from this point to the given target.
Definition: Point.h:282
Gorgon::Geometry::Translate
void Translate(basic_Bounds< T_ > &bounds, O_ x, O_ y)
Translation moves the given bounds by the given amount.
Definition: Bounds.h:526
Gorgon::Geometry::basic_Point::EuclideanSquare
Float EuclideanSquare() const
Calculates EuclideanSquare distance from this point to the given target.
Definition: Point.h:293
Gorgon::String::IllegalTokenError
This error will be thrown if a parsing function encounters with an illegal token.
Definition: Exceptions.h:25
Gorgon::Geometry::basic_Point::Perpendicular
basic_Point Perpendicular() const
Calculates perpendicular vector to this point.
Definition: Point.h:312
Gorgon::Geometry::SkewX
void SkewX(basic_Bounds< T_ > &bounds, const O_ &rate)
Skews the given bounds with the given rate along X axis.
Definition: Bounds.h:658
Gorgon::Geometry::ReflectY
void ReflectY(basic_Point< T_ > &point)
Reflects the given point along the Y axis.
Definition: Point.h:557
Gorgon
Root namespace for Gorgon Game Engine.
Definition: Any.h:19
Gorgon::Geometry::basic_Point::CrossProduct
T_ CrossProduct(const basic_Point< T_ > &value) const
Calculates cross product of two points.
Definition: Point.h:265
Gorgon::String::ParseError
This error will be thrown if a parsing function encounters with a general error.
Definition: Exceptions.h:10
Gorgon::Geometry::basic_Point::BaseType
T_ BaseType
Base type of the point elements.
Definition: Point.h:35
Gorgon::Geometry::basic_Point::operator*=
basic_Point & operator*=(O_ value)
Scales this point.
Definition: Point.h:248
Gorgon::Geometry::basic_Point::Distance
Float Distance() const
Calculates Euclidean distance from this point to origin.
Definition: Point.h:288
Gorgon::Geometry::basic_Point::Distance
Float Distance(const basic_Point &target) const
Calculates Euclidean distance from this point to the given target.
Definition: Point.h:276
Gorgon::Geometry::basic_Point
This class represents a 2D point.
Definition: Point.h:32
Gorgon::Geometry::basic_Point::DotProduct
T_ DotProduct(const basic_Point< T_ > &value) const
Calculates dot product of two points.
Definition: Point.h:270
Gorgon::Geometry::basic_Point::operator/=
basic_Point & operator/=(O_ value)
Scales this point.
Definition: Point.h:257
Gorgon::Geometry::basic_Point::operator+=
basic_Point & operator+=(const basic_Point &point)
Adds another point from this point.
Definition: Point.h:239
Gorgon::Geometry::basic_Point::operator+
basic_Point operator+(const basic_Point &point) const
Adds another point to this one and returns the result.
Definition: Point.h:205
Gorgon::Geometry::basic_Point::operator==
bool operator==(const basic_Point &point) const
Compares two points.
Definition: Point.h:350
Gorgon::Geometry::basic_Point::ManhattanDistance
Float ManhattanDistance(const basic_Point &target) const
Calculates Manhattan distance from this point to the given target.
Definition: Point.h:297
Gorgon::Geometry::basic_Point::Y
T_ Y
Y coordinate.
Definition: Point.h:371
Gorgon::Geometry::operator<<
std::ostream & operator<<(std::ostream &out, const basic_Bounds< T_ > &bounds)
Allows streaming of bounds.
Definition: Bounds.h:415
Gorgon::Geometry::basic_Point::Vector
T_ Vector[2]
Allows this point to be accessed as a vector.
Definition: Point.h:375
Gorgon::Geometry::basic_Point::basic_Point
basic_Point(const T_ &X, const T_ &Y)
Filling constructor.
Definition: Point.h:41
Gorgon::Geometry::basic_Point::operator!=
bool operator!=(const basic_Point &point) const
Compares two points.
Definition: Point.h:355
Gorgon::Geometry::basic_Point::operator-
basic_Point operator-() const
Negates this point.
Definition: Point.h:200
Gorgon::Geometry::basic_Point::Parse
static basic_Point Parse(const std::string &str, bool require_parenthesis=false)
Properly parses given string into a point.
Definition: Point.h:125
Gorgon::Geometry::HorizontalMirror
void HorizontalMirror(basic_Point< T_ > &point)
Reflects the given point horizontally.
Definition: Point.h:563
Gorgon::Geometry::basic_Point::Compare
bool Compare(const basic_Point &point) const
Compares two points.
Definition: Point.h:345
Gorgon::Geometry::basic_Point::operator*
basic_Point operator*(O_ value) const
Multiply this point with a scalar value.
Definition: Point.h:212
Gorgon::Geometry::basic_Point::Slope
Float Slope(const basic_Point &point) const
Calculates the slope of the line formed from the given point to this point.
Definition: Point.h:334
Gorgon::Geometry::basic_Point::ManhattanDistance
Float ManhattanDistance() const
Calculates Manhattan distance from this point to origin.
Definition: Point.h:302
Gorgon::Geometry::basic_Point::FromVector
static basic_Point FromVector(Float magnitute, Float angle, const basic_Point< O_ > &origin={0, 0})
Creates a new point from the given vector data.
Definition: Point.h:109
Gorgon::Geometry::Rotate
void Rotate(basic_Bounds< T_ > &bounds, Float angle)
Rotates the given bounds by the given angle.
Definition: Bounds.h:614
Gorgon::Geometry::basic_Point::Slope
Float Slope() const
Calculates the slope of the line formed from the origin to this point.
Definition: Point.h:340