从给定的2d点列表中找到所有凸四边形的算法

时间:2012-12-20 20:20:18

标签: algorithm geometry computational-geometry

我必须制作一个程序,从给定的2d点列表中找到所有凸四边形。 我用矢量交叉产品尝试了它,但它似乎不是一个正确的解决方案。

也许这个问题有一些有效的算法,但我找不到它。

这是输入和输出的示例:

输入

Number of Points:
6
coordinates of points (x,y):
0 0
0 1
1 0
1 1
2 0
2 1

输出

Number of convex quadrilaterals:
9

1 个答案:

答案 0 :(得分:10)

如果对角线相交,则四边形是凸的。相反,如果两个线段相交,则它们的四个端点形成一个凸四边形。

convex quadrilateral on left, non-convex on right

每对点都会给出一个线段,两个线段之间的每个交点都对应一个凸四边形。

您可以使用比较所有细分对的天真算法或points of intersection找到Bentley–Ottmann algorithm。前者需要O( n 4 );和后者O(( n 2 + q )log n )(其中 q 是凸四边形的数量)。在最坏的情况下 q =Θ( n 4 ) - 考虑一个圆上的 n 点 - 所以Bentley-奥特曼并不总是更快。

这是Python中的天真版本:

import numpy as np
from itertools import combinations

def intersection(s1, s2):
    """
    Return the intersection point of line segments `s1` and `s2`, or
    None if they do not intersect.
    """
    p, r = s1[0], s1[1] - s1[0]
    q, s = s2[0], s2[1] - s2[0]
    rxs = float(np.cross(r, s))
    if rxs == 0: return None
    t = np.cross(q - p, s) / rxs
    u = np.cross(q - p, r) / rxs
    if 0 < t < 1 and 0 < u < 1:
        return p + t * r
    return None

def convex_quadrilaterals(points):
    """
    Generate the convex quadrilaterals among `points`.
    """
    segments = combinations(points, 2)
    for s1, s2 in combinations(segments, 2):
        if intersection(s1, s2) != None:
            yield s1, s2

示例运行:

>>> points = map(np.array, [(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1)])
>>> len(list(convex_quadrilaterals(points)))
9