存在哪些现有服务来计算两个地址之间的距离?

时间:2020-03-06 14:32:56  来源:igfitidea点击:

我想实现一种方法来显示按与给定地址的接近程度排序的存储地址列表。

列表中的地址将存储在数据库表中。单独的部分具有单独的字段(我们有邮政编码,城市名称等字段),因此它不仅仅是一个巨大的" varchar"。这些是用户输入的,由于系统的性质,它们可能并不总是完整的(有些可能缺少邮政编码,而有些则可能只剩下城市和州名)。

尽管这是针对Intranet应用程序的,但我使用外部资源(包括访问Internet Web服务等)没有任何问题。实际上,与自己动手相比,我宁愿这样做,除非自己做事很琐碎。如果是Google或者Yahoo!已经提供了免费服务,我非常愿意查看。关键字是它必须​​是免费的,因为我不能随意为此功能引入此项目的任何额外费用,因为可以这么说,它已经是一个额外的"特权"。

我想到的就像许多实体店做其"查找位置"功能一样。将其显示在经过适当排序的简单表格中,并显示距离(以英里为单位)非常好。显示地图混搭甚至更酷,但我绝对可以忍受距离的回缩,然后处理所有后续显示和排序。

简单距离算法的问题在于数据的性质。由于地址的全部或者部分是不确定的,所以我没有像纬度/经度坐标这样方便的地方。另外,即使我要求提供邮政编码,90%的地址也可能具有相同的五个邮政编码。

众所周知,虽然不必太快,但由于延迟而需要花费超过7秒才能显示在页面上的所有内容对于普通用户来说可能太长了。如果这种假设的服务支持一次发送一批地址,而不是一次查询一个地址,那就太好了。不过,我不认为地址列表会超过50个(如果有的话)。

解决方案

我们不能只使用Google Maps API来获取距离并在我们身边对它们进行排序吗?

http://code.google.com/apis/maps/

我建议调查一下Google Maps API。

它将需要我们具有一个外部连接(并且可以将其上的数据分流到Web服务),但是它提供了我们所需要的,即通过请求2点之间的路线并从它。

方向API的API参考

我们公司所做的一件事是欺骗并使用邮政编码的纬度/经度(大约是邮政编码区域的中心)。这并不完美,但是对于那些在y种搜索的n英里内找到x的人来说,它已经足够接近了。当地址清理服务无法识别地址时,这特别有用。

在某个时候,我遇到了一个免费的邮政编码查询纬度/经度查找表,可以在这种近似中使用。抱歉,我没有链接到此。

Google和Yahoo!两者均免费提供地理编码服务。我们可以使用Haversine公式(在.NET或者SQL中实现)来计算距离。两种服务都可以让我们进行部分搜索(仅邮政编码,仅城市),并让我们知道其结果的精确度(以便我们可以排除没有有意义信息的位置,尽管Yahoo!提供的精确度信息要比Google多)。

Google Maps API的使用条款对我们不利。但是,Yahoo提供了REST服务,用于将地址转换为经度/纬度坐标,然后可以使用该服务计算距离。它在这里。

其他人已经在Daft Logic上做到了(编辑:错字)。他们使用Google Maps API和Great-circle公式。我认为实施起来并不困难。

更新:实际上,我们只需要从我们喜欢的提供程序中获取坐标,然后使用代码进行计算即可。我们可以预加载商店的坐标,当用户提供其位置时,我们甚至可以使用它进行验证。然后,在发出请求时,我们只能查找客户的位置。

要求他们输入一个邮政编码,然后创建一个将邮政编码映射到纬度/经度对的数据库表(或者在线查找一个)。我不知道工作地点,但是在这里,邮政编码可能特定于几米,因此应该足够精确。然后使用此方法来计算两个邮政编码之间的距离:

public static double distance(double lat1, double lon1, double lat2, double lon2, char unit)
{
  double theta = lon1 - lon2;
  double dist = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) +
    Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) * Math.Cos(deg2rad(theta));
  dist = Math.Acos(dist);
  dist = rad2deg(dist);
  dist = dist * 60 * 1.1515;
  if (unit == 'K')
  {
    dist = dist * 1.609344;
  }
  else if (unit == 'N')
  {
    dist = dist * 0.8684;
  }
  return (dist);
}

private static double deg2rad(double deg)
{
  return (deg * Math.PI / 180.0);
}

private static double rad2deg(double rad)
{
  return (rad / Math.PI * 180.0);
}

与地理编码服务相比,使用自己的代码的优势在于,我们可以对数据进行一堆更有趣的计算,以及将一些数据存储在数据库中。

请访问以下网站:http://geocoder.us/help/utility.shtml

我们可以每15秒处理1条记录,如下所示:
http://geocoder.us/service/distance?zip1=95472&zip2=94305

他们还提供没有时间限制的订阅服务