Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | Related Pages | Examples

agg_span_gradient.h

00001 //----------------------------------------------------------------------------
00002 // Anti-Grain Geometry - Version 2.2
00003 // Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
00004 //
00005 // Permission to copy, use, modify, sell and distribute this software 
00006 // is granted provided this copyright notice appears in all copies. 
00007 // This software is provided "as is" without express or implied
00008 // warranty, and with no claim as to its suitability for any purpose.
00009 //
00010 //----------------------------------------------------------------------------
00011 // Contact: mcseem@antigrain.com
00012 //          mcseemagg@yahoo.com
00013 //          http://www.antigrain.com
00014 //----------------------------------------------------------------------------
00015 
00016 #ifndef AGG_SPAN_GRADIENT_INCLUDED
00017 #define AGG_SPAN_GRADIENT_INCLUDED
00018 
00019 #include <math.h>
00020 #include <stdlib.h>
00021 #include "agg_basics.h"
00022 #include "agg_span_generator.h"
00023 #include "agg_math.h"
00024 
00025 
00026 namespace agg
00027 {
00028 
00029     enum
00030     {
00031         gradient_subpixel_shift = 4,
00032         gradient_subpixel_size  = 1 << gradient_subpixel_shift,
00033         gradient_subpixel_mask  = gradient_subpixel_size - 1
00034     };
00035 
00036 
00037     //==========================================================span_gradient
00038     template<class ColorT, 
00039              class Interpolator,
00040              class GradientF, 
00041              class ColorF,
00042              class Allocator = span_allocator<ColorT> >
00043     class span_gradient : public span_generator<ColorT, Allocator>
00044     {
00045     public:
00046         typedef Interpolator interpolator_type;
00047         typedef Allocator alloc_type;
00048         typedef ColorT color_type;
00049         typedef span_generator<color_type, alloc_type> base_type;
00050 
00051         enum
00052         {
00053             base_shift = 8,
00054             base_size  = 1 << base_shift,
00055             base_mask  = base_size - 1,
00056             downscale_shift = interpolator_type::subpixel_shift - gradient_subpixel_shift
00057         };
00058 
00059 
00060         //--------------------------------------------------------------------
00061         span_gradient(alloc_type& alloc) : base_type(alloc) {}
00062 
00063         //--------------------------------------------------------------------
00064         span_gradient(alloc_type& alloc,
00065                       interpolator_type& inter,
00066                       const GradientF& gradient_function,
00067                       ColorF color_function,
00068                       double d1, double d2) : 
00069             base_type(alloc),
00070             m_interpolator(&inter),
00071             m_gradient_function(&gradient_function),
00072             m_color_function(color_function),
00073             m_d1(int(d1 * gradient_subpixel_size)),
00074             m_d2(int(d2 * gradient_subpixel_size))
00075         {}
00076 
00077         //--------------------------------------------------------------------
00078         interpolator_type& interpolator() { return *m_interpolator; }
00079         const GradientF& gradient_function() const { return *m_gradient_function; }
00080         const ColorF color_function() const { return m_color_function; }
00081         double d1() const { return double(m_d1) / gradient_subpixel_size; }
00082         double d2() const { return double(m_d2) / gradient_subpixel_size; }
00083 
00084         //--------------------------------------------------------------------
00085         void interpolator(interpolator_type& i) { m_interpolator = &i; }
00086         void gradient_function(const GradientF& gf) { m_gradient_function = &gf; }
00087         void color_function(ColorF cf) { m_color_function = cf; }
00088         void d1(double v) { m_d1 = int(v * gradient_subpixel_size); }
00089         void d2(double v) { m_d2 = int(v * gradient_subpixel_size); }
00090 
00091         //--------------------------------------------------------------------
00092         color_type* generate(int x, int y, unsigned len)
00093         {   
00094             color_type* span = base_type::allocator().span();
00095             int dd = m_d2 - m_d1;
00096             if(dd < 1) dd = 1;
00097             m_interpolator->begin(x+0.5, y+0.5, len);
00098             do
00099             {
00100                 m_interpolator->coordinates(&x, &y);
00101                 int d = m_gradient_function->calculate(x >> downscale_shift, 
00102                                                        y >> downscale_shift, dd);
00103                 d = ((d - m_d1) << base_shift) / dd;
00104                 if(d < 0) d = 0;
00105                 if(d > base_mask) d = base_mask;
00106                 *span++ = m_color_function[d];
00107                 ++(*m_interpolator);
00108             }
00109             while(--len);
00110             return base_type::allocator().span();
00111         }
00112 
00113     private:
00114         interpolator_type* m_interpolator;
00115         const GradientF*   m_gradient_function;
00116         ColorF             m_color_function;
00117         int                m_d1;
00118         int                m_d2;
00119     };
00120 
00121 
00122 
00123 
00124     //=====================================================gradient_linear_color
00125     template<class ColorT, unsigned BaseShift=8> 
00126     struct gradient_linear_color
00127     {
00128         typedef ColorT color_type;
00129         enum
00130         {
00131             base_shift = BaseShift,
00132             base_size  = 1 << base_shift,
00133             base_mask  = base_size - 1
00134         };
00135 
00136         gradient_linear_color() {}
00137         gradient_linear_color(const color_type& c1, const color_type& c2) :
00138             m_c1(c1), m_c2(c2) {}
00139 
00140         color_type operator [] (unsigned v) const 
00141         {
00142             return m_c1.gradient(m_c2, double(v) / double(base_mask));
00143         }
00144 
00145         void colors(const color_type& c1, const color_type& c2)
00146         {
00147             m_c1 = c1;
00148             m_c2 = c2;
00149         }
00150 
00151         color_type m_c1;
00152         color_type m_c2;
00153     };
00154 
00155 
00156     //==========================================================gradient_circle
00157     class gradient_circle
00158     {
00159         // Actually the same as radial. Just for compatibility
00160     public:
00161         static int calculate(int x, int y, int)
00162         {
00163             return int(fast_sqrt(x*x + y*y));
00164         }
00165     };
00166 
00167 
00168     //==========================================================gradient_radial
00169     class gradient_radial
00170     {
00171     public:
00172         static int calculate(int x, int y, int)
00173         {
00174             return int(fast_sqrt(x*x + y*y));
00175         }
00176     };
00177 
00178 
00179     //========================================================gradient_radial_d
00180     class gradient_radial_d
00181     {
00182     public:
00183         static int calculate(int x, int y, int)
00184         {
00185             return int(sqrt(double(x)*double(x) + double(y)*double(y)));
00186         }
00187     };
00188 
00189 
00190     //====================================================gradient_radial_focus
00191     class gradient_radial_focus
00192     {
00193     public:
00194         //---------------------------------------------------------------------
00195         gradient_radial_focus() : 
00196             m_radius(100 * gradient_subpixel_size), 
00197             m_focus_x(0), 
00198             m_focus_y(0)
00199         {
00200             update_values();
00201         }
00202 
00203         //---------------------------------------------------------------------
00204         gradient_radial_focus(double r, double fx, double fy) : 
00205             m_radius (int(r  * gradient_subpixel_size)), 
00206             m_focus_x(int(fx * gradient_subpixel_size)), 
00207             m_focus_y(int(fy * gradient_subpixel_size))
00208         {
00209             update_values();
00210         }
00211 
00212         //---------------------------------------------------------------------
00213         void init(double r, double fx, double fy)
00214         {
00215             m_radius  = int(r  * gradient_subpixel_size);
00216             m_focus_x = int(fx * gradient_subpixel_size);
00217             m_focus_y = int(fy * gradient_subpixel_size);
00218             update_values();
00219         }
00220 
00221         //---------------------------------------------------------------------
00222         double radius()  const { return double(m_radius)  / gradient_subpixel_size; }
00223         double focus_x() const { return double(m_focus_x) / gradient_subpixel_size; }
00224         double focus_y() const { return double(m_focus_y) / gradient_subpixel_size; }
00225 
00226         //---------------------------------------------------------------------
00227         int calculate(int x, int y, int d) const
00228         {
00229             double solution_x;
00230             double solution_y;
00231 
00232             // Special case to avoid divide by zero or very near zero
00233             //---------------------------------
00234             if(x == int(m_focus_x))
00235             {          
00236                 solution_x = m_focus_x;
00237                 solution_y = 0.0;
00238                 solution_y += (y > m_focus_y) ? m_trivial : -m_trivial;
00239             }
00240             else 
00241             {    
00242                 // Slope of the focus-current line
00243                 //-------------------------------
00244                 double slope = double(y - m_focus_y) / double(x - m_focus_x);
00245 
00246                 // y-intercept of that same line
00247                 //--------------------------------
00248                 double yint  = double(y) - (slope * x); 
00249         
00250                 // Use the classical quadratic formula to calculate 
00251                 // the intersection point         
00252                 //--------------------------------
00253                 double a = (slope * slope) + 1; 
00254                 double b =  2 * slope * yint;
00255                 double c =  yint * yint - m_radius2;
00256                 double det = sqrt((b * b) - (4.0 * a * c));
00257                 solution_x = -b;
00258         
00259                 // Choose the positive or negative root depending
00260                 // on where the X coord lies with respect to the focus.
00261                 solution_x += (x < m_focus_x) ? -det : det;
00262                 solution_x /= 2.0 * a;
00263 
00264                 // Calculating of Y is trivial
00265                 solution_y  = (slope * solution_x) + yint;
00266             }                           
00267 
00268             // Calculate the percentage (0...1) of the current point along the 
00269             // focus-circumference line and return the normalized (0...d) value
00270             //-------------------------------
00271             solution_x -= double(m_focus_x);
00272             solution_y -= double(m_focus_y);
00273             double int_to_focus = solution_x * solution_x + solution_y * solution_y;
00274             double cur_to_focus = double(x - m_focus_x) * double(x - m_focus_x) +
00275                                   double(y - m_focus_y) * double(y - m_focus_y);
00276 
00277             return int(sqrt(cur_to_focus / int_to_focus) * d);
00278         }
00279 
00280     private:
00281         //---------------------------------------------------------------------
00282         void update_values()
00283         {
00284             // For use in the quadractic equation
00285             //-------------------------------
00286             m_radius2 = double(m_radius) * double(m_radius);
00287 
00288             double dist = sqrt(double(m_focus_x) * double(m_focus_x) + 
00289                                double(m_focus_y) * double(m_focus_y));
00290 
00291             // Test if distance from focus to center is greater than the radius
00292             // For the sake of assurance factor restrict the point to be 
00293             // no further than 99% of the radius.
00294             //-------------------------------
00295             double r = m_radius * 0.99;
00296             if(dist > r) 
00297             { 
00298                 // clamp focus to radius
00299                 // x = r cos theta, y = r sin theta
00300                 //------------------------
00301                 double a = atan2(double(m_focus_y), double(m_focus_x));
00302                 m_focus_x = int(r * cos(a));
00303                 m_focus_y = int(r * sin(a));
00304             }
00305 
00306             // Calculate the solution to be used in the case where x == focus_x
00307             //------------------------------
00308             m_trivial = sqrt(m_radius2 - (m_focus_x * m_focus_x));
00309         }
00310 
00311         int m_radius;
00312         int m_focus_x;
00313         int m_focus_y;
00314         double m_radius2;
00315         double m_trivial;
00316     };
00317 
00318 
00319 
00320     //==============================================================gradient_x
00321     class gradient_x
00322     {
00323     public:
00324         static int calculate(int x, int, int) { return x; }
00325     };
00326 
00327 
00328     //==============================================================gradient_y
00329     class gradient_y
00330     {
00331     public:
00332         static int calculate(int, int y, int) { return y; }
00333     };
00334 
00335 
00336     //========================================================gradient_diamond
00337     class gradient_diamond
00338     {
00339     public:
00340         static int calculate(int x, int y, int) 
00341         { 
00342             int ax = abs(x);
00343             int ay = abs(y);
00344             return ax > ay ? ax : ay; 
00345         }
00346     };
00347 
00348 
00349     //=============================================================gradient_xy
00350     class gradient_xy
00351     {
00352     public:
00353         static int calculate(int x, int y, int d) 
00354         { 
00355             return abs(x) * abs(y) / d; 
00356         }
00357     };
00358 
00359 
00360     //========================================================gradient_sqrt_xy
00361     class gradient_sqrt_xy
00362     {
00363     public:
00364         static int calculate(int x, int y, int) 
00365         { 
00366             return fast_sqrt(abs(x) * abs(y)); 
00367         }
00368     };
00369 
00370 
00371     //==========================================================gradient_conic
00372     class gradient_conic
00373     {
00374     public:
00375         static int calculate(int x, int y, int d) 
00376         { 
00377             return int(fabs(atan2(double(y), double(x))) * double(d) / pi);
00378         }
00379     };
00380 
00381 
00382     //=================================================gradient_repeat_adaptor
00383     template<class GradientF> class gradient_repeat_adaptor
00384     {
00385     public:
00386         gradient_repeat_adaptor(const GradientF& gradient) : 
00387             m_gradient(&gradient) {}
00388 
00389         int calculate(int x, int y, int d) const
00390         {
00391             int ret = m_gradient->calculate(x, y, d) % d;
00392             if(ret < 0) ret += d;
00393             return ret;
00394         }
00395 
00396     private:
00397         const GradientF* m_gradient;
00398     };
00399 
00400 
00401     //================================================gradient_reflect_adaptor
00402     template<class GradientF> class gradient_reflect_adaptor
00403     {
00404     public:
00405         gradient_reflect_adaptor(const GradientF& gradient) : 
00406             m_gradient(&gradient) {}
00407 
00408         int calculate(int x, int y, int d) const
00409         {
00410             int d2 = d << 1;
00411             int ret = m_gradient->calculate(x, y, d) % d2;
00412             if(ret <  0) ret += d2;
00413             if(ret >= d) ret  = d2 - ret;
00414             return ret;
00415         }
00416 
00417     private:
00418         const GradientF* m_gradient;
00419     };
00420 
00421 
00422 }
00423 
00424 #endif

Generated on Wed Feb 9 11:31:35 2005 for OpenGUI by  doxygen 1.4.0