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

agg_trans_affine.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 // Affine transformation classes.
00017 //
00018 //----------------------------------------------------------------------------
00019 #ifndef AGG_TRANS_AFFINE_INCLUDED
00020 #define AGG_TRANS_AFFINE_INCLUDED
00021 
00022 #include <math.h>
00023 #include "agg_basics.h"
00024 
00025 namespace agg
00026 {
00027     const double affine_epsilon = 1e-14; // About of precision of doubles
00028 
00029     //============================================================trans_affine
00030     //
00031     // See Implementation agg_trans_affine.cpp
00032     //
00033     // Affine transformation are linear transformations in Cartesian coordinates
00034     // (strictly speaking not only in Cartesian, but for the beginning we will 
00035     // think so). They are rotation, scaling, translation and skewing.  
00036     // After any affine transformation a line segment remains a line segment 
00037     // and it will never become a curve. 
00038     //
00039     // There will be no math about matrix calculations, since it has been 
00040     // described many times. Ask yourself a very simple question:
00041     // "why do we need to understand and use some matrix stuff instead of just 
00042     // rotating, scaling and so on". The answers are:
00043     //
00044     // 1. Any combination of transformations can be done by only 4 multiplications
00045     //    and 4 additions in floating point.
00046     // 2. One matrix transformation is equivalent to the number of consecutive
00047     //    discrete transformations, i.e. the matrix "accumulates" all transformations 
00048     //    in the order of their settings. Suppose we have 4 transformations: 
00049     //       * rotate by 30 degrees,
00050     //       * scale X to 2.0, 
00051     //       * scale Y to 1.5, 
00052     //       * move to (100, 100). 
00053     //    The result will depend on the order of these transformations, 
00054     //    and the advantage of matrix is that the sequence of discret calls:
00055     //    rotate(30), scaleX(2.0), scaleY(1.5), move(100,100) 
00056     //    will have exactly the same result as the following matrix transformations:
00057     //   
00058     //    affine_matrix m;
00059     //    m *= rotate_matrix(30); 
00060     //    m *= scaleX_matrix(2.0);
00061     //    m *= scaleY_matrix(1.5);
00062     //    m *= move_matrix(100,100);
00063     //
00064     //    m.transform_my_point_at_last(x, y);
00065     //
00066     // What is the good of it? In real life we will set-up the matrix only once
00067     // and then transform many points, let alone the convenience to set any 
00068     // combination of transformations.
00069     //
00070     // So, how to use it? Very easy - literally as it's shown above. Not quite,
00071     // let us write a correct example:
00072     //
00073     // agg::trans_affine m;
00074     // m *= agg::trans_affine_rotation(30.0 * 3.1415926 / 180.0);
00075     // m *= agg::trans_affine_scaling(2.0, 1.5);
00076     // m *= agg::trans_affine_translation(100.0, 100.0);
00077     // m.transform(&x, &y);
00078     //
00079     // The affine matrix is all you need to perform any linear transformation,
00080     // but all transformations have origin point (0,0). It means that we need to 
00081     // use 2 translations if we want to rotate someting around (100,100):
00082     // 
00083     // m *= agg::trans_affine_translation(-100.0, -100.0);         // move to (0,0)
00084     // m *= agg::trans_affine_rotation(30.0 * 3.1415926 / 180.0);  // rotate
00085     // m *= agg::trans_affine_translation(100.0, 100.0);           // move back to (100,100)
00086     //----------------------------------------------------------------------
00087     class trans_affine
00088     {
00089     public:
00090         //------------------------------------------ Construction
00091         // Construct an identity matrix - it does not transform anything
00092         trans_affine() :
00093             m0(1.0), m1(0.0), m2(0.0), m3(1.0), m4(0.0), m5(0.0)
00094         {}
00095 
00096         // Construct a custom matrix. Usually used in derived classes
00097         trans_affine(double v0, double v1, double v2, double v3, double v4, double v5) :
00098             m0(v0), m1(v1), m2(v2), m3(v3), m4(v4), m5(v5)
00099         {}
00100 
00101         // Construct a matrix to transform a parallelogram to another one.
00102         trans_affine(const double* rect, const double* parl)
00103         {
00104             parl_to_parl(rect, parl);
00105         }
00106 
00107         // Construct a matrix to transform a rectangle to a parallelogram.
00108         trans_affine(double x1, double y1, double x2, double y2, 
00109                      const double* parl)
00110         {
00111             rect_to_parl(x1, y1, x2, y2, parl);
00112         }
00113 
00114         // Construct a matrix to transform a parallelogram to a rectangle.
00115         trans_affine(const double* parl, 
00116                      double x1, double y1, double x2, double y2)
00117         {
00118             parl_to_rect(parl, x1, y1, x2, y2);
00119         }
00120 
00121 
00122         //---------------------------------- Parellelogram transformations
00123         // Calculate a matrix to transform a parallelogram to another one.
00124         // src and dst are pointers to arrays of three points 
00125         // (double[6], x,y,...) that identify three corners of the 
00126         // parallelograms assuming implicit fourth points.
00127         // There are also transformations rectangtle to parallelogram and 
00128         // parellelogram to rectangle
00129         const trans_affine& parl_to_parl(const double* src, 
00130                                          const double* dst);
00131 
00132         const trans_affine& rect_to_parl(double x1, double y1, 
00133                                          double x2, double y2, 
00134                                          const double* parl);
00135 
00136         const trans_affine& parl_to_rect(const double* parl, 
00137                                          double x1, double y1, 
00138                                          double x2, double y2);
00139 
00140 
00141         //------------------------------------------ Operations
00142         // Reset - actually load an identity matrix
00143         const trans_affine& reset();
00144 
00145         // Multiply matrix to another one
00146         const trans_affine& multiply(const trans_affine& m);
00147 
00148         // Multiply "m" to "this" and assign the result to "this"
00149         const trans_affine& premultiply(const trans_affine& m);
00150 
00151         // Invert matrix. Do not try to invert degenerate matrices, 
00152         // there's no check for validity. If you set scale to 0 and 
00153         // then try to invert matrix, expect unpredictable result.
00154         const trans_affine& invert();
00155 
00156         // Mirroring around X
00157         const trans_affine& flip_x();
00158 
00159         // Mirroring around Y
00160         const trans_affine& flip_y();
00161 
00162         //------------------------------------------- Load/Store
00163         // Store matrix to an array [6] of double
00164         void store_to(double* m) const
00165         {
00166             *m++ = m0; *m++ = m1; *m++ = m2; *m++ = m3; *m++ = m4; *m++ = m5;
00167         }
00168 
00169         // Load matrix from an array [6] of double
00170         const trans_affine& load_from(const double* m)
00171         {
00172             m0 = *m++; m1 = *m++; m2 = *m++; m3 = *m++; m4 = *m++;  m5 = *m++;
00173             return *this;
00174         }
00175 
00176         //------------------------------------------- Operators
00177         
00178         // Multiply current matrix to another one
00179         const trans_affine& operator *= (const trans_affine& m)
00180         {
00181             return multiply(m);
00182         }
00183 
00184         // Multiply current matrix to another one and return
00185         // the result in a separete matrix.
00186         trans_affine operator * (const trans_affine& m)
00187         {
00188             return trans_affine(*this).multiply(m);
00189         }
00190 
00191         // Calculate and return the inverse matrix
00192         trans_affine operator ~ () const
00193         {
00194             trans_affine ret = *this;
00195             return ret.invert();
00196         }
00197 
00198         // Equal operator with default epsilon
00199         bool operator == (const trans_affine& m) const
00200         {
00201             return is_equal(m, affine_epsilon);
00202         }
00203 
00204         // Not Equal operator with default epsilon
00205         bool operator != (const trans_affine& m) const
00206         {
00207             return !is_equal(m, affine_epsilon);
00208         }
00209 
00210         //-------------------------------------------- Transformations
00211         // Direct transformation x and y
00212         void transform(double* x, double* y) const;
00213 
00214         // Inverse transformation x and y. It works slower than the 
00215         // direct transformation, so if the performance is critical 
00216         // it's better to invert() the matrix and then use transform()
00217         void inverse_transform(double* x, double* y) const;
00218 
00219         //-------------------------------------------- Auxiliary
00220         // Calculate the determinant of matrix
00221         double determinant() const
00222         {
00223             return 1.0 / (m0 * m3 - m1 * m2);
00224         }
00225 
00226         // Get the average scale (by X and Y). 
00227         // Basically used to calculate the approximation_scale when
00228         // decomposinting curves into line segments.
00229         double scale() const;
00230 
00231         // Check to see if it's an identity matrix
00232         bool is_identity(double epsilon = affine_epsilon) const;
00233 
00234         // Check to see if two matrices are equal
00235         bool is_equal(const trans_affine& m, double epsilon = affine_epsilon) const;
00236 
00237         // Determine the major parameters. Use carefully considering degenerate matrices
00238         double rotation() const;
00239         void   translation(double* dx, double* dy) const;
00240         void   scaling(double* sx, double* sy) const;
00241 
00242     private:
00243         double m0;
00244         double m1;
00245         double m2;
00246         double m3;
00247         double m4;
00248         double m5;
00249     };
00250 
00251     //------------------------------------------------------------------------
00252     inline void trans_affine::transform(double* x, double* y) const
00253     {
00254         register double tx = *x;
00255         *x = tx * m0 + *y * m2 + m4;
00256         *y = tx * m1 + *y * m3 + m5;
00257     }
00258 
00259     //------------------------------------------------------------------------
00260     inline void trans_affine::inverse_transform(double* x, double* y) const
00261     {
00262         register double d = determinant();
00263         register double a = (*x - m4) * d;
00264         register double b = (*y - m5) * d;
00265         *x = a * m3 - b * m2;
00266         *y = b * m0 - a * m1;
00267     }
00268 
00269     //------------------------------------------------------------------------
00270     inline double trans_affine::scale() const
00271     {
00272         double x = 0.707106781 * m0 + 0.707106781 * m2;
00273         double y = 0.707106781 * m1 + 0.707106781 * m3;
00274         return sqrt(x*x + y*y);
00275     }
00276 
00277 
00278     //------------------------------------------------------------------------
00279     inline const trans_affine& trans_affine::premultiply(const trans_affine& m)
00280     {
00281         trans_affine t = m;
00282         return *this = t.multiply(*this);
00283     }
00284 
00285 
00286     //====================================================trans_affine_rotation
00287     // Rotation matrix. sin() and cos() are calculated twice for the same angle.
00288     // There's no harm because the performance of sin()/cos() is very good on all
00289     // modern processors. Besides, this operation is not going to be invoked too 
00290     // often.
00291     class trans_affine_rotation : public trans_affine
00292     {
00293     public:
00294         trans_affine_rotation(double a) : 
00295           trans_affine(cos(a), sin(a), -sin(a), cos(a), 0.0, 0.0)
00296         {}
00297     };
00298 
00299     //====================================================trans_affine_scaling
00300     // Scaling matrix. sx, sy - scale coefficients by X and Y respectively
00301     class trans_affine_scaling : public trans_affine
00302     {
00303     public:
00304         trans_affine_scaling(double sx, double sy) : 
00305           trans_affine(sx, 0.0, 0.0, sy, 0.0, 0.0)
00306         {}
00307 
00308         trans_affine_scaling(double s) : 
00309           trans_affine(s, 0.0, 0.0, s, 0.0, 0.0)
00310         {}
00311     };
00312 
00313     //================================================trans_affine_translation
00314     // Translation matrix
00315     class trans_affine_translation : public trans_affine
00316     {
00317     public:
00318         trans_affine_translation(double tx, double ty) : 
00319           trans_affine(1.0, 0.0, 0.0, 1.0, tx, ty)
00320         {}
00321     };
00322 
00323     //====================================================trans_affine_skewing
00324     // Sckewing (shear) matrix
00325     class trans_affine_skewing : public trans_affine
00326     {
00327     public:
00328         trans_affine_skewing(double sx, double sy) : 
00329           trans_affine(1.0, tan(sy), tan(sx), 1.0, 0.0, 0.0)
00330         {}
00331     };
00332 
00333 
00334 
00335 }
00336 
00337 
00338 #endif
00339 

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