Silverlight Virtual Earth, Part 2 MultiScaleTileSource

The feedback from Part 1 has been great! There is definitely interest in this. Shaun Becker sent through this gem that removes my proxy server completely! Yes we now have Silverlight Deep Zoom talking directly to Virtual Earth! And better still I can give you a live demo (need SL beta2 installed – click image to view):

VEDZ

So what has Shaun done to make this possible?

He has created a VETileSource class inheriting from MultiScaleTileSource. Perfect! Now this code is still rough, we only have the one tile source, its very hard coded but it is a great proof of concept.

using System;
        using System.Text;
        using System.Windows.Media;

        namespace DeepZoomProject
        {
        public class VETileSource : MultiScaleTileSource
        {
        const string Protocol = "http://";
        const string TilePath = ".ortho.tiles.virtualearth.net/tiles/";
        const string Prefix = "h";
        const string Suffix = ".jpeg?g=159";

        static string TileXYToQuadKey(int tileX, int tileY, int levelOfDetail) {
        StringBuilder quadKey = new StringBuilder();
        for (int i = levelOfDetail; i > 0; i--) {
        char digit = '0';
        int mask = 1 << (i - 1);
        if ((tileX & mask) != 0) {
        digit++;
        }
        if ((tileY & mask) != 0) {
        digit++;
        digit++;
        }
        quadKey.Append(digit);
        }
        return quadKey.ToString();
        }

        protected override void GetTileLayers(int tileLevel, int tilePositionX, int tilePositionY, System.Collections.Generic.IList<object> tileImageLayerSources) {
        int zoom = tileLevel - 8;
        if (zoom > 0) {
        string QuadKey = TileXYToQuadKey(tilePositionX, tilePositionY, zoom);
        string VEUrl = Protocol + Prefix + QuadKey[QuadKey.Length - 1] + TilePath + Prefix + QuadKey + Suffix;
        tileImageLayerSources.Add(new Uri(VEUrl));
        } else {
        string localPath = string.Format("http://localhost:1393/VE_files/{0}/{1}_{2}.jpg", tileLevel, tilePositionX, tilePositionY);
        Uri localUri = new Uri(localPath);
        tileImageLayerSources.Add(localUri);
        }
        }

        public VETileSource()
        : base(134217728, 134217728, 256, 256, 0) {
        }
        }
        }

In the constructor we have called the base class setting the enormous image size for VE, 256px tiles and no overlap. Awesome.

So the only change needed to our Page.xaml.cs is to change the tile source:

public Page()
        {
        InitializeComponent();

        //
        // We are setting the source here because of an issue that exists in Blend 2.5 when the Source is set via XAML
        //
        //this.msi.Source = new DeepZoomImageTileSource(new Uri("GeneratedImages/dzc_output.xml", UriKind.Relative));
        this.msi.Source = new VETileSource();

Next step is to clean up the code a little and work with some subimages to support Road, Shaded, Aerial and Hybrid tiles. The plan is build a codeplex open source project so if your interested send me an email to John at soulsolutions.com.au. Feel free to leave any comments here and I’ll again put a full download in the comments.