从 Bing 地图获取高程数据





5.00/5 (1投票)
使用 HTTP 与 Bing 地图获取高程数据
引言
本文详细介绍了一个 C# 类,可用于从 Bing 地图获取高程数据。
背景
在开发一个地图项目时,我们正在寻找一种获取指定位置(们)的高程信息的方法。在探索了一些替代方案后,我们决定从 Bing 获取此信息。但是,Bing 地图库似乎没有一种获取特定位置高程信息的方法,因此需要进行 HTTP 查询。
类描述
下图显示了 BingMapElevation
类的图表
- 类构造函数要求您指定 Bing 地图密钥。此 链接 描述了如何获取密钥。
- 用于获取高程的两个
public
方法名为getElevation
。一个用于获取单个高程,另一个用于获取高程列表。 - 实际工作由两个
protected
异步方法完成FormatURI
根据位置或位置返回一个格式化的string
。GetElevationsFromHTTP
使用格式化的string
获取高程列表。
- 可以使用
EARTH_MODEL
枚举指定用于高程的地球模型。可以在 此处 找到这些模型的说明。
该类适用于 UWP 和 .NET 项目(注意:对于 .NET 项目,我们必须显式添加 System.Net.Http
程序集)。
代码描述
在类中,protected FormatURI
和 GetElevationsFromHTTP
方法协同工作以下载高程。FormatURI
方法生成一个包含指定位置、密钥和地球模型的 string
。
// 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;
}
GetElevationsFromHTTP
方法使用 FormatURI
生成的 string
进行 HTTP 调用并下载高程信息。
/// 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;
}
调用两个 getElevation
方法以获取特定位置的高程。
此处显示了 BingMapElevation
用法的示例
//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());
}
}
可能的扩展
Bing 地图 HTTP 接口支持至少其他两个函数(在 此处 解释)
- 沿多段线路径等距位置处获取高程。
- 在地球上由边界框定义的区域内等距位置处获取高程。
可以轻松扩展此类以适应这些函数。
历史
- 2018 年 7 月 5 日:发布初始版本