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
1.4.0