rect.h

main 344 lines · 12.1 KB Raw
Alex Alex Commit Client Upload Part 2 19/10/2026 00:06
1/*
2 * Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#ifndef RECT_H
24#define RECT_H
25
26#include "../stdext/types.h"
27#include "../const.h"
28#include <sstream>
29
30template<class T>
31class TPoint;
32
33template<class T>
34class TSize;
35
36template<class T>
37class TRect
38{
39public:
40 TRect() : x1(0), y1(0), x2(-1), y2(-1) { }
41 TRect(T x, T y, T width, T height) : x1(x), y1(y), x2(x+width-1), y2(y+height-1) { }
42 TRect(const TPoint<T>& topLeft, const TPoint<T>& bottomRight) : x1(topLeft.x), y1(topLeft.y), x2(bottomRight.x), y2(bottomRight.y) { }
43 TRect(const TRect<T>& other) : x1(other.x1), y1(other.y1), x2(other.x2), y2(other.y2) { }
44 TRect(T x, T y, const TSize<T>& size) : x1(x), y1(y), x2(x+size.width()-1), y2(y+size.height()-1) { }
45 TRect(const TPoint<T>& topLeft, const TSize<T>& size) : x1(topLeft.x), y1(topLeft.y), x2(x1+size.width()-1), y2(y1+size.height()-1) { }
46 TRect(const TPoint<T>& topLeft, int width, int height) : x1(topLeft.x), y1(topLeft.y), x2(x1+width-1), y2(y1+height-1) { }
47
48 bool isNull() const { return x2 == x1 - 1 && y2 == y1 - 1; }
49 bool isEmpty() const { return x1 > x2 || y1 > y2; }
50 bool isValid() const { return x1 <= x2 && y1 <= y2; }
51
52 inline T left() const { return x1; }
53 inline T top() const { return y1; }
54 inline T right() const { return x2; }
55 inline T bottom() const { return y2; }
56 inline T horizontalCenter() const { return x1 + (x2 - x1)/2; }
57 inline T verticalCenter() const { return y1 + (y2 - y1)/2; }
58 inline T x() const { return x1; }
59 inline T y() const { return y1; }
60 TPoint<T> topLeft() const { return TPoint<T>(x1, y1); }
61 TPoint<T> bottomRight() const { return TPoint<T>(x2, y2); }
62 TPoint<T> topRight() const { return TPoint<T>(x2, y1); }
63 TPoint<T> bottomLeft() const { return TPoint<T>(x1, y2); }
64 TPoint<T> topCenter() const { return TPoint<T>((x1+x2)/2, y1); }
65 TPoint<T> bottomCenter() const { return TPoint<T>((x1+x2)/2, y2); }
66 TPoint<T> centerLeft() const { return TPoint<T>(x1, (y1+y2)/2); }
67 TPoint<T> centerRight() const { return TPoint<T>(x2, (y1+y2)/2); }
68 TPoint<T> center() const { return TPoint<T>((x1+x2)/2, (y1+y2)/2); }
69 T width() const { return x2 - x1 + 1; }
70 T height() const { return y2 - y1 + 1; }
71 TSize<T> size() const { return TSize<T>(width(), height()); }
72 void reset() { x1 = y1 = 0; x2 = y2 = -1; }
73 void clear() { x2 = x1 - 1; y2 = y1 - 1; }
74
75 void setLeft(T pos) { x1 = pos; }
76 void setTop(T pos) { y1 = pos; }
77 void setRight(T pos) { x2 = pos; }
78 void setBottom(T pos) { y2 = pos; }
79 void setX(T x) { x1 = x; }
80 void setY(T y) { y1 = y; }
81 void setTopLeft(const TPoint<T> &p) { x1 = p.x; y1 = p.y; }
82 void setBottomRight(const TPoint<T> &p) { x2 = p.x; y2 = p.y; }
83 void setTopRight(const TPoint<T> &p) { x2 = p.x; y1 = p.y; }
84 void setBottomLeft(const TPoint<T> &p) { x1 = p.x; y2 = p.y; }
85 void setWidth(T width) { x2 = x1 + width - 1; }
86 void setHeight(T height) { y2 = y1 + height- 1; }
87 void setSize(const TSize<T>& size) { x2 = x1 + size.width() - 1; y2 = y1 + size.height() - 1; }
88 void setRect(T x, T y, T width, T height) { x1 = x; y1 = y; x2 = (x + width - 1); y2 = (y + height - 1); }
89 void setCoords(int left, int top, int right, int bottom) { x1 = left; y1 = top; x2 = right; y2 = bottom; }
90
91 void expandLeft(T add) { x1 -= add; }
92 void expandTop(T add) { y1 -= add; }
93 void expandRight(T add) { x2 += add; }
94 void expandBottom(T add) { y2 += add; }
95 void expand(T top, T right, T bottom, T left) { x1 -= left; y1 -= top; x2 += right; y2 += bottom; }
96 void expand(T add) { x1 -= add; y1 -= add; x2 += add; y2 += add; }
97
98 void translate(T x, T y) { x1 += x; y1 += y; x2 += x; y2 += y; }
99 void translate(const TPoint<T> &p) { x1 += p.x; y1 += p.y; x2 += p.x; y2 += p.y; }
100 void resize(const TSize<T>& size) { x2 = x1 + size.width() - 1; y2 = y1 + size.height() - 1; }
101 void resize(T width, T height) { x2 = x1 + width - 1; y2 = y1 + height - 1; }
102 void move(T x, T y) { x2 += x - x1; y2 += y - y1; x1 = x; y1 = y; }
103 void move(const TPoint<T> &p) { x2 += p.x - x1; y2 += p.y - y1; x1 = p.x; y1 = p.y; }
104 void moveLeft(T pos) { x2 += (pos - x1); x1 = pos; }
105 void moveTop(T pos) { y2 += (pos - y1); y1 = pos; }
106 void moveRight(T pos) { x1 += (pos - x2); x2 = pos; }
107 void moveBottom(T pos) { y1 += (pos - y2); y2 = pos; }
108 void moveTopLeft(const TPoint<T> &p) { moveLeft(p.x); moveTop(p.y); }
109 void moveBottomRight(const TPoint<T> &p) { moveRight(p.x); moveBottom(p.y); }
110 void moveTopRight(const TPoint<T> &p) { moveRight(p.x); moveTop(p.y); }
111 void moveBottomLeft(const TPoint<T> &p) { moveLeft(p.x); moveBottom(p.y); }
112 void moveTopCenter(const TPoint<T> &p) { moveHorizontalCenter(p.x); moveTop(p.y); }
113 void moveBottomCenter(const TPoint<T> &p) { moveHorizontalCenter(p.x); moveBottom(p.y); }
114 void moveCenterLeft(const TPoint<T> &p) { moveLeft(p.x); moveVerticalCenter(p.y); }
115 void moveCenterRight(const TPoint<T> &p) { moveRight(p.x); moveVerticalCenter(p.y); }
116
117 TRect<T> translated(int x, int y) const { return TRect<T>(TPoint<T>(x1 + x, y1 + y), TPoint<T>(x2 + x, y2 + y)); }
118 TRect<T> translated(const TPoint<T> &p) const { return TRect<T>(TPoint<T>(x1 + p.x, y1 + p.y), TPoint<T>(x2 + p.x, y2 + p.y)); }
119
120 TRect<T> expanded(T add) const { return TRect<T>(TPoint<T>(x1 - add, y1 - add), TPoint<T>(x2 + add, y2 + add)); }
121
122 void moveCenter(const TPoint<T> &p) {
123 T w = x2 - x1;
124 T h = y2 - y1;
125 x1 = p.x - w/2;
126 y1 = p.y - h/2;
127 x2 = x1 + w;
128 y2 = y1 + h;
129 }
130 void moveHorizontalCenter(T x) {
131 T w = x2 - x1;
132 x1 = x - w/2;
133 x2 = x1 + w;
134 }
135 void moveVerticalCenter(T y) {
136 T h = y2 - y1;
137 y1 = y - h/2;
138 y2 = y1 + h;
139 }
140
141 bool contains(const TPoint<T> &p, bool insideOnly = false) const {
142 T l, r;
143 if(x2 < x1 - 1) {
144 l = x2;
145 r = x1;
146 } else {
147 l = x1;
148 r = x2;
149 }
150 if(insideOnly) {
151 if(p.x <= l || p.x >= r)
152 return false;
153 } else {
154 if(p.x < l || p.x > r)
155 return false;
156 }
157 T t, b;
158 if(y2 < y1 - 1) {
159 t = y2;
160 b = y1;
161 } else {
162 t = y1;
163 b = y2;
164 }
165 if(insideOnly) {
166 if(p.y <= t || p.y >= b)
167 return false;
168 } else {
169 if(p.y < t || p.y > b)
170 return false;
171 }
172 return true;
173 }
174
175 bool contains(const TRect<T> &r, bool insideOnly = false) const {
176 if(contains(r.topLeft(), insideOnly) && contains(r.bottomRight(), insideOnly))
177 return true;
178 return false;
179 }
180
181 bool intersects(const TRect<T> &r) const {
182 if(isNull() || r.isNull())
183 return false;
184
185 int l1 = x1;
186 int r1 = x1;
187 if(x2 - x1 + 1 < 0)
188 l1 = x2;
189 else
190 r1 = x2;
191
192 int l2 = r.x1;
193 int r2 = r.x1;
194 if(r.x2 - r.x1 + 1 < 0)
195 l2 = r.x2;
196 else
197 r2 = r.x2;
198
199 if(l1 > r2 || l2 > r1)
200 return false;
201
202 int t1 = y1;
203 int b1 = y1;
204 if(y2 - y1 + 1 < 0)
205 t1 = y2;
206 else
207 b1 = y2;
208
209 int t2 = r.y1;
210 int b2 = r.y1;
211 if(r.y2 - r.y1 + 1 < 0)
212 t2 = r.y2;
213 else
214 b2 = r.y2;
215
216 if(t1 > b2 || t2 > b1)
217 return false;
218
219 return true;
220 }
221
222 TRect<T> united(const TRect<T> &r) const {
223 TRect<T> tmp;
224 tmp.x1 = std::min<T>(x1, r.x1);
225 tmp.x2 = std::max<T>(x2, r.x2);
226 tmp.y1 = std::min<T>(y1, r.y1);
227 tmp.y2 = std::max<T>(y2, r.y2);
228 return tmp;
229 }
230
231 TRect<T> intersection(const TRect<T> &r) const {
232 if(isNull())
233 return r;
234 if(r.isNull())
235 return *this;
236
237 int l1 = x1;
238 int r1 = x1;
239 if(x2 - x1 + 1 < 0)
240 l1 = x2;
241 else
242 r1 = x2;
243
244 int l2 = r.x1;
245 int r2 = r.x1;
246 if(r.x2 - r.x1 + 1 < 0)
247 l2 = r.x2;
248 else
249 r2 = r.x2;
250
251 int t1 = y1;
252 int b1 = y1;
253 if(y2 - y1 + 1 < 0)
254 t1 = y2;
255 else
256 b1 = y2;
257
258 int t2 = r.y1;
259 int b2 = r.y1;
260 if(r.y2 - r.y1 + 1 < 0)
261 t2 = r.y2;
262 else
263 b2 = r.y2;
264
265 TRect<T> tmp;
266 tmp.x1 = std::max<int>(l1, l2);
267 tmp.x2 = std::min<int>(r1, r2);
268 tmp.y1 = std::max<int>(t1, t2);
269 tmp.y2 = std::min<int>(b1, b2);
270 return tmp;
271 }
272
273 void bind(const TRect<T> &r) {
274 if(isNull() || r.isNull())
275 return;
276
277 if(right() > r.right())
278 moveRight(r.right());
279 if(bottom() > r.bottom())
280 moveBottom(r.bottom());
281 if(left() < r.left())
282 moveLeft(r.left());
283 if(top() < r.top())
284 moveTop(r.top());
285 }
286
287 void alignIn(const TRect<T> &r, Fw::AlignmentFlag align) {
288 if(align == Fw::AlignTopLeft)
289 moveTopLeft(r.topLeft());
290 else if(align == Fw::AlignTopRight)
291 moveTopRight(r.topRight());
292 else if(align == Fw::AlignTopCenter)
293 moveTopCenter(r.topCenter());
294 else if(align == Fw::AlignBottomLeft)
295 moveBottomLeft(r.bottomLeft());
296 else if(align == Fw::AlignBottomRight)
297 moveBottomRight(r.bottomRight());
298 else if(align == Fw::AlignBottomCenter)
299 moveBottomCenter(r.bottomCenter());
300 else if(align == Fw::AlignLeftCenter)
301 moveCenterLeft(r.centerLeft());
302 else if(align == Fw::AlignCenter)
303 moveCenter(r.center());
304 else if(align == Fw::AlignRightCenter)
305 moveCenterRight(r.centerRight());
306 }
307
308 TRect<T>& operator=(const TRect<T>& other) { x1 = other.x1; y1 = other.y1; x2 = other.x2; y2 = other.y2; return *this; }
309 bool operator==(const TRect<T>& other) const { return (x1 == other.x1 && y1 == other.y1 && x2 == other.x2 && y2 == other.y2); }
310 bool operator!=(const TRect<T>& other) const { return (x1 != other.x1 || y1 != other.y1 || x2 != other.x2 || y2 != other.y2); }
311
312 TRect<T>& operator|=(const TRect<T>& other) { *this = united(other); return *this; }
313 TRect<T>& operator&=(const TRect<T>& other) { *this = intersection(other); return *this; }
314
315 TRect<T> operator+(TPoint<T> other) const { return translated(other); }
316 TRect<T>& operator+=(TPoint<T> other) { x1 += other.x; x2 += other.x; y1 += other.y; y2 += other.y; return *this; }
317
318 TRect<T> operator*(float num) const { return TRect<T>(x1 * num, y1 * num, (x2 - x1) * num, (y2 - y1) * num); }
319
320private:
321 T x1, y1, x2, y2;
322};
323
324typedef TRect<int> Rect;
325typedef TRect<float> RectF;
326
327template<class T>
328std::ostream& operator<<(std::ostream& out, const TRect<T>& rect)
329{
330 out << rect.left() << " " << rect.top() << " " << rect.width() << " " << rect.height();
331 return out;
332}
333
334template<class T>
335std::istream& operator>>(std::istream& in, TRect<T>& rect)
336{
337 T x, y , w, h;
338 in >> x >> y >> w >> h;
339 rect.setRect(x,y,w,h);
340 return in;
341}
342
343#endif
344
Top