TuttleOFX
1
|
00001 #ifndef _TUTTLE_COMMON_MATH_RECTOP_HPP_ 00002 #define _TUTTLE_COMMON_MATH_RECTOP_HPP_ 00003 00004 #include "minmax.hpp" 00005 00006 #include <ofxCore.h> 00007 #include <boost/gil/utilities.hpp> 00008 00009 #include <cmath> 00010 #include <algorithm> 00011 00012 namespace tuttle { 00013 00014 template<class P> 00015 inline OfxRectD pointsBoundingBox( const P& a, const P& b, const P& c, const P& d ) 00016 { 00017 OfxRectD res; 00018 res.x1 = std::min( a.x, b.x, c.x, d.x ); 00019 res.y1 = std::min( a.y, b.y, c.y, d.y ); 00020 res.x2 = std::max( a.x, b.x, c.x, d.x ); 00021 res.y2 = std::max( a.y, b.y, c.y, d.y ); 00022 return res; 00023 } 00024 00025 template<typename Point2> 00026 inline OfxRectD pointsBoundingBox( const std::vector<Point2>& points ) 00027 { 00028 // if( !points.size() ) 00029 // BOOST_THROW_EXCEPTION... 00030 const Point2 p( points[0] ); 00031 OfxRectD bounds = { p.x, p.y, p.x, p.y }; 00032 00033 for( typename std::vector<Point2>::const_iterator it = points.begin(), itEnd = points.end(); 00034 it != itEnd; 00035 ++it ) 00036 { 00037 if( it->x < bounds.x1 ) 00038 bounds.x1 = it->x; 00039 else if( it->x > bounds.x2 ) 00040 bounds.x2 = it->x; 00041 00042 if( it->y < bounds.y1 ) 00043 bounds.y1 = it->y; 00044 else if( it->y > bounds.y2 ) 00045 bounds.y2 = it->y; 00046 } 00047 return bounds; 00048 } 00049 00050 template<class Point2> 00051 inline Point2 pointsMinXY( const std::vector<Point2>& points ) 00052 { 00053 // if( !points.size() ) 00054 // BOOST_THROW_EXCEPTION... 00055 Point2 p = points[0]; 00056 00057 for( typename std::vector<Point2>::const_iterator it = points.begin() + 1, itEnd = points.end(); 00058 it != itEnd; 00059 ++it ) 00060 { 00061 if( it->x < p.x ) 00062 p.x = it->x; 00063 if( it->y < p.y ) 00064 p.y = it->y; 00065 } 00066 return p; 00067 } 00068 00069 template<class Point2> 00070 inline Point2 pointsMaxXY( const std::vector<Point2>& points ) 00071 { 00072 // if( !points.size() ) 00073 // BOOST_THROW_EXCEPTION... 00074 Point2 p = points[0]; 00075 00076 for( typename std::vector<Point2>::const_iterator it = points.begin() + 1, itEnd = points.end(); 00077 it != itEnd; 00078 ++it ) 00079 { 00080 if( it->x > p.x ) 00081 p.x = it->x; 00082 if( it->y > p.y ) 00083 p.y = it->y; 00084 } 00085 return p; 00086 } 00087 00088 template<class Point, class Rect> 00089 inline bool pointInRect( const Point& p, const Rect& rec ) 00090 { 00091 Rect orientedRec; 00092 if( rec.x1 < rec.x2 ) 00093 { 00094 orientedRec.x1 = rec.x1; 00095 orientedRec.x2 = rec.x2; 00096 } 00097 else 00098 { 00099 orientedRec.x1 = rec.x2; 00100 orientedRec.x2 = rec.x1; 00101 } 00102 if( rec.y1 < rec.y2 ) 00103 { 00104 orientedRec.y1 = rec.y1; 00105 orientedRec.y2 = rec.y2; 00106 } 00107 else 00108 { 00109 orientedRec.y1 = rec.y2; 00110 orientedRec.y2 = rec.y1; 00111 } 00112 return p.x >= orientedRec.x1 && p.x <= orientedRec.x2 && 00113 p.y >= orientedRec.y1 && p.y <= orientedRec.y2; 00114 } 00115 00116 template<class Rect> 00117 inline Rect translateRegion( const Rect& windowRoW, const Rect& dependingTo ) 00118 { 00119 Rect windowOutput = windowRoW; 00120 windowOutput.x1 -= dependingTo.x1; // to output clip coordinates 00121 windowOutput.y1 -= dependingTo.y1; 00122 windowOutput.x2 -= dependingTo.x1; 00123 windowOutput.y2 -= dependingTo.y1; 00124 return windowOutput; 00125 } 00126 00127 template<class Rect, class Point> 00128 inline Rect translateRegion( const Rect& windowRoW, const Point& move ) 00129 { 00130 Rect windowOutput = windowRoW; 00131 windowOutput.x1 += move.x; 00132 windowOutput.y1 += move.y; 00133 windowOutput.x2 += move.x; 00134 windowOutput.y2 += move.y; 00135 return windowOutput; 00136 } 00137 00138 template<class R> 00139 inline R rectanglesBoundingBox( const R& a, const R& b ) 00140 { 00141 R res; 00142 res.x1 = std::min( a.x1, b.x1 ); 00143 res.x2 = std::max( res.x1, std::max( a.x2, b.x2 ) ); 00144 res.y1 = std::min( a.y1, b.y1 ); 00145 res.y2 = std::max( res.y1, std::max( a.y2, b.y2 ) ); 00146 return res; 00147 } 00148 00149 template<class R> 00150 inline R rectanglesIntersection( const R& a, const R& b ) 00151 { 00152 R res; 00153 res.x1 = std::max( a.x1, b.x1 ); 00154 res.x2 = std::max( res.x1, std::min( a.x2, b.x2 ) ); 00155 res.y1 = std::max( a.y1, b.y1 ); 00156 res.y2 = std::max( res.y1, std::min( a.y2, b.y2 ) ); 00157 return res; 00158 } 00159 00160 template<class R> 00161 inline bool rectanglesIntersect( const R& a, const R& b ) 00162 { 00163 if( (a.x2 > b.x1) || (b.x2 > a.x1) ) 00164 return false; 00165 if( (a.y2 > b.y1) || (b.y2 > a.y1) ) 00166 return false; 00167 return true; 00168 } 00169 00170 template<class R> 00171 inline bool rectangleAContainsB( const R& a, const R& b ) 00172 { 00173 return 00174 (b.x1 >= a.x1) && (b.x2 <= a.x2) && 00175 (b.y1 >= a.y1) && (b.y2 <= a.y2); 00176 } 00177 00178 template<class R> 00179 inline bool rectangleContainsAnother( const R& a, const R& b ) 00180 { 00181 return rectangleAContainsB( a, b ) || rectangleAContainsB( b, a ); 00182 } 00183 00184 template<class R, class V> 00185 inline R rectangleGrow( const R& rect, const V marge ) 00186 { 00187 R res = rect; 00188 res.x1 -= marge; 00189 res.y1 -= marge; 00190 res.x2 += marge; 00191 res.y2 += marge; 00192 return res; 00193 } 00194 00195 template<class R, class V> 00196 inline R rectangleReduce( const R& rect, const V marge ) 00197 { 00198 R res = rect; 00199 res.x1 += marge; 00200 res.y1 += marge; 00201 res.x2 -= marge; 00202 res.y2 -= marge; 00203 return res; 00204 } 00205 00206 } 00207 00208 #endif 00209