ScummVM API documentation
geometry.h
1/* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22//=============================================================================
23//
24// Geometry data structures and helper functions
25//
26//=============================================================================
27
28#ifndef AGS_SHARED_UTIL_GEOMETRY_H
29#define AGS_SHARED_UTIL_GEOMETRY_H
30
31#include "ags/shared/util/math.h"
32
33namespace AGS3 {
34
35namespace AGSMath = AGS::Shared::Math;
36//namespace AGS
37//{
38//namespace Shared
39//{
40
41// Type of alignment of a geometric item of rectangular boundaries.
42enum FrameAlignment {
43 kAlignNone = 0,
44
45 // Alignment options are representing 8 sides of a frame (rectangle);
46 // they are implemented as flags that may be combined together if it
47 // is wanted to define alignment to multiple sides at once.
48 kAlignTopLeft = 0x0001,
49 kAlignTopCenter = 0x0002,
50 kAlignTopRight = 0x0004,
51 kAlignMiddleLeft = 0x0008,
52 kAlignMiddleCenter = 0x0010,
53 kAlignMiddleRight = 0x0020,
54 kAlignBottomLeft = 0x0040,
55 kAlignBottomCenter = 0x0080,
56 kAlignBottomRight = 0x0100,
57
58 // Masks are helping to determine whether alignment parameter contains
59 // particular horizontal or vertical component (for example: left side
60 // or bottom side)
61 kMAlignLeft = kAlignTopLeft | kAlignMiddleLeft | kAlignBottomLeft,
62 kMAlignRight = kAlignTopRight | kAlignMiddleRight | kAlignBottomRight,
63 kMAlignTop = kAlignTopLeft | kAlignTopCenter | kAlignTopRight,
64 kMAlignBottom = kAlignBottomLeft | kAlignBottomCenter | kAlignBottomRight,
65 kMAlignHCenter = kAlignTopCenter | kAlignMiddleCenter | kAlignBottomCenter,
66 kMAlignVCenter = kAlignMiddleLeft | kAlignMiddleCenter | kAlignMiddleRight
67};
68
69// Horizontal alignment; based on FrameAlignment, used to restrict alignment
70// setting to left/right/center option, while keeping compatibility with any
71// alignment in case it will be supported in the future.
72enum HorAlignment {
73 kHAlignNone = kAlignNone,
74 kHAlignLeft = kAlignTopLeft,
75 kHAlignRight = kAlignTopRight,
76 kHAlignCenter = kAlignTopCenter
77};
78
79enum RectPlacement {
80 kPlaceOffset,
81 kPlaceCenter,
82 kPlaceStretch,
83 kPlaceStretchProportional,
84 kNumRectPlacement
85};
86
87struct Point {
88 int X;
89 int Y;
90
91 Point() {
92 X = 0;
93 Y = 0;
94 }
95
96 Point(int x, int y) {
97 X = x;
98 Y = y;
99 }
100
101 inline bool operator ==(const Point &p) const {
102 return X == p.X && Y == p.Y;
103 }
104
105 inline bool operator !=(const Point &p) const {
106 return X != p.X || Y != p.Y;
107 }
108
109 inline Point operator +(const Point &p) const {
110 return Point(X + p.X, Y + p.Y);
111 }
112
113 inline bool Equals(const int x, const int y) const {
114 return X == x && Y == y;
115 }
116};
117
118struct Line {
119 int X1;
120 int Y1;
121 int X2;
122 int Y2;
123
124 Line() {
125 X1 = 0;
126 Y1 = 0;
127 X2 = 0;
128 Y2 = 0;
129 }
130
131 Line(int x1, int y1, int x2, int y2) {
132 X1 = x1;
133 Y1 = y1;
134 X2 = x2;
135 Y2 = y2;
136 }
137};
138
139// Helper factory functions
140inline Line HLine(int x1, int x2, int y) {
141 return Line(x1, y, x2, y);
142}
143
144inline Line VLine(int x, int y1, int y2) {
145 return Line(x, y1, x, y2);
146}
147
148struct Size {
149 int Width;
150 int Height;
151
152 Size() {
153 Width = 0;
154 Height = 0;
155 }
156
157 Size(int width, int height) {
158 Width = width;
159 Height = height;
160 }
161
162 inline bool IsNull() const {
163 return Width <= 0 || Height <= 0;
164 }
165
166 inline static Size Clamp(const Size &sz, const Size &floor, const Size &ceil) {
167 return Size(AGSMath::Clamp(sz.Width, floor.Width, ceil.Width),
168 AGSMath::Clamp(sz.Height, floor.Height, ceil.Height));
169 }
170
171 // Indicates if current size exceeds other size by any metric
172 inline bool ExceedsByAny(const Size &size) const {
173 return Width > size.Width || Height > size.Height;
174 }
175
176 inline bool operator==(const Size &size) const {
177 return Width == size.Width && Height == size.Height;
178 }
179
180 inline bool operator!=(const Size &size) const {
181 return Width != size.Width || Height != size.Height;
182 }
183
184 inline bool operator<(const Size &other) const { // TODO: this implementation is silly and not universally useful; make a realistic one and replace with another function where necessary
185 return Width < other.Width || (Width == other.Width && Height < other.Height);
186 }
187
188 inline Size operator+(const Size &size) const {
189 return Size(Width + size.Width, Height + size.Height);
190 }
191
192 inline Size operator-(const Size &size) const {
193 return Size(Width - size.Width, Height - size.Height);
194 }
195
196 inline Size operator *(int x) const {
197 return Size(Width * x, Height * x);
198 }
199
200 inline Size operator /(int x) const {
201 return Size(Width / x, Height / x);
202 }
203
204 inline Size &operator *=(int x) {
205 Width *= x;
206 Height *= x;
207 return *this;
208 }
209
210 inline Size &operator /=(int x) {
211 Width /= x;
212 Height /= x;
213 return *this;
214 }
215};
216
217// TODO: consider making Rect have right-bottom coordinate with +1 offset
218// to comply with many other libraries (i.e. Right - Left == Width)
219struct Rect {
220 int Left;
221 int Top;
222 int Right;
223 int Bottom;
224
225 Rect() {
226 Left = 0;
227 Top = 0;
228 Right = -1;
229 Bottom = -1;
230 }
231
232 Rect(int l, int t, int r, int b) {
233 Left = l;
234 Top = t;
235 Right = r;
236 Bottom = b;
237 }
238
239 inline Point GetLT() const {
240 return Point(Left, Top);
241 }
242
243 inline Point GetCenter() const {
244 return Point(Left + GetWidth() / 2, Top + GetHeight() / 2);
245 }
246
247 inline int GetWidth() const {
248 return Right - Left + 1;
249 }
250
251 inline int GetHeight() const {
252 return Bottom - Top + 1;
253 }
254
255 inline Size GetSize() const {
256 return Size(GetWidth(), GetHeight());
257 }
258
259 inline bool IsEmpty() const {
260 return Right < Left || Bottom < Top;
261 }
262
263 inline bool IsInside(int x, int y) const {
264 return x >= Left && y >= Top && (x <= Right) && (y <= Bottom);
265 }
266
267 inline bool IsInside(const Point &pt) const {
268 return IsInside(pt.X, pt.Y);
269 }
270
271 inline void MoveToX(int x) {
272 Right += x - Left;
273 Left = x;
274 }
275
276 inline void MoveToY(int y) {
277 Bottom += y - Top;
278 Top = y;
279 }
280
281 inline void MoveTo(const Point &pt) {
282 MoveToX(pt.X);
283 MoveToY(pt.Y);
284 }
285
286 inline void SetWidth(int width) {
287 Right = Left + width - 1;
288 }
289
290 inline void SetHeight(int height) {
291 Bottom = Top + height - 1;
292 }
293
294 inline static Rect MoveBy(const Rect &r, int x, int y) {
295 return Rect(r.Left + x, r.Top + y, r.Right + x, r.Bottom + y);
296 }
297
298 inline bool operator ==(const Rect &r) const {
299 return Left == r.Left && Top == r.Top &&
300 Right == r.Right && Bottom == r.Bottom;
301 }
302};
303
304// Helper factory function
305inline Rect RectWH(int x, int y, int width, int height) {
306 return Rect(x, y, x + width - 1, y + height - 1);
307}
308
309inline Rect RectWH(const Size &sz) {
310 return Rect(0, 0, sz.Width - 1, sz.Height - 1);
311}
312
313
314struct Triangle {
315 int X1;
316 int Y1;
317 int X2;
318 int Y2;
319 int X3;
320 int Y3;
321
322 Triangle() {
323 X1 = 0;
324 Y1 = 0;
325 X2 = 0;
326 Y2 = 0;
327 X3 = 0;
328 Y3 = 0;
329 }
330
331 Triangle(int x1, int y1, int x2, int y2, int x3, int y3) {
332 X1 = x1;
333 Y1 = y1;
334 X2 = x2;
335 Y2 = y2;
336 X3 = x3;
337 Y3 = y3;
338 }
339};
340
341struct Circle {
342 int X;
343 int Y;
344 int Radius;
345
346 Circle() {
347 X = 0;
348 Y = 0;
349 Radius = 0;
350 }
351
352 Circle(int x, int y, int radius) {
353 X = x;
354 Y = y;
355 Radius = radius;
356 }
357
358};
359
360
361// Tells if two rectangles intersect (overlap) at least partially
362bool AreRectsIntersecting(const Rect &r1, const Rect &r2);
363// Tells if the item is completely inside place
364bool IsRectInsideRect(const Rect &place, const Rect &item);
365// Calculates a distance between two axis-aligned rectangles, returns 0 if they intersect
366float DistanceBetween(const Rect &r1, const Rect &r2);
367
368int AlignInHRange(int x1, int x2, int off_x, int width, FrameAlignment align);
369int AlignInVRange(int y1, int y2, int off_y, int height, FrameAlignment align);
370Rect AlignInRect(const Rect &frame, const Rect &item, FrameAlignment align);
371
372Size ProportionalStretch(int dest_w, int dest_h, int item_w, int item_h);
373Size ProportionalStretch(const Size &dest, const Size &item);
374
375Rect OffsetRect(const Rect &r, const Point off);
376Rect CenterInRect(const Rect &place, const Rect &item);
377Rect ClampToRect(const Rect &place, const Rect &item);
378Rect PlaceInRect(const Rect &place, const Rect &item, const RectPlacement &placement);
379// Sum two rectangles, the result is the rectangle bounding them both
380Rect SumRects(const Rect &r1, const Rect &r2);
381// Intersect two rectangles, the resolt is the rectangle bounding their intersection
382Rect IntersectRects(const Rect &r1, const Rect &r2);
383
384//} // namespace Shared
385//} // namespace AGS
386} // namespace AGS3
387
388#endif
Definition: geometry.h:341
Definition: geometry.h:118
Definition: geometry.h:87
Definition: geometry.h:219
Definition: geometry.h:148
Definition: geometry.h:314