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 */
37template<class T>
38claw::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 */
48template<class T>
49claw::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 */
60template<class T>
61claw::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 */
74template<class T>
75claw::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 */
89template<class T>
90claw::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 */
105template<class T>
106void 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 */
134template<class T>
135template<typename U>
136claw::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 */
147template<class T>
148typename 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 */
158template<class T>
159bool
160claw::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 */
171template<class T>
172bool 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 */
182template<class T>
183bool 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 */
194template<class T>
195claw::math::box_2d<T>
196claw::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 */
217template<class T>
218claw::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 */
229template<class T>
230bool 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 */
239template<class T>
240typename 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 */
249template<class T>
250typename 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 */
259template<class T>
260typename 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 */
269template<class T>
270typename 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 */
279template<class T>
280typename claw::math::box_2d<T>::point_type
281claw::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 */
290template<class T>
291typename claw::math::box_2d<T>::point_type
292claw::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 */
301template<class T>
302typename claw::math::box_2d<T>::point_type
303claw::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 */
312template<class T>
313typename claw::math::box_2d<T>::point_type
314claw::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 */
324template<class T>
325void 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 */
335template<class T>
336void 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 */
346template<class T>
347void 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 */
357template<class T>
358void 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 */
368template<class T>
369void
370claw::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 */
381template<class T>
382void
383claw::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 */
394template<class T>
395void
396claw::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 */
407template<class T>
408void 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 */
420template<class T>
421void 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 */
432template<class T>
433void 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 */
443template<class T>
444claw::math::coordinate_2d< typename claw::math::box_2d<T>::value_type >
445claw::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 */
455template<class T>
456bool 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 */
467template<class T>
468bool 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 */
478template<class T>
479claw::math::box_2d<T>
480claw::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 */
490template<class T>
491claw::math::box_2d<T>
492claw::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 */
502template<class T>
503claw::math::box_2d<T>&
504claw::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 */
515template<class T>
516claw::math::box_2d<T>&
517claw::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 */
527template<class T>
528typename claw::math::box_2d<T>::value_type
529claw::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 */
541template<class T>
542typename claw::math::box_2d<T>::value_type
543claw::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 */
557template<class T>
558void 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 */
571template<class T>
572void 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()