Multiple FreeformPointLineSeries point tracking

A forum dedicated to WPF version of LightningChart Ultimate.

Moderator: Arction_LasseP

Post Reply
zhuzeweieddy
Posts: 1
Joined: Sat Nov 23, 2019 2:50 am

Multiple FreeformPointLineSeries point tracking

Post by zhuzeweieddy » Sat Nov 23, 2019 3:04 am

i read Scatter, point tracking and try to make a click event to track scatter point
the problem is that the example has to specified a FreeformPointLineSeries to apply SolveNearestDataPointByCoord
but i need to SolveNearestDataPointByCoord from all the three series data in the plot,
here in my example chart2.ViewXY.FreeformPointLineSeries[0] leads to tracking only the point of the first series.

any help from you guys? thanks a lot

testplot.JPG
testplot.JPG (37.57 KiB) Viewed 523 times
#region scatter1
private void createChartScatterplot1(Dictionary<string, List<Dictionary<string, string>>> _dataRaw)
{
// empty charts
this.scatterplot1.Children.Clear();

chart2 = new LightningChartUltimate();

chart2.BeginUpdate();

chart2.ChartBackground.GradientFill = GradientFill.Solid;
chart2.ChartBackground.Color = Colors.Black;

chart2.Title.Visible = false; // disable title
chart2.ViewXY.XAxes[0].Title.Visible = false;

chart2.ViewXY.GraphBackground.GradientFill = GradientFill.Solid;
chart2.ViewXY.GraphBackground.Color = Colors.Black;

// Remove Exisiting Y-axis
DisposeAllAndClear(chart2.ViewXY.YAxes);

List<List<string>> plotSiganls = new List<List<string>>();

List<Color> lineSeriesColor = new List<Color>();
lineSeriesColor.Add(Color.FromRgb(66, 80, 102));
lineSeriesColor.Add(Color.FromRgb(136, 142, 126));
lineSeriesColor.Add(Color.FromRgb(98, 42, 29));

// find the common xaxis
var axisX = chart2.ViewXY.XAxes[0];
axisX.Title.Text = "MisfDet_nEngSync";
axisX.Title.Font = new WpfFont("Arial", 11, false, false);
axisX.Title.Color = Colors.White;
axisX.Title.Visible = true;


// add new yaxis
var newAxisY = new AxisY(chart2.ViewXY);
newAxisY.AxisColor = Color.FromRgb(255, 255, 255);
newAxisY.Title.Font = new WpfFont("Arial", 11, false, false);
newAxisY.Title.Visible = true;
newAxisY.Title.Text = "MisfDet_tqBascSync";
newAxisY.Title.Angle = 90;
newAxisY.Title.Color = Colors.White;

chart2.ViewXY.YAxes.Add(newAxisY);

var index = 0;

foreach (var series in _dataRaw.Keys)
{
//Create a FreeformPointLineSeries to show scatter data
FreeformPointLineSeries freeformPointLineSeries = new FreeformPointLineSeries(chart2.ViewXY, chart2.ViewXY.XAxes[0], chart2.ViewXY.YAxes[0]);
freeformPointLineSeries.LineVisible = false;
freeformPointLineSeries.PointsVisible = true;
freeformPointLineSeries.PointStyle.Color1 = lineSeriesColor[index];
/*
freeformPointLineSeries.PointStyle.Shape = Arction.RenderingDefinitions.Shape.Circle;
*/
freeformPointLineSeries.PointStyle.Width = 9;
freeformPointLineSeries.PointStyle.Height = 9;
freeformPointLineSeries.PointStyle.GradientFill = GradientFillPoint.Solid;
freeformPointLineSeries.MouseInteraction = false;

SeriesPoint[] points = new SeriesPoint[_dataRaw[series].ToArray().Length];

for (int i=0; i<_dataRaw[series].ToArray().Length; i++)
{
points.X = Convert.ToDouble(_dataRaw[series]["x"]);
points.Y = Convert.ToDouble(_dataRaw[series]["y"]);
}

freeformPointLineSeries.Points = points;

SeriesEventMarker marker = new SeriesEventMarker(); // Create marker for point size change illusion.
marker.Symbol.BorderColor = Colors.Orange;
marker.Symbol.BorderWidth = 5;
marker.Symbol.Shape = SeriesMarkerPointShape.Circle;
marker.Symbol.GradientFill = GradientFillPoint.Solid;
marker.Symbol.Color1 = marker.Symbol.Color2 = marker.Symbol.Color3 = Colors.Transparent;
marker.MouseInteraction = false;
marker.Label.Visible = false;
marker.Visible = false;
freeformPointLineSeries.SeriesEventMarkers.Add(marker);
freeformPointLineSeries.Title.Text = series;


chart2.ViewXY.FreeformPointLineSeries.Add(freeformPointLineSeries);
index++;

}




AnnotationXY annotation = new AnnotationXY(chart2.ViewXY, chart2.ViewXY.XAxes[0], chart2.ViewXY.YAxes[0]);
annotation.Fill.Color = Color.FromArgb(180, 30, 30, 30);
annotation.Fill.GradientFill = GradientFill.Solid;
annotation.BorderLineStyle.Color = Color.FromArgb(50, 255, 255, 255);
annotation.Shadow.Visible = false;
annotation.TargetCoordinateSystem = AnnotationTargetCoordinates.AxisValues;
annotation.Visible = false; //Don't show before the data point has been found
annotation.MouseInteraction = false;
annotation.LocationCoordinateSystem = CoordinateSystem.RelativeCoordinatesToTarget;
annotation.LocationRelativeOffset.X = 0;
annotation.LocationRelativeOffset.Y = -40;
annotation.TextStyle.Color = Colors.White;
annotation.Style = AnnotationStyle.Rectangle;
chart2.ViewXY.Annotations.Add(annotation);


chart2.MouseClick += Chart2_MouseClick;

chart2.ViewXY.ZoomToFit();
chart2.EndUpdate();

this.scatterplot1.Children.Add(chart2);

}

private void Chart2_MouseClick(object sender, MouseButtonEventArgs e)
{
//Find nearest point and show its values
List<Dictionary<string, double>> distances = new List<Dictionary<string, double>>();
Point point = Mouse.GetPosition(chart2);
double xValue, yValue;
int nearestIndex;

/*
for (int i = 0; i < 3; i++)
{

chart2.ViewXY.FreeformPointLineSeries.SolveNearestDataPointByCoord((int)point.X, (int)point.Y, out xValue, out yValue, out nearestIndex);

Dictionary<string, double> item = new Dictionary<string, double>();
item.Add("xValue", xValue);
item.Add("yValue", yValue);
item.Add("X", (double)point.X);
item.Add("Y", (double)point.Y);
item.Add("nearestIndex", (double)nearestIndex);
item.Add("dist", Math.Sqrt((xValue - (double)point.X) * (xValue - (double)point.X) + (yValue - (double)point.Y) * (yValue - (double)point.Y)));
distances.Add(item);
}
*/

/*
Dictionary<string, double> item2 = distances.Select(s => new { s, y = s["dist"] }).OrderBy(s => s.y).First().s;
*/

if (chart2.ViewXY.FreeformPointLineSeries[0].SolveNearestDataPointByCoord((int)point.X, (int)point.Y, out xValue, out yValue, out nearestIndex))
{
chart2.BeginUpdate();

AnnotationXY annotation = chart2.ViewXY.Annotations[0];
annotation.TargetAxisValues.X = xValue;
annotation.TargetAxisValues.Y = yValue;
annotation.Text =
"X=" + xValue.ToString("0.0") + "\n" +
"Y=" + yValue.ToString("0.0");
annotation.Visible = true;

SeriesEventMarker marker = chart2.ViewXY.FreeformPointLineSeries[0].SeriesEventMarkers[0];
marker.XValue = xValue;
marker.YValue = yValue;
marker.Visible = true;

chart2.EndUpdate();
}

}

Arction_LasseP
Posts: 58
Joined: Wed Mar 27, 2019 1:05 pm

Re: Multiple FreeformPointLineSeries point tracking

Post by Arction_LasseP » Mon Nov 25, 2019 9:54 am

Hello,

This depends on do you want to use one or multiple markers. If you want to track each series separately and show the nearest points of all the series simultaneously (for instance 3 series -> 3 results shown), you can just use SolveNearestDataPointByCoord for all the series separately and have them each use their own markers/annotation to show the results.

If you however, want to calculate the nearest point of all series and show only that with a single marker, you need to compare the calculated distances. Here is an example in which the solving is done inside a MouseMove -event. The same logic works with mouse click events as well:

Code: Select all

private void _chart_MouseMove(object sender, MouseEventArgs e)
{
    _chart.BeginUpdate();
    double xValue = 0, yValue = 0, nearestX = 0, nearestY = 0, nearestDistance = double.MaxValue;
    double distance;
    int nearestIndex; // Not actually used but SolveNearestDataPointByCoord method requires it

    Point point = e.GetPosition(_chart); // Gets mouse position

    for (int i = 0; i < _chart.ViewXY.FreeformPointLineSeries.Count; i++)
    {
        if (_chart.ViewXY.FreeformPointLineSeries[i].SolveNearestDataPointByCoord((int)point.X, (int)point.Y, out xValue, out yValue, out nearestIndex))
        {
            double mX, mY;
            mX = _chart.ViewXY.XAxes[0].ValueToCoord(xValue);
            mY = _chart.ViewXY.YAxes[0].ValueToCoord(yValue);
            distance = Math.Sqrt(Math.Pow((mX - point.X), 2) + Math.Pow((mY - point.Y), 2));

            if (distance < nearestDistance) // Compare the distance to the current nearest point distance, update values if smaller
            {
                nearestDistance = distance;
                nearestX = xValue;
                nearestY = yValue;
            }
        }
    }
    _chart.ViewXY.FreeformPointLineSeries[2].SeriesEventMarkers[0].XValue = nearestX;
    _chart.ViewXY.FreeformPointLineSeries[2].SeriesEventMarkers[0].YValue = nearestY;
    _chart.ViewXY.FreeformPointLineSeries[2].SeriesEventMarkers[0].Label.Text = "X: " + nearestX.ToString("0.00") + " Y: " + nearestY.ToString("0.00");

    _chart.EndUpdate();
}
There are three FreeformPointLineSeries in the above example and only one marker used. Note that it is assigned to the last series to ensure that it is drawn on top of all the series.

Hope this helps.
Best regards,
Lasse

Post Reply