left-icon

Direct2D Succinctly®
by Chris Rose

Previous
Chapter

of
A
A
A

CHAPTER 12

Zooming

Zooming


As mentioned in the section on transformations, the entire view can be zoomed in or out using a simple Scale matrix. We will attach an event to the DirectXRenderer page that captures the mouse wheel (if the user is using a Windows 8 desktop), and allow the wheel to alter the zoom of our chart.

We already have a scale matrix being applied to our data, but its task is to flip the y-axis, so we are not drawing our chart upside down. To create a zoom capability, we can add an additional multiplication to the values in the parameters of this matrix. I have used two member floats to hold the zoom coefficients, and I have used #define to specify some limits, avoid zooming in too far, and to avoid division by zero errors that can occur when zooming out so far that it underflows the 32-bit floats. I've made the changes to the GraphRenderer.h file.

// Member variables for displaying FPS

     float m_timeDelta;     // Time since last update call

     float m_timeTotal;     // Total time of application 

     // Member variables and constants for zooming

     #define MIN_ZOOM (0.01f)     // Smallest zoom value is 1%

     #define MAX_ZOOM (100.0f)    // Largest zoom value is 10,000%

     float m_zoomX;   // The amount the x-axis is scaled by

     float m_zoomY;   // The amount the y-axis is scaled by

     Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> m_blackBrush;

     Microsoft::WRL::ComPtr<IDWriteTextFormat> m_textFormat;

Initialize the floats we just defined in the constructor of the GraphRenderer in the GraphRenderer.cpp file.

GraphRenderer::GraphRenderer():

     m_zoomX(1.0f),

     m_zoomY(1.0f)

{

Add a public, internal Zoom method prototype to the GraphRenderer class so we can call it from the DirectXPage class. I have placed this prototype directly after the GetLine method prototype.

internal:

     LineChart* GetLine() {

          return (LineChart*) m_lineChart;

          }

     // Zooming method

     void Zoom(float amount);

The body for the function in the GraphRenderer.cpp file is very basic. We multiply the axis zooms by the parameter passes, and make sure they are within the limits MAX_ZOOM and MIN_ZOOM. Place the following code in the GraphRenderer.cpp file. It can be placed at the end after the Render method.

void GraphRenderer::Zoom(float amount) {

// Multiply the zooms

m_zoomX *= amount;

m_zoomY *= amount;

// Make sure the new zooms are still within the limits:

if(m_zoomX < MIN_ZOOM) m_zoomX = MIN_ZOOM;

else if(m_zoomX > MAX_ZOOM) m_zoomX = MAX_ZOOM;

if(m_zoomY < MIN_ZOOM) m_zoomY = MIN_ZOOM;

else if(m_zoomY > MAX_ZOOM) m_zoomY = MAX_ZOOM;

}

Next, we need to add an event handler to capture when the mouse wheel is changed. Open the DirectXPage.xaml file, find the line describing the SwapChainBackground panel, and add a PointerWheelChanged event to the XAML code.

<SwapChainBackgroundPanel x:Name="SwapChainPanel"

     PointerWheelChanged="OnPointerWheelChanged" PointerMoved="OnPointerMoved"

     PointerReleased="OnPointerReleased">

Right-click on the event name in the XAML code (I've used OnPointerWheelChanged) and click Navigate to Event Handler on the context menu which appears.

Visual Studio will write the event handler code for us, and take us directly there so we can specify what is to happen when the mouse wheel changes. All we need to do is check which way the wheel was rotated, and call the GraphRenderer::Zoom method with appropriate values. I have used 1.2f to zoom in and 0.8f to zoom out. These values mean the zooming will be fairly smooth at around 20%. Here is the code for the DirectXPage::OnPointerWheelChangedEvent.

void DirectXPage::OnPointerWheelChanged(Platform::Object^ sender,

          Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e) {

     Windows::UI::Input::PointerPoint ^p = e->GetCurrentPoint(this);

     if(p->Properties->MouseWheelDelta > 0)

          m_renderer->Zoom(1.2f);

     else

          m_renderer->Zoom(0.8f);

     }

Add the additional multiplication of our new axis zoom values to the scale matrix in the GraphRenderer::Render method.

// The scale matrix inverts the y-axis

Matrix3x2F scale = Matrix3x2F::Scale(

     1.0f * m_zoomX,  // Multiply by x-axis zoom

     -1.0f * m_zoomY, // Flip and multiply by y-axis zoom

     D2D1::Point2F(0.0f, 0.0f));

Upon running the application, you should find that you can now zoom in and out of the chart using the mouse wheel. The Axes class is no longer rendering properly. First, the thickness of the axis lines is being altered by the scale matrix. When the user zooms in, the axis lines become thicker. When the user zooms out, they become thinner and disappear altogether. Figure 35 is a screenshot zoomed into the meeting point of the axes, the origin.

Zooming into Origin

The other problem is that when the chart is zoomed out, the axes’ lines no longer span the entire window. This destroys the illusion that they are infinite since the ends are clearly visible. See Figure 36.

Zooming Out

We can fix both of these problems by multiplying by the m_zoomX and m_zoomY in the m_axes::Render method call.

// The pan matrix still pans but it also adds the height of the screen

Matrix3x2F panMatrix = Matrix3x2F::Translation(m_pan.X, m_pan.Y +

     m_d2dContext->GetSize().height);

// Apply the scale first

m_d2dContext->SetTransform(scale*panMatrix*m_orientationTransform2D);

// Draw the axes

m_axes->Render(m_d2dContext, m_pan.X, m_pan.Y, m_zoomX*1.0f, m_zoomY*-1.0f);

//

// Draw objects here

//

Upon making this change, you should be able to run the application and zoom in and out without altering the thickness of the axis lines, and without making their ends visible. See Figure 37.

Zooming with Scaling Axes

Scroll To Top
Disclaimer
DISCLAIMER: Web reader is currently in beta. Please report any issues through our support system. PDF and Kindle format files are also available for download.

Previous

Next



You are one step away from downloading ebooks from the Succinctly® series premier collection!
A confirmation has been sent to your email address. Please check and confirm your email subscription to complete the download.