按顺时针的顺序排列点?

给定一组 x、y 点的数组,如何按顺时针顺序(围绕它们整体平均中心点)对这个数组的点进行排序?我的目标是将这些点传递给线条创建函数,以获得看起来非常“坚实”的东西,尽可能凸出,没有线条交错。

值得一提的是,我正在使用 Lua,但任何伪代码都将非常感激。

更新: 参考 Ciamej 出色的答案,这是基于 Lua 的代码(忽略我的“app”前缀):

原文链接 https://stackoverflow.com/questions/6989100

点赞
stackoverflow用户805808
stackoverflow用户805808

你所需要的系统就是所谓的polar coordinates(极坐标系)。在任何编程语言中,将笛卡尔坐标系转换为极坐标系都非常容易。转换的公式可以在这个章节中找到。

转换为极坐标系之后,只需要按角度theta进行排序即可。

2011-08-08 22:31:42
stackoverflow用户164171
stackoverflow用户164171

将下面翻译成中文并且保留原本的 markdown 格式

另一种有趣的解决问题的方法是找到旅行商问题(TSP)的近似最小值,即连接所有点的最短路径。如果您的点形成一个凸形状,则应该是正确的解决方案,否则,它仍然应该看起来很好(“固体”形状可以定义为周长/面积比低的形状,这就是我们在此优化的内容)。

您可以使用任何TSP优化器的实现,在您选择的语言中,我相信您可以找到很多这样的实现。

2011-08-10 15:01:30
stackoverflow用户10950731
stackoverflow用户10950731
  • 创建向量a = new vector3(1, 0, 0),相对于X轴
  • 创建向量b = 任意点 - 中心点
- y = |a * b|,x = a · b

- Atan2(y,x)…………………………返回弧度制下 -PI 到 + PI 之间的角度
- (Input % 360 + 360) % 360……将其转换为 0 到 2PI 的角度制
- 按照得到的角度从0到360,按添加点的顺序将其排序加入list_of_polygon_verts 

最终,您将获得按逆时针排序的顶点

list.Reverse()……………………按时针顺序排列

2019-02-13 14:12:41
stackoverflow用户6942666
stackoverflow用户6942666

以下是一种方法按顺时针顺序排序矩形的顶点。我修改了pyimagesearch提供的原始解决方案,并摆脱了scipy依赖项。

import numpy as np

def pointwise_distance(pts1, pts2):
    """计算点对之间的距离

    Args:
        pts1 (np.ndarray): 形式为[[x1, y1], [x2, y2], ...]的数组
        pts2 (np.ndarray): 形式为[[x1, y1], [x2, y2], ...]的数组

    Returns:
        np.array: 相应点之间的距离
    """
    dist = np.sqrt(np.sum((pts1 - pts2)**2, axis=1))
    return dist

def order_points(pts):
    """按照顺序排序形式为[top left, top right, bottom right, bottom left]的点。
    来源:https://www.pyimagesearch.com/2016/03/21/ordering-coordinates-clockwise-with-python-and-opencv/

    Args:
        pts (np.ndarray): 形式为[[x1, y1], [x2, y2], [x3, y3], [x4, y4]]的点列表

    Returns:
        np.ndarray: 按照顺序排序的坐标
    """
    # 根据x坐标对点进行排序
    x_sorted = pts[np.argsort(pts[:, 0]), :]

    # 从排序后的x坐标点中获取最左和最右的点
    left_most = x_sorted[:2, :]
    right_most = x_sorted[2:, :]

    # 根据它们的y坐标对最左边的坐标进行排序,从而可以分别获取左上和左下的点
    left_most = left_most[np.argsort(left_most[:, 1]), :]
    tl, bl = left_most

    # 现在我们有了左上坐标,以此为锚点计算左上和最右边点之间的欧几里得距离;
    # 根据勾股定理,具有最大距离的点将是我们的右下点。注意:这是一个有效的假设,因为我们只处理矩形。
    # 我们需要使用这个来代替只使用min/max来处理有相同x或y值的点的情况。
    D = pointwise_distance(np.vstack([tl, tl]), right_most)

    br, tr = right_most[np.argsort(D)[::-1], :]

    # 按照顶点的顺序返回坐标,分别是左上,右上,右下和左下
    return np.array([tl, tr, br, bl], dtype="float32")
2021-01-04 22:14:43
stackoverflow用户1551688
stackoverflow用户1551688

我知道这是一篇旧的帖子,有着一个优秀的被接受的答案,但是我觉得我还可以为此提供一些有用的东西。到目前为止,所有的答案本质上都使用了一个比较函数来比较两个点并确定它们的顺序,但是如果你只想一个点一个点地使用关键函数呢?

这不仅是可能的,而且生成的代码也非常紧凑。下面是使用 Python 的内置排序函数的完整解决方案:

# 创建一些随机点
num = 7
points = np.random.random((num, 2))
# 计算它们的中心点
center = np.mean(points, axis=0)

# 创建一个 arctan2 函数以返回一个从 [0, 2 pi) 而非 [-pi, pi) 区间内的值
arctan2 = lambda s, c: angle if (angle := np.arctan2(s, c)) >= 0 else 2 * np.pi + angle

# 定义关键函数
def clockwise_around_center(point):
    diff = point - center
    rcos = np.dot(diff, center)
    rsin = np.cross(diff, center)
    return arctan2(rsin, rcos)

# 使用关键函数对点进行排序
sorted_points = sorted(points, key=clockwise_around_center)

如果这些点位于嵌入到三维空间中的二维平面上,则此答案同样适用于 3D。我们只需要通过对它与该平面的法向量进行点积来修改 rsin 的计算。例如:

rsin = np.dot([0,0,1], np.cross(diff, center))

如果该平面的法向量为 e_z

这段代码的优点在于,它只使用了一个关键函数在一个点一个点地排序。通过在系数级别上推导出这个量 rsin,发现它与被接受的答案中所称的 det 完全相同,只是我计算 point - centercenter 之间,而不是 point1 - centerpoint2 - center 之间。但是这个量的几何意义是半径乘以正弦值,因此我称这个变量为 rsin。对于点积,同理,这是半径乘以余弦值,因此被称为 rcos

你可以认为这个解决方案使用了 arctan2,因此不太干净。然而,我个人认为使用关键函数的清晰度优于只需要一次三角函数调用的需要。请注意,我倾向于使 arctan2 返回来自 [0, 2 pi) 而非 [-pi, pi) 的值,因为当 point 恰好等于 center 时,我们得到角度为 0,因此它将成为我们排序列表中的第一个点。这是一个可选的选择。

为了理解这段代码是如何工作的,关键的见解是,所有我们的点都是定义为相对于原点的箭头,包括中心点 center 本身。因此,如果我们计算 point - center,这相当于将箭头从指向 center 的箭头的顶端放到指向 point 的箭头的顶端,在原点处。因此,我们可以根据与指向 center 的箭头所成角度的大小对箭头 point - center 进行排序。

2022-11-12 13:10:13
stackoverflow用户2769997
stackoverflow用户2769997

使用numpy:

import matplotlib.pyplot as plt
import numpy as np

# 坐标列表
coords = np.array([7,7, 5, 0, 0, 0, 5, 10, 10, 0, 0, 5, 10, 5, 0, 10, 10, 10]).reshape(-1, 2)
centroid = np.mean(coords, axis=0)
sorted_coords = coords[np.argsort(np.arctan2(coords[:, 1] - centroid[1], coords[:, 0] - centroid[0])), :]

plt.scatter(coords[:,0],coords[:,1])
plt.plot(coords[:,0],coords[:,1])
plt.plot(sorted_coords[:,0],sorted_coords[:,1])
plt.show()

enter image description here

2023-01-28 04:37:35