19 #ifndef AGG_TRANS_PERSPECTIVE_INCLUDED 20 #define AGG_TRANS_PERSPECTIVE_INCLUDED 23 #include "agg_trans_affine.h" 30 double sx, shy, w0, shx, sy, w1, tx, ty, w2;
35 sx (1), shy(0), w0(0),
36 shx(0), sy (1), w1(0),
37 tx (0), ty (0), w2(1) {}
41 double v3,
double v4,
double v5,
42 double v6,
double v7,
double v8) :
43 sx (v0), shy(v1), w0(v2),
44 shx(v3), sy (v4), w1(v5),
45 tx (v6), ty (v7), w2(v8) {}
49 sx (m[0]), shy(m[1]), w0(m[2]),
50 shx(m[3]), sy (m[4]), w1(m[5]),
51 tx (m[6]), ty (m[7]), w2(m[8]) {}
55 sx (a.sx ), shy(a.shy), w0(0),
56 shx(a.shx), sy (a.sy ), w1(0),
57 tx (a.tx ), ty (a.ty ), w2(1) {}
65 double x1,
double y1,
double x2,
double y2);
73 bool quad_to_quad(
const double* qs,
const double* qd);
75 bool rect_to_quad(
double x1,
double y1,
79 bool quad_to_rect(
const double* q,
81 double x2,
double y2);
84 bool square_to_quad(
const double* q);
85 bool quad_to_square(
const double* q);
126 void store_to(
double* m)
const;
143 return multiply_inv(m);
147 return multiply_inv(m);
183 return is_equal(m, affine_epsilon);
189 return !is_equal(m, affine_epsilon);
194 void transform(
double* x,
double* y)
const;
197 void transform_affine(
double* x,
double* y)
const;
200 void transform_2x2(
double* x,
double* y)
const;
206 void inverse_transform(
double* x,
double* y)
const;
211 double determinant()
const;
212 double determinant_reciprocal()
const;
214 bool is_valid(
double epsilon = affine_epsilon)
const;
215 bool is_identity(
double epsilon = affine_epsilon)
const;
217 double epsilon = affine_epsilon)
const;
221 double scale()
const;
222 double rotation()
const;
223 void translation(
double* dx,
double* dy)
const;
224 void scaling(
double* x,
double* y)
const;
225 void scaling_abs(
double* x,
double* y)
const;
245 den(px * m.w0 + py * m.w1 + m.w2),
246 den_step(m.w0 * step),
247 nom_x(px * m.sx + py * m.shx + m.tx),
248 nom_x_step(step * m.sx),
249 nom_y(px * m.shy + py * m.sy + m.ty),
250 nom_y_step(step * m.shy),
260 double d = 1.0 / den;
267 iterator_x begin(
double x,
double y,
double step)
const 287 inline bool trans_perspective::square_to_quad(
const double* q)
289 double dx = q[0] - q[2] + q[4] - q[6];
290 double dy = q[1] - q[3] + q[5] - q[7];
291 if(dx == 0.0 && dy == 0.0)
307 double dx1 = q[2] - q[4];
308 double dy1 = q[3] - q[5];
309 double dx2 = q[6] - q[4];
310 double dy2 = q[7] - q[5];
311 double den = dx1 * dy2 - dx2 * dy1;
316 sx = shy = w0 = shx = sy = w1 = tx = ty = w2 = 0.0;
321 double u = (dx * dy2 - dy * dx2) / den;
322 double v = (dy * dx1 - dx * dy1) / den;
323 sx = q[2] - q[0] + u * q[2];
324 shy = q[3] - q[1] + u * q[3];
326 shx = q[6] - q[0] + v * q[6];
327 sy = q[7] - q[1] + v * q[7];
337 inline bool trans_perspective::invert()
339 double d0 = sy * w2 - w1 * ty;
340 double d1 = w0 * ty - shy * w2;
341 double d2 = shy * w1 - w0 * sy;
342 double d = sx * d0 + shx * d1 + tx * d2;
345 sx = shy = w0 = shx = sy = w1 = tx = ty = w2 = 0.0;
353 shx = d * (a.w1 *a.tx - a.shx*a.w2);
354 sy = d * (a.sx *a.w2 - a.w0 *a.tx);
355 w1 = d * (a.w0 *a.shx - a.sx *a.w1);
356 tx = d * (a.shx*a.ty - a.sy *a.tx);
357 ty = d * (a.shy*a.tx - a.sx *a.ty);
358 w2 = d * (a.sx *a.sy - a.shy*a.shx);
363 inline bool trans_perspective::quad_to_square(
const double* q)
365 if(!square_to_quad(q))
return false;
371 inline bool trans_perspective::quad_to_quad(
const double* qs,
375 if(! quad_to_square(qs))
return false;
376 if(!p.square_to_quad(qd))
return false;
382 inline bool trans_perspective::rect_to_quad(
double x1,
double y1,
383 double x2,
double y2,
391 return quad_to_quad(r, q);
395 inline bool trans_perspective::quad_to_rect(
const double* q,
396 double x1,
double y1,
397 double x2,
double y2)
404 return quad_to_quad(q, r);
408 inline trans_perspective::trans_perspective(
double x1,
double y1,
409 double x2,
double y2,
412 rect_to_quad(x1, y1, x2, y2, quad);
416 inline trans_perspective::trans_perspective(
const double* quad,
417 double x1,
double y1,
418 double x2,
double y2)
420 quad_to_rect(quad, x1, y1, x2, y2);
424 inline trans_perspective::trans_perspective(
const double* src,
427 quad_to_quad(src, dst);
433 sx = 1; shy = 0; w0 = 0;
434 shx = 0; sy = 1; w1 = 0;
435 tx = 0; ty = 0; w2 = 1;
444 sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0;
445 shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1;
446 tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2;
447 shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0;
448 sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1;
449 ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2;
450 w0 = a.w0 *b.sx + a.w1 *b.shy + a.w2*b.w0;
451 w1 = a.w0 *b.shx + a.w1 *b.sy + a.w2*b.w1;
452 w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2*b.w2;
461 sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0;
462 shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1;
463 tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2;
464 shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0;
465 sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1;
466 ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2;
475 sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0;
476 shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1;
477 tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2;
478 shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0;
479 sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1;
480 ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2;
481 w0 = a.w0 *b.sx + a.w1 *b.shy + a.w2*b.w0;
482 w1 = a.w0 *b.shx + a.w1 *b.sy + a.w2*b.w1;
483 w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2*b.w2;
492 sx = a.sx *b.sx + a.shx*b.shy;
493 shx = a.sx *b.shx + a.shx*b.sy;
494 tx = a.sx *b.tx + a.shx*b.ty + a.tx;
495 shy = a.shy*b.sx + a.sy *b.shy;
496 sy = a.shy*b.shx + a.sy *b.sy;
497 ty = a.shy*b.tx + a.sy *b.ty + a.ty;
498 w0 = a.w0 *b.sx + a.w1 *b.shy;
499 w1 = a.w0 *b.shx + a.w1 *b.sy;
500 w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2;
528 return *
this = t.multiply(*
this);
533 trans_perspective::premultiply_inv(
const trans_affine& m)
537 return *
this = t.multiply(*
this);
542 trans_perspective::translate(
double x,
double y)
571 inline void trans_perspective::transform(
double* px,
double* py)
const 575 double m = 1.0 / (x*w0 + y*w1 + w2);
576 *px = m * (x*sx + y*shx + tx);
577 *py = m * (x*shy + y*sy + ty);
581 inline void trans_perspective::transform_affine(
double* x,
double* y)
const 584 *x = tmp * sx + *y * shx + tx;
585 *y = tmp * shy + *y * sy + ty;
589 inline void trans_perspective::transform_2x2(
double* x,
double* y)
const 592 *x = tmp * sx + *y * shx;
593 *y = tmp * shy + *y * sy;
597 inline void trans_perspective::inverse_transform(
double* x,
double* y)
const 600 if(t.invert()) t.transform(x, y);
604 inline void trans_perspective::store_to(
double* m)
const 606 *m++ = sx; *m++ = shy; *m++ = w0;
607 *m++ = shx; *m++ = sy; *m++ = w1;
608 *m++ = tx; *m++ = ty; *m++ = w2;
614 sx = *m++; shy = *m++; w0 = *m++;
615 shx = *m++; sy = *m++; w1 = *m++;
616 tx = *m++; ty = *m++; w2 = *m++;
624 sx = a.sx; shy = a.shy; w0 = 0;
625 shx = a.shx; sy = a.sy; w1 = 0;
626 tx = a.tx; ty = a.ty; w2 = 1;
631 inline double trans_perspective::determinant()
const 633 return sx * (sy * w2 - ty * w1) +
634 shx * (ty * w0 - shy * w2) +
635 tx * (shy * w1 - sy * w0);
639 inline double trans_perspective::determinant_reciprocal()
const 641 return 1.0 / determinant();
645 inline bool trans_perspective::is_valid(
double epsilon)
const 647 return std::fabs(sx) > epsilon && std::fabs(sy) > epsilon && std::fabs(w2) > epsilon;
651 inline bool trans_perspective::is_identity(
double epsilon)
const 653 return is_equal_eps(sx, 1.0, epsilon) &&
654 is_equal_eps(shy, 0.0, epsilon) &&
655 is_equal_eps(w0, 0.0, epsilon) &&
656 is_equal_eps(shx, 0.0, epsilon) &&
657 is_equal_eps(sy, 1.0, epsilon) &&
658 is_equal_eps(w1, 0.0, epsilon) &&
659 is_equal_eps(tx, 0.0, epsilon) &&
660 is_equal_eps(ty, 0.0, epsilon) &&
661 is_equal_eps(w2, 1.0, epsilon);
666 double epsilon)
const 668 return is_equal_eps(sx, m.sx, epsilon) &&
669 is_equal_eps(shy, m.shy, epsilon) &&
670 is_equal_eps(w0, m.w0, epsilon) &&
671 is_equal_eps(shx, m.shx, epsilon) &&
672 is_equal_eps(sy, m.sy, epsilon) &&
673 is_equal_eps(w1, m.w1, epsilon) &&
674 is_equal_eps(tx, m.tx, epsilon) &&
675 is_equal_eps(ty, m.ty, epsilon) &&
676 is_equal_eps(w2, m.w2, epsilon);
680 inline double trans_perspective::scale()
const 682 double x = 0.707106781 * sx + 0.707106781 * shx;
683 double y = 0.707106781 * shy + 0.707106781 * sy;
684 return std::sqrt(x*x + y*y);
688 inline double trans_perspective::rotation()
const 696 return std::atan2(y2-y1, x2-x1);
700 void trans_perspective::translation(
double* dx,
double* dy)
const 707 void trans_perspective::scaling(
double* x,
double* y)
const 715 t.transform(&x1, &y1);
716 t.transform(&x2, &y2);
722 void trans_perspective::scaling_abs(
double* x,
double* y)
const 724 *x = std::sqrt(sx * sx + shx * shx);
725 *y = std::sqrt(shy * shy + sy * sy);