TuttleOFX
1
|
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