We are using XamGeographicMap to display a heat map of data points for geo locations (for example, NOAA temperature data) that is resolved into a grid of about 5 mile intervals. This translates into adding 90,000 geolocations with a temperature value into the XamGeographicMap for each group/time we want to display in an animation (typically we will show a 24 hour animation). We are running into some performance and display issues, namely:
The triangulation operation on this data takes a long time (20 seconds or more) per group of data (typically 90,000 data points) - are there any recommendations on how to speed this process up? We need to cache 24 times this amount for a 24 hour animation.
The resulting display can use 40 MB or more of memory per group of 90,000 points which can reach 1 GB if 24 hours of data for hourly animation is pre-loaded - is there a away to compact this memory footprint?
Is there a way to have two ranges of Color scales instead of one - for example show various shades of blue for temperatures below 32 degrees and various shades of red above 100 degrees, but ignore drawing (or make the color transparent) for temperature values between 32 and 100? Currently the CustomPaletteColorScale has min/max values to generate colors for as an inclusive range, not an exclusive range. We attempt to create a color scale that includes a transparent color in the middle of the scale, but that is less desirable than just excluding that range from being considered. Also, how is the color scale matched up to a color value?
Attached is example code that generates a random value set (Lat, Lon, Value) of about 140,000 geo location data points in a periodic 5 mile grid format and renders them - this mimics how we get data and put it into the control.
There aren't any series types which display images. It is possible, although somewhat difficult, to create a custom series type and implement it yourself.
Also, the PlotAreaBackground property is provided, so you could set that to an ImageBrush.
Hi David, I did look at the ITF file option, however, it isn't a very dynamic solution for what we need (the user can look at displays for many different 24 hr day sets, so it is not practical to generate ITF files in anticipation of what the user could try to view). I considered eliminating data points we don't want to "color" from being loaded into the map, but that could be inconsistent performance-wise, so maybe we will have to determine other data sampling options.
We do null out data pointers and run the garbage collector so the only big memory objects left are directly related to the Series and because of the load/triangulation time for creating a series, I cache the various area series instead of re-creating them when the hour is changed.
Is there a way to show a layer that is an image? For example, from a PNG file or Image class? We generate a PNG file that is used as an overlay image for another application from the same data and it creates these in less than a second per data group. If there is a mechanism to add an image as a layer bound to specific lat/lon points, we can reuse those images with zero performance hits.
The color scale suggestion is helpful, I will try it out,
Thanks!
It's possible to pre-triangulate your data into a file format called ITF. The TriangulationSource class has a static method called LoadItf and an instance method called SaveItf. This can save you a lot of processing at runtime. There are two samples in the WPF samples browser which demonstrate this: "Binding Triangulated Files" and "Creating Triangulated Files."
If pre-triangulation is not an option or if it's insufficient, data sampling may be an option. This is where you take a sampling of your 90,000 points and show an abstracted view of it, containing a more manageable number of points.
On the subject of memory, it sounds like there's only a problem when keeping multiple sets of data in memory. I would suggest dereferencing any data which is not being displayed currently.
For your ColorScale, it's much easier to just create your own than it is to fit CustomPaletteColorScale to your scenario.
internal class MyColorScale : ColorScale { public override Color GetColor(double value, double defaultMinimum, double defaultMaximum, IList valueColumn) { if (value < 32) { return Colors.Blue; } else if (value < 100) { return Colors.Transparent; } else { return Colors.Red; } } }