Measurement Studio for .NET Languages

cancel
Showing results for 
Search instead for 
Did you mean: 

Interpolate every pixel on IntensityGraph (WPF)

Solved!
Go to solution

The IntensityGraph appears to be interpolating pixel color for every point along the X axis, but not along the Y axis. How can I achieve this? I was previously using the CWGraph3D which did this automatically, but we can no longer support the ActiveX control in this application.

 

 

scan.png

0 Kudos
Message 1 of 12
(6,871 Views)

I tried to reproduce your setup from the screenshot with the code below using Measurement Studio 2013, but I did not get the banding shown. If you could, please post some example data and display code that produces the issue.



MainPage.xaml
<Window x:Class="IntensityGraphQ.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ni="http://schemas.ni.com/controls/2009/xaml/presentation"
        Title="MainWindow" Height="480" Width="640" >
    <Grid>
        <ni:IntensityGraph x:Name="_graph">
            <ni:IntensityGraph.VerticalAxis>
                <ni:AxisDouble x:Name="verticalAxis1" Orientation="Vertical"/>
            </ni:IntensityGraph.VerticalAxis>
            <ni:IntensityGraph.HorizontalAxis>
                <ni:AxisInt32 x:Name="horizontalAxis1" Orientation="Horizontal"/>
            </ni:IntensityGraph.HorizontalAxis>
            <ni:IntensityGraph.ColorScale>
                <ni:ColorScale>
                    <ni:ColorScale.Markers>
                        <ni:ColorScaleMarker Color="Black" Value="-8.97"/>
                        <ni:ColorScaleMarker Color="DarkBlue" Value="-6.59"/>
                        <ni:ColorScaleMarker Color="Purple" Value="-4.32"/>
                        <ni:ColorScaleMarker Color="DarkViolet" Value="-2.04"/>
                        <ni:ColorScaleMarker Color="Red" Value="0.24"/>
                        <ni:ColorScaleMarker Color="Tomato" Value="2.52"/>
                        <ni:ColorScaleMarker Color="Orange" Value="4.8"/>
                        <ni:ColorScaleMarker Color="PeachPuff" Value="7.08"/>
                        <ni:ColorScaleMarker Color="White" Value="9.36"/>
                        <ni:ColorScaleMarker Color="White" Value="11.74"/>
                    </ni:ColorScale.Markers>
                </ni:ColorScale>
            </ni:IntensityGraph.ColorScale>
        </ni:IntensityGraph>
    </Grid>
</Window>


MainPage.xaml.cs
using System.Windows;

namespace IntensityGraphQ {
    public partial class MainWindow : Window {
        public MainWindow( ) {
            InitializeComponent( );

            int rows = 680;
            int columns = 330;
            double spread = rows * columns;
            var range = _graph.ColorScale.Range;
            double delta = range.Maximum - range.Minimum;

            double[,] data = new double[rows, columns];
            for( int i = 0; i < rows; i++ )
                for( int j = 0; j < columns; j++ )
                    data[i, j] = i * j * delta / spread + range.Minimum;

            _graph.DataSource = data;
        }
    }
}

~ Paul H
0 Kudos
Message 2 of 12
(6,862 Views)

Hi Paul, using the same XAML as you, run the following.

 

            InitializeComponent();

            int rows = 680;
            int columns = 330;
            double spread = rows * columns;
            var range = _graph.ColorScale.Range;
            double delta = range.Maximum - range.Minimum;

            var xSpacingInInches = 0.125;
            var ySpacingInInches = 4.5;

            var data = new Point3D[rows * columns];
            for (int i = 0; i < rows; i++)
                for (int j = 0; j < columns; j++)
                    data[i * columns + j] = new Point3D(i * xSpacingInInches, j * ySpacingInInches, i * j * delta / spread + range.Minimum);
                        
            _graph.DataSource = data; 

 

My data is taken along a surface in inches in both directions.

0 Kudos
Message 3 of 12
(6,855 Views)

Thanks for the update!


When given a sparse data type like Point3D, the IntensityGraph relies on the DefaultHorizontalInterval and DefaultVerticalInterval properties to control how data is drawn.


In the example, if you update the horizontal axis to be an AxisDouble in MainPage.xaml, and update the code in MainPage.xaml.cs to match the following, the graph should render without gaps:


    ...
    var xSpacingInInches = 0.125;
    var ySpacingInInches = 4.5;

    var data = ...;

    _graph.DefaultHorizontalInterval = xSpacingInInches;
    _graph.DefaultVerticalInterval = ySpacingInInches;
    _graph.DataSource = data;

~ Paul H
Message 4 of 12
(6,853 Views)

Thanks! That works good for evenly spaced data, how can we handle uneven data sets?

 

For example, the first 100 data points are spaced at 0.5in, the next 200 at 2.0in, the next 100 points at 0.5in (along the y axis)?

0 Kudos
Message 5 of 12
(6,848 Views)

Unfortunately, the intensity graph does not currently support interpolation between data points in the plot area. The easiest way to achieve that effect would be to introduce additional samples at 0.5 inch intervals within the 2.0 inch sample area.

~ Paul H
0 Kudos
Message 6 of 12
(6,841 Views)

Would it be possible to stack multiple IntensityPlots in a single graph? 1 plot for each set of intervals?

0 Kudos
Message 7 of 12
(6,839 Views)
Solution
Accepted by topic author cbgapac

Ah, excellent point! I had completely overlooked that idea.


Here is a mockup using a graph with two plots that have different vertical intervals:


MainWindow.xaml
<Window x:Class="IntensityGraphQ.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ni="http://schemas.ni.com/controls/2009/xaml/presentation"
        Title="MainWindow" Height="480" Width="640" >
    <Grid>
        <ni:Graph x:Name="_graph" RenderMode="Raster">
            <ni:Graph.Resources>
                <ni:ColorScale x:Key="colorScale">
                    <ni:ColorScale.Markers>
                        <ni:ColorScaleMarker Color="Black" Value="-8.97"/>
                        <ni:ColorScaleMarker Color="DarkBlue" Value="-6.59"/>
                        <ni:ColorScaleMarker Color="Purple" Value="-4.32"/>
                        <ni:ColorScaleMarker Color="DarkViolet" Value="-2.04"/>
                        <ni:ColorScaleMarker Color="Red" Value="0.24"/>
                        <ni:ColorScaleMarker Color="Tomato" Value="2.52"/>
                        <ni:ColorScaleMarker Color="Orange" Value="4.8"/>
                        <ni:ColorScaleMarker Color="PeachPuff" Value="7.08"/>
                        <ni:ColorScaleMarker Color="White" Value="9.36"/>
                        <ni:ColorScaleMarker Color="White" Value="11.74"/>
                    </ni:ColorScale.Markers>
                </ni:ColorScale>
            </ni:Graph.Resources>

            <ni:Graph.Plots>
                <ni:Plot>
                    <ni:IntensityPlotRenderer DefaultVerticalInterval="0.5"
                                              ColorScale="{StaticResource colorScale}" />
                </ni:Plot>
                <ni:Plot>
                    <ni:IntensityPlotRenderer DefaultVerticalInterval="2.0"
                                              ColorScale="{StaticResource colorScale}" />
                </ni:Plot>
            </ni:Graph.Plots>
        </ni:Graph>
    </Grid>
</Window>


MainWindow.xaml.cs
using NationalInstruments.Controls;
using System.Windows;
using System.Windows.Media.Media3D;

namespace IntensityGraphQ {
    public partial class MainWindow : Window {
        public MainWindow( ) {
            InitializeComponent( );

            int rows = 50;
            int columns = 200;
            double spread = rows * columns;
            var colorScale = (ColorScale)_graph.Resources["colorScale"];
            var range = colorScale.Range;
            double delta = range.Maximum - range.Minimum;

            double y1Spacing = 0.5;
            double y2Spacing = 2.0;
            double y1Offset = 2 * columns - y2Spacing;

            var data1 = new Point3D[rows * columns];
            var data2 = new Point3D[rows * columns];
            for( int i = 0; i < rows; ++i )
                for( int j = 0; j < columns; ++j ) {
                    double y1 = j * y1Spacing + (j > columns / 2 ? y1Offset : 0);
                    double y2 = j * y2Spacing + y1Spacing * columns / 2;
                    double v = i * j * delta / spread + range.Minimum;
                    data1[i * columns + j] = new Point3D( i, y1, v );
                    data2[i * columns + j] = new Point3D( i, y2, v );
                }

            _graph.Data[0] = data1;
            _graph.Data[1] = data2;
        }
    }
}

~ Paul H
Message 8 of 12
(6,831 Views)

Thanks for the help Paul, I actually just got this working myself. One bug I have found is changing the RenderMode to "Vector" or "Auto" renders the plot, then the plot dissapears after 3 seconds!

0 Kudos
Message 9 of 12
(6,828 Views)

Glad to hear you got it working!


Regarding RenderMode, using Vector is expected to override the preferences of the renderers. For the default Auto mode though, the graph should detect this case and automatically stay in Raster. I have created a task to fix the Auto mode behavior.

~ Paul H
0 Kudos
Message 10 of 12
(6,824 Views)