Posts tagged ‘Altitude’

January 27, 2011

The bing.com/maps site, the Bing Maps key, and the Elevation REST Service

http://www.bing.com/maps is Microsoft’s consumer-facing map site. The functionality that it exposes (geocoding, routing, map display etc.) is based on, although not identical to, the features available through the Bing Maps AJAX Control and Silverlight control.

A recent question on the MSDN forum asked whether it would be possible to implement a particular feature from the bing.com/maps site (draggable routes) that wasn’t included “out-of-the-box” in the Bing Maps API. Out of curiosity, this prompted me to have a look at the source code for bing.com/maps, to see how it was achieved there.

Since the AJAX map control used on www.bing.com/maps is just javascript, it’s possible to examine all the source used to create the map by just viewing the page source in a browser (although if has been somewhat obfuscated and minified). But before even getting round to the section of code responsible for draggable routes, I uncovered two interesting, unrelated things:

I’ll Show You My Key if you Show Me Yours

Firstly, the key used to access the Bing Maps services from http://www.bing.com/maps is in plain view in the source code of the page. Bing Maps keys are tied to a particular URL, so there shouldn’t be an issue with letting your key be known publicly. (In fact, since the AJAX map control is executed client-side, there is no way of using the key authentication method without somehow letting your client know the key). However, there had been some discussion on the Bing Maps Developer forum about whether it was wise to try to obfuscate your key from casual snoopers. If we assume that Microsoft lead by example in terms of setting best practice on the bing.com site, since they haven’t hidden their key is it safe to assume that we as developers shouldn’t worry about key obfuscation either?

The Elevation Service

The second interesting thing was a definition of an elevationServiceUrl, as follows:

"elevationServiceUrl","{urischeme}dev.virtualearth.net/REST/v1/Elevation/BoundingRect/{south},{west},{north},{east}/{rows}/{cols}?jsonp=microsoftMapsNetworkCallback&jsonso={jsono}&key={credentials}"

This seems to be an, as yet undocumented, elevation service that can be called via REST – and the URL schema and parameters follow a similar pattern as the existing Geocode, Locations, and Routing REST services.

Experimenting with this elevation service to find out what it did, I tried calling it as follows:

http://dev.virtualearth.net/REST/v1/Elevation/BoundingRect/52,1,53,2/4/4?jsonp=microsoftMapsNetworkCallback&key=AhGSgD1Twhjx9WqxjJZznCBCSzddrrBzkD7k6MjIaLGnp3b3hupQUVbNdv6Wb0qW

The result was a series of decimal “alt” values, rows * cols in length, together with a single “lod” value of 8, in JSON format:

microsoftMapsNetworkCallback({“alt”:[45, -1, 0, 0, 38, -6, -24, -8, 46, 2, -36, -12, 50, -27, -23, 0 ],”lod”:8})

Following the syntax of the other REST services, the result is passed to a callback function specified in the (optional) jsonp parameter – in this case a function called microsoftMapsNetworkCallback. Given that this URL is described as an elevation service, it seems fair to assume that the “alt” values are altitude. “lod” might stand for “level of detail”, but I’m not sure how it relates to the other values. What concerned me more, however, was the alt values themselves. What are they measured relative to, and in what units are they expressed?

The BoundingRect I supplied contains the northeast corner of East Anglia, extending out into the North Sea. I was therefore surprised to see so many negative values. Even assuming that altitude is measured relative to the ellipsoid rather than to sea-level, the altitude coordinates don’t seem to line up with the terrain I know….

To make the comparison simpler, I tried to request the elevation for a single point, by setting both the rows and columns parameters to 1, but this resulted in a “Bad Request” error – it seems that the service is only designed to produce elevation matrix of an area, and you’ll get an error from the service unless both these values are greater than 1. So, the next best thing was setting them both to 2:

http://dev.virtualearth.net/REST/v1/Elevation/BoundingRect/52,1,53,2/2/2?key=AhGSgD1Twhjx9WqxjJZznCBCSzddrrBzkD7k6MjIaLGnp3b3hupQUVbNdv6Wb0qW

which results in:

{“alt”:[45,-1,50,-50],”lod”:11}

A different “lod” value, and four elevation values, as expected. Next is to take a guess at how the rows and columns are assigned across the assigned BoundingRect range. If we were to include the range boundaries themselves, we might expect the previous results to correspond to the readings at each corner of the BoundingRect. Testing these results from the Google elevation service instead:

http://maps.googleapis.com/maps/api/elevation/xml?locations=52,1|52,2|53,1|53,2&sensor=false

Gives the following four elevations:

47.3150635, -27.7267170, -5.8248205, -27.2653141

These values look to be interpolated, whereas the Bing values are probably not, but they still don’t seem to line up particularly well.

Perhaps, instead, the Bing results represent the centrepoint of each cell having defined the BoundingRect into cols * rows. In other words, the four results correspond to the locations at:

http://maps.googleapis.com/maps/api/elevation/xml?locations=52.25,1.25|52.25,1.75|52.75,1.25|52.75,1.75&sensor=false

Which, according to Google, are located at elevations of:

60.4444427, -18.9525394, 25.1086426, -24.8328476

These results at least share the same sign as those from Bing and, accounting for the interpolation, could even be using the same dataset. It’s a bit hard to be certain though.

Under the Sea?

The last mystery remained about explaining the negative values – how could a location in the sea apparently have an altitude below sea level…. unless, the elevation service also includes bathymetry data, and is therefore reporting negative values for depth below sea level of locations on the ocean floor. Yes! Or so I thought, until I tried testing the elevation of an area somewhere near the Mariana Trench:

http://dev.virtualearth.net/REST/v1/Elevation/BoundingRect/11,142,12,143/2/2?key=AhGSgD1Twhjx9WqxjJZznCBCSzddrrBzkD7k6MjIaLGnp3b3hupQUVbNdv6Wb0qW

Fully expecting an answer of something like –10,000, instead I got the following:

{“alt”:[46,2,-11,3],”lod”:8}

Oh well. I guess that’s what you get for playing around with undocumented APIs….

December 12, 2010

Pushpin Altitude and the Birdseye Map Style (Bing Maps v7)

For the inaugural post in my new blog, I thought I’d cover one of the (many) issues that seems to have been generating some confusion following the release of the new v7 AJAX API – namely how to set altitude on a pushpin location, and the effects of doing so.

Before I get into any code, it’s worth making a couple of important observations about altitude:

- Although it may seem obvious, changing altitude will have no effect on the display of a pushpin if you’re using a two-dimensional, top-down map style.

- In contrast, when displaying maps in three-dimensional view (including oblique “birdseye” modes), considering altitude becomes essential in order to correctly position a pushpin in the display.

Under the old v6.x map control, you only generally needed to worry about setting the altitude of your pushpins if you were explicitly using the birdseye or (now deprecated) 3d mode. If you didn’t use those modes, you could set the EnableBirdseyeMode and showSwitch map options to false to prevent your users from accessing the birdseye and 3d map styles respectively, and then use only the road and aerial “top-down” styles, comfortably ignoring any implications of altitude. Every pushpin therefore needed only a latitude and longitude coordinate.

In version 7, the situation is slightly different for two reasons: firstly, there does not currently appear to be any way of limiting the range of map styles available – any style can be chosen from the main menu bar by the end user, including birdseye. Not only that, but the default Automatic map style is now a hybrid style that smoothly transitions from two-dimensional top-down road and aerial imagery at distant zoom levels into “tilted” three-dimensional birdseye at close zoom levels. The effect of these changes is that all Bing Maps developers should now consider what effect altitude has on the way their pushpins are displayed using the different map styles in v7.

Now, for an example: the following code listing creates two pushpins. The first, whose location is specified using only latitude and longitude coordinates, is positioned at the default ground level, at the base of Nelson’s column in Trafalgar Square. The second is positioned exactly 50m above the first, and is specified using both the altitude and the altitudereference of the location.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

  <title></title>

  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

  <script type="text/javascript" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0"></script>

  <script type="text/javascript">

    function GetMap() {

      var map = new Microsoft.Maps.Map(document.getElementById("mapDiv"),

        { credentials: "BINGMAPSKEY",

          center: new Microsoft.Maps.Location(51.5077007450027, -0.12793064117432637 ),

          zoom: 19

        });

      var NelsonsColumnBottom = new Microsoft.Maps.Pushpin(

        new Microsoft.Maps.Location(51.50772, -0.1279303)

      );

      var NelsonsColumnTop = new Microsoft.Maps.Pushpin(

        new Microsoft.Maps.Location(51.50772, -0.1279303, 50, Microsoft.Maps.AltitudeReference.ground)

      );

      map.entities.push(NelsonsColumnBottom);

      map.entities.push(NelsonsColumnTop);

    }

  </script>

</head>

<body onload="GetMap();">

  <div id='mapDiv' style="position: relative; width: 1024px; height: 768px;">

  </div>

</body>

</html>

 

When viewing this map at zoom level 16, the Automatic map style chooses the flat 2d road map view, so the two pushpins are completely superimposed:

automatic_16

However, zoom in one level and the Automatic map style changes to enhanced birdseye view, so the two pushpins diverge to show the bottom and top of the column:

automatic_17

Since we are viewing at an oblique angle from the south, while the bottom pushpin (placed on the ground) appears to have remained in the same place the “top” pushpin appears to have shifted north up the map (whereas, in fact, it is directly above the bottom pushpin). Notice that the image above is taken at zoom level 17, which, in v6.x would still only be capable of showing a flat aerial map (the old “birdseye” mode only being available at the very highest level of zoom).

The enhanced birdseye mode in v7 that replaces the old “aerial” mode still demonstrates perceivable 3d and distinction between these two pushpin locations even when significantly zoomed out. The following image demonstrates that there is still a slight perceivable difference between the location of the pushpins at the top and bottom of Nelson’s column when viewed in birdseye mode at zoom level 14:

automatic_14

Personally, I think the enhanced birdseye style is great since you get the best of both worlds: the traditional aerial imagery view combined with an added sense of depth perception from the slightly oblique angle. However, many developers used to dealing only with the purely top-down “aerial” view of 6.x might not have thought of some of the implications that the new map styles create on the clarity of pushpin location. The Bing Maps default, if no altitude is specified, is to place a pushpin at terrain height of that location (i.e. on the ground). However, there appear to be cases where the underlying terrain elevation data is incorrect, in which case pushpins are incorrectly placed above or below the correct ground height. When viewed obliquely, this can make it appear that they are then misplaced laterally…. to demonstrate what I mean by this, consider the following image:

nelsoncolumn_downingst

At first glance, this map might appear to be highlighting two street locations; one in Trafalgar Square and 10 Downing Street. However, it’s actually showing the same points as used earlier in this post – both placed at exactly the same latitude/longitude. The only difference is that this time the top point has been raised to an altitude of 500m. When viewed from this orientation, and combined with the expectation that both points lie on the same level, may lead a viewer to erroneously conclude that the two pushpins lie at different positions on the ground. So, if your pushpins appear to be displayed in the wrong place, be sure to check not only the latitude/longitude values, but also that you’ve specified the correct altitude.

Note: There is currently an error on the MSDN documentation concerning the location class. http://msdn.microsoft.com/en-us/library/gg427612.aspx should describe the property that determines the basis for stating an altitude of a location as altitudeReference, not altitudeMode.

Follow

Get every new post delivered to your Inbox.

Join 53 other followers