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_PERSPECTIVE_INCLUDED 00026 #define AGG_TRANS_PERSPECTIVE_INCLUDED 00027 00028 #include "agg_trans_affine.h" 00029 00030 namespace agg 00031 { 00032 //=======================================================trans_perspective 00033 struct trans_perspective 00034 { 00035 double sx, shy, w0, shx, sy, w1, tx, ty, w2; 00036 00037 //------------------------------------------------------- Construction 00038 // Identity matrix 00039 trans_perspective() : 00040 sx (1), shy(0), w0(0), 00041 shx(0), sy (1), w1(0), 00042 tx (0), ty (0), w2(1) {} 00043 00044 // Custom matrix 00045 trans_perspective(double v0, double v1, double v2, 00046 double v3, double v4, double v5, 00047 double v6, double v7, double v8) : 00048 sx (v0), shy(v1), w0(v2), 00049 shx(v3), sy (v4), w1(v5), 00050 tx (v6), ty (v7), w2(v8) {} 00051 00052 // Custom matrix from m[9] 00053 explicit trans_perspective(const double* m) : 00054 sx (m[0]), shy(m[1]), w0(m[2]), 00055 shx(m[3]), sy (m[4]), w1(m[5]), 00056 tx (m[6]), ty (m[7]), w2(m[8]) {} 00057 00058 // From affine 00059 explicit trans_perspective(const trans_affine& a) : 00060 sx (a.sx ), shy(a.shy), w0(0), 00061 shx(a.shx), sy (a.sy ), w1(0), 00062 tx (a.tx ), ty (a.ty ), w2(1) {} 00063 00064 // Rectangle to quadrilateral 00065 trans_perspective(double x1, double y1, double x2, double y2, 00066 const double* quad); 00067 00068 // Quadrilateral to rectangle 00069 trans_perspective(const double* quad, 00070 double x1, double y1, double x2, double y2); 00071 00072 // Arbitrary quadrilateral transformations 00073 trans_perspective(const double* src, const double* dst); 00074 00075 //-------------------------------------- Quadrilateral transformations 00076 // The arguments are double[8] that are mapped to quadrilaterals: 00077 // x1,y1, x2,y2, x3,y3, x4,y4 00078 bool quad_to_quad(const double* qs, const double* qd); 00079 00080 bool rect_to_quad(double x1, double y1, 00081 double x2, double y2, 00082 const double* q); 00083 00084 bool quad_to_rect(const double* q, 00085 double x1, double y1, 00086 double x2, double y2); 00087 00088 // Map square (0,0,1,1) to the quadrilateral and vice versa 00089 bool square_to_quad(const double* q); 00090 bool quad_to_square(const double* q); 00091 00092 00093 //--------------------------------------------------------- Operations 00094 // Reset - load an identity matrix 00095 const trans_perspective& reset(); 00096 00097 // Invert matrix. Returns false in degenerate case 00098 bool invert(); 00099 00100 // Direct transformations operations 00101 const trans_perspective& translate(double x, double y); 00102 const trans_perspective& rotate(double a); 00103 const trans_perspective& scale(double s); 00104 const trans_perspective& scale(double x, double y); 00105 00106 // Multiply the matrix by another one 00107 const trans_perspective& multiply(const trans_perspective& m); 00108 00109 // Multiply "m" by "this" and assign the result to "this" 00110 const trans_perspective& premultiply(const trans_perspective& m); 00111 00112 // Multiply matrix to inverse of another one 00113 const trans_perspective& multiply_inv(const trans_perspective& m); 00114 00115 // Multiply inverse of "m" by "this" and assign the result to "this" 00116 const trans_perspective& premultiply_inv(const trans_perspective& m); 00117 00118 // Multiply the matrix by another one 00119 const trans_perspective& multiply(const trans_affine& m); 00120 00121 // Multiply "m" by "this" and assign the result to "this" 00122 const trans_perspective& premultiply(const trans_affine& m); 00123 00124 // Multiply the matrix by inverse of another one 00125 const trans_perspective& multiply_inv(const trans_affine& m); 00126 00127 // Multiply inverse of "m" by "this" and assign the result to "this" 00128 const trans_perspective& premultiply_inv(const trans_affine& m); 00129 00130 //--------------------------------------------------------- Load/Store 00131 void store_to(double* m) const; 00132 const trans_perspective& load_from(const double* m); 00133 00134 //---------------------------------------------------------- Operators 00135 // Multiply the matrix by another one 00136 const trans_perspective& operator *= (const trans_perspective& m) 00137 { 00138 return multiply(m); 00139 } 00140 const trans_perspective& operator *= (const trans_affine& m) 00141 { 00142 return multiply(m); 00143 } 00144 00145 // Multiply the matrix by inverse of another one 00146 const trans_perspective& operator /= (const trans_perspective& m) 00147 { 00148 return multiply_inv(m); 00149 } 00150 const trans_perspective& operator /= (const trans_affine& m) 00151 { 00152 return multiply_inv(m); 00153 } 00154 00155 // Multiply the matrix by another one and return 00156 // the result in a separete matrix. 00157 trans_perspective operator * (const trans_perspective& m) 00158 { 00159 return trans_perspective(*this).multiply(m); 00160 } 00161 trans_perspective operator * (const trans_affine& m) 00162 { 00163 return trans_perspective(*this).multiply(m); 00164 } 00165 00166 // Multiply the matrix by inverse of another one 00167 // and return the result in a separete matrix. 00168 trans_perspective operator / (const trans_perspective& m) 00169 { 00170 return trans_perspective(*this).multiply_inv(m); 00171 } 00172 trans_perspective operator / (const trans_affine& m) 00173 { 00174 return trans_perspective(*this).multiply_inv(m); 00175 } 00176 00177 // Calculate and return the inverse matrix 00178 trans_perspective operator ~ () const 00179 { 00180 trans_perspective ret = *this; 00181 ret.invert(); 00182 return ret; 00183 } 00184 00185 // Equal operator with default epsilon 00186 bool operator == (const trans_perspective& m) const 00187 { 00188 return is_equal(m, affine_epsilon); 00189 } 00190 00191 // Not Equal operator with default epsilon 00192 bool operator != (const trans_perspective& m) const 00193 { 00194 return !is_equal(m, affine_epsilon); 00195 } 00196 00197 //---------------------------------------------------- Transformations 00198 // Direct transformation of x and y 00199 void transform(double* x, double* y) const; 00200 00201 // Direct transformation of x and y, affine part only 00202 void transform_affine(double* x, double* y) const; 00203 00204 // Direct transformation of x and y, 2x2 matrix only, no translation 00205 void transform_2x2(double* x, double* y) const; 00206 00207 // Inverse transformation of x and y. It works slow because 00208 // it explicitly inverts the matrix on every call. For massive 00209 // operations it's better to invert() the matrix and then use 00210 // direct transformations. 00211 void inverse_transform(double* x, double* y) const; 00212 00213 00214 //---------------------------------------------------------- Auxiliary 00215 const trans_perspective& from_affine(const trans_affine& a); 00216 double determinant() const; 00217 double determinant_reciprocal() const; 00218 00219 bool is_valid(double epsilon = affine_epsilon) const; 00220 bool is_identity(double epsilon = affine_epsilon) const; 00221 bool is_equal(const trans_perspective& m, 00222 double epsilon = affine_epsilon) const; 00223 00224 // Determine the major affine parameters. Use with caution 00225 // considering possible degenerate cases. 00226 double scale() const; 00227 double rotation() const; 00228 void translation(double* dx, double* dy) const; 00229 void scaling(double* x, double* y) const; 00230 void scaling_abs(double* x, double* y) const; 00231 00232 00233 00234 //-------------------------------------------------------------------- 00235 class iterator_x 00236 { 00237 double den; 00238 double den_step; 00239 double nom_x; 00240 double nom_x_step; 00241 double nom_y; 00242 double nom_y_step; 00243 00244 public: 00245 double x; 00246 double y; 00247 00248 iterator_x() {} 00249 iterator_x(double px, double py, double step, const trans_perspective& m) : 00250 den(px * m.w0 + py * m.w1 + m.w2), 00251 den_step(m.w0 * step), 00252 nom_x(px * m.sx + py * m.shx + m.tx), 00253 nom_x_step(step * m.sx), 00254 nom_y(px * m.shy + py * m.sy + m.ty), 00255 nom_y_step(step * m.shy), 00256 x(nom_x / den), 00257 y(nom_y / den) 00258 {} 00259 00260 void operator ++ () 00261 { 00262 den += den_step; 00263 nom_x += nom_x_step; 00264 nom_y += nom_y_step; 00265 double d = 1.0 / den; 00266 x = nom_x * d; 00267 y = nom_y * d; 00268 } 00269 }; 00270 00271 //-------------------------------------------------------------------- 00272 iterator_x begin(double x, double y, double step) const 00273 { 00274 return iterator_x(x, y, step, *this); 00275 } 00276 }; 00277 00278 00279 00280 00281 00282 00283 00284 00285 00286 00287 00288 00289 00290 00291 //------------------------------------------------------------------------ 00292 inline bool trans_perspective::square_to_quad(const double* q) 00293 { 00294 double dx = q[0] - q[2] + q[4] - q[6]; 00295 double dy = q[1] - q[3] + q[5] - q[7]; 00296 if(dx == 0.0 && dy == 0.0) 00297 { 00298 // Affine case (parallelogram) 00299 //--------------- 00300 sx = q[2] - q[0]; 00301 shy = q[3] - q[1]; 00302 w0 = 0.0; 00303 shx = q[4] - q[2]; 00304 sy = q[5] - q[3]; 00305 w1 = 0.0; 00306 tx = q[0]; 00307 ty = q[1]; 00308 w2 = 1.0; 00309 } 00310 else 00311 { 00312 double dx1 = q[2] - q[4]; 00313 double dy1 = q[3] - q[5]; 00314 double dx2 = q[6] - q[4]; 00315 double dy2 = q[7] - q[5]; 00316 double den = dx1 * dy2 - dx2 * dy1; 00317 if(den == 0.0) 00318 { 00319 // Singular case 00320 //--------------- 00321 sx = shy = w0 = shx = sy = w1 = tx = ty = w2 = 0.0; 00322 return false; 00323 } 00324 // General case 00325 //--------------- 00326 double u = (dx * dy2 - dy * dx2) / den; 00327 double v = (dy * dx1 - dx * dy1) / den; 00328 sx = q[2] - q[0] + u * q[2]; 00329 shy = q[3] - q[1] + u * q[3]; 00330 w0 = u; 00331 shx = q[6] - q[0] + v * q[6]; 00332 sy = q[7] - q[1] + v * q[7]; 00333 w1 = v; 00334 tx = q[0]; 00335 ty = q[1]; 00336 w2 = 1.0; 00337 } 00338 return true; 00339 } 00340 00341 //------------------------------------------------------------------------ 00342 inline bool trans_perspective::invert() 00343 { 00344 double d0 = sy * w2 - w1 * ty; 00345 double d1 = w0 * ty - shy * w2; 00346 double d2 = shy * w1 - w0 * sy; 00347 double d = sx * d0 + shx * d1 + tx * d2; 00348 if(d == 0.0) 00349 { 00350 sx = shy = w0 = shx = sy = w1 = tx = ty = w2 = 0.0; 00351 return false; 00352 } 00353 d = 1.0 / d; 00354 trans_perspective a = *this; 00355 sx = d * d0; 00356 shy = d * d1; 00357 w0 = d * d2; 00358 shx = d * (a.w1 *a.tx - a.shx*a.w2); 00359 sy = d * (a.sx *a.w2 - a.w0 *a.tx); 00360 w1 = d * (a.w0 *a.shx - a.sx *a.w1); 00361 tx = d * (a.shx*a.ty - a.sy *a.tx); 00362 ty = d * (a.shy*a.tx - a.sx *a.ty); 00363 w2 = d * (a.sx *a.sy - a.shy*a.shx); 00364 return true; 00365 } 00366 00367 //------------------------------------------------------------------------ 00368 inline bool trans_perspective::quad_to_square(const double* q) 00369 { 00370 if(!square_to_quad(q)) return false; 00371 invert(); 00372 return true; 00373 } 00374 00375 //------------------------------------------------------------------------ 00376 inline bool trans_perspective::quad_to_quad(const double* qs, 00377 const double* qd) 00378 { 00379 trans_perspective p; 00380 if(! quad_to_square(qs)) return false; 00381 if(!p.square_to_quad(qd)) return false; 00382 multiply(p); 00383 return true; 00384 } 00385 00386 //------------------------------------------------------------------------ 00387 inline bool trans_perspective::rect_to_quad(double x1, double y1, 00388 double x2, double y2, 00389 const double* q) 00390 { 00391 double r[8]; 00392 r[0] = r[6] = x1; 00393 r[2] = r[4] = x2; 00394 r[1] = r[3] = y1; 00395 r[5] = r[7] = y2; 00396 return quad_to_quad(r, q); 00397 } 00398 00399 //------------------------------------------------------------------------ 00400 inline bool trans_perspective::quad_to_rect(const double* q, 00401 double x1, double y1, 00402 double x2, double y2) 00403 { 00404 double r[8]; 00405 r[0] = r[6] = x1; 00406 r[2] = r[4] = x2; 00407 r[1] = r[3] = y1; 00408 r[5] = r[7] = y2; 00409 return quad_to_quad(q, r); 00410 } 00411 00412 //------------------------------------------------------------------------ 00413 inline trans_perspective::trans_perspective(double x1, double y1, 00414 double x2, double y2, 00415 const double* quad) 00416 { 00417 rect_to_quad(x1, y1, x2, y2, quad); 00418 } 00419 00420 //------------------------------------------------------------------------ 00421 inline trans_perspective::trans_perspective(const double* quad, 00422 double x1, double y1, 00423 double x2, double y2) 00424 { 00425 quad_to_rect(quad, x1, y1, x2, y2); 00426 } 00427 00428 //------------------------------------------------------------------------ 00429 inline trans_perspective::trans_perspective(const double* src, 00430 const double* dst) 00431 { 00432 quad_to_quad(src, dst); 00433 } 00434 00435 //------------------------------------------------------------------------ 00436 inline const trans_perspective& trans_perspective::reset() 00437 { 00438 sx = 1; shy = 0; w0 = 0; 00439 shx = 0; sy = 1; w1 = 0; 00440 tx = 0; ty = 0; w2 = 1; 00441 return *this; 00442 } 00443 00444 //------------------------------------------------------------------------ 00445 inline const trans_perspective& 00446 trans_perspective::multiply(const trans_perspective& a) 00447 { 00448 trans_perspective b = *this; 00449 sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0; 00450 shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1; 00451 tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2; 00452 shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0; 00453 sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1; 00454 ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2; 00455 w0 = a.w0 *b.sx + a.w1 *b.shy + a.w2*b.w0; 00456 w1 = a.w0 *b.shx + a.w1 *b.sy + a.w2*b.w1; 00457 w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2*b.w2; 00458 return *this; 00459 } 00460 00461 //------------------------------------------------------------------------ 00462 inline const trans_perspective& 00463 trans_perspective::multiply(const trans_affine& a) 00464 { 00465 trans_perspective b = *this; 00466 sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0; 00467 shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1; 00468 tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2; 00469 shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0; 00470 sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1; 00471 ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2; 00472 return *this; 00473 } 00474 00475 //------------------------------------------------------------------------ 00476 inline const trans_perspective& 00477 trans_perspective::premultiply(const trans_perspective& b) 00478 { 00479 trans_perspective a = *this; 00480 sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0; 00481 shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1; 00482 tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2; 00483 shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0; 00484 sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1; 00485 ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2; 00486 w0 = a.w0 *b.sx + a.w1 *b.shy + a.w2*b.w0; 00487 w1 = a.w0 *b.shx + a.w1 *b.sy + a.w2*b.w1; 00488 w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2*b.w2; 00489 return *this; 00490 } 00491 00492 //------------------------------------------------------------------------ 00493 inline const trans_perspective& 00494 trans_perspective::premultiply(const trans_affine& b) 00495 { 00496 trans_perspective a = *this; 00497 sx = a.sx *b.sx + a.shx*b.shy; 00498 shx = a.sx *b.shx + a.shx*b.sy; 00499 tx = a.sx *b.tx + a.shx*b.ty + a.tx; 00500 shy = a.shy*b.sx + a.sy *b.shy; 00501 sy = a.shy*b.shx + a.sy *b.sy; 00502 ty = a.shy*b.tx + a.sy *b.ty + a.ty; 00503 w0 = a.w0 *b.sx + a.w1 *b.shy; 00504 w1 = a.w0 *b.shx + a.w1 *b.sy; 00505 w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2; 00506 return *this; 00507 } 00508 00509 //------------------------------------------------------------------------ 00510 const trans_perspective& 00511 trans_perspective::multiply_inv(const trans_perspective& m) 00512 { 00513 trans_perspective t = m; 00514 t.invert(); 00515 return multiply(t); 00516 } 00517 00518 //------------------------------------------------------------------------ 00519 const trans_perspective& 00520 trans_perspective::multiply_inv(const trans_affine& m) 00521 { 00522 trans_affine t = m; 00523 t.invert(); 00524 return multiply(t); 00525 } 00526 00527 //------------------------------------------------------------------------ 00528 const trans_perspective& 00529 trans_perspective::premultiply_inv(const trans_perspective& m) 00530 { 00531 trans_perspective t = m; 00532 t.invert(); 00533 return *this = t.multiply(*this); 00534 } 00535 00536 //------------------------------------------------------------------------ 00537 const trans_perspective& 00538 trans_perspective::premultiply_inv(const trans_affine& m) 00539 { 00540 trans_perspective t(m); 00541 t.invert(); 00542 return *this = t.multiply(*this); 00543 } 00544 00545 //------------------------------------------------------------------------ 00546 inline const trans_perspective& 00547 trans_perspective::translate(double x, double y) 00548 { 00549 tx += x; 00550 ty += y; 00551 return *this; 00552 } 00553 00554 //------------------------------------------------------------------------ 00555 inline const trans_perspective& trans_perspective::rotate(double a) 00556 { 00557 multiply(trans_affine_rotation(a)); 00558 return *this; 00559 } 00560 00561 //------------------------------------------------------------------------ 00562 inline const trans_perspective& trans_perspective::scale(double s) 00563 { 00564 multiply(trans_affine_scaling(s)); 00565 return *this; 00566 } 00567 00568 //------------------------------------------------------------------------ 00569 inline const trans_perspective& trans_perspective::scale(double x, double y) 00570 { 00571 multiply(trans_affine_scaling(x, y)); 00572 return *this; 00573 } 00574 00575 //------------------------------------------------------------------------ 00576 inline void trans_perspective::transform(double* px, double* py) const 00577 { 00578 double x = *px; 00579 double y = *py; 00580 double m = 1.0 / (x*w0 + y*w1 + w2); 00581 *px = m * (x*sx + y*shx + tx); 00582 *py = m * (x*shy + y*sy + ty); 00583 } 00584 00585 //------------------------------------------------------------------------ 00586 inline void trans_perspective::transform_affine(double* x, double* y) const 00587 { 00588 double tmp = *x; 00589 *x = tmp * sx + *y * shx + tx; 00590 *y = tmp * shy + *y * sy + ty; 00591 } 00592 00593 //------------------------------------------------------------------------ 00594 inline void trans_perspective::transform_2x2(double* x, double* y) const 00595 { 00596 double tmp = *x; 00597 *x = tmp * sx + *y * shx; 00598 *y = tmp * shy + *y * sy; 00599 } 00600 00601 //------------------------------------------------------------------------ 00602 inline void trans_perspective::inverse_transform(double* x, double* y) const 00603 { 00604 trans_perspective t(*this); 00605 if(t.invert()) t.transform(x, y); 00606 } 00607 00608 //------------------------------------------------------------------------ 00609 inline void trans_perspective::store_to(double* m) const 00610 { 00611 *m++ = sx; *m++ = shy; *m++ = w0; 00612 *m++ = shx; *m++ = sy; *m++ = w1; 00613 *m++ = tx; *m++ = ty; *m++ = w2; 00614 } 00615 00616 //------------------------------------------------------------------------ 00617 inline const trans_perspective& trans_perspective::load_from(const double* m) 00618 { 00619 sx = *m++; shy = *m++; w0 = *m++; 00620 shx = *m++; sy = *m++; w1 = *m++; 00621 tx = *m++; ty = *m++; w2 = *m++; 00622 return *this; 00623 } 00624 00625 //------------------------------------------------------------------------ 00626 inline const trans_perspective& 00627 trans_perspective::from_affine(const trans_affine& a) 00628 { 00629 sx = a.sx; shy = a.shy; w0 = 0; 00630 shx = a.shx; sy = a.sy; w1 = 0; 00631 tx = a.tx; ty = a.ty; w2 = 1; 00632 return *this; 00633 } 00634 00635 //------------------------------------------------------------------------ 00636 inline double trans_perspective::determinant() const 00637 { 00638 return sx * (sy * w2 - ty * w1) + 00639 shx * (ty * w0 - shy * w2) + 00640 tx * (shy * w1 - sy * w0); 00641 } 00642 00643 //------------------------------------------------------------------------ 00644 inline double trans_perspective::determinant_reciprocal() const 00645 { 00646 return 1.0 / determinant(); 00647 } 00648 00649 //------------------------------------------------------------------------ 00650 inline bool trans_perspective::is_valid(double epsilon) const 00651 { 00652 return fabs(sx) > epsilon && fabs(sy) > epsilon && fabs(w2) > epsilon; 00653 } 00654 00655 //------------------------------------------------------------------------ 00656 inline bool trans_perspective::is_identity(double epsilon) const 00657 { 00658 return is_equal_eps(sx, 1.0, epsilon) && 00659 is_equal_eps(shy, 0.0, epsilon) && 00660 is_equal_eps(w0, 0.0, epsilon) && 00661 is_equal_eps(shx, 0.0, epsilon) && 00662 is_equal_eps(sy, 1.0, epsilon) && 00663 is_equal_eps(w1, 0.0, epsilon) && 00664 is_equal_eps(tx, 0.0, epsilon) && 00665 is_equal_eps(ty, 0.0, epsilon) && 00666 is_equal_eps(w2, 1.0, epsilon); 00667 } 00668 00669 //------------------------------------------------------------------------ 00670 inline bool trans_perspective::is_equal(const trans_perspective& m, 00671 double epsilon) const 00672 { 00673 return is_equal_eps(sx, m.sx, epsilon) && 00674 is_equal_eps(shy, m.shy, epsilon) && 00675 is_equal_eps(w0, m.w0, epsilon) && 00676 is_equal_eps(shx, m.shx, epsilon) && 00677 is_equal_eps(sy, m.sy, epsilon) && 00678 is_equal_eps(w1, m.w1, epsilon) && 00679 is_equal_eps(tx, m.tx, epsilon) && 00680 is_equal_eps(ty, m.ty, epsilon) && 00681 is_equal_eps(w2, m.w2, epsilon); 00682 } 00683 00684 //------------------------------------------------------------------------ 00685 inline double trans_perspective::scale() const 00686 { 00687 double x = 0.707106781 * sx + 0.707106781 * shx; 00688 double y = 0.707106781 * shy + 0.707106781 * sy; 00689 return sqrt(x*x + y*y); 00690 } 00691 00692 //------------------------------------------------------------------------ 00693 inline double trans_perspective::rotation() const 00694 { 00695 double x1 = 0.0; 00696 double y1 = 0.0; 00697 double x2 = 1.0; 00698 double y2 = 0.0; 00699 transform(&x1, &y1); 00700 transform(&x2, &y2); 00701 return atan2(y2-y1, x2-x1); 00702 } 00703 00704 //------------------------------------------------------------------------ 00705 void trans_perspective::translation(double* dx, double* dy) const 00706 { 00707 *dx = tx; 00708 *dy = ty; 00709 } 00710 00711 //------------------------------------------------------------------------ 00712 void trans_perspective::scaling(double* x, double* y) const 00713 { 00714 double x1 = 0.0; 00715 double y1 = 0.0; 00716 double x2 = 1.0; 00717 double y2 = 1.0; 00718 trans_perspective t(*this); 00719 t *= trans_affine_rotation(-rotation()); 00720 t.transform(&x1, &y1); 00721 t.transform(&x2, &y2); 00722 *x = x2 - x1; 00723 *y = y2 - y1; 00724 } 00725 00726 //------------------------------------------------------------------------ 00727 void trans_perspective::scaling_abs(double* x, double* y) const 00728 { 00729 *x = sqrt(sx * sx + shx * shx); 00730 *y = sqrt(shy * shy + sy * sy); 00731 } 00732 00733 00734 } 00735 00736 #endif 00737