merge the formfield patch from ooo-build
[ooovba.git] / agg / source / agg_trans_affine.cpp
blob907f44dd0e8b82d5fd8a18daa55ce655bea8e5b4
1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.3
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 //----------------------------------------------------------------------------
16 // Affine transformations
18 //----------------------------------------------------------------------------
19 #include "agg_trans_affine.h"
23 namespace agg
26 //------------------------------------------------------------------------
27 const trans_affine& trans_affine::parl_to_parl(const double* src,
28 const double* dst)
30 m0 = src[2] - src[0];
31 m1 = src[3] - src[1];
32 m2 = src[4] - src[0];
33 m3 = src[5] - src[1];
34 m4 = src[0];
35 m5 = 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;
43 //------------------------------------------------------------------------
44 const trans_affine& trans_affine::rect_to_parl(double x1, double y1,
45 double x2, double y2,
46 const double* parl)
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;
56 //------------------------------------------------------------------------
57 const trans_affine& trans_affine::parl_to_rect(const double* parl,
58 double x1, double y1,
59 double x2, double y2)
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;
69 //------------------------------------------------------------------------
70 const trans_affine& trans_affine::multiply(const trans_affine& m)
72 double t0 = m0 * m.m0 + m1 * m.m2;
73 double t2 = m2 * m.m0 + m3 * m.m2;
74 double t4 = m4 * m.m0 + m5 * m.m2 + m.m4;
75 m1 = m0 * m.m1 + m1 * m.m3;
76 m3 = m2 * m.m1 + m3 * m.m3;
77 m5 = m4 * m.m1 + m5 * m.m3 + m.m5;
78 m0 = t0;
79 m2 = t2;
80 m4 = t4;
81 return *this;
85 //------------------------------------------------------------------------
86 const trans_affine& trans_affine::invert()
88 double d = determinant();
90 double t0 = m3 * d;
91 m3 = m0 * d;
92 m1 = -m1 * d;
93 m2 = -m2 * d;
95 double t4 = -m4 * t0 - m5 * m2;
96 m5 = -m4 * m1 - m5 * m3;
98 m0 = t0;
99 m4 = t4;
100 return *this;
104 //------------------------------------------------------------------------
105 const trans_affine& trans_affine::flip_x()
107 m0 = -m0;
108 m1 = -m1;
109 m4 = -m4;
110 return *this;
113 //------------------------------------------------------------------------
114 const trans_affine& trans_affine::flip_y()
116 m2 = -m2;
117 m3 = -m3;
118 m5 = -m5;
119 return *this;
122 //------------------------------------------------------------------------
123 const trans_affine& trans_affine::reset()
125 m0 = m3 = 1.0;
126 m1 = m2 = m4 = m5 = 0.0;
127 return *this;
130 //------------------------------------------------------------------------
131 inline bool is_equal_eps(double v1, double v2, double epsilon)
133 return fabs(v1 - v2) < epsilon;
136 //------------------------------------------------------------------------
137 bool trans_affine::is_identity(double epsilon) const
139 return is_equal_eps(m0, 1.0, epsilon) &&
140 is_equal_eps(m1, 0.0, epsilon) &&
141 is_equal_eps(m2, 0.0, epsilon) &&
142 is_equal_eps(m3, 1.0, epsilon) &&
143 is_equal_eps(m4, 0.0, epsilon) &&
144 is_equal_eps(m5, 0.0, epsilon);
147 //------------------------------------------------------------------------
148 bool trans_affine::is_equal(const trans_affine& m, double epsilon) const
150 return is_equal_eps(m0, m.m0, epsilon) &&
151 is_equal_eps(m1, m.m1, epsilon) &&
152 is_equal_eps(m2, m.m2, epsilon) &&
153 is_equal_eps(m3, m.m3, epsilon) &&
154 is_equal_eps(m4, m.m4, epsilon) &&
155 is_equal_eps(m5, m.m5, epsilon);
158 //------------------------------------------------------------------------
159 double trans_affine::rotation() const
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 atan2(y2-y1, x2-x1);
170 //------------------------------------------------------------------------
171 void trans_affine::translation(double* dx, double* dy) const
173 trans_affine t(*this);
174 t *= trans_affine_rotation(-rotation());
175 t.transform(dx, dy);
178 //------------------------------------------------------------------------
179 void trans_affine::scaling(double* sx, double* sy) const
181 double x1 = 0.0;
182 double y1 = 0.0;
183 double x2 = 1.0;
184 double y2 = 1.0;
185 trans_affine t(*this);
186 t *= trans_affine_rotation(-rotation());
187 t.transform(&x1, &y1);
188 t.transform(&x2, &y2);
189 *sx = x2 - x1;
190 *sy = y2 - y1;