Skip to content

Instantly share code, notes, and snippets.

@dotMorten
Created January 16, 2013 05:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dotMorten/4544822 to your computer and use it in GitHub Desktop.
Save dotMorten/4544822 to your computer and use it in GitHub Desktop.
Bing Maps Elevation Service for Windows 8/RT
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Threading.Tasks;
using Windows.Foundation;
namespace SharpGIS.Bing
{
public class ElevationServiceClient
{
//Service documentation:
//http://msdn.microsoft.com/en-us/library/jj158961.aspx
private string m_bingMapsKey;
/// <summary>
/// Initializes a new instance of the <see cref="ElevationServiceClient" /> class.
/// </summary>
/// <param name="bingMapsKey">The bing maps key.</param>
public ElevationServiceClient(string bingMapsKey)
{
m_bingMapsKey = bingMapsKey;
}
/// <summary>
/// Get elevations for latitude and longitude coordinates.
/// </summary>
/// <param name="points">The points where X = Longitude, and Y = latitude.</param>
/// <param name="model">The height model used in results (default: Sea Level).</param>
/// <returns>Elevation data</returns>
public async Task<ElevationListResult> GetElevations(IEnumerable<Point> points, ElevationModel model = ElevationModel.Sealevel)
{
string svc = "http://dev.virtualearth.net/REST/v1/Elevation/List";
int count = points.Count();
var pntString = EncodePoints(points);
var client = new HttpClient(new HttpClientHandler()
{
AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip
});
HttpResponseMessage response;
if (count < 400) //use GET
{
string url = string.Format("{0}?points={1}&key={2}&hts={3}", svc, pntString, m_bingMapsKey, model == ElevationModel.Sealevel ? "sealevel" : "ellipsoid");
response = await client.GetAsync(url).ConfigureAwait(false);
}
else //Recommended to use POST when point count > 400
{
var content = new System.Net.Http.StringContent(
string.Format("points={0}&hts={1}", pntString, model == ElevationModel.Sealevel ? "sealevel" : "ellipsoid" ));
response = await client.PostAsync("http://dev.virtualearth.net/REST/v1/Elevation/List?key="+ m_bingMapsKey, content).ConfigureAwait(false);
}
var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
DataContractJsonSerializer s = new DataContractJsonSerializer(typeof(ElevationListResult));
return s.ReadObject(stream) as ElevationListResult;
}
private static string EncodePoints(IEnumerable<Point> points)
{
int latitude = 0;
int longitude = 0;
StringBuilder result = new StringBuilder();
foreach (var point in points)
{
// step 2
var newLatitude = (int)Math.Round(point.Y * 100000);
var newLongitude = (int)Math.Round(point.X * 100000);
// step 3
long dy = newLatitude - latitude;
long dx = newLongitude - longitude;
latitude = newLatitude;
longitude = newLongitude;
// step 4 and 5
dy = (dy << 1) ^ (dy >> 31);
dx = (dx << 1) ^ (dx >> 31);
// step 6
var index = ((dy + dx) * (dy + dx + 1) / 2) + dy;
while (index > 0)
{
// step 7
var rem = (int)(index & 31);
index = (index - rem) / 32;
// step 8
if (index > 0) rem += 32;
// step 9
result.Append("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-"[rem]);
}
}
// step 10
return result.ToString();
}
}
[DataContract]
public class ElevationListResult
{
[DataMember(Name = "authenticationResultCode")]
public string AuthenticationResultCode { get; set; }
[DataMember(Name = "brandLogoUri")]
public Uri BrandLogoUri { get; set; }
[DataMember(Name = "copyright")]
public string Copyright { get; set; }
[DataMember(Name = "resourceSets")]
public ResourceSet[] ResourceSets { get; set; }
[DataMember(Name = "statusCode")]
public int StatusCode { get; set; }
[DataMember(Name = "statusDescription")]
public string StatusDescription { get; set; }
}
[DataContract]
public class ResourceSet
{
[DataMember(Name = "estimatedTotal")]
public int EstimatedTotal { get; set; }
[DataMember(Name = "resources")]
public Resource[] Resources { get; set; }
[DataMember(Name = "zoomLevel")]
public int ZoomLevel { get; set; }
}
[DataContract(Namespace = "http://schemas.microsoft.com/search/local/ws/rest/v1", Name = "ElevationData")]
public class Resource
{
/// <summary>
/// Elevations in meters
/// </summary>
[DataMember(Name = "elevations")]
public int[] Elevations { get; set; }
[DataMember(Name = "zoomLevel")]
public int ZoomLevel { get; set; }
}
public enum ElevationModel
{
/// <summary>
/// Use the geoid Earth model (EGM2008 2.5’).
/// </summary>
Sealevel,
/// <summary>
/// Use the ellipsoid Earth model (WGS84)
/// </summary>
Ellipsoid
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment