查找与点最近的坐标

2024-10-01 15:30:55 发布

您现在位置:Python中文网/ 问答频道 /正文

我有城市的坐标:(52.2319581, 21.0067249)和Python字典,上面提到的城市周围都有城市。如何从给定坐标获得3个最近的城市:

({'Brwinów': (52.133333, 20.716667), 'Warszawa Bielany': (52.283333, 20.966667), 'Legionowo': (52.4, 20.966667), 'Warszawa-Okęcie': (52.16039, 20.961674), 'Warszawa': (52.280957, 20.961348), 'Belsk Duży': (51.833333, 20.8)}, {})

谢谢你的帮助


Tags: 字典okduciewarszawabelskbielanybrwin
3条回答

每个人都推荐欧几里德距离作为球坐标,当你不靠近赤道时,这是非常错误的。在示例坐标(波兰)中,大约52°纬度:
纬度的1°仍在10000 km/90°=111 km左右,但
经度的1°仅为10000公里*cos(52°)/90°=68公里。
所以至少我们必须用great-circle distance来代替

from math import sin, cos, acos

def angle(c1, 2):
  l1, p1 = c1
  l2, p2 = c2
  return acos(sin(p1) * sin(p2) + cos(p1) * cos(p2) * cos(l2 - l1))

sorted_coords = sorted(coords, key=lambda city: angle(city, center))
print(sorted_coords[:3])

更有可能的是,这些坐标甚至不是球坐标,而是使用球体的WGS84,但如果整个城市都可以被视为一个点,那么这种区别就不太重要了

也许这是可行的(这并没有考虑到一个经度意味着不同纬度的不同距离这一事实)

the_city = (52.2319581, 21.0067249)
cities = ({'Brwinów': (52.133333, 20.716667), 'Warszawa Bielany': (52.283333, 20.966667), 'Legionowo': (52.4, 20.966667), 'Warszawa-Okęcie': (52.16039, 20.961674), 'Warszawa': (52.280957, 20.961348), 'Belsk Duży': (51.833333, 20.8)}, {})

closest3 = sorted(cities[0], key=lambda k: (cities[0][k][0]-the_city[0])**2 + (cities[0][k][1]-the_city[1])**2)[:3]

没有任何外部库

from math import acos, cos, sin

def gc_distance(first_point, second_point):
    return acos(sin(first_point[1]) * sin(second_point[1]) + cos(first_point[1]) * cos(second_point[1]) * cos(first_point[0] - second_point[0]))

def three_closest(city, cities):
    cities_distances = { key: gc_distance(city, value) for key, value in cities.items()}
    return [k for k, v in sorted(cities_distances.items(), key=lambda item: item[1])][:3]

样本测试:

>>> city = (52.2319581, 21.0067249)
>>> cities = {'Brwinów': (52.133333, 20.716667), 'Warszawa Bielany': (52.283333, 20.966667), 'Legionowo': (52.4, 20.966667), 'Warszawa-Okęcie': (52.16039, 20.961674), 'Warszawa': (52.280957, 20.961348), 'Belsk Duży': (51.833333, 20.8)}
>>> three_closest(city, cities)
['Warszawa Bielany', 'Warszawa', 'Warszawa-Okęcie']

如果要返回键和值,请执行以下操作:

for result in three_closest(city, cities):
    print(result + " : " + str(cities[result]))

要获得:

Warszawa Bielany : (52.283333, 20.966667)
Warszawa : (52.280957, 20.961348)
Warszawa-Okęcie : (52.16039, 20.961674)

相关问题 更多 >

    热门问题