source: cpp/common/2d.h @ 848

Last change on this file since 848 was 848, checked in by Maciej Komosinski, 6 years ago

2D operations with more granular types of arguments

  • Property svn:eol-style set to native
File size: 6.5 KB
Line 
1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
2// Copyright (C) 1999-2019  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//unification of old GUIXY and Pt2D
12template <typename T> class XY
13{
14public:
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        // allows float operations on ints
27        template <typename Q> XY operator*=(Q q) { x *= q; y *= q; return *this; }
28        template <typename Q> XY operator/=(Q q) { x /= q; y /= q; return *this; }
29        template <typename Q> XY operator/(Q q) { return XY(x / q, y / q); }
30        template <typename Q> XY operator*(Q q) const { return XY(q*x, q*y); }
31        void set(T _x, T _y) { x = _x; y = _y; }
32        void add(T _x, T _y) { x += _x; y += _y; }
33        void sub(T _x, T _y) { x -= _x; y -= _y; }
34        bool operator==(const XY& p) const { return (fabs(double(x - p.x)) < 1e-20) && (fabs(double(y - p.y)) < 1e-20); }
35        bool operator!=(const XY& p) const { return !operator==(p); }
36        T distanceTo(const XY& p) const { return sqrt(double((p.x - x)*(p.x - x) + (p.y - y)*(p.y - y))); }
37        T magnitude() const { return sqrt(x*x + y * y); }
38        T length() const { return sqrt(x*x + y * y); }
39        T lengthSq() const { return x * x + y * y; }
40        T dotProduct(const XY& v) const { return x * v.x + y * v.y; }
41        T crossProduct(const XY& v) const { return x * v.y - y * v.x; }
42        void normalize() { operator/=(length()); } // length becomes 1
43        static XY average(const XY& v1, const XY& v2) { return XY((v1.x + v2.x)*0.5, (v1.y + v2.y)*0.5); }
44        double getDirection() const { return atan2(y, x); }
45        static XY interpolate(const XY& v1, const XY& v2, double t) { return v1 + (v2 - v1)*t; }
46        XY toInt() const { return XY(int(x), int(y)); }
47        XY transpose() const { return XY(y, x); }
48        static const XY& zero() { static XY t(0, 0); return t; }
49        static const XY& one() { static XY t(1, 1); return t; }
50};
51
52//specialized: int equality not using fabs()
53template<> inline bool XY<int>::operator==(const XY<int>& p) const { return (x == p.x) && (y == p.y); }
54
55template <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)); }
56template <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)); }
57
58template <typename T>
59class XYMargin
60{
61public:
62        XYMargin(T x = 0) :left(x), top(x), right(x), bottom(x) {}
63        XYMargin(T l, T t, T r, T b) :left(l), top(t), right(r), bottom(b) {}
64        T left, top, right, bottom;
65        void operator=(T x) { left = top = right = bottom = x; }
66        XYMargin operator-() const { return XYMargin(-left, -top, -right, -bottom); }
67        void operator=(const XYMargin<T> &other) { left = other.left; top = other.top; right = other.right; bottom = other.bottom; }
68        T horizontal() const { return left + right; }
69        T vertical() const { return top + bottom; }
70        bool operator==(const XYMargin &other) const { return left == other.left && top == other.top && right == other.right && bottom == other.bottom; }
71        XYMargin normalized() const { return XYMargin(max(left, T(0)), max(top, T(0)), max(right, T(0)), max(bottom, T(0))); }
72};
73
74template <typename T>
75class XYRect
76{
77public:
78        XY<T> p, size;
79        XYRect() {}
80        XYRect(const XY<T>& p1, const XY<T>& s) :p(p1), size(s) {}
81        template <typename Q> XYRect(const Q& other) : p(other.p), size(other.size) {}
82        XYRect(T _x, T _y, T _w, T _h) :p(_x, _y), size(_w, _h) {}
83        static XYRect<T> centeredAt(const XY<T>& p, XY<T> s) { return XYRect<T>(p - s * 0.5, s); }
84
85        bool isEmpty() const { return (size.x < 0) || (size.y < 0); }
86        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)); }
87        bool operator==(const XYRect& r) const { return (p == r.p) && (size == r.size); }
88        template <typename Q> const XYRect& operator=(const Q& other) { p = other.p; size = other.size; return *this; }
89
90        bool intersects(const XYRect& r) const
91        {
92                if (r.p.x >= (p.x + size.x)) return false;
93                if (r.p.y >= (p.y + size.y)) return false;
94                if ((r.p.x + r.size.x) <= p.x) return false;
95                if ((r.p.y + r.size.y) <= p.y) return false;
96                return true;
97        }
98
99        bool contains(const XY<T>& n) const
100        {
101                if (n.x < p.x) return false;
102                if (n.x > (p.x + size.x)) return false;
103                if (n.y < p.y) return false;
104                if (n.y > (p.y + size.y)) return false;
105                return true;
106        }
107
108        void add(const XY<T>& n)
109        {
110                if (n.x < p.x) { size.x += p.x - n.x; p.x = n.x; }
111                else if (n.x > (p.x + size.x)) size.x = n.x - p.x;
112                if (n.y < p.y) { size.y += p.y - n.y; p.y = n.y; }
113                else if (n.y > (p.y + size.y)) size.y = n.y - p.y;
114        }
115
116        XYRect extendBy(const XY<T>& border_size) const
117        {
118                return XYRect(p - border_size, size + border_size * 2);
119        }
120
121        XYRect shrinkBy(const XY<T>& border_size) const
122        {
123                return XYRect(p + border_size, size - border_size * 2);
124        }
125
126        XYRect extendBy(const XYMargin<T>& m) const
127        {
128                return XYRect(p.x - m.left, p.y - m.top, size.x + m.horizontal(), size.y + m.vertical());
129        }
130
131        XYRect shrinkBy(const XYMargin<T>& m) const
132        {
133                return XYRect(p.x + m.left, p.y + m.top, size.x - m.horizontal(), size.y - m.vertical());
134        }
135
136        XYMargin<T> marginTowards(const XYRect &r) const
137        {
138                return XYMargin<T>(r.p.x - p.x, r.p.y - p.y,
139                        (p.x + size.x) - (r.p.x + r.size.x), (p.y + size.y) - (r.p.y + r.size.y));
140        }
141
142        XYRect intersection(const XYRect& r) const
143        {
144                XYRect i;
145                XY<T> p2 = p + size;
146                XY<T> rp2 = r.p + r.size;
147                i.p.x = max(p.x, r.p.x);
148                i.p.y = max(p.y, r.p.y);
149                i.size.x = min(p2.x, rp2.x) - i.p.x;
150                i.size.y = min(p2.y, rp2.y) - i.p.y;
151                return i;
152        }
153
154        XYRect translation(const XY<T>& t) const
155        {
156                return XYRect(p + t, size);
157        }
158
159        T distanceTo(const XY<T>& n) const
160        {
161                XY<T> tp = n;
162                if (n.x < p.x) tp.x = p.x; else if (n.x >= (p.x + size.x)) tp.x = p.x + size.x;
163                if (n.y < p.y) tp.y = p.y; else if (n.y >= (p.y + size.y)) tp.y = p.y + size.y;
164                return tp.distanceTo(n);
165        }
166
167        static const XYRect& zero() { static XYRect t(0, 0, 0, 0); return t; }
168        static const XYRect& one() { static XYRect t(0, 0, 1, 1); return t; }
169};
170
171typedef XY<int> IntXY;
172typedef XYRect<int> IntRect;
173
174#endif
Note: See TracBrowser for help on using the repository browser.