Anti-Grain Geometry Tutorial
agg_trans_affine.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 // Affine transformation classes.
17 //
18 //----------------------------------------------------------------------------
19 #ifndef AGG_TRANS_AFFINE_INCLUDED
20 #define AGG_TRANS_AFFINE_INCLUDED
21 
22 #include <cmath>
23 #include "agg_basics.h"
24 
25 namespace agg
26 {
27  const double affine_epsilon = 1e-14;
28 
29  //============================================================trans_affine
30  //
31  // See Implementation agg_trans_affine.cpp
32  //
33  // Affine transformation are linear transformations in Cartesian coordinates
34  // (strictly speaking not only in Cartesian, but for the beginning we will
35  // think so). They are rotation, scaling, translation and skewing.
36  // After any affine transformation a line segment remains a line segment
37  // and it will never become a curve.
38  //
39  // There will be no math about matrix calculations, since it has been
40  // described many times. Ask yourself a very simple question:
41  // "why do we need to understand and use some matrix stuff instead of just
42  // rotating, scaling and so on". The answers are:
43  //
44  // 1. Any combination of transformations can be done by only 4 multiplications
45  // and 4 additions in floating point.
46  // 2. One matrix transformation is equivalent to the number of consecutive
47  // discrete transformations, i.e. the matrix "accumulates" all transformations
48  // in the order of their settings. Suppose we have 4 transformations:
49  // * rotate by 30 degrees,
50  // * scale X to 2.0,
51  // * scale Y to 1.5,
52  // * move to (100, 100).
53  // The result will depend on the order of these transformations,
54  // and the advantage of matrix is that the sequence of discret calls:
55  // rotate(30), scaleX(2.0), scaleY(1.5), move(100,100)
56  // will have exactly the same result as the following matrix transformations:
57  //
58  // affine_matrix m;
59  // m *= rotate_matrix(30);
60  // m *= scaleX_matrix(2.0);
61  // m *= scaleY_matrix(1.5);
62  // m *= move_matrix(100,100);
63  //
64  // m.transform_my_point_at_last(x, y);
65  //
66  // What is the good of it? In real life we will set-up the matrix only once
67  // and then transform many points, let alone the convenience to set any
68  // combination of transformations.
69  //
70  // So, how to use it? Very easy - literally as it's shown above. Not quite,
71  // let us write a correct example:
72  //
73  // agg::trans_affine m;
74  // m *= agg::trans_affine_rotation(30.0 * 3.1415926 / 180.0);
75  // m *= agg::trans_affine_scaling(2.0, 1.5);
76  // m *= agg::trans_affine_translation(100.0, 100.0);
77  // m.transform(&x, &y);
78  //
79  // The affine matrix is all you need to perform any linear transformation,
80  // but all transformations have origin point (0,0). It means that we need to
81  // use 2 translations if we want to rotate someting around (100,100):
82  //
83  // m *= agg::trans_affine_translation(-100.0, -100.0); // move to (0,0)
84  // m *= agg::trans_affine_rotation(30.0 * 3.1415926 / 180.0); // rotate
85  // m *= agg::trans_affine_translation(100.0, 100.0); // move back to (100,100)
86  //----------------------------------------------------------------------
87  struct trans_affine
88  {
89  double sx, shy, shx, sy, tx, ty;
90 
91  //------------------------------------------ Construction
92  // Identity matrix
93  trans_affine() :
94  sx(1.0), shy(0.0), shx(0.0), sy(1.0), tx(0.0), ty(0.0)
95  {}
96 
97  // Custom matrix. Usually used in derived classes
98  trans_affine(double v0, double v1, double v2,
99  double v3, double v4, double v5) :
100  sx(v0), shy(v1), shx(v2), sy(v3), tx(v4), ty(v5)
101  {}
102 
103  // Custom matrix from m[6]
104  explicit trans_affine(const double* m) :
105  sx(m[0]), shy(m[1]), shx(m[2]), sy(m[3]), tx(m[4]), ty(m[5])
106  {}
107 
108  // Rectangle to a parallelogram.
109  trans_affine(double x1, double y1, double x2, double y2,
110  const double* parl)
111  {
112  rect_to_parl(x1, y1, x2, y2, parl);
113  }
114 
115  // Parallelogram to a rectangle.
116  trans_affine(const double* parl,
117  double x1, double y1, double x2, double y2)
118  {
119  parl_to_rect(parl, x1, y1, x2, y2);
120  }
121 
122  // Arbitrary parallelogram transformation.
123  trans_affine(const double* src, const double* dst)
124  {
125  parl_to_parl(src, dst);
126  }
127 
128  //---------------------------------- Parellelogram transformations
129  // transform a parallelogram to another one. Src and dst are
130  // pointers to arrays of three points (double[6], x1,y1,...) that
131  // identify three corners of the parallelograms assuming implicit
132  // fourth point. The arguments are arrays of double[6] mapped
133  // to x1,y1, x2,y2, x3,y3 where the coordinates are:
134  // *-----------------*
135  // / (x3,y3)/
136  // / /
137  // /(x1,y1) (x2,y2)/
138  // *-----------------*
139  const trans_affine& parl_to_parl(const double* src,
140  const double* dst);
141 
142  const trans_affine& rect_to_parl(double x1, double y1,
143  double x2, double y2,
144  const double* parl);
145 
146  const trans_affine& parl_to_rect(const double* parl,
147  double x1, double y1,
148  double x2, double y2);
149 
150 
151  //------------------------------------------ Operations
152  // Reset - load an identity matrix
153  const trans_affine& reset();
154 
155  // Direct transformations operations
156  const trans_affine& translate(double x, double y);
157  const trans_affine& rotate(double a);
158  const trans_affine& scale(double s);
159  const trans_affine& scale(double x, double y);
160 
161  // Multiply matrix to another one
162  const trans_affine& multiply(const trans_affine& m);
163 
164  // Multiply "m" to "this" and assign the result to "this"
165  const trans_affine& premultiply(const trans_affine& m);
166 
167  // Multiply matrix to inverse of another one
168  const trans_affine& multiply_inv(const trans_affine& m);
169 
170  // Multiply inverse of "m" to "this" and assign the result to "this"
171  const trans_affine& premultiply_inv(const trans_affine& m);
172 
173  // Invert matrix. Do not try to invert degenerate matrices,
174  // there's no check for validity. If you set scale to 0 and
175  // then try to invert matrix, expect unpredictable result.
176  const trans_affine& invert();
177 
178  // Mirroring around X
179  const trans_affine& flip_x();
180 
181  // Mirroring around Y
182  const trans_affine& flip_y();
183 
184  //------------------------------------------- Load/Store
185  // Store matrix to an array [6] of double
186  void store_to(double* m) const
187  {
188  *m++ = sx; *m++ = shy; *m++ = shx; *m++ = sy; *m++ = tx; *m++ = ty;
189  }
190 
191  // Load matrix from an array [6] of double
192  const trans_affine& load_from(const double* m)
193  {
194  sx = *m++; shy = *m++; shx = *m++; sy = *m++; tx = *m++; ty = *m++;
195  return *this;
196  }
197 
198  //------------------------------------------- Operators
199 
200  // Multiply the matrix by another one
201  const trans_affine& operator *= (const trans_affine& m)
202  {
203  return multiply(m);
204  }
205 
206  // Multiply the matrix by inverse of another one
207  const trans_affine& operator /= (const trans_affine& m)
208  {
209  return multiply_inv(m);
210  }
211 
212  // Multiply the matrix by another one and return
213  // the result in a separete matrix.
214  trans_affine operator * (const trans_affine& m) const
215  {
216  return trans_affine(*this).multiply(m);
217  }
218 
219  // Multiply the matrix by inverse of another one
220  // and return the result in a separete matrix.
221  trans_affine operator / (const trans_affine& m) const
222  {
223  return trans_affine(*this).multiply_inv(m);
224  }
225 
226  // Calculate and return the inverse matrix
227  trans_affine operator ~ () const
228  {
229  trans_affine ret = *this;
230  return ret.invert();
231  }
232 
233  // Equal operator with default epsilon
234  bool operator == (const trans_affine& m) const
235  {
236  return is_equal(m, affine_epsilon);
237  }
238 
239  // Not Equal operator with default epsilon
240  bool operator != (const trans_affine& m) const
241  {
242  return !is_equal(m, affine_epsilon);
243  }
244 
245  //-------------------------------------------- Transformations
246  // Direct transformation of x and y
247  void transform(double* x, double* y) const;
248 
249  // Direct transformation of x and y, 2x2 matrix only, no translation
250  void transform_2x2(double* x, double* y) const;
251 
252  // Inverse transformation of x and y. It works slower than the
253  // direct transformation. For massive operations it's better to
254  // invert() the matrix and then use direct transformations.
255  void inverse_transform(double* x, double* y) const;
256 
257  //-------------------------------------------- Auxiliary
258  // Calculate the determinant of matrix
259  double determinant() const
260  {
261  return sx * sy - shy * shx;
262  }
263 
264  // Calculate the reciprocal of the determinant
265  double determinant_reciprocal() const
266  {
267  return 1.0 / (sx * sy - shy * shx);
268  }
269 
270  // Get the average scale (by X and Y).
271  // Basically used to calculate the approximation_scale when
272  // decomposinting curves into line segments.
273  double scale() const;
274 
275  // Check to see if the matrix is not degenerate
276  bool is_valid(double epsilon = affine_epsilon) const;
277 
278  // Check to see if it's an identity matrix
279  bool is_identity(double epsilon = affine_epsilon) const;
280 
281  // Check to see if two matrices are equal
282  bool is_equal(const trans_affine& m, double epsilon = affine_epsilon) const;
283 
284  // Determine the major parameters. Use with caution considering
285  // possible degenerate cases.
286  double rotation() const;
287  void translation(double* dx, double* dy) const;
288  void scaling(double* x, double* y) const;
289  void scaling_abs(double* x, double* y) const;
290  };
291 
292  //------------------------------------------------------------------------
293  inline void trans_affine::transform(double* x, double* y) const
294  {
295  double tmp = *x;
296  *x = tmp * sx + *y * shx + tx;
297  *y = tmp * shy + *y * sy + ty;
298  }
299 
300  //------------------------------------------------------------------------
301  inline void trans_affine::transform_2x2(double* x, double* y) const
302  {
303  double tmp = *x;
304  *x = tmp * sx + *y * shx;
305  *y = tmp * shy + *y * sy;
306  }
307 
308  //------------------------------------------------------------------------
309  inline void trans_affine::inverse_transform(double* x, double* y) const
310  {
311  double d = determinant_reciprocal();
312  double a = (*x - tx) * d;
313  double b = (*y - ty) * d;
314  *x = a * sy - b * shx;
315  *y = b * sx - a * shy;
316  }
317 
318  //------------------------------------------------------------------------
319  inline double trans_affine::scale() const
320  {
321  double x = 0.707106781 * sx + 0.707106781 * shx;
322  double y = 0.707106781 * shy + 0.707106781 * sy;
323  return std::sqrt(x*x + y*y);
324  }
325 
326  //------------------------------------------------------------------------
327  inline const trans_affine& trans_affine::translate(double x, double y)
328  {
329  tx += x;
330  ty += y;
331  return *this;
332  }
333 
334  //------------------------------------------------------------------------
335  inline const trans_affine& trans_affine::rotate(double a)
336  {
337  double ca = std::cos(a);
338  double sa = std::sin(a);
339  double t0 = sx * ca - shy * sa;
340  double t2 = shx * ca - sy * sa;
341  double t4 = tx * ca - ty * sa;
342  shy = sx * sa + shy * ca;
343  sy = shx * sa + sy * ca;
344  ty = tx * sa + ty * ca;
345  sx = t0;
346  shx = t2;
347  tx = t4;
348  return *this;
349  }
350 
351  //------------------------------------------------------------------------
352  inline const trans_affine& trans_affine::scale(double x, double y)
353  {
354  double mm0 = x; // Possible hint for the optimizer
355  double mm3 = y;
356  sx *= mm0;
357  shx *= mm0;
358  tx *= mm0;
359  shy *= mm3;
360  sy *= mm3;
361  ty *= mm3;
362  return *this;
363  }
364 
365  //------------------------------------------------------------------------
366  inline const trans_affine& trans_affine::scale(double s)
367  {
368  double m = s; // Possible hint for the optimizer
369  sx *= m;
370  shx *= m;
371  tx *= m;
372  shy *= m;
373  sy *= m;
374  ty *= m;
375  return *this;
376  }
377 
378  //------------------------------------------------------------------------
379  inline const trans_affine& trans_affine::premultiply(const trans_affine& m)
380  {
381  trans_affine t = m;
382  return *this = t.multiply(*this);
383  }
384 
385  //------------------------------------------------------------------------
386  inline const trans_affine& trans_affine::multiply_inv(const trans_affine& m)
387  {
388  trans_affine t = m;
389  t.invert();
390  return multiply(t);
391  }
392 
393  //------------------------------------------------------------------------
394  inline const trans_affine& trans_affine::premultiply_inv(const trans_affine& m)
395  {
396  trans_affine t = m;
397  t.invert();
398  return *this = t.multiply(*this);
399  }
400 
401  //------------------------------------------------------------------------
402  inline void trans_affine::scaling_abs(double* x, double* y) const
403  {
404  // Used to calculate scaling coefficients in image resampling.
405  // When there is considerable shear this method gives us much
406  // better estimation than just sx, sy.
407  *x = std::sqrt(sx * sx + shx * shx);
408  *y = std::sqrt(shy * shy + sy * sy);
409  }
410 
411  //====================================================trans_affine_rotation
412  // Rotation matrix. sin() and cos() are calculated twice for the same angle.
413  // There's no harm because the performance of sin()/cos() is very good on all
414  // modern processors. Besides, this operation is not going to be invoked too
415  // often.
417  {
418  public:
419  trans_affine_rotation(double a) :
420  trans_affine(std::cos(a), std::sin(a), -std::sin(a), std::cos(a), 0.0, 0.0)
421  {}
422  };
423 
424  //====================================================trans_affine_scaling
425  // Scaling matrix. x, y - scale coefficients by X and Y respectively
427  {
428  public:
429  trans_affine_scaling(double x, double y) :
430  trans_affine(x, 0.0, 0.0, y, 0.0, 0.0)
431  {}
432 
433  trans_affine_scaling(double s) :
434  trans_affine(s, 0.0, 0.0, s, 0.0, 0.0)
435  {}
436  };
437 
438  //================================================trans_affine_translation
439  // Translation matrix
441  {
442  public:
443  trans_affine_translation(double x, double y) :
444  trans_affine(1.0, 0.0, 0.0, 1.0, x, y)
445  {}
446  };
447 
448  //====================================================trans_affine_skewing
449  // Sckewing (shear) matrix
451  {
452  public:
453  trans_affine_skewing(double x, double y) :
454  trans_affine(1.0, std::tan(y), std::tan(x), 1.0, 0.0, 0.0)
455  {}
456  };
457 
458 
459  //===============================================trans_affine_line_segment
460  // Rotate, Scale and Translate, associating 0...dist with line segment
461  // x1,y1,x2,y2
463  {
464  public:
465  trans_affine_line_segment(double x1, double y1, double x2, double y2,
466  double dist)
467  {
468  double dx = x2 - x1;
469  double dy = y2 - y1;
470  if(dist > 0.0)
471  {
472  multiply(trans_affine_scaling(std::sqrt(dx * dx + dy * dy) / dist));
473  }
474  multiply(trans_affine_rotation(std::atan2(dy, dx)));
475  multiply(trans_affine_translation(x1, y1));
476  }
477  };
478 
479 
480  //============================================trans_affine_reflection_unit
481  // Reflection matrix. Reflect coordinates across the line through
482  // the origin containing the unit vector (ux, uy).
483  // Contributed by John Horigan
485  {
486  public:
487  trans_affine_reflection_unit(double ux, double uy) :
488  trans_affine(2.0 * ux * ux - 1.0,
489  2.0 * ux * uy,
490  2.0 * ux * uy,
491  2.0 * uy * uy - 1.0,
492  0.0, 0.0)
493  {}
494  };
495 
496 
497  //=================================================trans_affine_reflection
498  // Reflection matrix. Reflect coordinates across the line through
499  // the origin at the angle a or containing the non-unit vector (x, y).
500  // Contributed by John Horigan
502  {
503  public:
504  trans_affine_reflection(double a) :
505  trans_affine_reflection_unit(std::cos(a), std::sin(a))
506  {}
507 
508 
509  trans_affine_reflection(double x, double y) :
510  trans_affine_reflection_unit(x / std::sqrt(x * x + y * y), y / std::sqrt(x * x + y * y))
511  {}
512  };
513 
514 }
515 
516 
517 #endif
518 
Definition: agg_arc.cpp:24