1 //---------------------------------------------------------------------------- 2 // Anti-Grain Geometry - Version 2.4 3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) 4 // 5 // Permission to copy, use, modify, sell and distribute this software 6 // is granted provided this copyright notice appears in all copies. 7 // This software is provided "as is" without express or implied 8 // warranty, and with no claim as to its suitability for any purpose. 9 // 10 //---------------------------------------------------------------------------- 11 // Contact: mcseem@antigrain.com 12 // mcseemagg@yahoo.com 13 // http://www.antigrain.com 14 //---------------------------------------------------------------------------- 15 // 16 // Affine transformation classes. 17 // 18 //---------------------------------------------------------------------------- 19 #ifndef AGG_TRANS_AFFINE_INCLUDED 20 #define AGG_TRANS_AFFINE_INCLUDED 21 22 #include <math.h> 23 #include "agg_basics.h" 24 25 namespace agg 26 { 27 const double affine_epsilon = 1e-14; // About of precision of doubles 28 29 //============================================================trans_affine 30 // 31 // See Implementation agg_trans_affine.cpp 32 // 33 // Affine transformation are linear transformations in Cartesian coordinates 34 // (strictly speaking not only in Cartesian, but for the beginning we will 35 // think so). They are rotation, scaling, translation and skewing. 36 // After any affine transformation a line segment remains a line segment 37 // and it will never become a curve. 38 // 39 // There will be no math about matrix calculations, since it has been 40 // described many times. Ask yourself a very simple question: 41 // "why do we need to understand and use some matrix stuff instead of just 42 // rotating, scaling and so on". The answers are: 43 // 44 // 1. Any combination of transformations can be done by only 4 multiplications 45 // and 4 additions in floating point. 46 // 2. One matrix transformation is equivalent to the number of consecutive 47 // discrete transformations, i.e. the matrix "accumulates" all transformations 48 // in the order of their settings. Suppose we have 4 transformations: 49 // * rotate by 30 degrees, 50 // * scale X to 2.0, 51 // * scale Y to 1.5, 52 // * move to (100, 100). 53 // The result will depend on the order of these transformations, 54 // and the advantage of matrix is that the sequence of discret calls: 55 // rotate(30), scaleX(2.0), scaleY(1.5), move(100,100) 56 // will have exactly the same result as the following matrix transformations: 57 // 58 // affine_matrix m; 59 // m *= rotate_matrix(30); 60 // m *= scaleX_matrix(2.0); 61 // m *= scaleY_matrix(1.5); 62 // m *= move_matrix(100,100); 63 // 64 // m.transform_my_point_at_last(x, y); 65 // 66 // What is the good of it? In real life we will set-up the matrix only once 67 // and then transform many points, let alone the convenience to set any 68 // combination of transformations. 69 // 70 // So, how to use it? Very easy - literally as it's shown above. Not quite, 71 // let us write a correct example: 72 // 73 // agg::trans_affine m; 74 // m *= agg::trans_affine_rotation(30.0 * 3.1415926 / 180.0); 75 // m *= agg::trans_affine_scaling(2.0, 1.5); 76 // m *= agg::trans_affine_translation(100.0, 100.0); 77 // m.transform(&x, &y); 78 // 79 // The affine matrix is all you need to perform any linear transformation, 80 // but all transformations have origin point (0,0). It means that we need to 81 // use 2 translations if we want to rotate someting around (100,100): 82 // 83 // m *= agg::trans_affine_translation(-100.0, -100.0); // move to (0,0) 84 // m *= agg::trans_affine_rotation(30.0 * 3.1415926 / 180.0); // rotate 85 // m *= agg::trans_affine_translation(100.0, 100.0); // move back to (100,100) 86 //---------------------------------------------------------------------- 87 class trans_affine 88 { 89 public: 90 //------------------------------------------ Construction 91 // Construct an identity matrix - it does not transform anything 92 trans_affine() : 93 m0(1.0), m1(0.0), m2(0.0), m3(1.0), m4(0.0), m5(0.0) 94 {} 95 96 // Construct a custom matrix. Usually used in derived classes 97 trans_affine(double v0, double v1, double v2, double v3, double v4, double v5) : 98 m0(v0), m1(v1), m2(v2), m3(v3), m4(v4), m5(v5) 99 {} 100 101 // Construct a matrix to transform a parallelogram to another one. 102 trans_affine(const double* rect, const double* parl) 103 { 104 parl_to_parl(rect, parl); 105 } 106 107 // Construct a matrix to transform a rectangle to a parallelogram. 108 trans_affine(double x1, double y1, double x2, double y2, 109 const double* parl) 110 { 111 rect_to_parl(x1, y1, x2, y2, parl); 112 } 113 114 // Construct a matrix to transform a parallelogram to a rectangle. 115 trans_affine(const double* parl, 116 double x1, double y1, double x2, double y2) 117 { 118 parl_to_rect(parl, x1, y1, x2, y2); 119 } 120 121 122 //---------------------------------- Parellelogram transformations 123 // Calculate a matrix to transform a parallelogram to another one. 124 // src and dst are pointers to arrays of three points 125 // (double[6], x,y,...) that identify three corners of the 126 // parallelograms assuming implicit fourth points. 127 // There are also transformations rectangtle to parallelogram and 128 // parellelogram to rectangle 129 const trans_affine& parl_to_parl(const double* src, 130 const double* dst); 131 132 const trans_affine& rect_to_parl(double x1, double y1, 133 double x2, double y2, 134 const double* parl); 135 136 const trans_affine& parl_to_rect(const double* parl, 137 double x1, double y1, 138 double x2, double y2); 139 140 141 //------------------------------------------ Operations 142 // Reset - actually load an identity matrix 143 const trans_affine& reset(); 144 145 // Multiply matrix to another one 146 const trans_affine& multiply(const trans_affine& m); 147 148 // Multiply "m" to "this" and assign the result to "this" 149 const trans_affine& premultiply(const trans_affine& m); 150 151 // Multiply matrix to inverse of another one 152 const trans_affine& multiply_inv(const trans_affine& m); 153 154 // Multiply inverse of "m" to "this" and assign the result to "this" 155 const trans_affine& premultiply_inv(const trans_affine& m); 156 157 // Invert matrix. Do not try to invert degenerate matrices, 158 // there's no check for validity. If you set scale to 0 and 159 // then try to invert matrix, expect unpredictable result. 160 const trans_affine& invert(); 161 162 // Mirroring around X 163 const trans_affine& flip_x(); 164 165 // Mirroring around Y 166 const trans_affine& flip_y(); 167 168 //------------------------------------------- Load/Store 169 // Store matrix to an array [6] of double 170 void store_to(double* m) const 171 { 172 *m++ = m0; *m++ = m1; *m++ = m2; *m++ = m3; *m++ = m4; *m++ = m5; 173 } 174 175 // Load matrix from an array [6] of double 176 const trans_affine& load_from(const double* m) 177 { 178 m0 = *m++; m1 = *m++; m2 = *m++; m3 = *m++; m4 = *m++; m5 = *m++; 179 return *this; 180 } 181 182 //------------------------------------------- Operators 183 184 // Multiply current matrix to another one 185 const trans_affine& operator *= (const trans_affine& m) 186 { 187 return multiply(m); 188 } 189 190 // Multiply current matrix to inverse of another one 191 const trans_affine& operator /= (const trans_affine& m) 192 { 193 return multiply_inv(m); 194 } 195 196 // Multiply current matrix to another one and return 197 // the result in a separete matrix. 198 trans_affine operator * (const trans_affine& m) const 199 { 200 return trans_affine(*this).multiply(m); 201 } 202 203 // Multiply current matrix to inverse of another one 204 // and return the result in a separete matrix. 205 trans_affine operator / (const trans_affine& m) const 206 { 207 return trans_affine(*this).multiply_inv(m); 208 } 209 210 // Calculate and return the inverse matrix 211 trans_affine operator ~ () const 212 { 213 trans_affine ret = *this; 214 return ret.invert(); 215 } 216 217 // Equal operator with default epsilon 218 bool operator == (const trans_affine& m) const 219 { 220 return is_equal(m, affine_epsilon); 221 } 222 223 // Not Equal operator with default epsilon 224 bool operator != (const trans_affine& m) const 225 { 226 return !is_equal(m, affine_epsilon); 227 } 228 229 //-------------------------------------------- Transformations 230 // Direct transformation x and y 231 void transform(double* x, double* y) const; 232 233 // Direct transformation x and y, 2x2 matrix only, no translation 234 void transform_2x2(double* x, double* y) const; 235 236 // Inverse transformation x and y. It works slower than the 237 // direct transformation, so if the performance is critical 238 // it's better to invert() the matrix and then use transform() 239 void inverse_transform(double* x, double* y) const; 240 241 //-------------------------------------------- Auxiliary 242 // Calculate the determinant of matrix 243 double determinant() const 244 { 245 return 1.0 / (m0 * m3 - m1 * m2); 246 } 247 248 // Get the average scale (by X and Y). 249 // Basically used to calculate the approximation_scale when 250 // decomposinting curves into line segments. 251 double scale() const; 252 253 // Check to see if it's an identity matrix 254 bool is_identity(double epsilon = affine_epsilon) const; 255 256 // Check to see if two matrices are equal 257 bool is_equal(const trans_affine& m, double epsilon = affine_epsilon) const; 258 259 // Determine the major parameters. Use carefully considering degenerate matrices 260 double rotation() const; 261 void translation(double* dx, double* dy) const; 262 void scaling(double* sx, double* sy) const; 263 void scaling_abs(double* sx, double* sy) const 264 { 265 *sx = sqrt(m0*m0 + m2*m2); 266 *sy = sqrt(m1*m1 + m3*m3); 267 } 268 269 private: 270 double m0; 271 double m1; 272 double m2; 273 double m3; 274 double m4; 275 double m5; 276 }; 277 278 //------------------------------------------------------------------------ 279 inline void trans_affine::transform(double* x, double* y) const 280 { 281 double tx = *x; 282 *x = tx * m0 + *y * m2 + m4; 283 *y = tx * m1 + *y * m3 + m5; 284 } 285 286 //------------------------------------------------------------------------ 287 inline void trans_affine::transform_2x2(double* x, double* y) const 288 { 289 double tx = *x; 290 *x = tx * m0 + *y * m2; 291 *y = tx * m1 + *y * m3; 292 } 293 294 //------------------------------------------------------------------------ 295 inline void trans_affine::inverse_transform(double* x, double* y) const 296 { 297 double d = determinant(); 298 double a = (*x - m4) * d; 299 double b = (*y - m5) * d; 300 *x = a * m3 - b * m2; 301 *y = b * m0 - a * m1; 302 } 303 304 //------------------------------------------------------------------------ 305 inline double trans_affine::scale() const 306 { 307 double x = M_SQRT1_2 * m0 + M_SQRT1_2 * m2; 308 double y = M_SQRT1_2 * m1 + M_SQRT1_2 * m3; 309 return sqrt(x*x + y*y); 310 } 311 312 //------------------------------------------------------------------------ 313 inline const trans_affine& trans_affine::premultiply(const trans_affine& m) 314 { 315 trans_affine t = m; 316 return *this = t.multiply(*this); 317 } 318 319 //------------------------------------------------------------------------ 320 inline const trans_affine& trans_affine::multiply_inv(const trans_affine& m) 321 { 322 trans_affine t = m; 323 t.invert(); 324 multiply(t); 325 return *this; 326 } 327 328 //------------------------------------------------------------------------ 329 inline const trans_affine& trans_affine::premultiply_inv(const trans_affine& m) 330 { 331 trans_affine t = m; 332 t.invert(); 333 return *this = t.multiply(*this); 334 } 335 336 //====================================================trans_affine_rotation 337 // Rotation matrix. sin() and cos() are calculated twice for the same angle. 338 // There's no harm because the performance of sin()/cos() is very good on all 339 // modern processors. Besides, this operation is not going to be invoked too 340 // often. 341 class trans_affine_rotation : public trans_affine 342 { 343 public: 344 trans_affine_rotation(double a) : 345 trans_affine(cos(a), sin(a), -sin(a), cos(a), 0.0, 0.0) 346 {} 347 }; 348 349 //====================================================trans_affine_scaling 350 // Scaling matrix. sx, sy - scale coefficients by X and Y respectively 351 class trans_affine_scaling : public trans_affine 352 { 353 public: 354 trans_affine_scaling(double sx, double sy) : 355 trans_affine(sx, 0.0, 0.0, sy, 0.0, 0.0) 356 {} 357 358 trans_affine_scaling(double s) : 359 trans_affine(s, 0.0, 0.0, s, 0.0, 0.0) 360 {} 361 }; 362 363 //================================================trans_affine_translation 364 // Translation matrix 365 class trans_affine_translation : public trans_affine 366 { 367 public: 368 trans_affine_translation(double tx, double ty) : 369 trans_affine(1.0, 0.0, 0.0, 1.0, tx, ty) 370 {} 371 }; 372 373 //====================================================trans_affine_skewing 374 // Sckewing (shear) matrix 375 class trans_affine_skewing : public trans_affine 376 { 377 public: 378 trans_affine_skewing(double sx, double sy) : 379 trans_affine(1.0, tan(sy), tan(sx), 1.0, 0.0, 0.0) 380 {} 381 }; 382 383 384 //===============================================trans_affine_line_segment 385 // Rotate, Scale and Translate, associating 0...dist with line segment 386 // x1,y1,x2,y2 387 class trans_affine_line_segment : public trans_affine 388 { 389 public: 390 trans_affine_line_segment(double x1, double y1, double x2, double y2, 391 double dist) 392 { 393 double dx = x2 - x1; 394 double dy = y2 - y1; 395 if(dist > 0.0) 396 { 397 multiply(trans_affine_scaling(sqrt(dx * dx + dy * dy) / dist)); 398 } 399 multiply(trans_affine_rotation(atan2(dy, dx))); 400 multiply(trans_affine_translation(x1, y1)); 401 } 402 }; 403 404 405 } 406 407 408 #endif 409 410