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

时间:2015-02-01 04:58:50

标签: geometry pathgeometry

平原上有4个坐标点。 你需要用一条线连接它们。线不能越过自己。

你的策略是什么?

见图片Example

我的第一个直觉是将点组织为"左上角","右上角","左下角" "右下角"并继续连接它们,使左上角到左下角,左下角到右下角,右下角到右上角,右上角连接到左上角。

这在大多数情况下有效,但并非全部。有更好的策略吗?

谢谢大家。

2 个答案:

答案 0 :(得分:2)

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

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

事实证明,你没有找到负面区域,这意味着第四个点位于三角形内部。您可以将它插入任何一侧。

enter image description here

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

更新

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

enter image description here

看到允许区域的形状,您会发现它是半平面与插入侧的联合,以及原始三角形。

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

这种显而易见的方法向您展示您必须将第四点与三角形边(区域测试)进行比较,在最坏的情况下,您不能避免与三者进行比较。

边界的形状告诉您需要使用哪种方程式,并且区域数量暗示您将需要执行多少次测试。

答案 1 :(得分:0)

好吧,我还没有把它比作100%肯定,但我认为以下方法可行:

  • 选择一个点。
  • 从彼此的点中减去它以获得3个向量到其他3个点。
  • 使用点积和大小来确定每个之间的角度 一对矢量(3对3对)。
  • 以最大角度将点连接到其他2个点 他们的载体之间。
  • 将剩下的点也连接到这两个点。

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

快速说明:

A B = ax * bx + ay * by [+ az * bz ...] = | A || <强>乙 | COS(angle_between_A_and_B)


提高计算效率:

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

仍然需要你为每个幅度执行sqrt函数,因为点积给你| A || B | cos(角度),你必须除以| A || B |得到余弦。但是,通过一点启发式,我们也可以避免使用sqrt。 | A |和| B |必须始终是积极的。所以:

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

  • 如果它们都是正面的,那么你可以对点积进行平方,并且 然后除以平方的幅度(x ^ 2 + y ^ 2 [+ z ^ 2 ...]没有 sqrt)。较小的结果将是较小的余弦,因此角度较大。

  • 如果点积为负数,则执行相同的操作 操作,但随后较大的结果将是较小的余弦,因此角度较大。