In this blog post I look at how to add a new series type to the Visiblox charts by creating my own series type which renders a smoothed line using a Bézier curve.
This blog post describes how to create a new series type for the Visiblox charts, a spline series. The example below shows the new series type in action, with the various spline control points rendered (just for fun!):
Creating a New Series Type
The visual representation of a Visiblox
DataSeries is the responsibility of a chart series, as defined by the
IChartSeries interface. However, the abstract baseclass
ChartSeriesBase is most often the best place to start when creating a new series type.
The first step towards creating my smoothed series type is to create a
ChartSeries subclass. The only abstract method that we must implement is
InvalidateInternal, and it is here that we will place our logic to create the series:
A template also has to be supplied for the series in the generic.xaml file. The
ChartSeriesBase requires that a
ZoomCanvas element is located within the template as follows:
That's all the boiler plate code out of the way with, let's get down to writing our series implementation.
A Simple Line Series
We'll start by creating a straight-line implementation. Within the
UpdateInternal method the following code constructs a Path instance and adds it to the
Let's look at this code in detail. The method
GetRenderPoints creates a list of points which indicate the location where each datapoint should be rendered on the chart. The series has a property
DataSeries which is the data being rendered and we enumerate over each of the points in this series. The chart series also has a relationship to the X & Y axes, and it is each axis which is responsible for the converting the X & Y components of our data into a 'screen' coordinate. This is performed via the (succinctly named!)
GetDataValueAsRenderPositionWithoutZoom method (more on this later).
The list of points returned by the
GetRenderPoints method are used to define a path (a path is defined by a geometry which is defined by one or more figures which themselves are defined by one or more segments ... phew!). This path is styled and added to the
RootZoomCanvas, with the attached property
IsScaledPath set to true.
The net result of the above code is that we now have a fully functional line series which integrates with the Visiblox behaviours such as pan & zoom:
Now back to this ZoomCanvas ...
The Visiblox charts have been optimised for performance and providing user interactions. A common requirement for interactive charts is the ability to pan and zoom. Both of these can be implemented by changing the range of the X and Y axes (for example a pan operation would result in a fixed offset being applied to the axis range), however this would result in the chart having to recomputed the location of all of each of the points being rendered. As an alternative, the Visiblox axes have a Zoom property which is handled by the
ZoomCanvas directly. When a Zoom is applied, the required
RenderTransforms are applied to the elements in the canvas, i.e. the series, resulting in a rapid update of chart. When using the
ZoomCanvas you have to indicate whether the element added is based on a geometry, which should be transformed (i.e. a zoom makes the geometry appear bigger), or whether the element location should simply by updated to reflect the current zoom, for example, when you zoom in to a chart typically you would want the datapoints to maintain a fixed size.
Gergely Orosz describes the ZoomCanvas in more detail in his recent post on Panning & Zooming the charts.
To illustrate how this works, we will add points to our series which are not scaled as we zoom into the chart. The
InvalidateInternal method is updated with the additional code to render the points, note that the ellipses have a
RenderTransform applied so that their centre is anchored to the correct location on the
You can see the series in action below:
Creating a Smoothed Curve
So far we have created a simple line series; however the aim of this article is to create a smoothed line series. The
Figure within our
PathGeometry is currently composed of a number of straight line segments, in order to create a smoothed line we need to use curved segments. Silverlight and WPF both support Bézier curves and these can be used to specify a curved path geometry. A Bézier curve has four points, a start point, an end point and two control points which define the curvature:
In order to create a curved path for our series we need to determine suitable control points for our Bézier segments. After a bit of googling I stumbled upon an excellent article by Kerem Kat which describes how to use Bézier curves with Bing Maps. The article sourcecode has a method that will return the data points required to render a smoothed line as a Bézier Curve, using Catmull-Rom splines.
Modifying our series to use Bézier Curves, via the
GetBezierPoints method described in the above article, is pretty straightforward:
Tension property which is passed to the
GetBezierPoints method, this is a property of Catmull-Rom splines which describes how 'smoothed' the line should be. The
SplineSeries exposes this as a dependency property, as shown in the example below:
You can see the effect of changing the tension on the spline:
For a Bit Of Fun ...
I thought it would be fun to visualise the Catmull-Rom spline construction by also rendering the control points for each Bézier curve. You can see the results below:
You can download the full sourcecode for the article here: VisibloxSplineSeries.zip
To run the examples you will also need to download the Visiblox charts from www.visiblox.com.
Regards, Colin E.