Anti-Grain Geometry - AGG (libagg)  2.5
agg-2.5/include/agg_trans_affine.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_TRANS_AFFINE_INCLUDED
00026 #define AGG_TRANS_AFFINE_INCLUDED
00027 
00028 #include <math.h>
00029 #include "agg_basics.h"
00030 
00031 namespace agg
00032 {
00033     const double affine_epsilon = 1e-14; 
00034 
00035     //============================================================trans_affine
00036     //
00037     // See Implementation agg_trans_affine.cpp
00038     //
00039     // Affine transformation are linear transformations in Cartesian coordinates
00040     // (strictly speaking not only in Cartesian, but for the beginning we will 
00041     // think so). They are rotation, scaling, translation and skewing.  
00042     // After any affine transformation a line segment remains a line segment 
00043     // and it will never become a curve. 
00044     //
00045     // There will be no math about matrix calculations, since it has been 
00046     // described many times. Ask yourself a very simple question:
00047     // "why do we need to understand and use some matrix stuff instead of just 
00048     // rotating, scaling and so on". The answers are:
00049     //
00050     // 1. Any combination of transformations can be done by only 4 multiplications
00051     //    and 4 additions in floating point.
00052     // 2. One matrix transformation is equivalent to the number of consecutive
00053     //    discrete transformations, i.e. the matrix "accumulates" all transformations 
00054     //    in the order of their settings. Suppose we have 4 transformations: 
00055     //       * rotate by 30 degrees,
00056     //       * scale X to 2.0, 
00057     //       * scale Y to 1.5, 
00058     //       * move to (100, 100). 
00059     //    The result will depend on the order of these transformations, 
00060     //    and the advantage of matrix is that the sequence of discret calls:
00061     //    rotate(30), scaleX(2.0), scaleY(1.5), move(100,100) 
00062     //    will have exactly the same result as the following matrix transformations:
00063     //   
00064     //    affine_matrix m;
00065     //    m *= rotate_matrix(30); 
00066     //    m *= scaleX_matrix(2.0);
00067     //    m *= scaleY_matrix(1.5);
00068     //    m *= move_matrix(100,100);
00069     //
00070     //    m.transform_my_point_at_last(x, y);
00071     //
00072     // What is the good of it? In real life we will set-up the matrix only once
00073     // and then transform many points, let alone the convenience to set any 
00074     // combination of transformations.
00075     //
00076     // So, how to use it? Very easy - literally as it's shown above. Not quite,
00077     // let us write a correct example:
00078     //
00079     // agg::trans_affine m;
00080     // m *= agg::trans_affine_rotation(30.0 * 3.1415926 / 180.0);
00081     // m *= agg::trans_affine_scaling(2.0, 1.5);
00082     // m *= agg::trans_affine_translation(100.0, 100.0);
00083     // m.transform(&x, &y);
00084     //
00085     // The affine matrix is all you need to perform any linear transformation,
00086     // but all transformations have origin point (0,0). It means that we need to 
00087     // use 2 translations if we want to rotate someting around (100,100):
00088     // 
00089     // m *= agg::trans_affine_translation(-100.0, -100.0);         // move to (0,0)
00090     // m *= agg::trans_affine_rotation(30.0 * 3.1415926 / 180.0);  // rotate
00091     // m *= agg::trans_affine_translation(100.0, 100.0);           // move back to (100,100)
00092     //----------------------------------------------------------------------
00093     struct trans_affine
00094     {
00095         double sx, shy, shx, sy, tx, ty;
00096 
00097         //------------------------------------------ Construction
00098         // Identity matrix
00099         trans_affine() :
00100             sx(1.0), shy(0.0), shx(0.0), sy(1.0), tx(0.0), ty(0.0)
00101         {}
00102 
00103         // Custom matrix. Usually used in derived classes
00104         trans_affine(double v0, double v1, double v2, 
00105                      double v3, double v4, double v5) :
00106             sx(v0), shy(v1), shx(v2), sy(v3), tx(v4), ty(v5)
00107         {}
00108 
00109         // Custom matrix from m[6]
00110         explicit trans_affine(const double* m) :
00111             sx(m[0]), shy(m[1]), shx(m[2]), sy(m[3]), tx(m[4]), ty(m[5])
00112         {}
00113 
00114         // Rectangle to a parallelogram.
00115         trans_affine(double x1, double y1, double x2, double y2, 
00116                      const double* parl)
00117         {
00118             rect_to_parl(x1, y1, x2, y2, parl);
00119         }
00120 
00121         // Parallelogram to a rectangle.
00122         trans_affine(const double* parl, 
00123                      double x1, double y1, double x2, double y2)
00124         {
00125             parl_to_rect(parl, x1, y1, x2, y2);
00126         }
00127 
00128         // Arbitrary parallelogram transformation.
00129         trans_affine(const double* src, const double* dst)
00130         {
00131             parl_to_parl(src, dst);
00132         }
00133 
00134         //---------------------------------- Parellelogram transformations
00135         // transform a parallelogram to another one. Src and dst are 
00136         // pointers to arrays of three points (double[6], x1,y1,...) that 
00137         // identify three corners of the parallelograms assuming implicit 
00138         // fourth point. The arguments are arrays of double[6] mapped 
00139         // to x1,y1, x2,y2, x3,y3  where the coordinates are:
00140         //        *-----------------*
00141         //       /          (x3,y3)/
00142         //      /                 /
00143         //     /(x1,y1)   (x2,y2)/
00144         //    *-----------------*
00145         const trans_affine& parl_to_parl(const double* src, 
00146                                          const double* dst);
00147 
00148         const trans_affine& rect_to_parl(double x1, double y1, 
00149                                          double x2, double y2, 
00150                                          const double* parl);
00151 
00152         const trans_affine& parl_to_rect(const double* parl, 
00153                                          double x1, double y1, 
00154                                          double x2, double y2);
00155 
00156 
00157         //------------------------------------------ Operations
00158         // Reset - load an identity matrix
00159         const trans_affine& reset();
00160 
00161         // Direct transformations operations
00162         const trans_affine& translate(double x, double y);
00163         const trans_affine& rotate(double a);
00164         const trans_affine& scale(double s);
00165         const trans_affine& scale(double x, double y);
00166 
00167         // Multiply matrix to another one
00168         const trans_affine& multiply(const trans_affine& m);
00169 
00170         // Multiply "m" to "this" and assign the result to "this"
00171         const trans_affine& premultiply(const trans_affine& m);
00172 
00173         // Multiply matrix to inverse of another one
00174         const trans_affine& multiply_inv(const trans_affine& m);
00175 
00176         // Multiply inverse of "m" to "this" and assign the result to "this"
00177         const trans_affine& premultiply_inv(const trans_affine& m);
00178 
00179         // Invert matrix. Do not try to invert degenerate matrices, 
00180         // there's no check for validity. If you set scale to 0 and 
00181         // then try to invert matrix, expect unpredictable result.
00182         const trans_affine& invert();
00183 
00184         // Mirroring around X
00185         const trans_affine& flip_x();
00186 
00187         // Mirroring around Y
00188         const trans_affine& flip_y();
00189 
00190         //------------------------------------------- Load/Store
00191         // Store matrix to an array [6] of double
00192         void store_to(double* m) const
00193         {
00194             *m++ = sx; *m++ = shy; *m++ = shx; *m++ = sy; *m++ = tx; *m++ = ty;
00195         }
00196 
00197         // Load matrix from an array [6] of double
00198         const trans_affine& load_from(const double* m)
00199         {
00200             sx = *m++; shy = *m++; shx = *m++; sy = *m++; tx = *m++;  ty = *m++;
00201             return *this;
00202         }
00203 
00204         //------------------------------------------- Operators
00205         
00206         // Multiply the matrix by another one
00207         const trans_affine& operator *= (const trans_affine& m)
00208         {
00209             return multiply(m);
00210         }
00211 
00212         // Multiply the matrix by inverse of another one
00213         const trans_affine& operator /= (const trans_affine& m)
00214         {
00215             return multiply_inv(m);
00216         }
00217 
00218         // Multiply the matrix by another one and return
00219         // the result in a separete matrix.
00220         trans_affine operator * (const trans_affine& m)
00221         {
00222             return trans_affine(*this).multiply(m);
00223         }
00224 
00225         // Multiply the matrix by inverse of another one 
00226         // and return the result in a separete matrix.
00227         trans_affine operator / (const trans_affine& m)
00228         {
00229             return trans_affine(*this).multiply_inv(m);
00230         }
00231 
00232         // Calculate and return the inverse matrix
00233         trans_affine operator ~ () const
00234         {
00235             trans_affine ret = *this;
00236             return ret.invert();
00237         }
00238 
00239         // Equal operator with default epsilon
00240         bool operator == (const trans_affine& m) const
00241         {
00242             return is_equal(m, affine_epsilon);
00243         }
00244 
00245         // Not Equal operator with default epsilon
00246         bool operator != (const trans_affine& m) const
00247         {
00248             return !is_equal(m, affine_epsilon);
00249         }
00250 
00251         //-------------------------------------------- Transformations
00252         // Direct transformation of x and y
00253         void transform(double* x, double* y) const;
00254 
00255         // Direct transformation of x and y, 2x2 matrix only, no translation
00256         void transform_2x2(double* x, double* y) const;
00257 
00258         // Inverse transformation of x and y. It works slower than the 
00259         // direct transformation. For massive operations it's better to 
00260         // invert() the matrix and then use direct transformations. 
00261         void inverse_transform(double* x, double* y) const;
00262 
00263         //-------------------------------------------- Auxiliary
00264         // Calculate the determinant of matrix
00265         double determinant() const
00266         {
00267             return sx * sy - shy * shx;
00268         }
00269 
00270         // Calculate the reciprocal of the determinant
00271         double determinant_reciprocal() const
00272         {
00273             return 1.0 / (sx * sy - shy * shx);
00274         }
00275 
00276         // Get the average scale (by X and Y). 
00277         // Basically used to calculate the approximation_scale when
00278         // decomposinting curves into line segments.
00279         double scale() const;
00280 
00281         // Check to see if the matrix is not degenerate
00282         bool is_valid(double epsilon = affine_epsilon) const;
00283 
00284         // Check to see if it's an identity matrix
00285         bool is_identity(double epsilon = affine_epsilon) const;
00286 
00287         // Check to see if two matrices are equal
00288         bool is_equal(const trans_affine& m, double epsilon = affine_epsilon) const;
00289 
00290         // Determine the major parameters. Use with caution considering 
00291         // possible degenerate cases.
00292         double rotation() const;
00293         void   translation(double* dx, double* dy) const;
00294         void   scaling(double* x, double* y) const;
00295         void   scaling_abs(double* x, double* y) const;
00296     };
00297 
00298     //------------------------------------------------------------------------
00299     inline void trans_affine::transform(double* x, double* y) const
00300     {
00301         register double tmp = *x;
00302         *x = tmp * sx  + *y * shx + tx;
00303         *y = tmp * shy + *y * sy  + ty;
00304     }
00305 
00306     //------------------------------------------------------------------------
00307     inline void trans_affine::transform_2x2(double* x, double* y) const
00308     {
00309         register double tmp = *x;
00310         *x = tmp * sx  + *y * shx;
00311         *y = tmp * shy + *y * sy;
00312     }
00313 
00314     //------------------------------------------------------------------------
00315     inline void trans_affine::inverse_transform(double* x, double* y) const
00316     {
00317         register double d = determinant_reciprocal();
00318         register double a = (*x - tx) * d;
00319         register double b = (*y - ty) * d;
00320         *x = a * sy - b * shx;
00321         *y = b * sx - a * shy;
00322     }
00323 
00324     //------------------------------------------------------------------------
00325     inline double trans_affine::scale() const
00326     {
00327         double x = 0.707106781 * sx  + 0.707106781 * shx;
00328         double y = 0.707106781 * shy + 0.707106781 * sy;
00329         return sqrt(x*x + y*y);
00330     }
00331 
00332     //------------------------------------------------------------------------
00333     inline const trans_affine& trans_affine::translate(double x, double y) 
00334     { 
00335         tx += x;
00336         ty += y; 
00337         return *this;
00338     }
00339 
00340     //------------------------------------------------------------------------
00341     inline const trans_affine& trans_affine::rotate(double a) 
00342     {
00343         double ca = cos(a); 
00344         double sa = sin(a);
00345         double t0 = sx  * ca - shy * sa;
00346         double t2 = shx * ca - sy * sa;
00347         double t4 = tx  * ca - ty * sa;
00348         shy = sx  * sa + shy * ca;
00349         sy  = shx * sa + sy * ca; 
00350         ty  = tx  * sa + ty * ca;
00351         sx  = t0;
00352         shx = t2;
00353         tx  = t4;
00354         return *this;
00355     }
00356 
00357     //------------------------------------------------------------------------
00358     inline const trans_affine& trans_affine::scale(double x, double y) 
00359     {
00360         double mm0 = x; // Possible hint for the optimizer
00361         double mm3 = y; 
00362         sx  *= mm0;
00363         shx *= mm0;
00364         tx  *= mm0;
00365         shy *= mm3;
00366         sy  *= mm3;
00367         ty  *= mm3;
00368         return *this;
00369     }
00370 
00371     //------------------------------------------------------------------------
00372     inline const trans_affine& trans_affine::scale(double s) 
00373     {
00374         double m = s; // Possible hint for the optimizer
00375         sx  *= m;
00376         shx *= m;
00377         tx  *= m;
00378         shy *= m;
00379         sy  *= m;
00380         ty  *= m;
00381         return *this;
00382     }
00383 
00384     //------------------------------------------------------------------------
00385     inline const trans_affine& trans_affine::premultiply(const trans_affine& m)
00386     {
00387         trans_affine t = m;
00388         return *this = t.multiply(*this);
00389     }
00390 
00391     //------------------------------------------------------------------------
00392     inline const trans_affine& trans_affine::multiply_inv(const trans_affine& m)
00393     {
00394         trans_affine t = m;
00395         t.invert();
00396         return multiply(t);
00397     }
00398 
00399     //------------------------------------------------------------------------
00400     inline const trans_affine& trans_affine::premultiply_inv(const trans_affine& m)
00401     {
00402         trans_affine t = m;
00403         t.invert();
00404         return *this = t.multiply(*this);
00405     }
00406 
00407     //------------------------------------------------------------------------
00408     inline void trans_affine::scaling_abs(double* x, double* y) const
00409     {
00410         // Used to calculate scaling coefficients in image resampling. 
00411         // When there is considerable shear this method gives us much
00412         // better estimation than just sx, sy.
00413         *x = sqrt(sx  * sx  + shx * shx);
00414         *y = sqrt(shy * shy + sy  * sy);
00415     }
00416 
00417     //====================================================trans_affine_rotation
00418     // Rotation matrix. sin() and cos() are calculated twice for the same angle.
00419     // There's no harm because the performance of sin()/cos() is very good on all
00420     // modern processors. Besides, this operation is not going to be invoked too 
00421     // often.
00422     class trans_affine_rotation : public trans_affine
00423     {
00424     public:
00425         trans_affine_rotation(double a) : 
00426           trans_affine(cos(a), sin(a), -sin(a), cos(a), 0.0, 0.0)
00427         {}
00428     };
00429 
00430     //====================================================trans_affine_scaling
00431     // Scaling matrix. x, y - scale coefficients by X and Y respectively
00432     class trans_affine_scaling : public trans_affine
00433     {
00434     public:
00435         trans_affine_scaling(double x, double y) : 
00436           trans_affine(x, 0.0, 0.0, y, 0.0, 0.0)
00437         {}
00438 
00439         trans_affine_scaling(double s) : 
00440           trans_affine(s, 0.0, 0.0, s, 0.0, 0.0)
00441         {}
00442     };
00443 
00444     //================================================trans_affine_translation
00445     // Translation matrix
00446     class trans_affine_translation : public trans_affine
00447     {
00448     public:
00449         trans_affine_translation(double x, double y) : 
00450           trans_affine(1.0, 0.0, 0.0, 1.0, x, y)
00451         {}
00452     };
00453 
00454     //====================================================trans_affine_skewing
00455     // Sckewing (shear) matrix
00456     class trans_affine_skewing : public trans_affine
00457     {
00458     public:
00459         trans_affine_skewing(double x, double y) : 
00460           trans_affine(1.0, tan(y), tan(x), 1.0, 0.0, 0.0)
00461         {}
00462     };
00463 
00464 
00465     //===============================================trans_affine_line_segment
00466     // Rotate, Scale and Translate, associating 0...dist with line segment 
00467     // x1,y1,x2,y2
00468     class trans_affine_line_segment : public trans_affine
00469     {
00470     public:
00471         trans_affine_line_segment(double x1, double y1, double x2, double y2, 
00472                                   double dist)
00473         {
00474             double dx = x2 - x1;
00475             double dy = y2 - y1;
00476             if(dist > 0.0)
00477             {
00478                 multiply(trans_affine_scaling(sqrt(dx * dx + dy * dy) / dist));
00479             }
00480             multiply(trans_affine_rotation(atan2(dy, dx)));
00481             multiply(trans_affine_translation(x1, y1));
00482         }
00483     };
00484 
00485 
00486     //============================================trans_affine_reflection_unit
00487     // Reflection matrix. Reflect coordinates across the line through 
00488     // the origin containing the unit vector (ux, uy).
00489     // Contributed by John Horigan
00490     class trans_affine_reflection_unit : public trans_affine
00491     {
00492     public:
00493         trans_affine_reflection_unit(double ux, double uy) :
00494           trans_affine(2.0 * ux * ux - 1.0, 
00495                        2.0 * ux * uy, 
00496                        2.0 * ux * uy, 
00497                        2.0 * uy * uy - 1.0, 
00498                        0.0, 0.0)
00499         {}
00500     };
00501 
00502 
00503     //=================================================trans_affine_reflection
00504     // Reflection matrix. Reflect coordinates across the line through 
00505     // the origin at the angle a or containing the non-unit vector (x, y).
00506     // Contributed by John Horigan
00507     class trans_affine_reflection : public trans_affine_reflection_unit
00508     {
00509     public:
00510         trans_affine_reflection(double a) :
00511           trans_affine_reflection_unit(cos(a), sin(a))
00512         {}
00513 
00514 
00515         trans_affine_reflection(double x, double y) :
00516           trans_affine_reflection_unit(x / sqrt(x * x + y * y), y / sqrt(x * x + y * y))
00517         {}
00518     };
00519 
00520 }
00521 
00522 
00523 #endif
00524 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines