Page 1 of 1

How to improve performance in massive 'lines'

Posted: Tue Dec 26, 2017 7:08 am
by Harry943
Hello, I have a requirement of 'Massive lines', every line just have 2 points, and line's count is about to 100,000. And this is my demonstration:
1. Use one FreeformPointLineSeries
2. Set series' data breaking to enable
3. Add random data, every 2 data point add one double.NaN data for breaking, that is for simulate multi line.

Code: Select all

<lcusb:LightningChartUltimate x:Name="chart" Loaded="LightningChart_Loaded">
	<lcusb:LightningChartUltimate.ViewXY>
		<lcusb:ViewXY>
			<lcusb:ViewXY.FreeformPointLineSeries>
				<lcusb:FreeformPointLineSeries x:Name="series" PointsVisible="True" MouseInteraction="False">
					<lcusb:FreeformPointLineSeries.DataBreaking>
						<lcusb:DataBreakingOptions Enabled="True"/>
					</lcusb:FreeformPointLineSeries.DataBreaking>
				</lcusb:FreeformPointLineSeries>
			</lcusb:ViewXY.FreeformPointLineSeries>
			<lcusb:ViewXY.YAxes>
				<lcusb:AxisY Maximum="1000"/>
			</lcusb:ViewXY.YAxes>
			<lcusb:ViewXY.XAxes>
				<lcusb:AxisX Maximum="1000"/>
			</lcusb:ViewXY.XAxes>
		</lcusb:ViewXY>
	</lcusb:LightningChartUltimate.ViewXY>
</lcusb:LightningChartUltimate>

Code: Select all

var rand = new Random(Environment.TickCount);

List<SeriesPoint> ptLst = new List<SeriesPoint>();

for (int i = 0; i < 10000; i++)
{
	ptLst.Add(new SeriesPoint { X = rand.Next(1001), Y = rand.Next(1001) });
	ptLst.Add(new SeriesPoint { X = rand.Next(1001), Y = rand.Next(1001) });
	ptLst.Add(new SeriesPoint { X = double.NaN, Y = double.NaN });
}

ptLst.RemoveAt(ptLst.Count - 1);

series.Points = ptLst.ToArray<SeriesPoint>();
Is there any better solution for this kind of quest? Thx.

Re: How to improve performance in massive 'lines'

Posted: Wed Dec 27, 2017 9:04 am
by ArctionPasi
Hi Harry,

if you don't need to plot the points, but just the lines, we recommend using LineCollections for best performance in this case.

Code: Select all

 <lcusb:ViewXY>
                <lcusb:ViewXY.LineCollections>
                    <lcusb:LineCollection x:Name="lineCollection">
                        <lcusb:LineCollection.LineStyle>
                            <lcusb:LineStyle Color="#FFFF7400" Width="3"/>
                        </lcusb:LineCollection.LineStyle>
                    </lcusb:LineCollection>
                </lcusb:ViewXY.LineCollections>

Code: Select all

	private void LightningChart_Loaded(object sender, RoutedEventArgs e)
		{
            
            var rand = new Random(Environment.TickCount);
            int count = 100000;
            SegmentLine[] lines = new SegmentLine[count];
            for (int i = 0; i < count; i++)
            {
                lines[i].AX = rand.Next(1001);
                lines[i].AY = rand.Next(1001);
                lines[i].BX = rand.Next(1001);
                lines[i].BY = rand.Next(1001);
            } 
            
            lineCollection.Lines = lines; 
            
            
        }

Re: How to improve performance in massive 'lines'

Posted: Thu Dec 28, 2017 1:25 am
by Harry943
Hi ArctionPasi,
Thx for your reply, but we need both point and the line to be visible, and point can change to various shape, color and size, line can change thickness and color.

Re: How to improve performance in massive 'lines'

Posted: Thu Dec 28, 2017 8:23 am
by ArctionKestutis
Hi,

LineCollection has properties tree 'LineStyle', where you can set color, width and pattern of line. Those setting will be applied for all SegmentLine included in that collection. Even if you have one segment per LineCollection, it is still more efficient to use LineCollection than FreeformPointLineSeries.
Making points of various shapes color and size is possible, but it is not going to be rendering efficient. In addition, 200'000 points is not something you could read in ordinary monitor. Still, if you want to make such colorful chart, go with SeriesEventMarker (create dummy series and add all those markers). Each marker could be setup individually (shape, color, size). I believe, that SeriesEventMarker is most efficient solution for your requirements. However, how 200'000 of them will be handled depends on your machine resources (and interactivity you wish to have). I would suggest to limit number of SeriesEventMarker displayed at any single time. For example, show only at certain zoom level and only in visible range. Axis.RangeChange or ViewXY.Zoomed events may help you to identify situation then range is small/big enough.

All the best.

Re: How to improve performance in massive 'lines'

Posted: Thu Dec 28, 2017 8:47 am
by ArctionPasi
If the point style and color, and line width and color, have to be changed per line segment, I think the best way is to use N count of FreeformPointLineSeries, 2 points in each. I also recommend changing to Non-Bindable LC Wpf API.

Code: Select all

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Arction.RenderingDefinitions;
using Arction.Wpf.Charting;
using Arction.Wpf.Charting.SeriesXY;
using Arction.Wpf.Charting.Views;
using Arction.Wpf.Charting.Views.ViewXY;
using Arction.Wpf.Charting.Axes; 

namespace LCTempSemi
{
	/// <summary>
	/// MainWindow.xaml 的交互逻辑
	/// </summary>
	public partial class MainWindow : Window
	{
		public MainWindow()
		{
			InitializeComponent();
		}

        private void LightningChart_Loaded(object sender, RoutedEventArgs e)
        {

            chart.BeginUpdate();



            var rand = new Random(Environment.TickCount);
            int count = 10000;
            ViewXY v = chart.ViewXY;
            AxisX xAxis = v.XAxes[0];
            AxisY yAxis = v.YAxes[0];

            v.LegendBoxes[0].Visible = false; 


            for (int i = 0; i < count; i++)
            {
                FreeformPointLineSeries fpls = new FreeformPointLineSeries(v, xAxis, yAxis);
                fpls.ShowInLegendBox = false;
                fpls.LineStyle.Width = rand.Next(1, 3);
                fpls.LineStyle.Color = DefaultColors.SeriesForBlackBackgroundWpf[rand.Next(0, 10)];
                fpls.PointStyle.Color1 = fpls.LineStyle.Color;
                fpls.PointStyle.GradientFill = Arction.Wpf.Charting.GradientFillPoint.Solid;
                fpls.PointsVisible = true;
                fpls.LineVisible = true;
                fpls.MouseInteraction = false;
                int shape = rand.Next(0, 2);
                if (shape == 0)
                    fpls.PointStyle.Shape = Arction.Wpf.Charting.Shape.Circle;
                else if (shape == 1)
                    fpls.PointStyle.Shape = Arction.Wpf.Charting.Shape.Rectangle;
                else if (shape == 2)
                    fpls.PointStyle.Shape = Arction.Wpf.Charting.Shape.Triangle; 

                fpls.Points = new SeriesPoint[] { new SeriesPoint(rand.Next(1001), rand.Next(1001)), new SeriesPoint(rand.Next(1001), rand.Next(1001)) };
                v.FreeformPointLineSeries.Add(fpls); 
            }



            chart.EndUpdate(); 
        }
	}
}
Random lines with random styles, with FreeformPointLineSeries
Random lines with random styles, with FreeformPointLineSeries
FreeformPointLineSeries_lines.jpg (400.48 KiB) Viewed 16699 times
It is important to hide the LegendBox, otherwise LegendBox handling will cause significant overhead with over 1000 series.