The new raster series of Visiblox Charts provide a massive boost in performance. See here a chart streaming thousands of points smoothly and allowing user interaction.
You can zoom with the right mouse button and pan with the left.
XAML + CODE +
<UserControl x:Class="Visiblox.Charts.Examples.RasterLineSeries.RasterLineSeriesExample"
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:charts="clr-namespace:Visiblox.Charts;assembly=Visiblox.Charts"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<UserControl.Resources>
<!--This is the style that we will add to the plot area to fill the background-->
<Style TargetType="Grid" x:Key="PlotAreaStyle">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0.5,1" EndPoint="0.5,0">
<GradientStop Color="#FF256C98" Offset="0" />
<GradientStop Color="#FF104066" Offset="0.7" />
<GradientStop Color="#FF00142C" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
<!--This adds a border around the chart with a nice drop shadow effect to make the chart look indented-->
<Style TargetType="Border" x:Key="PlotAreaBorderStyle">
<Setter Property="BorderBrush" Value="#000718" />
<Setter Property="BorderThickness" Value="3" />
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect BlurRadius="9" Direction="304" ShadowDepth="5" Color="Black" />
</Setter.Value>
</Setter>
</Style>
<!--The style for the chart's title-->
<Style TargetType="TextBlock" x:Key="TitleStyle">
<Setter Property="FontSize" Value="22" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Padding" Value="10,0,0,0" />
</Style>
<!--Let's make our axes blue-->
<Style TargetType="Line" x:Key="AxisLineStyle">
<Setter Property="Stroke" Value="#FF3479A3" />
<Setter Property="StrokeThickness" Value="2" />
</Style>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<!--There is a border around all our controls with a nice '80s platic beige-->
<Border Background="#BBBBAF" BorderThickness="1" CornerRadius="5" Padding="10,0, 10, 10" BorderBrush="#827C5C">
<StackPanel Orientation="Vertical" Width="600">
<!--The chart with streaming mode and 2 fast line series-->
<!-- Ultimate Trial users should add 'ValidationKey="ENTER TRIAL LICENSE KEY HERE"' to each Chart declaration. -->
<charts:Chart x:Name="Chart" StreamingMode="StreamingOnX" Height="400" Title="Oscilloscope" TitleStyle="{StaticResource TitleStyle}"
Margin="0,20,0,10" PlotAreaStyle="{StaticResource PlotAreaStyle}"
Loaded="Chart_Loaded" LegendVisibility="Collapsed" PlotAreaBorderStyle="{StaticResource PlotAreaBorderStyle}">
<charts:Chart.Series>
<charts:RasterLineSeries AntiAliasingEnabled="True">
<charts:RasterLineSeries.DefaultStyle>
<charts:LineSeriesStyle LineStroke="#FFFFD56B" LineStrokeThickness="2" PointFill="#FFFFD56B" AreaFill="#FFFFD56B" PointSize="1" PointStroke="#FFFFD56B"/>
</charts:RasterLineSeries.DefaultStyle>
</charts:RasterLineSeries>
<charts:RasterLineSeries AntiAliasingEnabled="True">
<charts:RasterLineSeries.DefaultStyle>
<charts:LineSeriesStyle LineStroke="#FF60D1CB" LineStrokeThickness="2" PointFill="#FF60D1CB" AreaFill="#FF60D1CB" PointSize="1" PointStroke="#FF60D1CB"/>
</charts:RasterLineSeries.DefaultStyle>
</charts:RasterLineSeries>
</charts:Chart.Series>
<charts:Chart.XAxis>
<charts:LinearAxis ShowLabels="False" ShowMajorGridlines="False" MajorTickStyle="{StaticResource AxisLineStyle}" AxisLineStyle="{StaticResource AxisLineStyle}" ShowMinorTicks="False">
<charts:LinearAxis.Range>
<charts:DoubleRange Minimum="0" Maximum="12.56" />
</charts:LinearAxis.Range>
</charts:LinearAxis>
</charts:Chart.XAxis>
<charts:Chart.YAxis>
<charts:LinearAxis ShowLabels="False" ShowMajorGridlines="False" MajorTickStyle="{StaticResource AxisLineStyle}" AxisLineStyle="{StaticResource AxisLineStyle}" ShowMinorTicks="False">
<charts:LinearAxis.Range>
<charts:DoubleRange Minimum="-1.1" Maximum="1.1" />
</charts:LinearAxis.Range>
</charts:LinearAxis>
</charts:Chart.YAxis>
</charts:Chart>
<!--A slider to control the speed of the chart-->
<Border BorderBrush="Gray" BorderThickness="1" CornerRadius="5" Margin="10" Padding="10" Width="500">
<StackPanel Orientation="Horizontal">
<TextBlock FontWeight="Bold">Update Freq. (Hz):</TextBlock><Slider x:Name="FrequencySlider" Minimum="200" Maximum="500" Value="200" Width="250" />
</StackPanel>
</Border>
<!--Some controls for manipulating the two series independently-->
<StackPanel Orientation="Horizontal">
<Border BorderBrush="Gray" BorderThickness="1" CornerRadius="5" Margin="10" Padding="10">
<StackPanel>
<TextBlock FontWeight="Bold">Series 1</TextBlock>
<StackPanel Orientation="Horizontal">
<TextBlock>Phase:</TextBlock>
<Slider x:Name="S1PhaseSlider" Minimum="0" Maximum="3.1415" LargeChange="0.4" SmallChange="0.4" Value="0" Width="215" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock>Period:</TextBlock>
<Slider x:Name="S1Period" Minimum="0.1" Maximum="4" LargeChange="0.5" SmallChange="0.5" Value="1" Width="215" />
</StackPanel>
</StackPanel>
</Border>
<Border BorderBrush="Gray" BorderThickness="1" CornerRadius="5" Margin="10" Padding="10">
<StackPanel>
<TextBlock FontWeight="Bold">Series 2</TextBlock>
<StackPanel Orientation="Horizontal">
<TextBlock>Phase:</TextBlock>
<Slider x:Name="S2PhaseSlider" Minimum="0" Maximum="3.1415" Value="0.784" LargeChange="1" Width="215" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock>Period:</TextBlock>
<Slider x:Name="S2Period" Minimum="0.1" Maximum="4" LargeChange="1" Value="1" Width="215" />
</StackPanel>
</StackPanel>
</Border>
</StackPanel>
</StackPanel>
</Border>
</Grid>
</UserControl>
^ Back To Top
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Threading;
namespace Visiblox.Charts.Examples.RasterLineSeries
{
/// <summary>
/// This example demonstrates the use of the StreamingMode, as well as the high-performance raster series
/// </summary>
public partial class RasterLineSeriesExample : UserControl
{
private const double _increment = 0.1;
private const int _updateTimeInMilliseconds = 15;
private double _startValue = 0;
private double _dataMax = 4 * Math.PI;
private DateTime _lastPointTime = new DateTime();
//define some data series that we'll update later on
DataSeries<double, double> _dataSeries1 = new DataSeries<double, double>();
DataSeries<double, double> _dataSeries2 = new DataSeries<double, double>();
DispatcherTimer _timer = new DispatcherTimer();
/// <summary>
/// Default constructor
/// </summary>
public RasterLineSeriesExample()
{
InitializeComponent();
//Fill up our data series
CreateInitialData(_dataSeries1, S1Period.Value, S1PhaseSlider.Value);
Chart.Series[0].DataSeries = _dataSeries1;
CreateInitialData(_dataSeries2, S2Period.Value, S2PhaseSlider.Value);
Chart.Series[1].DataSeries = _dataSeries2;
//update the start value so we add data from the correct value later on
_startValue = _dataMax + _increment;
//start our timer for updates
_lastPointTime = DateTime.MinValue;
_timer.Interval = TimeSpan.FromMilliseconds(_updateTimeInMilliseconds);
_timer.Tick += new EventHandler(Timer_Tick);
_timer.Start();
}
/// <summary>
/// Fills up the data series with data from 0
/// </summary>
/// <param name="dataSeries">The dataseries to fill</param>
/// <param name="periodFactor">The multiplier on the standard period of the sine wave</param>
/// <param name="phaseOffset">The phase offset of the sine wave to plot</param>
private void CreateInitialData(DataSeries<double, double> dataSeries, double periodFactor, double phaseOffset)
{
dataSeries.Clear();
FillData(dataSeries, periodFactor, phaseOffset, 0, false);
}
/// <summary>
/// Add more data upto the new _dataMax value
/// </summary>
/// <param name="dataSeries">The dataseries to fill</param>
/// <param name="periodFactor">The multiplier on the standard period of the sine wave</param>
/// <param name="phaseOffset">The phase offset of the sine wave to plot</param>
/// <param name="startValue">The x value at which to start plotting.</param>
/// <param name="removeOld">
/// If true for every value we add to the end of the series we remove one from the start to avoid running out of memory over time
/// </param>
private void FillData(DataSeries<double, double> dataSeries, double periodFactor, double phaseOffset, double startValue, bool removeOld)
{
double x = startValue + _increment;
for (; x < _dataMax; x += _increment)
{
dataSeries.Add(new DataPoint<double, double>(x + phaseOffset, Math.Sin(periodFactor * x)));
if(removeOld)
dataSeries.RemoveAt(0);
}
}
/// <summary>
/// The method to invoke from the timer, which adds more data to the series based on the values of the sliders
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Timer_Tick(object sender, EventArgs e)
{
DateTime now = DateTime.Now;
if (_lastPointTime == DateTime.MinValue)
_lastPointTime = now;
var span = (now - _lastPointTime).TotalMilliseconds;
if (span > _updateTimeInMilliseconds)
{
var pointsPerSecond = FrequencySlider.Value;
int points = (int) ((span / 1000d) * pointsPerSecond);
if (points > 0)
{
_dataMax += _increment * points;
FillData(_dataSeries1, S1Period.Value, S1PhaseSlider.Value, _startValue, true);
FillData(_dataSeries2, S2Period.Value, S2PhaseSlider.Value, _startValue, true);
_startValue = _dataMax;
_lastPointTime = now;
}
}
}
/// <summary>
/// When we first load the chart we offset the axes so that they form a quadrant plot rather than the standard axes to the left and
/// below the chart
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Chart_Loaded(object sender, RoutedEventArgs e)
{
//place the axes in the middle of the plot area
FrameworkElement fe = (Chart.XAxis as FrameworkElement);
FrameworkElement fe2 = (Chart.YAxis as FrameworkElement);
double zero = Chart.YAxis.GetDataValueAsRenderPositionWithoutZoom(0);
fe.RenderTransform = new TranslateTransform() { Y = -zero, X = 0 };
fe2.RenderTransform = new TranslateTransform() { X = (Chart.ActualWidth / 2), Y = 0 };
}
}
}
^ Back To Top

