我有一个多边形C,如下所示:
C = 10 0
2 0
2 2
0 2
2 0
0 0
0 10
10 10
其中第一列表示x的坐标,第二列对应于多边形C的y坐标。 正如你在上面的图片中看到的,这不是一个简单的多边形(这个多边形包含一个由白色指定的孔),所以我想得到C中所有不包含孔的简单子多边形。 在这种情况下,输出应如下:
C1 = 0 2
2 0
0 0
C2 = 2 0
2 2
0 2
0 10
10 10
10 0
其中C1和C2分别对应小红色三角形和大红色多边形。
问题是如何生成这个子多边形?
任何想法都将受到赞赏。
答案 0 :(得分:2)
首先,我们可以假设所有交叉点都存在吗?很容易想出以有趣的方式相交的多边形。但是,使用类似http://en.wikipedia.org/wiki/Bentley%E2%80%93Ottmann_algorithm的内容,您应该可以在所有交叉点中找到并添加。
接下来,我将简化假设我们不会回转线段。 (你可以通过各种方式处理这种病态。)
随着细节的处理,接下来我们需要找到这些点可以定义的所有最小多边形,无论它们最终是在内部还是外部。 (为方便起见,我们将在无穷远处添加一个“点”并将外部计算为多边形。)为此,我们首先取每个点,然后按逆时针顺序列出它直接连接的点。 (平行于x轴行进为0度,y轴为90度,负x轴为180度,然后随着你走得更远,我们会四处走动。)所以对于你的例子,我们得到了一些东西像这样:
( 0, 0): ( 2, 0), ( 0, 2)
( 2, 0): (10, 0), ( 2, 2), ( 0, 2), ( 0, 0)
(10, 0): (10,10), ( 2, 0)
( 0, 2): ( 0, 0), ( 2, 0), ( 2, 2), ( 0,10)
( 2, 2): ( 2, 0), ( 0, 2)
( 0, 10): ( 0, 2), (10,10)
(10, 10): (10, 0), ( 0,10)
现在每个简单的多边形都会击中两个点之间的每个点,反之亦然,我们可以从其中一个间隙(包括环绕)中轻松生成相关的多边形,在每个角落尽可能小的逆时针转动(即从我们到达之后的那一点,可能是包装)。对于每个线段,多边形将位于右侧。我们知道,当我们有每一点和差距时,我们都拥有所有这些。因此,在上述情况下,我们从( 0, 0)
和以下点( 2, 0)
开始,然后我们查看( 2, 0)
并发现( 0, 0)
后跟(10, 0)
1}},转到(10, 0)
,发现( 2, 0)
后跟(10,10)
,然后以这种方式跟踪:
( 0, 0), ( 2, 0), (10, 0), (10,10), ( 0,10), ( 0, 2), ( 0, 0)
(注意,由于方向,这跟踪了外部区域。)
现在我们从( 0, 0)
和备用起点( 0, 2)
开始,并执行相同的操作:
( 0, 0), ( 0, 2), ( 2, 0), ( 0, 0)
(这是一个小的内三角。)
对于( 2, 0)
,我们尚未前往( 2, 2)
。让我们这样做。
( 2, 0), ( 2, 2), ( 0, 2), ( 0,10), (10,10), (10,0), ( 2, 0)
(这是大的不规则多边形。)
对于( 2, 0)
我们还没有前往( 0, 2)
所以让我们这样做:
( 2, 0), ( 0, 2), ( 2, 2), ( 2, 0)
(这是一个小的白色三角形。)
然后,我们可能想要旅行的所有可能的有向线段的枚举将发现我们已经覆盖了它们。所以这些是我们的多边形。现在我们要弄清楚里面是什么,外面是什么。有一个简单的技巧。找到一个具有最低可能值y的点(如果有平局,任何人都会这样做)。例如,假设我们选择( 2, 0)
。逆时针排列的连接点为(10, 0), ( 2, 2), ( 0, 2), ( 0, 0)
。它们分别在外部,内部,外部,内部......并且一旦给定多边形的一个边缘被标记为在外部或内部,则其所有指向边缘都是相同的。因此我们很容易得到:
outside:
- (10, 0), ( 2, 2), ( 0, 2), ( 0, 0)
- ( 2, 0), ( 0, 2), ( 2, 2), ( 2, 0)
inside:
- ( 2, 0), ( 2, 2), ( 0, 2), ( 0,10), (10,10), (10, 0), ( 2, 0)
- ( 0, 0), ( 0, 2), ( 2, 0), ( 0, 0)
你的答案只是内部多边形。
(小优化,我们根本不需要绘制外部多边形。我们可以采用我们发现的方向的第一个线段,找出内部的一个,然后转到其中一个角,确定方向接触该角落的线段,并开始绘制其他内部多边形。如果我们正确地跟踪,我们最终会得到它们。)