Claw  1.7.3
box_2d.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 box_2d.tpp
27  * \brief Implementation of claw::math::box_2d class.
28  * \author Julien Jorge
29  */
30 #include <claw/rectangle.hpp>
31 #include <claw/assert.hpp>
32 
33 /*----------------------------------------------------------------------------*/
34 /**
35  * \brief Constructor.
36  */
37 template<class T>
38 claw::math::box_2d<T>::box_2d()
39 {
40 
41 } // box_2d::box_2d() [constructor]
42 
43 /*----------------------------------------------------------------------------*/
44 /**
45  * \brief Copy constructor.
46  * \param that Box to copy from.
47  */
48 template<class T>
49 claw::math::box_2d<T>::box_2d( const self_type& that )
50  : first_point(that.first_point), second_point(that.second_point)
51 {
52 
53 } // box_2d::box_2d() [copy constructor]
54 
55 /*----------------------------------------------------------------------------*/
56 /**
57  * \brief Constructor from a rectangle.
58  * \param that Rectangle to copy from.
59  */
60 template<class T>
61 claw::math::box_2d<T>::box_2d( const rectangle<value_type>& that )
62  : first_point(that.position),
63  second_point(that.right(), that.bottom())
64 {
65 
66 } // box_2d::box_2d() [constructor from rectangle]
67 
68 /*----------------------------------------------------------------------------*/
69 /**
70  * \brief Constructor from two points.
71  * \param p1 The first point.
72  * \param p2 The second point.
73  */
74 template<class T>
75 claw::math::box_2d<T>::box_2d( const point_type& p1, const point_type& p2 )
76  : first_point(p1), second_point(p2)
77 {
78 
79 } // box_2d::box_2d() [constructor from coordinates]
80 
81 /*----------------------------------------------------------------------------*/
82 /**
83  * \brief Constructor with initialization.
84  * \param x1 X-coordinate of the first point.
85  * \param y1 Y-coordinate of the first point.
86  * \param x2 X-coordinate of the second point.
87  * \param y2 Y-coordinate of the second point.
88  */
89 template<class T>
90 claw::math::box_2d<T>::box_2d( const value_type& x1, const value_type& y1,
91  const value_type& x2, const value_type& y2 )
92  : first_point(x1, y1), second_point(x2, y2)
93 {
94 
95 } // box_2d::box_2d() [constructor with values]
96 
97 /*----------------------------------------------------------------------------*/
98 /**
99  * \brief Set the coordinates of the two points.
100  * \param x1 X-coordinate of the first point.
101  * \param y1 Y-coordinate of the first point.
102  * \param x2 X-coordinate of the second point.
103  * \param y2 Y-coordinate of the second point.
104  */
105 template<class T>
106 void claw::math::box_2d<T>::set
107 ( const value_type& x1, const value_type& y1, const value_type& x2,
108  const value_type& y2 )
109 {
110  first_point.set(x1, y1);
111  second_point.set(x2, y2);
112 } // box_2d::set()
113 
114 /*----------------------------------------------------------------------------*/
115 /**
116  * \brief Get a copy of the box by converting its members to a given type.
117  *
118  * Consider the following code:
119  *
120  * <tt> box_2d<float> a;
121  *
122  * ...
123  *
124  * box_2d<int> b(a); </tt>
125  *
126  * The copy constructor will be called, and your compiler should print some
127  * warnings in your console. These warnings have a meaning, so we don't wan't to
128  * make them disapear by adding explicit type conversion inside the box_2d
129  * class nor adding a cast operator that will be used silently by the compiler.
130  *
131  * If you really want to convert the type, this method will explicitly cast the
132  * member variables.
133  */
134 template<class T>
135 template<typename U>
136 claw::math::box_2d<U> claw::math::box_2d<T>::cast_value_type_to() const
137 {
138  return claw::math::box_2d<U>
139  ( first_point.template cast_value_type_to<U>(),
140  second_point.template cast_value_type_to<U>() );
141 } // box_2d::cast_value_type_to()
142 
143 /*----------------------------------------------------------------------------*/
144 /**
145  * \brief Calculate the box's area.
146  */
147 template<class T>
148 typename claw::math::box_2d<T>::value_type claw::math::box_2d<T>::area() const
149 {
150  return width() * height();
151 } // box_2d::area()
152 
153 /*----------------------------------------------------------------------------*/
154 /**
155  * \brief Tell if a point is in a box.
156  * \param p The supposed included point.
157  */
158 template<class T>
159 bool
160 claw::math::box_2d<T>::includes( const coordinate_2d<value_type>& p ) const
161 {
162  return (left() <= p.x) && (right() >= p.x)
163  && (bottom() <= p.y) && (top() >= p.y);
164 } // box_2d::includes()
165 
166 /*----------------------------------------------------------------------------*/
167 /**
168  * \brief Tell if a box_2d is in a box_2d.
169  * \param r The supposed included box_2d.
170  */
171 template<class T>
172 bool claw::math::box_2d<T>::includes( const self_type& r ) const
173 {
174  return includes(r.first_point) && includes(r.second_point);
175 } // box_2d::includes()
176 
177 /*----------------------------------------------------------------------------*/
178 /**
179  * \brief Tell if there is an intersection of two boxes.
180  * \param r The supposed intersecting box.
181  */
182 template<class T>
183 bool claw::math::box_2d<T>::intersects( const self_type& r ) const
184 {
185  return (right() >= r.left()) && (r.right() >= left())
186  && (top() >= r.bottom()) && (r.top() >= bottom());
187 } // box_2d::intersects()
188 
189 /*----------------------------------------------------------------------------*/
190 /**
191  * \brief Intersection of two box_2ds.
192  * \param r The supposed intersecting box_2d.
193  */
194 template<class T>
195 claw::math::box_2d<T>
196 claw::math::box_2d<T>::intersection( const self_type& r ) const
197 {
198  CLAW_PRECOND( intersects(r) );
199 
200  self_type result;
201 
202  if ( intersects(r) )
203  {
204  x_intersection(r, result);
205  y_intersection(r, result);
206  }
207 
208  return result;
209 } // box_2d::intersection()
210 
211 /*----------------------------------------------------------------------------*/
212 /**
213  * \brief Join two box_2ds.
214  * \param r The box to join with.
215  * \returns a box containing \a *this and \a r.
216  */
217 template<class T>
218 claw::math::box_2d<T> claw::math::box_2d<T>::join( const self_type& r ) const
219 {
220  return self_type
221  ( std::min(r.left(), left()), std::min(r.bottom(), bottom()),
222  std::max(r.right(), right()), std::max(r.top(), top()) );
223 } // box_2d::join()
224 
225 /*----------------------------------------------------------------------------*/
226 /**
227  * \brief Tell if the box has a dimension equal to zero.
228  */
229 template<class T>
230 bool claw::math::box_2d<T>::empty() const
231 {
232  return (width() == 0) || (height() == 0);
233 } // box_2d::empty()
234 
235 /*----------------------------------------------------------------------------*/
236 /**
237  * \brief Get the y-coordinate of the top edge.
238  */
239 template<class T>
240 typename claw::math::box_2d<T>::value_type claw::math::box_2d<T>::top() const
241 {
242  return (first_point.y > second_point.y) ? first_point.y : second_point.y;
243 } // box_2d::top()
244 
245 /*----------------------------------------------------------------------------*/
246 /**
247  * \brief Get the y-coordinate of the bottom edge.
248  */
249 template<class T>
250 typename claw::math::box_2d<T>::value_type claw::math::box_2d<T>::bottom() const
251 {
252  return (first_point.y < second_point.y) ? first_point.y : second_point.y;
253 } // box_2d::bottom()
254 
255 /*----------------------------------------------------------------------------*/
256 /**
257  * \brief Get the x-coordinate of the left edge.
258  */
259 template<class T>
260 typename claw::math::box_2d<T>::value_type claw::math::box_2d<T>::left() const
261 {
262  return (first_point.x < second_point.x) ? first_point.x : second_point.x;
263 } // box_2d::left()
264 
265 /*----------------------------------------------------------------------------*/
266 /**
267  * \brief Get the x-coordinate of the right edge.
268  */
269 template<class T>
270 typename claw::math::box_2d<T>::value_type claw::math::box_2d<T>::right() const
271 {
272  return (first_point.x > second_point.x) ? first_point.x : second_point.x;
273 } // box_2d::right()
274 
275 /*----------------------------------------------------------------------------*/
276 /**
277  * \brief Get the coordinate of the top-left corner.
278  */
279 template<class T>
280 typename claw::math::box_2d<T>::point_type
281 claw::math::box_2d<T>::top_left() const
282 {
283  return point_type(left(), top());
284 } // box_2d::top_left()
285 
286 /*----------------------------------------------------------------------------*/
287 /**
288  * \brief Get the coordinate of the top-right corner.
289  */
290 template<class T>
291 typename claw::math::box_2d<T>::point_type
292 claw::math::box_2d<T>::top_right() const
293 {
294  return point_type(right(), top());
295 } // box_2d::top_right()
296 
297 /*----------------------------------------------------------------------------*/
298 /**
299  * \brief Get the coordinate of the bottom-left corner.
300  */
301 template<class T>
302 typename claw::math::box_2d<T>::point_type
303 claw::math::box_2d<T>::bottom_left() const
304 {
305  return point_type(left(), bottom());
306 } // box_2d::bottom_left()
307 
308 /*----------------------------------------------------------------------------*/
309 /**
310  * \brief Get the coordinate of the bottom-right corner.
311  */
312 template<class T>
313 typename claw::math::box_2d<T>::point_type
314 claw::math::box_2d<T>::bottom_right() const
315 {
316  return point_type(right(), bottom());
317 } // box_2d::bottom_right()
318 
319 /*----------------------------------------------------------------------------*/
320 /**
321  * \brief Move the top edge at a given position.
322  * \param p The position.
323  */
324 template<class T>
325 void claw::math::box_2d<T>::top( const value_type& p )
326 {
327  shift_y(p - top());
328 } // box_2d::top()
329 
330 /*----------------------------------------------------------------------------*/
331 /**
332  * \brief Move the bottom edge at a given position.
333  * \param p The position.
334  */
335 template<class T>
336 void claw::math::box_2d<T>::bottom( const value_type& p )
337 {
338  shift_y(p - bottom());
339 } // box_2d::bottom()
340 
341 /*----------------------------------------------------------------------------*/
342 /**
343  * \brief Move the left edge at a given position.
344  * \param p The position.
345  */
346 template<class T>
347 void claw::math::box_2d<T>::left( const value_type& p )
348 {
349  shift_x(p - left());
350 } // box_2d::left()
351 
352 /*----------------------------------------------------------------------------*/
353 /**
354  * \brief Move the right edge at a given position.
355  * \param p The position.
356  */
357 template<class T>
358 void claw::math::box_2d<T>::right( const value_type& p )
359 {
360  shift_x(p - right());
361 } // box_2d::right()
362 
363 /*----------------------------------------------------------------------------*/
364 /**
365  * \brief Move the top-left corner at a given position.
366  * \param p The position.
367  */
368 template<class T>
369 void
370 claw::math::box_2d<T>::top_left( const coordinate_2d<value_type>& p )
371 {
372  top(p.y);
373  left(p.x);
374 } // box_2d::top_left()
375 
376 /*----------------------------------------------------------------------------*/
377 /**
378  * \brief Move the top-right corner at a given position.
379  * \param p The position.
380  */
381 template<class T>
382 void
383 claw::math::box_2d<T>::top_right( const coordinate_2d<value_type>& p )
384 {
385  top(p.y);
386  right(p.x);
387 } // box_2d::top_right()
388 
389 /*----------------------------------------------------------------------------*/
390 /**
391  * \brief Move the bottom-left corner at a given position.
392  * \param p The position.
393  */
394 template<class T>
395 void
396 claw::math::box_2d<T>::bottom_left( const coordinate_2d<value_type>& p )
397 {
398  bottom(p.y);
399  left(p.x);
400 } // box_2d::bottom_left()
401 
402 /*----------------------------------------------------------------------------*/
403 /**
404  * \brief Move the bottom-right corner at a given position.
405  * \param p The position.
406  */
407 template<class T>
408 void claw::math::box_2d<T>::bottom_right
409 ( const coordinate_2d<value_type>& p )
410 {
411  bottom(p.y);
412  right(p.x);
413 } // box_2d::bottom_right()
414 
415 /*----------------------------------------------------------------------------*/
416 /**
417  * \brief Shift the position of the box on the x-axis.
418  * \param d The movement length.
419  */
420 template<class T>
421 void claw::math::box_2d<T>::shift_x( const value_type& d )
422 {
423  first_point.x += d;
424  second_point.x += d;
425 } // box_2d::shift_x()
426 
427 /*----------------------------------------------------------------------------*/
428 /**
429  * \brief Shift the position of the box on the y-axis.
430  * \param d The movement length.
431  */
432 template<class T>
433 void claw::math::box_2d<T>::shift_y( const value_type& d )
434 {
435  first_point.y += d;
436  second_point.y += d;
437 } // box_2d::shift_y()
438 
439 /*----------------------------------------------------------------------------*/
440 /**
441  * \brief Get the size of the box_2d.
442  */
443 template<class T>
444 claw::math::coordinate_2d< typename claw::math::box_2d<T>::value_type >
445 claw::math::box_2d<T>::size() const
446 {
447  return claw::math::coordinate_2d<value_type>(width(), height());
448 } // box_2d::size()
449 
450 /*----------------------------------------------------------------------------*/
451 /**
452  * \brief Equality operator
453  * \param that Box to compare to.
454  */
455 template<class T>
456 bool claw::math::box_2d<T>::operator==(const self_type& that) const
457 {
458  return (left() == that.left()) && (right() == that.right())
459  && (top() == that.top()) && (bottom() == that.bottom());
460 } // box_2d::operator==()
461 
462 /*----------------------------------------------------------------------------*/
463 /**
464  * \brief Difference operator.
465  * \param that Box to compare to.
466  */
467 template<class T>
468 bool claw::math::box_2d<T>::operator!=(const self_type& that) const
469 {
470  return !( *this == that );
471 } // box_2d::operator!=()
472 
473 /*----------------------------------------------------------------------------*/
474 /**
475  * \brief Translation.
476  * \param vect The vector to add to points.
477  */
478 template<class T>
479 claw::math::box_2d<T>
480 claw::math::box_2d<T>::operator+(const point_type& vect) const
481 {
482  return self_type( first_point + vect, second_point + vect );
483 } // box_2d::operator+()
484 
485 /*----------------------------------------------------------------------------*/
486 /**
487  * \brief Translation.
488  * \param vect The vector to substract to points.
489  */
490 template<class T>
491 claw::math::box_2d<T>
492 claw::math::box_2d<T>::operator-(const point_type& vect) const
493 {
494  return self_type( first_point - vect, second_point - vect );
495 } // box_2d::operator-()
496 
497 /*----------------------------------------------------------------------------*/
498 /**
499  * \brief Translation.
500  * \param vect The vector to add to points.
501  */
502 template<class T>
503 claw::math::box_2d<T>&
504 claw::math::box_2d<T>::operator+=(const point_type& vect)
505 {
506  first_point += vect;
507  second_point += vect;
508 } // box_2d::operator+=()
509 
510 /*----------------------------------------------------------------------------*/
511 /**
512  * \brief Translation.
513  * \param vect The vector to substract to points.
514  */
515 template<class T>
516 claw::math::box_2d<T>&
517 claw::math::box_2d<T>::operator-=(const point_type& vect)
518 {
519  first_point -= vect;
520  second_point -= vect;
521 } // box_2d::operator-=()
522 
523 /*----------------------------------------------------------------------------*/
524 /**
525  * \brief Return box' width.
526  */
527 template<class T>
528 typename claw::math::box_2d<T>::value_type
529 claw::math::box_2d<T>::width() const
530 {
531  if (first_point.x > second_point.x)
532  return first_point.x - second_point.x;
533  else
534  return second_point.x - first_point.x;
535 } // box_2d::width()
536 
537 /*----------------------------------------------------------------------------*/
538 /**
539  * \brief Return box' height.
540  */
541 template<class T>
542 typename claw::math::box_2d<T>::value_type
543 claw::math::box_2d<T>::height() const
544 {
545  if (first_point.y > second_point.y)
546  return first_point.y - second_point.y;
547  else
548  return second_point.y - first_point.y;
549 } // box_2d::height()
550 
551 /*----------------------------------------------------------------------------*/
552 /**
553  * \brief X-intersection of two box_2ds.
554  * \pre There is an intersection between this and r.
555  * \post result's x and width fields are filled.
556  */
557 template<class T>
558 void claw::math::box_2d<T>::x_intersection
559 ( const self_type& r, self_type& result ) const
560 {
561  result.first_point.x = std::max(left(), r.left());
562  result.second_point.x = std::min(right(), r.right());
563 } // box_2d::x_intersection()
564 
565 /*----------------------------------------------------------------------------*/
566 /**
567  * \brief Y-intersection of two box_2ds.
568  * \pre There is an intersection between this and r.
569  * \post result's y and height fields are filled.
570  */
571 template<class T>
572 void claw::math::box_2d<T>::y_intersection
573 ( const self_type& r, self_type& result ) const
574 {
575  result.first_point.y = std::max(bottom(), r.bottom());
576  result.second_point.y = std::min(top(), r.top());
577 } // box_2d::y_intersection()