TuttleOFX  1
ColorGrandient1DLinearFunctor.hpp
Go to the documentation of this file.
00001 #ifndef _TUTTLE_PLUGIN_COLORGRADIENT_1DLINEARFUNCTOR_HPP_
00002 #define _TUTTLE_PLUGIN_COLORGRADIENT_1DLINEARFUNCTOR_HPP_
00003 
00004 #include "../ColorGradientDefinitions.hpp"
00005 
00006 #include <tuttle/plugin/global.hpp>
00007 
00008 #include <terry/globals.hpp>
00009 #include <terry/point/operations.hpp>
00010 #include <terry/numeric/operations.hpp>
00011 
00012 #include <boost/gil/gil_all.hpp>
00013 #include <boost/math/special_functions/pow.hpp>
00014 
00015 #include <cmath>
00016 #include <vector>
00017 
00018 namespace tuttle {
00019 namespace plugin {
00020 namespace colorGradient {
00021 typedef boost::gil::point2<double> point_t;
00022 
00023 class LineEquation
00024 {
00025 double _a, _b, _c;     ///< equation
00026 point_t _AB;     ///< BC vector
00027 
00028 public:
00029         LineEquation() {}
00030         LineEquation( const point_t& A, const point_t& B )
00031                 : _AB( B - A )
00032         {
00033                 // compute equation BC, ax + by + c = 0
00034                 _a = B.y - A.y;
00035                 _b = A.x - B.x;
00036                 _c = ( A.y - B.y ) * A.x + ( B.x - A.x ) * A.y;
00037         }
00038 
00039         template <class Point>
00040         Point pointOrthogonalProjection( const Point& p ) const
00041         {
00042                 // compute coordinates of M, the orthogonal projection of p on current line
00043                 Point res;
00044 
00045                 res.y = ( -( _a * p.x ) - ( _a * _AB.y * p.y / _AB.x ) - _c ) / ( _b - ( _a * _AB.y / _AB.x ) );
00046                 res.x = ( -_c - _b * res.y ) / _a;
00047                 return res;
00048         }
00049 
00050 };
00051 
00052 // Models a Unary Function
00053 template <typename P>
00054 // Models PixelValueConcept
00055 class ColorGrandient1DLinearFunctor
00056 {
00057 public:
00058         typedef boost::gil::point2<double> point_t;
00059 
00060         typedef ColorGrandient1DLinearFunctor const_t;
00061         typedef P value_type;
00062         typedef value_type reference;
00063         typedef value_type const_reference;
00064         typedef point_t argument_type;
00065         typedef reference result_type;
00066         BOOST_STATIC_CONSTANT( bool, is_mutable = false );
00067 
00068         /*
00069            struct ColoredPoint
00070            {
00071             point_t _position;
00072             value_type _color;
00073            };
00074          */
00075         std::vector<point_t> _points;
00076         std::vector<value_type> _colors;
00077         std::vector<double> _distanceToB;
00078         LineEquation _droiteEquation;
00079         point_t _pB; ///< point B
00080         point_t _pC; ///< point C
00081 
00082         ColorGrandient1DLinearFunctor() {}
00083 
00084         ColorGrandient1DLinearFunctor( const point_t& size, const std::vector<point_t>& points, const std::vector<value_type>& colors )
00085                 : _points( points )
00086                 , _colors( colors )
00087         {
00088                 assert( _points.size() == _colors.size() );
00089                 assert( _points.size() >= 2 );
00090 
00091                 _pB             = _points[0] * size; // to canonical coordinates
00092                 _pC             = _points[1] * size;
00093                 _droiteEquation = LineEquation( _pB, _pC );
00094 
00095                 // fill _distanceToB
00096                 _distanceToB.reserve( _points.size() );
00097                 for( std::vector<point_t>::const_iterator it = _points.begin(), itEnd = _points.end();
00098                      it != itEnd;
00099                      ++it )
00100                 {
00101                         _distanceToB.push_back( distance( *it, _pB ) );
00102                 }
00103                 // sort _points, _colors, _distanceToB
00104         }
00105 
00106         double distance( const point_t& a, const point_t& b ) const
00107         {
00108                 return std::sqrt( boost::math::pow<2>( b.x - a.x ) + boost::math::pow<2>( b.y - a.y ) );
00109         }
00110 
00111         result_type operator()( const point_t& pA ) const
00112         {
00113                 using namespace boost::gil;
00114                 using namespace terry;
00115                 using namespace terry::numeric;
00116                 point_t pM = _droiteEquation.pointOrthogonalProjection( pA );
00117                 //              TUTTLE_LOG_INFO( "________________________________________" );
00118                 //              TUTTLE_LOG_VAR( TUTTLE_INFO, _pB );
00119                 //              TUTTLE_LOG_VAR( TUTTLE_INFO, _pC );
00120                 //              TUTTLE_LOG_VAR( TUTTLE_INFO, pA );
00121                 //              TUTTLE_LOG_VAR( TUTTLE_INFO, pM );
00122                 double distB = distance( pM, _pB );
00123                 double distC = distance( pM, _pC );
00124                 double norm  = distB + distC;
00125                 //              TUTTLE_LOG_VAR3( TUTTLE_INFO, distB, distC, norm );
00126                 distB /= norm;
00127                 distC /= norm;
00128                 //              TUTTLE_LOG_VAR2( TUTTLE_INFO,  _pB, _pC );
00129                 //              TUTTLE_LOG_VAR2( TUTTLE_INFO, distB, distC );
00130                 // distB * _colors[0] + distC * _colors[1];
00131                 return pixel_plus_t<result_type, result_type, result_type>() (
00132                            pixel_multiplies_scalar_t<result_type, double, result_type>() ( _colors[0], distB ),
00133                            pixel_multiplies_scalar_t<result_type, double, result_type>() ( _colors[1], distC )
00134                            );
00135         }
00136 
00137 };
00138 
00139 }
00140 }
00141 }
00142 
00143 #endif