FINAL CUT
frect.h
1 /***********************************************************************
2 * frect.h - Rectangle with position and size *
3 * *
4 * This file is part of the FINAL CUT widget toolkit *
5 * *
6 * Copyright 2014-2024 Markus Gans *
7 * *
8 * FINAL CUT is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU Lesser General Public License as *
10 * published by the Free Software Foundation; either version 3 of *
11 * the License, or (at your option) any later version. *
12 * *
13 * FINAL CUT is distributed in the hope that it will be useful, but *
14 * WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU Lesser General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU Lesser General Public *
19 * License along with this program. If not, see *
20 * <http://www.gnu.org/licenses/>. *
21 ***********************************************************************/
22 
23 /* Standalone class
24  * ════════════════
25  *
26  * ▕▔▔▔▔▔▔▔▏1 *▕▔▔▔▔▔▔▔▔▏
27  * ▕ FRect ▏-┬- - -▕ FPoint ▏
28  * ▕▁▁▁▁▁▁▁▏ : ▕▁▁▁▁▁▁▁▁▏
29  * :
30  * : 1▕▔▔▔▔▔▔▔▏
31  * └- - -▕ FSize ▏
32  * ▕▁▁▁▁▁▁▁▏
33  */
34 
35 #ifndef FRECT_H
36 #define FRECT_H
37 
38 #if !defined (USE_FINAL_H) && !defined (COMPILE_FINAL_CUT)
39  #error "Only <final/final.h> can be included directly."
40 #endif
41 
42 #include <algorithm>
43 #include <utility>
44 
45 #include "final/util/fpoint.h"
46 #include "final/util/fsize.h"
47 #include "final/util/fstring.h"
48 
49 namespace finalcut
50 {
51 
52 //----------------------------------------------------------------------
53 // class FRect
54 //----------------------------------------------------------------------
55 
56 class FRect
57 {
58  public:
59  // Constructors
60  FRect () noexcept = default;
61  FRect (int, int, std::size_t, std::size_t) noexcept;
62  FRect (const FPoint&, const FSize&) noexcept;
63  FRect (const FPoint&, const FPoint&) noexcept;
64 
65  // Accessors
66  auto getClassName() const -> FString;
67  auto getX1() const noexcept -> int;
68  auto getY1() const noexcept -> int;
69  auto getX2() const noexcept -> int;
70  auto getY2() const noexcept -> int;
71  auto getX() const noexcept -> int;
72  auto getY() const noexcept -> int;
73  auto getPos() const noexcept -> FPoint;
74  auto getUpperLeftPos() const noexcept -> FPoint;
75  auto getUpperRightPos() const noexcept -> FPoint;
76  auto getLowerLeftPos() const noexcept -> FPoint;
77  auto getLowerRightPos() const noexcept -> FPoint;
78  auto getWidth() const noexcept -> std::size_t;
79  auto getHeight() const noexcept -> std::size_t;
80  auto getSize() const noexcept -> FSize;
81 
82  // Mutators
83  void setX1 (int) noexcept;
84  void setY1 (int) noexcept;
85  void setX2 (int) noexcept;
86  void setY2 (int) noexcept;
87  void setX (int) noexcept;
88  void setY (int) noexcept;
89  void setPos (int, int) noexcept;
90  void setPos (const FPoint&) noexcept;
91  void setWidth (std::size_t) noexcept;
92  void setHeight (std::size_t) noexcept;
93  void setSize (std::size_t, std::size_t) noexcept;
94  void setSize (const FSize&) noexcept;
95  void setRect (const FRect&) noexcept;
96  void setRect (const FPoint&, const FSize&) noexcept;
97  void setRect (int, int, std::size_t, std::size_t) noexcept;
98  void setCoordinates (const FPoint&, const FPoint&) noexcept;
99  void setCoordinates (int, int, int, int) noexcept;
100 
101  // Inquiry
102  auto isEmpty() const -> bool;
103 
104  // Coordinate references
105  auto x1_ref() & noexcept -> int&;
106  auto y1_ref() & noexcept -> int&;
107  auto x2_ref() & noexcept -> int&;
108  auto y2_ref() & noexcept -> int&;
109 
110  // Methods
111  void move (int, int) noexcept;
112  void move (const FPoint&) noexcept;
113  void scaleBy (int, int) noexcept;
114  void scaleBy (const FPoint&) noexcept;
115  auto contains (int, int) const noexcept -> bool;
116  auto contains (const FPoint&) const noexcept -> bool;
117  auto contains (const FRect&) const noexcept -> bool;
118  auto overlap (const FRect&) const noexcept -> bool;
119  auto intersect (const FRect&) const noexcept -> FRect;
120  auto combined (const FRect&) const noexcept -> FRect;
121 
122  private:
123  // Data members
124  int X1{0};
125  int Y1{0};
126  int X2{-1};
127  int Y2{-1};
128 
129  // Friend operator functions
130  friend inline auto operator + (const FRect& r, const FSize& s) -> FRect
131  {
132  return { r.X1
133  , r.Y1
134  , std::size_t(r.X2 - r.X1) + 1 + s.getWidth()
135  , std::size_t(r.Y2 - r.Y1) + 1 + s.getHeight() };
136  }
137 
138  friend inline auto operator - (const FRect& r, const FSize& s) -> FRect
139  {
140  return { r.X1
141  , r.Y1
142  , std::size_t(r.X2 - r.X1) + 1 - s.getWidth()
143  , std::size_t(r.Y2 - r.Y1) + 1 - s.getHeight() };
144  }
145 
146  friend inline auto operator == (const FRect& r1, const FRect& r2) -> bool
147  {
148  return r1.X1 == r2.X1
149  && r1.Y1 == r2.Y1
150  && r1.X2 == r2.X2
151  && r1.Y2 == r2.Y2;
152  }
153 
154  friend inline auto operator != (const FRect& r1, const FRect& r2) -> bool
155  {
156  return r1.X1 != r2.X1
157  || r1.Y1 != r2.Y1
158  || r1.X2 != r2.X2
159  || r1.Y2 != r2.Y2;
160  }
161 
162  friend inline auto operator << (std::ostream& outstr, const FRect& r) -> std::ostream&
163  {
164  outstr << r.X1 << " "
165  << r.Y1 << " "
166  << r.X2 << " "
167  << r.Y2;
168  return outstr;
169  }
170 
171  friend inline auto operator >> (std::istream& instr, FRect& r) -> std::istream&
172  {
173  int x1{};
174  int y1{};
175  int x2{};
176  int y2{};
177  instr >> x1;
178  instr >> y1;
179  instr >> x2;
180  instr >> y2;
181  r.setCoordinates (x1, y1, x2, y2);
182  return instr;
183  }
184 };
185 
186 // FRect inline functions
187 //----------------------------------------------------------------------
188 inline FRect::FRect (int x, int y, std::size_t width, std::size_t height) noexcept
189  : X1{x}
190  , Y1{y}
191  , X2{x + int(width) - 1}
192  , Y2{y + int(height) - 1}
193 { }
194 
195 //----------------------------------------------------------------------
196 inline auto FRect::getClassName() const -> FString
197 { return "FRect"; }
198 
199 //----------------------------------------------------------------------
200 inline auto FRect::getX1() const noexcept -> int
201 { return X1; }
202 
203 //----------------------------------------------------------------------
204 inline auto FRect::getY1() const noexcept -> int
205 { return Y1; }
206 
207 //----------------------------------------------------------------------
208 inline auto FRect::getX2() const noexcept -> int
209 { return X2; }
210 
211 //----------------------------------------------------------------------
212 inline auto FRect::getY2() const noexcept -> int
213 { return Y2; }
214 
215 //----------------------------------------------------------------------
216 inline auto FRect::getX() const noexcept -> int
217 { return X1; }
218 
219 //----------------------------------------------------------------------
220 inline auto FRect::getY() const noexcept -> int
221 { return Y1; }
222 
223 //----------------------------------------------------------------------
224 inline auto FRect::getPos() const noexcept -> FPoint
225 { return { X1, Y1 }; }
226 
227 //----------------------------------------------------------------------
228 inline auto FRect::getUpperLeftPos() const noexcept -> FPoint
229 { return { X1, Y1 }; }
230 
231 //----------------------------------------------------------------------
232 inline auto FRect::getUpperRightPos() const noexcept -> FPoint
233 { return { X2, Y1 }; }
234 
235 //----------------------------------------------------------------------
236 inline auto FRect::getLowerLeftPos() const noexcept -> FPoint
237 { return { X1, Y2 }; }
238 
239 //----------------------------------------------------------------------
240 inline auto FRect::getLowerRightPos() const noexcept -> FPoint
241 { return { X2, Y2 }; }
242 
243 //----------------------------------------------------------------------
244 inline auto FRect::getWidth() const noexcept -> std::size_t
245 {
246  return static_cast<std::size_t>(std::max(0, X2 - (X1 - 1))); // overflow save
247 }
248 
249 //----------------------------------------------------------------------
250 inline auto FRect::getHeight() const noexcept -> std::size_t
251 {
252  return static_cast<std::size_t>(std::max(0, Y2 - (Y1 - 1))); // overflow save
253 }
254 
255 //----------------------------------------------------------------------
256 inline auto FRect::getSize() const noexcept -> FSize
257 { return { FSize{getWidth(), getHeight()} }; }
258 
259 //----------------------------------------------------------------------
260 inline void FRect::setX1 (int n) noexcept
261 { X1 = n; }
262 
263 //----------------------------------------------------------------------
264 inline void FRect::setY1 (int n) noexcept
265 { Y1 = n; }
266 
267 //----------------------------------------------------------------------
268 inline void FRect::setX2 (int n) noexcept
269 { X2 = n; }
270 
271 //----------------------------------------------------------------------
272 inline void FRect::setY2 (int n) noexcept
273 { Y2 = n; }
274 
275 //----------------------------------------------------------------------
276 inline void FRect::setX (int n) noexcept
277 {
278  const int dX = X2 - X1;
279  X1 = n;
280  X2 = X1 + dX;
281 }
282 
283 //----------------------------------------------------------------------
284 inline void FRect::setY (int n) noexcept
285 {
286  const int dY = Y2 - Y1;
287  Y1 = n;
288  Y2 = Y1 + dY;
289 }
290 
291 //----------------------------------------------------------------------
292 inline void FRect::setPos (int x, int y) noexcept
293 {
294  const int dX = X2 - X1;
295  const int dY = Y2 - Y1;
296  X1 = x;
297  Y1 = y;
298  X2 = X1 + dX;
299  Y2 = Y1 + dY;
300 }
301 
302 //----------------------------------------------------------------------
303 inline void FRect::setPos (const FPoint& p) noexcept
304 {
305  const int dX = X2 - X1;
306  const int dY = Y2 - Y1;
307  X1 = p.getX();
308  Y1 = p.getY();
309  X2 = X1 + dX;
310  Y2 = Y1 + dY;
311 }
312 
313 //----------------------------------------------------------------------
314 inline void FRect::setWidth (std::size_t w) noexcept
315 { X2 = X1 + int(w) - 1; }
316 
317 //----------------------------------------------------------------------
318 inline void FRect::setHeight (std::size_t h) noexcept
319 { Y2 = Y1 + int(h) - 1; }
320 
321 //----------------------------------------------------------------------
322 inline void FRect::setSize (std::size_t width, std::size_t height) noexcept
323 {
324  X2 = X1 + int(width) - 1;
325  Y2 = Y1 + int(height) - 1;
326 }
327 
328 //----------------------------------------------------------------------
329 inline void FRect::setSize (const FSize& s) noexcept
330 {
331  X2 = X1 + int(s.getWidth()) - 1;
332  Y2 = Y1 + int(s.getHeight()) - 1;
333 }
334 
335 //----------------------------------------------------------------------
336 inline void FRect::setRect (const FRect& r) noexcept
337 {
338  X1 = r.X1;
339  Y1 = r.Y1;
340  X2 = r.X2;
341  Y2 = r.Y2;
342 }
343 
344 //----------------------------------------------------------------------
345 inline void FRect::setRect (const FPoint& p, const FSize& s) noexcept
346 {
347  X1 = p.getX();
348  Y1 = p.getY();
349  X2 = p.getX() + int(s.getWidth()) - 1;
350  Y2 = p.getY() + int(s.getHeight()) - 1;
351 }
352 
353 //----------------------------------------------------------------------
354 inline void FRect::setRect (int x, int y, std::size_t width, std::size_t height) noexcept
355 {
356  X1 = x;
357  Y1 = y;
358  X2 = x + int(width) - 1;
359  Y2 = y + int(height) - 1;
360 }
361 
362 //----------------------------------------------------------------------
363 inline void FRect::setCoordinates (const FPoint& p1, const FPoint& p2) noexcept
364 {
365  setCoordinates (p1.getX(), p1.getY(), p2.getX(), p2.getY());
366 }
367 
368 //----------------------------------------------------------------------
369 inline void FRect::setCoordinates (int x1, int y1, int x2, int y2) noexcept
370 {
371  X1 = x1;
372  Y1 = y1;
373  X2 = x2;
374  Y2 = y2;
375 }
376 
377 //----------------------------------------------------------------------
378 inline auto FRect::isEmpty() const -> bool
379 { return X2 == X1 - 1 && Y2 == Y1 - 1; }
380 
381 //----------------------------------------------------------------------
382 inline auto FRect::x1_ref() & noexcept -> int&
383 { return X1; }
384 
385 //----------------------------------------------------------------------
386 inline auto FRect::y1_ref() & noexcept -> int&
387 { return Y1; }
388 
389 //----------------------------------------------------------------------
390 inline auto FRect::x2_ref() & noexcept -> int&
391 { return X2; }
392 
393 //----------------------------------------------------------------------
394 inline auto FRect::y2_ref() & noexcept -> int&
395 { return Y2; }
396 
397 //----------------------------------------------------------------------
398 inline void FRect::move (int dx, int dy) noexcept
399 {
400  X1 += dx;
401  Y1 += dy;
402  X2 += dx;
403  Y2 += dy;
404 }
405 
406 //----------------------------------------------------------------------
407 inline void FRect::move (const FPoint& d) noexcept
408 {
409  X1 += d.getX();
410  Y1 += d.getY();
411  X2 += d.getX();
412  Y2 += d.getY();
413 }
414 
415 //----------------------------------------------------------------------
416 inline void FRect::scaleBy (int dx, int dy) noexcept
417 {
418  X2 += dx;
419  Y2 += dy;
420 }
421 
422 //----------------------------------------------------------------------
423 inline void FRect::scaleBy (const FPoint& d) noexcept
424 {
425  X2 += d.getX();
426  Y2 += d.getY();
427 }
428 
429 //----------------------------------------------------------------------
430 inline auto FRect::contains (int x, int y) const noexcept -> bool
431 {
432  return x >= X1 && x <= X2
433  && y >= Y1 && y <= Y2;
434 }
435 
436 //----------------------------------------------------------------------
437 inline auto FRect::contains (const FPoint& p) const noexcept -> bool
438 {
439  return p.getX() >= X1 && p.getX() <= X2
440  && p.getY() >= Y1 && p.getY() <= Y2;
441 }
442 
443 //----------------------------------------------------------------------
444 inline auto FRect::contains (const FRect& r) const noexcept -> bool
445 {
446  return r.X1 >= X1 && r.X2 <= X2
447  && r.Y1 >= Y1 && r.Y2 <= Y2;
448 }
449 
450 //----------------------------------------------------------------------
451 inline auto FRect::overlap (const FRect &r) const noexcept -> bool
452 {
453  return ( std::max(X1, r.X1) <= std::min(X2, r.X2)
454  && std::max(Y1, r.Y1) <= std::min(Y2, r.Y2) );
455 }
456 
457 } // namespace finalcut
458 
459 #endif // FRECT_H
Definition: frect.h:56
Definition: class_template.cpp:25
Definition: fpoint.h:50
Definition: fsize.h:55
Definition: fstring.h:79