如何在平面上的 4 个随机放置的点之间连接一条线,使该线不与自身交叉

How to connect a line between 4 randomly placed points on a plane such that the line does not cross itself

你得到平原上点的 4 个坐标。 您需要用一条线将它们全部连接起来。该线不得与自身交叉。

你的策略是什么?

见图

我的第一直觉是将这些点组织为 "Top left"、"Top right"、"Bottom left" 和 "Bottom right" 并继续连接它们,以便左上角转到左下角,左下角到右下角,右下角到右上角,右上角连接回左上角。

这在大多数情况下都有效,但并非在所有情况下都有效。有没有更好的策略?

谢谢大家。

好吧,我还没有足够的游戏来 100% 确定,但我认为以下方法可行:

  • 选择一个点。
  • 将它从其他点中减去,得到 3 个向量到其他 3 个点。
  • 使用点积和幅度来确定每个点之间的角度 向量对(3 点为 3 对)。
  • 将该点连接到其他 2 个角度最大的点 在他们的向量之间。
  • 将剩余的点也连接到这 2 个点。

到目前为止,我还没有想出一个失败的例子,但也许那只是因为对我来说太晚了。 :)

快速说明:

AB = ax*bx + ay*by [ + az*bz ... ] = |A||B|cos(angle_between_A_and_B)


为了让计算更有效率:

首先,由于点积只给出 0 到 180 度的角度,您可以通过检查哪个余弦更小或更负来检查哪个角度更大。这避免了需要执行反余弦。

这仍然需要您对每个量级执行 sqrt 函数,因为点积给您 |A||B|cos(angle),并且您必须除以 |A||B|得到余弦。但是,通过一些启发式方法,我们也可以避免使用 sqrt。 |一个|和|B|必须始终为正。所以:

  • 如果一个点积是负的,另一个是正的,那么 负点积必须有负余弦,另一个有 一个正余弦,所以负余弦是一个更大的角度。

  • 如果都是正数,就可以对点积求平方, 然后除以幅值的平方 (x^2 + y^2 [+ z^2...] 平方)。结果越小,余弦越小,角度越大。

  • 如果点积都是负数,你执行同样的操作 操作,但较大的结果将是较小的余弦,因此角度较大。

取三个点并形成一个顺时针三角形(计算面积为两条边的叉积 - 如果为负,则交换两个顶点)。

取第四个点并计算它与前者的每个(定向)边形成的三角形的面积。当你找到一个负区域时,在这一边插入新的顶点就大功告成了。

结果发现你没有找到负区域,这意味着第四个点在三角形内部。您可以将它插入任何一侧。

if Area(P0, P1, P2) < 0
  Swap(P0, P1)

if Area(P0, P1, P3) < 0
  Solution: P0-P3-P1-P2
else if Area(P1, P2, P3) < 0
  Solution: P1-P3-P2-P0
else if Area(P2, P0, P3) < 0
  Solution: P2-P3-P0-P1
else
  Solution: P0-P1-P2-P3

更新

您可以使用 so-called 轨迹方法来考虑它。假设您已经形成并定向了一个三角形并希望插入第四个点。选择要插入的边,您可以绘制插入不会导致插入的所有位置 要交叉的边。

看到允许区域的形状,你观察到它是对插入边的半平面与原始三角形的并集。

三角形的三条支撑线将平面划分为7个区域。在任何区域内,您可以在一侧插入 1、2 或 3 种可能性之间进行选择(在图中,我们处于类型 1 的区域中)。

这种明显做作的方法向您表明,您必须将第四个点与三角形边进行比较(面积测试),在最坏的情况下,您无法避免与其中三个点进行比较。

边界的形状告诉您需要使用什么样的方程,区域的数量提示您必须执行多少次测试。