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 <cmath> 23 #include "agg_basics.h" 24 25 namespace agg 26 { 27 const double affine_epsilon = 1e-14; 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 struct trans_affine 88 { 89 double sx, shy, shx, sy, tx, ty; 90 91 //------------------------------------------ Construction 92 // Identity matrix 93 trans_affine() : 94 sx(1.0), shy(0.0), shx(0.0), sy(1.0), tx(0.0), ty(0.0) 95 {} 96 97 // Custom matrix. Usually used in derived classes 98 trans_affine(double v0, double v1, double v2, 99 double v3, double v4, double v5) : 100 sx(v0), shy(v1), shx(v2), sy(v3), tx(v4), ty(v5) 101 {} 102 103 // Custom matrix from m[6] 104 explicit trans_affine(const double* m) : 105 sx(m[0]), shy(m[1]), shx(m[2]), sy(m[3]), tx(m[4]), ty(m[5]) 106 {} 107 108 // Rectangle to a parallelogram. 109 trans_affine(double x1, double y1, double x2, double y2, 110 const double* parl) 111 { 112 rect_to_parl(x1, y1, x2, y2, parl); 113 } 114 115 // Parallelogram to a rectangle. 116 trans_affine(const double* parl, 117 double x1, double y1, double x2, double y2) 118 { 119 parl_to_rect(parl, x1, y1, x2, y2); 120 } 121 122 // Arbitrary parallelogram transformation. 123 trans_affine(const double* src, const double* dst) 124 { 125 parl_to_parl(src, dst); 126 } 127 128 //---------------------------------- Parellelogram transformations 129 // transform a parallelogram to another one. Src and dst are 130 // pointers to arrays of three points (double[6], x1,y1,...) that 131 // identify three corners of the parallelograms assuming implicit 132 // fourth point. The arguments are arrays of double[6] mapped 133 // to x1,y1, x2,y2, x3,y3 where the coordinates are: 134 // *-----------------* 135 // / (x3,y3)/ 136 // / / 137 // /(x1,y1) (x2,y2)/ 138 // *-----------------* 139 const trans_affine& parl_to_parl(const double* src, 140 const double* dst); 141 142 const trans_affine& rect_to_parl(double x1, double y1, 143 double x2, double y2, 144 const double* parl); 145 146 const trans_affine& parl_to_rect(const double* parl, 147 double x1, double y1, 148 double x2, double y2); 149 150 151 //------------------------------------------ Operations 152 // Reset - load an identity matrix 153 const trans_affine& reset(); 154 155 // Direct transformations operations 156 const trans_affine& translate(double x, double y); 157 const trans_affine& rotate(double a); 158 const trans_affine& scale(double s); 159 const trans_affine& scale(double x, double y); 160 161 // Multiply matrix to another one 162 const trans_affine& multiply(const trans_affine& m); 163 164 // Multiply "m" to "this" and assign the result to "this" 165 const trans_affine& premultiply(const trans_affine& m); 166 167 // Multiply matrix to inverse of another one 168 const trans_affine& multiply_inv(const trans_affine& m); 169 170 // Multiply inverse of "m" to "this" and assign the result to "this" 171 const trans_affine& premultiply_inv(const trans_affine& m); 172 173 // Invert matrix. Do not try to invert degenerate matrices, 174 // there's no check for validity. If you set scale to 0 and 175 // then try to invert matrix, expect unpredictable result. 176 const trans_affine& invert(); 177 178 // Mirroring around X 179 const trans_affine& flip_x(); 180 181 // Mirroring around Y 182 const trans_affine& flip_y(); 183 184 //------------------------------------------- Load/Store 185 // Store matrix to an array [6] of double 186 void store_to(double* m) const 187 { 188 *m++ = sx; *m++ = shy; *m++ = shx; *m++ = sy; *m++ = tx; *m++ = ty; 189 } 190 191 // Load matrix from an array [6] of double 192 const trans_affine& load_from(const double* m) 193 { 194 sx = *m++; shy = *m++; shx = *m++; sy = *m++; tx = *m++; ty = *m++; 195 return *this; 196 } 197 198 //------------------------------------------- Operators 199 200 // Multiply the matrix by another one 201 const trans_affine& operator *= (const trans_affine& m) 202 { 203 return multiply(m); 204 } 205 206 // Multiply the matrix by inverse of another one 207 const trans_affine& operator /= (const trans_affine& m) 208 { 209 return multiply_inv(m); 210 } 211 212 // Multiply the matrix by another one and return 213 // the result in a separete matrix. 214 trans_affine operator * (const trans_affine& m) const 215 { 216 return trans_affine(*this).multiply(m); 217 } 218 219 // Multiply the matrix by inverse of another one 220 // and return the result in a separete matrix. 221 trans_affine operator / (const trans_affine& m) const 222 { 223 return trans_affine(*this).multiply_inv(m); 224 } 225 226 // Calculate and return the inverse matrix 227 trans_affine operator ~ () const 228 { 229 trans_affine ret = *this; 230 return ret.invert(); 231 } 232 233 // Equal operator with default epsilon 234 bool operator == (const trans_affine& m) const 235 { 236 return is_equal(m, affine_epsilon); 237 } 238 239 // Not Equal operator with default epsilon 240 bool operator != (const trans_affine& m) const 241 { 242 return !is_equal(m, affine_epsilon); 243 } 244 245 //-------------------------------------------- Transformations 246 // Direct transformation of x and y 247 void transform(double* x, double* y) const; 248 249 // Direct transformation of x and y, 2x2 matrix only, no translation 250 void transform_2x2(double* x, double* y) const; 251 252 // Inverse transformation of x and y. It works slower than the 253 // direct transformation. For massive operations it's better to 254 // invert() the matrix and then use direct transformations. 255 void inverse_transform(double* x, double* y) const; 256 257 //-------------------------------------------- Auxiliary 258 // Calculate the determinant of matrix 259 double determinant() const 260 { 261 return sx * sy - shy * shx; 262 } 263 264 // Calculate the reciprocal of the determinant 265 double determinant_reciprocal() const 266 { 267 return 1.0 / (sx * sy - shy * shx); 268 } 269 270 // Get the average scale (by X and Y). 271 // Basically used to calculate the approximation_scale when 272 // decomposinting curves into line segments. 273 double scale() const; 274 275 // Check to see if the matrix is not degenerate 276 bool is_valid(double epsilon = affine_epsilon) const; 277 278 // Check to see if it's an identity matrix 279 bool is_identity(double epsilon = affine_epsilon) const; 280 281 // Check to see if two matrices are equal 282 bool is_equal(const trans_affine& m, double epsilon = affine_epsilon) const; 283 284 // Determine the major parameters. Use with caution considering 285 // possible degenerate cases. 286 double rotation() const; 287 void translation(double* dx, double* dy) const; 288 void scaling(double* x, double* y) const; 289 void scaling_abs(double* x, double* y) const; 290 }; 291 292 //------------------------------------------------------------------------ 293 inline void trans_affine::transform(double* x, double* y) const 294 { 295 double tmp = *x; 296 *x = tmp * sx + *y * shx + tx; 297 *y = tmp * shy + *y * sy + ty; 298 } 299 300 //------------------------------------------------------------------------ 301 inline void trans_affine::transform_2x2(double* x, double* y) const 302 { 303 double tmp = *x; 304 *x = tmp * sx + *y * shx; 305 *y = tmp * shy + *y * sy; 306 } 307 308 //------------------------------------------------------------------------ 309 inline void trans_affine::inverse_transform(double* x, double* y) const 310 { 311 double d = determinant_reciprocal(); 312 double a = (*x - tx) * d; 313 double b = (*y - ty) * d; 314 *x = a * sy - b * shx; 315 *y = b * sx - a * shy; 316 } 317 318 //------------------------------------------------------------------------ 319 inline double trans_affine::scale() const 320 { 321 double x = M_SQRT1_2 * sx + M_SQRT1_2 * shx; 322 double y = M_SQRT1_2 * shy + M_SQRT1_2 * sy; 323 return std::sqrt(x*x + y*y); 324 } 325 326 //------------------------------------------------------------------------ 327 inline const trans_affine& trans_affine::translate(double x, double y) 328 { 329 tx += x; 330 ty += y; 331 return *this; 332 } 333 334 //------------------------------------------------------------------------ 335 inline const trans_affine& trans_affine::rotate(double a) 336 { 337 double ca = std::cos(a); 338 double sa = std::sin(a); 339 double t0 = sx * ca - shy * sa; 340 double t2 = shx * ca - sy * sa; 341 double t4 = tx * ca - ty * sa; 342 shy = sx * sa + shy * ca; 343 sy = shx * sa + sy * ca; 344 ty = tx * sa + ty * ca; 345 sx = t0; 346 shx = t2; 347 tx = t4; 348 return *this; 349 } 350 351 //------------------------------------------------------------------------ 352 inline const trans_affine& trans_affine::scale(double x, double y) 353 { 354 double mm0 = x; // Possible hint for the optimizer 355 double mm3 = y; 356 sx *= mm0; 357 shx *= mm0; 358 tx *= mm0; 359 shy *= mm3; 360 sy *= mm3; 361 ty *= mm3; 362 return *this; 363 } 364 365 //------------------------------------------------------------------------ 366 inline const trans_affine& trans_affine::scale(double s) 367 { 368 double m = s; // Possible hint for the optimizer 369 sx *= m; 370 shx *= m; 371 tx *= m; 372 shy *= m; 373 sy *= m; 374 ty *= m; 375 return *this; 376 } 377 378 //------------------------------------------------------------------------ 379 inline const trans_affine& trans_affine::premultiply(const trans_affine& m) 380 { 381 trans_affine t = m; 382 return *this = t.multiply(*this); 383 } 384 385 //------------------------------------------------------------------------ 386 inline const trans_affine& trans_affine::multiply_inv(const trans_affine& m) 387 { 388 trans_affine t = m; 389 t.invert(); 390 return multiply(t); 391 } 392 393 //------------------------------------------------------------------------ 394 inline const trans_affine& trans_affine::premultiply_inv(const trans_affine& m) 395 { 396 trans_affine t = m; 397 t.invert(); 398 return *this = t.multiply(*this); 399 } 400 401 //------------------------------------------------------------------------ 402 inline void trans_affine::scaling_abs(double* x, double* y) const 403 { 404 // Used to calculate scaling coefficients in image resampling. 405 // When there is considerable shear this method gives us much 406 // better estimation than just sx, sy. 407 *x = std::sqrt(sx * sx + shx * shx); 408 *y = std::sqrt(shy * shy + sy * sy); 409 } 410 411 //====================================================trans_affine_rotation 412 // Rotation matrix. sin() and cos() are calculated twice for the same angle. 413 // There's no harm because the performance of sin()/cos() is very good on all 414 // modern processors. Besides, this operation is not going to be invoked too 415 // often. 416 class trans_affine_rotation : public trans_affine 417 { 418 public: 419 trans_affine_rotation(double a) : 420 trans_affine(std::cos(a), std::sin(a), -std::sin(a), std::cos(a), 0.0, 0.0) 421 {} 422 }; 423 424 //====================================================trans_affine_scaling 425 // Scaling matrix. x, y - scale coefficients by X and Y respectively 426 class trans_affine_scaling : public trans_affine 427 { 428 public: 429 trans_affine_scaling(double x, double y) : 430 trans_affine(x, 0.0, 0.0, y, 0.0, 0.0) 431 {} 432 433 trans_affine_scaling(double s) : 434 trans_affine(s, 0.0, 0.0, s, 0.0, 0.0) 435 {} 436 }; 437 438 //================================================trans_affine_translation 439 // Translation matrix 440 class trans_affine_translation : public trans_affine 441 { 442 public: 443 trans_affine_translation(double x, double y) : 444 trans_affine(1.0, 0.0, 0.0, 1.0, x, y) 445 {} 446 }; 447 448 //====================================================trans_affine_skewing 449 // Sckewing (shear) matrix 450 class trans_affine_skewing : public trans_affine 451 { 452 public: 453 trans_affine_skewing(double x, double y) : 454 trans_affine(1.0, std::tan(y), std::tan(x), 1.0, 0.0, 0.0) 455 {} 456 }; 457 458 459 //===============================================trans_affine_line_segment 460 // Rotate, Scale and Translate, associating 0...dist with line segment 461 // x1,y1,x2,y2 462 class trans_affine_line_segment : public trans_affine 463 { 464 public: 465 trans_affine_line_segment(double x1, double y1, double x2, double y2, 466 double dist) 467 { 468 double dx = x2 - x1; 469 double dy = y2 - y1; 470 if(dist > 0.0) 471 { 472 multiply(trans_affine_scaling(std::sqrt(dx * dx + dy * dy) / dist)); 473 } 474 multiply(trans_affine_rotation(std::atan2(dy, dx))); 475 multiply(trans_affine_translation(x1, y1)); 476 } 477 }; 478 479 480 //============================================trans_affine_reflection_unit 481 // Reflection matrix. Reflect coordinates across the line through 482 // the origin containing the unit vector (ux, uy). 483 // Contributed by John Horigan 484 class trans_affine_reflection_unit : public trans_affine 485 { 486 public: 487 trans_affine_reflection_unit(double ux, double uy) : 488 trans_affine(2.0 * ux * ux - 1.0, 489 2.0 * ux * uy, 490 2.0 * ux * uy, 491 2.0 * uy * uy - 1.0, 492 0.0, 0.0) 493 {} 494 }; 495 496 497 //=================================================trans_affine_reflection 498 // Reflection matrix. Reflect coordinates across the line through 499 // the origin at the angle a or containing the non-unit vector (x, y). 500 // Contributed by John Horigan 501 class trans_affine_reflection : public trans_affine_reflection_unit 502 { 503 public: 504 trans_affine_reflection(double a) : 505 trans_affine_reflection_unit(std::cos(a), std::sin(a)) 506 {} 507 508 509 trans_affine_reflection(double x, double y) : 510 trans_affine_reflection_unit(x / std::sqrt(x * x + y * y), y / std::sqrt(x * x + y * y)) 511 {} 512 }; 513 514 } 515 516 517 #endif 518 519