Silverlight MapControl CTP and Custom Tile Sources

Silverlight Map Conntrol
Fig 1 – Example of Silverlight Map Control. Yahoo base tiles with GeoWebCache overlay

Microsoft just released their new Silverlight Virtual Earth MapControl CTP. This isn’t a release version yet, still just a CTP for developers to play with. It is a beautiful map control, and if you can log on to sharepoint you can see Microsoft’s interactive SDK demo here:

Silverlight Map Conntrol Interactive page
Fig 2 – Screen shot of the Silverlight Map Control CTP interactive SDK demo

This control takes advantage of the DeepZoom type of tile interface for very smooth pan and zoom navigation with an addictive elastic feel. Here is an example: Changing View Settings. The CTP version doesn’t handle this as smoothly as the examples at this Live Lab example. If you find this interesting, you can read more about change of view handling algorithms described in this paper on multiscale viewing.

Map navigation is very much like the DeepEarth codeplex project I wrote about recently: MapTiles, Pyramids, and DeepEarth Only Microsoft’s new VE Map Control incorporates a lot more features. For example you can add a video MediaElement directly onto a map lat,long location like this:

Silverlight Map Conntrol Video
Fig 3 – Silverlight VE Map Control CTP with Video overlay

Lots of similar whizz bang features are demonstrated in the interactive SDK demo. However, I’m more interested in seeing how I can use this for a small experimental project. In this project I want to demonstrate use of a base map with overlay tracks from vehicles. The track data is currently served from a PostgresSQL/PostGIS table which would be a bother to access through Linq or an .asmx. I wanted something quick and easy.

First off I noticed that the interactive demo showed some examples of tile overlays. This is interesting and got me looking into what other tile sources might be used. Chris Pietschmann has a set of articles that explored just the thing here:!.aspx

Chris provides some templates for adding base map tiles from OSM, Yahoo, and OpenAerial. It is really quite simple. First in the code behind you simply add a class to wrap a tile source Uri builder:

    public class OpenStreetMapTileSource : Microsoft.VirtualEarth.MapControl.TileSource
     public OpenStreetMapTileSource()
       : base(“{2}/{0}/{1}.png”)

     public override Uri GetUri(int x, int y, int zoomLevel)
      return new Uri(String.Format(this.UriFormat, x, y, zoomLevel));

In the GetUri override you are just taking the tileX, tileY, and zoomLevel furnished by the MapControl and substituting them into the url string used to populate your MapControl Layer. Then when this TileSource is added to the MapControl as a Child tile layer source it will use your GetUri to build the required tile urls:

  <m:Map Name=”MainMap”>
    <!– Set the MapMode to show no VE base tiles –>
      <mc:MercatorMode />


Not a lot of work here. However, I wanted to extend this idea to include a tile source from my PostGIS DB. The simplest aproach was to use Geoserver, which incorporates GeoWebCache. GeoWebCache is a tile caching tool that first builds, and then saves tiles as users grab them. What I needed was a way to setup my tilesource to point at a GeoWebCache service for the PostGIS vehicle track data.

GeoWebCache services are all readily available for use once I added a DataStore and FeatureType for my PostGIS track table. Remember to check the ‘enable cache’ checkbox and add some ‘cache time’ before submitting a FeatureType. Geoserver also adds a seed option to prebuild all of the tiles for a selected FeatureType. The resulting gwc cache is a subdirectory tile scheme located in the geoserver data directory: C:\geoserver-data\gwc\geo_exacteroutput\EPSG_4326_09\02_09\0070_0312.png

Geoserver 1.72 installs with a GeoWebCache Service for virutal earth, /gwc/service/ve. In order to use this service I needed to furnish a quadkey. Quadkeys are interesting numbers that efficiently encode zoomLevel, tilex, and tiley position into a single number. Micrsoft MSDN has a useful article and sample code – example of calculating VE quadkeys. This is similar to the map tile service over at google, only their quadkey uses letters instead of numbers to encode the quadkey source tile.

I used Microsoft’s example code to calculate quadkeys from the tileX, tileY, and zoomLevels kindly furnished by the MapControl resulting in this TileSource class:

  public class ExampleOutputTileSource : Microsoft.VirtualEarth.MapControl.TileSource
    public ExampleOutputTileSource()
      : base(“http://localhost:80/geoserver72/gwc/service/ve?quadkey={0}&format=image/png&transparent=true&layers=geo:exampleoutput”)

    public override Uri GetUri(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)
        if ((tileY & mask) != 0)
      return new Uri(String.Format(this.UriFormat, quadKey));

The GetUri override provides urls that look like this:


Plugging this into a browser gets me a tile of the data from my PostGIS table.

After recieving a helpful hint from Arne over on the GeoWebCache mailing list, I was aso able to use the GeoWebCache service for google maps named ‘gmaps.’ The gmaps service doesn’t need a quadkey, and the GetUri is consequently a bit simpler:

  public class exampleOutputTileSource : Microsoft.VirtualEarth.MapControl.TileSource
    public ExacterOutputTileSource()
     : base(“http://localhost/geoserver72/gwc/service/gmaps?layers=geo:exampleoutput&zoom={2}&x={0}&y={1}”)

   public override Uri GetUri(int x, int y, int zoomLevel)
     return new Uri(String.Format(this.UriFormat, x, y, zoomLevel));


Silverlight VE Map Control is easy to use and has a lot of features that developers want to see, however, one of the issues that is still unclear is the licensing. Tile navigation consumes tons of tiles and the transaction costs can pile up quickly with this kind of interface. There are some noises that the release version will come with a different approach to license pricing.

One interesting item to come out of my experiments is the realization that VE tiles aren’t required to use the viewing features of this control. By watching the http calls in Fiddler you can see the calls to ve tiles are eliminated by setting Map Mode to an empty MercatorMode. This means that transaction costs can be eliminated or at least reduced by using the VE MapControl with a different background source such as Open Street Map or Open Aerial. Routing and geocoding services will still require VE transactions, but far fewer than the tiles. If the USGS, JPL, and NOAA start furnishing tile pyramids for their data we might see lots of alternative tile backgrounds. Often clients want to use their own higher resolution or more specialized accurate base. Using Custom Tile sources, VE Map Control is able to meet this need.

X3D and Virtual Scene Graphs

x3d earth
Fig 1 – XJ3D Viewer showing an x3d earth model.

Virtual Worlds and Scene Graphs

Well I confess, I’m no gamer! I’ve never handled a Wii or blown away monsters on a PS3. It doesn’t hold my interest that much. Guitar Hero makes me feel slightly nauseous. (When will they introduce Symphony Conductor for the Wii?) I suppose I’m an anachronism of the old paperback book era. My kids groan, but I can still get excited about the E.E. Smith Lensman series. However, I’m a bit chagrined to admit that I was oblivious to X3D until this past week. It’s just that gaming and GIS have not overlapped in my world yet.

X3D has been around quite awhile. Some of the specs date back as far as 2003 and then there is the VRML97 ancestory so this is not new stuff. It reminds me a bit of the early SVG days, circa 2000. The novelty of event driven graphics in the browser was overpowering then, but it wasn’t until years later that Flash and Silverlight actually made xml graphics generally available to web app interfaces, almost ten years later. Now of course, SVG even has native support in most of the non microsoft browsers. I can imagine in the year 2018 that 3D graphics XML will be ubiquitous, but it will probably be some derivative of ChromeFlash, XNA, or WPF, while X3D may still languish in the outer reaches of civilization.

X3D has a similar feel in that it’s a powerful anticipating specification with beautiful XML scene graph capability, but only a few implementations far from the mainstream. I won’t say I’m a sucker for XML, but I really, really like to look at a file and understand what it says. Nothing beats a good old text editor for playing with an XML graphics file. Sorry, my text bias is showing again.

The Java3D API is a parallel enabling technology. The scene graph approach implemented in Java3D’s api enabled implementations of free X3D viewers. There are several viewers, but the one that actually worked on the geospatial component of X3D was Xj3D.

What is X3D?

Directly from the x3d site:

“X3D is a scalable and open software standard for defining and communicating real-time, interactive 3D content for visual effects and behavioral modeling. It can be used across hardware devices and in a broad range of applications including CAD, visual simulation, medical visualization, GIS, entertainment, educational, and multimedia presentations.”

“X3D provides both the XML-encoding and the Scene Authoring Interface (SAI) to enable both web and non-web applications to incorporate real-time 3D data, presentations and controls into non-3D content.”

and here is an example of what it looks like:
   <?xml version=”1.0″ encoding=”UTF-8″?>
         <component name=”Geospatial” level=”1″/>
            <PointLight location=”10000000000 0 0″ radius=”100000000000000″/>
            <PointLight location=”-10000000000 0 0″ radius=”100000000000000″/>
            <PointLight location=”0 10000000000 0″ radius=”100000000000000″/>
            <PointLight location=”0 -10000000000 0″ radius=”100000000000000″/>
            <PointLight location=”0 0 10000000000″ radius=”100000000000000″/>
            <PointLight location=”0 0 -10000000000″ radius=”100000000000000″/>
             position=”39.755092 -104.988123 60000″
             orientation=”1.0 0.0 0.0 -1.57″
             <GeoOrigin DEF=”ORIGIN”
             geoCoords=”0.0 0.0 -6378137″
             geoSystem=”GDC” />
            <Inline url=”tiles/0/tile_0.x3d”/>

After the normal XML declaration follows the root element:

In this case using version 3.2 of the X3D spec and a profile, “Immersive”. Profiles are used to break the X3D spec into smaller implementation areas. Consequently, with less effort, an implementor can meet a profile of the X3D spec suitable to the need instead of the entire “Full” specification.

X3D Profiles
Fig 2 – X3D Profiles

Curiously, the X3D Full profile lists the geospatial component, but the Immersive profile seemed to implement the geospatial elements of interest in my particular case. Perhaps geospatial was later moved to the Full profile. Here is a list of the xml node elments found in the geospatial component:

  • GeoCoordinate
  • GeoElevationGrid
  • GeoLocation
  • GeoLOD
  • GeoMetadata
  • GeoOrigin
  • GeoPositionInterpolator
  • GeoProximitySensor
  • GeoTouchSensor
  • GeoTransform
  • GeoViewpoint

You can see a ‘GeoViewpoint’ element and a ‘GeoOrigin’ element in the small x3d listing above. The Immersive/Full profile is meant to imply a virtual world immersion experience. This means that a scene graph populates a world with context including lighting and a viewpoint that navigates through the virtual world space. Now this is of interest to a GIS developer in the sense that the virtual world space can mimic a real world space.

X3D Earth provides some nice examples of using X3D with earth data. Not all of the examples are in working order using the latest build of XJ3D Browser. These are older samples and may not reflect the current configuration of the X3D specification.

Another example of a virtual world space mimicing the actual world is Google’s Earth API. You can use a flying viewpoint to navigate through a model of the Rocky Mountains and get something like the experience of a bird or fighter jet. The mimicry is still coarse but the effect is recognizable. This is the horizon end point of mapping. The map abstraction eventually disappears into a one to one mathematical mapping with some subtle abstraction available as overlays and heads up displays.

This is where the online mapping world eventually merges with the gaming world. Only for mapping, the imaginary part of the world is de-emphasized in favor of an immersive real world experience as an aid to navigating in external physical space. Thinking about these kinds of worlds and their overlaps has proven fascinating, as shown by the popularity of the Matrix movie series. Are we the Ghost in the Machine or the other way around? But that is best left to philosophy types.

Let’s move on to a couple of other useful X3D scene elements. GeoLOD geospatial Level Of Detail element is an interesting element for use in geospatial worlds. By recursively referencing deeper levels of x3d GeoTerrain tiles you have an affect similar to DeepEarth tile pyramids, but with the addition of 3D Terrain:

<?xml version=”1.0″ encoding=”UTF-8″?>
      <component name=”Geospatial” level=”1″/>
            center=”-61.875 -168.75 0.0 ”
         <GeoOrigin DEF=”ORIGIN”
            geoCoords=”0.0 0.0 -6378137.0 ”
            geoSystem=”GDC” />
         <Group containerField=’rootNode’>
                  <Material diffuseColor=”0.3 0.4 0.3 “/>
                        geoGridOrigin =”-67.5 -180.0 0.0 ”
                        yScale =’1.0′
·                     xSpacing=’0.625′
                        -1618 -3574 -3728 -3707 -3814 -3663 -3455 -3089
                         -3258 -3457 -3522 -3661 -3519 -3757 -3412 -3379
                         -3674 -3610 -3503 -3679 -3521 -3537 -3397 -3790
                         -3795 -3891 -3883 -3864
                         -5086 -5138 -5089 -5229 -4965 -5021 -5064 -5099
                         -5062 -4952 -4955 -4810 -4635 -4686 -4599 -4408
                         -4470 -5407 -4482 -4600 -4486 -3942 -4202 -4100
                         -4306 -4293 -4010 -4091
                      <GeoOrigin USE=”ORIGIN” />

In the x3d snippet above you can see the GeoLOD that references down to level 6 of the terrain tile hierarchy. This is a recursive reference as each tile lower in the pyramid references the four tiles of the next level that make up the current tile, basically a quad tree approach found in most tile setups. The element attributes include a center, range, geosystem, and the ChildURL references. Inside the GeoLOD is a <Group> <Shape> element containing the current tile’s Appearance Material with a reference to the draping tile image and a GeoElevationGrid element with an array of elevations relative to the GeoOrigin.

For this to work there are two pyramids, one containing the draping images and one with the x3d GeoTerrainGrids. The GeoTerrainGrid is the same as x3d ElevationGrid except it introduces the concept of a geospatial reference system. This is all very clever and useful, but it requires the Xj3D Browser viewer to play with it. In order to author this kind of world scene you also need tools to tile both the underlying terrain models as well as the overlaid imagery.

x3d earth
Fig 3 – x3d earth model tile pyramid

Over in Microsoft I took a quick look at XNA Game Studio, which is the current development tool for XBox games. The XNA serializer supports a type of XML <XnaContent>, but there doesn’t seem to be much information about the XML XnaContent schema. I wasn’t able to find an X3D importer for XNA. Too bad, since an XNA importer would be another way to experiment with Terrain grids.


As far as the future, it is easy to see that the WPF <MeshGeometry3D> can be used to perform the duties of a an ElevationGrid element. This means, at least in WPF, the basic building blocks are available to display and manipulate a scene in 3D. What is lacking is the concept of LOD, Level of Detail. After first seeing the DeepZoom MultiScaleImage element in action, I fell in love with the very natural navigation through its 2D space.

It is not much of a stretch to see this being extended to a “MultiScaleMeshGeometry3D” element. Again WPF appears to be a look at the future of Silverlight, so it is not impossible to imagine this type of capability in browsers by 2018. In the non-Microsoft world X3D will play a role once implementations make their way into Chrome, FireFox, and Opera. In some form or other, XML scene graphs will be in the future of GIS, and yes, we will all be pro gamers!

MapTiles, Pyramids, and DeepEarth

Fig 1 – DeepEarth Interface to an Amazon S3 tile layer

Tile Pyramids

While working with some DeepEarth map interfaces I stumbled across a really useful tool. Gdal2tiles is a cool python script that uses gdal to create tile pyramids from an image. This is the end result of a Google Summer of Code project and we have Klokan Petr Pridal to thank. In addition to creating the tile pyramid it can create a set of kml SuperOverlay files so that the resulting tile set can be served on top of Google. TMS tiles are also useful for other Tile interfaces like OpenLayers Flash and Silverlight DeepEarth.

As an experiment I downloaded the El Paso County Colorado NAIP from the USDA Geospatial Gateway site. This resulted in a .sid image of about 1.5Gb. Unfortunately the newer NAIP is not complete for El Paso County so I used the 2005 version at 1m resolution.

Now I downloaded the maptiler python wrapper: It is helpful to have the latest version of gdal2tiles, which for Windows, is easiest to get from the FWTools download page:

C:\NAIP>gdal2tiles –help
Usage: [options] input_file(s) [output]
–version show program’s version number and exit
-h, –help show this help message and exit
-p PROFILE, –profile=PROFILE
Tile cutting profile (mercator,geodetic,raster) -
default ‘mercator’ (Google Maps compatible)
Resampling method (average,near,bilinear,cubic,cubicsp
line,lanczos,antialias) – default ‘average’
-s SRS, –s_srs=SRS The spatial reference system used for the source input
-z ZOOM, –zoom=ZOOM Zoom levels to render (format:’2-5′ or ’10′).
-v, –verbose Print status messages to stdout

KML (Google Earth) options:
Options for generated Google Earth SuperOverlay metadata

-k, –force-kml Generate KML for Google Earth – default for ‘geodetic’
profile and ‘raster’ in EPSG:4326. For a dataset with
different projection use with caution!
-n, –no-kml Avoid automatic generation of KML files for EPSG:4326
-u URL, –url=URL URL address where the generated tiles are going to be

Web viewer options:
Options for generated HTML viewers a la Google Maps

Web viewer to generate (all,google,openlayers,none) -
default ‘all’
-t TITLE, –title=TITLE
Title of the map
Copyright for the map
Google Maps API key from

Yahoo Application ID from

I didn’t explore all of these options, but used maptiler’s nice gui .py interface that queries for parameters to feed into the gdal2tiles pyramiding tool. The NAIP data is in UTM coordinates or EPSG:26913 for El Paso, CO. This means to be useful in Google’s kml or VE the image tiles needed to be warped to EPSG:900913. Lots of computation there.

. . . . . .

30 hours later, boy I really need to use that 64bit High cpu EC2 instance …..

I was troubled at first to see that gdal2tiles was only using one of my system’s cores, until I found Maptiler cluster. Klokan Petr Pridal is already moving on to address the time issue and exploring EC2 cluster possibilities. In theory a cluster of 8core EC2 instances could build tile pyramids in minutes rather than hours.

After completing, here is what I have ‘../ElPaso2005′ with a completed tile pyramid in the subdirectory tree levels 8 to 16. 435 subdirectories and 46,228 tiles. Each tile is a 256×256 jpg tile that meets OSGeo Tile Map Service TMS specification. The coordinates default to EPSG:900913/EPSG:3785 Mercator which matches the Google projection. The gdal2tile evidently calculates the optimal depth for my image resolution in a World Wide image. It then appears to do the complete tile division at the lowest level, in this particular case 16. Subsequent tile levels are simply mosaics of four tiles from the next level down so it is a relatively fast process to produce all the tiles above the bottom level. Total disk size for the jpeg files is only 1.7Gb which is very close to the original MrSId size.

Interfaces – DeepEarth, OpenLayers, Google Earth

OK nice, I have a local static tile set and I have some auto generated Google SuperOverlay and OpenLayer Flash interfaces, but since I’ve been playing with DeepEarth recently I next went to the DeepEarth codeplex project to grab the latest 1.0 release. This project has come a long way since I last played with it. I liked the interface from the beginning, but was stymied by the VirtualEarth TileProvider that was pulling hundreds of tiles from VE. A cost analysis showed this was going to be too expensive for common use. Now, however, the project has a number of other TileProviders such as OSM, Yahoo, and WMS, not yet Google. (Google restricts direct use of their tile servers) Google would share the VE disadvantage of cost but way less since the cost is per page view not tile downloaded. Of course really cool is being able to develop any xaml + TileProvider you want.

The project also includes an example showing how to set up a local tile set. The example uses 256×256 tiles but not in the OSGeo TMS directory structure. Here is an example using this DeepEarth local example TileProvider DeepEarth BlueMarble. You can see the tiles spin in from a local directory store on the server. The resolution is not all that great, but a full resolution BlueMarble isn’t that hard to get from BitTorrent. The alternative selection “Blue Marble Web” tiles are full 500m resolution hosted on Amazon S3 courtesy of The Amazon S3 bucket is a flat structure, in other words the buckets don’t have an internal directory tree, which is why the tiles are not stored in a TMS directory tree.

The DeepEarth local TileProvider was easily adapted to suit the TMS directory so I could then directly pull in my El Paso tiles and show them with a DeepEarth interface. However, if I wished to take advantage of the high availability low latency S3 storage, I would need to flatten the tile tree. In S3 subdirectory trees are hiddeen inside buckets as file names. In the S3 case the tile names include the zoom level as a prefix: The 5 on the 5-r8-c24 nomenclature is the zoom level while row is 8 and column 24 at that level. TMS would encode this in a tree like this: ../bluemarble/5/24/8.jpg. The zoom level= subdirectory, row = subdirectory name, and column = name of tile. The beauty of TileProvider class in DeepEarth is that minor modifications can adapt a new TileProvider class to either of these encoding approaches.

Performance and reliability is a lot nicer on an Amazon S3 delivery, especially with heavy use. Once in S3 a map could also be promoted to a CloudFront edge cache without much difficulty. I imagine that would only make sense for the upper heavily used zoom levels, say 1-5 for BlueMarble. Once down in the level 6 part of the pyramid the number of tiles start escalating dramatically and repetitive hit rates are less likely.

Zoom Level Tile Count

  1. 1
  2. 4
  3. 16
  4. 64
  5. 256
  6. 1024
  7. 4096
  8. 16384
  9. 65536
  10. 262144

I can see a common scenario moving toward this approach:

  1. Base layer tile sets from OSM, OpenAerial, VE, (not GE) etc
  2. Client specific base tile pyramids as an opacity overlay
  3. Dynamic layers as WMS from a middle tier WMS/WCS server like Geoserver
  4. Dynamic vectors coming from a spatial RDBMS like PostGIS behind Geoserver

···In this architecture map data is reused from open sources wherever possible and dynamic custom layers are coming out of OGC spec servers. Adding static client specific overlays to Tile storage provides the faster performance helpful for DeepZoom and Flash enabled interfaces.


Geospatial data is growing up and specialized data sources are multiplying. Now there are several background basemaps to choose from Virtual Earth, Yahoo, OpenStreetMap, Open Aerial. Google Earth is also available if you stick with the Google API in a Google container. The more sophisticated backgrounds require a commercial license, but there are also open sources that provide a great deal of capability. Projects like Flash OpenLayers and SIlverlight DeepEarth are improving the user experience substantially while giving developers a great deal of freedom.

A new Silverlight VE Map control is evidently on the way from Microsoft in the next couple of weeks. It is Silverlight so has some of the coolness factor of DeepEarth. I should be able to write some more on it next week.

Some Samples:

Fig 2 – DeepEarth TileProvider interface to an OpenStreetMap

Fig3 – OpenLayer interface example created by MapTiles

Fig 4 – Google Earth interface example created by MapTiles

I still like the approach of using a kml servlet to pull quads on demand from the seamless DRG service on Terraserver. Terraserver keeps chugging along.

Fig – Google Earth interface with DRG quads from Terraserver

Fig 5 – OpenLayer with Virtual Earth background example created by MapTiles