Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Getting Elevation Data from a Bing Map

0.00/5 (No votes)
5 Jul 2018 1  
Using HTTP with Bing Maps to get Elevation Data

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.

// Format the URI from a list of locations.
protected string FormatURI(List<location> locList) 
{ 
   // The base URI string. Fill in: 
   // {0}: The lat/lon list, comma separated. 
   // {1}: The heights: datum string, lower case. 
   // {2}: The key. 
   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.

/// Format the URI from a list of locations.
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);
        
     //Check the status code. Throw an exception on error. 
     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))
     {
       //Get the string from the HTTP stream, find the index of the
       //substring where the altitudes are enumerated.
       string readString = reader.ReadToEnd();
       int ndx = readString.IndexOf(targetString);

       //Check to see if the substring has been found.
       if (ndx >= 0)
       {
         string elevationListStr = 
            readString.Substring(ndx + targetString.Length);
         ndx = elevationListStr.IndexOf(']');

         if (ndx > 0)
         {
           elevationListStr = elevationListStr.Substring(0, ndx);

           //Split the comma delimited list into doubles.
           char[] parm = { ',' };
           string[] result = elevationListStr.Split(parm);   

           //Add the strings to the list.
           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:

//Test Method
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>();
    
  //Load 10 lat/lon values
  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):

  1. Get elevations at equally-spaced locations along a polyline path.
  2. 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

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here