Snap to nearest data point and display value
Moderator: Queue Moderators
Snap to nearest data point and display value
I would like to have a feature of: snap to a data point and display the value at that data point i.e. When you drag the marker, it automatically snaps to nearest data point and shows the X and Y value of it.
- ArctionPasi
- Posts: 1367
- Joined: Tue Mar 26, 2013 10:57 pm
- Location: Finland
- Contact:
Re: Snap to nearest data point and display value
PointLineSeries, SampleDataSeries, AreaSeries and FreeformPointLineSeries have marker snapping built-in (they are ITrackable series). FreeformPointLineSeries that you are using, does not.
So you'll have to implement this in the application side as follows. Define MovedByMouse event handler for the marker. In the handler, seek the nearest data point from the series, with the SeekNearestDataPointIndex method below.
This code (WinForms) creates the chart, creates one FreeformPointLineSeries, fills it with points and inserts 2 markers.
When you move a marker, it'll snap to nearest data point and show the solved values in the marker's label.
So you'll have to implement this in the application side as follows. Define MovedByMouse event handler for the marker. In the handler, seek the nearest data point from the series, with the SeekNearestDataPointIndex method below.
This code (WinForms) creates the chart, creates one FreeformPointLineSeries, fills it with points and inserts 2 markers.
Code: Select all
void CreateChart()
{
m_chart = new LightningChartUltimate("Y3PT77S2RQRCKU6M6PR2EQ7XKJEHMSG9WHAZUQAHZLWY7RTFYU74CP6UT9DGB7AFJVTJB35PML8RWY4HBGAVHL9NP9WEGRVU2R9FF5JXWVQZMJ9T4TZMLYK65EX9WCSSVSFRTZKVUJCVKHJPJFVYXD75XVDUMJSFK2ZKJHLLRGS9J9B4M6W2");
m_chart.Parent = this;
m_chart.Dock = DockStyle.Fill;
m_chart.BeginUpdate();
m_chart.ViewXY.XAxes[0].ValueType = AxisValueType.Number;
//Add FreeformPointLineSeries
FreeformPointLineSeries fpls = new FreeformPointLineSeries(m_chart.ViewXY, m_chart.ViewXY.XAxes[0], m_chart.ViewXY.YAxes[0]);
fpls.MouseInteraction = false;
int iPointCount = 101;
SeriesPoint[] aPoints = new SeriesPoint[iPointCount];
Random rand = new Random();
for (int i = 0; i < iPointCount; i++)
{
aPoints[i].X = 50 + rand.NextDouble() * 20.0;
aPoints[i].Y = i;
}
fpls.Points = aPoints;
m_chart.ViewXY.FreeformPointLineSeries.Add(fpls);
AddMarker(aPoints[20].X, aPoints[20].Y, fpls);
AddMarker(aPoints[35].X, aPoints[35].Y, fpls);
m_chart.ViewXY.LegendBox.Visible = false;
m_chart.ViewXY.XAxes[0].SetRange(0, 100);
m_chart.ViewXY.YAxes[0].SetRange(0, 80);
m_chart.EndUpdate();
}
void AddMarker(double x, double y, FreeformPointLineSeries series)
{
SeriesEventMarker marker = new SeriesEventMarker(series);
marker.VerticalPosition = SeriesEventMarkerVerticalPosition.AtYValue;
marker.HorizontalPosition = SeriesEventMarkerHorizontalPosition.AtXValue;
marker.XValue = x;
marker.YValue = y;
marker.MovedByMouse += new MouseEventHandler(marker_MovedByMouse);
marker.MouseUp += new MouseEventHandler(marker_MouseUp);
series.SeriesEventMarkers.Add(marker);
}
void marker_MouseUp(object sender, MouseEventArgs e)
{
UpdateMarkerToTrackedPosition((SeriesEventMarker)sender);
}
void marker_MovedByMouse(object sender, MouseEventArgs e)
{
int iNearestDataPointIndex = SeekNearestDataPointIndex(e.GetPosition(m_chart));
if (iNearestDataPointIndex >= 0)
{
m_spLatestTrack = m_chart.ViewXY.FreeformPointLineSeries[0].Points[iNearestDataPointIndex];
UpdateMarkerToTrackedPosition((SeriesEventMarker) sender);
}
}
void UpdateMarkerToTrackedPosition(SeriesEventMarker marker)
{
m_chart.BeginUpdate();
marker.XValue = m_spLatestTrack.X;
marker.YValue = m_spLatestTrack.Y;
marker.Label.Text = "[" + marker.XValue.ToString("0.0") + " | " + marker.YValue.ToString("0.0")+"]";
m_chart.EndUpdate();
}
int SeekNearestDataPointIndex(Point mouseLocation)
{
FreeformPointLineSeries fpls = m_chart.ViewXY.FreeformPointLineSeries[0];
int iPointCount = fpls.PointCount;
SeriesPoint[] aPoints = fpls.Points; //store reference to avoid calling Points property getter each loop round
double dValueUnderMouseX = 0;
bool bXSolved = m_chart.ViewXY.XAxes[0].CoordToValue((int)mouseLocation.X, out dValueUnderMouseX, false);
double dValueUnderMouseY = 0;
bool bYSolved = m_chart.ViewXY.YAxes[0].CoordToValue((int)mouseLocation.Y, out dValueUnderMouseY);
double dDistSq;
double dMinDistSq = double.MaxValue;
int iNearestIndex = -1;
//Seek nearest point, by using squared method. It's faster than calling Sqrt every time.
for (int i = 0; i < iPointCount; i++)
{
dDistSq = (aPoints[i].Y - dValueUnderMouseY) * (aPoints[i].Y - dValueUnderMouseY)
+ (aPoints[i].X - dValueUnderMouseX) * (aPoints[i].X - dValueUnderMouseX);
if (dDistSq < dMinDistSq)
{
dMinDistSq = dDistSq;
iNearestIndex = i;
}
}
return iNearestIndex;
}
- Attachments
-
- FreeformPointLineSeries with 2 markers snapped to data nearest data points.
- fpls_markers.jpg (54.96 KiB) Viewed 10348 times
LightningChart Support Team, PT