Claw  1.7.3
rectangle.tpp
1 /*
2  CLAW - a C++ Library Absolutely Wonderful
3 
4  CLAW is a free library without any particular aim but being useful to
5  anyone.
6 
7  Copyright (C) 2005-2011 Julien Jorge
8 
9  This library is free software; you can redistribute it and/or
10  modify it under the terms of the GNU Lesser General Public
11  License as published by the Free Software Foundation; either
12  version 2.1 of the License, or (at your option) any later version.
13 
14  This library is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  Lesser General Public License for more details.
18 
19  You should have received a copy of the GNU Lesser General Public
20  License along with this library; if not, write to the Free Software
21  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 
23  contact: julien.jorge@gamned.org
24 */
25 /**
26  * \file rectangle.tpp
27  * \brief Implementation of claw::math::rectangle class.
28  * \author Julien Jorge
29  */
30 #include <algorithm>
31 
32 /*----------------------------------------------------------------------------*/
33 /**
34  * \brief Constructor.
35  */
36 template<class T>
37 claw::math::rectangle<T>::rectangle()
38 {
39 
40 } // rectangle::rectangle() [constructor]
41 
42 /*----------------------------------------------------------------------------*/
43 /**
44  * \brief Copy constructor.
45  * \param that Rectangle to copy from.
46  */
47 template<class T>
48 template<class U>
49 claw::math::rectangle<T>::rectangle( const rectangle<U>& that )
50  : position(that.position), width(that.width), height(that.height)
51 {
52 
53 } // rectangle::rectangle() [copy constructor]
54 
55 /*----------------------------------------------------------------------------*/
56 /**
57  * \brief Constructor from a box.
58  * \param that The box to copy from.
59  */
60 template<class T>
61 template<class U>
62 claw::math::rectangle<T>::rectangle( const box_2d<U>& that )
63  : position(that.left(), that.top()), width(that.width()),
64  height(that.height())
65 {
66 
67 } // rectangle::rectangle() [copy constructor]
68 
69 /*----------------------------------------------------------------------------*/
70 /**
71  * \brief Constructor with initialization.
72  * \param _x Rectangle's X-coordinate.
73  * \param _y Rectangle's Y-coordinate.
74  * \param _width Rectangle's width.
75  * \param _height Rectangle's height.
76  */
77 template<class T>
78 claw::math::rectangle<T>::rectangle
79 ( const value_type& _x, const value_type& _y,
80  const value_type& _width, const value_type& _height )
81  : position(_x, _y), width(_width), height(_height)
82 {
83 
84 } // rectangle::rectangle() [constructor with values]
85 
86 /*----------------------------------------------------------------------------*/
87 /**
88  * \brief Constructor with initialization.
89  * \param pos The position of the rectangle.
90  * \param _width Rectangle's width.
91  * \param _height Rectangle's height.
92  */
93 template<class T>
94 template<typename U>
95 claw::math::rectangle<T>::rectangle
96 ( const coordinate_2d<U>& pos, const value_type& _width,
97  const value_type& _height )
98  : position(pos), width(_width), height(_height)
99 {
100 
101 } // rectangle::rectangle() [constructor from position and size]
102 
103 /*----------------------------------------------------------------------------*/
104 /**
105  * \brief Constructor with initialization.
106  * \param pos The position of the rectangle.
107  * \param size The size of the rectangle.
108  */
109 template<class T>
110 template<typename U>
111 claw::math::rectangle<T>::rectangle
112 ( const coordinate_2d<U>& pos, const coordinate_2d<U>& size )
113  : position(pos), width(size.x), height(size.y)
114 {
115 
116 } // rectangle::rectangle() [constructor from position and size]
117 
118 /*----------------------------------------------------------------------------*/
119 /**
120  * \brief Get a copy of the rectangle by converting its members to a given type.
121  *
122  * Consider the following code:
123  *
124  * <tt> rectangle<float> a;
125  *
126  * ...
127  *
128  * rectangle<int> b(a); </tt>
129  *
130  * The copy constructor will be called, and your compiler should print some
131  * warnings in your console. These warnings have a meaning, so we don't want to
132  * make them disapear by adding explicit type conversion inside the rectangle
133  * class nor adding a cast operator that will be used silently by the compiler.
134  *
135  * If you really want to convert the type, this method will explicitly cast the
136  * member variables.
137  */
138 template<class T>
139 template<typename U>
140 claw::math::rectangle<U> claw::math::rectangle<T>::cast_value_type_to() const
141 {
142  return claw::math::rectangle<U>
143  ( position.template cast_value_type_to<U>(), (U)width, (U)height );
144 } // rectangle::cast_value_type_to()
145 
146 /*----------------------------------------------------------------------------*/
147 /**
148  * \brief Tell if this rectangle equals an other rectangle.
149  * \param that The rectangle to compare to.
150  */
151 template<class T>
152 bool claw::math::rectangle<T>::operator==( const self_type& that ) const
153 {
154  return (position == that.position) && (width == that.width)
155  && (height == that.height);
156 } // rectangle::operator==()
157 
158 /*----------------------------------------------------------------------------*/
159 /**
160  * \brief Tell if this rectangle equals an other rectangle.
161  * \param that The rectangle to compare to.
162  */
163 template<class T>
164 bool claw::math::rectangle<T>::operator!=( const self_type& that ) const
165 {
166  return !(*this == that);
167 } // rectangle::operator!=()
168 
169 /*----------------------------------------------------------------------------*/
170 /**
171  * \brief Calculate the rectangle's area.
172  */
173 template<class T>
174 typename claw::math::rectangle<T>::value_type
175 claw::math::rectangle<T>::area() const
176 {
177  return width * height;
178 } // rectangle::area()
179 
180 /*----------------------------------------------------------------------------*/
181 /**
182  * \brief Tell if a point is in a rectangle.
183  * \param p The supposed included point.
184  */
185 template<class T>
186 bool
187 claw::math::rectangle<T>::includes( const coordinate_2d<value_type>& p ) const
188 {
189  return (position.x <= p.x) && (right() >= p.x)
190  && (position.y <= p.y) && (bottom() >= p.y);
191 } // rectangle::includes()
192 
193 /*----------------------------------------------------------------------------*/
194 /**
195  * \brief Tell if a rectangle is in a rectangle.
196  * \param r The supposed included rectangle.
197  */
198 template<class T>
199 bool claw::math::rectangle<T>::includes( const self_type& r ) const
200 {
201  box_2d<value_type> his_box(r);
202 
203  return includes(his_box.first_point) && includes(his_box.second_point);
204 } // rectangle::includes() [rectangle]
205 
206 /*----------------------------------------------------------------------------*/
207 /**
208  * \brief Tell if there is an intersection of two rectangles.
209  * \param r The supposed intersecting rectangle.
210  */
211 template<class T>
212 bool claw::math::rectangle<T>::intersects( const self_type& r ) const
213 {
214  return (right() >= r.position.x)
215  && (r.right() >= position.x)
216  && (bottom() >= r.position.y)
217  && (r.bottom() >= position.y);
218 } // rectangle::intersects()
219 
220 /*----------------------------------------------------------------------------*/
221 /**
222  * \brief Intersection of two rectangles.
223  * \param r The supposed intersecting rectangle.
224  */
225 template<class T>
226 claw::math::rectangle<T>
227 claw::math::rectangle<T>::intersection( const self_type& r ) const
228 {
229  self_type result;
230 
231  if ( intersects(r) )
232  {
233  x_intersection(r, result);
234  y_intersection(r, result);
235  }
236 
237  return result;
238 } // rectangle::intersection()
239 
240 /*----------------------------------------------------------------------------*/
241 /**
242  * \brief Get the smallest rectangle bounding both this rectangle and another
243  * one.
244  * \param r The other rectangle.
245  */
246 template<class T>
247 claw::math::rectangle<T>
248 claw::math::rectangle<T>::join( const self_type& r ) const
249 {
250  const T result_left = std::min( left(), r.left() );
251  const T result_top = std::min( top(), r.top() );
252  const T result_bottom = std::max( bottom(), r.bottom() );
253  const T result_right = std::max( right(), r.right() );
254 
255  return self_type
256  ( result_left, result_top, result_right - result_left,
257  result_bottom - result_top );
258 } // rectangle::join()
259 
260 /*----------------------------------------------------------------------------*/
261 /**
262  * \brief set new position and size to the rectangle.
263  * \param new_x New x-coordinate.
264  * \param new_y New y-coordinate.
265  * \param new_width New width.
266  * \param new_height New height.
267  */
268 template<class T>
269 void claw::math::rectangle<T>::set
270 ( const value_type& new_x, const value_type& new_y,
271  const value_type& new_width, const value_type& new_height )
272 {
273  position.x = new_x;
274  position.y = new_y;
275  width = new_width;
276  height = new_height;
277 } // rectangle::set()
278 
279 /*----------------------------------------------------------------------------*/
280 /**
281  * \brief Get the x-coordinate of the left edge.
282  */
283 template<class T>
284 typename claw::math::rectangle<T>::value_type
285 claw::math::rectangle<T>::left() const
286 {
287  return position.x;
288 } // rectangle::left()
289 
290 /*----------------------------------------------------------------------------*/
291 /**
292  * \brief Get the x-coordinate of the right edge.
293  */
294 template<class T>
295 typename claw::math::rectangle<T>::value_type
296 claw::math::rectangle<T>::right() const
297 {
298  return position.x + width;
299 } // rectangle::right()
300 
301 /*----------------------------------------------------------------------------*/
302 /**
303  * \brief Get the y-coordinate of the bottom edge.
304  */
305 template<class T>
306 typename claw::math::rectangle<T>::value_type
307 claw::math::rectangle<T>::bottom() const
308 {
309  return position.y + height;
310 } // rectangle::bottom()
311 
312 /*----------------------------------------------------------------------------*/
313 /**
314  * \brief Get the y-coordinate of the top edge.
315  */
316 template<class T>
317 typename claw::math::rectangle<T>::value_type
318 claw::math::rectangle<T>::top() const
319 {
320  return position.y;
321 } // rectangle::top()
322 
323 /*----------------------------------------------------------------------------*/
324 /**
325  * \brief Get the size of the rectangle.
326  */
327 template<class T>
328 claw::math::coordinate_2d< typename claw::math::rectangle<T>::value_type >
329 claw::math::rectangle<T>::size() const
330 {
331  return claw::math::coordinate_2d<value_type>(width, height);
332 } // rectangle::size()
333 
334 /*----------------------------------------------------------------------------*/
335 /**
336  * \brief X-intersection of two rectangles.
337  * \pre There is an intersection between this and r.
338  * \post result's x and width fields are filled.
339  */
340 template<class T>
341 void claw::math::rectangle<T>::x_intersection
342 ( const self_type& r, self_type& result ) const
343 {
344  if (position.x <= r.position.x)
345  {
346  result.position.x = r.position.x;
347 
348  if (right() >= r.right())
349  result.width = r.width;
350  else
351  result.width = right() - r.position.x;
352  }
353  else
354  r.x_intersection(*this, result);
355 
356 } // rectangle::x_intersection()
357 
358 /*----------------------------------------------------------------------------*/
359 /**
360  * \brief Y-intersection of two rectangles.
361  * \pre There is an intersection between this and r.
362  * \post result's y and height fields are filled.
363  */
364 template<class T>
365 void claw::math::rectangle<T>::y_intersection
366 ( const self_type& r, self_type& result ) const
367 {
368  if (position.y <= r.position.y)
369  {
370  result.position.y = r.position.y;
371 
372  if (bottom() >= r.bottom())
373  result.height = r.height;
374  else
375  result.height = bottom() - r.position.y;
376  }
377  else
378  r.y_intersection(*this, result);
379 
380 } // rectangle::y_intersection()