The Microsoft Virtual Earth API lets you add your own tile layer to your VE Map. My colleague StevenO wrote about preparing a suitable TileCache setup. This used to work in both 2D and 3D map modes. Recently, Microsoft introduced the latest version of the API, 6.1, along with a major data upgrade and a new version of the 3D control. A step forward in many respects, but the tile layers will not show up in 3D mode anymore. Let’s investigate. UPDATED 080508 11pm, see below
Let me start out by saying that I did not get the tile layers to display again in the new 3D control, so my preliminary conclusion is that this is a bug (read: feature) in the new VE version. But let me at least reiterate what I’ve tried. I’m also touching on some more general VE API topics that crossed my path.
First, I decided to define as many of the optional parameters for the VETileSourceSpecification as possible. Almost all are optional; only TileSource and ID are required and set in the constructor. I defined the Bounds property, first as a simple VELatLongRectangle (supplying only the top left and bottom right coordinates), that made no difference whatsoever.
As a sidenote: having a GIS background, I can’t really get used to the way a bounding box, or a simple VELatLong point for that matter, are defined. I am used to defining bounding boxes by supplying their bottom-left and top-right points, but the VE API turns that all around and has you supply the top-left and bottom-right points. Those points, in turn, are defined as lat-long instead of long-lat. Does MS do this just to annoy us, or what?
The VELatLongRectangle can also be defined using four points, which is relevant for 3D mode, as you might not be looking straight down and the bounding box of your viewport might not be a rectangle at all. So I tried to define the full rectangle for the Bounds property as well, with no discernible effect:
var bounds = [new VELatLongRectangle(new VELatLong(57,3),new VELatLong(50,7),new VELatLong(57,7),new VELatLong(50,3))];
Next up is the MinZoom and MaxZoom properties. When not set, the tile layer will just show up in every zoom level, which is considered to be a possible performance issue. I don’t really see why, as the tiles will be generated by a tile caching mechanism in any decent implementation. I can see that you want to restrict the visibility of your tile layer to certain zoom levels for aesthetic reasons, however.
In 3D mode, zooming is continuous, so I was wondering what the GetZoomLevel() method would return. The SDK documentation states: ‘This method may not give the same value in 3D mode as in 2D mode.’, without elaborating. It must have something to do with the viewport bounding box in 3D being determined by three variables (heading, pitch and distance to the earth) instead of just one in 2D (just the distance). In any case, you can’t expect the zoom level to remain constant when switching between 2D and 3D modes. It does however provide you with an indication of scale to base layer visibility on. Also note that in 3D mode, the GetZoomLevel() returns a single value, whereas the control internally seems to use a more dynamic approach to zoom levels. Notice that when you tilt your view, tiles that are closer to the ‘camera’ location are rendered with more detail than tiles that are nearer the horizon.
To get back on track; still no luck displaying our tile layers in 3D mode. Let’s see what options are left. There are a couple more properties in the VETileSourceSpecification: NumServers, Opacity and ZIndex. Experimenting with those did not yield any results though. ZIndex looked somewhat promising, but whereas changing values does affect layer ordering in 2D, in 3D we still see no custom layers.
The last thing I tried was reverting to an older API version. The test page I was using only worked with versions 5 and 6, although older versions down to 3 are still supported. IIRC, the custom tile layer functionality was implemented in version 4, but there could be other backward compatibility issues that I don’t want to investigate right now. Anyway, switching to v6 and v5 did not yield any results in what I was actually trying to achieve: to get the custom tile layers to show up.
I asked Johannes Kebeck about this issue, following the VE Technical Briefing that was held this morning. For those just starting in VE API development, as well as for developers already somewhat experienced, sessions with Johannes are a really good introduction. Keep an eye on his blog or the MS Events site for future events. If and when Johannes gets back to me, I’ll update this post.
After having looked into the issue with Johannes Kebeck, we pinpointed the problem: the tile store was served up from a nonstandard port, 8080. Microsoft confirms that fetching tiles from a port other than 80 is disabled in the 3D control, for security reasons. We chose the nonstandard port in order to be able to serve both the VE web application and the tilecache from our VE appliance. Because TileCache prefers an Apache environment and VE an IIS server environment, different port numbers seemed the easy way to accomplish this.