diff --git a/include/wx/affinematrix2d.h b/include/wx/affinematrix2d.h index 6516cd46f5..28055f8d35 100644 --- a/include/wx/affinematrix2d.h +++ b/include/wx/affinematrix2d.h @@ -36,7 +36,7 @@ public: virtual bool IsEqual(const wxAffineMatrix2DBase& t) const; virtual void Translate(wxDouble dx, wxDouble dy); virtual void Scale(wxDouble xScale, wxDouble yScale); - virtual void Rotate(wxDouble ccRadians); + virtual void Rotate(wxDouble cRadians); protected: virtual wxPoint2DDouble DoTransformPoint(const wxPoint2DDouble& p) const; diff --git a/interface/wx/affinematrix2d.h b/interface/wx/affinematrix2d.h index 340051fa3b..b600494f4c 100644 --- a/interface/wx/affinematrix2d.h +++ b/interface/wx/affinematrix2d.h @@ -107,6 +107,12 @@ public: The translation in x direction. @param dy The translation in y direction. + + @code + // | 1 0 0 | | m_11 m_12 0 | + // matrix' = | 0 1 0 | x | m_21 m_22 0 | + // | dx dy 1 | | m_tx m_ty 1 | + @endcode */ void Translate(wxDouble dx, wxDouble dy); @@ -117,6 +123,12 @@ public: Scaling in x direction. @param yScale Scaling in y direction. + + @code + // | xScale 0 0 | | m_11 m_12 0 | + // matrix' = | 0 yScale 0 | x | m_21 m_22 0 | + // | 0 0 1 | | m_tx m_ty 1 | + @endcode */ void Scale(wxDouble xScale, wxDouble yScale); @@ -130,12 +142,18 @@ public: void Mirror(int direction = wxHORIZONTAL); /** - Add counter clockwise rotation to this matrix. + Add clockwise rotation to this matrix. - @param ccRadians - Rotation angle in radians. + @param cRadians + Rotation angle in radians, clockwise. + + @code + // | cos sin 0 | | m_11 m_12 0 | + // matrix' = | -sin cos 0 | x | m_21 m_22 0 | + // | 0 0 1 | | m_tx m_ty 1 | + @endcode */ - void Rotate(wxDouble ccRadians); + void Rotate(wxDouble cRadians); /** Applies this matrix to the point. @@ -144,6 +162,12 @@ public: The point receiving the transformations. @return The point with the transformations applied. + + @code + // | m_11 m_12 0 | + // point' = | src.m_x src._my 1 | x | m_21 m_22 0 | + // | m_tx m_ty 1 | + @endcode */ wxPoint2DDouble TransformPoint(const wxPoint2DDouble& p) const; void TransformPoint(wxDouble* x, wxDouble* y) const; @@ -155,6 +179,12 @@ public: The source receiving the transformations. @return The source with the transformations applied. + + @code + // | m_11 m_12 0 | + // dist' = | src.m_x src._my 0 | x | m_21 m_22 0 | + // | m_tx m_ty 1 | + @endcode */ wxPoint2DDouble TransformDistance(const wxPoint2DDouble& p) const; void TransformDistance(wxDouble* dx, wxDouble* dy) const; diff --git a/interface/wx/affinematrix2dbase.h b/interface/wx/affinematrix2dbase.h index 630cbc8740..efbeb7bd18 100644 --- a/interface/wx/affinematrix2dbase.h +++ b/interface/wx/affinematrix2dbase.h @@ -156,12 +156,12 @@ public: virtual void Scale(wxDouble xScale, wxDouble yScale) = 0; /** - Add counter clockwise rotation to this matrix. + Add clockwise rotation to this matrix. - @param ccRadians - Rotation angle in radians. + @param cRadians + Rotation angle in radians, clockwise. */ - virtual void Rotate(wxDouble ccRadians) = 0; + virtual void Rotate(wxDouble cRadians) = 0; /** Add mirroring to this matrix. diff --git a/interface/wx/graphics.h b/interface/wx/graphics.h index 630662f47a..ac46f91a31 100644 --- a/interface/wx/graphics.h +++ b/interface/wx/graphics.h @@ -1299,7 +1299,10 @@ public: virtual bool IsIdentity() const; /** - Rotates this matrix (in radians). + Rotates this matrix clockwise (in radians). + + @param radians + Rotation angle in radians, clockwise. */ virtual void Rotate(wxDouble angle); diff --git a/src/common/affinematrix2d.cpp b/src/common/affinematrix2d.cpp index 0b1b9207dc..5013b31f15 100644 --- a/src/common/affinematrix2d.cpp +++ b/src/common/affinematrix2d.cpp @@ -127,19 +127,19 @@ void wxAffineMatrix2D::Scale(wxDouble xScale, wxDouble yScale) m_22 *= yScale; } -// add the rotation to this matrix (counter clockwise, radians) -// | cos -sin 0 | | m_11 m_12 0 | -// | sin cos 0 | x | m_21 m_22 0 | +// add the rotation to this matrix (clockwise, radians) +// | cos sin 0 | | m_11 m_12 0 | +// | -sin cos 0 | x | m_21 m_22 0 | // | 0 0 1 | | m_tx m_ty 1 | -void wxAffineMatrix2D::Rotate(wxDouble ccRadians) +void wxAffineMatrix2D::Rotate(wxDouble cRadians) { - wxDouble c = cos(ccRadians); - wxDouble s = sin(ccRadians); + wxDouble c = cos(cRadians); + wxDouble s = sin(cRadians); - wxDouble e11 = c*m_11 - s*m_21; - wxDouble e12 = c*m_12 - s*m_22; - m_21 = s*m_11 + c*m_21; - m_22 = s*m_12 + c*m_22; + wxDouble e11 = c*m_11 + s*m_21; + wxDouble e12 = c*m_12 + s*m_22; + m_21 = c*m_21 - s*m_11; + m_22 = c*m_22 - s*m_12; m_11 = e11; m_12 = e12; } @@ -159,7 +159,7 @@ wxAffineMatrix2D::DoTransformPoint(const wxPoint2DDouble& src) const return src; return wxPoint2DDouble(src.m_x * m_11 + src.m_y * m_21 + m_tx, - src.m_y * m_12 + src.m_y * m_22 + m_ty); + src.m_x * m_12 + src.m_y * m_22 + m_ty); } // applies the matrix except for translations @@ -173,7 +173,7 @@ wxAffineMatrix2D::DoTransformDistance(const wxPoint2DDouble& src) const return src; return wxPoint2DDouble(src.m_x * m_11 + src.m_y * m_21, - src.m_y * m_12 + src.m_y * m_22); + src.m_x * m_12 + src.m_y * m_22); } bool wxAffineMatrix2D::IsIdentity() const diff --git a/tests/graphics/affinematrix.cpp b/tests/graphics/affinematrix.cpp index 90f56cc1a9..22ade75033 100644 --- a/tests/graphics/affinematrix.cpp +++ b/tests/graphics/affinematrix.cpp @@ -16,6 +16,7 @@ #pragma hdrstop #endif +#include "wx/graphics.h" #include "wx/dcmemory.h" #include "wx/affinematrix2d.h" #include "wx/math.h" @@ -42,6 +43,9 @@ private: #if wxUSE_DC_TRANSFORM_MATRIX CPPUNIT_TEST( VMirrorAndTranslate ); CPPUNIT_TEST( Rotate90Clockwise ); +#if wxUSE_GRAPHICS_CONTEXT + CPPUNIT_TEST( CompareToGraphicsContext ); +#endif // wxUSE_GRAPHICS_CONTEXT #endif // wxUSE_DC_TRANSFORM_MATRIX CPPUNIT_TEST_SUITE_END(); @@ -49,6 +53,9 @@ private: #if wxUSE_DC_TRANSFORM_MATRIX void VMirrorAndTranslate(); void Rotate90Clockwise(); +#if wxUSE_GRAPHICS_CONTEXT + void CompareToGraphicsContext(); +#endif // wxUSE_GRAPHICS_CONTEXT wxImage m_imgOrig; wxBitmap m_bmpOrig; @@ -133,7 +140,7 @@ void AffineTransformTestCase::Rotate90Clockwise() return; wxAffineMatrix2D matrix; - matrix.Rotate(-0.5 * M_PI); + matrix.Rotate(0.5 * M_PI); matrix.Translate(0, -m_bmpOrig.GetHeight()); dc.SetTransformMatrix(matrix); dc.DrawBitmap(m_bmpOrig, 0, 0); @@ -143,4 +150,102 @@ void AffineTransformTestCase::Rotate90Clockwise() m_imgOrig.Rotate90(true) ); } +#if wxUSE_GRAPHICS_CONTEXT +void AffineTransformTestCase::CompareToGraphicsContext() +{ + wxPoint2DDouble pointA1(1.0, 3.0), pointA2(60.0, 50.0), + pointG1(1.0, 3.0), pointG2(60.0, 50.0); + + // Create affine matrix and transform it + wxAffineMatrix2D matrixA1, matrixA2; + matrixA2.Rotate(M_PI / 3); + matrixA1.Translate(-m_bmpOrig.GetWidth()/2, -m_bmpOrig.GetHeight()/2); + matrixA1.Rotate(-M_PI *2/ 6); + matrixA1.Translate(m_bmpOrig.GetWidth()/2, m_bmpOrig.GetHeight()/2); + matrixA1.Mirror(wxHORIZONTAL); + matrixA1.Concat(matrixA2); + matrixA1.Mirror(wxVERTICAL); + matrixA1.Translate(m_bmpOrig.GetWidth()/2, -m_bmpOrig.GetHeight()/2); + matrixA1.Scale(0.9, 0.9); + matrixA1.Invert(); + + // Create image using first matrix + wxBitmap bmpUsingMatrixA1(m_bmpOrig.GetHeight(), m_bmpOrig.GetWidth()); + + // Build the transformed image using the transformation matrix + { + wxMemoryDC dc(bmpUsingMatrixA1); + + if ( !dc.CanUseTransformMatrix() ) + return; + + // Draw the bitmap + dc.SetTransformMatrix(matrixA1); + dc.DrawBitmap(m_bmpOrig, 0, 0); + + // Draw a line + matrixA1.TransformPoint(&pointA1.m_x, &pointA1.m_y); + matrixA1.TransformDistance(&pointA2.m_x, &pointA2.m_y); + + dc.DrawLine(wxRound(pointA1.m_x), wxRound(pointA1.m_y), + wxRound(pointA1.m_x + pointA2.m_x), wxRound(pointA1.m_x + pointA2.m_y)); + } + + + // Create graphics matrix and transform it + wxMemoryDC mDc; + wxGraphicsContext* gDc = wxGraphicsContext::Create(mDc); + wxGraphicsMatrix matrixG1 = gDc->CreateMatrix(); + wxGraphicsMatrix matrixG2 = gDc->CreateMatrix(); + matrixG2.Rotate(M_PI / 3); + matrixG1.Translate(-m_bmpOrig.GetWidth()/2, -m_bmpOrig.GetHeight()/2); + matrixG1.Rotate(-M_PI*2 / 6); + matrixG1.Translate(m_bmpOrig.GetWidth()/2, m_bmpOrig.GetHeight()/2); + matrixG1.Scale(-1, 1); + matrixG1.Concat(matrixG2); + matrixG1.Scale(1, -1); + matrixG1.Translate(m_bmpOrig.GetWidth()/2, -m_bmpOrig.GetHeight()/2); + matrixG1.Scale(0.9, 0.9); + matrixG1.Invert(); + // Create affine matrix from the graphics matrix + wxMatrix2D mat2D; + wxPoint2DDouble tr; + matrixG1.Get(&mat2D.m_11, &mat2D.m_12, &mat2D.m_21, &mat2D.m_22, &tr.m_x, &tr.m_y); + wxAffineMatrix2D matrixAG; + matrixAG.Set(mat2D, tr); + + delete gDc; + + // Create image using last matrix + wxBitmap bmpUsingMatrixAG(m_bmpOrig.GetHeight(), m_bmpOrig.GetWidth()); + + // Build the transformed image using the transformation matrix + { + wxMemoryDC dc(bmpUsingMatrixAG); + + if ( !dc.CanUseTransformMatrix() ) + return; + + // Draw the bitmap + dc.SetTransformMatrix(matrixAG); + dc.DrawBitmap(m_bmpOrig, 0, 0); + + // Draw a line + matrixG1.TransformPoint(&pointG1.m_x, &pointG1.m_y); + matrixG1.TransformDistance(&pointG2.m_x, &pointG2.m_y); + + dc.DrawLine(wxRound(pointG1.m_x), wxRound(pointG1.m_y), + wxRound(pointG1.m_x + pointG2.m_x), wxRound(pointG1.m_x + pointG2.m_y)); + } + + + CPPUNIT_ASSERT_EQUAL( bmpUsingMatrixA1.ConvertToImage(), + bmpUsingMatrixAG.ConvertToImage() ); + + // Save the images to check that something _is_ inside the visible area. + //bmpUsingMatrixA1.SaveFile("matrixA1.jpg", wxBITMAP_TYPE_JPEG); + //bmpUsingMatrixAG.SaveFile("matrixAG.jpg", wxBITMAP_TYPE_JPEG); +} +#endif // wxUSE_GRAPHICS_CONTEXT + #endif // wxUSE_DC_TRANSFORM_MATRIX