Python地理编码距离过滤

Python地理编码距离过滤,python,geocoding,Python,Geocoding,我需要过滤地理代码,以确定是否靠近某个位置。例如,我想筛选餐厅地理代码列表,以识别距离我当前位置10英里以内的餐厅 有人能告诉我一个将距离转换为经纬度增量的函数吗?例如: class GeoCode(object): """Simple class to store geocode as lat, lng attributes.""" def __init__(self, lat=0, lng=0, tag=None): self.lat = lat self

我需要过滤地理代码,以确定是否靠近某个位置。例如,我想筛选餐厅地理代码列表,以识别距离我当前位置10英里以内的餐厅

有人能告诉我一个将距离转换为经纬度增量的函数吗?例如:

class GeoCode(object):
   """Simple class to store geocode as lat, lng attributes."""
   def __init__(self, lat=0, lng=0, tag=None):
      self.lat = lat
      self.lng = lng
      self.tag = None

def distance_to_deltas(geocode, max_distance):
   """Given a geocode and a distance, provides dlat, dlng
      such that

         |geocode.lat - dlat| <= max_distance
         |geocode.lng - dlng| <= max_distance
   """
   # implementation
   # uses inverse Haversine, or other function?
   return dlat, dlng
class地理编码(对象):
“”“将地理代码存储为lat、lng属性的简单类。”“”
def _;初始(自身,纬度=0,液化天然气=0,标签=None):
self.lat=lat
self.lng=lng
self.tag=None
定义到三角洲的距离(地理代码,最大距离):
“”“给定地理编码和距离,提供dlat、dlng
以致

|geocode.lat-dlat |这是使用哈弗森公式计算lat/长对之间距离的方法:

import math 

R = 6371 # km
dLat = (lat2-lat1) # Make sure it's in radians, not degrees
dLon = (lon2-lon1) # Idem 
a = math.sin(dLat/2) * math.sin(dLat/2) +
    math.cos(lat1) * math.cos(lat2) * 
    math.sin(dLon/2) * math.sin(dLon/2) 
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a)) 
d = R * c;
现在,根据阈值测试“d”(也以km为单位)是很简单的。如果您想要的不是km,请调整半径

很抱歉,我无法为您提供一个临时解决方案,但我不理解您的代码框架(请参阅注释)


还要注意的是,现在你可能想使用余弦球面定律,而不是哈弗森公式。数值稳定性方面的优势不再值得,而且它的理解、编码和使用非常简单。

这就是如何使用哈弗森公式计算lat/long对之间的距离:

import math 

R = 6371 # km
dLat = (lat2-lat1) # Make sure it's in radians, not degrees
dLon = (lon2-lon1) # Idem 
a = math.sin(dLat/2) * math.sin(dLat/2) +
    math.cos(lat1) * math.cos(lat2) * 
    math.sin(dLon/2) * math.sin(dLon/2) 
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a)) 
d = R * c;
现在,根据阈值测试“d”(也以km为单位)是很简单的。如果您想要的不是km,请调整半径

很抱歉,我无法为您提供一个临时解决方案,但我不理解您的代码框架(请参阅注释)


还要注意的是,现在你可能想使用球面余弦定律而不是哈弗森定律。数值稳定性方面的优势不再值得,而且它的理解、编码和使用都非常简单。

如果你将数据存储在MongoDB中,它可以很好地索引地理位置搜索,并且优于纯Pyt支持以上解决方案,因为它将为您处理优化


如果您将数据存储在MongoDB中,它可以为您进行索引良好的地理位置搜索,并且优于上面的纯Python解决方案,因为它可以为您处理优化


似乎没有一个好的Python实现。幸运的是,所谓的“相关文章”侧栏是我们的朋友。指向一个给出数学和Java实现的。您需要的实际函数非常简短,并且嵌入在下面我的Python代码中。测试到一定程度。请阅读注释中的警告

from math import sin, cos, asin, sqrt, degrees, radians

Earth_radius_km = 6371.0
RADIUS = Earth_radius_km

def haversine(angle_radians):
    return sin(angle_radians / 2.0) ** 2

def inverse_haversine(h):
    return 2 * asin(sqrt(h)) # radians

def distance_between_points(lat1, lon1, lat2, lon2):
    # all args are in degrees
    # WARNING: loss of absolute precision when points are near-antipodal
    lat1 = radians(lat1)
    lat2 = radians(lat2)
    dlat = lat2 - lat1
    dlon = radians(lon2 - lon1)
    h = haversine(dlat) + cos(lat1) * cos(lat2) * haversine(dlon)
    return RADIUS * inverse_haversine(h)

def bounding_box(lat, lon, distance):
    # Input and output lats/longs are in degrees.
    # Distance arg must be in same units as RADIUS.
    # Returns (dlat, dlon) such that
    # no points outside lat +/- dlat or outside lon +/- dlon
    # are <= "distance" from the (lat, lon) point.
    # Derived from: http://janmatuschek.de/LatitudeLongitudeBoundingCoordinates
    # WARNING: problems if North/South Pole is in circle of interest
    # WARNING: problems if longitude meridian +/-180 degrees intersects circle of interest
    # See quoted article for how to detect and overcome the above problems.
    # Note: the result is independent of the longitude of the central point, so the
    # "lon" arg is not used.
    dlat = distance / RADIUS
    dlon = asin(sin(dlat) / cos(radians(lat)))
    return degrees(dlat), degrees(dlon)

if __name__ == "__main__":

    # Examples from Jan Matuschek's article

    def test(lat, lon, dist):
        print "test bounding box", lat, lon, dist
        dlat, dlon = bounding_box(lat, lon, dist)
        print "dlat, dlon degrees", dlat, dlon
        print "lat min/max rads", map(radians, (lat - dlat, lat + dlat))
        print "lon min/max rads", map(radians, (lon - dlon, lon + dlon))

    print "liberty to eiffel"
    print distance_between_points(40.6892, -74.0444, 48.8583, 2.2945) # about 5837 km
    print
    print "calc min/max lat/lon"
    degs = map(degrees, (1.3963, -0.6981))
    test(*degs, dist=1000)
    print
    degs = map(degrees, (1.3963, -0.6981, 1.4618, -1.6021))
    print degs, "distance", distance_between_points(*degs) # 872 km
从数学导入sin、cos、asin、sqrt、度、弧度
地球半径公里=6371.0
半径=地球半径×公里
def haversine(角度弧度):
返回正弦(角度×弧度/2.0)**2
def逆哈弗森(h):
返回2*asin(sqrt(h))弧度
def点之间的距离(lat1、lon1、lat2、lon2):
#所有参数均以度为单位
#警告:当点接近对足点时,绝对精度损失
lat1=弧度(lat1)
lat2=弧度(lat2)
dlat=lat2-lat1
dlon=弧度(lon2-lon1)
h=haversine(dlat)+cos(lat1)*cos(lat2)*haversine(dlon)
返回半径*逆哈弗斯线(h)
def边界框(纬度、经度、距离):
#输入和输出lat/long以度为单位。
#距离arg的单位必须与半径相同。
#返回(dlat、dlon),以便
#lat+/-dlat或lon+/-dlon外无点

#似乎没有一个好的Python实现。幸运的是,“相关文章”侧栏是我们的朋友。指向提供数学和Java实现的。您需要的实际函数很短,嵌入在下面我的Python代码中。测试到一定程度。阅读注释中的警告

from math import sin, cos, asin, sqrt, degrees, radians

Earth_radius_km = 6371.0
RADIUS = Earth_radius_km

def haversine(angle_radians):
    return sin(angle_radians / 2.0) ** 2

def inverse_haversine(h):
    return 2 * asin(sqrt(h)) # radians

def distance_between_points(lat1, lon1, lat2, lon2):
    # all args are in degrees
    # WARNING: loss of absolute precision when points are near-antipodal
    lat1 = radians(lat1)
    lat2 = radians(lat2)
    dlat = lat2 - lat1
    dlon = radians(lon2 - lon1)
    h = haversine(dlat) + cos(lat1) * cos(lat2) * haversine(dlon)
    return RADIUS * inverse_haversine(h)

def bounding_box(lat, lon, distance):
    # Input and output lats/longs are in degrees.
    # Distance arg must be in same units as RADIUS.
    # Returns (dlat, dlon) such that
    # no points outside lat +/- dlat or outside lon +/- dlon
    # are <= "distance" from the (lat, lon) point.
    # Derived from: http://janmatuschek.de/LatitudeLongitudeBoundingCoordinates
    # WARNING: problems if North/South Pole is in circle of interest
    # WARNING: problems if longitude meridian +/-180 degrees intersects circle of interest
    # See quoted article for how to detect and overcome the above problems.
    # Note: the result is independent of the longitude of the central point, so the
    # "lon" arg is not used.
    dlat = distance / RADIUS
    dlon = asin(sin(dlat) / cos(radians(lat)))
    return degrees(dlat), degrees(dlon)

if __name__ == "__main__":

    # Examples from Jan Matuschek's article

    def test(lat, lon, dist):
        print "test bounding box", lat, lon, dist
        dlat, dlon = bounding_box(lat, lon, dist)
        print "dlat, dlon degrees", dlat, dlon
        print "lat min/max rads", map(radians, (lat - dlat, lat + dlat))
        print "lon min/max rads", map(radians, (lon - dlon, lon + dlon))

    print "liberty to eiffel"
    print distance_between_points(40.6892, -74.0444, 48.8583, 2.2945) # about 5837 km
    print
    print "calc min/max lat/lon"
    degs = map(degrees, (1.3963, -0.6981))
    test(*degs, dist=1000)
    print
    degs = map(degrees, (1.3963, -0.6981, 1.4618, -1.6021))
    print degs, "distance", distance_between_points(*degs) # 872 km
从数学导入sin、cos、asin、sqrt、度、弧度
地球半径公里=6371.0
半径=地球半径×公里
def haversine(角度弧度):
返回正弦(角度×弧度/2.0)**2
def逆哈弗森(h):
返回2*asin(sqrt(h))弧度
def点之间的距离(lat1、lon1、lat2、lon2):
#所有参数均以度为单位
#警告:当点接近对足点时,绝对精度损失
lat1=弧度(lat1)
lat2=弧度(lat2)
dlat=lat2-lat1
dlon=弧度(lon2-lon1)
h=haversine(dlat)+cos(lat1)*cos(lat2)*haversine(dlon)
返回半径*逆哈弗斯线(h)
def边界框(纬度、经度、距离):
#输入和输出lat/long以度为单位。
#距离arg的单位必须与半径相同。
#返回(dlat、dlon),以便
#lat+/-dlat或lon+/-dlon外无点

#约翰·梅辛的回答对我帮助很大。这里有一个小错误:纬度和经度在
边界框中交换:

dlon = distance / RADIUS
dlat = asin(sin(dlon) / cos(radians(lon)))
return degrees(dlat), degrees(dlon)

这就解决了问题。原因是经度不会改变每度的距离,但经度会改变。它们的距离取决于经度。

约翰·梅辛的回答对我帮助很大。只是有一个小错误:经度和经度在
边界框
中交换:

dlon = distance / RADIUS
dlat = asin(sin(dlon) / cos(radians(lon)))
return degrees(dlat), degrees(dlon)

这就解决了问题。原因是经度不会改变每度的距离,但经度会改变距离。它们的距离取决于经度。

对不起,我不明白。您希望inverse\u haversine返回一个可调用的参数,该参数采用“other”参数并返回True或False吗?还是您计划传递“other”“以其他方式?(1)“有人能指给我看吗”:someone==google(2)“提供了dlat,dlng,这样”没有提到dlat,dlng的东西——请编辑你的问题。(3) “距离度量的上确界范数”是什么?@johnmachin。当然,谷歌也是你的朋友,因为它了解了最高标准。@Ranieri抱歉,编辑了这个函数来澄清dlat,dlng。反向haversine应给出lat/lng中相对于参考地理代码的最大增量,以定义参考地理代码周围的最大距离平方区域。@AndrewB:我知道什么是“上确界范数”。我