xref: /haiku/src/libs/agg/src/agg_trans_affine.cpp (revision a1c86e7ada868534162e52dae3a1f8a87549d7d4)
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 
23 namespace agg
24 {
25 
26     //------------------------------------------------------------------------
parl_to_parl(const double * src,const double * dst)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     //------------------------------------------------------------------------
rect_to_parl(double x1,double y1,double x2,double y2,const double * parl)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     //------------------------------------------------------------------------
parl_to_rect(const double * parl,double x1,double y1,double x2,double y2)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     //------------------------------------------------------------------------
multiply(const trans_affine & m)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     //------------------------------------------------------------------------
invert()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    //------------------------------------------------------------------------
flip_x()105     const trans_affine& trans_affine::flip_x()
106     {
107         sx  = -sx;
108         shy = -shy;
109         tx  = -tx;
110         return *this;
111     }
112 
113     //------------------------------------------------------------------------
flip_y()114     const trans_affine& trans_affine::flip_y()
115     {
116         shx = -shx;
117         sy  = -sy;
118         ty  = -ty;
119         return *this;
120     }
121 
122     //------------------------------------------------------------------------
reset()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     //------------------------------------------------------------------------
is_identity(double epsilon) const131     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     //------------------------------------------------------------------------
is_valid(double epsilon) const142     bool trans_affine::is_valid(double epsilon) const
143     {
144         return std::fabs(sx) > epsilon && std::fabs(sy) > epsilon;
145     }
146 
147     //------------------------------------------------------------------------
is_equal(const trans_affine & m,double epsilon) const148     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     //------------------------------------------------------------------------
rotation() const159     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     //------------------------------------------------------------------------
translation(double * dx,double * dy) const171     void trans_affine::translation(double* dx, double* dy) const
172     {
173         *dx = tx;
174         *dy = ty;
175     }
176 
177     //------------------------------------------------------------------------
scaling(double * x,double * y) const178     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