]>
git.saurik.com Git - wxWidgets.git/blob - src/common/matrix.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/matrix.cpp
3 // Purpose: wxTransformMatrix class
4 // Author: Chris Breeze, Julian Smart
5 // Modified by: Klaas Holwerda
7 // Copyright: (c) Julian Smart
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
11 // Note: this is intended to be used in wxDC at some point to replace
12 // the current system of scaling/translation. It is not yet used.
14 // For compilers that support precompilation, includes "wx.h".
15 #include "wx/wxprec.h"
21 #include "wx/matrix.h"
27 static const double pi
= M_PI
;
29 wxTransformMatrix::wxTransformMatrix(void)
36 wxTransformMatrix::wxTransformMatrix(const wxTransformMatrix
& mat
)
42 double wxTransformMatrix::GetValue(int col
, int row
) const
44 if (row
< 0 || row
> 2 || col
< 0 || col
> 2)
47 return m_matrix
[col
][row
];
50 void wxTransformMatrix::SetValue(int col
, int row
, double value
)
52 if (row
< 0 || row
> 2 || col
< 0 || col
> 2)
55 m_matrix
[col
][row
] = value
;
56 m_isIdentity
= IsIdentity1();
59 void wxTransformMatrix::operator = (const wxTransformMatrix
& mat
)
62 for (i
= 0; i
< 3; i
++)
64 for (j
= 0; j
< 3; j
++)
66 m_matrix
[i
][j
] = mat
.m_matrix
[i
][j
];
69 m_isIdentity
= mat
.m_isIdentity
;
72 bool wxTransformMatrix::operator == (const wxTransformMatrix
& mat
) const
74 if (m_isIdentity
&& mat
.m_isIdentity
)
78 for (i
= 0; i
< 3; i
++)
80 for (j
= 0; j
< 3; j
++)
82 if ( !wxIsSameDouble(m_matrix
[i
][j
], mat
.m_matrix
[i
][j
]) )
89 bool wxTransformMatrix::operator != (const wxTransformMatrix
& mat
) const
91 return (! ((*this) == mat
));
94 double& wxTransformMatrix::operator()(int col
, int row
)
96 if (row
< 0 || row
> 2 || col
< 0 || col
> 2)
97 return m_matrix
[0][0];
99 return m_matrix
[col
][row
];
102 double wxTransformMatrix::operator()(int col
, int row
) const
104 if (row
< 0 || row
> 2 || col
< 0 || col
> 2)
107 return m_matrix
[col
][row
];
111 bool wxTransformMatrix::Invert(void)
113 double inverseMatrix
[3][3];
115 // calculate the adjoint
116 inverseMatrix
[0][0] = wxCalculateDet(m_matrix
[1][1],m_matrix
[2][1],m_matrix
[1][2],m_matrix
[2][2]);
117 inverseMatrix
[0][1] = -wxCalculateDet(m_matrix
[0][1],m_matrix
[2][1],m_matrix
[0][2],m_matrix
[2][2]);
118 inverseMatrix
[0][2] = wxCalculateDet(m_matrix
[0][1],m_matrix
[1][1],m_matrix
[0][2],m_matrix
[1][2]);
120 inverseMatrix
[1][0] = -wxCalculateDet(m_matrix
[1][0],m_matrix
[2][0],m_matrix
[1][2],m_matrix
[2][2]);
121 inverseMatrix
[1][1] = wxCalculateDet(m_matrix
[0][0],m_matrix
[2][0],m_matrix
[0][2],m_matrix
[2][2]);
122 inverseMatrix
[1][2] = -wxCalculateDet(m_matrix
[0][0],m_matrix
[1][0],m_matrix
[0][2],m_matrix
[1][2]);
124 inverseMatrix
[2][0] = wxCalculateDet(m_matrix
[1][0],m_matrix
[2][0],m_matrix
[1][1],m_matrix
[2][1]);
125 inverseMatrix
[2][1] = -wxCalculateDet(m_matrix
[0][0],m_matrix
[2][0],m_matrix
[0][1],m_matrix
[2][1]);
126 inverseMatrix
[2][2] = wxCalculateDet(m_matrix
[0][0],m_matrix
[1][0],m_matrix
[0][1],m_matrix
[1][1]);
128 // now divide by the determinant
129 double det
= m_matrix
[0][0] * inverseMatrix
[0][0] + m_matrix
[0][1] * inverseMatrix
[1][0] + m_matrix
[0][2] * inverseMatrix
[2][0];
130 if ( wxIsNullDouble(det
) )
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
;
137 for (int i
= 0; i
< 3; i
++)
139 for (int j
= 0; j
< 3; j
++)
141 m_matrix
[i
][j
] = inverseMatrix
[i
][j
];
144 m_isIdentity
= IsIdentity1();
148 // Make into identity matrix
149 bool wxTransformMatrix::Identity(void)
151 m_matrix
[0][0] = m_matrix
[1][1] = m_matrix
[2][2] = 1.0;
152 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;
158 // Scale by scale (isotropic scaling i.e. the same in x and y):
160 // matrix' = | 0 scale 0 | x matrix
163 bool wxTransformMatrix::Scale(double scale
)
166 for (i
= 0; i
< 3; i
++)
168 for (j
= 0; j
< 3; j
++)
170 m_matrix
[i
][j
] *= scale
;
173 m_isIdentity
= IsIdentity1();
179 // scale a matrix in 2D
185 wxTransformMatrix
& wxTransformMatrix::Scale(const double &xs
, const double &ys
,const double &xc
, const double &yc
)
187 double r00
,r10
,r20
,r01
,r11
,r21
;
191 double tx
= xc
*(1-xs
);
192 double ty
= yc
*(1-ys
);
200 else if ( !wxIsNullDouble(xc
) || !wxIsNullDouble(yc
) )
202 double tx
= xc
*(1-xs
);
203 double ty
= yc
*(1-ys
);
204 r00
= xs
* m_matrix
[0][0];
205 r10
= xs
* m_matrix
[1][0];
206 r20
= xs
* m_matrix
[2][0] + tx
;
207 r01
= ys
* m_matrix
[0][1];
208 r11
= ys
* m_matrix
[1][1];
209 r21
= ys
* m_matrix
[2][1] + ty
;
213 r00
= xs
* m_matrix
[0][0];
214 r10
= xs
* m_matrix
[1][0];
215 r20
= xs
* m_matrix
[2][0];
216 r01
= ys
* m_matrix
[0][1];
217 r11
= ys
* m_matrix
[1][1];
218 r21
= ys
* m_matrix
[2][1];
221 m_matrix
[0][0] = r00
;
222 m_matrix
[1][0] = r10
;
223 m_matrix
[2][0] = r20
;
224 m_matrix
[0][1] = r01
;
225 m_matrix
[1][1] = r11
;
226 m_matrix
[2][1] = r21
;
229 // first translate to origin O
230 (*this).Translate(-x_cen, -y_cen);
232 // now do the scaling
233 wxTransformMatrix scale;
234 scale.m_matrix[0][0] = x_fac;
235 scale.m_matrix[1][1] = y_fac;
236 scale.m_isIdentity = IsIdentity1();
238 *this = scale * (*this);
240 // translate back from origin to x_cen, y_cen
241 (*this).Translate(x_cen, y_cen);
244 m_isIdentity
= IsIdentity1();
250 // mirror a matrix in x, y
255 wxTransformMatrix
& wxTransformMatrix::Mirror(bool x
, bool y
)
257 wxTransformMatrix temp
;
260 temp
.m_matrix
[1][1] = -1;
261 temp
.m_isIdentity
=false;
265 temp
.m_matrix
[0][0] = -1;
266 temp
.m_isIdentity
=false;
269 *this = temp
* (*this);
270 m_isIdentity
= IsIdentity1();
274 // Translate by dx, dy:
276 // matrix' = | 0 1 dy | x matrix
279 bool wxTransformMatrix::Translate(double dx
, double dy
)
282 for (i
= 0; i
< 3; i
++)
283 m_matrix
[i
][0] += dx
* m_matrix
[i
][2];
284 for (i
= 0; i
< 3; i
++)
285 m_matrix
[i
][1] += dy
* m_matrix
[i
][2];
287 m_isIdentity
= IsIdentity1();
292 // Rotate clockwise by the given number of degrees:
294 // matrix' = | -sin cos 0 | x matrix
296 bool wxTransformMatrix::Rotate(double degrees
)
298 Rotate(-degrees
,0,0);
302 // counter clockwise rotate around a point
304 // cos(r) -sin(r) x(1-cos(r))+y(sin(r)
305 // sin(r) cos(r) y(1-cos(r))-x(sin(r)
307 wxTransformMatrix
& wxTransformMatrix::Rotate(const double °rees
, const double &x
, const double &y
)
309 double angle
= degrees
* pi
/ 180.0;
310 double c
= cos(angle
);
311 double s
= sin(angle
);
312 double r00
,r10
,r20
,r01
,r11
,r21
;
316 double tx
= x
*(1-c
)+y
*s
;
317 double ty
= y
*(1-c
)-x
*s
;
325 else if ( !wxIsNullDouble(x
) || !wxIsNullDouble(y
) )
327 double tx
= x
*(1-c
)+y
*s
;
328 double ty
= y
*(1-c
)-x
*s
;
329 r00
= c
* m_matrix
[0][0] - s
* m_matrix
[0][1] + tx
* m_matrix
[0][2];
330 r10
= c
* m_matrix
[1][0] - s
* m_matrix
[1][1] + tx
* m_matrix
[1][2];
331 r20
= c
* m_matrix
[2][0] - s
* m_matrix
[2][1] + tx
;// * m_matrix[2][2];
332 r01
= c
* m_matrix
[0][1] + s
* m_matrix
[0][0] + ty
* m_matrix
[0][2];
333 r11
= c
* m_matrix
[1][1] + s
* m_matrix
[1][0] + ty
* m_matrix
[1][2];
334 r21
= c
* m_matrix
[2][1] + s
* m_matrix
[2][0] + ty
;// * m_matrix[2][2];
338 r00
= c
* m_matrix
[0][0] - s
* m_matrix
[0][1];
339 r10
= c
* m_matrix
[1][0] - s
* m_matrix
[1][1];
340 r20
= c
* m_matrix
[2][0] - s
* m_matrix
[2][1];
341 r01
= c
* m_matrix
[0][1] + s
* m_matrix
[0][0];
342 r11
= c
* m_matrix
[1][1] + s
* m_matrix
[1][0];
343 r21
= c
* m_matrix
[2][1] + s
* m_matrix
[2][0];
346 m_matrix
[0][0] = r00
;
347 m_matrix
[1][0] = r10
;
348 m_matrix
[2][0] = r20
;
349 m_matrix
[0][1] = r01
;
350 m_matrix
[1][1] = r11
;
351 m_matrix
[2][1] = r21
;
354 wxTransformMatrix rotate;
355 rotate.m_matrix[2][0] = tx;
356 rotate.m_matrix[2][1] = ty;
358 rotate.m_matrix[0][0] = c;
359 rotate.m_matrix[0][1] = s;
361 rotate.m_matrix[1][0] = -s;
362 rotate.m_matrix[1][1] = c;
364 rotate.m_isIdentity=false;
365 *this = rotate * (*this);
367 m_isIdentity
= IsIdentity1();
372 // Transform a point from logical to device coordinates
373 bool wxTransformMatrix::TransformPoint(double x
, double y
, double& tx
, double& ty
) const
377 tx
= x
; ty
= y
; return true;
380 tx
= x
* m_matrix
[0][0] + y
* m_matrix
[1][0] + m_matrix
[2][0];
381 ty
= x
* m_matrix
[0][1] + y
* m_matrix
[1][1] + m_matrix
[2][1];
386 // Transform a point from device to logical coordinates.
389 // wxTransformMatrix mat = dc.GetTransformation();
391 // mat.InverseTransformPoint(x, y, x1, y1);
393 // dc.LogicalToDevice(x, y, x1, y1);
394 // The latter is slightly less efficient if we're doing several
395 // conversions, since the matrix is inverted several times.
396 bool wxTransformMatrix::InverseTransformPoint(double x
, double y
, double& tx
, double& ty
) const
405 const double z
= (1.0 - m_matrix
[0][2] * x
- m_matrix
[1][2] * y
) / m_matrix
[2][2];
406 if ( wxIsNullDouble(z
) )
409 tx
= x
* m_matrix
[0][0] + y
* m_matrix
[1][0] + z
* m_matrix
[2][0];
410 ty
= x
* m_matrix
[0][1] + y
* m_matrix
[1][1] + z
* m_matrix
[2][1];
414 wxTransformMatrix
& wxTransformMatrix::operator*=(const double& t
)
416 for (int i
= 0; i
< 3; i
++)
417 for (int j
= 0; j
< 3; j
++)
419 m_isIdentity
= IsIdentity1();
423 wxTransformMatrix
& wxTransformMatrix::operator/=(const double& t
)
425 for (int i
= 0; i
< 3; i
++)
426 for (int j
= 0; j
< 3; j
++)
428 m_isIdentity
= IsIdentity1();
432 wxTransformMatrix
& wxTransformMatrix::operator+=(const wxTransformMatrix
& mat
)
434 for (int i
= 0; i
< 3; i
++)
435 for (int j
= 0; j
< 3; j
++)
436 m_matrix
[i
][j
] += mat
.m_matrix
[i
][j
];
437 m_isIdentity
= IsIdentity1();
441 wxTransformMatrix
& wxTransformMatrix::operator-=(const wxTransformMatrix
& mat
)
443 for (int i
= 0; i
< 3; i
++)
444 for (int j
= 0; j
< 3; j
++)
445 m_matrix
[i
][j
] -= mat
.m_matrix
[i
][j
];
446 m_isIdentity
= IsIdentity1();
450 wxTransformMatrix
& wxTransformMatrix::operator*=(const wxTransformMatrix
& mat
)
453 if (mat
.m_isIdentity
)
462 wxTransformMatrix result
;
463 for (int i
= 0; i
< 3; i
++)
465 for (int j
= 0; j
< 3; j
++)
468 for (int k
= 0; k
< 3; k
++)
469 sum
+= m_matrix
[k
][i
] * mat
.m_matrix
[j
][k
];
470 result
.m_matrix
[j
][i
] = sum
;
476 m_isIdentity
= IsIdentity1();
481 // constant operators
482 wxTransformMatrix
wxTransformMatrix::operator*(const double& t
) const
484 wxTransformMatrix result
= *this;
486 result
.m_isIdentity
= result
.IsIdentity1();
490 wxTransformMatrix
wxTransformMatrix::operator/(const double& t
) const
492 wxTransformMatrix result
= *this;
495 result
.m_isIdentity
= result
.IsIdentity1();
499 wxTransformMatrix
wxTransformMatrix::operator+(const wxTransformMatrix
& m
) const
501 wxTransformMatrix result
= *this;
503 result
.m_isIdentity
= result
.IsIdentity1();
507 wxTransformMatrix
wxTransformMatrix::operator-(const wxTransformMatrix
& m
) const
509 wxTransformMatrix result
= *this;
511 result
.m_isIdentity
= result
.IsIdentity1();
516 wxTransformMatrix
wxTransformMatrix::operator*(const wxTransformMatrix
& m
) const
518 wxTransformMatrix result
= *this;
520 result
.m_isIdentity
= result
.IsIdentity1();
525 wxTransformMatrix
wxTransformMatrix::operator-() const
527 wxTransformMatrix result
= *this;
528 for (int i
= 0; i
< 3; i
++)
529 for (int j
= 0; j
< 3; j
++)
530 result
.m_matrix
[i
][j
] = -(this->m_matrix
[i
][j
]);
531 result
.m_isIdentity
= result
.IsIdentity1();
535 static double CheckInt(double getal
)
537 // check if the number is very close to an integer
538 if ( (ceil(getal
) - getal
) < 0.0001)
541 else if ( (getal
- floor(getal
)) < 0.0001)
548 double wxTransformMatrix::Get_scaleX()
551 double rot_angle
= CheckInt(atan2(m_matrix
[1][0],m_matrix
[0][0])*180/pi
);
552 if ( !wxIsSameDouble(rot_angle
, 90) && !wxIsSameDouble(rot_angle
, -90) )
553 scale_factor
= m_matrix
[0][0]/cos((rot_angle
/180)*pi
);
555 scale_factor
= m_matrix
[0][0]/sin((rot_angle
/180)*pi
); // er kan nl. niet door 0 gedeeld worden !
557 scale_factor
= CheckInt(scale_factor
);
558 if (scale_factor
< 0)
559 scale_factor
= -scale_factor
;
564 double wxTransformMatrix::Get_scaleY()
567 double rot_angle
= CheckInt(atan2(m_matrix
[1][0],m_matrix
[0][0])*180/pi
);
568 if ( !wxIsSameDouble(rot_angle
, 90) && !wxIsSameDouble(rot_angle
, -90) )
569 scale_factor
= m_matrix
[1][1]/cos((rot_angle
/180)*pi
);
571 scale_factor
= m_matrix
[1][1]/sin((rot_angle
/180)*pi
); // er kan nl. niet door 0 gedeeld worden !
573 scale_factor
= CheckInt(scale_factor
);
574 if (scale_factor
< 0)
576 scale_factor
= -scale_factor
;
582 double wxTransformMatrix::GetRotation()
584 double temp1
= GetValue(0,0); // for angle calculation
585 double temp2
= GetValue(0,1); //
588 double rot_angle
= atan2(temp2
,temp1
)*180/pi
;
590 rot_angle
= CheckInt(rot_angle
);
594 void wxTransformMatrix::SetRotation(double rotation
)
596 double x
=GetValue(2,0);
597 double y
=GetValue(2,1);
598 Rotate(-GetRotation(), x
, y
);
599 Rotate(rotation
, x
, y
);