Introduction
This article details a C# class that can be used to get elevation data from a Bing map.
Background
While developing a mapping project, we were looking for a way to get elevation information for a specified list of location(s). After exploring a few alternatives, we decided to get this information from Bing. However, the Bing map library does not seem to have a way to get elevation information for a specific location and an HTTP query is necessary.
Class Description
The image below shows the diagram for the BingMapElevation
class:
- The class constructor requires you to specify a Bing map key. This link describes how to get a key.
- The two
public
methods used to get elevation(s) are named getElevation
. One is used to get a single elevation, the other for getting a list of elevations. - The actual work is done by two
protected
, asynchronous methods:
FormatURI
returns a formatted string
based on the location or locations. GetElevationsFromHTTP
uses the formatted string
to get a list of elevations.
- The earth model used for the elevations may be specified using the
EARTH_MODEL
enumerations. An explanation of these models can be found here.
The class will work with both UWP and .NET projects (Note: For the .NET project, we had to explicitly add the System.Net.Http
assembly).
Code Description
In the class, the protected FormatURI
and GetElevationsFromHTTP
methods work in tandem to download the elevations. The FormatURI
method generates a string
with the specified locations, the key, and the Earth Model.
protected string FormatURI(List<location> locList)
{
const string BASE_URI_STRING =
"http://dev.virtualearth.net/REST/v1/Elevation/List?points={0}&heights={1}&key={2}";
string retVal = string.Empty;
string locString = string.Empty;
for (int ndx = 0; ndx < locList.Count; ++ndx)
{
if (ndx != 0)
{
locString += ",";
}
locString += locList[ndx].latitude.ToString() + "," + locList[ndx].longitude.ToString();
}
retVal = string.Format(BASE_URI_STRING, locString, Model.ToString().ToLower(), Key);
return retVal;
}
The GetElevationsFromHTTP
method uses the string
generated by FormatURI
to make an HTTP call and download the elevation information.
protected async Task<List<double>> GetElevationsFromHTTP(string url)
{
List<double> retVal = new List<double>();
try
{
HttpClient httpClient = new HttpClient();
HttpResponseMessage msg = await httpClient.GetAsync(url);
if (!msg.IsSuccessStatusCode)
{
string errMsg = "HTTP Response Error: [" + msg + "]";
throw new Exception(errMsg);
}
Stream inStream = await msg.Content.ReadAsStreamAsync();
using (StreamReader reader = new StreamReader(inStream))
{
string readString = reader.ReadToEnd();
int ndx = readString.IndexOf(targetString);
if (ndx >= 0)
{
string elevationListStr =
readString.Substring(ndx + targetString.Length);
ndx = elevationListStr.IndexOf(']');
if (ndx > 0)
{
elevationListStr = elevationListStr.Substring(0, ndx);
char[] parm = { ',' };
string[] result = elevationListStr.Split(parm);
foreach (string dbl in result)
{
retVal.Add(double.Parse(dbl));
}
}
else
{
string errMsg = "Format Error: [" + readString + "]";
throw new Exception(errMsg);
}
}
else
{
string errMsg = "No elevations found in the return string: [" +
readString + "]";
throw new Exception(errMsg);
}
}
}
catch (Exception e)
{
throw new Exception(e.Message, e);
}
return retVal;
}
The two getElevation
methods are called to get elevations at specific locations.
An example of BingMapElevation
usage is shown here:
static async Task Test()
{
string key = "Your Bing Map Key Here";
BingMapElevation mapElevation = new BingMapElevation(key);
double lat = 35.89431;
double lon = -110.72522;
List<location>locList = new List<location>();
for (int ndx = 0; ndx < 10; ++ndx)
{
locList.Add(new Location() { latitude = lat, longitude = lon });
lat += 0.1;
lon -= 0.1;
}
List<double> dList = await mapElevation.getElevation(locList);
Debug.WriteLine("List:");
foreach (double d in dList)
{
Debug.WriteLine(d.ToString());
}
Debug.WriteLine("Single Location Test:");
foreach (Location loc in locList)
{
Debug.WriteLine(loc.latitude.ToString() + "," + loc.longitude.ToString());
double dbl = await mapElevation.getElevation(loc.latitude, loc.longitude);
Debug.WriteLine(dbl.ToString());
}
}
Possible Extensions
The Bing Map HTTP interface supports at least two other functions (explained here):
- Get elevations at equally-spaced locations along a polyline path.
- Get elevations at equally-spaced locations within an area on the Earth defined as a bounding box.
This class can easily be extended to accommodate these functions.
History
- July 5th, 2018: Initial version posted