While the MapPoint Web Service SDK is highly cool and nice and lightweight, I gotten lots of requests about using this technique with Virtual Earth.
At first I thought “sure – no problem – I’ll just grab a VisualBrush from the .NET Web Browser control and then point it to a web page hosting the VE control.” It turned out to me much trickier than I expected (hardcore WPF folks are probably snickering at the naivete of my attempt…)
Fortunately for me, I have friends who are much smarter than I am, and even more fortunately, this topic came up in a recent conversation. The friend in question here is Marc Schweigert, and he’s been doing some really advanced work with these technologies for a while now.
Of late, Marc’s been working with the SP1 Beta of Visual Studio 2008 + .NET Framework 3.5. Lurking therein is the WPF WebBroswer control, which enables layering WPF over web content. Marc updated one of his integration samples and posted the results on http://blogs.msdn.com/devkeydet/archive/2008/06/24/wpf-and-virtual-earth-revisited.aspx.
The transparency of the canvas is important, because when the mouse is not over the WPF objects, the VE control functions as it normally does. That’s highly cool.
However, one additional problem remained. How could I still do the client side transformations and get the WPF content placed properly on over the VE control? I found the answer at http://blogs.msdn.com/virtualearth/archive/2006/02/25/map-control-zoom-levels-gt-resolution.aspx.
The Virtual Earth control can be zoomed to 1 of 19 pre-defined levels, and the control can be arbitrarily sized. This is quite a bit different than the MapPoint Web Service SDK scenario, in which the centerpoint, resolution, and image size are all known before WPF/SL objects are overlaid.
The blog posting above provides a formula for converting zoom level to a meters/pixel value given a latitude:
mapResolution = 156543.04 * Math.Cos(latitude * Math.PI / 180) / (Math.Pow(2, zoomLevel)
That enabled me to compute the viewscale required by the PointConverter as:
mapResolution /= 1000.0; // now km/pixel
viewScale = mapResolution * ((myCanvas.Width < myCanvas.Height) ? myCanvas.Width : myCanvas.Height)
and then just continued on as previously described. The result looks like this:
The gradient filled region is completely WPF, and the map is Virtual Earth. I added the pins in Virtual Earth to verify that my client side transformation was doing the right thing.
As you’ve probably guessed, I’m very pleased with the result, and can’t thank Marc and the Virtual Earth team enough. Now if only I had some design skill, I might be able to make a more appealing gradient fill… 🙂
I’ll take a brief digression into geocoding in my next post…