Anti-Grain Geometry - AGG (libagg)
2.5
|
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