Changes to the version now include:
- Speed/Memory improvement using feature clipping.
- Tooltips tags for features, (mouse over a line or area to see)
The neeed for speed: performance investigation
This is where the ability to swap drawers has been helpful, I was able to create try out new ideas without having to worry about breaking the existing drawing system. One of the technique's I investigated was drawing using Silverlight's mini-language, this allows you to draw complex shapes using a LOGO like definition:
<Canvas> <Path Stroke="Black" Fill="Gray"Data="M 10,100 C 10,300 300,-200 300,100" /> </Canvas>
Since I need to draw this dynamically I need to load the Path.Data from a string:
StringBuilder sb = new StringBuilder();
sb.Append("<Path xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"");
sb.Append(" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"");
sb.Append(" Data=\"");
sb.Append("");
ShowWay(sb, tileBorder);
foreach (var gpp in quadrant.GeoPolyPoints)
DrawFeature(sb, gpp);
sb.Append("\"/>");
GeometryGroup gg = new GeometryGroup();
Path uiPath = (Path)System.Windows.Markup.XamlReader.Load(sb.ToString());
using a helper function to turn a set of points into a set of draw instructions:
private void DrawFeature(StringBuilder sb, GeoPolyPoint gpp)
{
bool isFirst = true;
foreach (GeoPoint geoPoint in gpp.GeoPoints)
{
int y = geoPoint.GetScaledX(viewport);
int x = geoPoint.GetScaledY(viewport);
if (isFirst)
{
isFirst = false;
sb.Append(" M ");
}
else
sb.Append("L ");
sb.Append(x);
sb.Append(',');
sb.Append(y);
}
if (gpp.PolyConstruct == PolyConstruct.Polygon)
sb.Append("Z ");
return count;
}
I then timed this against my previous attempt, and found hardly any difference - and I also tried create PathFigures, Geometries etc - these were painfully slow (mainly due to the need to create lots of LineSegment objects). So I am sticking with creating Shapes (Polygon and Polyline) as both of these take a collection of points, so no need to create lots of lines.
I then had a look at Seema's blog again and had a play with
<param name="enableRedrawRegions" value="true" />
This showed that I was updating a vast region of the screen, this seems to be related to clipping not behaving as expected - I've asked Seema for some clarification on this. However I also knew my draw routine was pretty lazy - it did not check when drawing a feature if it would even be visible on the tile (for example to the left of the tile).
I was relying on Silverlight clipping to do all the work. So I put in a simple check to only draw features that actually appear in the tile. This reduced the New Malden draw set from 26,038 features to 7,979. This means my code is drawing 3 times less shapes - a massive memory and speed improvement (10% faster), but more importantly ~20,000 shapes that Silverlight does not have to calculate, rotate, clip for no visible effect.
Once I get an answer from Seema on the clipping issue things should get even quicker!
1 comment:
use http://www.codeplex.com/StringToPathGeometry
to cover String To PathGeometry
Post a Comment