Sunday, February 03, 2008
Posted on Sunday, February 03, 2008 3:32:04 PM (Mountain Standard Time, UTC-07:00)  Comments [6] | 
Categories: ArcDeveloper | ArcGIS Devt | ArcGIS Server | Community

Starting from the little bit of hacked up code that I cooked up a while back, I've created an extensible, interface based, adaptive caching Virtual Earth Tile Server that can be extended to use any map rendering engine. The initial release has one Tile Provider which uses the ArcGIS Server SOAP API. In the coming weeks I will be adding providers for both WMS and ArcIMS services.

Project Features:

  • HttpHandler (.ashx)that responds to Tile requests from Virtual Earth
  • Supports multiple layers/map services through the same handler
  • ArcGIS Server Tile Provider uses the AGS SOAP API (fast!)
  • Projects the data - can be used with any ArcGIS Server map service
  • Extensible design allows for additional Tile Providers - i.e. ArcIMS, Image Server
  • Extensible design allows for additional storage providers - i.e. Amazon S3, DBMS
  • Easy to use - just edit the web.config file.
  • Includes a demo web page to get you up and running quickly.
  • API Documentation compiled using DocProject is at http://doc.arcdeveloper.net/tileserver (coming soon!)
  • Leverages the Castle Windsor Inversion of Control Container.
  • Exceptions are written into a tile image so it's easy to debug your configuration.

Design

The Virtual Earth Tile Handler uses a Virtual Earth Tile Service Manager to actually do all the work. The Tile Service Manager contains a collection of Tile Services, keyed by a name. This allows a single instance of the Tile Handler to host multiple tile services. The handler determines which Tile Service to use by extracting the service name from the url of the request. Assuming your tile handler lives in a subdirectory called "tileHandler", a request to http://myserver/tileHandler/tahoe/<vetileindex>.ashx will look for the tahoe tile service, and use it's settings to create the map.

Tile Service is simply a named container for a Tile Provider (a class which creates map image tiles) and a Storage Provider (a class which can cache the images on disk)

The logic in the system is quite simple as shown below:

 TileServer-logic

How to Configure Tile Server:

There are 2 main things you need to do to configure this for your site - add the layer to your Virtual Earth map control, setup a TileService in the web.config.

Adding a Tile Layer to the Virtual Earth Map Control:

Using version 6 of the Map control this is very easy (the Default.aspx file in the attached zip file has this code in it)

First Create a bounding box that will limit the area that Virtual Earth will make tile requests. This box is for Colorado.

var bounds = [new VELatLongRectangle(new VELatLong(40,-109),new VELatLong(37,-102))];

Next, create a Tile Source Specification. You will need to specify the full Url to the handler if your Virtual Earth page is not located in the same web application. What's important to note is that the name of the TileService must be in the url - in this case it's "colorado". You will need to change this to the name of the TileService you want this layer to pull from.
var tileSourceSpec = new VETileSourceSpecification("agssoap", "./colorado/%4.ashx");

From here, it's just setting some simple tile source properties...
tileSourceSpec.NumServers = 1;
tileSourceSpec.Bounds = bounds;
tileSourceSpec.MinZoomLevel = 10;
tileSourceSpec.MaxZoomLevel = 18;
tileSourceSpec.Opacity = 0.5;
tileSourceSpec.ZIndex = 100;

Finally you want to add the layer to your map
map.AddTileLayer(tileSourceSpec, true);

 

Setting up a Tile Service in Web.config

A Tile Service is a container for a Tile Provider and a Storage Provider, so we are going to set up these three things, and link them together. The web.config file in the download already has these sections in it - you will just need to change a few things.

Step 1: Configure the Tile Service

Change the service name to match what you put into the VETileSourceSpecification path, as this is the linkage between the Tile Service and the Url that the request is coming from. For now, leave the other elements alone.

<!-- Colorado Tile Service-->

      <component id="ColoradoVETileService"

                service="ArcDeveloper.TileServer.Interfaces.IVirtualEarthTileService, ArcDeveloper.TileServer.Interfaces"

                type="ArcDeveloper.TileServer.Core.VirtualEarthTileService, ArcDeveloper.TileServer.Core" >

        <parameters>

          <!-- Service Name - must be specified in the url parsed by the handler -->

          <servicename>colorado</servicename>

          <!-- The tile provider for this service is AGSColorado, with it's settings defined lower down -->

          <tileProvider>${AGSColorado}</tileProvider>

          <!-- The storage provide for the cache is the default FileStorage Provider, but this could be changed as needed -->

          <storageProvider>${FileStorageProvider}</storageProvider>

        </parameters>

      </component>

The other sections specify the TileProvider and StorageProvider that this Tile Service will use. If you want to use different or differently configurated providers, just copy/paste the sections and rename them. The configuration syntax here is based on the Castle Windsor project, and you can get more information about how this works by reading Simone Busoli's articles here: Part 1, Part 2, Part 3, and Part 4.

Step 2: Specify the Map Service URL

Locate the following section in the web.config

<component id="AGSColorado"

                service="ArcDeveloper.TileServer.Interfaces.ITileProvider, ArcDeveloper.TileServer.Interfaces"

                type="ArcDeveloper.TileServer.ArcGIS.ArcSoapTileProvider, ArcDeveloper.TileServer.ArcGIS">

        <parameters>

          <!-- Make sure this Url is accessible from this web server or you'll get an exception -->

          <webServiceUrl>http://YOURSERVER/arcgis/services/YOURSERVICENAME/MapServer</webServiceUrl>

        </parameters>

      </component

 

Step 3: Change the StorageProvider location

The Storage Provider is used to cache the tiles as they are created. Thus the location you specify must have write privileges granted to the identity that the ASP.NET application runs as (ASPNET on Windows XP and NETWORK SERVICE on Windows Server 2003)

<component id="FileStorageProvider"

                service="ArcDeveloper.TileServer.Interfaces.IStorageProvider, ArcDeveloper.TileServer.Interfaces"

                type="ArcDeveloper.TileServer.Core.FileStorageProvider, ArcDeveloper.TileServer.Core">

        <parameters>

          <!-- Make sure this path exists, or you'll get an Exception instantiating the FileStorageProvider -->

          <cacheFilePath>c:\tiles\</cacheFilePath>

        </parameters>

      </component>

That's it.

Known Issues:

Occasionally empty tiles are returned from ArcGIS Server. I am still looking into why this occurs, but since the SOAP API actually returns an image, there is no way for the code to know that it's a blank image, and thus it is still added to the cache.

Do not use labeling in the map service. This is because the images are requested at their native tile size of 256 x 256. Thus the labels will be cramped into the tile, and you will have a lot of repeated labels across your map. In the future we may build out a tool that will pre-cook a tile cache, and when doing that you can request larger images which will not have this issue. For now, just turn your labels off.

Feedback / Bugs / Issues

Please use the ArcDeveloper.net forums to ask questions or raise issues. This way everyone will benefit, and it's less one on one emailing.

Source Code:

All the source code for this project is available at the ArcDeveloper project hosted at Assembla.com. You can get the source code from http://svn2.assembla.com/svn/arcdeveloper/tileserver/trunk

If you would like to contribute to the project, use the contact link at the top of this page and I will send you an invitation to join the project team.

Download

Download ArcDeveloper.net Tile Server v0.1 (from ArcScripts). This zip file contains the source code current as of February 3,2008.

Vote!

I also entered this code in the ESRI Code Challenge . If you are an EDN subscriber or are going to the 2008 Developer Summit, and find this code useful, I'd appreciate your vote!

Sunday, February 03, 2008 4:58:05 PM (Mountain Standard Time, UTC-07:00)
TileCache.NET?
Monday, February 04, 2008 3:18:48 PM (Mountain Standard Time, UTC-07:00)
You owe me a beer if you win $15k : http://mapwrecker.wordpress.com/2008/02/04/arcgis-server-virtual-earth-tile-server-vs-arcims/
Monday, February 04, 2008 5:26:56 PM (Mountain Standard Time, UTC-07:00)
I wonder if the image size can be used as an indicator of whether the image is blank or not. With my own on the fly tileserver, one issue that I've run into sometimes with IE is tile ghosting, where a tile remains on the screen as I zoom in or out. To deal with that, I have the handler set the cache properties of the response to have the browser not cache the image. You may want to add that feature as an option.
Tim Maddle
Monday, February 04, 2008 6:32:54 PM (Mountain Standard Time, UTC-07:00)
Hi Dave,

This all looks really cool. I've been lurking here for a while :) I'm a .NET dev, and I'm into all the alt.net stuff you mention, but I'm a beginner with ESRI GIS stuff. We use ESRI products at work for a few different things, and I would really like to look into some alternatives for our web GUI. We used to use ArcIMS, and we just upgraded to Map Server. I've looked at ADF a little, but it is complicated, and the documentation is not so hot. Plus I'm using VS 2008 now :)

So I'm wondering if this might be a good way to go. I need to show some of our maps that are in shape files and then show layers of custom dynamic data on top of them. The custom data is anything from property information to crime information, some should be public and some should be available on our intranet only. Can I use Virtual Earth and this tile server to build those types of things?

I'm just looking for a good starting point to dive in, and if this tile server looks like it will fit the bill, I'll be happy to put it through some testing. Thanks for any help.
Lance Fisher
Wednesday, February 13, 2008 11:54:57 AM (Mountain Standard Time, UTC-07:00)
From the VE "code of conduct":
[..] Unless you have a contract explicitly authorizing it (and without limiting the terms of the Virtual Earth and Microsoft MapPoint license agreements), under no circumstances may you:

Access the underlying map data or photographic imagery other than through documented methods that Microsoft provides to you.
Work around any technical limitations in the API.
Copy, store, archive, or create a database of results from the service.
Sell, lease, or sublicense results or access to the API or the service.
Copy, save, download, distribute, transmit, or in any way manipulate the photographic imagery.
[..]
WW@VE
Wednesday, February 13, 2008 3:08:56 PM (Mountain Standard Time, UTC-07:00)
@ WW@VE

Not sure what your getting at - this uses the VE Control, and adds data into it using the VE API. So how would that be against the "code of conduct"??
Comments are closed.