Applies to: Nevron Chart for .NET
How to implement custom cursor snapping?
In many cases you may need to snap the axis cursors to nearest data point value or some other value which has some user defined meaning (for example an important value or threshold in data).
In such cases you need to implement custom snapping for the axis cursor. The following code example will snap a vertical axis cursor to randomly generated values of a line series:
[C#]
using
System;
using
System.Windows.Forms;
using
Nevron.Chart;
using
Nevron.Chart.WinForm;
using
Nevron.GraphicsCore;
...
private
void
Form1_Load(
object
sender, EventArgs e)
{
m_Chart = (NChart)nChartControl1.Charts[0];
m_Chart.BoundsMode = BoundsMode.Stretch;
Random random =
new
Random();
// create a 2D line chart
NLineSeries line =
new
NLineSeries();
m_Chart.Series.Add(line);
line.DataLabelStyle.Format =
"<value>"
;
line.MarkerStyle.PointShape = PointShape.Cylinder;
line.MarkerStyle.Visible =
true
;
line.MarkerStyle.PointShape = PointShape.Cross;
line.Values.FillRandom(random, 17);
// confiure the axis cursor tool
ConfigureAxisCursorTool();
}
private
void
ConfigureAxisCursorTool()
{
m_HorizontalAxisCursor =
new
NAxisCursor();
m_HorizontalAxisCursor.BeginEndAxis = (
int
)StandardAxis.PrimaryY;
m_HorizontalAxisCursor.ValueSnapper =
null
;
m_HorizontalAxisCursor.ValueChanged +=
new
EventHandler(OnValueChanged);
m_HorizontalAxisCursor.SynchronizeOnMouseAction = MouseAction.Move;
m_VerticalAxisCursor =
new
NAxisCursor();
m_VerticalAxisCursor.BeginEndAxis = (
int
)StandardAxis.PrimaryX;
m_VerticalAxisCursor.ValueSnapper =
null
;
m_VerticalAxisCursor.ValueChanged +=
new
EventHandler(OnValueChanged);
m_VerticalAxisCursor.SynchronizeOnMouseAction = MouseAction.Move;
m_Chart.Axis(StandardAxis.PrimaryX).Cursors.Add(m_HorizontalAxisCursor);
m_Chart.Axis(StandardAxis.PrimaryY).Cursors.Add(m_VerticalAxisCursor);
nChartControl1.Controller.Tools.Clear();
nChartControl1.Controller.Selection.Clear();
nChartControl1.Controller.Selection.Add(m_Chart);
nChartControl1.Controller.Tools.Add(
new
NDataCursorTool());
}
private
double
SnapToValue(NDataSeriesDouble series,
double
value)
{
if
(series.Count == 0)
return
value;
double
snapValue = (
double
)series[0];
double
minDistance = Math.Abs(snapValue - value);
for
(
int
i = 1; i < series.Count; i++)
{
double
currentSnapValue = (
double
)series[i];
double
currentDistance = Math.Abs(currentSnapValue - value);
if
(currentDistance < minDistance)
{
snapValue = currentSnapValue;
minDistance = currentDistance;
}
}
return
snapValue;
}
private
void
OnValueChanged(
object
sender, EventArgs e)
{
NLineSeries line = (NLineSeries)m_Chart.Series[0];
m_VerticalAxisCursor.Value = SnapToValue(line.Values, m_VerticalAxisCursor.Value);
}
NChart m_Chart;
NAxisCursor m_HorizontalAxisCursor;
NAxisCursor m_VerticalAxisCursor;
[VB.NET]
Imports
System
Imports
System.Windows.Forms
Imports
Nevron.Chart
Imports
Nevron.Chart.WinForm
Imports
Nevron.GraphicsCore
...
Private
Sub
Form1_Load(sender
As
System.
Object
, e
As
System.EventArgs)
Handles
MyBase
.Load
m_Chart =
DirectCast
(NChartControl1.Charts(0), NChart)
m_Chart.BoundsMode = BoundsMode.Stretch
Dim
random
As
New
Random()
' create a 2D line chart
Dim
line
As
New
NLineSeries()
m_Chart.Series.Add(line)
line.DataLabelStyle.Format =
"<value>"
line.MarkerStyle.PointShape = PointShape.Cylinder
line.MarkerStyle.Visible =
True
line.MarkerStyle.PointShape = PointShape.Cross
line.Values.FillRandom(random, 17)
' confiure the axis cursor tool
ConfigureAxisCursorTool()
End
Sub
Private
Sub
ConfigureAxisCursorTool()
m_HorizontalAxisCursor =
New
NAxisCursor()
m_HorizontalAxisCursor.BeginEndAxis =
CInt
(StandardAxis.PrimaryY)
m_HorizontalAxisCursor.ValueSnapper =
Nothing
AddHandler
m_HorizontalAxisCursor.ValueChanged,
AddressOf
OnValueChanged
m_HorizontalAxisCursor.SynchronizeOnMouseAction = MouseAction.Move
m_VerticalAxisCursor =
New
NAxisCursor()
m_VerticalAxisCursor.BeginEndAxis =
CInt
(StandardAxis.PrimaryX)
m_VerticalAxisCursor.ValueSnapper =
Nothing
AddHandler
m_VerticalAxisCursor.ValueChanged,
AddressOf
OnValueChanged
m_VerticalAxisCursor.SynchronizeOnMouseAction = MouseAction.Move
m_Chart.Axis(StandardAxis.PrimaryX).Cursors.Add(m_HorizontalAxisCursor)
m_Chart.Axis(StandardAxis.PrimaryY).Cursors.Add(m_VerticalAxisCursor)
nChartControl1.Controller.Tools.Clear()
nChartControl1.Controller.Selection.Clear()
nChartControl1.Controller.Selection.Add(m_Chart)
nChartControl1.Controller.Tools.Add(
New
NDataCursorTool())
End
Sub
Private
Function
SnapToValue(series
As
NDataSeriesDouble, value
As
Double
)
As
Double
If
series.Count = 0
Then
Return
value
End
If
Dim
snapValue
As
Double
=
CDbl
(series(0))
Dim
minDistance
As
Double
= Math.Abs(snapValue - value)
For
i
As
Integer
= 1
To
series.Count - 1
Dim
currentSnapValue
As
Double
=
CDbl
(series(i))
Dim
currentDistance
As
Double
= Math.Abs(currentSnapValue - value)
If
currentDistance < minDistance
Then
snapValue = currentSnapValue
minDistance = currentDistance
End
If
Next
Return
snapValue
End
Function
Private
Sub
OnValueChanged(sender
As
Object
, e
As
EventArgs)
Dim
line
As
NLineSeries =
DirectCast
(m_Chart.Series(0), NLineSeries)
m_VerticalAxisCursor.Value = SnapToValue(line.Values, m_VerticalAxisCursor.Value)
End
Sub
Dim
m_Chart
As
NChart
Dim
m_HorizontalAxisCursor
As
NAxisCursor
Dim
m_VerticalAxisCursor
As
NAxisCursor
Note that the SnapToValue function accepts as a parameter a NDataSeries object – this allows you use to the same function to snap to any value series (for example X values in a line series).
Article ID: 57, Created On: 10/6/2010, Modified: 6/20/2011