【问题标题】:How can I sort a coordinate list for a rectangle counterclockwise?如何逆时针对矩形的坐标列表进行排序?
【发布时间】:2009-11-10 16:32:46
【问题描述】:

我需要对一个矩形的坐标列表进行逆时针排序,并将东北角作为第一个坐标。这些是十进制形式的地理坐标(即经度、纬度)。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当映射到地球表面时,这不是一个真正的矩形,但是由于我确实有 2 个对角,所以为了便于阅读,我将其称为矩形。环绕 +180/-180 经度或 +90/-90 纬度的形状不是问题。

【问题讨论】:

    标签: python algorithm sorting coordinates geospatial


    【解决方案1】:

    解决方案似乎很简单:

    >>> 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) 周围的括号对于获得有效结果很重要。

    【讨论】:

    • 不错。这看起来类似于 @tom10 试图传达的内容(没有映射到 [0, 2pi]),对吗?
    • 是的,在我实现我的代码之前还没有看到他的回复。唯一的区别确实是获得这个订单。我也测试了我的代码:)
    • @SilentGhost:您在回答中说列表将按顺时针排序,但这实际上不是按我的要求逆时针排序吗?
    • @Crescent Fresh:当然,它是逆时针排序的,只是一个错字。
    【解决方案2】:

    假设您的“矩形”始终平行于赤道和子午线(这就是您的示例所暗示的,但没有明确说明),即您只有两对不同的 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代码)

    【讨论】:

    • +1 因为这个解释比我的更清楚,并且使假设明确
    • @Curd:问题底部的脚注试图传达您所说的内容(不想进入问题中的纬度/经度线)。无论如何,找到对角 (lat0, lat1)(lng0, lng1) 本身就是搜索最小和最大点(分别产生 SW 和 NE 角),对吗?
    • @Crescent Fresh:在你上面的问题中,我不明白你所说的“对角......”是什么意思。使用“(lat0,lat1)”我只是指您的两个纬度值的列表。顺序无关紧要。
    • @Curd:在我的场景中,我有 4 个坐标,而不是 2 个。找到你所说的 2 是为了从 4 个相互对立的坐标中找到 2 个。
    【解决方案3】:

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

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

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

    【讨论】:

    • “重建”两个相对角的列表相当于我想对整个列表进行排序,尽管有点不正统。
    【解决方案4】:

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

    要计算角度,请在形状中间找一个点,例如,(average_lat, average_lng) 将在中心。那么atan2(lng - average_lng, lat - average_lat)就是那个点的角度。

    【讨论】:

      【解决方案5】:

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

      【讨论】:

      • 我需要的不仅仅是方向,我还需要按发布顺序排序的列表,以便进一步操作。
      • @Crescent Fresh - 知道方向是正确分类的第一步,不是吗?如果您需要它以逆时针顺序排列并且列表按顺时针顺序排列,那么您将列表反转并且 - ta da - 您按逆时针顺序排列它。
      • 抱歉,我没有说得很清楚:我需要从 north-east 角开始排序的列表。仅仅知道方向并不能告诉我列表中的哪个项目是东北方向。
      【解决方案6】:

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

      先按 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}]
      

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

      【讨论】:

      • 我想知道这是否适用于穿越赤道或本初子午线(lat/lng 从- 翻转到+)...
      • 实际上应该可以正常工作。如果没有交换,会更喜欢它;)+1
      • 没有交换是不可能的:我们需要先从北到南排序,然后才能知道哪些点是最南端的,然后我们从东西方向反向排序。
      【解决方案7】:

      所以,你有 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 开始,fixt。

      【讨论】:

      • 知道该列表是否从 NW 开始。抱歉,如果不清楚。
      猜你喜欢
      • 2020-01-07
      • 2012-10-29
      • 2021-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-23
      • 1970-01-01
      相关资源
      最近更新 更多