text: /////////////////////////////////////////////////////////////////////////////
  // Name:         wx/matrix.h
  // Purpose:      wxTransformMatrix class. NOT YET USED
  // Author:       Chris Breeze, Julian Smart
  // Modified by:  Klaas Holwerda
  // Created:      01/02/97
  // Copyright:    (c) Julian Smart, Chris Breeze
  // Licence:      wxWindows licence
  /////////////////////////////////////////////////////////////////////////////
  
  #ifndef _WX_MATRIXH__
  #define _WX_MATRIXH__
  
  #include "wx/defs.h"
  
  // Contents of this file is deprecated and shouldn't be used in the new code,
  // please see wxAffineMatrix2D instead.
  
  #if WXWIN_COMPATIBILITY_3_0
  
  #include "wx/object.h"
  #include "wx/math.h"
  
  //! codefiles="matrix.cpp"
  
  // A simple 3x3 matrix. This may be replaced by a more general matrix
  // class some day.
  //
  // Note: this is intended to be used in wxDC at some point to replace
  // the current system of scaling/translation. It is not yet used.
  
  //:definition
  //  A 3x3 matrix to do 2D transformations.
  //  It can be used to map data to window coordinates,
  //  and also for manipulating your own data.
  //  For example drawing a picture (composed of several primitives)
  //  at a certain coordinate and angle within another parent picture.
  //  At all times m_isIdentity is set if the matrix itself is an Identity matrix.
  //  It is used where possible to optimize calculations.
  class
  #ifndef WXBUILDING
  wxDEPRECATED_MSG("use wxAffineMatrix2D instead")
  #endif
  WXDLLIMPEXP_CORE wxTransformMatrix: public wxObject
  {
  public:
      wxTransformMatrix();
      wxTransformMatrix(const wxTransformMatrix& mat);
  
      //get the value in the matrix at col,row
      //rows are horizontal (second index of m_matrix member)
      //columns are vertical (first index of m_matrix member)
      double GetValue(int col, int row) const;
  
      //set the value in the matrix at col,row
      //rows are horizontal (second index of m_matrix member)
      //columns are vertical (first index of m_matrix member)
      void SetValue(int col, int row, double value);
  
      void operator = (const wxTransformMatrix& mat);
      bool operator == (const wxTransformMatrix& mat) const;
      bool operator != (const wxTransformMatrix& mat) const;
  
      //multiply every element by t
      wxTransformMatrix&          operator*=(const double& t);
      //divide every element by t
      wxTransformMatrix&          operator/=(const double& t);
      //add matrix m to this t
      wxTransformMatrix&          operator+=(const wxTransformMatrix& m);
      //subtract matrix m from this
      wxTransformMatrix&          operator-=(const wxTransformMatrix& m);
      //multiply matrix m with this
      wxTransformMatrix&          operator*=(const wxTransformMatrix& m);
  
      // constant operators
  
      //multiply every element by t  and return result
      wxTransformMatrix           operator*(const double& t) const;
      //divide this matrix by t and return result
      wxTransformMatrix           operator/(const double& t) const;
      //add matrix m to this and return result
      wxTransformMatrix           operator+(const wxTransformMatrix& m) const;
      //subtract matrix m from this and return result
      wxTransformMatrix           operator-(const wxTransformMatrix& m) const;
      //multiply this by matrix m and return result
      wxTransformMatrix           operator*(const wxTransformMatrix& m) const;
      wxTransformMatrix           operator-() const;
  
      //rows are horizontal (second index of m_matrix member)
      //columns are vertical (first index of m_matrix member)
      double& operator()(int col, int row);
  
      //rows are horizontal (second index of m_matrix member)
      //columns are vertical (first index of m_matrix member)
      double operator()(int col, int row) const;
  
      // Invert matrix
      bool Invert();
  
      // Make into identity matrix
      bool Identity();
  
      // Is the matrix the identity matrix?
      // Only returns a flag, which is set whenever an operation
      // is done.
      inline bool IsIdentity() const { return m_isIdentity; }
  
      // This does an actual check.
      inline bool IsIdentity1() const ;
  
      //Scale by scale (isotropic scaling i.e. the same in x and y):
      //!ex:
      //!code:           | scale  0      0      |
      //!code: matrix' = |  0     scale  0      | x matrix
      //!code:           |  0     0      scale  |
      bool Scale(double scale);
  
      //Scale with center point and x/y scale
      //
      //!ex:
      //!code:           |  xs    0      xc(1-xs) |
      //!code: matrix' = |  0    ys      yc(1-ys) | x matrix
      //!code:           |  0     0      1        |
      wxTransformMatrix&  Scale(const double &xs, const double &ys,const double &xc, const double &yc);
  
      // mirror a matrix in x, y
      //!ex:
      //!code:           | -1     0      0 |
      //!code: matrix' = |  0    -1      0 | x matrix
      //!code:           |  0     0      1 |
      wxTransformMatrix&  Mirror(bool x=true, bool y=false);
      // Translate by dx, dy:
      //!ex:
      //!code:           | 1  0 dx |
      //!code: matrix' = | 0  1 dy | x matrix
      //!code:           | 0  0  1 |
      bool Translate(double x, double y);
  
      // Rotate clockwise by the given number of degrees:
      //!ex:
      //!code:           |  cos sin 0 |
      //!code: matrix' = | -sin cos 0 | x matrix
      //!code:           |   0   0  1 |
      bool Rotate(double angle);
  
      //Rotate counter clockwise with point of rotation
      //
      //!ex:
      //!code:           |  cos(r) -sin(r)    x(1-cos(r))+y(sin(r)|
      //!code: matrix' = |  sin(r)  cos(r)    y(1-cos(r))-x(sin(r)| x matrix
      //!code:           |   0          0                       1 |
      wxTransformMatrix&  Rotate(const double &r, const double &x, const double &y);
  
      // Transform X value from logical to device
      inline double TransformX(double x) const;
  
      // Transform Y value from logical to device
      inline double TransformY(double y) const;
  
      // Transform a point from logical to device coordinates
      bool TransformPoint(double x, double y, double& tx, double& ty) const;
  
      // Transform a point from device to logical coordinates.
      // Example of use:
      //   wxTransformMatrix mat = dc.GetTransformation();
      //   mat.Invert();
      //   mat.InverseTransformPoint(x, y, x1, y1);
      // OR (shorthand:)
      //   dc.LogicalToDevice(x, y, x1, y1);
      // The latter is slightly less efficient if we're doing several
      // conversions, since the matrix is inverted several times.
      // N.B. 'this' matrix is the inverse at this point
      bool InverseTransformPoint(double x, double y, double& tx, double& ty) const;
  
      double Get_scaleX();
      double Get_scaleY();
      double GetRotation();
      void   SetRotation(double rotation);
  
  
  public:
      double  m_matrix[3][3];
      bool    m_isIdentity;
  };
  
  
  /*
  Chris Breeze reported, that
  some functions of wxTransformMatrix cannot work because it is not
  known if he matrix has been inverted. Be careful when using it.
  */
  
  // Transform X value from logical to device
  // warning: this function can only be used for this purpose
  // because no rotation is involved when mapping logical to device coordinates
  // mirror and scaling for x and y will be part of the matrix
  // if you have a matrix that is rotated, eg a shape containing a matrix to place
  // it in the logical coordinate system, use TransformPoint
  inline double wxTransformMatrix::TransformX(double x) const
  {
      //normally like this, but since no rotation is involved (only mirror and scale)
      //we can do without Y -> m_matrix[1]{0] is -sin(rotation angle) and therefore zero
      //(x * m_matrix[0][0] + y * m_matrix[1][0] + m_matrix[2][0]))
      return (m_isIdentity ? x : (x * m_matrix[0][0] +  m_matrix[2][0]));
  }
  
  // Transform Y value from logical to device
  // warning: this function can only be used for this purpose
  // because no rotation is involved when mapping logical to device coordinates
  // mirror and scaling for x and y will be part of the matrix
  // if you have a matrix that is rotated, eg a shape containing a matrix to place
  // it in the logical coordinate system, use TransformPoint
  inline double wxTransformMatrix::TransformY(double y) const
  {
      //normally like this, but since no rotation is involved (only mirror and scale)
      //we can do without X -> m_matrix[0]{1] is sin(rotation angle) and therefore zero
      //(x * m_matrix[0][1] + y * m_matrix[1][1] + m_matrix[2][1]))
      return (m_isIdentity ? y : (y * m_matrix[1][1] + m_matrix[2][1]));
  }
  
  
  // Is the matrix the identity matrix?
  // Each operation checks whether the result is still the identity matrix and sets a flag.
  inline bool wxTransformMatrix::IsIdentity1() const
  {
      return
      ( wxIsSameDouble(m_matrix[0][0], 1.0) &&
        wxIsSameDouble(m_matrix[1][1], 1.0) &&
        wxIsSameDouble(m_matrix[2][2], 1.0) &&
        wxIsSameDouble(m_matrix[1][0], 0.0) &&
        wxIsSameDouble(m_matrix[2][0], 0.0) &&
        wxIsSameDouble(m_matrix[0][1], 0.0) &&
        wxIsSameDouble(m_matrix[2][1], 0.0) &&
        wxIsSameDouble(m_matrix[0][2], 0.0) &&
        wxIsSameDouble(m_matrix[1][2], 0.0) );
  }
  
  // Calculates the determinant of a 2 x 2 matrix
  wxDEPRECATED_BUT_USED_INTERNALLY_INLINE(
      inline double wxCalculateDet(double a11, double a21, double a12, double a22),
      return a11 * a22 - a12 * a21;
  )
  
  #endif // WXWIN_COMPATIBILITY_3_0
  
  #endif // _WX_MATRIXH__
  