1 | // SuperTux |
2 | // Copyright (C) 2006 Matthias Braun <matze@braunis.de> |
3 | // |
4 | // This program is free software: you can redistribute it and/or modify |
5 | // it under the terms of the GNU General Public License as published by |
6 | // the Free Software Foundation, either version 3 of the License, or |
7 | // (at your option) any later version. |
8 | // |
9 | // This program is distributed in the hope that it will be useful, |
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | // GNU General Public License for more details. |
13 | // |
14 | // You should have received a copy of the GNU General Public License |
15 | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 | |
17 | #ifndef HEADER_SUPERTUX_MATH_RECTF_HPP |
18 | #define |
19 | |
20 | #include <assert.h> |
21 | #include <iosfwd> |
22 | |
23 | #include "math/anchor_point.hpp" |
24 | #include "math/sizef.hpp" |
25 | #include "math/vector.hpp" |
26 | |
27 | class Rect; |
28 | |
29 | class Rectf final |
30 | { |
31 | public: |
32 | static Rectf from_center(const Vector& center, const Sizef& size) |
33 | { |
34 | return Rectf(center.x - size.width / 2.0f, |
35 | center.y - size.height / 2.0f, |
36 | center.x + size.width / 2.0f, |
37 | center.y + size.height / 2.0f); |
38 | } |
39 | |
40 | public: |
41 | Rectf() : |
42 | m_p1(), |
43 | m_size() |
44 | { } |
45 | |
46 | Rectf(const Rectf& rhs) = default; |
47 | Rectf& operator=(const Rectf& rhs) = default; |
48 | |
49 | Rectf(const Vector& np1, const Vector& np2) : |
50 | m_p1(np1), m_size(np2.x - np1.x, np2.y - np1.y) |
51 | { |
52 | } |
53 | |
54 | Rectf(float x1, float y1, float x2, float y2) : |
55 | m_p1(x1, y1), m_size(x2 - x1, y2 - y1) |
56 | { |
57 | assert(m_size.width >= 0 && |
58 | m_size.height >= 0); |
59 | } |
60 | |
61 | Rectf(const Vector& p1, const Sizef& size) : |
62 | m_p1(p1), |
63 | m_size(size) |
64 | { |
65 | } |
66 | |
67 | Rectf(const Rect& rect); |
68 | |
69 | bool operator==(const Rectf& other) const |
70 | { |
71 | return (m_p1 == other.m_p1 && |
72 | m_size == other.m_size); |
73 | } |
74 | |
75 | // This is a temporary hack to pass x/y to ReaderMapping |
76 | float& get_left() { return m_p1.x; } |
77 | float& get_top() { return m_p1.y; } |
78 | |
79 | float get_left() const { return m_p1.x; } |
80 | float get_right() const { return m_p1.x + m_size.width; } |
81 | float get_top() const { return m_p1.y; } |
82 | float get_bottom() const { return m_p1.y + m_size.height; } |
83 | |
84 | float get_width() const { return m_size.width; } |
85 | float get_height() const { return m_size.height; } |
86 | |
87 | void set_left(float v) { m_size.width -= v - m_p1.x; m_p1.x = v; } |
88 | void set_right(float v) { m_size.width += v - get_right(); } |
89 | |
90 | void set_top(float v) { m_size.height -= v - m_p1.y; m_p1.y = v; } |
91 | void set_bottom(float v) { m_size.height += v - get_bottom(); } |
92 | |
93 | Vector get_middle() const { return Vector(m_p1.x + m_size.width / 2.0f, |
94 | m_p1.y + m_size.height / 2.0f); } |
95 | |
96 | void set_pos(const Vector& v) { m_p1 = v; } |
97 | |
98 | void set_width(float width) { m_size.width = width; } |
99 | void set_height(float height) { m_size.height = height; } |
100 | void set_size(float width, float height) { m_size = Sizef(width, height); } |
101 | Sizef get_size() const { return m_size; } |
102 | |
103 | void move(const Vector& v) { m_p1 += v; } |
104 | Rectf moved(const Vector& v) const { return Rectf(m_p1 + v, m_size); } |
105 | |
106 | bool contains(const Vector& v) const { |
107 | return v.x >= m_p1.x && v.y >= m_p1.y && v.x < get_right() && v.y < get_bottom(); |
108 | } |
109 | |
110 | bool contains(const Rectf& other) const |
111 | { |
112 | // FIXME: This is overlaps(), not contains()! |
113 | if (m_p1.x >= other.get_right() || other.get_left() >= get_right()) |
114 | return false; |
115 | if (m_p1.y >= other.get_bottom() || other.get_top() >= get_bottom()) |
116 | return false; |
117 | |
118 | return true; |
119 | } |
120 | |
121 | float distance (const Vector& other, AnchorPoint ap = ANCHOR_MIDDLE) const |
122 | { |
123 | Vector v = get_anchor_pos (*this, ap); |
124 | return ((v - other).norm ()); |
125 | } |
126 | |
127 | float distance (const Rectf& other, AnchorPoint ap = ANCHOR_MIDDLE) const |
128 | { |
129 | Vector v1 = get_anchor_pos(*this, ap); |
130 | Vector v2 = get_anchor_pos(other, ap); |
131 | |
132 | return ((v1 - v2).norm ()); |
133 | } |
134 | |
135 | Rectf grown(float border) const |
136 | { |
137 | return Rectf(m_p1.x - border, m_p1.y - border, |
138 | get_right() + border, get_bottom() + border); |
139 | } |
140 | |
141 | // leave these two public to save the headaches of set/get functions for such |
142 | // simple things :) |
143 | |
144 | Vector p1() const { return m_p1; } |
145 | Vector p2() const { return Vector(m_p1.x + m_size.width, m_p1.y + m_size.height); } |
146 | |
147 | void set_p1(const Vector& p) { |
148 | m_size = Sizef(m_size.width + (m_p1.x - p.x), |
149 | m_size.height + (m_p1.y - p.y)); |
150 | m_p1 = p; |
151 | } |
152 | void set_p2(const Vector& p) { |
153 | m_size = Sizef(p.x - m_p1.x, |
154 | p.y - m_p1.y); |
155 | } |
156 | |
157 | private: |
158 | /// upper left edge |
159 | Vector m_p1; |
160 | Sizef m_size; |
161 | }; |
162 | |
163 | std::ostream& operator<<(std::ostream& out, const Rectf& rect); |
164 | |
165 | #endif |
166 | |
167 | /* EOF */ |
168 | |