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 "math/anchor_point.hpp"
24#include "math/sizef.hpp"
25#include "math/vector.hpp"
26
27class Rect;
28
29class Rectf final
30{
31public:
32 static Rectf from_center(const Vector& center, const Sizef& size)
33 {
34 return Rectf(center.x - size.width / 2.0f,
35 center.y - size.height / 2.0f,
36 center.x + size.width / 2.0f,
37 center.y + size.height / 2.0f);
38 }
39
40public:
41 Rectf() :
42 m_p1(),
43 m_size()
44 { }
45
46 Rectf(const Rectf& rhs) = default;
47 Rectf& operator=(const Rectf& rhs) = default;
48
49 Rectf(const Vector& np1, const Vector& np2) :
50 m_p1(np1), m_size(np2.x - np1.x, np2.y - np1.y)
51 {
52 }
53
54 Rectf(float x1, float y1, float x2, float y2) :
55 m_p1(x1, y1), m_size(x2 - x1, y2 - y1)
56 {
57 assert(m_size.width >= 0 &&
58 m_size.height >= 0);
59 }
60
61 Rectf(const Vector& p1, const Sizef& size) :
62 m_p1(p1),
63 m_size(size)
64 {
65 }
66
67 Rectf(const Rect& rect);
68
69 bool operator==(const Rectf& other) const
70 {
71 return (m_p1 == other.m_p1 &&
72 m_size == other.m_size);
73 }
74
75 // This is a temporary hack to pass x/y to ReaderMapping
76 float& get_left() { return m_p1.x; }
77 float& get_top() { return m_p1.y; }
78
79 float get_left() const { return m_p1.x; }
80 float get_right() const { return m_p1.x + m_size.width; }
81 float get_top() const { return m_p1.y; }
82 float get_bottom() const { return m_p1.y + m_size.height; }
83
84 float get_width() const { return m_size.width; }
85 float get_height() const { return m_size.height; }
86
87 void set_left(float v) { m_size.width -= v - m_p1.x; m_p1.x = v; }
88 void set_right(float v) { m_size.width += v - get_right(); }
89
90 void set_top(float v) { m_size.height -= v - m_p1.y; m_p1.y = v; }
91 void set_bottom(float v) { m_size.height += v - get_bottom(); }
92
93 Vector get_middle() const { return Vector(m_p1.x + m_size.width / 2.0f,
94 m_p1.y + m_size.height / 2.0f); }
95
96 void set_pos(const Vector& v) { m_p1 = v; }
97
98 void set_width(float width) { m_size.width = width; }
99 void set_height(float height) { m_size.height = height; }
100 void set_size(float width, float height) { m_size = Sizef(width, height); }
101 Sizef get_size() const { return m_size; }
102
103 void move(const Vector& v) { m_p1 += v; }
104 Rectf moved(const Vector& v) const { return Rectf(m_p1 + v, m_size); }
105
106 bool contains(const Vector& v) const {
107 return v.x >= m_p1.x && v.y >= m_p1.y && v.x < get_right() && v.y < get_bottom();
108 }
109
110 bool contains(const Rectf& other) const
111 {
112 // FIXME: This is overlaps(), not contains()!
113 if (m_p1.x >= other.get_right() || other.get_left() >= get_right())
114 return false;
115 if (m_p1.y >= other.get_bottom() || other.get_top() >= get_bottom())
116 return false;
117
118 return true;
119 }
120
121 float distance (const Vector& other, AnchorPoint ap = ANCHOR_MIDDLE) const
122 {
123 Vector v = get_anchor_pos (*this, ap);
124 return ((v - other).norm ());
125 }
126
127 float distance (const Rectf& other, AnchorPoint ap = ANCHOR_MIDDLE) const
128 {
129 Vector v1 = get_anchor_pos(*this, ap);
130 Vector v2 = get_anchor_pos(other, ap);
131
132 return ((v1 - v2).norm ());
133 }
134
135 Rectf grown(float border) const
136 {
137 return Rectf(m_p1.x - border, m_p1.y - border,
138 get_right() + border, get_bottom() + border);
139 }
140
141 // leave these two public to save the headaches of set/get functions for such
142 // simple things :)
143
144 Vector p1() const { return m_p1; }
145 Vector p2() const { return Vector(m_p1.x + m_size.width, m_p1.y + m_size.height); }
146
147 void set_p1(const Vector& p) {
148 m_size = Sizef(m_size.width + (m_p1.x - p.x),
149 m_size.height + (m_p1.y - p.y));
150 m_p1 = p;
151 }
152 void set_p2(const Vector& p) {
153 m_size = Sizef(p.x - m_p1.x,
154 p.y - m_p1.y);
155 }
156
157private:
158 /// upper left edge
159 Vector m_p1;
160 Sizef m_size;
161};
162
163std::ostream& operator<<(std::ostream& out, const Rectf& rect);
164
165#endif
166
167/* EOF */
168