]>
git.saurik.com Git - wxWidgets.git/blob - src/common/matrix.cpp
2 // Purpose: wxTransformMatrix class
3 // Author: Chris Breeze, Julian Smart
4 // Modified by: Klaas Holwerda
7 // Copyright: (c) Julian Smart
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "matrix.h"
15 // Note: this is intended to be used in wxDC at some point to replace
16 // the current system of scaling/translation. It is not yet used.
18 // For compilers that support precompilation, includes "wx.h".
19 #include "wx/wxprec.h"
29 #include "wx/matrix.h"
32 static const double pi
= 3.1415926535;
34 wxTransformMatrix::wxTransformMatrix(void)
41 wxTransformMatrix::wxTransformMatrix(const wxTransformMatrix
& mat
)
47 double wxTransformMatrix::GetValue(int col
, int row
) const
49 if (row
< 0 || row
> 2 || col
< 0 || col
> 2)
52 return m_matrix
[col
][row
];
55 void wxTransformMatrix::SetValue(int col
, int row
, double value
)
57 if (row
< 0 || row
> 2 || col
< 0 || col
> 2)
60 m_matrix
[col
][row
] = value
;
61 m_isIdentity
= IsIdentity1();
64 void wxTransformMatrix::operator = (const wxTransformMatrix
& mat
)
67 for (i
= 0; i
< 3; i
++)
69 for (j
= 0; j
< 3; j
++)
71 m_matrix
[i
][j
] = mat
.m_matrix
[i
][j
];
74 m_isIdentity
= mat
.m_isIdentity
;
77 bool wxTransformMatrix::operator == (const wxTransformMatrix
& mat
)
79 if (m_isIdentity
==TRUE
&& mat
.m_isIdentity
==TRUE
)
83 for (i
= 0; i
< 3; i
++)
85 for (j
= 0; j
< 3; j
++)
87 if (m_matrix
[i
][j
] != mat
.m_matrix
[i
][j
])
94 bool wxTransformMatrix::operator != (const wxTransformMatrix
& mat
)
96 return (! ((*this) == mat
));
99 double& wxTransformMatrix::operator()(int col
, int row
)
101 if (row
< 0 || row
> 2 || col
< 0 || col
> 2)
102 return m_matrix
[0][0];
104 return m_matrix
[col
][row
];
107 double wxTransformMatrix::operator()(int col
, int row
) const
109 if (row
< 0 || row
> 2 || col
< 0 || col
> 2)
112 return m_matrix
[col
][row
];
116 bool wxTransformMatrix::Invert(void)
118 double inverseMatrix
[3][3];
120 // calculate the adjoint
121 inverseMatrix
[0][0] = wxCalculateDet(m_matrix
[1][1],m_matrix
[2][1],m_matrix
[1][2],m_matrix
[2][2]);
122 inverseMatrix
[0][1] = -wxCalculateDet(m_matrix
[0][1],m_matrix
[2][1],m_matrix
[0][2],m_matrix
[2][2]);
123 inverseMatrix
[0][2] = wxCalculateDet(m_matrix
[0][1],m_matrix
[1][1],m_matrix
[0][2],m_matrix
[1][2]);
125 inverseMatrix
[1][0] = -wxCalculateDet(m_matrix
[1][0],m_matrix
[2][0],m_matrix
[1][2],m_matrix
[2][2]);
126 inverseMatrix
[1][1] = wxCalculateDet(m_matrix
[0][0],m_matrix
[2][0],m_matrix
[0][2],m_matrix
[2][2]);
127 inverseMatrix
[1][2] = -wxCalculateDet(m_matrix
[0][0],m_matrix
[1][0],m_matrix
[0][2],m_matrix
[1][2]);
129 inverseMatrix
[2][0] = wxCalculateDet(m_matrix
[1][0],m_matrix
[2][0],m_matrix
[1][1],m_matrix
[2][1]);
130 inverseMatrix
[2][1] = -wxCalculateDet(m_matrix
[0][0],m_matrix
[2][0],m_matrix
[0][1],m_matrix
[2][1]);
131 inverseMatrix
[2][2] = wxCalculateDet(m_matrix
[0][0],m_matrix
[1][0],m_matrix
[0][1],m_matrix
[1][1]);
133 // now divide by the determinant
134 double det
= m_matrix
[0][0] * inverseMatrix
[0][0] + m_matrix
[0][1] * inverseMatrix
[1][0] + m_matrix
[0][2] * inverseMatrix
[2][0];
137 inverseMatrix
[0][0] /= det
; inverseMatrix
[1][0] /= det
; inverseMatrix
[2][0] /= det
;
138 inverseMatrix
[0][1] /= det
; inverseMatrix
[1][1] /= det
; inverseMatrix
[2][1] /= det
;
139 inverseMatrix
[0][2] /= det
; inverseMatrix
[1][2] /= det
; inverseMatrix
[2][2] /= det
;
142 for (i
= 0; i
< 3; i
++)
144 for (j
= 0; j
< 3; j
++)
146 m_matrix
[i
][j
] = inverseMatrix
[i
][j
];
149 m_isIdentity
= IsIdentity1();
158 // Make into identity matrix
159 bool wxTransformMatrix::Identity(void)
161 m_matrix
[0][0] = m_matrix
[1][1] = m_matrix
[2][2] = 1.0;
162 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;
168 // Scale by scale (isotropic scaling i.e. the same in x and y):
170 // matrix' = | 0 scale 0 | x matrix
173 bool wxTransformMatrix::Scale(double scale
)
176 for (i
= 0; i
< 3; i
++)
178 for (j
= 0; j
< 3; j
++)
180 m_matrix
[i
][j
] *= scale
;
183 m_isIdentity
= IsIdentity1();
189 // scale a matrix in 2D
195 wxTransformMatrix
& wxTransformMatrix::Scale(const double &xs
, const double &ys
,const double &xc
, const double &yc
)
197 double r00
,r10
,r20
,r01
,r11
,r21
;
201 double tx
=xc
*(1-xs
);
202 double ty
=yc
*(1-ys
);
210 else if (xc
!=0 || yc
!=0)
212 double tx
=xc
*(1-xs
);
213 double ty
=yc
*(1-ys
);
214 r00
= xs
* m_matrix
[0][0];
215 r10
= xs
* m_matrix
[1][0];
216 r20
= xs
* m_matrix
[2][0] + tx
;
217 r01
= ys
* m_matrix
[0][1];
218 r11
= ys
* m_matrix
[1][1];
219 r21
= ys
* m_matrix
[2][1] + ty
;
223 r00
= xs
* m_matrix
[0][0];
224 r10
= xs
* m_matrix
[1][0];
225 r20
= xs
* m_matrix
[2][0];
226 r01
= ys
* m_matrix
[0][1];
227 r11
= ys
* m_matrix
[1][1];
228 r21
= ys
* m_matrix
[2][1];
231 m_matrix
[0][0] = r00
;
232 m_matrix
[1][0] = r10
;
233 m_matrix
[2][0] = r20
;
234 m_matrix
[0][1] = r01
;
235 m_matrix
[1][1] = r11
;
236 m_matrix
[2][1] = r21
;
239 // first translate to origin O
240 (*this).Translate(-x_cen, -y_cen);
242 // now do the scaling
243 wxTransformMatrix scale;
244 scale.m_matrix[0][0] = x_fac;
245 scale.m_matrix[1][1] = y_fac;
246 scale.m_isIdentity = IsIdentity1();
248 *this = scale * (*this);
250 // translate back from origin to x_cen, y_cen
251 (*this).Translate(x_cen, y_cen);
254 m_isIdentity
= IsIdentity1();
260 // mirror a matrix in x, y
265 wxTransformMatrix
& wxTransformMatrix::Mirror(bool x
, bool y
)
267 wxTransformMatrix temp
;
270 temp
.m_matrix
[1][1] = -1;
271 temp
.m_isIdentity
=FALSE
;
275 temp
.m_matrix
[0][0] = -1;
276 temp
.m_isIdentity
=FALSE
;
279 *this = temp
* (*this);
280 m_isIdentity
= IsIdentity1();
284 // Translate by dx, dy:
286 // matrix' = | 0 1 dy | x matrix
289 bool wxTransformMatrix::Translate(double dx
, double dy
)
292 for (i
= 0; i
< 3; i
++)
293 m_matrix
[i
][0] += dx
* m_matrix
[i
][2];
294 for (i
= 0; i
< 3; i
++)
295 m_matrix
[i
][1] += dy
* m_matrix
[i
][2];
297 m_isIdentity
= IsIdentity1();
302 // Rotate clockwise by the given number of degrees:
304 // matrix' = | -sin cos 0 | x matrix
306 bool wxTransformMatrix::Rotate(double degrees
)
308 Rotate(-degrees
,0,0);
312 // counter clockwise rotate around a point
314 // cos(r) -sin(r) x(1-cos(r))+y(sin(r)
315 // sin(r) cos(r) y(1-cos(r))-x(sin(r)
317 wxTransformMatrix
& wxTransformMatrix::Rotate(const double °rees
, const double &x
, const double &y
)
319 double angle
= degrees
* pi
/ 180.0;
320 double c
= cos(angle
);
321 double s
= sin(angle
);
322 double r00
,r10
,r20
,r01
,r11
,r21
;
326 double tx
= x
*(1-c
)+y
*s
;
327 double ty
= y
*(1-c
)-x
*s
;
335 else if (x
!=0 || y
!=0)
337 double tx
= x
*(1-c
)+y
*s
;
338 double ty
= y
*(1-c
)-x
*s
;
339 r00
= c
* m_matrix
[0][0] - s
* m_matrix
[0][1] + tx
* m_matrix
[0][2];
340 r10
= c
* m_matrix
[1][0] - s
* m_matrix
[1][1] + tx
* m_matrix
[1][2];
341 r20
= c
* m_matrix
[2][0] - s
* m_matrix
[2][1] + tx
;// * m_matrix[2][2];
342 r01
= c
* m_matrix
[0][1] + s
* m_matrix
[0][0] + ty
* m_matrix
[0][2];
343 r11
= c
* m_matrix
[1][1] + s
* m_matrix
[1][0] + ty
* m_matrix
[1][2];
344 r21
= c
* m_matrix
[2][1] + s
* m_matrix
[2][0] + ty
;// * m_matrix[2][2];
348 r00
= c
* m_matrix
[0][0] - s
* m_matrix
[0][1];
349 r10
= c
* m_matrix
[1][0] - s
* m_matrix
[1][1];
350 r20
= c
* m_matrix
[2][0] - s
* m_matrix
[2][1];
351 r01
= c
* m_matrix
[0][1] + s
* m_matrix
[0][0];
352 r11
= c
* m_matrix
[1][1] + s
* m_matrix
[1][0];
353 r21
= c
* m_matrix
[2][1] + s
* m_matrix
[2][0];
356 m_matrix
[0][0] = r00
;
357 m_matrix
[1][0] = r10
;
358 m_matrix
[2][0] = r20
;
359 m_matrix
[0][1] = r01
;
360 m_matrix
[1][1] = r11
;
361 m_matrix
[2][1] = r21
;
364 wxTransformMatrix rotate;
365 rotate.m_matrix[2][0] = tx;
366 rotate.m_matrix[2][1] = ty;
368 rotate.m_matrix[0][0] = c;
369 rotate.m_matrix[0][1] = s;
371 rotate.m_matrix[1][0] = -s;
372 rotate.m_matrix[1][1] = c;
374 rotate.m_isIdentity=false;
375 *this = rotate * (*this);
377 m_isIdentity
= IsIdentity1();
382 // Transform a point from logical to device coordinates
383 bool wxTransformMatrix::TransformPoint(double x
, double y
, double& tx
, double& ty
) const
387 tx
= x
; ty
= y
; return TRUE
;
390 tx
= x
* m_matrix
[0][0] + y
* m_matrix
[1][0] + m_matrix
[2][0];
391 ty
= x
* m_matrix
[0][1] + y
* m_matrix
[1][1] + m_matrix
[2][1];
396 // Transform a point from device to logical coordinates.
399 // wxTransformMatrix mat = dc.GetTransformation();
401 // mat.InverseTransformPoint(x, y, x1, y1);
403 // dc.LogicalToDevice(x, y, x1, y1);
404 // The latter is slightly less efficient if we're doing several
405 // conversions, since the matrix is inverted several times.
406 bool wxTransformMatrix::InverseTransformPoint(double x
, double y
, double& tx
, double& ty
) const
410 tx
= x
; ty
= y
; return TRUE
;
413 double z
= (1.0 - m_matrix
[0][2] * x
- m_matrix
[1][2] * y
) / m_matrix
[2][2];
419 tx
= x
* m_matrix
[0][0] + y
* m_matrix
[1][0] + z
* m_matrix
[2][0];
420 ty
= x
* m_matrix
[0][1] + y
* m_matrix
[1][1] + z
* m_matrix
[2][1];
424 wxTransformMatrix
& wxTransformMatrix::operator*=(const double& t
)
426 for (int i
= 0; i
< 3; i
++)
427 for (int j
= 0; j
< 3; j
++)
429 m_isIdentity
= IsIdentity1();
433 wxTransformMatrix
& wxTransformMatrix::operator/=(const double& t
)
435 for (int i
= 0; i
< 3; i
++)
436 for (int j
= 0; j
< 3; j
++)
438 m_isIdentity
= IsIdentity1();
442 wxTransformMatrix
& wxTransformMatrix::operator+=(const wxTransformMatrix
& mat
)
444 for (int i
= 0; i
< 3; i
++)
445 for (int j
= 0; j
< 3; j
++)
446 m_matrix
[i
][j
] += mat
.m_matrix
[i
][j
];
447 m_isIdentity
= IsIdentity1();
451 wxTransformMatrix
& wxTransformMatrix::operator-=(const wxTransformMatrix
& mat
)
453 for (int i
= 0; i
< 3; i
++)
454 for (int j
= 0; j
< 3; j
++)
455 m_matrix
[i
][j
] -= mat
.m_matrix
[i
][j
];
456 m_isIdentity
= IsIdentity1();
460 wxTransformMatrix
& wxTransformMatrix::operator*=(const wxTransformMatrix
& mat
)
463 if (mat
.m_isIdentity
)
472 wxTransformMatrix result
;
473 for (int i
= 0; i
< 3; i
++)
475 for (int j
= 0; j
< 3; j
++)
478 for (int k
= 0; k
< 3; k
++)
479 sum
+= m_matrix
[k
][i
] * mat
.m_matrix
[j
][k
];
480 result
.m_matrix
[j
][i
] = sum
;
486 m_isIdentity
= IsIdentity1();
491 // constant operators
492 wxTransformMatrix
wxTransformMatrix::operator*(const double& t
) const
494 wxTransformMatrix result
= *this;
496 result
.m_isIdentity
= result
.IsIdentity1();
500 wxTransformMatrix
wxTransformMatrix::operator/(const double& t
) const
502 wxTransformMatrix result
= *this;
505 result
.m_isIdentity
= result
.IsIdentity1();
509 wxTransformMatrix
wxTransformMatrix::operator+(const wxTransformMatrix
& m
) const
511 wxTransformMatrix result
= *this;
513 result
.m_isIdentity
= result
.IsIdentity1();
517 wxTransformMatrix
wxTransformMatrix::operator-(const wxTransformMatrix
& m
) const
519 wxTransformMatrix result
= *this;
521 result
.m_isIdentity
= result
.IsIdentity1();
526 wxTransformMatrix
wxTransformMatrix::operator*(const wxTransformMatrix
& m
) const
528 wxTransformMatrix result
= *this;
530 result
.m_isIdentity
= result
.IsIdentity1();
535 wxTransformMatrix
wxTransformMatrix::operator-() const
537 wxTransformMatrix result
= *this;
538 for (int i
= 0; i
< 3; i
++)
539 for (int j
= 0; j
< 3; j
++)
540 result
.m_matrix
[i
][j
] = -(this->m_matrix
[i
][j
]);
541 result
.m_isIdentity
= result
.IsIdentity1();
545 static double CheckInt(double getal
)
547 // check if the number is very close to an integer
548 if ( (ceil(getal
) - getal
) < 0.0001)
551 else if ( (getal
- floor(getal
)) < 0.0001)
558 double wxTransformMatrix::Get_scaleX()
561 double rot_angle
= CheckInt(atan2(m_matrix
[1][0],m_matrix
[0][0])*180/pi
);
562 if (rot_angle
!= 90 && rot_angle
!= -90)
563 scale_factor
= m_matrix
[0][0]/cos((rot_angle
/180)*pi
);
565 scale_factor
= m_matrix
[0][0]/sin((rot_angle
/180)*pi
); // er kan nl. niet door 0 gedeeld worden !
567 scale_factor
= CheckInt(scale_factor
);
568 if (scale_factor
< 0)
569 scale_factor
= -scale_factor
;
574 double wxTransformMatrix::Get_scaleY()
577 double rot_angle
= CheckInt(atan2(m_matrix
[1][0],m_matrix
[0][0])*180/pi
);
578 if (rot_angle
!= 90 && rot_angle
!= -90)
579 scale_factor
= m_matrix
[1][1]/cos((rot_angle
/180)*pi
);
581 scale_factor
= m_matrix
[1][1]/sin((rot_angle
/180)*pi
); // er kan nl. niet door 0 gedeeld worden !
583 scale_factor
= CheckInt(scale_factor
);
584 if (scale_factor
< 0)
586 scale_factor
= -scale_factor
;
592 double wxTransformMatrix::GetRotation()
594 double temp1
= GetValue(0,0); // for angle calculation
595 double temp2
= GetValue(0,1); //
598 double rot_angle
= atan2(temp2
,temp1
)*180/pi
;
600 rot_angle
= CheckInt(rot_angle
);
604 void wxTransformMatrix::SetRotation(double rotation
)
606 double x
=GetValue(2,0);
607 double y
=GetValue(2,1);
608 Rotate(-GetRotation(), x
, y
);
609 Rotate(rotation
, x
, y
);