]> git.cworth.org Git - vogl/blob - src/voglcore/vogl_rect.h
Initial vogl checkin
[vogl] / src / voglcore / vogl_rect.h
1 /**************************************************************************
2  *
3  * Copyright 2013-2014 RAD Game Tools and Valve Software
4  * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  *
25  **************************************************************************/
26
27 // File: vogl_rect.h
28 #pragma once
29
30 #include "vogl_core.h"
31 #include "vogl_vec.h"
32 #include "vogl_hash.h"
33
34 namespace vogl
35 {
36     class rect
37     {
38     public:
39         inline rect()
40         {
41         }
42
43         inline rect(eClear)
44         {
45             clear();
46         }
47
48         // up to, but not including right/bottom
49         inline rect(int left, int top, int right, int bottom)
50         {
51             set(left, top, right, bottom);
52         }
53
54         inline rect(const vec2I &lo, const vec2I &hi)
55         {
56             m_corner[0] = lo;
57             m_corner[1] = hi;
58         }
59
60         inline rect(const vec2I &point)
61         {
62             m_corner[0] = point;
63             m_corner[1].set(point[0] + 1, point[1] + 1);
64         }
65
66         inline bool operator==(const rect &r) const
67         {
68             return (m_corner[0] == r.m_corner[0]) && (m_corner[1] == r.m_corner[1]);
69         }
70
71         inline bool operator<(const rect &r) const
72         {
73             for (uint i = 0; i < 2; i++)
74             {
75                 if (m_corner[i] < r.m_corner[i])
76                     return true;
77                 else if (!(m_corner[i] == r.m_corner[i]))
78                     return false;
79             }
80
81             return false;
82         }
83
84         inline void clear()
85         {
86             m_corner[0].clear();
87             m_corner[1].clear();
88         }
89
90         inline void set(int left, int top, int right, int bottom)
91         {
92             m_corner[0].set(left, top);
93             m_corner[1].set(right, bottom);
94         }
95
96         inline void set(const vec2I &lo, const vec2I &hi)
97         {
98             m_corner[0] = lo;
99             m_corner[1] = hi;
100         }
101
102         inline void set(const vec2I &point)
103         {
104             m_corner[0] = point;
105             m_corner[1].set(point[0] + 1, point[1] + 1);
106         }
107
108         inline uint get_width() const
109         {
110             return m_corner[1][0] - m_corner[0][0];
111         }
112         inline uint get_height() const
113         {
114             return m_corner[1][1] - m_corner[0][1];
115         }
116
117         inline int get_left() const
118         {
119             return m_corner[0][0];
120         }
121         inline int get_top() const
122         {
123             return m_corner[0][1];
124         }
125         inline int get_right() const
126         {
127             return m_corner[1][0];
128         }
129         inline int get_bottom() const
130         {
131             return m_corner[1][1];
132         }
133
134         inline bool is_empty() const
135         {
136             return (m_corner[1][0] <= m_corner[0][0]) || (m_corner[1][1] <= m_corner[0][1]);
137         }
138
139         inline uint get_dimension(uint axis) const
140         {
141             return m_corner[1][axis] - m_corner[0][axis];
142         }
143         inline uint get_area() const
144         {
145             return get_dimension(0) * get_dimension(1);
146         }
147
148         inline const vec2I &operator[](uint i) const
149         {
150             VOGL_ASSERT(i < 2);
151             return m_corner[i];
152         }
153         inline vec2I &operator[](uint i)
154         {
155             VOGL_ASSERT(i < 2);
156             return m_corner[i];
157         }
158
159         inline rect &translate(int x_ofs, int y_ofs)
160         {
161             m_corner[0][0] += x_ofs;
162             m_corner[0][1] += y_ofs;
163             m_corner[1][0] += x_ofs;
164             m_corner[1][1] += y_ofs;
165             return *this;
166         }
167
168         inline rect &init_expand()
169         {
170             m_corner[0].set(INT_MAX);
171             m_corner[1].set(INT_MIN);
172             return *this;
173         }
174
175         inline rect &expand(int x, int y)
176         {
177             m_corner[0][0] = math::minimum(m_corner[0][0], x);
178             m_corner[0][1] = math::minimum(m_corner[0][1], y);
179             m_corner[1][0] = math::maximum(m_corner[1][0], x + 1);
180             m_corner[1][1] = math::maximum(m_corner[1][1], y + 1);
181             return *this;
182         }
183
184         inline rect &expand(const rect &r)
185         {
186             m_corner[0][0] = math::minimum(m_corner[0][0], r[0][0]);
187             m_corner[0][1] = math::minimum(m_corner[0][1], r[0][1]);
188             m_corner[1][0] = math::maximum(m_corner[1][0], r[1][0]);
189             m_corner[1][1] = math::maximum(m_corner[1][1], r[1][1]);
190             return *this;
191         }
192
193         inline bool touches(const rect &r) const
194         {
195             for (uint i = 0; i < 2; i++)
196             {
197                 if (r[1][i] <= m_corner[0][i])
198                     return false;
199                 else if (r[0][i] >= m_corner[1][i])
200                     return false;
201             }
202
203             return true;
204         }
205
206         inline bool fully_within(const rect &r) const
207         {
208             for (uint i = 0; i < 2; i++)
209             {
210                 if (m_corner[0][i] < r[0][i])
211                     return false;
212                 else if (m_corner[1][i] > r[1][i])
213                     return false;
214             }
215
216             return true;
217         }
218
219         inline bool intersect(const rect &r)
220         {
221             if (!touches(r))
222             {
223                 clear();
224                 return false;
225             }
226
227             for (uint i = 0; i < 2; i++)
228             {
229                 m_corner[0][i] = math::maximum<int>(m_corner[0][i], r[0][i]);
230                 m_corner[1][i] = math::minimum<int>(m_corner[1][i], r[1][i]);
231             }
232
233             return true;
234         }
235
236         inline bool contains(int x, int y) const
237         {
238             return (x >= m_corner[0][0]) && (x < m_corner[1][0]) &&
239                    (y >= m_corner[0][1]) && (y < m_corner[1][1]);
240         }
241
242         inline bool contains(const vec2I &p) const
243         {
244             return contains(p[0], p[1]);
245         }
246
247     private:
248         vec2I m_corner[2];
249     };
250
251     inline rect make_rect(uint width, uint height)
252     {
253         return rect(0, 0, width, height);
254     }
255
256 } // namespace vogl