]>
git.saurik.com Git - wxWidgets.git/blob - src/common/matrix.cpp
1 ///////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxTransformMatrix class
4 // Author: Chris Breeze, Julian Smart
5 // Modified by: Klaas Holwerda
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // Note: this is intended to be used in wxDC at some point to replace
13 // the current system of scaling/translation. It is not yet used.
15 // For compilers that support precompilation, includes "wx.h".
16 #include "wx/wxprec.h"
27 #include "wx/matrix.h"
29 static const double pi
= M_PI
;
31 wxTransformMatrix::wxTransformMatrix(void)
38 wxTransformMatrix::wxTransformMatrix(const wxTransformMatrix
& mat
)
44 double wxTransformMatrix::GetValue(int col
, int row
) const
46 if (row
< 0 || row
> 2 || col
< 0 || col
> 2)
49 return m_matrix
[col
][row
];
52 void wxTransformMatrix::SetValue(int col
, int row
, double value
)
54 if (row
< 0 || row
> 2 || col
< 0 || col
> 2)
57 m_matrix
[col
][row
] = value
;
58 m_isIdentity
= IsIdentity1();
61 void wxTransformMatrix::operator = (const wxTransformMatrix
& mat
)
64 for (i
= 0; i
< 3; i
++)
66 for (j
= 0; j
< 3; j
++)
68 m_matrix
[i
][j
] = mat
.m_matrix
[i
][j
];
71 m_isIdentity
= mat
.m_isIdentity
;
74 bool wxTransformMatrix::operator == (const wxTransformMatrix
& mat
) const
76 if (m_isIdentity
&& mat
.m_isIdentity
)
80 for (i
= 0; i
< 3; i
++)
82 for (j
= 0; j
< 3; j
++)
84 if (m_matrix
[i
][j
] != mat
.m_matrix
[i
][j
])
91 bool wxTransformMatrix::operator != (const wxTransformMatrix
& mat
) const
93 return (! ((*this) == mat
));
96 double& wxTransformMatrix::operator()(int col
, int row
)
98 if (row
< 0 || row
> 2 || col
< 0 || col
> 2)
99 return m_matrix
[0][0];
101 return m_matrix
[col
][row
];
104 double wxTransformMatrix::operator()(int col
, int row
) const
106 if (row
< 0 || row
> 2 || col
< 0 || col
> 2)
109 return m_matrix
[col
][row
];
113 bool wxTransformMatrix::Invert(void)
115 double inverseMatrix
[3][3];
117 // calculate the adjoint
118 inverseMatrix
[0][0] = wxCalculateDet(m_matrix
[1][1],m_matrix
[2][1],m_matrix
[1][2],m_matrix
[2][2]);
119 inverseMatrix
[0][1] = -wxCalculateDet(m_matrix
[0][1],m_matrix
[2][1],m_matrix
[0][2],m_matrix
[2][2]);
120 inverseMatrix
[0][2] = wxCalculateDet(m_matrix
[0][1],m_matrix
[1][1],m_matrix
[0][2],m_matrix
[1][2]);
122 inverseMatrix
[1][0] = -wxCalculateDet(m_matrix
[1][0],m_matrix
[2][0],m_matrix
[1][2],m_matrix
[2][2]);
123 inverseMatrix
[1][1] = wxCalculateDet(m_matrix
[0][0],m_matrix
[2][0],m_matrix
[0][2],m_matrix
[2][2]);
124 inverseMatrix
[1][2] = -wxCalculateDet(m_matrix
[0][0],m_matrix
[1][0],m_matrix
[0][2],m_matrix
[1][2]);
126 inverseMatrix
[2][0] = wxCalculateDet(m_matrix
[1][0],m_matrix
[2][0],m_matrix
[1][1],m_matrix
[2][1]);
127 inverseMatrix
[2][1] = -wxCalculateDet(m_matrix
[0][0],m_matrix
[2][0],m_matrix
[0][1],m_matrix
[2][1]);
128 inverseMatrix
[2][2] = wxCalculateDet(m_matrix
[0][0],m_matrix
[1][0],m_matrix
[0][1],m_matrix
[1][1]);
130 // now divide by the determinant
131 double det
= m_matrix
[0][0] * inverseMatrix
[0][0] + m_matrix
[0][1] * inverseMatrix
[1][0] + m_matrix
[0][2] * inverseMatrix
[2][0];
134 inverseMatrix
[0][0] /= det
; inverseMatrix
[1][0] /= det
; inverseMatrix
[2][0] /= det
;
135 inverseMatrix
[0][1] /= det
; inverseMatrix
[1][1] /= det
; inverseMatrix
[2][1] /= det
;
136 inverseMatrix
[0][2] /= det
; inverseMatrix
[1][2] /= det
; inverseMatrix
[2][2] /= det
;
139 for (i
= 0; i
< 3; i
++)
141 for (j
= 0; j
< 3; j
++)
143 m_matrix
[i
][j
] = inverseMatrix
[i
][j
];
146 m_isIdentity
= IsIdentity1();
155 // Make into identity matrix
156 bool wxTransformMatrix::Identity(void)
158 m_matrix
[0][0] = m_matrix
[1][1] = m_matrix
[2][2] = 1.0;
159 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;
165 // Scale by scale (isotropic scaling i.e. the same in x and y):
167 // matrix' = | 0 scale 0 | x matrix
170 bool wxTransformMatrix::Scale(double scale
)
173 for (i
= 0; i
< 3; i
++)
175 for (j
= 0; j
< 3; j
++)
177 m_matrix
[i
][j
] *= scale
;
180 m_isIdentity
= IsIdentity1();
186 // scale a matrix in 2D
192 wxTransformMatrix
& wxTransformMatrix::Scale(const double &xs
, const double &ys
,const double &xc
, const double &yc
)
194 double r00
,r10
,r20
,r01
,r11
,r21
;
198 double tx
=xc
*(1-xs
);
199 double ty
=yc
*(1-ys
);
207 else if (xc
!=0 || yc
!=0)
209 double tx
=xc
*(1-xs
);
210 double ty
=yc
*(1-ys
);
211 r00
= xs
* m_matrix
[0][0];
212 r10
= xs
* m_matrix
[1][0];
213 r20
= xs
* m_matrix
[2][0] + tx
;
214 r01
= ys
* m_matrix
[0][1];
215 r11
= ys
* m_matrix
[1][1];
216 r21
= ys
* m_matrix
[2][1] + ty
;
220 r00
= xs
* m_matrix
[0][0];
221 r10
= xs
* m_matrix
[1][0];
222 r20
= xs
* m_matrix
[2][0];
223 r01
= ys
* m_matrix
[0][1];
224 r11
= ys
* m_matrix
[1][1];
225 r21
= ys
* m_matrix
[2][1];
228 m_matrix
[0][0] = r00
;
229 m_matrix
[1][0] = r10
;
230 m_matrix
[2][0] = r20
;
231 m_matrix
[0][1] = r01
;
232 m_matrix
[1][1] = r11
;
233 m_matrix
[2][1] = r21
;
236 // first translate to origin O
237 (*this).Translate(-x_cen, -y_cen);
239 // now do the scaling
240 wxTransformMatrix scale;
241 scale.m_matrix[0][0] = x_fac;
242 scale.m_matrix[1][1] = y_fac;
243 scale.m_isIdentity = IsIdentity1();
245 *this = scale * (*this);
247 // translate back from origin to x_cen, y_cen
248 (*this).Translate(x_cen, y_cen);
251 m_isIdentity
= IsIdentity1();
257 // mirror a matrix in x, y
262 wxTransformMatrix
& wxTransformMatrix::Mirror(bool x
, bool y
)
264 wxTransformMatrix temp
;
267 temp
.m_matrix
[1][1] = -1;
268 temp
.m_isIdentity
=false;
272 temp
.m_matrix
[0][0] = -1;
273 temp
.m_isIdentity
=false;
276 *this = temp
* (*this);
277 m_isIdentity
= IsIdentity1();
281 // Translate by dx, dy:
283 // matrix' = | 0 1 dy | x matrix
286 bool wxTransformMatrix::Translate(double dx
, double dy
)
289 for (i
= 0; i
< 3; i
++)
290 m_matrix
[i
][0] += dx
* m_matrix
[i
][2];
291 for (i
= 0; i
< 3; i
++)
292 m_matrix
[i
][1] += dy
* m_matrix
[i
][2];
294 m_isIdentity
= IsIdentity1();
299 // Rotate clockwise by the given number of degrees:
301 // matrix' = | -sin cos 0 | x matrix
303 bool wxTransformMatrix::Rotate(double degrees
)
305 Rotate(-degrees
,0,0);
309 // counter clockwise rotate around a point
311 // cos(r) -sin(r) x(1-cos(r))+y(sin(r)
312 // sin(r) cos(r) y(1-cos(r))-x(sin(r)
314 wxTransformMatrix
& wxTransformMatrix::Rotate(const double °rees
, const double &x
, const double &y
)
316 double angle
= degrees
* pi
/ 180.0;
317 double c
= cos(angle
);
318 double s
= sin(angle
);
319 double r00
,r10
,r20
,r01
,r11
,r21
;
323 double tx
= x
*(1-c
)+y
*s
;
324 double ty
= y
*(1-c
)-x
*s
;
332 else if (x
!=0 || y
!=0)
334 double tx
= x
*(1-c
)+y
*s
;
335 double ty
= y
*(1-c
)-x
*s
;
336 r00
= c
* m_matrix
[0][0] - s
* m_matrix
[0][1] + tx
* m_matrix
[0][2];
337 r10
= c
* m_matrix
[1][0] - s
* m_matrix
[1][1] + tx
* m_matrix
[1][2];
338 r20
= c
* m_matrix
[2][0] - s
* m_matrix
[2][1] + tx
;// * m_matrix[2][2];
339 r01
= c
* m_matrix
[0][1] + s
* m_matrix
[0][0] + ty
* m_matrix
[0][2];
340 r11
= c
* m_matrix
[1][1] + s
* m_matrix
[1][0] + ty
* m_matrix
[1][2];
341 r21
= c
* m_matrix
[2][1] + s
* m_matrix
[2][0] + ty
;// * m_matrix[2][2];
345 r00
= c
* m_matrix
[0][0] - s
* m_matrix
[0][1];
346 r10
= c
* m_matrix
[1][0] - s
* m_matrix
[1][1];
347 r20
= c
* m_matrix
[2][0] - s
* m_matrix
[2][1];
348 r01
= c
* m_matrix
[0][1] + s
* m_matrix
[0][0];
349 r11
= c
* m_matrix
[1][1] + s
* m_matrix
[1][0];
350 r21
= c
* m_matrix
[2][1] + s
* m_matrix
[2][0];
353 m_matrix
[0][0] = r00
;
354 m_matrix
[1][0] = r10
;
355 m_matrix
[2][0] = r20
;
356 m_matrix
[0][1] = r01
;
357 m_matrix
[1][1] = r11
;
358 m_matrix
[2][1] = r21
;
361 wxTransformMatrix rotate;
362 rotate.m_matrix[2][0] = tx;
363 rotate.m_matrix[2][1] = ty;
365 rotate.m_matrix[0][0] = c;
366 rotate.m_matrix[0][1] = s;
368 rotate.m_matrix[1][0] = -s;
369 rotate.m_matrix[1][1] = c;
371 rotate.m_isIdentity=false;
372 *this = rotate * (*this);
374 m_isIdentity
= IsIdentity1();
379 // Transform a point from logical to device coordinates
380 bool wxTransformMatrix::TransformPoint(double x
, double y
, double& tx
, double& ty
) const
384 tx
= x
; ty
= y
; return true;
387 tx
= x
* m_matrix
[0][0] + y
* m_matrix
[1][0] + m_matrix
[2][0];
388 ty
= x
* m_matrix
[0][1] + y
* m_matrix
[1][1] + m_matrix
[2][1];
393 // Transform a point from device to logical coordinates.
396 // wxTransformMatrix mat = dc.GetTransformation();
398 // mat.InverseTransformPoint(x, y, x1, y1);
400 // dc.LogicalToDevice(x, y, x1, y1);
401 // The latter is slightly less efficient if we're doing several
402 // conversions, since the matrix is inverted several times.
403 bool wxTransformMatrix::InverseTransformPoint(double x
, double y
, double& tx
, double& ty
) const
407 tx
= x
; ty
= y
; return true;
410 double z
= (1.0 - m_matrix
[0][2] * x
- m_matrix
[1][2] * y
) / m_matrix
[2][2];
416 tx
= x
* m_matrix
[0][0] + y
* m_matrix
[1][0] + z
* m_matrix
[2][0];
417 ty
= x
* m_matrix
[0][1] + y
* m_matrix
[1][1] + z
* m_matrix
[2][1];
421 wxTransformMatrix
& wxTransformMatrix::operator*=(const double& t
)
423 for (int i
= 0; i
< 3; i
++)
424 for (int j
= 0; j
< 3; j
++)
426 m_isIdentity
= IsIdentity1();
430 wxTransformMatrix
& wxTransformMatrix::operator/=(const double& t
)
432 for (int i
= 0; i
< 3; i
++)
433 for (int j
= 0; j
< 3; j
++)
435 m_isIdentity
= IsIdentity1();
439 wxTransformMatrix
& wxTransformMatrix::operator+=(const wxTransformMatrix
& mat
)
441 for (int i
= 0; i
< 3; i
++)
442 for (int j
= 0; j
< 3; j
++)
443 m_matrix
[i
][j
] += mat
.m_matrix
[i
][j
];
444 m_isIdentity
= IsIdentity1();
448 wxTransformMatrix
& wxTransformMatrix::operator-=(const wxTransformMatrix
& mat
)
450 for (int i
= 0; i
< 3; i
++)
451 for (int j
= 0; j
< 3; j
++)
452 m_matrix
[i
][j
] -= mat
.m_matrix
[i
][j
];
453 m_isIdentity
= IsIdentity1();
457 wxTransformMatrix
& wxTransformMatrix::operator*=(const wxTransformMatrix
& mat
)
460 if (mat
.m_isIdentity
)
469 wxTransformMatrix result
;
470 for (int i
= 0; i
< 3; i
++)
472 for (int j
= 0; j
< 3; j
++)
475 for (int k
= 0; k
< 3; k
++)
476 sum
+= m_matrix
[k
][i
] * mat
.m_matrix
[j
][k
];
477 result
.m_matrix
[j
][i
] = sum
;
483 m_isIdentity
= IsIdentity1();
488 // constant operators
489 wxTransformMatrix
wxTransformMatrix::operator*(const double& t
) const
491 wxTransformMatrix result
= *this;
493 result
.m_isIdentity
= result
.IsIdentity1();
497 wxTransformMatrix
wxTransformMatrix::operator/(const double& t
) const
499 wxTransformMatrix result
= *this;
502 result
.m_isIdentity
= result
.IsIdentity1();
506 wxTransformMatrix
wxTransformMatrix::operator+(const wxTransformMatrix
& m
) const
508 wxTransformMatrix result
= *this;
510 result
.m_isIdentity
= result
.IsIdentity1();
514 wxTransformMatrix
wxTransformMatrix::operator-(const wxTransformMatrix
& m
) const
516 wxTransformMatrix result
= *this;
518 result
.m_isIdentity
= result
.IsIdentity1();
523 wxTransformMatrix
wxTransformMatrix::operator*(const wxTransformMatrix
& m
) const
525 wxTransformMatrix result
= *this;
527 result
.m_isIdentity
= result
.IsIdentity1();
532 wxTransformMatrix
wxTransformMatrix::operator-() const
534 wxTransformMatrix result
= *this;
535 for (int i
= 0; i
< 3; i
++)
536 for (int j
= 0; j
< 3; j
++)
537 result
.m_matrix
[i
][j
] = -(this->m_matrix
[i
][j
]);
538 result
.m_isIdentity
= result
.IsIdentity1();
542 static double CheckInt(double getal
)
544 // check if the number is very close to an integer
545 if ( (ceil(getal
) - getal
) < 0.0001)
548 else if ( (getal
- floor(getal
)) < 0.0001)
555 double wxTransformMatrix::Get_scaleX()
558 double rot_angle
= CheckInt(atan2(m_matrix
[1][0],m_matrix
[0][0])*180/pi
);
559 if (rot_angle
!= 90 && rot_angle
!= -90)
560 scale_factor
= m_matrix
[0][0]/cos((rot_angle
/180)*pi
);
562 scale_factor
= m_matrix
[0][0]/sin((rot_angle
/180)*pi
); // er kan nl. niet door 0 gedeeld worden !
564 scale_factor
= CheckInt(scale_factor
);
565 if (scale_factor
< 0)
566 scale_factor
= -scale_factor
;
571 double wxTransformMatrix::Get_scaleY()
574 double rot_angle
= CheckInt(atan2(m_matrix
[1][0],m_matrix
[0][0])*180/pi
);
575 if (rot_angle
!= 90 && rot_angle
!= -90)
576 scale_factor
= m_matrix
[1][1]/cos((rot_angle
/180)*pi
);
578 scale_factor
= m_matrix
[1][1]/sin((rot_angle
/180)*pi
); // er kan nl. niet door 0 gedeeld worden !
580 scale_factor
= CheckInt(scale_factor
);
581 if (scale_factor
< 0)
583 scale_factor
= -scale_factor
;
589 double wxTransformMatrix::GetRotation()
591 double temp1
= GetValue(0,0); // for angle calculation
592 double temp2
= GetValue(0,1); //
595 double rot_angle
= atan2(temp2
,temp1
)*180/pi
;
597 rot_angle
= CheckInt(rot_angle
);
601 void wxTransformMatrix::SetRotation(double rotation
)
603 double x
=GetValue(2,0);
604 double y
=GetValue(2,1);
605 Rotate(-GetRotation(), x
, y
);
606 Rotate(rotation
, x
, y
);