I have been required to write a program which can handle a 1 million points curve as fast as possible. That curve (a spiral which I called Megaspiral) shall have to be moved and zoomed through mouse events. After a short research I decided that WPF would do for me. I tried two different approaches:
The first one is this: at first I prepare the point then I add them to the canvas.
private void PreparePoints()
{
double radius = 100;
double xc = 100, yc = 150;
double numPunti = Math.Pow(10, exp);
double increment = ((double)360 / numPunti) * DEG_2_RAD * 10;
int count = 0;
DateTime beforePoint = DateTime.Now;
for (double iii = increment; iii <= ((360 * DEG_2_RAD) * 10); iii += increment)
{
count++;
radius -= Math.Pow(10, -exp + 2);
Point P = new Point(xc + 50 + radius * Math.Cos(iii), yc + radius * Math.Sin(iii));
pl1.Points.Add(P);
}
TimeSpan tsPoint = DateTime.Now - beforePoint;
Trace.WriteLine("Prepared " + count + " points in " + tsPoint.TotalMilliseconds/1000.0);
}
double exp = 6;
PolyLineSegment pl1 = new PolyLineSegment();
private void AddGraphics()
{
PathFigure pf = new PathFigure();
pf.Segments.Add(pl1);
int aaa = pl1.Points.Count;
PathGeometry pg = new PathGeometry();
pg.Figures.Add(pf);
Path p = new Path();
p.StrokeThickness = 2;
p.Stroke = Brushes.Red;
p.Data = pg;
plotCanvas.Children.Add(p);
}
In the AddGraphics I both tried to use a pathfigure as above and adding them directly.
In short I noticed that both routines take a little time to be executed (<1sec) but then the computer gets stuck for a much longer time.
As a second approach I draw the 1million curve as custom Curve:
namespace CustomShapes
{
public class MegaSpyral : Shape
{
protected PathGeometry pg;
PathFigure pf;
PolyLineSegment pls;
public MegaSpyral()
{
pg = new PathGeometry();
pf = new PathFigure();
pls = new PolyLineSegment();
pg.Figures.Add(pf);
}
// Specify the center of the star
public static readonly DependencyProperty CenterProperty = DependencyProperty.Register("MegaSpyralCenter", typeof(Point), typeof(Star),
new FrameworkPropertyMetadata(new Point(20.0, 20.0),
FrameworkPropertyMetadataOptions.AffectsMeasure));
public Point Center
{
set { SetValue(CenterProperty, value); }
get { return (Point)GetValue(CenterProperty); }
}
// Specify the size of the star:
public static readonly DependencyProperty SizeRProperty =
DependencyProperty.Register("MegaSpyralSizeR", typeof(double), typeof(Star),
new FrameworkPropertyMetadata(10.0,
FrameworkPropertyMetadataOptions.AffectsMeasure));
public double SizeR
{
set { SetValue(SizeRProperty, value); }
get { return (double)GetValue(SizeRProperty); }
}
private const double DEG_2_RAD = Math.PI / 180;
protected override Geometry DefiningGeometry
{
get
{
int exp = 5;
double radius = 100;// SizeR;
double xc = Center.X, yc = Center.X;
double prev = 0;
double numPunti = Math.Pow(10, exp);
double increment = ((double)360 / numPunti) * DEG_2_RAD * 10;
int count = 0;
for (double iii = increment; iii <= ((360 * DEG_2_RAD) * 10); iii += increment)
{
count++;
radius -= Math.Pow(10, -exp + 2);
//Point P1 = new Point(xc + 50 + radius * Math.Cos(prev), yc + radius * Math.Sin(prev));
Point P2 = new Point(xc + 50 + radius * Math.Cos(iii), yc + radius * Math.Sin(iii));
if (count == 1)
pf.StartPoint = P2;
else
pls.Points.Add(P2);
}
pf.Segments.Add(pls);
pf.IsClosed = false;
pf.Segments.Add(pls);
pf.IsClosed = true;
pg.FillRule = FillRule.Nonzero;
return pg;
}
}
}
}
but that took an even longer time.
Sorry for having made it so long but I wanted to make the problem clear. So here are my two questions:
- Is there really no other way to make it work faster?
- Since I have to time it accurately what is the event that tells me the canvas has been drawn (i tried ALL events on EVERY element)
Patrick
EDIT: in reference to Most performant way to graph thousands of data points with WPF? i think it's a different problem because: all answers lead to downsampling point which is the right hint in general but not for me since at the moment I have not to make my program perform in a very fast time (that will be later) but only to choose the fastest way to display ALL those points.
===> EDIT 2: sorry my bad for not having made it clearer. I DO NOT NEED TO DRAW 10^6 POINTS. I've already made a s/r which optimize the curve and reduce them from 10^6 to some 4000. What I'd like to know is the fastest way to draw polyline segments. In order to do that I'd deactivate the optimization routine and go back to 10^6 point but just to measure an accurate timing on different draw methods. So back to my original question. Can anyone tell me WHAT IS THE FASTEST WAY TO DRAW CURVES MADE BY POLYLINE SEGMENTS?