在由4个点定义的一组6个段中找到对角线的算法,形成凸四边形

时间:2013-11-06 22:21:27

标签: c++ algorithm geometry 2d

这是2D计算几何的一个简单问题,我一直未能成功解决:

we have four points A, B, C, D defining a CONVEX QUADRILATERAL 

(not a square or a rectangle!)

we know the (x, y) coordinates of each point.

有6个段连接2个点:

AB, AC, AD, BC, BD, CD

这些线段的一个交叉点将在图中形成一个点:两个对角线的交点。

对角线夫妇有3种可能:

[AB] and [CD]
[AC] and [BD]
[AD] and [BC]

(见下图)

illustration

我正在寻找一种简单的算法来查找当我改变A,B,C,D的(x,y)坐标时发生的3种可能情况中的哪一种

5 个答案:

答案 0 :(得分:2)

  1. 走AB,AC,AD。
  2. 测量它们之间的角度(两个归一化矢量的点积是它们之间的角度的余弦)。 测量角度CAB,CAD,BAD并找到两个最小角度。
  3. 这两个最小的角度共享一面。这边是对角线。属于非共享边的点形成另一个对角线。
  4. 实施例

    1. 测量角度BAC,CAD,BAD。
    2. BAC和CAD是两个最小的角度。 (另外,角度BAC和CAD的总和将等于角度BAD,所以你也可以检查它。)
    3. 他们分享AC。这使得AC成为第一个对角线,这意味着BD是另一个对角线。
    4. 不适用于凹几何体。

      更好的解释(附图)

      diagram

      在这张图片中,∠DAB = ∠DAC + ∠BAC。因此,∠DAC < ∠DAB∠BAC < ∠DAB。 AC是共享的,是对角的。 BC是另一个对角线。

      即。在所有情况下,两个小角度形成“大”角度,并且它们的共享侧将“大”角分成两个小角度。对于凸四边形中的单个顶点,只需要检查3个角度,这足以找到所有对角线。

      矢量标准化

      归一化向量是长度为1.0的向量。 要标准化矢量,请按因子1.0/length进行缩放。长度可以用点积计算。

      normalizedVector = scale(originalVector, 1/length(originalVector))(注意这里长度为0的向量。)
      length(vector) = sqrtf(dotProduct(vector, vector))
      “缩放”向量将其与标量相乘。

答案 1 :(得分:1)

我能弄清楚的简单:

  1. 取点A。
  2. 测量矢量AB,AC,AD的斜率。
  3. 看看他们之间的关系。

      Case 1: SAC>SAB>SAD,
      Case 2: SAB>SAC>SAD,
      Case 3: SAB>SAD>SAC.
    

    考虑360度差异。

  4. P.S。我不确定你是否关心角度> 4的四边形180.如果是,你必须另外考虑它们。

答案 2 :(得分:1)

提示: 我认为你要从定义凸包点和线开始。 Wiki-Graham Scan Alg.可用于确定参与创建凸包的线段。一旦确定了线段,就可以轻松找到对角线。使用链接中的示例,可以在数组中存储以下线段(按算法确定的顺序)(每对点定义一个线段):

P,A
A,B
B,D
D,P

从这个数组中,你可以立即得到对角点为P,B和A,D。

该算法不需要角度计算,也没有区域形状的假设。

答案 3 :(得分:1)

点{A,B,C,D}形成4个三角形:ABC,ABD,ACD和BCD。计算它们的方向产生一个4位二进制特征,它确定凸包的顺序如下:

       signature key: "+" for counterclockwise, "-" for clockwise

A A A B
B B C C   convex hull, in counterclockwise order:
C D D D

+ + + +   quadrilateral ABCD
+ + + -   triangle ABD (C is internal)
+ + - +   triangle ABC (D is internal)
+ + - -   quadrilateral ABDC
+ - + +   triangle BCD (A is internal)
+ - + -   (should not happen)
+ - - +   quadrilateral ADBC
+ - - -   triangle ADC (B is internal)

          (inverting all signature bits reverses hull orientation)

- + + +   triangle CDA (B is internal)
- + + -   quadrilateral CBDA
- + - +   (should not happen)
- + - -   triangle DCB (A is internal)
- - + +   quadrilateral CDBA
- - + -   triangle CBA (D is internal)
- - - +   triangle DBA (C is internal)
- - - -   quadrilateral DCBA

您可以按如下方式计算任何给定三角形的方向(顺时针或逆时针):

struct Point {
  float x, y;
  Point(float xx,float yy):x(xx),y(yy){}
};
Point operator+(Point A, Point B) { return Point(A.x+B.x,A.y+B.y); }
Point operator-(Point A, Point B) { return Point(A.x-B.x,A.y-B.y); }

float orientation(Point A, Point B, Point C) {
  Point AB = B - A;
  Point AC = C - A;
  return AB.x*AC.y - AB.y*AC.x; // 2-D equivalent to the 3-D cross-product
}

如果三角形ABC是逆时针,则函数orientation(A,B,C)返回正值,如果是顺时针,则返回负值,如果是退化,则返回零。 (如果你的坐标系是左手而不是右手,那么顺时针方向是逆时针交换的,但这并不重要......)

答案 4 :(得分:0)

如果你的坐标是:

0,0
0,1
1,0
1,1

你可以认识到具有相同x和y坐标的那些形成对角线,而具有不同x和y坐标的那些形成对角线。

所以如果坐标是:

1,1
1,3
3,1
3,3

那么a,b处的字母,其中a = b形成一个,而a,b处的字母,其中a!= b形成一个,所以 1,1和3,3的字母是1,1,3和3,1也是如此。

请注意,这只适用于正方形。

另外,无论如何,你可以这样做:

你可以匹配不共享相同坐标的对。

代表

A--B
|  |
C--D

你可以知道A和D是一对,因为A和C共用一个X坐标,而A和B共用一个Y坐标。

没有共同的坐标==对角线。 (以这种方式任何方形或矩形。)

希望这有帮助。