如何逆时针对矩形的坐标列表进行排序?

时间:2009-11-10 16:32:46

标签: python algorithm sorting coordinates geospatial

我需要逆时针对矩形的坐标列表进行排序,并将东北角作为第一个坐标。这些是十进制形式的地理坐标(即经度,纬度)。 1

例如,这里是一个矩形的4个角,从西北角开始顺时针移动:

[
  { "lat": 34.495239, "lng": -118.127747 }, # north-west
  { "lat": 34.495239, "lng": -117.147217 }, # north-east
  { "lat": 34.095174, "lng": -117.147217 }, # south-east
  { "lat": 34.095174, "lng": -118.127747 }  # south-west
]

我需要逆时针对它们进行排序并将“锚点”/起点改为东北方向:

[
  { "lat": 34.495239, "lng": -117.147217 }, # north-east
  { "lat": 34.495239, "lng": -118.127747 }, # north-west
  { "lat": 34.095174, "lng": -118.127747 }, # south-west
  { "lat": 34.095174, "lng": -117.147217 }  # south-east
]

我不知道列表最初的顺序(即顺时针或逆时针)。我不知道列表中第一个坐标代表哪个角。


1 当映射到地球表面时,这不是一个真正的矩形,但是因为我有两个相对的角,所以我称之为矩形以便于阅读。包裹+ 180 / -180经度或+ 90 / -90纬度的形状不是问题。

7 个答案:

答案 0 :(得分:8)

解决方案看起来非常简单:

>>> import math
>>> mlat = sum(x['lat'] for x in l) / len(l)
>>> mlng = sum(x['lng'] for x in l) / len(l)
>>> def algo(x):
    return (math.atan2(x['lat'] - mlat, x['lng'] - mlng) + 2 * math.pi) % (2*math.pi)

>>> l.sort(key=algo)

基本上,algo将输入标准化为[0, 2pi]空间,并且它将自然地“逆时针”排序。请注意,%运算符和*运算符具有相同的优先级,因此括号(2 * math.pi)对于获得有效结果非常重要。

答案 1 :(得分:5)

假设你的“矩形”总是与赤道和经线平行(这就是你的例子所暗示的,但它没有明确说明),即你只有两对不同的lat和lng值:(lat0,lat1)和(lng0,lng1)。

你得到以下4个角落:

NE: (lat = max(lat0, lat1), lng = max(lng0, lng1))
NW: (lat = max(lat0, lat1), lng = min(lng0, lng1))
SW: (lat = min(lat0, lat1), lng = min(lng0, lng1))
SE: (lat = min(lat0, lat1), lng = max(lng0, lng1))

(这不应该是python代码)

答案 2 :(得分:3)

您可以按照您想要的任何顺序“重建”矩形,而不是排序。

从原始集合中,收集最小和最大纬度以及最小和最大经度。然后以任何你想要的顺序构造矩形。

西北角是最大纬度和经度。西南角是最小经度和最小经度。等

答案 3 :(得分:3)

将角度与每个点(相对于内部点)相关联,然后四处移动是微不足道的。

要计算角度,请在形状中间找到一个点,例如,(average_lat, average_lng)将位于中心。然后,atan2(lng - average_lng, lat - average_lat)将成为该点的角度。

答案 4 :(得分:1)

如果从角落取两个向量的叉积,那么结果的符号将告诉你它是顺时针还是逆时针。

答案 5 :(得分:1)

很容易。首先,我们对坐标进行排序,以便我们知道它们的顺序,然后我们只需选择它们:

首先按lat然后按lng排序,最大的第一个。然后我们交换最后两个:

L = [
  { "lat": 34.495239, "lng": -118.127747 }, # north-west
  { "lat": 34.495239, "lng": -117.147217 }, # north-east
  { "lat": 34.095174, "lng": -117.147217 }, # south-east
  { "lat": 34.095174, "lng": -118.127747 }  # south-west
]


L = sorted(L, key=lambda k: (-k["lat"], -k["lng"]))

L[-2], L[-1] = L[-1], L[-2]
import pprint
pprint.pprint(L)

输出

[{'lat': 34.495238999999998, 'lng': -117.147217},
 {'lat': 34.495238999999998, 'lng': -118.127747},
 {'lat': 34.095174, 'lng': -118.127747},
 {'lat': 34.095174, 'lng': -117.147217}]

(关键函数中的缺点是这样,较大的值在较小的值之前排序。通过排序我们将北向前放北,然后在向西之前向东;为了获得所需的顺序,我们只需交换最后两个(南方)值。 )

答案 6 :(得分:0)

所以,你有4分。

你总是从NW点开始。

你知道这些点是分类的,而不是在哪个方向。

这是前两个点的简单测试,无论列表是顺时针还是逆时针。

如果(pt1.y!= pt2.y)则方向=顺时针。

如果您检测到点是顺时针方向,则简单地反转列表中的最后3个点。

所以

逆时针点:(0,1),(0,0),(1,0),(1,1)

顺时针点:(0,1),(1,1),(1,0),(0,0)

您可以查看是否反转pts2-4顺时针列表变为逆时针。

编辑:我从NE开始得到我的积分,固定。