如何确定非零填充多边形的边是否是外边?

时间:2015-01-07 22:09:36

标签: geometry

假设我有一个多边形并且我已经计算了它的所有自交叉。如何根据非零填充规则确定特定边缘是在内部还是外部?通过"外边缘"我的意思是位于填充区域和非填充区域之间的边缘。

示例:

enter image description here

左边是一个示例多边形,根据非零填充规则填充。右侧是相同的多边形,其外边缘以红色突出显示。我正在寻找一种算法,给定多边形的边缘及其相互交叉,可以将每个边缘标记为外部或内部。

优选地,该解决方案应该概括为由例如组成的路径。贝齐尔曲线。

[编辑]另外两个例子:

enter image description here

4 个答案:

答案 0 :(得分:1)

我注意到了"外边缘"封闭在形状内必须穿过偶数个交叉点才能到达外面。 "非外边缘"封闭的必须穿过奇数个交叉点。

您可以尝试这样的算法

isOutside = true
edge = find first outside edge*
edge.IsOutside = isOutside
while (not got back to start) {
  edge = next
  if (gone over intersection)
    isOutside = !isOutside
  edge.IsOutside = isOutside
}

例如:

Visual summary of how the algorithm works

*我认为你总是可以通过依次尝试每条线来找到外边缘:尝试无限延伸它 - 如果它没有穿过另一条线那么它应该在外面。这似乎是直观的,但我想知道是否有一些病态情况,你无法使用此规则找到起始线。使用这种查找第一行的方法不适用于曲线。

答案 1 :(得分:1)

我认为,你的问题可以分两步解决。

  1. 使用支持自相交多边形的算法对源多边形进行三角剖分。好的开始是Seidel algorithm。链接的PDF文档的5.2节描述了自交叉多边形。

  2. 使用支持孔的算法将三角形合并到单个多边形中,即Weiler-Atherton algorithm。此算法可用于剪切和合并,因此您需要它的“合并”情况。也许你可以简化算法,导致第一步的三角形不相交。

答案 2 :(得分:1)

我意识到这可以通过一种相当简单的方式确定,使用稍微修改计算绕组数的标准程序。它在概念上类似于直接在目标边缘的左侧和右侧评估绕组。以下是任意曲线的算法,而不仅仅是线段:

  1. 在目标细分上选择一个点。确保此时的Y导数非零。
  2. 在其衍生物的Y根处细分目标细分。在下一点中,忽略包含您在步骤1中选择的点的段的部分。
  3. 确定在1中拾取的点处的绕组数。这可以通过沿+ X方向投射光线并查看与其相交的位置以及在什么方向上来完成。导数的Y分量为正的点处的交点计为+1。执行此操作时,请忽略包含您在步骤1中选择的点的Y单调部分。
  4. 如果匝数为0,我们就完成了 - 这绝对是一个外边缘。如果它非零且不同于-1,0或1,我们就完成了 - 这绝对是一个内部边缘。
  5. 检查在步骤1中拾取的点处的导数。如果光线与该点的交点将计为-1并且在步骤3中获得的绕组数是+1,则这是外边缘;同样适用于+ 1 / -1的情况。否则这是一个内部边缘。
  6. 本质上,我们正在检查光线与目标段的交点是否会改变零和非零之间的绕组数。

答案 3 :(得分:0)

我建议,我认为这是对我有用的解决方案的更简单实现:

1。在目标路段上选择任意点。(我任意选择中点。)

2。从该点垂直于线段的点构造光线。(我对CW多边形使用左法线,对CCW多边形使用右法线。)

3。计算射线与多边形的交点,而忽略目标线段本身。在这里,您可以选择NonZero缠绕规则[多边形线段向左交叉(CCW)递减,向右交叉线(CW)交叉递减);内部边缘产生零计数的地方]或EvenOdd规则[计算内部边缘产生奇数的所有交叉点]。对于线段,通过简单的左右检验来确定其起点和终点的交叉方向。对于圆弧和曲线,可以在相交处切线完成,这是读者的练习。

我进行此分析的目的是将一个自相交的多边形划分为一组等效的不自相交的多边形。为此,同样有用相反的方向分析射线并检测原始多边形是否会在此处填充是有用的。这导致了该段的两个侧面的内部/外部确定,从而产生了四种可能的状态。我怀疑OUTSIDE-OUTSIDE状态可能仅对未关闭的多边形有效,但是对于此分析,可能需要暂时关闭它。可以通过跟踪状态相同的线段共享的相交点,将它们收集到不相交的多边形中。在某些情况下,例如使用纯填充,您甚至可能决定消除INSIDE-INSIDE多边形,因为它们会填充已经填充的空间。

感谢您的原创解决方案!