rectangle.tpp
/*
CLAW - a C++ Library Absolutely Wonderful
CLAW is a free library without any particular aim but being useful to
anyone.
Copyright (C) 2005-2011 Julien Jorge
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
contact: julien.jorge@gamned.org
*/
/**
* \file rectangle.tpp
* \brief Implementation of claw::math::rectangle class.
* \author Julien Jorge
*/
#include <algorithm>
/*----------------------------------------------------------------------------*/
/**
* \brief Constructor.
*/
template<class T>
claw::math::rectangle<T>::rectangle()
{
} // rectangle::rectangle() [constructor]
/*----------------------------------------------------------------------------*/
/**
* \brief Copy constructor.
* \param that Rectangle to copy from.
*/
template<class T>
template<class U>
claw::math::rectangle<T>::rectangle( const rectangle<U>& that )
: position(that.position), width(that.width), height(that.height)
{
} // rectangle::rectangle() [copy constructor]
/*----------------------------------------------------------------------------*/
/**
* \brief Constructor from a box.
* \param that The box to copy from.
*/
template<class T>
template<class U>
claw::math::rectangle<T>::rectangle( const box_2d<U>& that )
: position(that.left(), that.top()), width(that.width()),
height(that.height())
{
} // rectangle::rectangle() [copy constructor]
/*----------------------------------------------------------------------------*/
/**
* \brief Constructor with initialization.
* \param _x Rectangle's X-coordinate.
* \param _y Rectangle's Y-coordinate.
* \param _width Rectangle's width.
* \param _height Rectangle's height.
*/
template<class T>
claw::math::rectangle<T>::rectangle
( const value_type& _x, const value_type& _y,
const value_type& _width, const value_type& _height )
: position(_x, _y), width(_width), height(_height)
{
} // rectangle::rectangle() [constructor with values]
/*----------------------------------------------------------------------------*/
/**
* \brief Constructor with initialization.
* \param pos The position of the rectangle.
* \param _width Rectangle's width.
* \param _height Rectangle's height.
*/
template<class T>
template<typename U>
claw::math::rectangle<T>::rectangle
( const coordinate_2d<U>& pos, const value_type& _width,
const value_type& _height )
: position(pos), width(_width), height(_height)
{
} // rectangle::rectangle() [constructor from position and size]
/*----------------------------------------------------------------------------*/
/**
* \brief Constructor with initialization.
* \param pos The position of the rectangle.
* \param size The size of the rectangle.
*/
template<class T>
template<typename U>
claw::math::rectangle<T>::rectangle
( const coordinate_2d<U>& pos, const coordinate_2d<U>& size )
: position(pos), width(size.x), height(size.y)
{
} // rectangle::rectangle() [constructor from position and size]
/*----------------------------------------------------------------------------*/
/**
* \brief Get a copy of the rectangle by converting its members to a given type.
*
* Consider the following code:
*
* <tt> rectangle<float> a;
*
* ...
*
* rectangle<int> b(a); </tt>
*
* The copy constructor will be called, and your compiler should print some
* warnings in your console. These warnings have a meaning, so we don't want to
* make them disapear by adding explicit type conversion inside the rectangle
* class nor adding a cast operator that will be used silently by the compiler.
*
* If you really want to convert the type, this method will explicitly cast the
* member variables.
*/
template<class T>
template<typename U>
claw::math::rectangle<U> claw::math::rectangle<T>::cast_value_type_to() const
{
return claw::math::rectangle<U>
( position.template cast_value_type_to<U>(), (U)width, (U)height );
} // rectangle::cast_value_type_to()
/*----------------------------------------------------------------------------*/
/**
* \brief Tell if this rectangle equals an other rectangle.
* \param that The rectangle to compare to.
*/
template<class T>
bool claw::math::rectangle<T>::operator==( const self_type& that ) const
{
return (position == that.position) && (width == that.width)
&& (height == that.height);
} // rectangle::operator==()
/*----------------------------------------------------------------------------*/
/**
* \brief Tell if this rectangle equals an other rectangle.
* \param that The rectangle to compare to.
*/
template<class T>
bool claw::math::rectangle<T>::operator!=( const self_type& that ) const
{
return !(*this == that);
} // rectangle::operator!=()
/*----------------------------------------------------------------------------*/
/**
* \brief Calculate the rectangle's area.
*/
template<class T>
typename claw::math::rectangle<T>::value_type
claw::math::rectangle<T>::area() const
{
return width * height;
} // rectangle::area()
/*----------------------------------------------------------------------------*/
/**
* \brief Tell if a point is in a rectangle.
* \param p The supposed included point.
*/
template<class T>
bool
claw::math::rectangle<T>::includes( const coordinate_2d<value_type>& p ) const
{
return (position.x <= p.x) && (right() >= p.x)
&& (position.y <= p.y) && (bottom() >= p.y);
} // rectangle::includes()
/*----------------------------------------------------------------------------*/
/**
* \brief Tell if a rectangle is in a rectangle.
* \param r The supposed included rectangle.
*/
template<class T>
bool claw::math::rectangle<T>::includes( const self_type& r ) const
{
box_2d<value_type> his_box(r);
return includes(his_box.first_point) && includes(his_box.second_point);
} // rectangle::includes() [rectangle]
/*----------------------------------------------------------------------------*/
/**
* \brief Tell if there is an intersection of two rectangles.
* \param r The supposed intersecting rectangle.
*/
template<class T>
bool claw::math::rectangle<T>::intersects( const self_type& r ) const
{
return (right() >= r.position.x)
&& (r.right() >= position.x)
&& (bottom() >= r.position.y)
&& (r.bottom() >= position.y);
} // rectangle::intersects()
/*----------------------------------------------------------------------------*/
/**
* \brief Intersection of two rectangles.
* \param r The supposed intersecting rectangle.
*/
template<class T>
claw::math::rectangle<T>
claw::math::rectangle<T>::intersection( const self_type& r ) const
{
self_type result;
if ( intersects(r) )
{
x_intersection(r, result);
y_intersection(r, result);
}
return result;
} // rectangle::intersection()
/*----------------------------------------------------------------------------*/
/**
* \brief Get the smallest rectangle bounding both this rectangle and another
* one.
* \param r The other rectangle.
*/
template<class T>
claw::math::rectangle<T>
claw::math::rectangle<T>::join( const self_type& r ) const
{
const T result_left = std::min( left(), r.left() );
const T result_top = std::min( top(), r.top() );
const T result_bottom = std::max( bottom(), r.bottom() );
const T result_right = std::max( right(), r.right() );
return self_type
( result_left, result_top, result_right - result_left,
result_bottom - result_top );
} // rectangle::join()
/*----------------------------------------------------------------------------*/
/**
* \brief set new position and size to the rectangle.
* \param new_x New x-coordinate.
* \param new_y New y-coordinate.
* \param new_width New width.
* \param new_height New height.
*/
template<class T>
void claw::math::rectangle<T>::set
( const value_type& new_x, const value_type& new_y,
const value_type& new_width, const value_type& new_height )
{
position.x = new_x;
position.y = new_y;
width = new_width;
height = new_height;
} // rectangle::set()
/*----------------------------------------------------------------------------*/
/**
* \brief Get the x-coordinate of the left edge.
*/
template<class T>
typename claw::math::rectangle<T>::value_type
claw::math::rectangle<T>::left() const
{
return position.x;
} // rectangle::left()
/*----------------------------------------------------------------------------*/
/**
* \brief Get the x-coordinate of the right edge.
*/
template<class T>
typename claw::math::rectangle<T>::value_type
claw::math::rectangle<T>::right() const
{
return position.x + width;
} // rectangle::right()
/*----------------------------------------------------------------------------*/
/**
* \brief Get the y-coordinate of the bottom edge.
*/
template<class T>
typename claw::math::rectangle<T>::value_type
claw::math::rectangle<T>::bottom() const
{
return position.y + height;
} // rectangle::bottom()
/*----------------------------------------------------------------------------*/
/**
* \brief Get the y-coordinate of the top edge.
*/
template<class T>
typename claw::math::rectangle<T>::value_type
claw::math::rectangle<T>::top() const
{
return position.y;
} // rectangle::top()
/*----------------------------------------------------------------------------*/
/**
* \brief Get the size of the rectangle.
*/
template<class T>
claw::math::coordinate_2d< typename claw::math::rectangle<T>::value_type >
claw::math::rectangle<T>::size() const
{
return claw::math::coordinate_2d<value_type>(width, height);
} // rectangle::size()
/*----------------------------------------------------------------------------*/
/**
* \brief X-intersection of two rectangles.
* \pre There is an intersection between this and r.
* \post result's x and width fields are filled.
*/
template<class T>
void claw::math::rectangle<T>::x_intersection
( const self_type& r, self_type& result ) const
{
if (position.x <= r.position.x)
{
result.position.x = r.position.x;
if (right() >= r.right())
result.width = r.width;
else
result.width = right() - r.position.x;
}
else
r.x_intersection(*this, result);
} // rectangle::x_intersection()
/*----------------------------------------------------------------------------*/
/**
* \brief Y-intersection of two rectangles.
* \pre There is an intersection between this and r.
* \post result's y and height fields are filled.
*/
template<class T>
void claw::math::rectangle<T>::y_intersection
( const self_type& r, self_type& result ) const
{
if (position.y <= r.position.y)
{
result.position.y = r.position.y;
if (bottom() >= r.bottom())
result.height = r.height;
else
result.height = bottom() - r.position.y;
}
else
r.y_intersection(*this, result);
} // rectangle::y_intersection()