home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / common / matrix.cpp < prev    next >
C/C++ Source or Header  |  2002-05-03  |  16KB  |  612 lines

  1. // Name:        matrix.cpp
  2. // Purpose:     wxTransformMatrix class
  3. // Author:      Chris Breeze, Julian Smart
  4. // Modified by: Klaas Holwerda
  5. // Created:     01/02/97
  6. // RCS-ID:      $Id: matrix.cpp,v 1.7 2002/05/03 19:49:20 GD Exp $
  7. // Copyright:   (c) Julian Smart and Markus Holzem
  8. // Licence:     wxWindows licence
  9. /////////////////////////////////////////////////////////////////////////////
  10.  
  11. #ifdef __GNUG__
  12. #pragma implementation "matrix.h"
  13. #endif
  14.  
  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.
  17.  
  18. // For compilers that support precompilation, includes "wx.h".
  19. #include "wx/wxprec.h"
  20.  
  21. #ifdef __BORLANDC__
  22. #pragma hdrstop
  23. #endif
  24.  
  25. #ifndef WX_PRECOMP
  26. #include "wx/defs.h"
  27. #endif
  28.  
  29. #include "wx/matrix.h"
  30. #include <math.h>
  31.  
  32. static const double pi = 3.1415926535;
  33.  
  34. wxTransformMatrix::wxTransformMatrix(void)
  35. {
  36.     m_isIdentity = FALSE;
  37.  
  38.     Identity();
  39. }
  40.  
  41. wxTransformMatrix::wxTransformMatrix(const wxTransformMatrix& mat)
  42.     : wxObject()
  43. {
  44.     (*this) = mat;
  45. }
  46.  
  47. double wxTransformMatrix::GetValue(int col, int row) const
  48. {
  49.     if (row < 0 || row > 2 || col < 0 || col > 2)
  50.         return 0.0;
  51.  
  52.     return m_matrix[col][row];
  53. }
  54.  
  55. void wxTransformMatrix::SetValue(int col, int row, double value)
  56. {
  57.     if (row < 0 || row > 2 || col < 0 || col > 2)
  58.         return;
  59.  
  60.     m_matrix[col][row] = value;
  61.     m_isIdentity = IsIdentity1();
  62. }
  63.  
  64. void wxTransformMatrix::operator = (const wxTransformMatrix& mat)
  65. {
  66.     int i, j;
  67.     for (i = 0; i < 3; i++)
  68.     {
  69.         for (j = 0; j < 3; j++)
  70.         {
  71.             m_matrix[i][j] = mat.m_matrix[i][j];
  72.         }
  73.     }
  74.     m_isIdentity = mat.m_isIdentity;
  75. }
  76.  
  77. bool wxTransformMatrix::operator == (const wxTransformMatrix& mat)
  78. {
  79.     if (m_isIdentity==TRUE && mat.m_isIdentity==TRUE)
  80.         return TRUE;
  81.  
  82.     int i, j;
  83.     for (i = 0; i < 3; i++)
  84.     {
  85.         for (j = 0; j < 3; j++)
  86.         {
  87.             if (m_matrix[i][j] != mat.m_matrix[i][j])
  88.                 return FALSE;
  89.         }
  90.     }
  91.     return TRUE;
  92. }
  93.  
  94. bool wxTransformMatrix::operator != (const wxTransformMatrix& mat)
  95. {
  96.     return (! ((*this) == mat));
  97. }
  98.  
  99. double& wxTransformMatrix::operator()(int col, int row)
  100. {
  101.     if (row < 0 || row > 2 || col < 0 || col > 2)
  102.         return m_matrix[0][0];
  103.  
  104.     return m_matrix[col][row];
  105. }
  106.  
  107. double wxTransformMatrix::operator()(int col, int row) const
  108. {
  109.     if (row < 0 || row > 2 || col < 0 || col > 2)
  110.         return 0.0;
  111.  
  112.     return m_matrix[col][row];
  113. }
  114.  
  115. // Invert matrix
  116. bool wxTransformMatrix::Invert(void)
  117. {
  118.     double inverseMatrix[3][3];
  119.  
  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]);
  124.  
  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]);
  128.  
  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]);
  132.  
  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];
  135.     if (det != 0.0)
  136.     {
  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;
  140.  
  141.         int i, j;
  142.         for (i = 0; i < 3; i++)
  143.         {
  144.             for (j = 0; j < 3; j++)
  145.             {
  146.                 m_matrix[i][j] = inverseMatrix[i][j];
  147.             }
  148.         }
  149.         m_isIdentity = IsIdentity1();
  150.         return TRUE;
  151.     }
  152.     else
  153.     {
  154.         return FALSE;
  155.     }
  156. }
  157.  
  158. // Make into identity matrix
  159. bool wxTransformMatrix::Identity(void)
  160. {
  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;
  163.     m_isIdentity = TRUE;
  164.  
  165.     return TRUE;
  166. }
  167.  
  168. // Scale by scale (isotropic scaling i.e. the same in x and y):
  169. //           | scale  0      0      |
  170. // matrix' = |  0     scale  0      | x matrix
  171. //           |  0     0      scale  |
  172. //
  173. bool wxTransformMatrix::Scale(double scale)
  174. {
  175.     int i, j;
  176.     for (i = 0; i < 3; i++)
  177.     {
  178.         for (j = 0; j < 3; j++)
  179.         {
  180.             m_matrix[i][j] *= scale;
  181.         }
  182.     }
  183.     m_isIdentity = IsIdentity1();
  184.  
  185.     return TRUE;
  186. }
  187.  
  188.  
  189. // scale a matrix in 2D
  190. //
  191. //     xs    0      xc(1-xs)
  192. //     0    ys      yc(1-ys)
  193. //     0     0      1
  194. //
  195. wxTransformMatrix&  wxTransformMatrix::Scale(const double &xs, const double &ys,const double &xc, const double &yc)
  196. {
  197.     double r00,r10,r20,r01,r11,r21;
  198.  
  199.     if (m_isIdentity)
  200.     {
  201.         double tx  =xc*(1-xs);
  202.         double ty  =yc*(1-ys);
  203.         r00 = xs;
  204.         r10 = 0;
  205.         r20 = tx;
  206.         r01 = 0;
  207.         r11 = ys;
  208.         r21 = ty;
  209.     }
  210.     else if (xc!=0 || yc!=0)
  211.     {
  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;
  220.     }
  221.     else
  222.     {
  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];
  229.     }
  230.  
  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;
  237.  
  238. /* or like this
  239.     // first translate to origin O
  240.     (*this).Translate(-x_cen, -y_cen);
  241.  
  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();
  247.  
  248.     *this = scale * (*this);
  249.  
  250.     // translate back from origin to x_cen, y_cen
  251.     (*this).Translate(x_cen, y_cen);
  252. */
  253.  
  254.     m_isIdentity = IsIdentity1();
  255.  
  256.     return *this;
  257. }
  258.  
  259.  
  260. // mirror a matrix in x, y
  261. //
  262. //     -1      0      0     Y-mirror
  263. //      0     -1      0     X-mirror
  264. //      0      0     -1     Z-mirror
  265. wxTransformMatrix&  wxTransformMatrix::Mirror(bool x, bool y)
  266. {
  267.     wxTransformMatrix temp;
  268.     if (x)
  269.     {
  270.         temp.m_matrix[1][1] = -1;
  271.         temp.m_isIdentity=FALSE;
  272.     }
  273.     if (y)
  274.     {
  275.         temp.m_matrix[0][0] = -1;
  276.         temp.m_isIdentity=FALSE;
  277.     }
  278.  
  279.     *this = temp * (*this);
  280.     m_isIdentity = IsIdentity1();
  281.     return *this;
  282. }
  283.  
  284. // Translate by dx, dy:
  285. //           | 1  0 dx |
  286. // matrix' = | 0  1 dy | x matrix
  287. //           | 0  0  1 |
  288. //
  289. bool wxTransformMatrix::Translate(double dx, double dy)
  290. {
  291.     int i;
  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];
  296.  
  297.     m_isIdentity = IsIdentity1();
  298.  
  299.     return TRUE;
  300. }
  301.  
  302. // Rotate clockwise by the given number of degrees:
  303. //           |  cos sin 0 |
  304. // matrix' = | -sin cos 0 | x matrix
  305. //           |   0   0  1 |
  306. bool wxTransformMatrix::Rotate(double degrees)
  307. {
  308.     Rotate(-degrees,0,0);
  309.     return TRUE;
  310. }
  311.  
  312. // counter clockwise rotate around a point
  313. //
  314. //  cos(r) -sin(r)    x(1-cos(r))+y(sin(r)
  315. //  sin(r)  cos(r)    y(1-cos(r))-x(sin(r)
  316. //    0      0        1
  317. wxTransformMatrix&  wxTransformMatrix::Rotate(const double °rees, const double &x, const double &y)
  318. {
  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;
  323.  
  324.     if (m_isIdentity)
  325.     {
  326.         double tx  = x*(1-c)+y*s;
  327.         double ty  = y*(1-c)-x*s;
  328.         r00 = c ;
  329.         r10 = -s;
  330.         r20 = tx;
  331.         r01 = s;
  332.         r11 = c;
  333.         r21 = ty;
  334.     }
  335.     else if (x!=0 || y!=0)
  336.     {
  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];
  345.     }
  346.     else
  347.     {
  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];
  354.     }
  355.  
  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;
  362.  
  363. /* or like this
  364.     wxTransformMatrix rotate;
  365.     rotate.m_matrix[2][0] = tx;
  366.     rotate.m_matrix[2][1] = ty;
  367.  
  368.     rotate.m_matrix[0][0] = c;
  369.     rotate.m_matrix[0][1] = s;
  370.  
  371.     rotate.m_matrix[1][0] = -s;
  372.     rotate.m_matrix[1][1] = c;
  373.  
  374.    rotate.m_isIdentity=false;
  375.    *this = rotate * (*this);
  376. */
  377.     m_isIdentity = IsIdentity1();
  378.  
  379.     return *this;
  380. }
  381.  
  382. // Transform a point from logical to device coordinates
  383. bool wxTransformMatrix::TransformPoint(double x, double y, double& tx, double& ty) const
  384. {
  385.     if (IsIdentity())
  386.     {
  387.         tx = x; ty = y; return TRUE;
  388.     }
  389.  
  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];
  392.  
  393.     return TRUE;
  394. }
  395.  
  396. // Transform a point from device to logical coordinates.
  397.  
  398. // Example of use:
  399. //   wxTransformMatrix mat = dc.GetTransformation();
  400. //   mat.Invert();
  401. //   mat.InverseTransformPoint(x, y, x1, y1);
  402. // OR (shorthand:)
  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
  407. {
  408.     if (IsIdentity())
  409.     {
  410.         tx = x; ty = y; return TRUE;
  411.     }
  412.  
  413.     double z = (1.0 - m_matrix[0][2] * x - m_matrix[1][2] * y) / m_matrix[2][2];
  414.     if (z == 0.0)
  415.     {
  416. //      z = 0.0000001;
  417.         return FALSE;
  418.     }
  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];
  421.     return TRUE;
  422. }
  423.  
  424. wxTransformMatrix& wxTransformMatrix::operator*=(const double& t)
  425. {
  426.     for (int i = 0; i < 3; i++)
  427.         for (int j = 0; j < 3; j++)
  428.             m_matrix[i][j]*= t;
  429.     m_isIdentity = IsIdentity1();
  430.     return *this;
  431. }
  432.  
  433. wxTransformMatrix& wxTransformMatrix::operator/=(const double& t)
  434. {
  435.     for (int i = 0; i < 3; i++)
  436.         for (int j = 0; j < 3; j++)
  437.             m_matrix[i][j]/= t;
  438.     m_isIdentity = IsIdentity1();
  439.     return *this;
  440. }
  441.  
  442. wxTransformMatrix& wxTransformMatrix::operator+=(const wxTransformMatrix& mat)
  443. {
  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();
  448.     return *this;
  449. }
  450.  
  451. wxTransformMatrix& wxTransformMatrix::operator-=(const wxTransformMatrix& mat)
  452. {
  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();
  457.     return *this;
  458. }
  459.  
  460. wxTransformMatrix& wxTransformMatrix::operator*=(const wxTransformMatrix& mat)
  461. {
  462.  
  463.     if (mat.m_isIdentity)
  464.         return *this;
  465.     if (m_isIdentity)
  466.     {
  467.         *this = mat;
  468.         return *this;
  469.     }
  470.     else
  471.     {
  472.         wxTransformMatrix  result;
  473.         for (int i = 0; i < 3; i++)
  474.         {
  475.            for (int j = 0; j < 3; j++)
  476.            {
  477.                double sum = 0;
  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;
  481.            }
  482.         }
  483.         *this = result;
  484.     }
  485.  
  486.     m_isIdentity = IsIdentity1();
  487.     return *this;
  488. }
  489.  
  490.  
  491. // constant operators
  492. wxTransformMatrix  wxTransformMatrix::operator*(const double& t) const
  493. {
  494.     wxTransformMatrix result = *this;
  495.     result *= t;
  496.     result.m_isIdentity = result.IsIdentity1();
  497.     return result;
  498. }
  499.  
  500. wxTransformMatrix  wxTransformMatrix::operator/(const double& t) const
  501. {
  502.     wxTransformMatrix result = *this;
  503. //    wxASSERT(t!=0);
  504.     result /= t;
  505.     result.m_isIdentity = result.IsIdentity1();
  506.     return result;
  507. }
  508.  
  509. wxTransformMatrix  wxTransformMatrix::operator+(const wxTransformMatrix& m) const
  510. {
  511.     wxTransformMatrix result = *this;
  512.     result += m;
  513.     result.m_isIdentity = result.IsIdentity1();
  514.     return result;
  515. }
  516.  
  517. wxTransformMatrix  wxTransformMatrix::operator-(const wxTransformMatrix& m) const
  518. {
  519.     wxTransformMatrix result = *this;
  520.     result -= m;
  521.     result.m_isIdentity = result.IsIdentity1();
  522.     return result;
  523. }
  524.  
  525.  
  526. wxTransformMatrix  wxTransformMatrix::operator*(const wxTransformMatrix& m) const
  527. {
  528.     wxTransformMatrix result = *this;
  529.     result *= m;
  530.     result.m_isIdentity = result.IsIdentity1();
  531.     return result;
  532. }
  533.  
  534.  
  535. wxTransformMatrix  wxTransformMatrix::operator-() const
  536. {
  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();
  542.     return result;
  543. }
  544.  
  545. static double CheckInt(double getal)
  546. {
  547.     // check if the number is very close to an integer
  548.     if ( (ceil(getal) - getal) < 0.0001)
  549.         return ceil(getal);
  550.  
  551.     else if ( (getal - floor(getal)) < 0.0001)
  552.         return floor(getal);
  553.  
  554.     return getal;
  555.  
  556. }
  557.  
  558. double wxTransformMatrix::Get_scaleX()
  559. {
  560.     double scale_factor;
  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);
  564.     else
  565.         scale_factor = m_matrix[0][0]/sin((rot_angle/180)*pi);  // er kan nl. niet door 0 gedeeld worden !
  566.  
  567.     scale_factor = CheckInt(scale_factor);
  568.     if (scale_factor < 0)
  569.         scale_factor = -scale_factor;
  570.  
  571.     return scale_factor;
  572. }
  573.  
  574. double wxTransformMatrix::Get_scaleY()
  575. {
  576.     double scale_factor;
  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);
  580.     else
  581.        scale_factor = m_matrix[1][1]/sin((rot_angle/180)*pi);   // er kan nl. niet door 0 gedeeld worden !
  582.  
  583.     scale_factor = CheckInt(scale_factor);
  584.     if (scale_factor < 0)
  585.  
  586.         scale_factor = -scale_factor;
  587.  
  588.     return scale_factor;
  589.  
  590. }
  591.  
  592. double wxTransformMatrix::GetRotation()
  593. {
  594.     double temp1 = GetValue(0,0);   // for angle calculation
  595.     double temp2 = GetValue(0,1);   //
  596.  
  597.     // Rotation
  598.     double rot_angle = atan2(temp2,temp1)*180/pi;
  599.  
  600.     rot_angle = CheckInt(rot_angle);
  601.     return rot_angle;
  602. }
  603.  
  604. void wxTransformMatrix::SetRotation(double rotation)
  605. {
  606.     double x=GetValue(2,0);
  607.     double y=GetValue(2,1);
  608.     Rotate(-GetRotation(), x, y);
  609.     Rotate(rotation, x, y);
  610. }
  611.  
  612.