ChartDirector 7.1 (.NET Edition)

Contour Plot Zoom/Scroll (Windows)




NOTE: For conciseness, some of the following descriptions only mention WinChartViewer. Those descriptions apply to WPFChartViewer as well.

This example demonstrates zooming and scrolling for a contour chart.

This example is similar to XY Zooming and Scrolling (Windows) except a contour chart is used instead of a scatter chart. It demonstrates considerations specific to contour charts:

Source Code Listing

[Windows Forms - C# version] NetWinCharts\CSharpWinCharts\frmcontourzoomscroll.cs
using System; using System.Drawing; using System.Windows.Forms; using ChartDirector; namespace CSharpChartExplorer { public partial class FrmContourZoomScroll : Form { // Data points for the chart private double[] dataX; private double[] dataY; private double[] dataZ; // To ensure color consistency, we need to save the first color axis and // synchronize the color axis of the zoom-in charts with the this axis. XYChart firstChart; ColorAxis firstColorAxis; public FrmContourZoomScroll() { InitializeComponent(); } // // Form Load Event Handler // private void FrmContourZoomScroll_Load(object sender, EventArgs e) { // Set initial mouse usage for ChartViewer winChartViewer1.MouseUsage = WinChartMouseUsage.ScrollOnDrag; winChartViewer1.ScrollDirection = WinChartDirection.HorizontalVertical; // By default, when the user drags a rectangle to zoom in, the x and y dimensions can zoom by // different factors. KeepAspectRatio can be used to ensure the x and y dimensions are zoom by // the same factor, thereby keeping the aspect ratio unchanged. winChartViewer1.ZoomDirection = WinChartDirection.KeepAspectRatio; // Enable mouse wheel zooming by setting the zoom ratio to 1.1 per wheel event winChartViewer1.MouseWheelZoomRatio = 1.1; // Configure CDML tooltip to use a semi-transparent rounded rectangle as container and // Arial Bold as font winChartViewer1.CDMLToolTipPrefix = "<*block,bgColor=60FFFFDD,roundedCorners=5,margin=5,edgeColor=000000*><*font=Arial Bold*>"; // Load the data loadData(); // Trigger the ViewPortChanged event to draw the chart winChartViewer1.updateViewPort(true, true); // Configure the CViewPortControl to use transparent black for region outside the viewport, // that is, to darken the outside region. viewPortControl1.ViewPortExternalColor = Color.FromArgb(80, 0, 0, 0); viewPortControl1.ViewPortBorderColor = Color.FromArgb(80, 255, 255, 255); viewPortControl1.SelectionBorderColor = Color.FromArgb(80, 255, 255, 255); // Draw the full thumbnail chart for the ViewPortControl drawFullChart(viewPortControl1, winChartViewer1); // Bind the winChartViewer1 to the viewPortControl1 viewPortControl1.Viewer = winChartViewer1; } // // Load the data // private void loadData() { // The x and y coordinates of the grid dataX = new double[] {-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; dataY = new double[] {-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // The values at the grid points. In this example, we will compute the values using the // formula z = x * sin(y) + y * sin(x). dataZ = new double[dataX.Length * dataY.Length]; for (int yIndex = 0; yIndex < dataY.Length; ++yIndex) { double y = dataY[yIndex]; for (int xIndex = 0; xIndex < dataX.Length; ++xIndex) { double x = dataX[xIndex]; dataZ[yIndex * dataX.Length + xIndex] = x * Math.Sin(y) + y * Math.Sin(x); } } } // // Pointer (Drag to Scroll) button event handler // private void pointerPB_CheckedChanged(object sender, EventArgs e) { if (((RadioButton)sender).Checked) winChartViewer1.MouseUsage = WinChartMouseUsage.ScrollOnDrag; } // // Zoom In button event handler // private void zoomInPB_CheckedChanged(object sender, EventArgs e) { if (((RadioButton)sender).Checked) winChartViewer1.MouseUsage = WinChartMouseUsage.ZoomIn; } // // Zoom Out button event handler // private void zoomOutPB_CheckedChanged(object sender, EventArgs e) { if (((RadioButton)sender).Checked) winChartViewer1.MouseUsage = WinChartMouseUsage.ZoomOut; } // // Save button event handler // private void savePB_Click(object sender, EventArgs e) { // The standard Save File dialog SaveFileDialog fileDlg = new SaveFileDialog(); fileDlg.Filter = "PNG (*.png)|*.png|JPG (*.jpg)|*.jpg|GIF (*.gif)|*.gif|BMP (*.bmp)|*.bmp|" + "SVG (*.svg)|*.svg|PDF (*.pdf)|*.pdf"; fileDlg.FileName = "chartdirector_demo"; if (fileDlg.ShowDialog() != DialogResult.OK) return; // Save the chart if (null != winChartViewer1.Chart) winChartViewer1.Chart.makeChart(fileDlg.FileName); } // // The ViewPortChanged event handler. This event occurs if the user scrolls or zooms in or // out the chart by dragging or clicking on the chart. It can also be triggered by calling // WinChartViewer.updateViewPort. // private void winChartViewer1_ViewPortChanged(object sender, WinViewPortEventArgs e) { // In addition to updating the chart, we may also need to update other controls that // changes based on the view port. updateControls(winChartViewer1); // Update the chart if necessary if (e.NeedUpdateChart) drawChart(winChartViewer1); } // // Update controls when the view port changed // private void updateControls(WinChartViewer viewer) { // Synchronize the zoom bar value with the view port width/height zoomBar.Value = (int)Math.Round(Math.Min(viewer.ViewPortWidth, viewer.ViewPortHeight) * zoomBar.Maximum); } // // ValueChanged event handler for zoomBar. Zoom in around the center point and try to // maintain the aspect ratio // private void zoomBar_ValueChanged(object sender, EventArgs e) { if (!winChartViewer1.IsInViewPortChangedEvent) { //Remember the center point double centerX = winChartViewer1.ViewPortLeft + winChartViewer1.ViewPortWidth / 2; double centerY = winChartViewer1.ViewPortTop + winChartViewer1.ViewPortHeight / 2; //Aspect ratio and zoom factor double aspectRatio = winChartViewer1.ViewPortWidth / winChartViewer1.ViewPortHeight; double zoomTo = ((double)zoomBar.Value) / zoomBar.Maximum; //Zoom while respecting the aspect ratio winChartViewer1.ViewPortWidth = zoomTo * Math.Max(1, aspectRatio); winChartViewer1.ViewPortHeight = zoomTo * Math.Max(1, 1 / aspectRatio); //Adjust ViewPortLeft and ViewPortTop to keep center point unchanged winChartViewer1.ViewPortLeft = centerX - winChartViewer1.ViewPortWidth / 2; winChartViewer1.ViewPortTop = centerY - winChartViewer1.ViewPortHeight / 2; //update the chart, but no need to update the image map yet, as the chart is still //zooming and is unstable winChartViewer1.updateViewPort(true, false); } } // // Draw the chart and display it in the given viewer // private void drawChart(WinChartViewer viewer) { // Create an XYChart object 540 x 490 pixels in size XYChart c = new XYChart(540, 490); // Set the plotarea at (50, 40) and of size 400 x 400 pixels. Use semi-transparent black // (7f000000) dotted lines for both horizontal and vertical grid lines c.setPlotArea(50, 40, 400, 400, -1, -1, -1, c.dashLineColor(0x7f000000, Chart.DotLine), -1); // Enable clipping mode to clip the part of the data that is outside the plot area. c.setClipping(); // Add a title to the chart using 15 points Arial Bold Italic font c.addTitle("z = x * sin(y) + y * sin(x) ", "Arial Bold Italic", 15); // Set x-axis and y-axis title using 12 points Arial Bold Italic font c.xAxis().setTitle("X-Axis Title Place Holder", "Arial Bold Italic", 12); c.yAxis().setTitle("Y-Axis Title Place Holder", "Arial Bold Italic", 12); // Set x-axis and y-axis labels to use Arial Bold font c.xAxis().setLabelStyle("Arial Bold"); c.yAxis().setLabelStyle("Arial Bold"); // When auto-scaling, use tick spacing of 40 pixels as a guideline c.yAxis().setTickDensity(40); c.xAxis().setTickDensity(40); // Add a contour layer using the given data ContourLayer layer = c.addContourLayer(dataX, dataY, dataZ); // Move the grid lines in front of the contour layer c.getPlotArea().moveGridBefore(layer); // Add a color axis (the legend) in which the top left corner is anchored at (470, 40). Set the // length to 400 pixels and the labels on the right side. ColorAxis cAxis = layer.setColorAxis(470, 40, Chart.TopLeft, 400, Chart.Right); // Add a title to the color axis using 12 points Arial Bold Italic font cAxis.setTitle("Color Legend Title Place Holder", "Arial Bold Italic", 12) .setAlignment(Chart.Right); // Set color axis labels to use Arial Bold font cAxis.setLabelStyle("Arial Bold"); // In this example, we have not explicitly configured the full x and y range. In this case, // the first time syncLinearAxisWithViewPort is called, ChartDirector will auto-scale the axis // and assume the resulting range is the full range. In subsequent calls, ChartDirector will // set the axis range based on the view port and the full range. viewer.syncLinearAxisWithViewPort("x", c.xAxis()); viewer.syncLinearAxisWithViewPort("y", c.yAxis()); // To ensure the color is consistent, we must keep the color axis the same when the zooming or // scrolling the chart. To do this, we save the color axis of the first chart and synchronize // all future charts with this color axis. if (null == firstChart) { // We need to save the first chart as well as the first color axis. Otherwise the first // chart may get deleted, and this will delete the first color axis as well. firstChart = c; firstColorAxis = cAxis; } else cAxis.syncAxis(firstColorAxis); // Display chart viewer.Chart = c; // Tooltip for the contour chart viewer.ImageMap = c.getHTMLImageMap("", "", "title='<*cdml*>X={x|2}<*br*>Y={y|2}<*br*>Z={z|2}'"); } // // Draw the full thumbnail chart and display it in the given ViewPortControl // private void drawFullChart(WinViewPortControl vpc, WinChartViewer viewer) { // Create an XYChart object 110 x 110 pixels in size XYChart c = new XYChart(110, 110); // Set the plotarea to cover the entire chart. Disable grid lines by setting their colors // to transparent. c.setPlotArea(0, 0, c.getWidth() - 1, c.getHeight() - 1, -1, -1, -1, Chart.Transparent, Chart.Transparent); // Add a contour layer using the given data ContourLayer layer = c.addContourLayer(dataX, dataY, dataZ); layer.setContourColor(unchecked((int)0xcf000000)); // To maintain color consistency, the color axis is synchronized to that of the first chart. layer.colorAxis().syncAxis(firstColorAxis); // The x and y axis scales reflect the full range of the view port c.xAxis().setLinearScale(viewer.getValueAtViewPort("x", 0), viewer.getValueAtViewPort("x", 1), Chart.NoValue); c.yAxis().setLinearScale(viewer.getValueAtViewPort("y", 0), viewer.getValueAtViewPort("y", 1), Chart.NoValue); // Set the chart image to the viewport control vpc.Chart = c; } } }

[Windows Forms - VB Version] NetWinCharts\VBNetWinCharts\frmcontourzoomscroll.vb
Imports ChartDirector Public Class FrmContourZoomScroll ' Data points for the chart Dim dataX As Double() Dim dataY As Double() Dim dataZ As Double() ' To ensure color consistency, we need to save the first color axis And ' synchronize the color axis of the zoom-in charts with the this axis. Dim firstChart As XYChart Dim firstColorAxis As ColorAxis ' ' Form Load Event Handler ' Private Sub FrmContourZoomScroll_Load(ByVal sender As Object, ByVal e As EventArgs) _ Handles MyBase.Load ' Set initial mouse usage for ChartViewer winChartViewer1.MouseUsage = WinChartMouseUsage.ScrollOnDrag winChartViewer1.ScrollDirection = WinChartDirection.HorizontalVertical ' By default, when the user drags a rectangle to zoom in, the x And y dimensions can zoom by ' different factors. KeepAspectRatio can be used to ensure the x And y dimensions are zoom by ' the same factor, thereby keeping the aspect ratio unchanged. winChartViewer1.ZoomDirection = WinChartDirection.KeepAspectRatio ' Enable mouse wheel zooming by setting the zoom ratio to 1.1 per wheel event winChartViewer1.MouseWheelZoomRatio = 1.1 ' Configure CDML tooltip to use a semi-transparent rounded rectangle as container And ' Arial Bold as font winChartViewer1.CDMLToolTipPrefix = "<*block,bgColor=60FFFFDD,roundedCorners=5,margin=5,edgeColor=000000*><*font=Arial Bold*>" ' Load the data loadData() ' Trigger the ViewPortChanged event to draw the chart winChartViewer1.updateViewPort(True, True) ' Configure the CViewPortControl to use transparent black for region outside the viewport, ' that Is, to darken the outside region. viewPortControl1.ViewPortExternalColor = Color.FromArgb(80, 0, 0, 0) viewPortControl1.ViewPortBorderColor = Color.FromArgb(80, 255, 255, 255) viewPortControl1.SelectionBorderColor = Color.FromArgb(80, 255, 255, 255) ' Draw the full thumbnail chart for the ViewPortControl drawFullChart(viewPortControl1, winChartViewer1) ' Bind the winChartViewer1 to the viewPortControl1 viewPortControl1.Viewer = winChartViewer1 End Sub ' ' Load the data ' Private Sub loadData() ' The x And y coordinates of the grid dataX = New Double() {-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10} dataY = New Double() {-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10} ' The values at the grid points. In this example, we will compute the values using the ' formula z = x * sin(y) + y * sin(x). dataZ = New Double(dataX.Length * dataY.Length - 1) {} For yIndex As Integer = 0 To dataY.Length - 1 Dim y As Double = dataY(yIndex) For xIndex As Integer = 0 To dataX.Length - 1 Dim x As Double = dataX(xIndex) dataZ(yIndex * dataX.Length + xIndex) = x * Math.Sin(y) + y * Math.Sin(x) Next Next End Sub ' ' The ViewPortChanged event handler. This event occurs if the user scrolls or zooms in ' or out the chart by dragging or clicking on the chart. It can also be triggered by ' calling WinChartViewer.updateViewPort. ' Private Sub winChartViewer1_ViewPortChanged(ByVal sender As Object, ByVal e As WinViewPortEventArgs) Handles winChartViewer1.ViewPortChanged ' In addition to updating the chart, we may also need to update other controls that ' changes based on the view port. updateControls(winChartViewer1) ' Update the chart if necessary If e.NeedUpdateChart Then drawChart(winChartViewer1) End If End Sub ' ' Update controls when the view port changed ' Private Sub updateControls(ByVal viewer As WinChartViewer) ' Synchronize the zoom bar value with the view port width/height zoomBar.Value = Math.Round(Math.Min(viewer.ViewPortWidth, viewer.ViewPortHeight) * zoomBar.Maximum) End Sub ' ' Draw the chart. ' Private Sub drawChart(ByVal viewer As WinChartViewer) ' Create an XYChart object 540 x 490 pixels in size Dim c As XYChart = New XYChart(540, 490) ' Set the plotarea at (50, 40) And of size 400 x 400 pixels. Use semi-transparent black ' (7f000000) dotted lines for both horizontal And vertical grid lines c.setPlotArea(50, 40, 400, 400, -1, -1, -1, c.dashLineColor(&H7F000000, Chart.DotLine), -1) ' Enable clipping mode to clip the part of the data that Is outside the plot area. c.setClipping() ' Add a title to the chart using 15 points Arial Bold Italic font c.addTitle("z = x * sin(y) + y * sin(x) ", "Arial Bold Italic", 15) ' Set x-axis And y-axis title using 12 points Arial Bold Italic font c.xAxis().setTitle("X-Axis Title Place Holder", "Arial Bold Italic", 12) c.yAxis().setTitle("Y-Axis Title Place Holder", "Arial Bold Italic", 12) ' Set x-axis And y-axis labels to use Arial Bold font c.xAxis().setLabelStyle("Arial Bold") c.yAxis().setLabelStyle("Arial Bold") ' When auto-scaling, use tick spacing of 40 pixels as a guideline c.yAxis().setTickDensity(40) c.xAxis().setTickDensity(40) ' Add a contour layer using the given data Dim layer As ContourLayer = c.addContourLayer(dataX, dataY, dataZ) ' Move the grid lines in front of the contour layer c.getPlotArea().moveGridBefore(Layer) ' Add a color axis (the legend) in which the top left corner Is anchored at (470, 40). Set the ' length to 400 pixels And the labels on the right side. Dim cAxis As ColorAxis = layer.setColorAxis(470, 40, Chart.TopLeft, 400, Chart.Right) ' Add a title to the color axis using 12 points Arial Bold Italic font cAxis.setTitle("Color Legend Title Place Holder", "Arial Bold Italic", 12 ).setAlignment(Chart.Right) ' Set color axis labels to use Arial Bold font cAxis.setLabelStyle("Arial Bold") ' In this example, we have Not explicitly configured the full x And y range. In this case, ' the first time syncLinearAxisWithViewPort Is called, ChartDirector will auto-scale the axis ' And assume the resulting range Is the full range. In subsequent calls, ChartDirector will ' set the axis range based on the view port And the full range. viewer.syncLinearAxisWithViewPort("x", c.xAxis()) viewer.syncLinearAxisWithViewPort("y", c.yAxis()) ' To ensure the color Is consistent, we must keep the color axis the same when the zooming Or ' scrolling the chart. To do this, we save the color axis of the first chart And synchronize ' all future charts with this color axis. If IsNothing(firstChart) Then ' We need to save the first chart as well as the first color axis. Otherwise the first ' chart may get deleted, And this will delete the first color axis as well. firstChart = c firstColorAxis = cAxis Else cAxis.syncAxis(firstColorAxis) End If ' Display chart viewer.Chart = c ' Tooltip for the contour chart viewer.ImageMap = c.getHTMLImageMap("", "", "title='<*cdml*>X={x|2}<*br*>Y={y|2}<*br*>Z={z|2}'") End Sub ' ' Draw the full thumbnail chart and display it in the given ViewPortControl ' Private Sub drawFullChart(ByVal vpc As WinViewPortControl, ByVal viewer As WinChartViewer) ' Create an XYChart object 110 x 110 pixels in size Dim c As XYChart = New XYChart(110, 110) ' Set the plotarea to cover the entire chart. Disable grid lines by setting their colors ' to transparent. c.setPlotArea(0, 0, c.getWidth() - 1, c.getHeight() - 1, -1, -1, -1, Chart.Transparent, Chart.Transparent) ' Add a contour layer using the given data Dim layer As ContourLayer = c.addContourLayer(dataX, dataY, dataZ) layer.setContourColor(&HCF000000) ' To maintain color consistency, the color axis Is synchronized to that of the first chart. layer.colorAxis().syncAxis(firstColorAxis) ' The x And y axis scales reflect the full range of the view port c.xAxis().setLinearScale(viewer.getValueAtViewPort("x", 0), viewer.getValueAtViewPort("x", 1), Chart.NoValue) c.yAxis().setLinearScale(viewer.getValueAtViewPort("y", 0), viewer.getValueAtViewPort("y", 1), Chart.NoValue) ' Set the chart image to the viewport control vpc.Chart = c End Sub ' ' Pointer (Drag to Scroll) button event handler ' Private Sub pointerPB_CheckedChanged(ByVal sender As Object, ByVal e As EventArgs) _ Handles pointerPB.CheckedChanged If sender.Checked Then winChartViewer1.MouseUsage = WinChartMouseUsage.ScrollOnDrag End If End Sub ' ' Zoom In button event handler ' Private Sub zoomInPB_CheckedChanged(ByVal sender As Object, ByVal e As EventArgs) _ Handles zoomInPB.CheckedChanged If sender.Checked Then winChartViewer1.MouseUsage = WinChartMouseUsage.ZoomIn End If End Sub ' ' Zoom Out button event handler ' Private Sub zoomOutPB_CheckedChanged(ByVal sender As Object, ByVal e As EventArgs) _ Handles zoomOutPB.CheckedChanged If sender.Checked Then winChartViewer1.MouseUsage = WinChartMouseUsage.ZoomOut End If End Sub ' ' Save button event handler ' Private Sub savePB_Click(ByVal sender As Object, ByVal e As EventArgs) _ Handles savePB.Click ' The standard Save File dialog Dim fileDlg As SaveFileDialog = New SaveFileDialog() fileDlg.Filter = "PNG (*.png)|*.png|JPG (*.jpg)|*.jpg|GIF (*.gif)|*.gif|BMP (*.bmp)|*.bmp|" & "SVG (*.svg)|*.svg|PDF (*.pdf)|*.pdf" fileDlg.FileName = "chartdirector_demo" If fileDlg.ShowDialog() <> DialogResult.OK Then Return End If ' Save the chart If Not IsNothing(winChartViewer1.Chart) Then winChartViewer1.Chart.makeChart(fileDlg.FileName) End If End Sub ' ' ValueChanged event handler for zoomBar. Zoom in around the center point and try to ' maintain the aspect ratio ' Private Sub zoomBar_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles zoomBar.ValueChanged If Not winChartViewer1.IsInViewPortChangedEvent Then 'Remember the center point Dim centerX As Double = winChartViewer1.ViewPortLeft + winChartViewer1.ViewPortWidth / 2 Dim centerY As Double = winChartViewer1.ViewPortTop + winChartViewer1.ViewPortHeight / 2 'Aspect ratio and zoom factor Dim aspectRatio As Double = winChartViewer1.ViewPortWidth / winChartViewer1.ViewPortHeight Dim zoomTo As Double = CDbl(zoomBar.Value) / zoomBar.Maximum 'Zoom while respecting the aspect ratio winChartViewer1.ViewPortWidth = zoomTo * Math.Max(1, aspectRatio) winChartViewer1.ViewPortHeight = zoomTo * Math.Max(1, 1 / aspectRatio) 'Adjust ViewPortLeft and ViewPortTop to keep center point unchanged winChartViewer1.ViewPortLeft = centerX - winChartViewer1.ViewPortWidth / 2 winChartViewer1.ViewPortTop = centerY - winChartViewer1.ViewPortHeight / 2 'update the chart, but no need to update the image map yet, as the chart is still 'zooming and is unstable winChartViewer1.updateViewPort(True, False) End If End Sub End Class

[WPF - XAML] NetWPFCharts\CSharpWPFCharts\ContourZoomScrollWindow.xaml
<Window x:Class="CSharpWPFCharts.ContourZoomScrollWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:CSharpWPFCharts" mc:Ignorable="d" xmlns:ChartDirector="clr-namespace:ChartDirector;assembly=netchartdir" UseLayoutRounding="True" Title="Contour Plot Zooming and Scrolling" Loaded="Window_Loaded" SizeToContent="WidthAndHeight" ResizeMode="NoResize" > <DockPanel> <Label Content="Advanced Software Engineering" Height="25" DockPanel.Dock="Top" FontFamily="Arial" FontStyle="Italic" FontWeight="Bold" FontSize="13" Background="#FF02098D" Foreground="#FFF4FF04" HorizontalContentAlignment="Right"/> <StackPanel DockPanel.Dock="Left" Width="120" Background="#FFF0F0F0"> <RadioButton x:Name="pointerPB" Style="{StaticResource {x:Type ToggleButton}}" HorizontalContentAlignment="Left" Checked="pointerPB_Checked" > <StackPanel Orientation="Horizontal" Margin="5"> <Image Source="/icons/scroll_icon.png" Height="16" /> <TextBlock Text="Pointer" Margin="6,0,0,0" /> </StackPanel> </RadioButton> <RadioButton x:Name="zoomInPB" Style="{StaticResource {x:Type ToggleButton}}" HorizontalContentAlignment="Left" Checked="zoomInPB_Checked" > <StackPanel Orientation="Horizontal" Margin="5" > <Image Source="/icons/zoomin_icon.png" Height="16" /> <TextBlock Text="Zoom In" Margin="6,0,0,0" /> </StackPanel> </RadioButton> <RadioButton x:Name="zoomOutPB" Style="{StaticResource {x:Type ToggleButton}}" HorizontalContentAlignment="Left" Checked="zoomOutPB_Checked"> <StackPanel Orientation="Horizontal" Margin="5" > <Image Source="/icons/zoomout_icon.png" Height="16" /> <TextBlock Text="Zoom Out" Margin="6,0,0,0" /> </StackPanel> </RadioButton> <Button x:Name="savePB" Margin="0,32,0,0" HorizontalContentAlignment="Left" Click="savePB_Click"> <StackPanel Orientation="Horizontal" Margin="5" > <Image Source="/icons/save_icon.png" Height="16" /> <TextBlock Text="Save" Margin="6,0,0,0" /> </StackPanel> </Button> <TextBlock Text="Zoom Level" Margin="0,46,0,0" HorizontalAlignment="Center" FontWeight="Bold" /> <Slider x:Name="zoomBar" Margin="5" ValueChanged="zoomBar_ValueChanged" TickPlacement="Both" Foreground="#FF555555" /> <ChartDirector:WPFViewPortControl x:Name="ViewPortControl1" Width="110" Height="110" Margin="0,68,0,0" ViewPortExternalColor="#7F000000" ViewPortBorderColor="#7FFFFFFF" SelectionBorderColor="#7FFFFFFF" /> </StackPanel> <ChartDirector:WPFChartViewer x:Name="WPFChartViewer1" Width="540" Height="490" Margin="8" ViewPortChanged="WPFChartViewer1_ViewPortChanged" /> </DockPanel> </Window>

[WPF - C#] NetWPFCharts\CSharpWPFCharts\ContourZoomScrollWindow.xaml.cs
using System; using System.Windows; using System.Windows.Media; using Microsoft.Win32; using ChartDirector; namespace CSharpWPFCharts { /// <summary> /// Interaction logic for ContourZoomScrollWindow.xaml /// </summary> public partial class ContourZoomScrollWindow : Window { // Data points for the chart private double[] dataX; private double[] dataY; private double[] dataZ; // To ensure color consistency, we need to save the first color axis and // synchronize the color axis of the zoom-in charts with the this axis. XYChart firstChart; ColorAxis firstColorAxis; public ContourZoomScrollWindow() { InitializeComponent(); } private void Window_Loaded(object sender, RoutedEventArgs e) { // Set initial mouse usage for ChartViewer WPFChartViewer1.MouseUsage = WinChartMouseUsage.ScrollOnDrag; WPFChartViewer1.ScrollDirection = WinChartDirection.HorizontalVertical; // By default, when the user drags a rectangle to zoom in, the x and y dimensions can zoom by // different factors. KeepAspectRatio can be used to ensure the x and y dimensions are zoom by // the same factor, thereby keeping the aspect ratio unchanged. WPFChartViewer1.ZoomDirection = WinChartDirection.KeepAspectRatio; // Enable mouse wheel zooming by setting the zoom ratio to 1.1 per wheel event WPFChartViewer1.MouseWheelZoomRatio = 1.1; // Configure CDML tooltip to use a semi-transparent rounded rectangle as container and // Arial Bold as font WPFChartViewer1.CDMLToolTipPrefix = "<*block,bgColor=60FFFFDD,roundedCorners=5,margin=5,edgeColor=000000*><*font=Arial Bold*>"; // Load the data loadData(); // Trigger the ViewPortChanged event to draw the chart WPFChartViewer1.updateViewPort(true, true); // Configure the CViewPortControl to use transparent black for region outside the viewport, // that is, to darken the outside region. ViewPortControl1.ViewPortExternalColor = Color.FromArgb(80, 0, 0, 0); ViewPortControl1.ViewPortBorderColor = Color.FromArgb(80, 255, 255, 255); ViewPortControl1.SelectionBorderColor = Color.FromArgb(80, 255, 255, 255); // Draw the full thumbnail chart for the ViewPortControl drawFullChart(ViewPortControl1, WPFChartViewer1); // Bind the winChartViewer1 to the viewPortControl1 ViewPortControl1.Viewer = WPFChartViewer1; } // // Load the data // private void loadData() { // The x and y coordinates of the grid dataX = new double[] {-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; dataY = new double[] {-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // The values at the grid points. In this example, we will compute the values using the // formula z = x * sin(y) + y * sin(x). dataZ = new double[dataX.Length * dataY.Length]; for (int yIndex = 0; yIndex < dataY.Length; ++yIndex) { double y = dataY[yIndex]; for (int xIndex = 0; xIndex < dataX.Length; ++xIndex) { double x = dataX[xIndex]; dataZ[yIndex * dataX.Length + xIndex] = x * Math.Sin(y) + y * Math.Sin(x); } } } // // Pointer (Drag to Scroll) button event handler // private void pointerPB_Checked(object sender, RoutedEventArgs e) { WPFChartViewer1.MouseUsage = WinChartMouseUsage.ScrollOnDrag; } // // Zoom In button event handler // private void zoomInPB_Checked(object sender, RoutedEventArgs e) { WPFChartViewer1.MouseUsage = WinChartMouseUsage.ZoomIn; } // // Zoom Out button event handler // private void zoomOutPB_Checked(object sender, RoutedEventArgs e) { WPFChartViewer1.MouseUsage = WinChartMouseUsage.ZoomOut; } // // Save button event handler // private void savePB_Click(object sender, RoutedEventArgs e) { // The standard Save File dialog SaveFileDialog fileDlg = new SaveFileDialog(); fileDlg.Filter = "PNG (*.png)|*.png|JPG (*.jpg)|*.jpg|GIF (*.gif)|*.gif|BMP (*.bmp)|*.bmp|" + "SVG (*.svg)|*.svg|PDF (*.pdf)|*.pdf"; fileDlg.FileName = "chartdirector_demo"; var ret = fileDlg.ShowDialog(this); if (!(ret.HasValue && ret.Value)) return; // Save the chart if (null != WPFChartViewer1.Chart) WPFChartViewer1.Chart.makeChart(fileDlg.FileName); } // // The ViewPortChanged event handler. This event occurs if the user scrolls or zooms in // or out the chart by dragging or clicking on the chart. It can also be triggered by // calling WinChartViewer.updateViewPort. // private void WPFChartViewer1_ViewPortChanged(object sender, WPFViewPortEventArgs e) { // In addition to updating the chart, we may also need to update other controls that // changes based on the view port. updateControls(WPFChartViewer1); // Update the chart if necessary if (e.NeedUpdateChart) drawChart(WPFChartViewer1); } // // Update controls when the view port changed // private void updateControls(WPFChartViewer viewer) { // Synchronize the zoom bar value with the view port width/height zoomBar.Value = Math.Min(viewer.ViewPortWidth, viewer.ViewPortHeight) * zoomBar.Maximum; } // // ValueChanged event handler for zoomBar. Zoom in around the center point and try to // maintain the aspect ratio // private void zoomBar_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) { var viewer = WPFChartViewer1; if (!viewer.IsInViewPortChangedEvent) { //Remember the center point double centerX = viewer.ViewPortLeft + viewer.ViewPortWidth / 2; double centerY = viewer.ViewPortTop + viewer.ViewPortHeight / 2; //Aspect ratio and zoom factor double aspectRatio = viewer.ViewPortWidth / viewer.ViewPortHeight; double zoomTo = ((double)zoomBar.Value) / zoomBar.Maximum; zoomTo = Math.Max(zoomTo, Math.Min(viewer.ZoomInWidthLimit, viewer.ZoomInHeightLimit)); //Zoom while respecting the aspect ratio viewer.ViewPortWidth = zoomTo * Math.Max(1, aspectRatio); viewer.ViewPortHeight = zoomTo * Math.Max(1, 1 / aspectRatio); //Adjust ViewPortLeft and ViewPortTop to keep center point unchanged viewer.ViewPortLeft = centerX - viewer.ViewPortWidth / 2; viewer.ViewPortTop = centerY - viewer.ViewPortHeight / 2; //update the chart, but no need to update the image map yet, as the chart is still //zooming and is unstable viewer.updateViewPort(true, false); } } // // Draw the chart and display it in the given viewer // private void drawChart(WPFChartViewer viewer) { // Create an XYChart object 540 x 490 pixels in size XYChart c = new XYChart(540, 490); // Set the plotarea at (50, 40) and of size 400 x 400 pixels. Use semi-transparent black // (7f000000) dotted lines for both horizontal and vertical grid lines c.setPlotArea(50, 40, 400, 400, -1, -1, -1, c.dashLineColor(0x7f000000, Chart.DotLine), -1); // Enable clipping mode to clip the part of the data that is outside the plot area. c.setClipping(); // Add a title to the chart using 15 points Arial Bold Italic font c.addTitle("z = x * sin(y) + y * sin(x) ", "Arial Bold Italic", 15); // Set x-axis and y-axis title using 12 points Arial Bold Italic font c.xAxis().setTitle("X-Axis Title Place Holder", "Arial Bold Italic", 12); c.yAxis().setTitle("Y-Axis Title Place Holder", "Arial Bold Italic", 12); // Set x-axis and y-axis labels to use Arial Bold font c.xAxis().setLabelStyle("Arial Bold"); c.yAxis().setLabelStyle("Arial Bold"); // When auto-scaling, use tick spacing of 40 pixels as a guideline c.yAxis().setTickDensity(40); c.xAxis().setTickDensity(40); // Add a contour layer using the given data ContourLayer layer = c.addContourLayer(dataX, dataY, dataZ); // Move the grid lines in front of the contour layer c.getPlotArea().moveGridBefore(layer); // Add a color axis (the legend) in which the top left corner is anchored at (470, 40). Set the // length to 400 pixels and the labels on the right side. ColorAxis cAxis = layer.setColorAxis(470, 40, Chart.TopLeft, 400, Chart.Right); // Add a title to the color axis using 12 points Arial Bold Italic font cAxis.setTitle("Color Legend Title Place Holder", "Arial Bold Italic", 12) .setAlignment(Chart.Right); // Set color axis labels to use Arial Bold font cAxis.setLabelStyle("Arial Bold"); // In this example, we have not explicitly configured the full x and y range. In this case, // the first time syncLinearAxisWithViewPort is called, ChartDirector will auto-scale the axis // and assume the resulting range is the full range. In subsequent calls, ChartDirector will // set the axis range based on the view port and the full range. viewer.syncLinearAxisWithViewPort("x", c.xAxis()); viewer.syncLinearAxisWithViewPort("y", c.yAxis()); // To ensure the color is consistent, we must keep the color axis the same when the zooming or // scrolling the chart. To do this, we save the color axis of the first chart and synchronize // all future charts with this color axis. if (null == firstChart) { // We need to save the first chart as well as the first color axis. Otherwise the first // chart may get deleted, and this will delete the first color axis as well. firstChart = c; firstColorAxis = cAxis; } else cAxis.syncAxis(firstColorAxis); // Display chart viewer.Chart = c; // Tooltip for the contour chart viewer.ImageMap = c.getHTMLImageMap("", "", "title='<*cdml*>X={x|2}<*br*>Y={y|2}<*br*>Z={z|2}'"); } // // Draw the full thumbnail chart and display it in the given ViewPortControl // private void drawFullChart(WPFViewPortControl vpc, WPFChartViewer viewer) { // Create an XYChart object 110 x 110 pixels in size XYChart c = new XYChart(110, 110); // Set the plotarea to cover the entire chart. Disable grid lines by setting their colors // to transparent. c.setPlotArea(0, 0, c.getWidth() - 1, c.getHeight() - 1, -1, -1, -1, Chart.Transparent, Chart.Transparent); // Add a contour layer using the given data ContourLayer layer = c.addContourLayer(dataX, dataY, dataZ); layer.setContourColor(unchecked((int)0xcf000000)); // To maintain color consistency, the color axis is synchronized to that of the first chart. layer.colorAxis().syncAxis(firstColorAxis); // The x and y axis scales reflect the full range of the view port c.xAxis().setLinearScale(viewer.getValueAtViewPort("x", 0), viewer.getValueAtViewPort("x", 1), Chart.NoValue); c.yAxis().setLinearScale(viewer.getValueAtViewPort("y", 0), viewer.getValueAtViewPort("y", 1), Chart.NoValue); // Set the chart image to the viewport control vpc.Chart = c; } } }