【问题标题】:Given coordinates, how do I get all the Zip Codes within a 10 mile radius?给定坐标,我如何获得 10 英里半径内的所有邮政编码?
【发布时间】:2011-05-10 13:29:53
【问题描述】:

我有一个位置(纬度和经度)。如何获取部分或全部位于我所在位置 10 英里半径内的邮政编码列表?

解决方案可以是调用知名的网络服务(谷歌地图、必应地图等)或本地数据库解决方案(客户端有 sql server 2005)或算法。

我看过similar question,但那里的所有答案都与使用我无法使用的 SQL Server 2008 地理功能有关。

【问题讨论】:

  • 您要查找哪个国家/地区的邮政编码?

标签: c# .net-3.5 geolocation latitude-longitude zipcode


【解决方案1】:

大多数搜索都使用质心。为了使用 10 英里内的部分邮政编码,您将不得不购买一个邮政编码多边形数据库 (*)。然后实现一个算法,检查 10 英里半径内顶点的邮政编码。要正确完成,您应该使用 Haversine 公式进行距离测量。通过一些巧妙的数据结构,您可以显着减少搜索空间。同样,通过存储和初步比较 zipcoe 范围(北、西、东、南),可以大大加快搜索速度。

(*) 注意:从技术上讲,邮政编码不是多边形!我知道我们都这样想它们,但实际上它们是数据点(街道地址)的集合,这就是 USPS 真正使用它们的方式。这意味着邮政编码可以包含其他邮政编码;邮政编码可以由多个“多边形”组成;邮政编码可以与其他邮政编码重叠。大多数情况应该不是问题,但是您必须处理可以定义为多个多边形的邮政编码。

【讨论】:

    【解决方案2】:

    首先,您需要一个包含所有邮政编码及其对应纬度和经度的数据库。在澳大利亚,只有几千个(而且信息很容易获得),但我认为在美国这可能是一项更艰巨的任务。

    其次,如果您知道自己在哪里,并且知道要查找的半径,您就可以查找该半径内的所有邮政编码。用 PHP 编写的一些简单的东西如下:(抱歉,它不在 C# 中)

    function distanceFromTo($latitude1,$longitude1,$latitude2,$longitude2,$km){
      $latitude1  = deg2rad($latitude1);
      $longitude1 = deg2rad($longitude1);
      $latitude2  = deg2rad($latitude2);
      $longitude2 = deg2rad($longitude2);
      $delta_latitude  = $latitude2  - $latitude1;
      $delta_longitude = $longitude2 - $longitude1;
      $temp = pow(sin($delta_latitude/2.0),2) + cos($latitude1) * cos($latitude2) * pow(sin($delta_longitude/2.0),2);
      $earth_radius = 3956;
      $distance = $earth_radius * 2 * atan2(sqrt($temp),sqrt(1-$temp));
      if ($km)
        $distance = $distance * 1.609344;
      return $distance;
    }
    

    【讨论】:

    • AngryHacker:Luke 发布了我提到的 Haversine 公式的 PHP 实现。
    【解决方案3】:

    从包含邮政编码及其对应的经纬度坐标的邮政编码数据库开始:

    http://www.zipcodedownload.com/Products/Product/Z5Commercial/Standard/Overview/

    要获得纬度和经度之间的距离,您需要一个好的距离公式。这个网站有几个变体:

    http://www.meridianworlddata.com/distance-calculation/

    “大圆距离”公式有点极端。根据我的经验,这个效果很好:

    sqrt(x * x + y * y)
    
    where x = 69.1 * (lat2 - lat1)
    and y = 69.1 * (lon2 - lon1) * cos(lat1/57.3)
    

    您的 SQL 查询将如下所示:

    select zd.ZipCode
    from ZipData zd
    where 
        sqrt(
            square(69.1 * (zd.Latitude - @Latitude)) +
            square(69.1 * (zd.Longitude - @Longitude) * cos(@Latitude/57.3))
        ) < @Distance
    

    祝你好运!

    【讨论】:

    • 这实际上是一个很好的答案...所有距离都在我认为的四分之一英里之内...+1
    • 很好的答案 +1 - 你能告诉我数学是从哪里来的吗?十进制数字代表什么?
    • meridianworld.com 的链接不再有效,因此我将其更新为缓存版本。我相信神奇的数字来自一些计算球体表面距离的距离近似值。那里有更准确的公式,但对于您的基本“商店定位器”场景,这个对我来说效果很好。
    • @dana 如果您删除 .asp 扩展名,链接似乎仍然有效 (meridianworlddata.com/distance-calculation)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-20
    • 1970-01-01
    • 2014-10-21
    • 2015-12-11
    • 2011-12-29
    相关资源
    最近更新 更多