65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 C# 和 MapPoint 2009 进行反向地理编码

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2009年3月27日

CPOL

2分钟阅读

viewsIcon

63479

downloadIcon

1141

使用 C# 和 MapPoint 2009,根据经纬度查找街道地址。

引言

本文演示了如何使用 C# 和 MapPoint 2009 根据经纬度查找街道地址。MapPoint 不使用 Web 服务。所有数据都存储在用户本地机器上。根据我的研究,MapPoint 提供了一种在本地执行反向地理编码的最经济的解决方案。来自 ThinkGeo 或 GeoFrameworks 等供应商的库价格高达 3000 美元,而 MapPoint 的价格为 300 美元。

背景

您可以从 http://www.microsoft.com/downloads/details.aspx?FamilyID=60905dfe-5aea-44ec-b5fb-0e4130c3e7e5&DisplayLang=en 下载 MapPoint North America 2009 试用版。下载量高达 1.2GB,因为它包含北美所有地理信息。

MapPoint 不包含 .NET 程序集,只能通过 COM 接口。如果您和我年龄相仿(26 岁),您可能没有太多使用 COM 的经验。Windows SDK 包含一个名为 tlbimp.exe 的工具,用于从 COM 类型库生成 .NET 程序集。程序集 Interop.MapPoint.dll 包含在代码下载中,您可以使用以下命令自行生成:

"C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\tlbimp.exe" 
 "C:\Program Files\Microsoft MapPoint 2009\MPNA83.tlb" /out:c:\Interop.MapPoint.dll
 /namespace:Interop.MapPoint

有关 COM 的更多信息,我建议您参考 http://en.wikipedia.org/wiki/Component_Object_Model

使用代码

方法 Map.ObjectsFromPoint(int x, int y) 查询 MapPoint 在给定经纬度处的对象。此方法返回街道地址、国家/地区、餐馆以及 MapPoint 数据库中的任何其他内容。我们实现了该方法

private StreetAddress LookupStreetAddress(Location loc)
{
    FindResults arr = _map.ObjectsFromPoint(_map.LocationToX(loc), _map.LocationToY(loc));
    return arr.OfType<location>().Where(o => o.StreetAddress 
       != null).Select(o => o.StreetAddress).FirstOrDefault();
}

以筛选结果,只保留街道地址。如果位置不接触街道,则不太可能返回街道地址。MapPoint 不包含查找最近街道地址的方法。

我们的 GetNearestAddress 算法

街道的宽度似乎约为 .0001 度,因此我们的算法使用间隔 .0001 度的点网格。我们遍历这些点,从离起始位置最近的点开始,对每个点调用 LookupStreetAddress,直到找到匹配项为止。

public StreetAddress GetNearestAddress(double lat, double lon)
{
    if (lat == double.NaN || lon == double.NaN)
    {
        return null;
    }

    // MapPoint needs to be centered
    _map.GoToLatLong(lat, lon, 1);

    // Zoom level seems to affect what is returned...
    // haven't figured out the pattern here
    for (int i = 0; i < 10; i++)
    {
        _map.ZoomIn();
    }

    // make 10 squares around, each .0001 degrees apart
    StreetAddress addr;
    for (int i = 0; i < 10; i++)
    {
        foreach (Location loc in GetPointsAround(lat, lon, i, .0001))
        {
            if ((addr = LookupStreetAddress(loc)) != null)
            {
                return addr;
            }
        }
    }

    return null;
}

就这样。我已将其与 GPS 设备一起使用,并能够准确查看我的当前地址。

© . All rights reserved.