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.
416     class trans_affine_rotation : public trans_affine
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
426     class trans_affine_scaling : public trans_affine
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
440     class trans_affine_translation : public trans_affine
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
450     class trans_affine_skewing : public trans_affine
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
462     class trans_affine_line_segment : public trans_affine
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
484     class trans_affine_reflection_unit : public trans_affine
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
501     class trans_affine_reflection : public trans_affine_reflection_unit
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 
519