如何在Python中按顺时针/逆时针方向对点列表进行排序?

2024-01-09

我得到了坐标点列表,我想按顺时针/逆时针对它们进行排序。

这是我提到的清单:
[(985, 268), (112, 316), (998, 448), (1018, 453), (1279, 577), (1196, 477), (1161, 443), (986, 0), (830, 0), (983, 230), (998, 425), (998, 255)]

这些坐标点将帮助我绘制物体的线段。下面是用于说明的图像。正如您所看到的,我已经标记了该图像列表中的所有点。

我的目标是对这些坐标点进行排序,以创建多个线段。因此,我的预期结果如下:
逆时针方向:[(985, 268), (998, 425), (112, 316), (998, 448), (1018, 453), (1279, 577), (1196, 477), (1161, 443), (998, 255), (986, 0), (983, 230), (830, 0)]

顺时针方向:[(985, 268), (830, 0),(983, 230), (986, 0), (998, 255), (1161, 443), (1196, 477), (1279, 577), (1018, 453), (998, 448), (112, 316), (998, 425)]

到目前为止,我已经建立了一个网站,https://www.baeldung.com/cs/sort-points-顺时针 https://www.baeldung.com/cs/sort-points-clockwise,作为参考并编写了以下代码,但它不起作用:

def getDistance(pt1 , pt2):
    x = pt1[0] - pt2[0]
    y = pt1[1] - pt2[1]
    return math.sqrt(x*x+y*y)

def getAngle(pt_center, pt):
    x = pt[0] - pt_center[0]
    y = pt[1] - pt_center[1]
    angle = math.atan2(y,x)

    if angle <= 0:
        angle = 2*math.pi + angle

    return angle

def comparePoints(pt_center, pt1, pt2):
    angle1 = getAngle(pt_center, pt1)
    angle2 = getAngle(pt_center, pt2)

    if angle1 < angle2:
        return True

    d1 = getDistance(pt_center, pt1)
    d2 = getDistance(pt_center, pt2)

    if angle1 == angle2 and d1 < d2:
        return True

    return False

final_concave_points_list = []
for items in final_concave_points:
    final_concave_points_list.append([])
    for points in items:
        final_concave_points_list[-1].append(list(points))

pt_center = [0,0]
point = []
points = final_concave_points_list[0]
for pt in points:
    pt_center[0] = pt_center[0] + pt[0]
    pt_center[1] = pt_center[1] + pt[1]

pt_center[0] = pt_center[0] / len(points)
pt_center[1] = pt_center[1] / len(points)

for pt in points:
    pt[0] = pt[0] - pt_center[0]
    pt[1] = pt[1] - pt_center[1]
    point.append((pt[0], pt[1]))
print(point)

'''
[(23.0, -56.333333333333314), (-850.0, -8.333333333333314), (36.0, 123.66666666666669), (56.0, 128.66666666666669), (317.0, 252.66666666666669), (234.0, 152.66666666666669), (199.0, 118.66666666666669), (24.0, -324.3333333333333), (-132.0, -324.3333333333333), (21.0, -94.33333333333331), (36.0, 100.66666666666669), (36.0, -69.33333333333331)]
'''

points = scaled_point_list[0]
angle_list = []
for concave in points:
    angle = getAngle((0,0), concave)
    angle_list.append(angle)
print(angle_list)

'''
[5.102097551727555, 3.15100414040828, 1.2882413743253092, 1.1612360403462985, 0.6735857636846376, 0.5790742693677309, 0.5389402114087971, 4.78632801804263, 4.325513262653661, 4.932184051908722, 1.2283997388640362, 5.193276260580025]
'''

zipped_list = zip(angle_list, points)
sorted_zipped_lists = sorted(zipped_list)
sorted_list1 = [element for _, element in sorted_zipped_lists]
print(sorted_list1)

'''
[(199, 119), (234, 153), (317, 253), (56, 129), (36, 101), (36, 124), (-850, -8), (-132, -324), (24, -324), (21, -94), (23, -56), (36, -69)]
'''

虽然我将中心点(962, 324)添加回上述每个点,但它们仍然不是期望的结果。

多谢。


我已经在评论中链接了 7 个相关/重复的问题。这些问题通过几种不同的方法得到了有趣的答案。两种主要方法是“计算凸包”方法和“围绕中心”方法。

由于 Danielhao 已经发布了凸包方法的答案,所以让我用中心方法给出答案。

基本算法如下:

  • 定义一个新点C,称为中心; C 可能是任何东西,并且 C 的精确选择将影响结果,特别是如果由点定义的多边形不是凸的。 C 的一个简单选择是取点列表的重心(即取列表中坐标的平均值)。
  • 对于列表中的每个点 P,计算 x 轴和矢量 CP 之间的定向角 alpha_P。
  • 按相关角度对点列表进行排序;逆时针方向按递增顺序,顺时针方向按递减顺序。

python中的实现:

import matplotlib.pyplot as plt  # plot, show
import math                      # atan2

points = [(985, 268), (112, 316), (998, 448), (1018, 453), (1279, 577), (1196, 477), (1161, 443), (986, 0), (830, 0), (983, 230), (998, 425), (998, 255)]

def sort_counterclockwise(points, centre = None):
  if centre:
    centre_x, centre_y = centre
  else:
    centre_x, centre_y = sum([x for x,_ in points])/len(points), sum([y for _,y in points])/len(points)
  angles = [math.atan2(y - centre_y, x - centre_x) for x,y in points]
  counterclockwise_indices = sorted(range(len(points)), key=lambda i: angles[i])
  counterclockwise_points = [points[i] for i in counterclockwise_indices]
  return counterclockwise_points

我强烈鼓励您使用不同的中心坐标值,看看这如何影响点的最终顺序。

points = sort_counterclockwise(points)
plt.plot([x for x,_ in points], [y for _,y in points])
plt.show()
points = sort_counterclockwise(points, (0,0))
plt.plot([x for x,_ in points], [y for _,y in points])
plt.show()
points = sort_counterclockwise(points, (1000, 200))
plt.plot([x for x,_ in points], [y for _,y in points])
plt.show()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在Python中按顺时针/逆时针方向对点列表进行排序? 的相关文章

  • Gunicorn 工作人员无论如何都会超时

    我正在尝试通过gunicorn运行一个简单的烧瓶应用程序 但是无论我做什么 我的工作人员都会超时 无论是否有针对应用程序的活动 工作人员在我设置任何内容后总是会超时timeout值到 是什么导致它们超时 当我发出请求时 请求成功通过 但工作
  • 使用模数按字母顺序对列表进行排序

    我在获取元素列表并按字母顺序对它们进行排序方面没有任何问题 但我很难理解如何使用模数来做到这一点 更新 这是按我的方式工作的代码 但是 我更喜欢下面提供的答案的可重用性 因此接受了该答案
  • 我应该使用 Python 双端队列还是列表作为堆栈? [复制]

    这个问题在这里已经有答案了 我想要一个可以用作堆栈的 Python 对象 使用双端队列还是列表更好 元素数量较少还是数量较多有什么区别 您的情况可能会根据您的应用程序和具体用例而有所不同 但在一般情况下 列表非常适合堆栈 append is
  • Haskell:从后面访问列表

    今天我开始学习Haskell 我对函数式语言有点陌生 而且我非常喜欢 Haskell 然而 我有一个关于它的设计的问题困扰着我 从我到目前为止的理解来看 访问列表后面的元素似乎比访问前面的元素要复杂得多 类似于xs x where xs a
  • PyQt 使用 ctrl+Enter 触发按钮

    我正在尝试在我的应用程序中触发 确定 按钮 我当前尝试的代码是这样的 self okPushButton setShortcut ctrl Enter 然而 它不起作用 这是有道理的 我尝试查找一些按键序列here http ftp ics
  • Pycharm 在 os.path 连接上出现“未解析的引用”

    将pycharm升级到2018 1 并将python升级到3 6 5后 pycharm报告 未解析的引用 join 最新版本的 pycharm 不会显示以下行的任何警告 from os path import join expanduser
  • 打印包含字符串和其他 2 个变量的变量

    var a 8 var b 3 var c hello my name is var a and var b bye print var c 当我运行程序时 var c 会像这样打印出来 hello my name is 8 and 3 b
  • Python 3:将字符串转换为变量[重复]

    这个问题在这里已经有答案了 我正在从 txt 文件读取文本 并且需要使用我读取的数据之一作为类实例的变量 class Sports def init self players 0 location name self players pla
  • 如何匹配 R 中的所有匹配项?

    我有 1000 个名字的列表 说A 我还有另外 5 个名字的清单 说B 我想找出这5个名字出现在1000个号码列表中的第几行 例如 Amy 在 A 中可以出现 25 次 B 里有艾米 我想知道 Amy 出现在 A 中的哪些行 我以前使用过
  • 如何将 ascii 值列表转换为 python 中的字符串?

    我在 Python 程序中有一个列表 其中包含一系列数字 这些数字本身就是 ASCII 值 如何将其转换为可以在屏幕上回显的 常规 字符串 您可能正在寻找 chr gt gt gt L 104 101 108 108 111 44 32 1
  • pandas - 包含时间序列数据的堆积条形图

    我正在尝试使用时间序列数据在 pandas 中创建堆积条形图 DATE TYPE VOL 0 2010 01 01 Heavy 932 612903 1 2010 01 01 Light 370 612903 2 2010 01 01 Me
  • Python - 如何确定解析的 XML 元素的层次结构级别?

    我正在尝试使用 Python 解析 XML 文件中具有特定标记的元素并生成输出 excel 文档 该文档将包含元素并保留其层次结构 我的问题是我无法弄清楚每个元素 解析器在其上迭代 的嵌套深度 XML 示例摘录 3 个元素 它们可以任意嵌套
  • 将 Matlab 的 datenum 格式转换为 Python

    我刚刚开始从 Matlab 迁移到 Python 2 7 在读取 mat 文件时遇到一些问题 时间信息以 Matlab 的日期数字格式存储 对于那些不熟悉它的人 日期序列号将日历日期表示为自固定基准日期以来已经过去的天数 在 MATLAB
  • PySpark groupByKey 返回 pyspark.resultiterable.ResultIterable

    我试图找出为什么我的 groupByKey 返回以下内容 0
  • C# HashSet 只读解决方法

    这是示例代码 static class Store private static List
  • Python:Goslate 翻译请求返回“503:服务不可用”[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我们不允许提出寻求书籍 工具 软件库等推荐的问题 您可以编辑问题 以便用事实和引文来回答 这个问题似乎不是关于主要由程序员使用的特定编程问
  • 如果 PyPy 快 6.3 倍,为什么我不应该使用 PyPy 而不是 CPython?

    我已经听到很多关于PyPy http en wikipedia org wiki PyPy项目 他们声称它比现有技术快 6 3 倍CPython http en wikipedia org wiki CPython口译员开启他们的网站 ht
  • 制作一份 Python 文档的 PDF 文件

    Python 官方网站提供 PDF 文档下载 但它们是按章节分隔的 我下载了源代码并构建了 PDF 文档 这些文档也是单独的 PDF 我怎么能够从源代码中的 Makefile 构建一个 PDF 文件 我认为这样阅读起来会更方便 如果连接单独
  • 如何使用 Boto3 启动具有 IAM 角色的 EC2 实例?

    我无法弄清楚如何使用指定的 IAM 角色在 Boto3 中启动 EC2 实例 以下是迄今为止我如何成功创建实例的一些示例代码 import boto3 ec2 boto3 resource ec2 region name us west 2
  • 如何在Python脚本中从youtube-dl中提取文件大小?

    我是 python 编程新手 我想在下载之前提取视频 音频大小 任何 YouTube 视频 gt gt gt from youtube dl import YoutubeDL gt gt gt url https www youtube c

随机推荐