TuttleOFX  1
TuttleOFX/libraries/tuttle/src/tuttle/common/math/rectOp.hpp
Go to the documentation of this file.
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