1 | // This file is a part of Framsticks SDK. http://www.framsticks.com/ |
---|
2 | // Copyright (C) 1999-2015 Maciej Komosinski and Szymon Ulatowski. |
---|
3 | // See LICENSE.txt for details. |
---|
4 | |
---|
5 | #ifndef _2D_H_ |
---|
6 | #define _2D_H_ |
---|
7 | |
---|
8 | #include "nonstd_stl.h" |
---|
9 | #include <math.h> |
---|
10 | |
---|
11 | //unifikacja starych GUIXY i Pt2D |
---|
12 | template <typename T> class XY |
---|
13 | { |
---|
14 | public: |
---|
15 | T x,y; |
---|
16 | XY() {} |
---|
17 | XY(T _x,T _y):x(_x),y(_y) {} |
---|
18 | template <typename Q> XY(const Q& other):x(other.x),y(other.y) {} |
---|
19 | template <typename Q> const XY& operator=(const Q& other) {x=other.x; y=other.y; return *this;} |
---|
20 | template <typename Q> const XY operator()(const Q& other) {return XY(other.x,other.y);} |
---|
21 | XY operator+(const XY&p) const {return XY(x+p.x,y+p.y);} |
---|
22 | XY operator-(const XY&p) const {return XY(x-p.x,y-p.y);} |
---|
23 | XY operator+=(const XY&p) {x+=p.x; y+=p.y; return *this;} |
---|
24 | XY operator-=(const XY&p) {x-=p.x; y-=p.y; return *this;} |
---|
25 | XY operator-() const {return XY(-x,-y);} |
---|
26 | XY operator*=(T q) {x*=q; y*=q; return *this;} |
---|
27 | XY operator/=(T q) {x/=q; y/=q; return *this;} |
---|
28 | XY operator/(T q) {return XY(x/q,y/q);} |
---|
29 | XY operator*(T q) const {return XY(q*x,q*y);} |
---|
30 | void set(T _x,T _y) {x=_x; y=_y;} |
---|
31 | void add(T _x,T _y) {x+=_x; y+=_y;} |
---|
32 | void sub(T _x,T _y) {x-=_x; y-=_y;} |
---|
33 | bool operator==(const XY& p) const {return (fabs(double(x-p.x))<1e-20)&&(fabs(double(y-p.y))<1e-20);} |
---|
34 | T distanceTo(const XY& p) const {return sqrt(double((p.x-x)*(p.x-x)+(p.y-y)*(p.y-y)));} |
---|
35 | T magnitude() const {return sqrt(x*x+y*y);} |
---|
36 | T length() const {return sqrt(x*x+y*y);} |
---|
37 | T lengthSq() const { return x*x + y*y; } |
---|
38 | T dotProduct(const XY& v) const {return x*v.x + y*v.y;} |
---|
39 | T crossProduct(const XY& v) const {return x*v.y - y*v.x;} |
---|
40 | void normalize() { operator/=(length()); } // length becomes 1 |
---|
41 | static XY average(const XY& v1,const XY& v2) { return XY((v1.x+v2.x)*0.5,(v1.y+v2.y)*0.5); } |
---|
42 | double getDirection() const {return atan2(y,x);} |
---|
43 | static XY interpolate(const XY& v1, const XY& v2,double t) {return v1+(v2-v1)*t;} |
---|
44 | XY toInt() const {return XY(int(x),int(y));} |
---|
45 | static const XY& zero() {static XY t(0,0); return t;} |
---|
46 | static const XY& one() {static XY t(1,1); return t;} |
---|
47 | }; |
---|
48 | |
---|
49 | template <typename T> XY<T> xymin(const XY<T>& a, const XY<T>& b) {return XY<T>(min(a.x,b.x),min(a.y,b.y));} |
---|
50 | template <typename T> XY<T> xymax(const XY<T>& a, const XY<T>& b) {return XY<T>(max(a.x,b.x),max(a.y,b.y));} |
---|
51 | |
---|
52 | template <typename T> |
---|
53 | class XYMargin |
---|
54 | { |
---|
55 | public: |
---|
56 | XYMargin(T x=0):left(x),top(x),right(x),bottom(x) {} |
---|
57 | XYMargin(T l,T t,T r,T b):left(l),top(t),right(r),bottom(b) {} |
---|
58 | T left,top,right,bottom; |
---|
59 | void operator=(T x) {left=top=right=bottom=x;} |
---|
60 | XYMargin operator-() const {return XYMargin(-left,-top,-right,-bottom);} |
---|
61 | void operator=(const XYMargin<T> &other) {left=other.left; top=other.top; right=other.right; bottom=other.bottom;} |
---|
62 | T horizontal() const {return left+right;} |
---|
63 | T vertical() const {return top+bottom;} |
---|
64 | bool operator==(const XYMargin &other) const {return left==other.left && top==other.top && right==other.right && bottom==other.bottom;} |
---|
65 | XYMargin normalized() const {return XYMargin(max(left,T(0)),max(top,T(0)),max(right,T(0)),max(bottom,T(0)));} |
---|
66 | }; |
---|
67 | |
---|
68 | template <typename T> |
---|
69 | class XYRect |
---|
70 | { |
---|
71 | public: |
---|
72 | XY<T> p,size; |
---|
73 | XYRect() {} |
---|
74 | XYRect(const XY<T>& p1,const XY<T>& s):p(p1),size(s) {} |
---|
75 | template <typename Q> XYRect(const Q& other):p(other.p),size(other.size) {} |
---|
76 | XYRect(T _x,T _y,T _w,T _h):p(_x,_y),size(_w,_h) {} |
---|
77 | static XYRect<T> centeredAt(const XY<T>& p,XY<T> s) {return XYRect<T>(p-s*0.5,s);} |
---|
78 | |
---|
79 | bool isEmpty() const {return (size.x<0)||(size.y<0);} |
---|
80 | XYRect toInt() const {return XYRect(int(p.x),int(p.y),int(p.x+size.x)-int(p.x),int(p.y+size.y)-int(p.y));} |
---|
81 | bool operator==(const XYRect& r) const {return (p==r.p) && (size==r.size);} |
---|
82 | template <typename Q> const XYRect& operator=(const Q& other) {p=other.p; size=other.size; return *this;} |
---|
83 | |
---|
84 | bool intersects(const XYRect& r) const |
---|
85 | { |
---|
86 | if (r.p.x >= (p.x+size.x)) return false; |
---|
87 | if (r.p.y >= (p.y+size.y)) return false; |
---|
88 | if ((r.p.x+r.size.x) <= p.x) return false; |
---|
89 | if ((r.p.y+r.size.y) <= p.y) return false; |
---|
90 | return true; |
---|
91 | } |
---|
92 | |
---|
93 | bool contains(const XY<T>& n) const |
---|
94 | { |
---|
95 | if (n.x<p.x) return false; |
---|
96 | if (n.x>(p.x+size.x)) return false; |
---|
97 | if (n.y<p.y) return false; |
---|
98 | if (n.y>(p.y+size.y)) return false; |
---|
99 | return true; |
---|
100 | } |
---|
101 | |
---|
102 | void add(const XY<T>& n) |
---|
103 | { |
---|
104 | if (n.x<p.x) {size.x+=p.x-n.x; p.x=n.x;} |
---|
105 | else if (n.x>(p.x+size.x)) size.x=n.x-p.x; |
---|
106 | if (n.y<p.y) {size.y+=p.y-n.y; p.y=n.y;} |
---|
107 | else if (n.y>(p.y+size.y)) size.y=n.y-p.y; |
---|
108 | } |
---|
109 | |
---|
110 | XYRect extendBy(const XY<T>& border_size) const |
---|
111 | { |
---|
112 | return XYRect(p-border_size,size+border_size*2); |
---|
113 | } |
---|
114 | |
---|
115 | XYRect shrinkBy(const XY<T>& border_size) const |
---|
116 | { |
---|
117 | return XYRect(p+border_size,size-border_size*2); |
---|
118 | } |
---|
119 | |
---|
120 | XYRect extendBy(const XYMargin<T>& m) const |
---|
121 | { |
---|
122 | return XYRect(p.x-m.left,p.y-m.top,size.x+m.horizontal(),size.y+m.vertical()); |
---|
123 | } |
---|
124 | |
---|
125 | XYRect shrinkBy(const XYMargin<T>& m) const |
---|
126 | { |
---|
127 | return XYRect(p.x+m.left,p.y+m.top,size.x-m.horizontal(),size.y-m.vertical()); |
---|
128 | } |
---|
129 | |
---|
130 | XYMargin<T> marginTowards(const XYRect &r) const |
---|
131 | { |
---|
132 | return XYMargin<T>(r.p.x-p.x, r.p.y-p.y, |
---|
133 | (p.x+size.x)-(r.p.x+r.size.x), (p.y+size.y)-(r.p.y+r.size.y)); |
---|
134 | } |
---|
135 | |
---|
136 | XYRect intersection(const XYRect& r) const |
---|
137 | { |
---|
138 | XYRect i; |
---|
139 | XY<T> p2=p+size; |
---|
140 | XY<T> rp2=r.p+r.size; |
---|
141 | i.p.x=max(p.x,r.p.x); |
---|
142 | i.p.y=max(p.y,r.p.y); |
---|
143 | i.size.x=min(p2.x,rp2.x)-i.p.x; |
---|
144 | i.size.y=min(p2.y,rp2.y)-i.p.y; |
---|
145 | return i; |
---|
146 | } |
---|
147 | |
---|
148 | XYRect translation(const XY<T>& t) const |
---|
149 | { |
---|
150 | return XYRect(p+t,size); |
---|
151 | } |
---|
152 | |
---|
153 | T distanceTo(const XY<T>& n) const |
---|
154 | { |
---|
155 | XY<T> tp=n; |
---|
156 | if (n.x<p.x) tp.x=p.x; else if (n.x>=(p.x+size.x)) tp.x=p.x+size.x; |
---|
157 | if (n.y<p.y) tp.y=p.y; else if (n.y>=(p.y+size.y)) tp.y=p.y+size.y; |
---|
158 | return tp.distanceTo(n); |
---|
159 | } |
---|
160 | |
---|
161 | static const XYRect& zero() {static XYRect t(0,0,0,0); return t;} |
---|
162 | static const XYRect& one() {static XYRect t(0,0,1,1); return t;} |
---|
163 | }; |
---|
164 | |
---|
165 | typedef XY<int> IntXY; |
---|
166 | typedef XYRect<int> IntRect; |
---|
167 | |
---|
168 | #endif |
---|