12-17-2008 08:33 AM
Hi,
I can't seem to find an example where I can create a custom plot class. I need to be able to color the line of the plot as a function of it's Y value, and make it look like a smooth gradient. Ideally I'd like to change the point size of the line as well. This would allow me to "plot" 3 variables using a 2D graph. I've started (VB.Net):
Imports NationalInstruments.UI
Public Class clCustomPlotInherits ScatterPlot
Public Sub New()MyBase.New()
End Sub
Protected Overrides Sub OnBeforeDraw(ByVal sender As Object, ByVal e As NationalInstruments.UI.BeforeDrawXYPlotEventArgs)End Sub
End Class
But VS tells me that:
Error MeasStudioGraphLineColour sub 'OnBeforeDraw' cannot be declared 'Overrides' because it does not override a sub in a base class.
Thanks for your help,
Nicolas
Solved! Go to Solution.
12-17-2008 08:41 AM
Hello Nicolas,
You will actually want to create your own custom LineStyle class. There is an excellent example of how to do that in the Measurement Studio help topic entitled "Creating a Custom Line Style for the Measurement Studio Web Forms Graph .NET Controls" Also, you may want to check out a forum I recently answered using a similar method - found here. Let me know if you have any questions.
NickB
National Instruments
12-17-2008 09:01 AM
12-17-2008 09:14 AM
The forum wouldn't let me attach a zip with my code so here it is (gr is a ScatterGraph on the form which initially contains no plot):
12-17-2008 09:25 AM
I've now tried implementing the example
Creating a Custom Line Style for the Measurement Studio Windows Forms Graph .NET Controls
and get the same error. I'm using VS2008. Can you replicate this on your side?
12-17-2008 09:46 AM
I've now tride implementing it in C#. I get the exact same error so I must be doing something wrong! Here's the code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
double[] x = new double[1000];
double[] y = new double[1000];
for (int i = 0; i < 1000; i++)
{
x[i]=i;
y[i] = 5 + (5 * Math.Cos(i * Math.PI / 180)) * ((i + 1) / 1000);
}
GradientLineStyle GL;
GL=new GradientLineStyle();
scatterPlot1.LineStyle = GL;
scatterPlot1.PlotXY(x, y);
}
}
public class GradientLineStyle : NationalInstruments.UI.LineStyle
{
private Color _startColor;
private Color _endColor;
public GradientLineStyle()
: this(Color.Red, Color.Blue)
{
}
public GradientLineStyle(Color startColor, Color endColor)
{
_startColor = startColor;
_endColor = endColor;
}
public Color StartColor
{
get
{
return _startColor;
}
set
{
_startColor = value;
}
}
public Color EndColor
{
get
{
return _endColor;
}
set
{
_endColor = value;
}
}
public override bool IsContextDependent
{
get
{
// Return true to indicate that CreatePen
// should be called for any change in context
return true;
}
}
public override Pen CreatePen(object context, NationalInstruments.UI.LineStyleDrawArgs args)
{
Rectangle bounds = args.ContextBounds;
// Add 1 to width and height of context bounds to include
// the right and bottom edge of the rectangle in the linear
// gradient brush
bounds.Width += 1;
bounds.Height += 1;
using (Brush brush = new LinearGradientBrush(bounds, StartColor, EndColor, LinearGradientMode.Vertical))
{
return new Pen(brush, args.Width);
}
}
}
12-17-2008 11:03 AM
I got it working! For all those interested, here is a VB.Net custom ScatterPlot which will show you how to control/color every step of the line.
Imports NationalInstruments.UI
Imports System.Drawing
Imports System.Drawing.Drawing2D
Public Class clCustomScatterPlot
Inherits ScatterPlot
Private dblMin As Double
Private dblMax As Double
Private colMinColour As System.Drawing.Color
Private colMaxColour As System.Drawing.Color
Public Sub New(ByVal MinValue As Double, ByVal MaxValue As Double, _
ByVal MinValueColour As System.Drawing.Color, ByVal MaxValueColour As System.Drawing.Color)
MyBase.New()
' no checking is done for the fact that MinValue<MaxValue
dblMin = MinValue
dblMax = MaxValue
colMinColour = MinValueColour
colMaxColour = MaxValueColour
End Sub
Protected Overrides Sub OnBeforeDraw(ByVal e As BeforeDrawXYPlotEventArgs)
' Clip data, iterate through clipped data, map, and draw.
Dim plot As XYPlot = e.Plot
Dim clippedXData() As Double = Nothing
Dim clippedYData() As Double = Nothing
plot.ClipDataPoints(clippedXData, clippedYData)
For i As Integer = 0 To clippedXData.Length - 2
Dim x1 As Double = clippedXData(i)
Dim x2 As Double = clippedXData(i + 1)
Dim y1 As Double = clippedYData(i)
Dim y2 As Double = clippedYData(i + 1)
Dim point1 As PointF = plot.MapDataPoint(e.Bounds, x1, y1)
Dim point2 As PointF = plot.MapDataPoint(e.Bounds, x2, y2)
Dim pen As Pen = New Pen(ValueToColour(y2))
Dim g As Graphics = e.Graphics
g.DrawLines(pen, New PointF() {point1, point2})
Next
e.Cancel = True
End Sub
Private Function ValueToColour(ByVal value As Double) As Color
If value <= dblMin Then Return colMinColour
If value >= dblMax Then Return colMaxColour
Dim pctg As Double = (value - dblMin) / (dblMax - dblMin)
Dim a, r, g, b As Integer
a = CInt(CInt(colMinColour.A) + pctg * (CInt(colMaxColour.A) - CInt(colMinColour.A)))
r = CInt(CInt(colMinColour.R) + pctg * (CInt(colMaxColour.R) - CInt(colMinColour.R)))
g = CInt(CInt(colMinColour.G) + pctg * (CInt(colMaxColour.G) - CInt(colMinColour.G)))
b = CInt(CInt(colMinColour.B) + pctg * (CInt(colMaxColour.B) - CInt(colMinColour.B)))
r = Math.Max(0, r) : r = Math.Min(255, r)
g = Math.Max(0, g) : g = Math.Min(255, g)
b = Math.Max(0, b) : b = Math.Min(255, b)
Return System.Drawing.Color.FromArgb(a, r, g, b)
Dim col As Color = System.Drawing.Color.FromArgb(a, r, g, b)
Return col
End Function
End Class