Anti-Grain Geometry Tutorial
agg_trans_perspective.h
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 
22 #include <cmath>
23 #include "agg_trans_affine.h"
24 
25 namespace agg
26 {
27  //=======================================================trans_perspective
29  {
30  double sx, shy, w0, shx, sy, w1, tx, ty, w2;
31 
32  //------------------------------------------------------- Construction
33  // Identity matrix
35  sx (1), shy(0), w0(0),
36  shx(0), sy (1), w1(0),
37  tx (0), ty (0), w2(1) {}
38 
39  // Custom matrix
40  trans_perspective(double v0, double v1, double v2,
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) {}
46 
47  // Custom matrix from m[9]
48  explicit trans_perspective(const double* m) :
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]) {}
52 
53  // From affine
54  explicit trans_perspective(const trans_affine& a) :
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) {}
58 
59  // Rectangle to quadrilateral
60  trans_perspective(double x1, double y1, double x2, double y2,
61  const double* quad);
62 
63  // Quadrilateral to rectangle
64  trans_perspective(const double* quad,
65  double x1, double y1, double x2, double y2);
66 
67  // Arbitrary quadrilateral transformations
68  trans_perspective(const double* src, const double* dst);
69 
70  //-------------------------------------- Quadrilateral transformations
71  // The arguments are double[8] that are mapped to quadrilaterals:
72  // x1,y1, x2,y2, x3,y3, x4,y4
73  bool quad_to_quad(const double* qs, const double* qd);
74 
75  bool rect_to_quad(double x1, double y1,
76  double x2, double y2,
77  const double* q);
78 
79  bool quad_to_rect(const double* q,
80  double x1, double y1,
81  double x2, double y2);
82 
83  // Map square (0,0,1,1) to the quadrilateral and vice versa
84  bool square_to_quad(const double* q);
85  bool quad_to_square(const double* q);
86 
87 
88  //--------------------------------------------------------- Operations
89  // Reset - load an identity matrix
90  const trans_perspective& reset();
91 
92  // Invert matrix. Returns false in degenerate case
93  bool invert();
94 
95  // Direct transformations operations
96  const trans_perspective& translate(double x, double y);
97  const trans_perspective& rotate(double a);
98  const trans_perspective& scale(double s);
99  const trans_perspective& scale(double x, double y);
100 
101  // Multiply the matrix by another one
102  const trans_perspective& multiply(const trans_perspective& m);
103 
104  // Multiply "m" by "this" and assign the result to "this"
105  const trans_perspective& premultiply(const trans_perspective& m);
106 
107  // Multiply matrix to inverse of another one
108  const trans_perspective& multiply_inv(const trans_perspective& m);
109 
110  // Multiply inverse of "m" by "this" and assign the result to "this"
111  const trans_perspective& premultiply_inv(const trans_perspective& m);
112 
113  // Multiply the matrix by another one
114  const trans_perspective& multiply(const trans_affine& m);
115 
116  // Multiply "m" by "this" and assign the result to "this"
117  const trans_perspective& premultiply(const trans_affine& m);
118 
119  // Multiply the matrix by inverse of another one
120  const trans_perspective& multiply_inv(const trans_affine& m);
121 
122  // Multiply inverse of "m" by "this" and assign the result to "this"
123  const trans_perspective& premultiply_inv(const trans_affine& m);
124 
125  //--------------------------------------------------------- Load/Store
126  void store_to(double* m) const;
127  const trans_perspective& load_from(const double* m);
128 
129  //---------------------------------------------------------- Operators
130  // Multiply the matrix by another one
131  const trans_perspective& operator *= (const trans_perspective& m)
132  {
133  return multiply(m);
134  }
135  const trans_perspective& operator *= (const trans_affine& m)
136  {
137  return multiply(m);
138  }
139 
140  // Multiply the matrix by inverse of another one
141  const trans_perspective& operator /= (const trans_perspective& m)
142  {
143  return multiply_inv(m);
144  }
145  const trans_perspective& operator /= (const trans_affine& m)
146  {
147  return multiply_inv(m);
148  }
149 
150  // Multiply the matrix by another one and return
151  // the result in a separete matrix.
152  trans_perspective operator * (const trans_perspective& m) const
153  {
154  return trans_perspective(*this).multiply(m);
155  }
156  trans_perspective operator * (const trans_affine& m) const
157  {
158  return trans_perspective(*this).multiply(m);
159  }
160 
161  // Multiply the matrix by inverse of another one
162  // and return the result in a separete matrix.
163  trans_perspective operator / (const trans_perspective& m) const
164  {
165  return trans_perspective(*this).multiply_inv(m);
166  }
167  trans_perspective operator / (const trans_affine& m) const
168  {
169  return trans_perspective(*this).multiply_inv(m);
170  }
171 
172  // Calculate and return the inverse matrix
173  trans_perspective operator ~ () const
174  {
175  trans_perspective ret = *this;
176  ret.invert();
177  return ret;
178  }
179 
180  // Equal operator with default epsilon
181  bool operator == (const trans_perspective& m) const
182  {
183  return is_equal(m, affine_epsilon);
184  }
185 
186  // Not Equal operator with default epsilon
187  bool operator != (const trans_perspective& m) const
188  {
189  return !is_equal(m, affine_epsilon);
190  }
191 
192  //---------------------------------------------------- Transformations
193  // Direct transformation of x and y
194  void transform(double* x, double* y) const;
195 
196  // Direct transformation of x and y, affine part only
197  void transform_affine(double* x, double* y) const;
198 
199  // Direct transformation of x and y, 2x2 matrix only, no translation
200  void transform_2x2(double* x, double* y) const;
201 
202  // Inverse transformation of x and y. It works slow because
203  // it explicitly inverts the matrix on every call. For massive
204  // operations it's better to invert() the matrix and then use
205  // direct transformations.
206  void inverse_transform(double* x, double* y) const;
207 
208 
209  //---------------------------------------------------------- Auxiliary
210  const trans_perspective& from_affine(const trans_affine& a);
211  double determinant() const;
212  double determinant_reciprocal() const;
213 
214  bool is_valid(double epsilon = affine_epsilon) const;
215  bool is_identity(double epsilon = affine_epsilon) const;
216  bool is_equal(const trans_perspective& m,
217  double epsilon = affine_epsilon) const;
218 
219  // Determine the major affine parameters. Use with caution
220  // considering possible degenerate cases.
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;
226 
227 
228 
229  //--------------------------------------------------------------------
231  {
232  double den;
233  double den_step;
234  double nom_x;
235  double nom_x_step;
236  double nom_y;
237  double nom_y_step;
238 
239  public:
240  double x;
241  double y;
242 
243  iterator_x() {}
244  iterator_x(double px, double py, double step, const trans_perspective& m) :
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),
251  x(nom_x / den),
252  y(nom_y / den)
253  {}
254 
255  void operator ++ ()
256  {
257  den += den_step;
258  nom_x += nom_x_step;
259  nom_y += nom_y_step;
260  double d = 1.0 / den;
261  x = nom_x * d;
262  y = nom_y * d;
263  }
264  };
265 
266  //--------------------------------------------------------------------
267  iterator_x begin(double x, double y, double step) const
268  {
269  return iterator_x(x, y, step, *this);
270  }
271  };
272 
273 
274 
275 
276 
277 
278 
279 
280 
281 
282 
283 
284 
285 
286  //------------------------------------------------------------------------
287  inline bool trans_perspective::square_to_quad(const double* q)
288  {
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)
292  {
293  // Affine case (parallelogram)
294  //---------------
295  sx = q[2] - q[0];
296  shy = q[3] - q[1];
297  w0 = 0.0;
298  shx = q[4] - q[2];
299  sy = q[5] - q[3];
300  w1 = 0.0;
301  tx = q[0];
302  ty = q[1];
303  w2 = 1.0;
304  }
305  else
306  {
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;
312  if(den == 0.0)
313  {
314  // Singular case
315  //---------------
316  sx = shy = w0 = shx = sy = w1 = tx = ty = w2 = 0.0;
317  return false;
318  }
319  // General case
320  //---------------
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];
325  w0 = u;
326  shx = q[6] - q[0] + v * q[6];
327  sy = q[7] - q[1] + v * q[7];
328  w1 = v;
329  tx = q[0];
330  ty = q[1];
331  w2 = 1.0;
332  }
333  return true;
334  }
335 
336  //------------------------------------------------------------------------
337  inline bool trans_perspective::invert()
338  {
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;
343  if(d == 0.0)
344  {
345  sx = shy = w0 = shx = sy = w1 = tx = ty = w2 = 0.0;
346  return false;
347  }
348  d = 1.0 / d;
349  trans_perspective a = *this;
350  sx = d * d0;
351  shy = d * d1;
352  w0 = d * d2;
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);
359  return true;
360  }
361 
362  //------------------------------------------------------------------------
363  inline bool trans_perspective::quad_to_square(const double* q)
364  {
365  if(!square_to_quad(q)) return false;
366  invert();
367  return true;
368  }
369 
370  //------------------------------------------------------------------------
371  inline bool trans_perspective::quad_to_quad(const double* qs,
372  const double* qd)
373  {
375  if(! quad_to_square(qs)) return false;
376  if(!p.square_to_quad(qd)) return false;
377  multiply(p);
378  return true;
379  }
380 
381  //------------------------------------------------------------------------
382  inline bool trans_perspective::rect_to_quad(double x1, double y1,
383  double x2, double y2,
384  const double* q)
385  {
386  double r[8];
387  r[0] = r[6] = x1;
388  r[2] = r[4] = x2;
389  r[1] = r[3] = y1;
390  r[5] = r[7] = y2;
391  return quad_to_quad(r, q);
392  }
393 
394  //------------------------------------------------------------------------
395  inline bool trans_perspective::quad_to_rect(const double* q,
396  double x1, double y1,
397  double x2, double y2)
398  {
399  double r[8];
400  r[0] = r[6] = x1;
401  r[2] = r[4] = x2;
402  r[1] = r[3] = y1;
403  r[5] = r[7] = y2;
404  return quad_to_quad(q, r);
405  }
406 
407  //------------------------------------------------------------------------
408  inline trans_perspective::trans_perspective(double x1, double y1,
409  double x2, double y2,
410  const double* quad)
411  {
412  rect_to_quad(x1, y1, x2, y2, quad);
413  }
414 
415  //------------------------------------------------------------------------
416  inline trans_perspective::trans_perspective(const double* quad,
417  double x1, double y1,
418  double x2, double y2)
419  {
420  quad_to_rect(quad, x1, y1, x2, y2);
421  }
422 
423  //------------------------------------------------------------------------
424  inline trans_perspective::trans_perspective(const double* src,
425  const double* dst)
426  {
427  quad_to_quad(src, dst);
428  }
429 
430  //------------------------------------------------------------------------
431  inline const trans_perspective& trans_perspective::reset()
432  {
433  sx = 1; shy = 0; w0 = 0;
434  shx = 0; sy = 1; w1 = 0;
435  tx = 0; ty = 0; w2 = 1;
436  return *this;
437  }
438 
439  //------------------------------------------------------------------------
440  inline const trans_perspective&
441  trans_perspective::multiply(const trans_perspective& a)
442  {
443  trans_perspective b = *this;
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;
453  return *this;
454  }
455 
456  //------------------------------------------------------------------------
457  inline const trans_perspective&
458  trans_perspective::multiply(const trans_affine& a)
459  {
460  trans_perspective b = *this;
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;
467  return *this;
468  }
469 
470  //------------------------------------------------------------------------
471  inline const trans_perspective&
472  trans_perspective::premultiply(const trans_perspective& b)
473  {
474  trans_perspective a = *this;
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;
484  return *this;
485  }
486 
487  //------------------------------------------------------------------------
488  inline const trans_perspective&
489  trans_perspective::premultiply(const trans_affine& b)
490  {
491  trans_perspective a = *this;
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;
501  return *this;
502  }
503 
504  //------------------------------------------------------------------------
505  const trans_perspective&
506  trans_perspective::multiply_inv(const trans_perspective& m)
507  {
508  trans_perspective t = m;
509  t.invert();
510  return multiply(t);
511  }
512 
513  //------------------------------------------------------------------------
514  const trans_perspective&
515  trans_perspective::multiply_inv(const trans_affine& m)
516  {
517  trans_affine t = m;
518  t.invert();
519  return multiply(t);
520  }
521 
522  //------------------------------------------------------------------------
523  const trans_perspective&
524  trans_perspective::premultiply_inv(const trans_perspective& m)
525  {
526  trans_perspective t = m;
527  t.invert();
528  return *this = t.multiply(*this);
529  }
530 
531  //------------------------------------------------------------------------
532  const trans_perspective&
533  trans_perspective::premultiply_inv(const trans_affine& m)
534  {
535  trans_perspective t(m);
536  t.invert();
537  return *this = t.multiply(*this);
538  }
539 
540  //------------------------------------------------------------------------
541  inline const trans_perspective&
542  trans_perspective::translate(double x, double y)
543  {
544  tx += x;
545  ty += y;
546  return *this;
547  }
548 
549  //------------------------------------------------------------------------
550  inline const trans_perspective& trans_perspective::rotate(double a)
551  {
552  multiply(trans_affine_rotation(a));
553  return *this;
554  }
555 
556  //------------------------------------------------------------------------
557  inline const trans_perspective& trans_perspective::scale(double s)
558  {
559  multiply(trans_affine_scaling(s));
560  return *this;
561  }
562 
563  //------------------------------------------------------------------------
564  inline const trans_perspective& trans_perspective::scale(double x, double y)
565  {
566  multiply(trans_affine_scaling(x, y));
567  return *this;
568  }
569 
570  //------------------------------------------------------------------------
571  inline void trans_perspective::transform(double* px, double* py) const
572  {
573  double x = *px;
574  double y = *py;
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);
578  }
579 
580  //------------------------------------------------------------------------
581  inline void trans_perspective::transform_affine(double* x, double* y) const
582  {
583  double tmp = *x;
584  *x = tmp * sx + *y * shx + tx;
585  *y = tmp * shy + *y * sy + ty;
586  }
587 
588  //------------------------------------------------------------------------
589  inline void trans_perspective::transform_2x2(double* x, double* y) const
590  {
591  double tmp = *x;
592  *x = tmp * sx + *y * shx;
593  *y = tmp * shy + *y * sy;
594  }
595 
596  //------------------------------------------------------------------------
597  inline void trans_perspective::inverse_transform(double* x, double* y) const
598  {
599  trans_perspective t(*this);
600  if(t.invert()) t.transform(x, y);
601  }
602 
603  //------------------------------------------------------------------------
604  inline void trans_perspective::store_to(double* m) const
605  {
606  *m++ = sx; *m++ = shy; *m++ = w0;
607  *m++ = shx; *m++ = sy; *m++ = w1;
608  *m++ = tx; *m++ = ty; *m++ = w2;
609  }
610 
611  //------------------------------------------------------------------------
612  inline const trans_perspective& trans_perspective::load_from(const double* m)
613  {
614  sx = *m++; shy = *m++; w0 = *m++;
615  shx = *m++; sy = *m++; w1 = *m++;
616  tx = *m++; ty = *m++; w2 = *m++;
617  return *this;
618  }
619 
620  //------------------------------------------------------------------------
621  inline const trans_perspective&
622  trans_perspective::from_affine(const trans_affine& a)
623  {
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;
627  return *this;
628  }
629 
630  //------------------------------------------------------------------------
631  inline double trans_perspective::determinant() const
632  {
633  return sx * (sy * w2 - ty * w1) +
634  shx * (ty * w0 - shy * w2) +
635  tx * (shy * w1 - sy * w0);
636  }
637 
638  //------------------------------------------------------------------------
639  inline double trans_perspective::determinant_reciprocal() const
640  {
641  return 1.0 / determinant();
642  }
643 
644  //------------------------------------------------------------------------
645  inline bool trans_perspective::is_valid(double epsilon) const
646  {
647  return std::fabs(sx) > epsilon && std::fabs(sy) > epsilon && std::fabs(w2) > epsilon;
648  }
649 
650  //------------------------------------------------------------------------
651  inline bool trans_perspective::is_identity(double epsilon) const
652  {
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);
662  }
663 
664  //------------------------------------------------------------------------
665  inline bool trans_perspective::is_equal(const trans_perspective& m,
666  double epsilon) const
667  {
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);
677  }
678 
679  //------------------------------------------------------------------------
680  inline double trans_perspective::scale() const
681  {
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);
685  }
686 
687  //------------------------------------------------------------------------
688  inline double trans_perspective::rotation() const
689  {
690  double x1 = 0.0;
691  double y1 = 0.0;
692  double x2 = 1.0;
693  double y2 = 0.0;
694  transform(&x1, &y1);
695  transform(&x2, &y2);
696  return std::atan2(y2-y1, x2-x1);
697  }
698 
699  //------------------------------------------------------------------------
700  void trans_perspective::translation(double* dx, double* dy) const
701  {
702  *dx = tx;
703  *dy = ty;
704  }
705 
706  //------------------------------------------------------------------------
707  void trans_perspective::scaling(double* x, double* y) const
708  {
709  double x1 = 0.0;
710  double y1 = 0.0;
711  double x2 = 1.0;
712  double y2 = 1.0;
713  trans_perspective t(*this);
714  t *= trans_affine_rotation(-rotation());
715  t.transform(&x1, &y1);
716  t.transform(&x2, &y2);
717  *x = x2 - x1;
718  *y = y2 - y1;
719  }
720 
721  //------------------------------------------------------------------------
722  void trans_perspective::scaling_abs(double* x, double* y) const
723  {
724  *x = std::sqrt(sx * sx + shx * shx);
725  *y = std::sqrt(shy * shy + sy * sy);
726  }
727 
728 
729 }
730 
731 #endif
732 
Definition: agg_arc.cpp:24