]> git.saurik.com Git - wxWidgets.git/blame - src/common/matrix.cpp
* Changed behaviour of wxTextStreams::operator(wxUint8/wxInt8). Now it writes
[wxWidgets.git] / src / common / matrix.cpp
CommitLineData
c801d85f
KB
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
33const double pi = 3.1415926535;
34
35wxTransformMatrix::wxTransformMatrix(void)
36{
37 m_isIdentity = FALSE;
38
39 Identity();
40}
41
42wxTransformMatrix::wxTransformMatrix(const wxTransformMatrix& mat)
43{
44 (*this) = mat;
45}
46
47double 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
55void 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
63void 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
76bool 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
90bool wxTransformMatrix::operator != (const wxTransformMatrix& mat)
91{
92 return (! ((*this) == mat));
93}
94
95double& 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
103double 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
112bool 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
155bool 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//
169bool 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//
189bool 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//
207bool 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
226bool 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
250bool 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