Draw curves in WPF efficiently

2016-12-16 11:19:38 Coding C++ WPF

I have a customized canvas inheriting Canvas and overrides the OnRender(DrawingContext dc) method. And I need to draw some curves. I have precomputed the points on the curve and stored them in a List<Tuple<double, double>> because I am drawing different parts of the curve at different time. So, it is natural to come up with

for (int i = start; i <= end; ++i)
    dc.DrawLine(CurvePen, new Point(list[i].Item1, list[i].Item2), new Point(list[i+1].Item1, list[i+1].Item2));

However this approach is slow and CPU-intensive as hell. Guess what? I had a naive test and wrote

var gstr = new StringBuilder();
gstr.Append($"M {list[start].Item1},{list[start].Item2} L ");
for (int i = start + 1; i <= end; ++i)
    gstr.Append($"{t.Item1},{t.Item2} ");
dc.DrawGeometry(null, CurvePen, Geometry.Parse(gstr.ToString()));

Basically the code constructs a Path Markup, parse it to a Geometry object and draw it. It looks terrible – that’s a lot of string operations… but it is actually very, very fast. In fact, much faster than the multiple DrawLine calls.

One possible optimization is to, apparently, precompute all the Geometry objects, although it may result in worse performance because that’s a lot of objects. So I’ll just stick to this construct-on-the-fly thing at the moment 😛