Anti-Grain Geometry - AGG (libagg)  2.5
agg-2.5/include/agg_span_interpolator_persp.h
Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 // Anti-Grain Geometry (AGG) - Version 2.5
00003 // A high quality rendering engine for C++
00004 // Copyright (C) 2002-2006 Maxim Shemanarev
00005 // Contact: mcseem@antigrain.com
00006 //          mcseemagg@yahoo.com
00007 //          http://antigrain.com
00008 // 
00009 // AGG is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU General Public License
00011 // as published by the Free Software Foundation; either version 2
00012 // of the License, or (at your option) any later version.
00013 // 
00014 // AGG is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 // GNU General Public License for more details.
00018 // 
00019 // You should have received a copy of the GNU General Public License
00020 // along with AGG; if not, write to the Free Software
00021 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
00022 // MA 02110-1301, USA.
00023 //----------------------------------------------------------------------------
00024 
00025 #ifndef AGG_SPAN_INTERPOLATOR_PERSP_INCLUDED
00026 #define AGG_SPAN_INTERPOLATOR_PERSP_INCLUDED
00027 
00028 #include "agg_trans_perspective.h"
00029 #include "agg_dda_line.h"
00030 
00031 namespace agg
00032 {
00033 
00034 
00035 
00036     //===========================================span_interpolator_persp_exact
00037     template<unsigned SubpixelShift = 8> 
00038     class span_interpolator_persp_exact
00039     {
00040     public:
00041         typedef trans_perspective trans_type;
00042         typedef trans_perspective::iterator_x iterator_type;
00043         enum subpixel_scale_e
00044         {
00045             subpixel_shift = SubpixelShift,
00046             subpixel_scale = 1 << subpixel_shift
00047         };
00048 
00049         //--------------------------------------------------------------------
00050         span_interpolator_persp_exact() {}
00051 
00052         //--------------------------------------------------------------------
00053         // Arbitrary quadrangle transformations
00054         span_interpolator_persp_exact(const double* src, const double* dst) 
00055         {
00056             quad_to_quad(src, dst);
00057         }
00058 
00059         //--------------------------------------------------------------------
00060         // Direct transformations 
00061         span_interpolator_persp_exact(double x1, double y1, 
00062                                       double x2, double y2, 
00063                                       const double* quad)
00064         {
00065             rect_to_quad(x1, y1, x2, y2, quad);
00066         }
00067 
00068         //--------------------------------------------------------------------
00069         // Reverse transformations 
00070         span_interpolator_persp_exact(const double* quad, 
00071                                       double x1, double y1, 
00072                                       double x2, double y2)
00073         {
00074             quad_to_rect(quad, x1, y1, x2, y2);
00075         }
00076 
00077         //--------------------------------------------------------------------
00078         // Set the transformations using two arbitrary quadrangles.
00079         void quad_to_quad(const double* src, const double* dst)
00080         {
00081             m_trans_dir.quad_to_quad(src, dst);
00082             m_trans_inv.quad_to_quad(dst, src);
00083         }
00084 
00085         //--------------------------------------------------------------------
00086         // Set the direct transformations, i.e., rectangle -> quadrangle
00087         void rect_to_quad(double x1, double y1, double x2, double y2, 
00088                           const double* quad)
00089         {
00090             double src[8];
00091             src[0] = src[6] = x1;
00092             src[2] = src[4] = x2;
00093             src[1] = src[3] = y1;
00094             src[5] = src[7] = y2;
00095             quad_to_quad(src, quad);
00096         }
00097 
00098 
00099         //--------------------------------------------------------------------
00100         // Set the reverse transformations, i.e., quadrangle -> rectangle
00101         void quad_to_rect(const double* quad, 
00102                           double x1, double y1, double x2, double y2)
00103         {
00104             double dst[8];
00105             dst[0] = dst[6] = x1;
00106             dst[2] = dst[4] = x2;
00107             dst[1] = dst[3] = y1;
00108             dst[5] = dst[7] = y2;
00109             quad_to_quad(quad, dst);
00110         }
00111 
00112         //--------------------------------------------------------------------
00113         // Check if the equations were solved successfully
00114         bool is_valid() const { return m_trans_dir.is_valid(); }
00115 
00116         //----------------------------------------------------------------
00117         void begin(double x, double y, unsigned len)
00118         {
00119             m_iterator = m_trans_dir.begin(x, y, 1.0);
00120             double xt = m_iterator.x;
00121             double yt = m_iterator.y;
00122 
00123             double dx;
00124             double dy;
00125             const double delta = 1/double(subpixel_scale);
00126             dx = xt + delta;
00127             dy = yt;
00128             m_trans_inv.transform(&dx, &dy);
00129             dx -= x;
00130             dy -= y;
00131             int sx1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
00132             dx = xt;
00133             dy = yt + delta;
00134             m_trans_inv.transform(&dx, &dy);
00135             dx -= x;
00136             dy -= y;
00137             int sy1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
00138 
00139             x += len;
00140             xt = x;
00141             yt = y;
00142             m_trans_dir.transform(&xt, &yt);
00143 
00144             dx = xt + delta;
00145             dy = yt;
00146             m_trans_inv.transform(&dx, &dy);
00147             dx -= x;
00148             dy -= y;
00149             int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
00150             dx = xt;
00151             dy = yt + delta;
00152             m_trans_inv.transform(&dx, &dy);
00153             dx -= x;
00154             dy -= y;
00155             int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
00156 
00157             m_scale_x = dda2_line_interpolator(sx1, sx2, len);
00158             m_scale_y = dda2_line_interpolator(sy1, sy2, len);
00159         }
00160 
00161 
00162         //----------------------------------------------------------------
00163         void resynchronize(double xe, double ye, unsigned len)
00164         {
00165             // Assume x1,y1 are equal to the ones at the previous end point 
00166             int sx1 = m_scale_x.y();
00167             int sy1 = m_scale_y.y();
00168 
00169             // Calculate transformed coordinates at x2,y2 
00170             double xt = xe;
00171             double yt = ye;
00172             m_trans_dir.transform(&xt, &yt);
00173 
00174             const double delta = 1/double(subpixel_scale);
00175             double dx;
00176             double dy;
00177 
00178             // Calculate scale by X at x2,y2
00179             dx = xt + delta;
00180             dy = yt;
00181             m_trans_inv.transform(&dx, &dy);
00182             dx -= xe;
00183             dy -= ye;
00184             int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
00185 
00186             // Calculate scale by Y at x2,y2
00187             dx = xt;
00188             dy = yt + delta;
00189             m_trans_inv.transform(&dx, &dy);
00190             dx -= xe;
00191             dy -= ye;
00192             int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
00193 
00194             // Initialize the interpolators
00195             m_scale_x = dda2_line_interpolator(sx1, sx2, len);
00196             m_scale_y = dda2_line_interpolator(sy1, sy2, len);
00197         }
00198 
00199 
00200 
00201         //----------------------------------------------------------------
00202         void operator++()
00203         {
00204             ++m_iterator;
00205             ++m_scale_x;
00206             ++m_scale_y;
00207         }
00208 
00209         //----------------------------------------------------------------
00210         void coordinates(int* x, int* y) const
00211         {
00212             *x = iround(m_iterator.x * subpixel_scale);
00213             *y = iround(m_iterator.y * subpixel_scale);
00214         }
00215 
00216         //----------------------------------------------------------------
00217         void local_scale(int* x, int* y)
00218         {
00219             *x = m_scale_x.y();
00220             *y = m_scale_y.y();
00221         }
00222 
00223         //----------------------------------------------------------------
00224         void transform(double* x, double* y) const
00225         {
00226             m_trans_dir.transform(x, y);
00227         }
00228         
00229     private:
00230         trans_type             m_trans_dir;
00231         trans_type             m_trans_inv;
00232         iterator_type          m_iterator;
00233         dda2_line_interpolator m_scale_x;
00234         dda2_line_interpolator m_scale_y;
00235     };
00236 
00237 
00238 
00239 
00240 
00241 
00242 
00243 
00244 
00245 
00246 
00247     //============================================span_interpolator_persp_lerp
00248     template<unsigned SubpixelShift = 8> 
00249     class span_interpolator_persp_lerp
00250     {
00251     public:
00252         typedef trans_perspective trans_type;
00253         enum subpixel_scale_e
00254         {
00255             subpixel_shift = SubpixelShift,
00256             subpixel_scale = 1 << subpixel_shift
00257         };
00258 
00259         //--------------------------------------------------------------------
00260         span_interpolator_persp_lerp() {}
00261 
00262         //--------------------------------------------------------------------
00263         // Arbitrary quadrangle transformations
00264         span_interpolator_persp_lerp(const double* src, const double* dst) 
00265         {
00266             quad_to_quad(src, dst);
00267         }
00268 
00269         //--------------------------------------------------------------------
00270         // Direct transformations 
00271         span_interpolator_persp_lerp(double x1, double y1, 
00272                                      double x2, double y2, 
00273                                      const double* quad)
00274         {
00275             rect_to_quad(x1, y1, x2, y2, quad);
00276         }
00277 
00278         //--------------------------------------------------------------------
00279         // Reverse transformations 
00280         span_interpolator_persp_lerp(const double* quad, 
00281                                      double x1, double y1, 
00282                                      double x2, double y2)
00283         {
00284             quad_to_rect(quad, x1, y1, x2, y2);
00285         }
00286 
00287         //--------------------------------------------------------------------
00288         // Set the transformations using two arbitrary quadrangles.
00289         void quad_to_quad(const double* src, const double* dst)
00290         {
00291             m_trans_dir.quad_to_quad(src, dst);
00292             m_trans_inv.quad_to_quad(dst, src);
00293         }
00294 
00295         //--------------------------------------------------------------------
00296         // Set the direct transformations, i.e., rectangle -> quadrangle
00297         void rect_to_quad(double x1, double y1, double x2, double y2, 
00298                           const double* quad)
00299         {
00300             double src[8];
00301             src[0] = src[6] = x1;
00302             src[2] = src[4] = x2;
00303             src[1] = src[3] = y1;
00304             src[5] = src[7] = y2;
00305             quad_to_quad(src, quad);
00306         }
00307 
00308 
00309         //--------------------------------------------------------------------
00310         // Set the reverse transformations, i.e., quadrangle -> rectangle
00311         void quad_to_rect(const double* quad, 
00312                           double x1, double y1, double x2, double y2)
00313         {
00314             double dst[8];
00315             dst[0] = dst[6] = x1;
00316             dst[2] = dst[4] = x2;
00317             dst[1] = dst[3] = y1;
00318             dst[5] = dst[7] = y2;
00319             quad_to_quad(quad, dst);
00320         }
00321 
00322         //--------------------------------------------------------------------
00323         // Check if the equations were solved successfully
00324         bool is_valid() const { return m_trans_dir.is_valid(); }
00325 
00326         //----------------------------------------------------------------
00327         void begin(double x, double y, unsigned len)
00328         {
00329             // Calculate transformed coordinates at x1,y1 
00330             double xt = x;
00331             double yt = y;
00332             m_trans_dir.transform(&xt, &yt);
00333             int x1 = iround(xt * subpixel_scale);
00334             int y1 = iround(yt * subpixel_scale);
00335 
00336             double dx;
00337             double dy;
00338             const double delta = 1/double(subpixel_scale);
00339 
00340             // Calculate scale by X at x1,y1
00341             dx = xt + delta;
00342             dy = yt;
00343             m_trans_inv.transform(&dx, &dy);
00344             dx -= x;
00345             dy -= y;
00346             int sx1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
00347 
00348             // Calculate scale by Y at x1,y1
00349             dx = xt;
00350             dy = yt + delta;
00351             m_trans_inv.transform(&dx, &dy);
00352             dx -= x;
00353             dy -= y;
00354             int sy1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
00355 
00356             // Calculate transformed coordinates at x2,y2 
00357             x += len;
00358             xt = x;
00359             yt = y;
00360             m_trans_dir.transform(&xt, &yt);
00361             int x2 = iround(xt * subpixel_scale);
00362             int y2 = iround(yt * subpixel_scale);
00363 
00364             // Calculate scale by X at x2,y2
00365             dx = xt + delta;
00366             dy = yt;
00367             m_trans_inv.transform(&dx, &dy);
00368             dx -= x;
00369             dy -= y;
00370             int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
00371 
00372             // Calculate scale by Y at x2,y2
00373             dx = xt;
00374             dy = yt + delta;
00375             m_trans_inv.transform(&dx, &dy);
00376             dx -= x;
00377             dy -= y;
00378             int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
00379 
00380             // Initialize the interpolators
00381             m_coord_x = dda2_line_interpolator(x1,  x2,  len);
00382             m_coord_y = dda2_line_interpolator(y1,  y2,  len);
00383             m_scale_x = dda2_line_interpolator(sx1, sx2, len);
00384             m_scale_y = dda2_line_interpolator(sy1, sy2, len);
00385         }
00386 
00387 
00388         //----------------------------------------------------------------
00389         void resynchronize(double xe, double ye, unsigned len)
00390         {
00391             // Assume x1,y1 are equal to the ones at the previous end point 
00392             int x1  = m_coord_x.y();
00393             int y1  = m_coord_y.y();
00394             int sx1 = m_scale_x.y();
00395             int sy1 = m_scale_y.y();
00396 
00397             // Calculate transformed coordinates at x2,y2 
00398             double xt = xe;
00399             double yt = ye;
00400             m_trans_dir.transform(&xt, &yt);
00401             int x2 = iround(xt * subpixel_scale);
00402             int y2 = iround(yt * subpixel_scale);
00403 
00404             const double delta = 1/double(subpixel_scale);
00405             double dx;
00406             double dy;
00407 
00408             // Calculate scale by X at x2,y2
00409             dx = xt + delta;
00410             dy = yt;
00411             m_trans_inv.transform(&dx, &dy);
00412             dx -= xe;
00413             dy -= ye;
00414             int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
00415 
00416             // Calculate scale by Y at x2,y2
00417             dx = xt;
00418             dy = yt + delta;
00419             m_trans_inv.transform(&dx, &dy);
00420             dx -= xe;
00421             dy -= ye;
00422             int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
00423 
00424             // Initialize the interpolators
00425             m_coord_x = dda2_line_interpolator(x1,  x2,  len);
00426             m_coord_y = dda2_line_interpolator(y1,  y2,  len);
00427             m_scale_x = dda2_line_interpolator(sx1, sx2, len);
00428             m_scale_y = dda2_line_interpolator(sy1, sy2, len);
00429         }
00430 
00431 
00432         //----------------------------------------------------------------
00433         void operator++()
00434         {
00435             ++m_coord_x;
00436             ++m_coord_y;
00437             ++m_scale_x;
00438             ++m_scale_y;
00439         }
00440 
00441         //----------------------------------------------------------------
00442         void coordinates(int* x, int* y) const
00443         {
00444             *x = m_coord_x.y();
00445             *y = m_coord_y.y();
00446         }
00447 
00448         //----------------------------------------------------------------
00449         void local_scale(int* x, int* y)
00450         {
00451             *x = m_scale_x.y();
00452             *y = m_scale_y.y();
00453         }
00454 
00455         //----------------------------------------------------------------
00456         void transform(double* x, double* y) const
00457         {
00458             m_trans_dir.transform(x, y);
00459         }
00460         
00461     private:
00462         trans_type             m_trans_dir;
00463         trans_type             m_trans_inv;
00464         dda2_line_interpolator m_coord_x;
00465         dda2_line_interpolator m_coord_y;
00466         dda2_line_interpolator m_scale_x;
00467         dda2_line_interpolator m_scale_y;
00468     };
00469 
00470 }
00471 
00472 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines