supertux
rectf.hpp
1 // SuperTux
2 // Copyright (C) 2006 Matthias Braun <matze@braunis.de>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 
17 #ifndef HEADER_SUPERTUX_MATH_RECTF_HPP
18 #define HEADER_SUPERTUX_MATH_RECTF_HPP
19 
20 #include <assert.h>
21 #include <iosfwd>
22 
23 #include <SDL.h>
24 
25 #include "math/anchor_point.hpp"
26 #include "math/sizef.hpp"
27 #include "math/vector.hpp"
28 
29 class Rect;
30 
31 class Rectf final
32 {
33 public:
34  static Rectf from_center(const Vector& center, const Sizef& size)
35  {
36  return Rectf(center.x - size.width / 2.0f,
37  center.y - size.height / 2.0f,
38  center.x + size.width / 2.0f,
39  center.y + size.height / 2.0f);
40  }
41 
42 public:
43  Rectf() :
44  m_p1(0.0f, 0.0f),
45  m_size()
46  { }
47 
48  Rectf(const Rectf& rhs) = default;
49  Rectf& operator=(const Rectf& rhs) = default;
50 
51  Rectf(const Vector& np1, const Vector& np2) :
52  m_p1(np1), m_size(np2.x - np1.x, np2.y - np1.y)
53  {
54  assert(m_size.width >= 0 &&
55  m_size.height >= 0);
56  }
57 
58  Rectf(float x1, float y1, float x2, float y2) :
59  m_p1(x1, y1), m_size(x2 - x1, y2 - y1)
60  {
61  assert(m_size.width >= 0 &&
62  m_size.height >= 0);
63  }
64 
65  Rectf(const Vector& p1, const Sizef& size) :
66  m_p1(p1),
67  m_size(size)
68  {
69  }
70 
71  Rectf(const SDL_FRect& rect) :
72  m_p1(rect.x, rect.y), m_size(rect.w, rect.h)
73  {
74  }
75 
76  Rectf(const Rect& rect);
77 
78  bool operator==(const Rectf& other) const
79  {
80  return (m_p1 == other.m_p1 &&
81  m_size == other.m_size);
82  }
83 
84  float& get_left() { return m_p1.x; }
85  float& get_top() { return m_p1.y; }
86 
87  float get_left() const { return m_p1.x; }
88  float get_right() const { return m_p1.x + m_size.width; }
89  float get_top() const { return m_p1.y; }
90  float get_bottom() const { return m_p1.y + m_size.height; }
91 
92  float& get_width() { return m_size.width; }
93  float& get_height() { return m_size.height; }
94 
95  float get_width() const { return m_size.width; }
96  float get_height() const { return m_size.height; }
97 
98  void set_left(float v) { m_size.width -= v - m_p1.x; m_p1.x = v; }
99  void set_right(float v) { m_size.width += v - get_right(); }
100 
101  void set_top(float v) { m_size.height -= v - m_p1.y; m_p1.y = v; }
102  void set_bottom(float v) { m_size.height += v - get_bottom(); }
103 
104  Vector get_middle() const { return Vector(m_p1.x + m_size.width / 2.0f,
105  m_p1.y + m_size.height / 2.0f); }
106 
107  void set_pos(const Vector& v) { m_p1 = v; }
108 
109  void set_width(float width) { m_size.width = width; }
110  void set_height(float height) { m_size.height = height; }
111  void set_size(float width, float height) { m_size = Sizef(width, height); }
112  Sizef get_size() const { return m_size; }
113 
114  bool empty() const
115  {
116  return get_width() <= 0 ||
117  get_height() <= 0;
118  }
119 
120  void move(const Vector& v) { m_p1 += v; }
121  Rectf moved(const Vector& v) const { return Rectf(m_p1 + v, m_size); }
122 
123  bool contains(const Vector& v) const {
124  return v.x >= m_p1.x && v.y >= m_p1.y && v.x < get_right() && v.y < get_bottom();
125  }
126 
127  bool overlaps(const Rectf& other) const
128  {
129  if (get_right() < other.get_left() || get_left() > other.get_right())
130  return false;
131  if (get_bottom() < other.get_top() || get_top() > other.get_bottom())
132  return false;
133 
134  return true;
135  }
136 
137  float distance (const Vector& other, AnchorPoint ap = ANCHOR_MIDDLE) const
138  {
139  Vector v = get_anchor_pos (*this, ap);
140  return glm::distance(v, other);
141  }
142 
143  float distance (const Rectf& other, AnchorPoint ap = ANCHOR_MIDDLE) const
144  {
145  Vector v1 = get_anchor_pos(*this, ap);
146  Vector v2 = get_anchor_pos(other, ap);
147 
148  return glm::distance(v1, v2);
149  }
150 
151  Rectf grown(float border) const
152  {
153  // If the size would be shrunk below 0, do not resize.
154  if (m_size.width + border * 2 < 0.f || m_size.height + border * 2 < 0.f)
155  return *this;
156 
157  return Rectf(m_p1.x - border, m_p1.y - border,
158  get_right() + border, get_bottom() + border);
159  }
160 
161  // leave these two public to save the headaches of set/get functions for such
162  // simple things :)
163 
164  Vector p1() const { return m_p1; }
165  Vector p2() const { return Vector(m_p1.x + m_size.width, m_p1.y + m_size.height); }
166 
167  void set_p1(const Vector& p) {
168  m_size = Sizef(m_size.width + (m_p1.x - p.x),
169  m_size.height + (m_p1.y - p.y));
170  m_p1 = p;
171  }
172  void set_p2(const Vector& p) {
173  m_size = Sizef(p.x - m_p1.x,
174  p.y - m_p1.y);
175  }
176 
177  Rect to_rect() const;
178  SDL_FRect to_sdl() const
179  {
180  return { m_p1.x, m_p1.y, m_size.width, m_size.height };
181  }
182 
183 private:
185  Vector m_p1;
186  Sizef m_size;
187 };
188 
189 std::ostream& operator<<(std::ostream& out, const Rectf& rect);
190 
191 #endif
192 
193 /* EOF */
Definition: rect.hpp:30
Definition: rectf.hpp:31
Definition: sizef.hpp:26