PointLineSeries

A forum dedicated to WPF version of LightningChart Ultimate.

Moderator: Queue Moderators

Post Reply
itz_me_cheyi
Posts: 12
Joined: Wed Oct 02, 2013 6:26 am

PointLineSeries

Post by itz_me_cheyi » Wed Jan 29, 2014 10:00 am

Hi there,

We are generating chart in ViewXY using PointLineSeries. Is there any way to create different style for each point? For example, I want to create a point in triangle symbol while the others are circle. And, is it possible to identify which point is being hovered or clicked?


Thank you,


Syarli

User avatar
ArctionPasi
Posts: 1367
Joined: Tue Mar 26, 2013 10:57 pm
Location: Finland
Contact:

Re: PointLineSeries

Post by ArctionPasi » Wed Jan 29, 2014 2:04 pm

That is possible with usage of SeriesEventMarkers.

Set pointLineSeries.PointsVisible = false.
Then create a new SeriesEventMarker for each data point position with preferred style, and add it to pointLineSeries.SeriesEventMarkers collection.

SeriesEventMarkers support mouse-interactivity, use for example seriesEventMarker.MouseOverOn/MouseOverOff/MouseClick/MouseUp/MouseDown events. :)
LightningChart Support Team, PT

itz_me_cheyi
Posts: 12
Joined: Wed Oct 02, 2013 6:26 am

Re: PointLineSeries

Post by itz_me_cheyi » Thu Jan 30, 2014 3:58 am

We have tried using SeriesEventMarkers but rendering graph process takes more time if we have a large number of point. (we have to wait 6 seconds for graph to render 60.000 points with marker for each point) :(

Is there any better way to achieve this?

User avatar
ArctionPasi
Posts: 1367
Joined: Tue Mar 26, 2013 10:57 pm
Location: Finland
Contact:

Re: PointLineSeries

Post by ArctionPasi » Thu Jan 30, 2014 7:48 am

Sounds like a delay that really is not acceptable. Markers rendering is a lot more work for the computer than a simple line.

Follow my code, it renders 60000 markers in approx. 200-300 ms refresh time, when I just tested with my 5-years-old laptop.

Code: Select all

private void CreateChart()
        {
			// Create a new chart.
			m_chart = new LightningChartUltimate.LightningChartUltimate();
			m_chart.ChartName = "Point line series chart with markers";
            gridChart.Children.Add(m_chart);
           
            // Disable rendering, strongly recommended before updating chart properties.            
            m_chart.BeginUpdate();

            // Hide the legend box.
            //m_chart.ViewXY.LegendBox.Visible = false;
            m_chart.ViewXY.LegendBox.Position = LegendBoxPosition.BottomCenter;
            //Setup x-axis
            AxisX axisX = m_chart.ViewXY.XAxes[0];
            axisX.SetRange(0, 20);
            axisX.ScrollMode = XAxisScrollMode.None;
            axisX.Title.Visible = false;
            axisX.AutoDivSpacing = false;
            axisX.MajorDiv = 2;
            axisX.ValueType = AxisValueType.Number;
            
           
            //Add point line series 
            PointLineSeries pls = new PointLineSeries(m_chart.ViewXY, axisX, m_chart.ViewXY.YAxes[0]);
            pls.PointsVisible = false;

            //Generate random data 
            Random rand = new Random();

            int iPointCount = 60000;

            SeriesPoint[] dataPoints = new SeriesPoint[iPointCount];
            List<SeriesEventMarker> listMarkers = new List<SeriesEventMarker>(iPointCount); 
            
            for (int iPoint = 0; iPoint < iPointCount; iPoint++)
            {
                //Randomize a data point
                dataPoints[iPoint].X = (double)iPoint;
                dataPoints[iPoint].Y = 50 + 10.0 * rand.NextDouble();

                //Create a marker for that data point
                SeriesEventMarker marker = new SeriesEventMarker(pls);
                marker.Symbol.Shape = Shape.Rectangle;
                marker.VerticalPosition = SeriesEventMarkerVerticalPosition.AtYValue;
                marker.HorizontalPosition = SeriesEventMarkerHorizontalPosition.AtXValue;
                marker.Symbol.GradientFill = GradientFillPoint.Solid;
                if (iPoint % 2 == 0)
                {
                    marker.Symbol.Shape = Shape.Triangle;
                    marker.Symbol.Color1 = System.Windows.Media.Colors.Lime;
                }
                marker.XValue = dataPoints[iPoint].X;
                marker.YValue = dataPoints[iPoint].Y;
                marker.MoveByMouse = false;
                marker.Label.Visible = false;

                listMarkers.Add(marker); 
            }
            //Assign the data for the point line series 
            pls.Points = dataPoints;

            //Add the created point line series into PointLineSeries list 
            m_chart.ViewXY.PointLineSeries.Add(pls);

            //Assign the marker list to point line series 
            pls.SeriesEventMarkers = new System.ComponentModel.BindingList<SeriesEventMarker>(listMarkers); 
            
            m_chart.ViewXY.XAxes[0].SetRange(0, iPointCount - 1);
            m_chart.ViewXY.YAxes[0].SetRange(0, 80);

            m_chart.BeforeRendering += new LightningChartUltimate.LightningChartUltimate.BeforeRenderingHandler(m_chart_BeforeRendering);
            m_chart.AfterRendering += new LightningChartUltimate.LightningChartUltimate.AfterRenderingHandler(m_chart_AfterRendering);
            //Allow chart rendering
            m_chart.EndUpdate();
           
        }

        void m_chart_BeforeRendering(LightningChartUltimate.LightningChartUltimate chart, int width, int height)
        {
            m_stopWatch.Restart(); 
        }



        void m_chart_AfterRendering(LightningChartUltimate.LightningChartUltimate chart)
        {
            ChartTools.WriteLog(m_stopWatch.ElapsedMilliseconds.ToString(), "c:\\temp\\markersLog.txt");  
        }

The log file then reveals the rendering delay:
1761[9:33:43 AM] //Initial delay when chart is loaded and DirectX initialized, and chart's object tree takes form.
441[9:33:57 AM] //Some resizes for the chart
454[9:33:57 AM]
428[9:33:58 AM]
507[9:33:59 AM] //Starting dragging from Y axis to adjust scale
196[9:33:59 AM]
207[9:33:59 AM]
200[9:33:59 AM]
285[9:34:00 AM]
203[9:34:00 AM]
199[9:34:00 AM]
201[9:34:00 AM]
196[9:34:00 AM]
197[9:34:01 AM]
307[9:34:01 AM]
204[9:34:01 AM]
197[9:34:01 AM]
198[9:34:02 AM]
196[9:34:02 AM]
287[9:34:02 AM]
247[9:34:02 AM]
207[9:34:02 AM]
200[9:34:03 AM]
198[9:34:03 AM]
289[9:34:03 AM] //Moving mouse over the chart area, where the line and markers are
354[9:34:04 AM]
435[9:34:04 AM]
569[9:34:05 AM] //Pressing right mouse-button down to start panning
446[9:34:05 AM]
410[9:34:06 AM]
421[9:34:06 AM] //Panning the view
410[9:34:07 AM]
400[9:34:07 AM]
467[9:34:08 AM]
424[9:34:08 AM]
424[9:34:08 AM]
417[9:34:09 AM]

Please note that each marker is mouse-hit-tested separately, and mouse hit test with high marker count is quite overheading. Mouse operations over the graph area are therefor slower than in the margins area.
LightningChart Support Team, PT

itz_me_cheyi
Posts: 12
Joined: Wed Oct 02, 2013 6:26 am

Re: PointLineSeries

Post by itz_me_cheyi » Tue Feb 11, 2014 9:38 am

Hi,

Thank you for your help.

We choose to remove all marker to speed up the rendering graph process and display the points of the PointLineSeries by setting the PointsVisible property to true.
However, we still need to change the color of those points (the color is red by default). Is it possible to change the color of these points?

Thank you.

User avatar
ArctionPasi
Posts: 1367
Joined: Tue Mar 26, 2013 10:57 pm
Location: Finland
Contact:

Re: PointLineSeries

Post by ArctionPasi » Tue Feb 11, 2014 10:20 am

Unfortunately, not. A series can only have one color or style on the points.
LightningChart Support Team, PT

krunalc
Posts: 24
Joined: Sat Sep 27, 2014 7:46 am

Re: PointLineSeries

Post by krunalc » Fri Oct 31, 2014 6:58 pm

Are you sure you are able to create 60,000 markers in just 200-300 ms? In my application, I'm using the same code but it takes around 6-8 seconds to create 42000 markers. Only change I see is I also shows marker label so do label configuration as well while creating marker object. I have pasted my code below. Pls suggest if you see anything wrong

Code: Select all

            var marker = new SeriesEventMarker(pls);
            marker.XValue = xValue;
            marker.YValue = yValue;
            marker.VerticalPosition = SeriesEventMarkerVerticalPosition.AtYValue;
            marker.HorizontalPosition = SeriesEventMarkerHorizontalPosition.AtXValue;
            marker.Symbol.GradientFill = GradientFillPoint.Solid;
            //if (iPoint % 2 == 0)
            {
                marker.Symbol.Shape = Arction.WPF.LightningChartUltimate.Shape.Circle;
                marker.Symbol.Color1 = seriesColors[seriesIndex];
            }
/* Pls ignore following code which assigns label text
            if (isXAxisDateTime)
                marker.Label.Text = string.Format("{0} - {1}\n{2} - {3}", _xAxisColumnName, xAxisDateTimeValue.Value.ToString(LabelTimeFormat), ySeiresName, yValue.ToString("0.00000000"));
            else if (string.IsNullOrEmpty(customAxisValue))
                marker.Label.Text = string.Format("{0} - {1}\n{2} - {3}", _xAxisColumnName, xValue, ySeiresName, yValue.ToString("0.00000000"));
            else
                marker.Label.Text = string.Format("{0} - {1}\n{2} - {3}", _xAxisColumnName, customAxisValue, ySeiresName, yValue.ToString("0.00000000"));
*/
            marker.Label.HorizontalAlign = AlignmentHorizontal.Center;
            marker.Label.Font = new WPFFont(System.Drawing.FontFamily.GenericSerif, 9f, System.Drawing.FontStyle.Regular);
            marker.Label.Shadow.Style = TextShadowStyle.Off;
            marker.Label.Shadow.ContrastColor = Colors.Black;
            marker.Label.VerticalAlign = AlignmentVertical.Top;
            marker.Label.MouseInteraction = false;
            marker.Label.MoveByMouse = false;
            marker.Label.Color = MediaColor.FromRgb(0,0,0);
            marker.Label.Visible = false;
            marker.MoveByMouse = false;
            marker.MouseOverOn += marker_MouseOverOn;
            marker.MouseOverOff += marker_MouseOverOff;

            return marker;
Thanks,
Krunal

User avatar
ArctionPasi
Posts: 1367
Joined: Tue Mar 26, 2013 10:57 pm
Location: Finland
Contact:

Re: PointLineSeries

Post by ArctionPasi » Fri Oct 31, 2014 7:17 pm

The collection classes have lately changed, I'll try to provide a fast-working example for the new collections soon. The problem is that every time a new item is added to the list, it refreshes a vast property tree and is heavy. The markers collection should be created and filled as a separate object, and then assigned for the series.
LightningChart Support Team, PT

krunalc
Posts: 24
Joined: Sat Sep 27, 2014 7:46 am

Re: PointLineSeries

Post by krunalc » Fri Oct 31, 2014 7:28 pm

Thanks for your quick response. I will wait for your new sample code.

User avatar
ArctionPasi
Posts: 1367
Joined: Tue Mar 26, 2013 10:57 pm
Location: Finland
Contact:

Re: PointLineSeries

Post by ArctionPasi » Fri Oct 31, 2014 9:21 pm

Collecting the markers in a list like in my previous example is the optimal way, in v.6 it's a SeriesEventMarkerObservableCollection now, not a BindingList.

Code: Select all

SeriesEventMarkerObservableCollection markersCollection = new SeriesEventMarkerObservableCollection(listMarkers);
pls.SeriesEventMarkers = markersCollection;
But... it won't help much because the marker creating itself is slow in v.6 :| The old example was for v.5 and it didn't have MVVM bindable DependencyProperties. It seems in v.6 DP's are causing a major overhead a especially the text objects creating (markers have Label sub-property) is the slow part. The overhead exponentially grows as the marker count grows because we are using a Dictionary for fonts. I couldn't find a way to create marker faster than in this example.

We'll have a R&D meeting on Monday to discuss what are our options to improve the performance with the markers.

Could you summarize your actual need, so we can perhaps come up with an alternative solution if markers creating performance can't be improved.
- Do you need a text label for each marker?
- Do you need to set individual style for each marker?
- Do the markers have to be movable by mouse, or even do they have to track the data?
LightningChart Support Team, PT

krunalc
Posts: 24
Joined: Sat Sep 27, 2014 7:46 am

Re: PointLineSeries

Post by krunalc » Sat Nov 01, 2014 5:04 am

As you mentioned changing to following code (i.e. removing the use of BindingList) didn't help.
SeriesEventMarkerObservableCollection markersCollection = new SeriesEventMarkerObservableCollection(listMarkers);
pls.SeriesEventMarkers = markersCollection;
To your below question my response will be
Could you summarize your actual need, so we can perhaps come up with an alternative solution if markers creating performance can't be improved.
- Do you need a text label for each marker?
- Do you need to set individual style for each marker?
- Do the markers have to be movable by mouse, or even do they have to track the data?
- If disabling the label helps in improving the performance then we can consider not showing labels. However, in my current code I removed the label code and made it invisible but it didn't help me in improving the performance.
- As of now I don't have need to set different marker styles.
- markers don't need to move by mouse. In current code also it is disabled. I didn't get what do you mean by tracking the data?

In our application, chart may contain around 50-60K datapoints for which we need to create the markers. So considering this can you provide any optimum solution? Currently, creating around 42K markers it is taking around 6-8 seconds which is definitely not acceptable.

User avatar
ArctionPasi
Posts: 1367
Joined: Tue Mar 26, 2013 10:57 pm
Location: Finland
Contact:

Re: PointLineSeries

Post by ArctionPasi » Sat Nov 01, 2014 9:12 am

Based on your description, probably markers are not needed at all.

How about just using a PointLineSeries (progressing data by time) or FreeformPointLineSeries (arbitrary data), and setting 60000 points in the Points property. Also set PointsVisible = True.

Does it work for you?
LightningChart Support Team, PT

krunalc
Posts: 24
Joined: Sat Sep 27, 2014 7:46 am

Re: PointLineSeries

Post by krunalc » Tue Nov 04, 2014 4:58 pm

I can see that without adding marker objects also I can see the (kind of marker object) markers if I set PointsVisible = true. That is good enough for me. But the thing is this points won't show the value when I hover the cursor on it. Is it possible to show the point value without using marker label?

User avatar
ArctionPasi
Posts: 1367
Joined: Tue Mar 26, 2013 10:57 pm
Location: Finland
Contact:

Re: PointLineSeries

Post by ArctionPasi » Wed Nov 05, 2014 3:36 pm

You can set chart.MouseMove event handler. In the handler, seek the nearest data point by calling series.SolveNearestDataPointByCoord, pass the mouse screen coordinate for it.

Then you'll get the nearest data point X and Y value, as axis values.

Create one marker or annotation
- and update marker.ValueAtXAxis value and its label,
- or annotation.TargetAxisValues and Text based on value info.

We have an example that's very close to this (WPF demo app: XY view examples / Others / Scatter, Point tracking):
nearest data point tracking
nearest data point tracking
ScatterPointTracking.jpg (286.27 KiB) Viewed 25751 times
It is a scatter chart, but just putting series.LineVisible = true, you'll get the line visible as well. And tracking works, and Annotation shows the value.
LightningChart Support Team, PT

User avatar
ArctionPasi
Posts: 1367
Joined: Tue Mar 26, 2013 10:57 pm
Location: Finland
Contact:

Re: PointLineSeries

Post by ArctionPasi » Wed Nov 05, 2014 3:36 pm

You can set chart.MouseMove event handler. In the handler, seek the nearest data point by calling series.SolveNearestDataPointByCoord, pass the mouse screen coordinate for it.

Then you'll get the nearest data point X and Y value, as axis values.

Create one marker or annotation
- and update marker.ValueAtXAxis value and its label,
- or annotation.TargetAxisValues and Text based on value info.

We have an example that's very close to this:
ScatterPointTracking.jpg
It is a scatter chart, but just putting series.LineVisible = true, you'll get the line visible as well. And tracking works, and Annotation shows the value.
LightningChart Support Team, PT

Post Reply