1/////////////////////////////////////////////////////////////////////////////
2// Name:         wx/matrix.h
3// Purpose:      wxTransformMatrix class. NOT YET USED
4// Author:       Chris Breeze, Julian Smart
5// Modified by:  Klaas Holwerda
6// Created:      01/02/97
7// RCS-ID:       $Id: matrix.h 45498 2007-04-16 13:03:05Z VZ $
8// Copyright:    (c) Julian Smart, Chris Breeze
9// Licence:      wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifndef _WX_MATRIXH__
13#define _WX_MATRIXH__
14
15//! headerfiles="matrix.h wx/object.h"
16#include "wx/object.h"
17#include "wx/math.h"
18
19//! codefiles="matrix.cpp"
20
21// A simple 3x3 matrix. This may be replaced by a more general matrix
22// class some day.
23//
24// Note: this is intended to be used in wxDC at some point to replace
25// the current system of scaling/translation. It is not yet used.
26
27//:definition
28//  A 3x3 matrix to do 2D transformations.
29//  It can be used to map data to window coordinates,
30//  and also for manipulating your own data.
31//  For example drawing a picture (composed of several primitives)
32//  at a certain coordinate and angle within another parent picture.
33//  At all times m_isIdentity is set if the matrix itself is an Identity matrix.
34//  It is used where possible to optimize calculations.
35class WXDLLEXPORT wxTransformMatrix: public wxObject
36{
37public:
38    wxTransformMatrix(void);
39    wxTransformMatrix(const wxTransformMatrix& mat);
40
41    //get the value in the matrix at col,row
42    //rows are horizontal (second index of m_matrix member)
43    //columns are vertical (first index of m_matrix member)
44    double GetValue(int col, int row) const;
45
46    //set the value in the matrix at col,row
47    //rows are horizontal (second index of m_matrix member)
48    //columns are vertical (first index of m_matrix member)
49    void SetValue(int col, int row, double value);
50
51    void operator = (const wxTransformMatrix& mat);
52    bool operator == (const wxTransformMatrix& mat) const;
53    bool operator != (const wxTransformMatrix& mat) const;
54
55    //multiply every element by t
56    wxTransformMatrix&          operator*=(const double& t);
57    //divide every element by t
58    wxTransformMatrix&          operator/=(const double& t);
59    //add matrix m to this t
60    wxTransformMatrix&          operator+=(const wxTransformMatrix& m);
61    //subtract matrix m from this
62    wxTransformMatrix&          operator-=(const wxTransformMatrix& m);
63    //multiply matrix m with this
64    wxTransformMatrix&          operator*=(const wxTransformMatrix& m);
65
66    // constant operators
67
68    //multiply every element by t  and return result
69    wxTransformMatrix           operator*(const double& t) const;
70    //divide this matrix by t and return result
71    wxTransformMatrix           operator/(const double& t) const;
72    //add matrix m to this and return result
73    wxTransformMatrix           operator+(const wxTransformMatrix& m) const;
74    //subtract matrix m from this and return result
75    wxTransformMatrix           operator-(const wxTransformMatrix& m) const;
76    //multiply this by matrix m and return result
77    wxTransformMatrix           operator*(const wxTransformMatrix& m) const;
78    wxTransformMatrix           operator-() const;
79
80    //rows are horizontal (second index of m_matrix member)
81    //columns are vertical (first index of m_matrix member)
82    double& operator()(int col, int row);
83
84    //rows are horizontal (second index of m_matrix member)
85    //columns are vertical (first index of m_matrix member)
86    double operator()(int col, int row) const;
87
88    // Invert matrix
89    bool Invert(void);
90
91    // Make into identity matrix
92    bool Identity(void);
93
94    // Is the matrix the identity matrix?
95    // Only returns a flag, which is set whenever an operation
96    // is done.
97    inline bool IsIdentity(void) const { return m_isIdentity; }
98
99    // This does an actual check.
100    inline bool IsIdentity1(void) const ;
101
102    //Scale by scale (isotropic scaling i.e. the same in x and y):
103    //!ex:
104    //!code:           | scale  0      0      |
105    //!code: matrix' = |  0     scale  0      | x matrix
106    //!code:           |  0     0      scale  |
107    bool Scale(double scale);
108
109    //Scale with center point and x/y scale
110    //
111    //!ex:
112    //!code:           |  xs    0      xc(1-xs) |
113    //!code: matrix' = |  0    ys      yc(1-ys) | x matrix
114    //!code:           |  0     0      1        |
115    wxTransformMatrix&  Scale(const double &xs, const double &ys,const double &xc, const double &yc);
116
117    // mirror a matrix in x, y
118    //!ex:
119    //!code:           | -1     0      0 |
120    //!code: matrix' = |  0    -1      0 | x matrix
121    //!code:           |  0     0      1 |
122    wxTransformMatrix&  Mirror(bool x=true, bool y=false);
123    // Translate by dx, dy:
124    //!ex:
125    //!code:           | 1  0 dx |
126    //!code: matrix' = | 0  1 dy | x matrix
127    //!code:           | 0  0  1 |
128    bool Translate(double x, double y);
129
130    // Rotate clockwise by the given number of degrees:
131    //!ex:
132    //!code:           |  cos sin 0 |
133    //!code: matrix' = | -sin cos 0 | x matrix
134    //!code:           |   0   0  1 |
135    bool Rotate(double angle);
136
137    //Rotate counter clockwise with point of rotation
138    //
139    //!ex:
140    //!code:           |  cos(r) -sin(r)    x(1-cos(r))+y(sin(r)|
141    //!code: matrix' = |  sin(r)  cos(r)    y(1-cos(r))-x(sin(r)| x matrix
142    //!code:           |   0          0                       1 |
143    wxTransformMatrix&  Rotate(const double &r, const double &x, const double &y);
144
145    // Transform X value from logical to device
146    inline double TransformX(double x) const;
147
148    // Transform Y value from logical to device
149    inline double TransformY(double y) const;
150
151    // Transform a point from logical to device coordinates
152    bool TransformPoint(double x, double y, double& tx, double& ty) const;
153
154    // Transform a point from device to logical coordinates.
155    // Example of use:
156    //   wxTransformMatrix mat = dc.GetTransformation();
157    //   mat.Invert();
158    //   mat.InverseTransformPoint(x, y, x1, y1);
159    // OR (shorthand:)
160    //   dc.LogicalToDevice(x, y, x1, y1);
161    // The latter is slightly less efficient if we're doing several
162    // conversions, since the matrix is inverted several times.
163    // N.B. 'this' matrix is the inverse at this point
164    bool InverseTransformPoint(double x, double y, double& tx, double& ty) const;
165
166    double Get_scaleX();
167    double Get_scaleY();
168    double GetRotation();
169    void   SetRotation(double rotation);
170
171
172public:
173    double  m_matrix[3][3];
174    bool    m_isIdentity;
175};
176
177
178/*
179Chris Breeze reported, that
180some functions of wxTransformMatrix cannot work because it is not
181known if he matrix has been inverted. Be careful when using it.
182*/
183
184// Transform X value from logical to device
185// warning: this function can only be used for this purpose
186// because no rotation is involved when mapping logical to device coordinates
187// mirror and scaling for x and y will be part of the matrix
188// if you have a matrix that is rotated, eg a shape containing a matrix to place
189// it in the logical coordinate system, use TransformPoint
190inline double wxTransformMatrix::TransformX(double x) const
191{
192    //normally like this, but since no rotation is involved (only mirror and scale)
193    //we can do without Y -> m_matrix[1]{0] is -sin(rotation angle) and therefore zero
194    //(x * m_matrix[0][0] + y * m_matrix[1][0] + m_matrix[2][0]))
195    return (m_isIdentity ? x : (x * m_matrix[0][0] +  m_matrix[2][0]));
196}
197
198// Transform Y value from logical to device
199// warning: this function can only be used for this purpose
200// because no rotation is involved when mapping logical to device coordinates
201// mirror and scaling for x and y will be part of the matrix
202// if you have a matrix that is rotated, eg a shape containing a matrix to place
203// it in the logical coordinate system, use TransformPoint
204inline double wxTransformMatrix::TransformY(double y) const
205{
206    //normally like this, but since no rotation is involved (only mirror and scale)
207    //we can do without X -> m_matrix[0]{1] is sin(rotation angle) and therefore zero
208    //(x * m_matrix[0][1] + y * m_matrix[1][1] + m_matrix[2][1]))
209    return (m_isIdentity ? y : (y * m_matrix[1][1] + m_matrix[2][1]));
210}
211
212
213// Is the matrix the identity matrix?
214// Each operation checks whether the result is still the identity matrix and sets a flag.
215inline bool wxTransformMatrix::IsIdentity1(void) const
216{
217    return
218    ( wxIsSameDouble(m_matrix[0][0], 1.0) &&
219      wxIsSameDouble(m_matrix[1][1], 1.0) &&
220      wxIsSameDouble(m_matrix[2][2], 1.0) &&
221      wxIsSameDouble(m_matrix[1][0], 0.0) &&
222      wxIsSameDouble(m_matrix[2][0], 0.0) &&
223      wxIsSameDouble(m_matrix[0][1], 0.0) &&
224      wxIsSameDouble(m_matrix[2][1], 0.0) &&
225      wxIsSameDouble(m_matrix[0][2], 0.0) &&
226      wxIsSameDouble(m_matrix[1][2], 0.0) );
227}
228
229// Calculates the determinant of a 2 x 2 matrix
230inline double wxCalculateDet(double a11, double a21, double a12, double a22)
231{
232    return a11 * a22 - a12 * a21;
233}
234
235#endif // _WX_MATRIXH__
236