TuttleOFX  1
Rect.hpp
Go to the documentation of this file.
00001 #ifndef _TERRY_MATH_RECT_HPP_
00002 #define _TERRY_MATH_RECT_HPP_
00003 
00004 #include <boost/gil/utilities.hpp>
00005 
00006 #include <cmath>
00007 #include <algorithm>
00008 #include <iostream>
00009 
00010 namespace terry {
00011 
00012 using namespace boost::gil;
00013 
00014 template <typename T>
00015 class Rect {
00016 public:
00017     typedef T value_type;
00018     static const std::size_t num_dimensions = 4;
00019 
00020     Rect() : x1(0), y1(0), x2(0), y2(0) {}
00021     Rect( const T nX1, const T nY1, const T nX2, const T nY2 )
00022                 : x1(nX1), y1(nY1)
00023                 , x2(nX2), y2(nY2)
00024         {}
00025     Rect(const Rect& r)
00026                 : x1(r.x1), y1(r.y1)
00027                 , x2(r.x2), y2(r.y2)
00028         {}
00029         template<class OtherRect>
00030     Rect(const OtherRect& r)
00031                 : x1(r.x1), y1(r.y1)
00032                 , x2(r.x2), y2(r.y2)
00033         {}
00034     ~Rect() {}
00035 
00036     Rect& operator=(const Rect& r) { x1=r.x1; y1=r.y1; x2=r.x2; y2=r.y2; return *this; }
00037 
00038     const T& operator[](const std::size_t i)          const   { return this->*mem_array[i]; }
00039           T& operator[](const std::size_t i)                  { return this->*mem_array[i]; }
00040 
00041     point2<T> cornerMin() const { return point2<T>(x1, y1); }
00042     point2<T> cornerMax() const { return point2<T>(x2, y2); }
00043     
00044         // return unsigned ?
00045     point2<T> size() const { return point2<T>(x2-x1, y2-y1); }
00046 
00047     T x1,y1,x2,y2;
00048         
00049 private:
00050     // this static array of pointers to member variables makes operator[] safe and doesn't seem to exhibit any performance penalty
00051     static T Rect<T>::* const mem_array[num_dimensions];
00052 };
00053 
00054 template <typename T>
00055 T Rect<T>::* const Rect<T>::mem_array[Rect<T>::num_dimensions] = { &Rect<T>::x1, &Rect<T>::y1, &Rect<T>::x2, &Rect<T>::y2 };
00056 
00057 
00058 template <typename T>
00059 std::ostream& operator<<( std::ostream& os, const Rect<T>& rect )
00060 {
00061         os << "{ "
00062            << rect.x1 << ", " <<  rect.y1 << ", "
00063            << rect.x2 << ", " <<  rect.y2
00064            << " }";
00065         return os;
00066 }
00067 
00068 /**
00069  * @brief Retrieve the bounding box of an image [0, 0, width, height].
00070  */
00071 template<typename T, class View>
00072 Rect<T> getBounds( const View& v )
00073 {
00074         return Rect<T>( 0, 0, v.width(), v.height() );
00075 }
00076 
00077 template<class Point, class Rect>
00078 inline bool pointInRect( const Point& p, const Rect& rec )
00079 {
00080         Rect orientedRec;
00081         if( rec.x1 < rec.x2 )
00082         {
00083                 orientedRec.x1 = rec.x1;
00084                 orientedRec.x2 = rec.x2;
00085         }
00086         else
00087         {
00088                 orientedRec.x1 = rec.x2;
00089                 orientedRec.x2 = rec.x1;
00090         }
00091         if( rec.y1 < rec.y2 )
00092         {
00093                 orientedRec.y1 = rec.y1;
00094                 orientedRec.y2 = rec.y2;
00095         }
00096         else
00097         {
00098                 orientedRec.y1 = rec.y2;
00099                 orientedRec.y2 = rec.y1;
00100         }
00101         return p.x >= orientedRec.x1 && p.x <= orientedRec.x2 &&
00102                p.y >= orientedRec.y1 && p.y <= orientedRec.y2;
00103 }
00104 
00105 
00106 template<class Rect>
00107 inline Rect translateRegion( const Rect& windowRoW, const Rect& dependingTo )
00108 {
00109         Rect windowOutput = windowRoW;
00110         windowOutput.x1 -= dependingTo.x1; // to output clip coordinates
00111         windowOutput.y1 -= dependingTo.y1;
00112         windowOutput.x2 -= dependingTo.x1;
00113         windowOutput.y2 -= dependingTo.y1;
00114         return windowOutput;
00115 }
00116 
00117 template<class Rect, class Point>
00118 inline Rect translateRegion( const Rect& windowRoW, const Point& move )
00119 {
00120         Rect windowOutput = windowRoW;
00121         windowOutput.x1 += move.x;
00122         windowOutput.y1 += move.y;
00123         windowOutput.x2 += move.x;
00124         windowOutput.y2 += move.y;
00125         return windowOutput;
00126 }
00127 
00128 template<class Rect>
00129 inline Rect translateRegion( const Rect& windowRoW, const std::ptrdiff_t x, const std::ptrdiff_t y )
00130 {
00131         Rect windowOutput = windowRoW;
00132         windowOutput.x1 += x;
00133         windowOutput.y1 += y;
00134         windowOutput.x2 += x;
00135         windowOutput.y2 += y;
00136         return windowOutput;
00137 }
00138 
00139 template<class R>
00140 inline R rectanglesBoundingBox( const R& a, const R& b )
00141 {
00142         R res;
00143         res.x1 = std::min( a.x1, b.x1 );
00144         res.x2 = std::max( res.x1, std::max( a.x2, b.x2 ) );
00145         res.y1 = std::min( a.y1, b.y1 );
00146         res.y2 = std::max( res.y1, std::max( a.y2, b.y2 ) );
00147         return res;
00148 }
00149 
00150 template<class R>
00151 inline R rectanglesIntersection( const R& a, const R& b )
00152 {
00153         R res;
00154         res.x1 = std::max( a.x1, b.x1 );
00155         res.x2 = std::max( res.x1, std::min( a.x2, b.x2 ) );
00156         res.y1 = std::max( a.y1, b.y1 );
00157         res.y2 = std::max( res.y1, std::min( a.y2, b.y2 ) );
00158         return res;
00159 }
00160 
00161 template<class R, class V>
00162 inline R rectangleGrow( const R& rect, const V marge )
00163 {
00164         R res = rect;
00165         res.x1 -= marge;
00166         res.y1 -= marge;
00167         res.x2 += marge;
00168         res.y2 += marge;
00169         return res;
00170 }
00171 
00172 template<class R, class V>
00173 inline R rectangleReduce( const R& rect, const V marge )
00174 {
00175         R res = rect;
00176         res.x1 += marge;
00177         res.y1 += marge;
00178         res.x2 -= marge;
00179         res.y2 -= marge;
00180         return res;
00181 }
00182 
00183 
00184 }
00185 
00186 #endif