按脚印排序包含经纬度的字典
我正在计算卫星在椭球表面的覆盖区域,得到的结果是一个包含经纬度的列表,格式如下。这是一个包含字典的Python列表。如果我在Matlab或Matplotlib中用散点图展示这些点,我会得到一堆不连贯的3D点。不过,我想用绘图命令(而不是散点图)来画出一个光滑的3D圆圈,来表示这个覆盖区域。为了做到这一点,我需要对这些点进行排序。我尝试过使用哈弗辛公式(计算大圆距离)来找出每个点的最近邻,但在处理较大的数据集(比如地球静止卫星)时,这样仍然会出现偶尔不连贯的线。我还尝试在覆盖区域跨越赤道时,将值分成南北纬度,然后按经度排序。我可能遗漏了一些东西——有没有人有更好或更快的方法来排序这样的列表,以便连接列表中的所有连续点,形成一个完整、有序的圆圈呢?
latLons = [{'lat': -33.783781327, 'lon': 137.47747747700001}, {'lat': -33.783781326899998, 'lon': 139.63963964000001}, {'lat': -33.603601166200001, 'lon': 136.03603603600001}, {'lat': -33.423421005500003, 'lon': 134.59459459499999}, {'lat': -32.882880523399997, 'lon': 132.43243243200001}, {'lat': -32.522520202199999, 'lon': 131.71171171200001}, {'lat': -32.342340041600004, 'lon': 145.40540540500001}, {'lat': -31.261259078399998, 'lon': 147.56756756799999}, {'lat': -31.081078917799999, 'lon': 128.828828829}, {'lat': -29.459457473099999, 'lon': 126.666666667}, {'lat': -28.558556670200002, 'lon': 125.94594594599999}, {'lat': -27.657655866700001, 'lon': 125.225225225}, {'lat': -26.936935223300001, 'lon': 151.89189189199999}, {'lat': -26.7567550624, 'lon': 124.504504504}, {'lat': -25.6756740961, 'lon': 152.61261261300001}, {'lat': -25.3153137736, 'lon': 123.78378378399999}, {'lat': -23.873872481599999, 'lon': 153.33333333300001}, {'lat': -23.333331995999998, 'lon': 123.063063063}, {'lat': -19.3693684138, 'lon': 154.05405405400001}, {'lat': -15.765765115600001, 'lon': 123.063063063}, {'lat': -15.2252246167, 'lon': 153.33333333300001}, {'lat': -13.243242777300001, 'lon': 152.61261261300001}, {'lat': -12.162161767000001, 'lon': 124.504504505}, {'lat': -11.801801428999999, 'lon': 151.89189189199999}, {'lat': -10.9009005815, 'lon': 125.225225225}, {'lat': -8.1981980155999992, 'lon': 149.00900900900001}, {'lat': -6.9369368056800003, 'lon': 147.56756756799999}, {'lat': -6.5765764584799999, 'lon': 129.54954954999999}, {'lat': -6.5765764584799999, 'lon': 146.84684684699999}, {'lat': -5.6756755875199998, 'lon': 130.99099099099999}, {'lat': -4.7747747122700002, 'lon': 143.24324324299999}, {'lat': -4.23423418502, 'lon': 141.08108108100001}, {'lat': -3.8738738326600002, 'lon': 138.198198198}]
2 个回答
0
我觉得普通的排序可能不太适合你的需求。在普通排序中,物品之间有一个绝对的顺序。但在这里,你没有绝对的顺序(比如,哪个坐标是“第一个”?),只有相对的顺序。
首先,我会把数据从字典中提取出来,放到一个元组的列表里:
latlonslist = [ (x['lat'],x['lon']) for x in latLons ]
然后你可以import scipy.spatial
,使用你选择的距离来找到每个点最近的邻居。当然,你也可以直接使用欧几里得距离,而不需要用到scipy。
用类似下面的方式计算所有可能的距离(应该是n^2
次操作):
distances = {}
for n1 in latlonslist:
for n2 in latlonslist:
if n1 == n2:
continue
thisdist = scipy.spatial.distance.euclidean(n1,n2)
distances[n1,n2] = thisdist
然后从任意一个节点开始,遍历节点列表,在每一步中寻找最近的节点。
1
一种方法是把你的点用极坐标表示,也就是相对于中心点来表示,然后用角度作为排序的依据。
下面是一个简单的实现:
import matplotlib.pyplot as plt
import math
def polar_sort(l):
x, y = zip(*((c['lat'], c['lon']) for c in l))
ave_x = float(sum(x))/len(x)
ave_y = float(sum(y))/len(y)
return sorted(l, key=lambda c: math.atan2(c['lat']-ave_x, c['lon']-ave_y))
latLons = [{'lat': -33.783781327, 'lon': 137.47747747700001}, {'lat': -33.783781326899998, 'lon': 139.63963964000001}, {'lat': -33.603601166200001, 'lon': 136.03603603600001}, {'lat': -33.423421005500003, 'lon': 134.59459459499999}, {'lat': -32.882880523399997, 'lon': 132.43243243200001}, {'lat': -32.522520202199999, 'lon': 131.71171171200001}, {'lat': -32.342340041600004, 'lon': 145.40540540500001}, {'lat': -31.261259078399998, 'lon': 147.56756756799999}, {'lat': -31.081078917799999, 'lon': 128.828828829}, {'lat': -29.459457473099999, 'lon': 126.666666667}, {'lat': -28.558556670200002, 'lon': 125.94594594599999}, {'lat': -27.657655866700001, 'lon': 125.225225225}, {'lat': -26.936935223300001, 'lon': 151.89189189199999}, {'lat': -26.7567550624, 'lon': 124.504504504}, {'lat': -25.6756740961, 'lon': 152.61261261300001}, {'lat': -25.3153137736, 'lon': 123.78378378399999}, {'lat': -23.873872481599999, 'lon': 153.33333333300001}, {'lat': -23.333331995999998, 'lon': 123.063063063}, {'lat': -19.3693684138, 'lon': 154.05405405400001}, {'lat': -15.765765115600001, 'lon': 123.063063063}, {'lat': -15.2252246167, 'lon': 153.33333333300001}, {'lat': -13.243242777300001, 'lon': 152.61261261300001}, {'lat': -12.162161767000001, 'lon': 124.504504505}, {'lat': -11.801801428999999, 'lon': 151.89189189199999}, {'lat': -10.9009005815, 'lon': 125.225225225}, {'lat': -8.1981980155999992, 'lon': 149.00900900900001}, {'lat': -6.9369368056800003, 'lon': 147.56756756799999}, {'lat': -6.5765764584799999, 'lon': 129.54954954999999}, {'lat': -6.5765764584799999, 'lon': 146.84684684699999}, {'lat': -5.6756755875199998, 'lon': 130.99099099099999}, {'lat': -4.7747747122700002, 'lon': 143.24324324299999}, {'lat': -4.23423418502, 'lon': 141.08108108100001}, {'lat': -3.8738738326600002, 'lon': 138.198198198}]
x,y = zip(*((c['lat'], c['lon']) for c in polar_sort(latLons)))
plt.plot(x,y)
plt.show()