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 
38 namespace Pt {
39 
40 namespace Gfx {
41 
42 class RectI;
43 
46 class Rect
47 {
48  public:
49  explicit Rect(const Point& p = Point(0, 0),
50  const Size& s = Size(0, 0))
51  : _p(p)
52  , _s(s)
53  {
54  }
55 
56  explicit Rect(const Size& s)
57  : _p()
58  , _s(s)
59  {
60  }
61 
62  Rect(Float width, Float height)
63  : _p()
64  , _s(width, height)
65  {
66  }
67 
68  Rect(const Point& p1, const Point& p2)
69  : _p(p1)
70  , _s(p2.x() - p1.x(), p2.y() - p1.y())
71  {
72  }
73 
74  Rect(const Rect& val)
75  : _p(val._p)
76  , _s(val._s)
77  {
78  }
79 
82  bool isEmpty() const
83  {
84  return (_s.width() == 0 || _s.height() == 0);
85  }
86 
89  static Rect fromLTRB(Float left, Float top, Float right, Float bottom)
90  {
91  return Rect(Point(left, top), Size(right - left, bottom - top));
92  }
93 
96  static Rect fromXYWH(Float x, Float y, Float w, Float h)
97  {
98  return Rect(Point(x, y), Size(w, h));
99  }
100 
101  void clear()
102  {
103  _p.clear();
104  _s.clear();
105  }
106 
107  void set(const Point& p, const Size& s)
108  {
109  _p = p;
110  _s = s;
111  }
112 
113  void set(const Point& p1, const Point& p2)
114  {
115  this->setOrigin(p1);
116  this->setWidth(p2.x() - p1.x());
117  this->setHeight(p2.y() - p1.y());
118  }
119 
120  void set(Float width, Float height)
121  {
122  _p.clear();
123  _s.set(width, height);
124  }
125 
126  const Point& origin() const
127  {
128  return _p;
129  }
130 
131  void setOrigin(const Point& p)
132  {
133  _p = p;
134  }
135 
136  void setSize(const Size& s)
137  {
138  _s = s;
139  }
140 
141  void setWidth(Float w)
142  {
143  _s.setWidth(w);
144  }
145 
146  void setHeight(Float h)
147  {
148  _s.setHeight(h);
149  }
150 
151  Float x() const
152  {
153  return _p.x();
154  }
155 
156  Float y() const
157  {
158  return _p.y();
159  }
160 
161  const Size& size() const
162  {
163  return _s;
164  }
165 
166  Float width() const
167  {
168  return _s.width();
169  }
170 
171  Float height() const
172  {
173  return _s.height();
174  }
175 
176  Float left() const
177  {
178  return _p.x();
179  }
180 
181  Float top() const
182  {
183  return _p.y();
184  }
185 
186  Float right() const
187  {
188  return _p.x() + _s.width();
189  }
190 
191  Float bottom() const
192  {
193  return _p.y() + _s.height();
194  }
195 
196  const Point& topLeft() const
197  {
198  return _p;
199  }
200 
201  Point topRight() const
202  {
203  return Point(this->x() + this->width(), this->y());
204  }
205 
206  Point bottomLeft() const
207  {
208  return Point(this->x(), this->y() + this->height());
209  }
210 
211  Point bottomRight() const
212  {
213  return Point(this->x() + this->width(),
214  this->y() + this->height());
215  }
216 
217  bool isEqual(const Rect& other, Float eps = FloatNearlyZero) const
218  {
219  return _p.isEqual(other._p, eps) && _s.isEqual(other._s, eps);
220  }
221 
222  void move(Float dx, Float dy)
223  {
224  _p.addX(dx);
225  _p.addY(dy);
226  }
227 
228  void expand(Float dw, Float dh)
229  {
230  _s.addWidth(dw);
231  _s.addHeight(dh);
232  }
233 
234  void shrink(Float dw, Float dh)
235  {
236  _s.addWidth(-dw);
237  _s.addHeight(-dh);
238  }
239 
240  void unify(const Rect& rect)
241  {
242  if( rect.isEmpty() )
243  return;
244 
245  if( this->isEmpty() )
246  {
247  _p = rect._p;
248  _s = rect._s;
249  return;
250  }
251 
252  const Float l = std::min(this->left(), rect.left());
253  const Float t = std::min(this->top(), rect.top());
254  const Float r = std::max(this->right(), rect.right());
255  const Float b = std::max(this->bottom(), rect.bottom());
256 
257  _p = Point(l, t);
258  _s = Size(r - l, b - t);
259  }
260 
263  Rect toIntersected(const Rect& rect) const
264  {
265  const Float l = std::max(this->left(), rect.left());
266  const Float t = std::max(this->top(), rect.top());
267  const Float r = std::min(this->right(), rect.right());
268  const Float b = std::min(this->bottom(), rect.bottom());
269 
270  return r >= l && b >= t ? Rect::fromLTRB(l, t, r, b)
271  : Rect();
272  }
273 
276  bool contains(const Point& p) const
277  {
278  return p.x() >= _p.x() &&
279  p.x() < _p.x() + _s.width() &&
280  p.y() >= _p.y() &&
281  p.y() < _p.y() + _s.height();
282  }
283 
286  bool contains(const Rect& r) const
287  {
288  return r.left() >= this->left() &&
289  r.right() <= this->right() &&
290  r.top() >= this->top() &&
291  r.bottom() <= this->bottom();
292  }
293 
296  bool intersects(const Rect& r) const
297  {
298  return this->right() > r.left() &&
299  r.right() > this->left() &&
300  this->bottom() > r.top() &&
301  r.bottom() > this->top();
302  }
303 
306  Point center() const
307  {
308  return Point(_p.x() + _s.width() / 2, _p.y() + _s.height() / 2);
309  }
310 
313  void normalize()
314  {
315  if(_s.width() < 0)
316  {
317  _p.addX(_s.width());
318  _s.setWidth(-_s.width());
319  }
320  if(_s.height() < 0)
321  {
322  _p.addY(_s.height());
323  _s.setHeight(-_s.height());
324  }
325  }
326 
330  {
331  Rect r(*this);
332  r.normalize();
333  return r;
334  }
335 
338  explicit Rect(const RectI& r);
339 
342  Rect& operator=(const RectI& r);
343 
346  RectI round() const;
347 
350  RectI floor() const;
351 
354  RectI ceil() const;
355 
358  RectI roundOut() const;
359 
362  RectI roundIn() const;
363 
364  private:
365  Point _p;
366  Size _s;
367 };
368 
369 typedef Rect RectF;
370 
373 class RectI
374 {
375  public:
376  explicit RectI(const PointI& p = PointI(0, 0),
377  const SizeI& s = SizeI(0, 0))
378  : _p(p)
379  , _s(s)
380  {
381  }
382 
383  explicit RectI(const SizeI& s)
384  : _p()
385  , _s(s)
386  {
387  }
388 
389  RectI(Int width, Int height)
390  : _p()
391  , _s(width, height)
392  {
393  }
394 
395  RectI(const PointI& p1, const PointI& p2)
396  : _p(p1)
397  , _s(p2.x() - p1.x(), p2.y() - p1.y())
398  {
399  }
400 
401  RectI(const RectI& val)
402  : _p(val._p)
403  , _s(val._s)
404  {
405  }
406 
409  bool isEmpty() const
410  {
411  return (_s.width() == 0 || _s.height() == 0);
412  }
413 
416  static RectI fromLTRB(Int left, Int top, Int right, Int bottom)
417  {
418  return RectI(PointI(left, top), SizeI(right - left, bottom - top));
419  }
420 
423  static RectI fromXYWH(Int x, Int y, Int w, Int h)
424  {
425  return RectI(PointI(x, y), SizeI(w, h));
426  }
427 
428  void clear()
429  {
430  _p.clear();
431  _s.clear();
432  }
433 
434  void set(const PointI& p, const SizeI& s)
435  {
436  _p = p;
437  _s = s;
438  }
439 
440  void set(const PointI& p1, const PointI& p2)
441  {
442  this->setOrigin(p1);
443  this->setWidth(p2.x() - p1.x());
444  this->setHeight(p2.y() - p1.y());
445  }
446 
447  void set(Int width, Int height)
448  {
449  _p.clear();
450  _s.set(width, height);
451  }
452 
453  const PointI& origin() const
454  {
455  return _p;
456  }
457 
458  void setOrigin(const PointI& p)
459  {
460  _p = p;
461  }
462 
463  void setSize(const SizeI& s)
464  {
465  _s = s;
466  }
467 
468  void setWidth(Int w)
469  {
470  _s.setWidth(w);
471  }
472 
473  void setHeight(Int h)
474  {
475  _s.setHeight(h);
476  }
477 
478  Int x() const
479  {
480  return _p.x();
481  }
482 
483  Int y() const
484  {
485  return _p.y();
486  }
487 
488  const SizeI& size() const
489  {
490  return _s;
491  }
492 
493  Int width() const
494  {
495  return _s.width();
496  }
497 
498  Int height() const
499  {
500  return _s.height();
501  }
502 
503  Int left() const
504  {
505  return _p.x();
506  }
507 
508  Int top() const
509  {
510  return _p.y();
511  }
512 
513  Int right() const
514  {
515  return _p.x() + _s.width();
516  }
517 
518  Int bottom() const
519  {
520  return _p.y() + _s.height();
521  }
522 
523  const PointI& topLeft() const
524  {
525  return _p;
526  }
527 
528  PointI topRight() const
529  {
530  return PointI(this->x() + this->width(), this->y());
531  }
532 
533  PointI bottomLeft() const
534  {
535  return PointI(this->x(), this->y() + this->height());
536  }
537 
538  PointI bottomRight() const
539  {
540  return PointI(this->x() + this->width(),
541  this->y() + this->height());
542  }
543 
544  bool operator==(const RectI& other) const
545  {
546  return _p == other._p && _s == other._s;
547  }
548 
549  bool operator!=(const RectI& other) const
550  {
551  return _p != other._p || _s != other._s;
552  }
553 
554  void move(Int dx, Int dy)
555  {
556  _p.addX(dx);
557  _p.addY(dy);
558  }
559 
560  void expand(Int dw, Int dh)
561  {
562  _s.addWidth(dw);
563  _s.addHeight(dh);
564  }
565 
566  void shrink(Int dw, Int dh)
567  {
568  _s.addWidth(-dw);
569  _s.addHeight(-dh);
570  }
571 
572  void unify(const RectI& rect)
573  {
574  if( rect.isEmpty() )
575  return;
576 
577  if( this->isEmpty() )
578  {
579  _p = rect._p;
580  _s = rect._s;
581  return;
582  }
583 
584  const Int l = std::min(this->left(), rect.left());
585  const Int t = std::min(this->top(), rect.top());
586  const Int r = std::max(this->right(), rect.right());
587  const Int b = std::max(this->bottom(), rect.bottom());
588 
589  _p = PointI(l, t);
590  _s = SizeI(r - l, b - t);
591  }
592 
595  RectI toIntersected(const RectI& rect) const
596  {
597  const Int l = std::max(this->left(), rect.left());
598  const Int t = std::max(this->top(), rect.top());
599  const Int r = std::min(this->right(), rect.right());
600  const Int b = std::min(this->bottom(), rect.bottom());
601 
602  return r >= l && b >= t ? RectI::fromLTRB(l, t, r, b)
603  : RectI();
604  }
605 
608  bool contains(const PointI& p) const
609  {
610  return p.x() >= _p.x() &&
611  p.x() < _p.x() + _s.width() &&
612  p.y() >= _p.y() &&
613  p.y() < _p.y() + _s.height();
614  }
615 
618  bool contains(const RectI& r) const
619  {
620  return r.left() >= this->left() &&
621  r.right() <= this->right() &&
622  r.top() >= this->top() &&
623  r.bottom() <= this->bottom();
624  }
625 
628  bool intersects(const RectI& r) const
629  {
630  return this->right() > r.left() &&
631  r.right() > this->left() &&
632  this->bottom() > r.top() &&
633  r.bottom() > this->top();
634  }
635 
638  PointI center() const
639  {
640  return PointI(_p.x() + _s.width() / 2, _p.y() + _s.height() / 2);
641  }
642 
645  void normalize()
646  {
647  if(_s.width() < 0)
648  {
649  _p.addX(_s.width());
650  _s.setWidth(-_s.width());
651  }
652  if(_s.height() < 0)
653  {
654  _p.addY(_s.height());
655  _s.setHeight(-_s.height());
656  }
657  }
658 
662  {
663  RectI r(*this);
664  r.normalize();
665  return r;
666  }
667 
668  private:
669  PointI _p;
670  SizeI _s;
671 };
672 
673 inline Rect::Rect(const RectI& r)
674 : _p(r.origin())
675 , _s(r.size())
676 {}
677 
678 inline Rect& Rect::operator=(const RectI& r)
679 {
680  _p = r.origin();
681  _s = r.size();
682  return *this;
683 }
684 
685 inline RectI Rect::round() const
686 {
687  return RectI(_p.round(), _s.round());
688 }
689 
690 inline RectI Rect::floor() const
691 {
692  return RectI(_p.floor(), _s.floor());
693 }
694 
695 inline RectI Rect::ceil() const
696 {
697  return RectI(_p.ceil(), _s.ceil());
698 }
699 
700 inline RectI Rect::roundOut() const
701 {
702  const Int l = static_cast<Int>(std::floor(this->left()));
703  const Int t = static_cast<Int>(std::floor(this->top()));
704  const Int r = static_cast<Int>(std::ceil(this->right()));
705  const Int b = static_cast<Int>(std::ceil(this->bottom()));
706  return RectI(PointI(l, t), SizeI(r - l, b - t));
707 }
708 
709 inline RectI Rect::roundIn() const
710 {
711  const Int l = static_cast<Int>(std::ceil(this->left()));
712  const Int t = static_cast<Int>(std::ceil(this->top()));
713  const Int r = static_cast<Int>(std::floor(this->right()));
714  const Int b = static_cast<Int>(std::floor(this->bottom()));
715  return RectI(PointI(l, t), SizeI(r - l, b - t));
716 }
717 
718 } // namespace
719 
720 } // namespace
721 
722 #endif
Core module.
Definition: Allocator.h:33
bool isEmpty() const
Returns true if width or height is zero.
Definition: Rect.h:409
bool contains(const Rect &r) const
Returns true if the given rect is entirely inside this rect.
Definition: Rect.h:286
Size with integer width and height.
Definition: Size.h:248
PointI floor() const
Floors each coordinate and returns a PointI.
Definition: Point.h:415
bool contains(const PointI &p) const
Returns true if the given point is inside or on the edge of this rect.
Definition: Rect.h:608
PointI round() const
Rounds each coordinate to the nearest integer and returns a PointI.
Definition: Point.h:409
RectI roundOut() const
Returns the smallest enclosing integer rect.
Definition: Rect.h:700
Rect & operator=(const RectI &r)
Assigns from a RectI by widening the coordinates.
Definition: Rect.h:678
static Rect fromLTRB(Float left, Float top, Float right, Float bottom)
Creates a rect from left, top, right, and bottom edges.
Definition: Rect.h:89
Size with floating-point width and height.
Definition: Size.h:47
bool intersects(const Rect &r) const
Returns true if this rect overlaps with the given rect.
Definition: Rect.h:296
PointI ceil() const
Ceils each coordinate and returns a PointI.
Definition: Point.h:421
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:263
Point with floating-point X and Y coordinates.
Definition: Point.h:47
SizeI round() const
Rounds each dimension to the nearest integer and returns a SizeI.
Definition: Size.h:422
static Rect fromXYWH(Float x, Float y, Float w, Float h)
Creates a rect from x, y, width, and height.
Definition: Rect.h:96
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:595
RectI roundIn() const
Returns the largest integer rect contained within this rect.
Definition: Rect.h:709
void normalize()
Normalizes this rect so that width and height are non-negative.
Definition: Rect.h:313
bool contains(const RectI &r) const
Returns true if the given rect is entirely inside this rect.
Definition: Rect.h:618
static RectI fromLTRB(Int left, Int top, Int right, Int bottom)
Creates a rect from left, top, right, and bottom edges.
Definition: Rect.h:416
SizeI floor() const
Floors each dimension and returns a SizeI.
Definition: Size.h:428
PointI center() const
Returns the center point of this rect.
Definition: Rect.h:638
RectI ceil() const
Ceils each component and returns a RectI.
Definition: Rect.h:695
Point with integer X and Y coordinates.
Definition: Point.h:255
bool isEmpty() const
Returns true if width or height is zero.
Definition: Rect.h:82
bool intersects(const RectI &r) const
Returns true if this rect overlaps with the given rect.
Definition: Rect.h:628
static RectI fromXYWH(Int x, Int y, Int w, Int h)
Creates a rect from x, y, width, and height.
Definition: Rect.h:423
RectI round() const
Rounds each component to the nearest integer and returns a RectI.
Definition: Rect.h:685
Rect toNormalized() const
Returns a normalized copy of this rect.
Definition: Rect.h:329
RectI floor() const
Floors each component and returns a RectI.
Definition: Rect.h:690
RectI toNormalized() const
Returns a normalized copy of this rect.
Definition: Rect.h:661
Point center() const
Returns the center point of this rect.
Definition: Rect.h:306
SizeI ceil() const
Ceils each dimension and returns a SizeI.
Definition: Size.h:434
bool contains(const Point &p) const
Returns true if the given point is inside or on the edge of this rect.
Definition: Rect.h:276
void normalize()
Normalizes this rect so that width and height are non-negative.
Definition: Rect.h:645
Rect with floating-point coordinates.
Definition: Rect.h:47
Rect with integer coordinates.
Definition: Rect.h:374