Rect.h
1/* Copyright (C) 2006-2015 Laurentiu-Gheorghe Crisan
2 * Copyright (C) 2006-2015 Marc Boris Duerner
3 * Copyright (C) 2010 Aloysius Indrayanto
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * As a special exception, you may use this file as part of a free
11 * software library without restriction. Specifically, if other files
12 * instantiate templates or use macros or inline functions from this
13 * file, or you compile this file and link it with other files to
14 * produce an executable, this file does not by itself cause the
15 * resulting executable to be covered by the GNU General Public
16 * License. This exception does not however invalidate any other
17 * reasons why the executable file might be covered by the GNU Library
18 * General Public License.
19 *
20 * This library is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * Lesser General Public License for more details.
24 *
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
28 * MA 02110-1301 USA
29 */
30
31#ifndef PT_GFX_RECT_H
32#define PT_GFX_RECT_H
33
34#include <Pt/Gfx/Point.h>
35#include <Pt/Gfx/Size.h>
36#include <algorithm>
37
38namespace Pt {
39
40namespace Gfx {
41
42class RectI;
43
75class Rect
76{
77 public:
78 explicit Rect(const Point& p = Point(0, 0),
79 const Size& s = Size(0, 0))
80 : _p(p)
81 , _s(s)
82 {
83 }
84
85 explicit Rect(const Size& s)
86 : _p()
87 , _s(s)
88 {
89 }
90
91 Rect(Float width, Float height)
92 : _p()
93 , _s(width, height)
94 {
95 }
96
97 Rect(const Point& p1, const Point& p2)
98 : _p(p1)
99 , _s(p2.x() - p1.x(), p2.y() - p1.y())
100 {
101 }
102
103 Rect(const Rect& val)
104 : _p(val._p)
105 , _s(val._s)
106 {
107 }
108
111 bool isEmpty() const
112 {
113 return (_s.width() == 0 || _s.height() == 0);
114 }
115
118 static Rect fromLTRB(Float left, Float top, Float right, Float bottom)
119 {
120 return Rect(Point(left, top), Size(right - left, bottom - top));
121 }
122
125 static Rect fromXYWH(Float x, Float y, Float w, Float h)
126 {
127 return Rect(Point(x, y), Size(w, h));
128 }
129
130 void clear()
131 {
132 _p.clear();
133 _s.clear();
134 }
135
136 void set(const Point& p, const Size& s)
137 {
138 _p = p;
139 _s = s;
140 }
141
142 void set(const Point& p1, const Point& p2)
143 {
144 this->setOrigin(p1);
145 this->setWidth(p2.x() - p1.x());
146 this->setHeight(p2.y() - p1.y());
147 }
148
149 void set(Float width, Float height)
150 {
151 _p.clear();
152 _s.set(width, height);
153 }
154
155 const Point& origin() const
156 {
157 return _p;
158 }
159
160 void setOrigin(const Point& p)
161 {
162 _p = p;
163 }
164
165 void setSize(const Size& s)
166 {
167 _s = s;
168 }
169
170 void setWidth(Float w)
171 {
172 _s.setWidth(w);
173 }
174
175 void setHeight(Float h)
176 {
177 _s.setHeight(h);
178 }
179
180 Float x() const
181 {
182 return _p.x();
183 }
184
185 Float y() const
186 {
187 return _p.y();
188 }
189
190 const Size& size() const
191 {
192 return _s;
193 }
194
195 Float width() const
196 {
197 return _s.width();
198 }
199
200 Float height() const
201 {
202 return _s.height();
203 }
204
205 Float left() const
206 {
207 return _p.x();
208 }
209
210 Float top() const
211 {
212 return _p.y();
213 }
214
215 Float right() const
216 {
217 return _p.x() + _s.width();
218 }
219
220 Float bottom() const
221 {
222 return _p.y() + _s.height();
223 }
224
225 const Point& topLeft() const
226 {
227 return _p;
228 }
229
230 Point topRight() const
231 {
232 return Point(this->x() + this->width(), this->y());
233 }
234
235 Point bottomLeft() const
236 {
237 return Point(this->x(), this->y() + this->height());
238 }
239
240 Point bottomRight() const
241 {
242 return Point(this->x() + this->width(),
243 this->y() + this->height());
244 }
245
246 bool isEqual(const Rect& other, Float eps = FloatNearlyZero) const
247 {
248 return _p.isEqual(other._p, eps) && _s.isEqual(other._s, eps);
249 }
250
251 void move(Float dx, Float dy)
252 {
253 _p.addX(dx);
254 _p.addY(dy);
255 }
256
257 void expand(Float dw, Float dh)
258 {
259 _s.addWidth(dw);
260 _s.addHeight(dh);
261 }
262
263 void shrink(Float dw, Float dh)
264 {
265 _s.addWidth(-dw);
266 _s.addHeight(-dh);
267 }
268
269 void unify(const Rect& rect)
270 {
271 if( rect.isEmpty() )
272 return;
273
274 if( this->isEmpty() )
275 {
276 _p = rect._p;
277 _s = rect._s;
278 return;
279 }
280
281 const Float l = std::min(this->left(), rect.left());
282 const Float t = std::min(this->top(), rect.top());
283 const Float r = std::max(this->right(), rect.right());
284 const Float b = std::max(this->bottom(), rect.bottom());
285
286 _p = Point(l, t);
287 _s = Size(r - l, b - t);
288 }
289
292 Rect toIntersected(const Rect& rect) const
293 {
294 const Float l = std::max(this->left(), rect.left());
295 const Float t = std::max(this->top(), rect.top());
296 const Float r = std::min(this->right(), rect.right());
297 const Float b = std::min(this->bottom(), rect.bottom());
298
299 return r >= l && b >= t ? Rect::fromLTRB(l, t, r, b)
300 : Rect();
301 }
302
305 bool contains(const Point& p) const
306 {
307 return p.x() >= _p.x() &&
308 p.x() < _p.x() + _s.width() &&
309 p.y() >= _p.y() &&
310 p.y() < _p.y() + _s.height();
311 }
312
315 bool contains(const Rect& r) const
316 {
317 return r.left() >= this->left() &&
318 r.right() <= this->right() &&
319 r.top() >= this->top() &&
320 r.bottom() <= this->bottom();
321 }
322
325 bool intersects(const Rect& r) const
326 {
327 return this->right() > r.left() &&
328 r.right() > this->left() &&
329 this->bottom() > r.top() &&
330 r.bottom() > this->top();
331 }
332
335 Point center() const
336 {
337 return Point(_p.x() + _s.width() / 2, _p.y() + _s.height() / 2);
338 }
339
343 {
344 if(_s.width() < 0)
345 {
346 _p.addX(_s.width());
347 _s.setWidth(-_s.width());
348 }
349 if(_s.height() < 0)
350 {
351 _p.addY(_s.height());
352 _s.setHeight(-_s.height());
353 }
354 }
355
358 Rect toNormalized() const
359 {
360 Rect r(*this);
361 r.normalize();
362 return r;
363 }
364
367 explicit Rect(const RectI& r);
368
371 Rect& operator=(const RectI& r);
372
375 RectI round() const;
376
379 RectI floor() const;
380
383 RectI ceil() const;
384
387 RectI roundOut() const;
388
391 RectI roundIn() const;
392
393 private:
394 Point _p;
395 Size _s;
396};
397
398typedef Rect RectF;
399
413class RectI
414{
415 public:
416 explicit RectI(const PointI& p = PointI(0, 0),
417 const SizeI& s = SizeI(0, 0))
418 : _p(p)
419 , _s(s)
420 {
421 }
422
423 explicit RectI(const SizeI& s)
424 : _p()
425 , _s(s)
426 {
427 }
428
429 RectI(Int width, Int height)
430 : _p()
431 , _s(width, height)
432 {
433 }
434
435 RectI(const PointI& p1, const PointI& p2)
436 : _p(p1)
437 , _s(p2.x() - p1.x(), p2.y() - p1.y())
438 {
439 }
440
441 RectI(const RectI& val)
442 : _p(val._p)
443 , _s(val._s)
444 {
445 }
446
449 bool isEmpty() const
450 {
451 return (_s.width() == 0 || _s.height() == 0);
452 }
453
456 static RectI fromLTRB(Int left, Int top, Int right, Int bottom)
457 {
458 return RectI(PointI(left, top), SizeI(right - left, bottom - top));
459 }
460
463 static RectI fromXYWH(Int x, Int y, Int w, Int h)
464 {
465 return RectI(PointI(x, y), SizeI(w, h));
466 }
467
468 void clear()
469 {
470 _p.clear();
471 _s.clear();
472 }
473
474 void set(const PointI& p, const SizeI& s)
475 {
476 _p = p;
477 _s = s;
478 }
479
480 void set(const PointI& p1, const PointI& p2)
481 {
482 this->setOrigin(p1);
483 this->setWidth(p2.x() - p1.x());
484 this->setHeight(p2.y() - p1.y());
485 }
486
487 void set(Int width, Int height)
488 {
489 _p.clear();
490 _s.set(width, height);
491 }
492
493 const PointI& origin() const
494 {
495 return _p;
496 }
497
498 void setOrigin(const PointI& p)
499 {
500 _p = p;
501 }
502
503 void setSize(const SizeI& s)
504 {
505 _s = s;
506 }
507
508 void setWidth(Int w)
509 {
510 _s.setWidth(w);
511 }
512
513 void setHeight(Int h)
514 {
515 _s.setHeight(h);
516 }
517
518 Int x() const
519 {
520 return _p.x();
521 }
522
523 Int y() const
524 {
525 return _p.y();
526 }
527
528 const SizeI& size() const
529 {
530 return _s;
531 }
532
533 Int width() const
534 {
535 return _s.width();
536 }
537
538 Int height() const
539 {
540 return _s.height();
541 }
542
543 Int left() const
544 {
545 return _p.x();
546 }
547
548 Int top() const
549 {
550 return _p.y();
551 }
552
553 Int right() const
554 {
555 return _p.x() + _s.width();
556 }
557
558 Int bottom() const
559 {
560 return _p.y() + _s.height();
561 }
562
563 const PointI& topLeft() const
564 {
565 return _p;
566 }
567
568 PointI topRight() const
569 {
570 return PointI(this->x() + this->width(), this->y());
571 }
572
573 PointI bottomLeft() const
574 {
575 return PointI(this->x(), this->y() + this->height());
576 }
577
578 PointI bottomRight() const
579 {
580 return PointI(this->x() + this->width(),
581 this->y() + this->height());
582 }
583
584 bool operator==(const RectI& other) const
585 {
586 return _p == other._p && _s == other._s;
587 }
588
589 bool operator!=(const RectI& other) const
590 {
591 return _p != other._p || _s != other._s;
592 }
593
594 void move(Int dx, Int dy)
595 {
596 _p.addX(dx);
597 _p.addY(dy);
598 }
599
600 void expand(Int dw, Int dh)
601 {
602 _s.addWidth(dw);
603 _s.addHeight(dh);
604 }
605
606 void shrink(Int dw, Int dh)
607 {
608 _s.addWidth(-dw);
609 _s.addHeight(-dh);
610 }
611
612 void unify(const RectI& rect)
613 {
614 if( rect.isEmpty() )
615 return;
616
617 if( this->isEmpty() )
618 {
619 _p = rect._p;
620 _s = rect._s;
621 return;
622 }
623
624 const Int l = std::min(this->left(), rect.left());
625 const Int t = std::min(this->top(), rect.top());
626 const Int r = std::max(this->right(), rect.right());
627 const Int b = std::max(this->bottom(), rect.bottom());
628
629 _p = PointI(l, t);
630 _s = SizeI(r - l, b - t);
631 }
632
635 RectI toIntersected(const RectI& rect) const
636 {
637 const Int l = std::max(this->left(), rect.left());
638 const Int t = std::max(this->top(), rect.top());
639 const Int r = std::min(this->right(), rect.right());
640 const Int b = std::min(this->bottom(), rect.bottom());
641
642 return r >= l && b >= t ? RectI::fromLTRB(l, t, r, b)
643 : RectI();
644 }
645
648 bool contains(const PointI& p) const
649 {
650 return p.x() >= _p.x() &&
651 p.x() < _p.x() + _s.width() &&
652 p.y() >= _p.y() &&
653 p.y() < _p.y() + _s.height();
654 }
655
658 bool contains(const RectI& r) const
659 {
660 return r.left() >= this->left() &&
661 r.right() <= this->right() &&
662 r.top() >= this->top() &&
663 r.bottom() <= this->bottom();
664 }
665
668 bool intersects(const RectI& r) const
669 {
670 return this->right() > r.left() &&
671 r.right() > this->left() &&
672 this->bottom() > r.top() &&
673 r.bottom() > this->top();
674 }
675
679 {
680 return PointI(_p.x() + _s.width() / 2, _p.y() + _s.height() / 2);
681 }
682
686 {
687 if(_s.width() < 0)
688 {
689 _p.addX(_s.width());
690 _s.setWidth(-_s.width());
691 }
692 if(_s.height() < 0)
693 {
694 _p.addY(_s.height());
695 _s.setHeight(-_s.height());
696 }
697 }
698
701 RectI toNormalized() const
702 {
703 RectI r(*this);
704 r.normalize();
705 return r;
706 }
707
708 private:
709 PointI _p;
710 SizeI _s;
711};
712
713inline Rect::Rect(const RectI& r)
714: _p(r.origin())
715, _s(r.size())
716{}
717
718inline Rect& Rect::operator=(const RectI& r)
719{
720 _p = r.origin();
721 _s = r.size();
722 return *this;
723}
724
725inline RectI Rect::round() const
726{
727 return RectI(_p.round(), _s.round());
728}
729
730inline RectI Rect::floor() const
731{
732 return RectI(_p.floor(), _s.floor());
733}
734
735inline RectI Rect::ceil() const
736{
737 return RectI(_p.ceil(), _s.ceil());
738}
739
740inline RectI Rect::roundOut() const
741{
742 const Int l = static_cast<Int>(std::floor(this->left()));
743 const Int t = static_cast<Int>(std::floor(this->top()));
744 const Int r = static_cast<Int>(std::ceil(this->right()));
745 const Int b = static_cast<Int>(std::ceil(this->bottom()));
746 return RectI(PointI(l, t), SizeI(r - l, b - t));
747}
748
749inline RectI Rect::roundIn() const
750{
751 const Int l = static_cast<Int>(std::ceil(this->left()));
752 const Int t = static_cast<Int>(std::ceil(this->top()));
753 const Int r = static_cast<Int>(std::floor(this->right()));
754 const Int b = static_cast<Int>(std::floor(this->bottom()));
755 return RectI(PointI(l, t), SizeI(r - l, b - t));
756}
757
758} // namespace
759
760} // namespace
761
762#endif
Integer X and Y coordinates.
Definition Point.h:292
Floating-point X and Y coordinates.
Definition Point.h:73
Integer rectangle.
Definition Rect.h:414
bool contains(const RectI &r) const
Returns true if the given rect is entirely inside this rect.
Definition Rect.h:658
static RectI fromXYWH(Int x, Int y, Int w, Int h)
Creates a rect from x, y, width, and height.
Definition Rect.h:463
bool contains(const PointI &p) const
Returns true if the given point is inside or on the edge of this rect.
Definition Rect.h:648
bool intersects(const RectI &r) const
Returns true if this rect overlaps with the given rect.
Definition Rect.h:668
static RectI fromLTRB(Int left, Int top, Int right, Int bottom)
Creates a rect from left, top, right, and bottom edges.
Definition Rect.h:456
RectI toNormalized() const
Returns a normalized copy of this rect.
Definition Rect.h:701
RectI toIntersected(const RectI &rect) const
Returns the intersection of this rect and another, or an empty rect if they do not overlap.
Definition Rect.h:635
PointI center() const
Returns the center point of this rect.
Definition Rect.h:678
void normalize()
Normalizes this rect so that width and height are non-negative.
Definition Rect.h:685
bool isEmpty() const
Returns true if width or height is zero.
Definition Rect.h:449
Floating-point rectangle.
Definition Rect.h:76
Point center() const
Returns the center point of this rect.
Definition Rect.h:335
Rect toIntersected(const Rect &rect) const
Returns the intersection of this rect and another, or an empty rect if they do not overlap.
Definition Rect.h:292
bool intersects(const Rect &r) const
Returns true if this rect overlaps with the given rect.
Definition Rect.h:325
RectI roundIn() const
Returns the largest integer rect contained within this rect.
Definition Rect.h:749
bool contains(const Rect &r) const
Returns true if the given rect is entirely inside this rect.
Definition Rect.h:315
static Rect fromLTRB(Float left, Float top, Float right, Float bottom)
Creates a rect from left, top, right, and bottom edges.
Definition Rect.h:118
RectI floor() const
Floors each component and returns a RectI.
Definition Rect.h:730
static Rect fromXYWH(Float x, Float y, Float w, Float h)
Creates a rect from x, y, width, and height.
Definition Rect.h:125
Rect & operator=(const RectI &r)
Assigns from a RectI by widening the coordinates.
Definition Rect.h:718
bool contains(const Point &p) const
Returns true if the given point is inside or on the edge of this rect.
Definition Rect.h:305
RectI roundOut() const
Returns the smallest enclosing integer rect.
Definition Rect.h:740
RectI ceil() const
Ceils each component and returns a RectI.
Definition Rect.h:735
RectI round() const
Rounds each component to the nearest integer and returns a RectI.
Definition Rect.h:725
Rect toNormalized() const
Returns a normalized copy of this rect.
Definition Rect.h:358
void normalize()
Normalizes this rect so that width and height are non-negative.
Definition Rect.h:342
bool isEmpty() const
Returns true if width or height is zero.
Definition Rect.h:111
Integer width and height.
Definition Size.h:279
Floating-point width and height.
Definition Size.h:69
Graphics and imaging services.
Definition Api-Argb32Image.h:12
Core module.
Definition Allocator.h:33