【问题标题】:Retreiving neighbors with geohash algorithm?使用 geohash 算法检索邻居?
【发布时间】:2019-08-27 09:49:28
【问题描述】:

我正在查看 GIS SE -Using geohash for proximity searches? 上这个最受好评的接受答案的 pythonic 实现,但我无法为我的 geohash 查询检索任何匹配项。这是我迄今为止尝试过的方法。

要运行此最小可验证完整示例 (MVCE),您需要下载以下文件 - geohash intsortedlist python 并通过pip 安装python 排序列表。你还需要在你的机器上安装最新版本的 Cython,以便包装 geohash-int 的 C 功能(注意我只包装了这个 MVCE 所必需的东西)。

geohash_test.py

# GeoHash is my Cython wrapper of geohash-int C package
from geo import GeoHash
from sortedcontainers import SortedList

import numpy as np

def main():
    # Bounding coordinates of my grid.
    minLat = 27.401436
    maxLat = 62.54858
    minLo = -180.0
    maxLo = 179.95000000000002
    latGrid = np.arange(minLat,maxLat,0.05)
    lonGrid = np.arange(minLo,maxLo,0.05)
    geoHash = GeoHash()

    # Create my own data set of points with a resolution of
    # 0.05 in the latitude and longitude direction. 
    gridLon,gridLat = np.meshgrid(lonGrid,latGrid)
    grid_points = np.c_[gridLon.ravel(),gridLat.ravel()]

    sl = SortedList()

   #Store my grid points in the best resolution possible i.e. 52(First step in accepted answer)
   for grid_point in grid_points:
      lon = grid_point[0]
      lat = grid_point[1]
      geohash = geoHash.encode(lat,lon,52)
      bitsOriginal = geohash["bits"]
      sl.add(bitsOriginal)
      #Derive the minimum and maximum value for the range query from method below
   minValue,maxValue = getMinMaxForQueryGeoHash(geoHash)
   # Do the actual range query with a sorted list
   it = sl.irange(minValue,maxValue,inclusive=(False,False))
   print(len(list(it)))

def getMinMaxForQueryGeoHash(geoHash):
    lonTest = 172.76843
    latTest = 61.560745

    #Query geohash encoded at resolution 26 because my search area
    # is around 10 kms.(Step 2 and 3 in accepted answer)

    queryGeoHash = geoHash.encode(latTest,lonTest,26)

    # Step 4 is getting the neighbors for query geohash

    neighbors = geoHash.get_neighbors(queryGeoHash)
    bitsList = []
    for key,value in neighbors.items():
       bitsList.append(value["bits"])

    #Step 5 from accepted answer
    bitsList.append(queryGeoHash["bits"])

   # Step 6 We need 1 to all the neighbors 
   newList = [x+1 for x in bitsList]
   joinedList = bitsList + newList

    #Step 7 Left bit shift this to 52 
    newList2 = [x <<26 for x in joinedList]
    #Return min and max value to main method
    minValue = min(newList2)
    maxValue = max(newList2)
    return minValue,maxValue

 main()

如果有人把它写成伪代码,这就是我正在做的事情

  1. 鉴于我的边界框是一个网格,我通过计算每个纬度和经度的 geohash(这恰好是位深度 52)以可能的最高分辨率存储它

  2. 我将 geohash 添加到排序列表中

  3. 然后我想通过指定搜索半径为 10 公里的特定查询坐标来进行范围查询

  4. 从接受的答案中,您需要查询 geohash 的最小值和最大值

  5. 我在getMinMaxForQueryGeoHash方法中计算最小值和最大值

  6. 计算位深度为26的查询geohash(这是10公里的半径)

  7. 计算查询geohash的邻居并创建18个成员数组

  8. 18个成员是C方法返回的8个邻居加上原始查询geohash,剩下的9个是这个数组加1得到的

  9. 然后将这个数组左移26位,并将最小值和最大值返回给有序列表的irange查询。

    位移 = 52(最大分辨率) - 查询 geohash 精度(26) = 26

但该查询返回给我一个NULL。有人可以解释我哪里出错了吗?

【问题讨论】:

    标签: python-3.x nearest-neighbor proximity geohashing


    【解决方案1】:

    使用您的行话:对于 MVCE,您不需要复杂的两种语言实现。 Geohash 有很多简单的优秀实现,其中一些使用 100% Python (example)。他们都使用Morton Curve (example)。

    结论:尝试即插即用纯Python实现,先测试encode/decode,再测试neighbors(geohash)函数的使用。

    【讨论】:

    • 感谢您的回答。我正在尝试使用 geohash 来执行我所谓的近似最近邻搜索而不计算距离(这在我当前的代码中非常昂贵)。我会对近似匹配感到满意。因此需要范围查询。
    • 我引用的 neighbors(geohash)is here in the cited example... 但它是拓扑的,要转换为“计算距离”,您必须从单元宽度或单元质心估计... LatLong 不是公制,请参阅faster distance estimators as Turf 或任何 Python geo-lib。如果需要超过“1个单元格距离”需要使用迭代,因此对于超过1个或2个单元格距离的“最近邻搜索”效率不高(您对焦点不精确)。
    • 现在我开始明白了(我想)。您是说我的经纬度网格不能用于使用 geohash 进行范围查询。但是,如果数据是拓扑的,例如球体或椭球体,则可以使用 geohash 对这些点进行索引,然后我们可以进行范围查询。我说的对吗?
    • 拓扑在这种情况下是关于“网格单元拓扑”和4-connected or 8-connected的选择...好吧,您也可以“全部倒带”并检查您真正问题的大局。今天(2019 年)还有其他更快的索引可以做到这一点,我认为最好的索引是 H3 Uber,基于六边形网格。
    猜你喜欢
    • 2015-09-28
    • 2020-06-21
    • 2020-02-25
    • 2012-04-27
    • 2015-09-14
    • 1970-01-01
    • 1970-01-01
    • 2020-08-12
    • 1970-01-01
    相关资源
    最近更新 更多