This project has moved. For the latest updates, please go here.

MapGraticule is slow

Oct 21, 2013 at 9:23 PM
Edited Oct 21, 2013 at 9:30 PM
Hey guys!

I've spent the past few days fixing bugs and cleaning up performance in my app. One thing that I noticed when profiling is that MapGraticule is really slow! We have 'waypoints' that render on our map for missions and sometimes we can get a lot (100 plus) of them and the app will start to chuck quite badly. After playing around with some performance tools, we found that the lag is actually part of the MapGraticule and when we disable/remove it the app ceases the chug! Just wanted to open up a thread for discussion on this since it might not be a known issue.

Regards,
-Free
Coordinator
Oct 21, 2013 at 10:20 PM
That's certainly because it is rendered every time the ViewportChanged event is raised. Can you provide a better solution?
Oct 21, 2013 at 10:23 PM
ClemensF wrote:
That's certainly because it is rendered every time the ViewportChanged event is raised. Can you provide a better solution?
Maybe only render it when the zoom level has changed? And don't re-render it during the lerp phase? Unless there is a hack we can perform where we 'scale' it while zooming, but only ensure it's accuracy after it's finished zooming to the desired zoom level.
Coordinator
Oct 21, 2013 at 10:30 PM
lerp phase?
Anyway, rendering only on zoom changes would obviously be no option. I could simply pan the graticule out of view.
But you've got the code, try to use it as a base for writing your own graticule overlay.
Oct 22, 2013 at 12:02 AM
Based on some small amount of analysis, I think most of the time is spent on drawing the text (glyphs), and creating the glyphruns. I was able to get a noticeable improvement in speed by caching the GlyphRuns in a Dictionary (base origin at 0,0), and doing a TranslateTransform instead to move them. Here's a sloppy implementation:
if (!glyphs.ContainsKey(latLabel))
    glyphs.Add(latLabel, GlyphRunText.Create(latLabel, Typeface, FontSize, new Point(0, 0)));
if (!glyphs.ContainsKey(lonLabel))
    glyphs.Add(lonLabel, GlyphRunText.Create(lonLabel, Typeface, FontSize, new Point(0, FontSize + 3)));

drawingContext.PushTransform(new TranslateTransform(latPos.X, latPos.Y));
drawingContext.PushTransform(new RotateTransform(ParentMap.Heading, p.X, p.Y));
drawingContext.DrawGlyphRun(Foreground, glyphs[latLabel]);
drawingContext.DrawGlyphRun(Foreground, glyphs[lonLabel]);
drawingContext.Pop();
drawingContext.Pop();
with glyphs being a Dictionary<string, GlyphRun>. It's still a lot faster to just not include the graticule, but I don't know of faster ways to draw text in WPF without resorting to DirectWrite.
Coordinator
Oct 22, 2013 at 6:44 AM
Edited Oct 22, 2013 at 6:44 AM
myoon, thanks for the info. I'll have a look at it and I'm sure I will find a way to reuse existing Glyphs, just like TextBlocks are reused in the Silverlight/WinRT version of MapGraticule.
Coordinator
Oct 22, 2013 at 5:19 PM
Edited Oct 22, 2013 at 5:19 PM
Please check the latest version 1.6.0.