From bb9c8b11def762cb9a3f6c1787905973b1fe3a8e Mon Sep 17 00:00:00 2001 From: Artur Wieczorek Date: Fri, 27 Dec 2019 20:17:19 +0100 Subject: [PATCH] Add demonstration of affine transformations to drawing sample This adds a demonstration of drawing with affine 2D transformation applied to wxDC. Transformation paramaters (translation, scale, rotation angle) can be set/reset with new menu "Transformation". --- samples/drawing/drawing.cpp | 145 ++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) diff --git a/samples/drawing/drawing.cpp b/samples/drawing/drawing.cpp index 2ba0ffc6ce..8f5800a750 100644 --- a/samples/drawing/drawing.cpp +++ b/samples/drawing/drawing.cpp @@ -286,6 +286,13 @@ public: int m_yLogicalOrigin; bool m_xAxisReversed, m_yAxisReversed; +#if wxUSE_DC_TRANSFORM_MATRIX + wxDouble m_transform_dx; + wxDouble m_transform_dy; + wxDouble m_transform_scx; + wxDouble m_transform_scy; + wxDouble m_transform_rot; +#endif // wxUSE_DC_TRANSFORM_MATRIX wxColour m_colourForeground, // these are _text_ colours m_colourBackground; wxBrush m_backgroundBrush; @@ -377,6 +384,11 @@ enum LogicalOrigin_Set, LogicalOrigin_Restore, +#if wxUSE_DC_TRANSFORM_MATRIX + TransformMatrix_Set, + TransformMatrix_Reset, +#endif // wxUSE_DC_TRANSFORM_MATRIX + #if wxUSE_COLOURDLG Colour_TextForeground, Colour_TextBackground, @@ -2119,6 +2131,91 @@ void MyCanvas::UseGraphicRenderer(wxGraphicsRenderer* renderer) } #endif // wxUSE_GRAPHICS_CONTEXT + +#if wxUSE_DC_TRANSFORM_MATRIX +#include + +class TransformDataDialog : public wxDialog +{ +public: + TransformDataDialog(wxWindow* parent, wxDouble dx, wxDouble dy, wxDouble scx, wxDouble scy, wxDouble rotAngle) + : wxDialog(parent, wxID_ANY, "Affine transformation parameters") + , m_dx(dx) + , m_dy(dy) + , m_scx(scx) + , m_scy(scy) + , m_rotAngle(rotAngle) + { + wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL); + + const int border = wxSizerFlags::GetDefaultBorder(); + wxFlexGridSizer* paramSizer = new wxFlexGridSizer(2, wxSize(border, border)); + paramSizer->Add(new wxStaticText(this, wxID_ANY, "Translation X:"), wxSizerFlags().CentreVertical()); + wxFloatingPointValidator val_dx(1, &m_dx, wxNUM_VAL_NO_TRAILING_ZEROES); + paramSizer->Add(new wxTextCtrl(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, 0, val_dx), wxSizerFlags().CentreVertical()); + paramSizer->Add(new wxStaticText(this, wxID_ANY, "Translation Y:"), wxSizerFlags().CentreVertical()); + wxFloatingPointValidator val_dy(1, &m_dy, wxNUM_VAL_NO_TRAILING_ZEROES); + paramSizer->Add(new wxTextCtrl(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, 0, val_dy), wxSizerFlags().CentreVertical()); + paramSizer->Add(new wxStaticText(this, wxID_ANY, "Scale X (0.2 - 5):"), wxSizerFlags().CentreVertical()); + wxFloatingPointValidator val_scx(2, &m_scx, wxNUM_VAL_NO_TRAILING_ZEROES); + paramSizer->Add(new wxTextCtrl(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, 0, val_scx), wxSizerFlags().CentreVertical()); + paramSizer->Add(new wxStaticText(this, wxID_ANY, "Scale Y (0.2 - 5):"), wxSizerFlags().CentreVertical()); + wxFloatingPointValidator val_scy(2, &m_scy, wxNUM_VAL_NO_TRAILING_ZEROES); + paramSizer->Add(new wxTextCtrl(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, 0, val_scy), wxSizerFlags().CentreVertical()); + paramSizer->Add(new wxStaticText(this, wxID_ANY, "Rotation angle (deg):"), wxSizerFlags().CentreVertical()); + wxFloatingPointValidator val_rot(1, &m_rotAngle, wxNUM_VAL_NO_TRAILING_ZEROES); + paramSizer->Add(new wxTextCtrl(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, 0, val_rot), wxSizerFlags().CentreVertical()); + sizer->Add(paramSizer, wxSizerFlags().DoubleBorder()); + + wxSizer *btnSizer = CreateSeparatedButtonSizer(wxOK | wxCANCEL); + sizer->Add(btnSizer, wxSizerFlags().Expand().Border()); + + SetSizerAndFit(sizer); + } + + virtual bool TransferDataFromWindow() wxOVERRIDE + { + if ( !wxDialog::TransferDataFromWindow() ) + return false; + + if ( m_scx < 0.2 || m_scx > 5.0 || m_scy < 0.2 || m_scy > 5.0 ) + { + if ( !wxValidator::IsSilent() ) + wxBell(); + + return false; + } + + return true; + } + + void GetTransformationData(wxDouble* dx, wxDouble* dy, wxDouble* scx, wxDouble* scy, wxDouble* rotAngle) const + { + if ( dx ) + *dx = m_dx; + + if ( dy ) + *dy = m_dy; + + if ( scx ) + *scx = m_scx; + + if ( scy ) + *scy = m_scy; + + if ( rotAngle ) + *rotAngle = m_rotAngle; + } + +private: + wxDouble m_dx; + wxDouble m_dy; + wxDouble m_scx; + wxDouble m_scy; + wxDouble m_rotAngle; +}; +#endif // wxUSE_DC_TRANSFORM_MATRIX + // ---------------------------------------------------------------------------- // MyFrame // ---------------------------------------------------------------------------- @@ -2258,6 +2355,13 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) menuLogical->Append( LogicalOrigin_Set, "Set to (&100, 100)\tShift-Ctrl-1" ); menuLogical->Append( LogicalOrigin_Restore, "&Restore to normal\tShift-Ctrl-0" ); +#if wxUSE_DC_TRANSFORM_MATRIX + wxMenu *menuTransformMatrix = new wxMenu; + menuTransformMatrix->Append(TransformMatrix_Set, "Set &transformation matrix"); + menuTransformMatrix->AppendSeparator(); + menuTransformMatrix->Append(TransformMatrix_Reset, "Restore to &normal"); +#endif // wxUSE_DC_TRANSFORM_MATRIX + wxMenu *menuColour = new wxMenu; #if wxUSE_COLOURDLG menuColour->Append( Colour_TextForeground, "Text &foreground..." ); @@ -2275,6 +2379,9 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) menuBar->Append(menuUserScale, "&Scale"); menuBar->Append(menuAxis, "&Axis"); menuBar->Append(menuLogical, "&Origin"); +#if wxUSE_DC_TRANSFORM_MATRIX + menuBar->Append(menuTransformMatrix, "&Transformation"); +#endif // wxUSE_DC_TRANSFORM_MATRIX menuBar->Append(menuColour, "&Colours"); // ... and attach this menu bar to the frame @@ -2292,6 +2399,13 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) m_yLogicalOrigin = 0; m_xAxisReversed = m_yAxisReversed = false; +#if wxUSE_DC_TRANSFORM_MATRIX + m_transform_dx = 0.0; + m_transform_dy = 0.0; + m_transform_scx = 1.0; + m_transform_scy = 1.0; + m_transform_rot = 0.0; +#endif // wxUSE_DC_TRANSFORM_MATRIX m_backgroundMode = wxBRUSHSTYLE_SOLID; m_colourForeground = *wxBLACK; m_colourBackground = *wxLIGHT_GREY; @@ -2539,6 +2653,27 @@ void MyFrame::OnOption(wxCommandEvent& event) m_xAxisReversed = !m_xAxisReversed; break; +#if wxUSE_DC_TRANSFORM_MATRIX + case TransformMatrix_Set: + { + TransformDataDialog dlg(this, m_transform_dx, m_transform_dy, + m_transform_scx, m_transform_scy, m_transform_rot); + if ( dlg.ShowModal() == wxID_OK ) + { + dlg.GetTransformationData(&m_transform_dx, &m_transform_dy, + &m_transform_scx, &m_transform_scy, &m_transform_rot); + } + } + break; + case TransformMatrix_Reset: + m_transform_dx = 0.0; + m_transform_dy = 0.0; + m_transform_scx = 1.0; + m_transform_scy = 1.0; + m_transform_rot = 0.0; + break; +#endif // wxUSE_DC_TRANSFORM_MATRIX + #if wxUSE_COLOURDLG case Colour_TextForeground: m_colourForeground = SelectColour(); @@ -2591,6 +2726,16 @@ void MyFrame::OnBoundingBoxUpdateUI(wxUpdateUIEvent& evt) void MyFrame::PrepareDC(wxDC& dc) { +#if wxUSE_DC_TRANSFORM_MATRIX + if ( dc.CanUseTransformMatrix() ) + { + wxAffineMatrix2D mtx; + mtx.Translate(m_transform_dx, m_transform_dy); + mtx.Rotate(wxDegToRad(m_transform_rot)); + mtx.Scale(m_transform_scx, m_transform_scy); + dc.SetTransformMatrix(mtx); + } +#endif // wxUSE_DC_TRANSFORM_MATRIX dc.SetLogicalOrigin( m_xLogicalOrigin, m_yLogicalOrigin ); dc.SetAxisOrientation( !m_xAxisReversed, m_yAxisReversed ); dc.SetUserScale( m_xUserScale, m_yUserScale );