将纬度、经度转换为距赤道的距离(以公里为单位)并舍入到最近的公里

Convert latitude, longitude to distance from equator in kilometers and round to nearest kilometer

对于我拥有的每个坐标,我找到了以公里为单位的距赤道的距离,并给出了两个距离:

from pyproj import Geod
wgs84_geod = Geod(ellps='WGS84')    
_,_, lon_dist = wgs84_geod.inv(0, 0,lon, 0)
_,_, lat_dist = wgs84_geod.inv(0, 0,0, lat)

作为完整性检查,我可以从这些值重新计算原始坐标如下(假设赤道坐标 (0,0) 的方向是北和西:

_, new_lat, _ = wgs84_geod.fwd(0,0, 0, lat_dist)
new_lon, _, _ = wgs84_geod.fwd(0, 0, 90, lon_dist)

这让我返回了与开始时相同的坐标。

现在我想找到离我的坐标最近的公里点。我将 lon_dist 和 lat_dist 四舍五入到距赤道值公里数。

lat_km_dist = round(lat_dist/1000)*1000 #to nearest km and back to meters
lon_km_dist = round(lon_dist/1000)*1000 

我以与以前相同的方式使用这些距离获取坐标

_, km_lat, _ = wgs84_geod.fwd(0,0, 0, lat_km_dist)
km_lon, _, _ = wgs84_geod.fwd(0, 0, 90, lon_km_dist)

逻辑上应该是,对于同一区域的多个坐标,任何km_lat、km_lon对之间的最近距离应该是1km。 这在 North/South 轴上是正确的,但对于经度,距离会根据我所在的纬度而变化。 我附上两个屏幕截图以可视化 km_lat、km_lon 坐标由面积为 1km 的多边形中心的黑色圆圈表示的问题。

我该如何纠正?

这个算法本质上是在赤道 (lat=0) 和主子午线 (lon=0) 上构造一个等距网格(点间距为 1km)。然后它有效地在椭圆体上构建一个网格作为这些点的笛卡尔积。

然而,lat/lon坐标不构成笛卡尔坐标系,由这些网格点生成的结果parallels/meridians定义"squares"其大小不仅取决于特定的经度, 但纬度也是如此。在一个完美的球体上,这将适用于南北方向,因为 lon=0 上的等距(根据大圆距离)网格在纬度上也是等距的(纬度差等于距离差)球体的半径)。

换句话说,如果您固定两个纬度 lat1lat2 并且对于特定的经度 lon(lat1, lon)(lat2, lon) 移动 1 公里, 比如说, 向西方向, 那么这些新得到的点不会有相同的经度...

我不完全确定你想要达到什么目的,但如果目标是获得一些彼此不太接近的代表点,那么也许 hierarchical clustering 就大圆距离而言可以提供合理的结果...

编辑:

作为一种近似的解决方法,您最有可能通过选择 (0, 0) 之外的另一个参考点来摆脱困境 - 新参考点不应距离您试图描述的区域太远(某物例如感兴趣区域的 "bottom-left" 角)。如果整个感兴趣区域没有覆盖地球的很大一部分(大纬度跨度),那么差异将非常小,因此它们可能在 GoogleMaps 可视化中几乎不可见...

因此,如果您对丹麦感兴趣(根据屏幕截图判断),那么类似以下内容可能有用:

lat_ref, lon_ref = 53.637976, 6.694138

_,_, lon_dist = wgs84_geod.inv(lon_ref,lat_ref, lon, 0)
_,_, lat_dist = wgs84_geod.inv(lon_ref,lat_ref, 0, lat)

lat_km_dist = round(lat_dist/1000)*1000 #to nearest km and back to meters
lon_km_dist = round(lon_dist/1000)*1000


_, km_lat, _ = wgs84_geod.fwd(lon_ref,lat_ref,  0, lat_km_dist)
km_lon, _, _ = wgs84_geod.fwd(lon_ref,lat_ref, 90, lon_km_dist)