将纬度、经度转换为距赤道的距离(以公里为单位)并舍入到最近的公里
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 上的等距(根据大圆距离)网格在纬度上也是等距的(纬度差等于距离差)球体的半径)。
换句话说,如果您固定两个纬度 lat1
、lat2
并且对于特定的经度 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)
对于我拥有的每个坐标,我找到了以公里为单位的距赤道的距离,并给出了两个距离:
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 上的等距(根据大圆距离)网格在纬度上也是等距的(纬度差等于距离差)球体的半径)。
换句话说,如果您固定两个纬度 lat1
、lat2
并且对于特定的经度 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)