]> git.saurik.com Git - wxWidgets.git/blob - src/common/matrix.cpp
Added chapter on collection and container classes to contents
[wxWidgets.git] / src / common / matrix.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: matrix.cpp
3 // Purpose: wxTransformMatrix class
4 // Author: Chris Breeze, Julian Smart
5 // Modified by:
6 // Created: 01/02/97
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "matrix.h"
14 #endif
15
16 // Note: this is intended to be used in wxDC at some point to replace
17 // the current system of scaling/translation. It is not yet used.
18
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
21
22 #ifdef __BORLANDC__
23 #pragma hdrstop
24 #endif
25
26 #ifndef WX_PRECOMP
27 #include "wx/defs.h"
28 #endif
29
30 #include "wx/matrix.h"
31 #include <math.h>
32
33 const double pi = 3.1415926535;
34
35 wxTransformMatrix::wxTransformMatrix(void)
36 {
37 m_isIdentity = FALSE;
38
39 Identity();
40 }
41
42 wxTransformMatrix::wxTransformMatrix(const wxTransformMatrix& mat)
43 {
44 (*this) = mat;
45 }
46
47 double wxTransformMatrix::GetValue(int row, int col) const
48 {
49 if (row < 0 || row > 2 || col < 0 || col > 2)
50 return 0.0;
51
52 return m_matrix[row][col];
53 }
54
55 void wxTransformMatrix::SetValue(int row, int col, double value)
56 {
57 if (row < 0 || row > 2 || col < 0 || col > 2)
58 return;
59
60 m_matrix[row][col] = value;
61 }
62
63 void wxTransformMatrix::operator = (const wxTransformMatrix& mat)
64 {
65 int i, j;
66 for (i = 0; i < 3; i++)
67 {
68 for (j = 0; j < 3; j++)
69 {
70 m_matrix[i][j] = mat.m_matrix[i][j];
71 }
72 }
73 m_isIdentity = mat.m_isIdentity;
74 }
75
76 bool wxTransformMatrix::operator == (const wxTransformMatrix& mat)
77 {
78 int i, j;
79 for (i = 0; i < 3; i++)
80 {
81 for (j = 0; j < 3; j++)
82 {
83 if (m_matrix[i][j] != mat.m_matrix[i][j])
84 return FALSE;
85 }
86 }
87 return TRUE;
88 }
89
90 bool wxTransformMatrix::operator != (const wxTransformMatrix& mat)
91 {
92 return (! ((*this) == mat));
93 }
94
95 double& wxTransformMatrix::operator()(int row, int col)
96 {
97 if (row < 0 || row > 2 || col < 0 || col > 2)
98 return m_matrix[0][0];
99
100 return m_matrix[row][col];
101 }
102
103 double wxTransformMatrix::operator()(int row, int col) const
104 {
105 if (row < 0 || row > 2 || col < 0 || col > 2)
106 return 0.0;
107
108 return m_matrix[row][col];
109 }
110
111 // Invert matrix
112 bool wxTransformMatrix::Invert(void)
113 {
114 double inverseMatrix[3][3];
115
116 // calculate the adjoint
117 inverseMatrix[0][0] = wxCalculateDet(m_matrix[1][1],m_matrix[2][1],m_matrix[1][2],m_matrix[2][2]);
118 inverseMatrix[0][1] = -wxCalculateDet(m_matrix[0][1],m_matrix[2][1],m_matrix[0][2],m_matrix[2][2]);
119 inverseMatrix[0][2] = wxCalculateDet(m_matrix[0][1],m_matrix[1][1],m_matrix[0][2],m_matrix[1][2]);
120
121 inverseMatrix[1][0] = -wxCalculateDet(m_matrix[1][0],m_matrix[2][0],m_matrix[1][2],m_matrix[2][2]);
122 inverseMatrix[1][1] = wxCalculateDet(m_matrix[0][0],m_matrix[2][0],m_matrix[0][2],m_matrix[2][2]);
123 inverseMatrix[1][2] = -wxCalculateDet(m_matrix[0][0],m_matrix[1][0],m_matrix[0][2],m_matrix[1][2]);
124
125 inverseMatrix[2][0] = wxCalculateDet(m_matrix[1][0],m_matrix[2][0],m_matrix[1][1],m_matrix[2][1]);
126 inverseMatrix[2][1] = -wxCalculateDet(m_matrix[0][0],m_matrix[2][0],m_matrix[0][1],m_matrix[2][1]);
127 inverseMatrix[2][2] = wxCalculateDet(m_matrix[0][0],m_matrix[1][0],m_matrix[0][1],m_matrix[1][1]);
128
129 // now divide by the determinant
130 double det = m_matrix[0][0] * inverseMatrix[0][0] + m_matrix[0][1] * inverseMatrix[1][0] + m_matrix[0][2] * inverseMatrix[2][0];
131 if (det != 0.0)
132 {
133 inverseMatrix[0][0] /= det; inverseMatrix[1][0] /= det; inverseMatrix[2][0] /= det;
134 inverseMatrix[0][1] /= det; inverseMatrix[1][1] /= det; inverseMatrix[2][1] /= det;
135 inverseMatrix[0][2] /= det; inverseMatrix[1][2] /= det; inverseMatrix[2][2] /= det;
136
137 int i, j;
138 for (i = 0; i < 3; i++)
139 {
140 for (j = 0; j < 3; j++)
141 {
142 m_matrix[i][j] = inverseMatrix[i][j];
143 }
144 }
145 m_isIdentity = IsIdentity1();
146 return TRUE;
147 }
148 else
149 {
150 return FALSE;
151 }
152 }
153
154 // Make into identity matrix
155 bool wxTransformMatrix::Identity(void)
156 {
157 m_matrix[0][0] = m_matrix[1][1] = m_matrix[2][2] = 1.0;
158 m_matrix[1][0] = m_matrix[2][0] = m_matrix[0][1] = m_matrix[2][1] = m_matrix[0][2] = m_matrix[1][2] = 0.0;
159 m_isIdentity = TRUE;
160
161 return TRUE;
162 }
163
164 // Scale by scale (isotropic scaling i.e. the same in x and y):
165 // | scale 0 0 |
166 // matrix' = | 0 scale 0 | x matrix
167 // | 0 0 scale |
168 //
169 bool wxTransformMatrix::Scale(double scale)
170 {
171 int i, j;
172 for (i = 0; i < 3; i++)
173 {
174 for (j = 0; j < 3; j++)
175 {
176 m_matrix[i][j] *= scale;
177 }
178 }
179 m_isIdentity = IsIdentity1();
180
181 return TRUE;
182 }
183
184 // Translate by dx, dy:
185 // | 1 0 dx |
186 // matrix' = | 0 1 dy | x matrix
187 // | 0 0 1 |
188 //
189 bool wxTransformMatrix::Translate(double dx, double dy)
190 {
191 int i;
192 for (i = 0; i < 3; i++)
193 m_matrix[i][0] += dx * m_matrix[i][2];
194 for (i = 0; i < 3; i++)
195 m_matrix[i][1] += dy * m_matrix[i][2];
196
197 m_isIdentity = IsIdentity1();
198
199 return TRUE;
200 }
201
202 // Rotate by the given number of degrees:
203 // | cos sin 0 |
204 // matrix' = | -sin cos 0 | x matrix
205 // | 0 0 1 |
206 //
207 bool wxTransformMatrix::Rotate(double degrees)
208 {
209 double angle = degrees * pi / 180.0;
210 double s = sin(angle);
211 double c = cos(angle);
212
213 m_matrix[0][0] = c * m_matrix[0][0] + s * m_matrix[0][1];
214 m_matrix[1][0] = c * m_matrix[1][0] + s * m_matrix[1][1];
215 m_matrix[2][0] = c * m_matrix[2][0] + s * m_matrix[2][1];
216 m_matrix[0][2] = c * m_matrix[0][1] - s * m_matrix[0][0];
217 m_matrix[1][2] = c * m_matrix[1][1] - s * m_matrix[1][0];
218 m_matrix[2][2] = c * m_matrix[2][1] - s * m_matrix[2][0];
219
220 m_isIdentity = IsIdentity1();
221
222 return TRUE;
223 }
224
225 // Transform a point from logical to device coordinates
226 bool wxTransformMatrix::TransformPoint(double x, double y, double& tx, double& ty) const
227 {
228 if (IsIdentity())
229 {
230 tx = x; ty = y; return TRUE;
231 }
232
233 tx = x * m_matrix[0][0] + y * m_matrix[1][0] + m_matrix[2][0];
234 ty = x * m_matrix[0][1] + y * m_matrix[1][1] + m_matrix[2][1];
235
236 return TRUE;
237 }
238
239 // Transform a point from device to logical coordinates.
240
241 // Example of use:
242 // wxTransformMatrix mat = dc.GetTransformation();
243 // mat.Invert();
244 // mat.InverseTransformPoint(x, y, x1, y1);
245 // OR (shorthand:)
246 // dc.LogicalToDevice(x, y, x1, y1);
247 // The latter is slightly less efficient if we're doing several
248 // conversions, since the matrix is inverted several times.
249
250 bool wxTransformMatrix::InverseTransformPoint(double x, double y, double& tx, double& ty) const
251 {
252 if (IsIdentity())
253 {
254 tx = x; ty = y; return TRUE;
255 }
256
257 double z = (1.0 - m_matrix[0][2] * x - m_matrix[1][2] * y) / m_matrix[2][2];
258 if (z == 0.0)
259 {
260 // z = 0.0000001;
261 return FALSE;
262 }
263 tx = x * m_matrix[0][0] + y * m_matrix[1][0] + z * m_matrix[2][0];
264 ty = x * m_matrix[0][1] + y * m_matrix[1][1] + z * m_matrix[2][1];
265 return TRUE;
266 }
267