agg_trans_perspective.h 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731
  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. // Perspective 2D transformations
  17. //
  18. //----------------------------------------------------------------------------
  19. #ifndef AGG_TRANS_PERSPECTIVE_INCLUDED
  20. #define AGG_TRANS_PERSPECTIVE_INCLUDED
  21. #include "agg_trans_affine.h"
  22. namespace agg
  23. {
  24. //=======================================================trans_perspective
  25. struct trans_perspective
  26. {
  27. double sx, shy, w0, shx, sy, w1, tx, ty, w2;
  28. //------------------------------------------------------- Construction
  29. // Identity matrix
  30. trans_perspective() :
  31. sx (1), shy(0), w0(0),
  32. shx(0), sy (1), w1(0),
  33. tx (0), ty (0), w2(1) {}
  34. // Custom matrix
  35. trans_perspective(double v0, double v1, double v2,
  36. double v3, double v4, double v5,
  37. double v6, double v7, double v8) :
  38. sx (v0), shy(v1), w0(v2),
  39. shx(v3), sy (v4), w1(v5),
  40. tx (v6), ty (v7), w2(v8) {}
  41. // Custom matrix from m[9]
  42. explicit trans_perspective(const double* m) :
  43. sx (m[0]), shy(m[1]), w0(m[2]),
  44. shx(m[3]), sy (m[4]), w1(m[5]),
  45. tx (m[6]), ty (m[7]), w2(m[8]) {}
  46. // From affine
  47. explicit trans_perspective(const trans_affine& a) :
  48. sx (a.sx ), shy(a.shy), w0(0),
  49. shx(a.shx), sy (a.sy ), w1(0),
  50. tx (a.tx ), ty (a.ty ), w2(1) {}
  51. // Rectangle to quadrilateral
  52. trans_perspective(double x1, double y1, double x2, double y2,
  53. const double* quad);
  54. // Quadrilateral to rectangle
  55. trans_perspective(const double* quad,
  56. double x1, double y1, double x2, double y2);
  57. // Arbitrary quadrilateral transformations
  58. trans_perspective(const double* src, const double* dst);
  59. //-------------------------------------- Quadrilateral transformations
  60. // The arguments are double[8] that are mapped to quadrilaterals:
  61. // x1,y1, x2,y2, x3,y3, x4,y4
  62. bool quad_to_quad(const double* qs, const double* qd);
  63. bool rect_to_quad(double x1, double y1,
  64. double x2, double y2,
  65. const double* q);
  66. bool quad_to_rect(const double* q,
  67. double x1, double y1,
  68. double x2, double y2);
  69. // Map square (0,0,1,1) to the quadrilateral and vice versa
  70. bool square_to_quad(const double* q);
  71. bool quad_to_square(const double* q);
  72. //--------------------------------------------------------- Operations
  73. // Reset - load an identity matrix
  74. const trans_perspective& reset();
  75. // Invert matrix. Returns false in degenerate case
  76. bool invert();
  77. // Direct transformations operations
  78. const trans_perspective& translate(double x, double y);
  79. const trans_perspective& rotate(double a);
  80. const trans_perspective& scale(double s);
  81. const trans_perspective& scale(double x, double y);
  82. // Multiply the matrix by another one
  83. const trans_perspective& multiply(const trans_perspective& m);
  84. // Multiply "m" by "this" and assign the result to "this"
  85. const trans_perspective& premultiply(const trans_perspective& m);
  86. // Multiply matrix to inverse of another one
  87. const trans_perspective& multiply_inv(const trans_perspective& m);
  88. // Multiply inverse of "m" by "this" and assign the result to "this"
  89. const trans_perspective& premultiply_inv(const trans_perspective& m);
  90. // Multiply the matrix by another one
  91. const trans_perspective& multiply(const trans_affine& m);
  92. // Multiply "m" by "this" and assign the result to "this"
  93. const trans_perspective& premultiply(const trans_affine& m);
  94. // Multiply the matrix by inverse of another one
  95. const trans_perspective& multiply_inv(const trans_affine& m);
  96. // Multiply inverse of "m" by "this" and assign the result to "this"
  97. const trans_perspective& premultiply_inv(const trans_affine& m);
  98. //--------------------------------------------------------- Load/Store
  99. void store_to(double* m) const;
  100. const trans_perspective& load_from(const double* m);
  101. //---------------------------------------------------------- Operators
  102. // Multiply the matrix by another one
  103. const trans_perspective& operator *= (const trans_perspective& m)
  104. {
  105. return multiply(m);
  106. }
  107. const trans_perspective& operator *= (const trans_affine& m)
  108. {
  109. return multiply(m);
  110. }
  111. // Multiply the matrix by inverse of another one
  112. const trans_perspective& operator /= (const trans_perspective& m)
  113. {
  114. return multiply_inv(m);
  115. }
  116. const trans_perspective& operator /= (const trans_affine& m)
  117. {
  118. return multiply_inv(m);
  119. }
  120. // Multiply the matrix by another one and return
  121. // the result in a separete matrix.
  122. trans_perspective operator * (const trans_perspective& m) const
  123. {
  124. return trans_perspective(*this).multiply(m);
  125. }
  126. trans_perspective operator * (const trans_affine& m) const
  127. {
  128. return trans_perspective(*this).multiply(m);
  129. }
  130. // Multiply the matrix by inverse of another one
  131. // and return the result in a separete matrix.
  132. trans_perspective operator / (const trans_perspective& m) const
  133. {
  134. return trans_perspective(*this).multiply_inv(m);
  135. }
  136. trans_perspective operator / (const trans_affine& m) const
  137. {
  138. return trans_perspective(*this).multiply_inv(m);
  139. }
  140. // Calculate and return the inverse matrix
  141. trans_perspective operator ~ () const
  142. {
  143. trans_perspective ret = *this;
  144. ret.invert();
  145. return ret;
  146. }
  147. // Equal operator with default epsilon
  148. bool operator == (const trans_perspective& m) const
  149. {
  150. return is_equal(m, affine_epsilon);
  151. }
  152. // Not Equal operator with default epsilon
  153. bool operator != (const trans_perspective& m) const
  154. {
  155. return !is_equal(m, affine_epsilon);
  156. }
  157. //---------------------------------------------------- Transformations
  158. // Direct transformation of x and y
  159. void transform(double* x, double* y) const;
  160. // Direct transformation of x and y, affine part only
  161. void transform_affine(double* x, double* y) const;
  162. // Direct transformation of x and y, 2x2 matrix only, no translation
  163. void transform_2x2(double* x, double* y) const;
  164. // Inverse transformation of x and y. It works slow because
  165. // it explicitly inverts the matrix on every call. For massive
  166. // operations it's better to invert() the matrix and then use
  167. // direct transformations.
  168. void inverse_transform(double* x, double* y) const;
  169. //---------------------------------------------------------- Auxiliary
  170. const trans_perspective& from_affine(const trans_affine& a);
  171. double determinant() const;
  172. double determinant_reciprocal() const;
  173. bool is_valid(double epsilon = affine_epsilon) const;
  174. bool is_identity(double epsilon = affine_epsilon) const;
  175. bool is_equal(const trans_perspective& m,
  176. double epsilon = affine_epsilon) const;
  177. // Determine the major affine parameters. Use with caution
  178. // considering possible degenerate cases.
  179. double scale() const;
  180. double rotation() const;
  181. void translation(double* dx, double* dy) const;
  182. void scaling(double* x, double* y) const;
  183. void scaling_abs(double* x, double* y) const;
  184. //--------------------------------------------------------------------
  185. class iterator_x
  186. {
  187. double den;
  188. double den_step;
  189. double nom_x;
  190. double nom_x_step;
  191. double nom_y;
  192. double nom_y_step;
  193. public:
  194. double x;
  195. double y;
  196. iterator_x() {}
  197. iterator_x(double px, double py, double step, const trans_perspective& m) :
  198. den(px * m.w0 + py * m.w1 + m.w2),
  199. den_step(m.w0 * step),
  200. nom_x(px * m.sx + py * m.shx + m.tx),
  201. nom_x_step(step * m.sx),
  202. nom_y(px * m.shy + py * m.sy + m.ty),
  203. nom_y_step(step * m.shy),
  204. x(nom_x / den),
  205. y(nom_y / den)
  206. {}
  207. void operator ++ ()
  208. {
  209. den += den_step;
  210. nom_x += nom_x_step;
  211. nom_y += nom_y_step;
  212. double d = 1.0 / den;
  213. x = nom_x * d;
  214. y = nom_y * d;
  215. }
  216. };
  217. //--------------------------------------------------------------------
  218. iterator_x begin(double x, double y, double step) const
  219. {
  220. return iterator_x(x, y, step, *this);
  221. }
  222. };
  223. //------------------------------------------------------------------------
  224. inline bool trans_perspective::square_to_quad(const double* q)
  225. {
  226. double dx = q[0] - q[2] + q[4] - q[6];
  227. double dy = q[1] - q[3] + q[5] - q[7];
  228. if(dx == 0.0 && dy == 0.0)
  229. {
  230. // Affine case (parallelogram)
  231. //---------------
  232. sx = q[2] - q[0];
  233. shy = q[3] - q[1];
  234. w0 = 0.0;
  235. shx = q[4] - q[2];
  236. sy = q[5] - q[3];
  237. w1 = 0.0;
  238. tx = q[0];
  239. ty = q[1];
  240. w2 = 1.0;
  241. }
  242. else
  243. {
  244. double dx1 = q[2] - q[4];
  245. double dy1 = q[3] - q[5];
  246. double dx2 = q[6] - q[4];
  247. double dy2 = q[7] - q[5];
  248. double den = dx1 * dy2 - dx2 * dy1;
  249. if(den == 0.0)
  250. {
  251. // Singular case
  252. //---------------
  253. sx = shy = w0 = shx = sy = w1 = tx = ty = w2 = 0.0;
  254. return false;
  255. }
  256. // General case
  257. //---------------
  258. double u = (dx * dy2 - dy * dx2) / den;
  259. double v = (dy * dx1 - dx * dy1) / den;
  260. sx = q[2] - q[0] + u * q[2];
  261. shy = q[3] - q[1] + u * q[3];
  262. w0 = u;
  263. shx = q[6] - q[0] + v * q[6];
  264. sy = q[7] - q[1] + v * q[7];
  265. w1 = v;
  266. tx = q[0];
  267. ty = q[1];
  268. w2 = 1.0;
  269. }
  270. return true;
  271. }
  272. //------------------------------------------------------------------------
  273. inline bool trans_perspective::invert()
  274. {
  275. double d0 = sy * w2 - w1 * ty;
  276. double d1 = w0 * ty - shy * w2;
  277. double d2 = shy * w1 - w0 * sy;
  278. double d = sx * d0 + shx * d1 + tx * d2;
  279. if(d == 0.0)
  280. {
  281. sx = shy = w0 = shx = sy = w1 = tx = ty = w2 = 0.0;
  282. return false;
  283. }
  284. d = 1.0 / d;
  285. trans_perspective a = *this;
  286. sx = d * d0;
  287. shy = d * d1;
  288. w0 = d * d2;
  289. shx = d * (a.w1 *a.tx - a.shx*a.w2);
  290. sy = d * (a.sx *a.w2 - a.w0 *a.tx);
  291. w1 = d * (a.w0 *a.shx - a.sx *a.w1);
  292. tx = d * (a.shx*a.ty - a.sy *a.tx);
  293. ty = d * (a.shy*a.tx - a.sx *a.ty);
  294. w2 = d * (a.sx *a.sy - a.shy*a.shx);
  295. return true;
  296. }
  297. //------------------------------------------------------------------------
  298. inline bool trans_perspective::quad_to_square(const double* q)
  299. {
  300. if(!square_to_quad(q)) return false;
  301. invert();
  302. return true;
  303. }
  304. //------------------------------------------------------------------------
  305. inline bool trans_perspective::quad_to_quad(const double* qs,
  306. const double* qd)
  307. {
  308. trans_perspective p;
  309. if(! quad_to_square(qs)) return false;
  310. if(!p.square_to_quad(qd)) return false;
  311. multiply(p);
  312. return true;
  313. }
  314. //------------------------------------------------------------------------
  315. inline bool trans_perspective::rect_to_quad(double x1, double y1,
  316. double x2, double y2,
  317. const double* q)
  318. {
  319. double r[8];
  320. r[0] = r[6] = x1;
  321. r[2] = r[4] = x2;
  322. r[1] = r[3] = y1;
  323. r[5] = r[7] = y2;
  324. return quad_to_quad(r, q);
  325. }
  326. //------------------------------------------------------------------------
  327. inline bool trans_perspective::quad_to_rect(const double* q,
  328. double x1, double y1,
  329. double x2, double y2)
  330. {
  331. double r[8];
  332. r[0] = r[6] = x1;
  333. r[2] = r[4] = x2;
  334. r[1] = r[3] = y1;
  335. r[5] = r[7] = y2;
  336. return quad_to_quad(q, r);
  337. }
  338. //------------------------------------------------------------------------
  339. inline trans_perspective::trans_perspective(double x1, double y1,
  340. double x2, double y2,
  341. const double* quad)
  342. {
  343. rect_to_quad(x1, y1, x2, y2, quad);
  344. }
  345. //------------------------------------------------------------------------
  346. inline trans_perspective::trans_perspective(const double* quad,
  347. double x1, double y1,
  348. double x2, double y2)
  349. {
  350. quad_to_rect(quad, x1, y1, x2, y2);
  351. }
  352. //------------------------------------------------------------------------
  353. inline trans_perspective::trans_perspective(const double* src,
  354. const double* dst)
  355. {
  356. quad_to_quad(src, dst);
  357. }
  358. //------------------------------------------------------------------------
  359. inline const trans_perspective& trans_perspective::reset()
  360. {
  361. sx = 1; shy = 0; w0 = 0;
  362. shx = 0; sy = 1; w1 = 0;
  363. tx = 0; ty = 0; w2 = 1;
  364. return *this;
  365. }
  366. //------------------------------------------------------------------------
  367. inline const trans_perspective&
  368. trans_perspective::multiply(const trans_perspective& a)
  369. {
  370. trans_perspective b = *this;
  371. sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0;
  372. shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1;
  373. tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2;
  374. shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0;
  375. sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1;
  376. ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2;
  377. w0 = a.w0 *b.sx + a.w1 *b.shy + a.w2*b.w0;
  378. w1 = a.w0 *b.shx + a.w1 *b.sy + a.w2*b.w1;
  379. w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2*b.w2;
  380. return *this;
  381. }
  382. //------------------------------------------------------------------------
  383. inline const trans_perspective&
  384. trans_perspective::multiply(const trans_affine& a)
  385. {
  386. trans_perspective b = *this;
  387. sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0;
  388. shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1;
  389. tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2;
  390. shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0;
  391. sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1;
  392. ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2;
  393. return *this;
  394. }
  395. //------------------------------------------------------------------------
  396. inline const trans_perspective&
  397. trans_perspective::premultiply(const trans_perspective& b)
  398. {
  399. trans_perspective a = *this;
  400. sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0;
  401. shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1;
  402. tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2;
  403. shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0;
  404. sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1;
  405. ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2;
  406. w0 = a.w0 *b.sx + a.w1 *b.shy + a.w2*b.w0;
  407. w1 = a.w0 *b.shx + a.w1 *b.sy + a.w2*b.w1;
  408. w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2*b.w2;
  409. return *this;
  410. }
  411. //------------------------------------------------------------------------
  412. inline const trans_perspective&
  413. trans_perspective::premultiply(const trans_affine& b)
  414. {
  415. trans_perspective a = *this;
  416. sx = a.sx *b.sx + a.shx*b.shy;
  417. shx = a.sx *b.shx + a.shx*b.sy;
  418. tx = a.sx *b.tx + a.shx*b.ty + a.tx;
  419. shy = a.shy*b.sx + a.sy *b.shy;
  420. sy = a.shy*b.shx + a.sy *b.sy;
  421. ty = a.shy*b.tx + a.sy *b.ty + a.ty;
  422. w0 = a.w0 *b.sx + a.w1 *b.shy;
  423. w1 = a.w0 *b.shx + a.w1 *b.sy;
  424. w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2;
  425. return *this;
  426. }
  427. //------------------------------------------------------------------------
  428. const trans_perspective&
  429. trans_perspective::multiply_inv(const trans_perspective& m)
  430. {
  431. trans_perspective t = m;
  432. t.invert();
  433. return multiply(t);
  434. }
  435. //------------------------------------------------------------------------
  436. const trans_perspective&
  437. trans_perspective::multiply_inv(const trans_affine& m)
  438. {
  439. trans_affine t = m;
  440. t.invert();
  441. return multiply(t);
  442. }
  443. //------------------------------------------------------------------------
  444. const trans_perspective&
  445. trans_perspective::premultiply_inv(const trans_perspective& m)
  446. {
  447. trans_perspective t = m;
  448. t.invert();
  449. return *this = t.multiply(*this);
  450. }
  451. //------------------------------------------------------------------------
  452. const trans_perspective&
  453. trans_perspective::premultiply_inv(const trans_affine& m)
  454. {
  455. trans_perspective t(m);
  456. t.invert();
  457. return *this = t.multiply(*this);
  458. }
  459. //------------------------------------------------------------------------
  460. inline const trans_perspective&
  461. trans_perspective::translate(double x, double y)
  462. {
  463. tx += x;
  464. ty += y;
  465. return *this;
  466. }
  467. //------------------------------------------------------------------------
  468. inline const trans_perspective& trans_perspective::rotate(double a)
  469. {
  470. multiply(trans_affine_rotation(a));
  471. return *this;
  472. }
  473. //------------------------------------------------------------------------
  474. inline const trans_perspective& trans_perspective::scale(double s)
  475. {
  476. multiply(trans_affine_scaling(s));
  477. return *this;
  478. }
  479. //------------------------------------------------------------------------
  480. inline const trans_perspective& trans_perspective::scale(double x, double y)
  481. {
  482. multiply(trans_affine_scaling(x, y));
  483. return *this;
  484. }
  485. //------------------------------------------------------------------------
  486. inline void trans_perspective::transform(double* px, double* py) const
  487. {
  488. double x = *px;
  489. double y = *py;
  490. double m = 1.0 / (x*w0 + y*w1 + w2);
  491. *px = m * (x*sx + y*shx + tx);
  492. *py = m * (x*shy + y*sy + ty);
  493. }
  494. //------------------------------------------------------------------------
  495. inline void trans_perspective::transform_affine(double* x, double* y) const
  496. {
  497. double tmp = *x;
  498. *x = tmp * sx + *y * shx + tx;
  499. *y = tmp * shy + *y * sy + ty;
  500. }
  501. //------------------------------------------------------------------------
  502. inline void trans_perspective::transform_2x2(double* x, double* y) const
  503. {
  504. double tmp = *x;
  505. *x = tmp * sx + *y * shx;
  506. *y = tmp * shy + *y * sy;
  507. }
  508. //------------------------------------------------------------------------
  509. inline void trans_perspective::inverse_transform(double* x, double* y) const
  510. {
  511. trans_perspective t(*this);
  512. if(t.invert()) t.transform(x, y);
  513. }
  514. //------------------------------------------------------------------------
  515. inline void trans_perspective::store_to(double* m) const
  516. {
  517. *m++ = sx; *m++ = shy; *m++ = w0;
  518. *m++ = shx; *m++ = sy; *m++ = w1;
  519. *m++ = tx; *m++ = ty; *m++ = w2;
  520. }
  521. //------------------------------------------------------------------------
  522. inline const trans_perspective& trans_perspective::load_from(const double* m)
  523. {
  524. sx = *m++; shy = *m++; w0 = *m++;
  525. shx = *m++; sy = *m++; w1 = *m++;
  526. tx = *m++; ty = *m++; w2 = *m++;
  527. return *this;
  528. }
  529. //------------------------------------------------------------------------
  530. inline const trans_perspective&
  531. trans_perspective::from_affine(const trans_affine& a)
  532. {
  533. sx = a.sx; shy = a.shy; w0 = 0;
  534. shx = a.shx; sy = a.sy; w1 = 0;
  535. tx = a.tx; ty = a.ty; w2 = 1;
  536. return *this;
  537. }
  538. //------------------------------------------------------------------------
  539. inline double trans_perspective::determinant() const
  540. {
  541. return sx * (sy * w2 - ty * w1) +
  542. shx * (ty * w0 - shy * w2) +
  543. tx * (shy * w1 - sy * w0);
  544. }
  545. //------------------------------------------------------------------------
  546. inline double trans_perspective::determinant_reciprocal() const
  547. {
  548. return 1.0 / determinant();
  549. }
  550. //------------------------------------------------------------------------
  551. inline bool trans_perspective::is_valid(double epsilon) const
  552. {
  553. return fabs(sx) > epsilon && fabs(sy) > epsilon && fabs(w2) > epsilon;
  554. }
  555. //------------------------------------------------------------------------
  556. inline bool trans_perspective::is_identity(double epsilon) const
  557. {
  558. return is_equal_eps(sx, 1.0, epsilon) &&
  559. is_equal_eps(shy, 0.0, epsilon) &&
  560. is_equal_eps(w0, 0.0, epsilon) &&
  561. is_equal_eps(shx, 0.0, epsilon) &&
  562. is_equal_eps(sy, 1.0, epsilon) &&
  563. is_equal_eps(w1, 0.0, epsilon) &&
  564. is_equal_eps(tx, 0.0, epsilon) &&
  565. is_equal_eps(ty, 0.0, epsilon) &&
  566. is_equal_eps(w2, 1.0, epsilon);
  567. }
  568. //------------------------------------------------------------------------
  569. inline bool trans_perspective::is_equal(const trans_perspective& m,
  570. double epsilon) const
  571. {
  572. return is_equal_eps(sx, m.sx, epsilon) &&
  573. is_equal_eps(shy, m.shy, epsilon) &&
  574. is_equal_eps(w0, m.w0, epsilon) &&
  575. is_equal_eps(shx, m.shx, epsilon) &&
  576. is_equal_eps(sy, m.sy, epsilon) &&
  577. is_equal_eps(w1, m.w1, epsilon) &&
  578. is_equal_eps(tx, m.tx, epsilon) &&
  579. is_equal_eps(ty, m.ty, epsilon) &&
  580. is_equal_eps(w2, m.w2, epsilon);
  581. }
  582. //------------------------------------------------------------------------
  583. inline double trans_perspective::scale() const
  584. {
  585. double x = 0.707106781 * sx + 0.707106781 * shx;
  586. double y = 0.707106781 * shy + 0.707106781 * sy;
  587. return sqrt(x*x + y*y);
  588. }
  589. //------------------------------------------------------------------------
  590. inline double trans_perspective::rotation() const
  591. {
  592. double x1 = 0.0;
  593. double y1 = 0.0;
  594. double x2 = 1.0;
  595. double y2 = 0.0;
  596. transform(&x1, &y1);
  597. transform(&x2, &y2);
  598. return atan2(y2-y1, x2-x1);
  599. }
  600. //------------------------------------------------------------------------
  601. void trans_perspective::translation(double* dx, double* dy) const
  602. {
  603. *dx = tx;
  604. *dy = ty;
  605. }
  606. //------------------------------------------------------------------------
  607. void trans_perspective::scaling(double* x, double* y) const
  608. {
  609. double x1 = 0.0;
  610. double y1 = 0.0;
  611. double x2 = 1.0;
  612. double y2 = 1.0;
  613. trans_perspective t(*this);
  614. t *= trans_affine_rotation(-rotation());
  615. t.transform(&x1, &y1);
  616. t.transform(&x2, &y2);
  617. *x = x2 - x1;
  618. *y = y2 - y1;
  619. }
  620. //------------------------------------------------------------------------
  621. void trans_perspective::scaling_abs(double* x, double* y) const
  622. {
  623. *x = sqrt(sx * sx + shx * shx);
  624. *y = sqrt(shy * shy + sy * sy);
  625. }
  626. }
  627. #endif