Created
January 16, 2013 05:16
-
-
Save dotMorten/4544822 to your computer and use it in GitHub Desktop.
Bing Maps Elevation Service for Windows 8/RT
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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