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 transformations
17//
18//----------------------------------------------------------------------------
19#include "agg_trans_affine.h"
20
21
22
23namespace agg
24{
25
26    //------------------------------------------------------------------------
27    const trans_affine& trans_affine::parl_to_parl(const double* src,
28                                                   const double* dst)
29    {
30        sx  = src[2] - src[0];
31        shy = src[3] - src[1];
32        shx = src[4] - src[0];
33        sy  = src[5] - src[1];
34        tx  = src[0];
35        ty  = src[1];
36        invert();
37        multiply(trans_affine(dst[2] - dst[0], dst[3] - dst[1],
38                              dst[4] - dst[0], dst[5] - dst[1],
39                              dst[0], dst[1]));
40        return *this;
41    }
42
43    //------------------------------------------------------------------------
44    const trans_affine& trans_affine::rect_to_parl(double x1, double y1,
45                                                   double x2, double y2,
46                                                   const double* parl)
47    {
48        double src[6];
49        src[0] = x1; src[1] = y1;
50        src[2] = x2; src[3] = y1;
51        src[4] = x2; src[5] = y2;
52        parl_to_parl(src, parl);
53        return *this;
54    }
55
56    //------------------------------------------------------------------------
57    const trans_affine& trans_affine::parl_to_rect(const double* parl,
58                                                   double x1, double y1,
59                                                   double x2, double y2)
60    {
61        double dst[6];
62        dst[0] = x1; dst[1] = y1;
63        dst[2] = x2; dst[3] = y1;
64        dst[4] = x2; dst[5] = y2;
65        parl_to_parl(parl, dst);
66        return *this;
67    }
68
69    //------------------------------------------------------------------------
70    const trans_affine& trans_affine::multiply(const trans_affine& m)
71    {
72        double t0 = sx  * m.sx + shy * m.shx;
73        double t2 = shx * m.sx + sy  * m.shx;
74        double t4 = tx  * m.sx + ty  * m.shx + m.tx;
75        shy = sx  * m.shy + shy * m.sy;
76        sy  = shx * m.shy + sy  * m.sy;
77        ty  = tx  * m.shy + ty  * m.sy + m.ty;
78        sx  = t0;
79        shx = t2;
80        tx  = t4;
81        return *this;
82    }
83
84
85    //------------------------------------------------------------------------
86    const trans_affine& trans_affine::invert()
87    {
88        double d  = determinant_reciprocal();
89
90        double t0  =  sy  * d;
91               sy  =  sx  * d;
92               shy = -shy * d;
93               shx = -shx * d;
94
95        double t4 = -tx * t0  - ty * shx;
96               ty = -tx * shy - ty * sy;
97
98        sx = t0;
99        tx = t4;
100        return *this;
101    }
102
103
104   //------------------------------------------------------------------------
105    const trans_affine& trans_affine::flip_x()
106    {
107        sx  = -sx;
108        shy = -shy;
109        tx  = -tx;
110        return *this;
111    }
112
113    //------------------------------------------------------------------------
114    const trans_affine& trans_affine::flip_y()
115    {
116        shx = -shx;
117        sy  = -sy;
118        ty  = -ty;
119        return *this;
120    }
121
122    //------------------------------------------------------------------------
123    const trans_affine& trans_affine::reset()
124    {
125        sx  = sy  = 1.0;
126        shy = shx = tx = ty = 0.0;
127        return *this;
128    }
129
130    //------------------------------------------------------------------------
131    bool trans_affine::is_identity(double epsilon) const
132    {
133        return is_equal_eps(sx,  1.0, epsilon) &&
134               is_equal_eps(shy, 0.0, epsilon) &&
135               is_equal_eps(shx, 0.0, epsilon) &&
136               is_equal_eps(sy,  1.0, epsilon) &&
137               is_equal_eps(tx,  0.0, epsilon) &&
138               is_equal_eps(ty,  0.0, epsilon);
139    }
140
141    //------------------------------------------------------------------------
142    bool trans_affine::is_valid(double epsilon) const
143    {
144        return std::fabs(sx) > epsilon && std::fabs(sy) > epsilon;
145    }
146
147    //------------------------------------------------------------------------
148    bool trans_affine::is_equal(const trans_affine& m, double epsilon) const
149    {
150        return is_equal_eps(sx,  m.sx,  epsilon) &&
151               is_equal_eps(shy, m.shy, epsilon) &&
152               is_equal_eps(shx, m.shx, epsilon) &&
153               is_equal_eps(sy,  m.sy,  epsilon) &&
154               is_equal_eps(tx,  m.tx,  epsilon) &&
155               is_equal_eps(ty,  m.ty,  epsilon);
156    }
157
158    //------------------------------------------------------------------------
159    double trans_affine::rotation() const
160    {
161        double x1 = 0.0;
162        double y1 = 0.0;
163        double x2 = 1.0;
164        double y2 = 0.0;
165        transform(&x1, &y1);
166        transform(&x2, &y2);
167        return std::atan2(y2-y1, x2-x1);
168    }
169
170    //------------------------------------------------------------------------
171    void trans_affine::translation(double* dx, double* dy) const
172    {
173        *dx = tx;
174        *dy = ty;
175    }
176
177    //------------------------------------------------------------------------
178    void trans_affine::scaling(double* x, double* y) const
179    {
180        double x1 = 0.0;
181        double y1 = 0.0;
182        double x2 = 1.0;
183        double y2 = 1.0;
184        trans_affine t(*this);
185        t *= trans_affine_rotation(-rotation());
186        t.transform(&x1, &y1);
187        t.transform(&x2, &y2);
188        *x = x2 - x1;
189        *y = y2 - y1;
190    }
191
192
193}
194
195