Measurement Studio for .NET Languages

Showing results for 
Search instead for 
Did you mean: 

3D data in wpf graph

Go to solution



We are trying to visualize 3D data using PointPlotRenderer in a WPF graph . The data is stored in an ObservabaleCollection containing Point3D entries. Is there any way to use the last coordinate to set the color of each point? I guess you will need to create your own renderer? If this is possible do you have any examples of how this can be done?

0 Kudos
Message 1 of 7

I have attached an example of a custom plot renderer that uses the third dimension of data and a color scale to draw colored points in a WPF graph. Here is how you can add the renderer to your graph in XAML:


                    <ni:ColorScaleMarker Value="0.0" Color="White" />
                    <ni:ColorScaleMarker Value="50.0" Color="Blue" />
                    <ni:ColorScaleMarker Value="100.0" Color="Black" />



~ Paul H
0 Kudos
Message 2 of 7

Thanks for a quick solution Paul, the code runs fine! However, I see that if I add 10k points the response time (zoom, window resize, etc.) gets very high compared to the PointPlotRenderer. Is this because the default renderer has a more efficient implementation?

0 Kudos
Message 3 of 7

I had a further look at the code, and I see that the RenderTarget provides a DrawShapes function and I guess this method is used in the default render? Since this method only allow for a single option and not a table, the only solution is to iterate trough each point using DrawShape and set individual options. I guess this is what makes the plot unresponsive when the number of points gets high?

0 Kudos
Message 4 of 7

Yes, making a lot of individual DrawShape calls is much less efficient than a single DrawShapes call. Depending on the granularity of your color scale and how IsInterpolated is set, you might be able to group points by matching color, and make a smaller number of DrawShapes calls with those groups, to improve performance.

~ Paul H
0 Kudos
Message 5 of 7
Accepted by OddvarC

Here is a quick example implementation of same-color grouping:


protected override void RenderGraphCore( PlotRenderArgs renderArgs ) {
    var colorScale = this.ColorScale;
    var target = renderArgs.RenderTarget;
    var xValues = renderArgs.RelativeData[0];
    var yValues = renderArgs.RelativeData[1];
    var zValues = renderArgs.RelativeData[2];
    var groups = new Dictionary<Color, (RenderTargetOptions, List<double>, List<double>)>( );
    for( int i = 0; i < xValues.Size; ++i ) {
        Color color = colorScale.RelativeValueToColor( zValues[i] );
        if( groups.TryGetValue( color, out var group ) ) {
            group.Item2.Add( xValues[i] );
            group.Item3.Add( yValues[i] );

        var options = new RenderTargetOptions( null,
            RenderTargetOption.CreateValue( RenderTargetOptionsProperty.Fill, new SolidColorBrush( color ) ),
            RenderTargetOption.CreateValue( RenderTargetOptionsProperty.Stroke, Brushes.Black ),
            RenderTargetOption.CreateValue( RenderTargetOptionsProperty.StrokeThickness, 1.0 ) );
        groups.Add( color, (options, new List<double> { xValues[i] }, new List<double> { yValues[i] }) );

    Size shapeSize = new Size( 10, 10 );
    foreach( var (options, xs, ys) in groups.Values ) {
        using(var xBuffer = BufferPool.Default.GetBuffer(xs, RelativeValueUnit.Instance))
        using(var yBuffer = BufferPool.Default.GetBuffer(ys, RelativeValueUnit.Instance))
            target.DrawShapes( options, xBuffer, yBuffer, PointShape.Ellipse, shapeSize  );


Testing on ten thousand random points, I saw a notable improvement. Hopefully this will work with your scenario!


(Note that it does not preserve ordering, so points will appear in whatever order they happen to be returned by the dictionary.)

~ Paul H
0 Kudos
Message 6 of 7

Wow Paul, this really improved the code. Works perfect for my data! Thanks a lot for your quick and impressive help!

0 Kudos
Message 7 of 7