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
25namespace 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 = M_SQRT1_2 * sx  + M_SQRT1_2 * shx;
322        double y = M_SQRT1_2 * shy + M_SQRT1_2 * 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