如何添加和减少凸多边形?


12

我有两个彼此重叠的 2D凸多边形。我正在寻找一种算法来减去添加它们。结果必须是单个凹面多边形或(甚至更好)一组形成凹面结果的最大凸面多边形(例如三角形)。

在此处输入图片说明

左:初始重叠的多边形。中:添加后得到的凹多边形。右:形成凹结果的一组凸多边形。出于性能原因,最好使凸多边形大于三角形。两个重叠的多边形将产生与左侧相同的图片,但重叠区域不属于所得多边形。)

我怎样才能做到这一点?


我们在这里谈论2D吗?因为在3D中组合多边形并没有多大意义。
concept3d 2014年

是的,对不起,我正在谈论2D!尽管我不明白为什么在3D中它没有在2D中意义不大。
塞巴斯蒂安·巴特

2
在3D中添加两个多边形,如果它们是平坦的,除非它们在同一平面上,否则没有多大意义;如果它们具有体积(实体),那么情况就不同了。
concept3d

好的,我知道了。我不是在考虑图形,而是在碰撞物体。谢谢你的澄清。
塞巴斯蒂安·巴斯

此外,找到它们相交的所有点并将顶点添加到集合中。该集合对于防止重叠很重要。然后,只需将来自其他两个形状的所有其他顶点添加到集合中。该集合包含加法形状的所有顶点。
沃恩·希茨

Answers:


9

TL; DR您需要使用BSP树实现布尔运算。

好吧,看来我们在这里谈论的是构造实体几何。我已经在商业级别实施了CSG,所以我对此了解一两件事。

关于CSG的经典论文称为“ 合并BSP树产量多面体集合操作”,老实说,这里要解释太多了,但是简单地说,该算法处理的是与二进制空间分区位于同一平面上的多边形,基本上是在构造每个多边形网格中的一棵BSP树。第二步是合并那些BSP树。您只需将一棵树插入另一棵树即可。然后,该算法将继续说明如何处理每个叶节点以划分和减去这些节点,最终形状中不需要的节点将被删除,其他节点将被赋予适当的父节点。

可是等等!那篇论文基本上是关于多边形网格和3D平面的,不是吗?

该算法可以推广到任何维度,因此在2D情况下,使用线段代替平面作为二进制分区很容易。因此,每个多边形将被转换成BSP树,而不是将两者合并。最后,您遍历结果树以生成最终的多边形,

请注意,该算法和CSG通常不会直接处理渲染和网格面,并且还没有真正准备好渲染,因此您需要提取最终BSP树的面。我还发现射线追踪是一种更容易呈现CSG结果的方法,您只需要射线穿过树即可,而不是提取并实际分割面(请记住,我们仅处理二进制分区)。

关于数值鲁棒性。值得一提的是,有两种类型的几何计算,

  • 基于构造的形状,可以根据上一个操作的结果构造形状。例如y = sqrt(x),然后y在新操作中使用。这称为构造;问题在于数值误差会迅速累积。
  • 另外,也有一些使用谓词的运算,实质上不是使用构造,而是询问条件是否为true / false,并在不同的运算中使用相同的值。经典测试包括圆度和方向测试;这也容易引起数值误差,特别是如果您使用单精度或双精度,但通常会得到更好的结果。存在其他在速度和准确性上有所不同的解决方案。这是最近的一篇论文,该论文通过使用基于平面的几何形状来给出准确的结果来避免构造。我还将引用这篇论文:

Sugihara和Iri [SI89]首先描述了基于平面的多边形网格表示概念。当涉及涉及更改由网格表示的实体的拓扑的任务(例如布尔表达式的求值)时,这种表示形式提供了一个重要的优势:无需构造新的主要几何信息即可获得最终的多面体

在此处输入图片说明

最后,我想补充一下,如果您想启动BSP CSG实施,我建议您从BSP常见问题解答开始。


考虑到凸多边形或多面体的BSP是列表,这很酷,但是违反直觉。很棒的纸。
3Dave

@DavidLively是的,但是可以通过选择根面不包含面来使其成为平衡树。实际上,这是他们没有谈论的挑战的一部分
concept3d 2014年

嗯,那很有道理。然后,混合BSP。
3Dave 2014年

@DavidLively的BSP也不是那么容易渲染,尽管OP问题很简单,在更复杂的情况下(具有数百万个多边形的几何图形),一旦完成树的构建,您就很难完成。
concept3d 2014年

@ concept3d我希望这不会太烦人了,因为这是5年的历史了,但是我确实不明白两件事:当试图确定一个点位于平面/直线的左侧还是右侧时,简单地旋转整个物体,使平面/线对应于平凡的平面/线,然后仅考虑旋转点的坐标会不会更容易?如何使用Sutherland-Hodgman算法代替BSP树?听起来与这种方法非常相似。
John P

1

以您的示例为例:

在面A上选择一个起始顶点,然后开始检查顺时针(或逆时针)的相交边。如果没有相交,则将前一个顶点添加到生成的多边形中。如果存在相交,则将它们相交的点添加到生成的多边形中,然后以相同的缠绕顺序开始在多边形B上进行迭代。做同样的事情,如果相交发生,再次交换到多边形A。

累积了新多边形的所有顶点后,对其执行三角剖分算法。该耳裁剪方法很容易实现,但也有较快的选择了。

重要提示:请确保您起始的顶点不在另一个多边形内(请在本文中查看多边形测试中的点)。

遍历每个边缘以检查交叉点将是O(n ^ 2)算法。您可以通过首先找到另一个多边形内的顶点来加快速度,因为链接到这些顶点的边将是相交的。


0

如果需要凹面,只需选择两个输入面之间最接近的边,然后添加两个新边:

在此处输入图片说明

凸面变得稍微复杂一些:

在此处输入图片说明

一种方法是迭代的,因为它一次将一个顶点从第二个多边形添加到第一个多边形,将第一个多边形演化为一个包含所有内容的容器。

基本上:

  • 遍历第二个多边形的顶点。
  • 对于每个顶点V,遍历第一个多边形的边缘:
  • 找到全部面对顶点的边缘“范围”
  • 取得定义该范围的外部顶点对,并删除连接它们的范围内的所有边
  • 从这些外部顶点到新顶点(从第二个多边形开始)绘制两个新的线段,确保新的边面向正确的方向。
  • 从第二个多边形进入下一个顶点

这是说明第一个顶点的过程的图:

在此处输入图片说明

一种更快的方法是在每个多边形上找到不与另一个多边形面对的边列表,删除其他所有内容,并将其余线条的端点彼此连接。

也许其他人可以提供一些减法建议。


这似乎只能解决一半的问题(附加)。指出多边形重叠时算法的工作方式或优化方法也可能是一件好事。

该算法隐式忽略了目标多边形“内部”的顶点,这也弥补了第二个多边形的边与第一个多边形相交的问题。
3Dave 2014年

这几乎等于合并阶段(合并船体算法的第4点。在我的情况下,合并多边形后包围更多区域不是正确的解决方案。正确的解决方案是将两个多边形保持原样,因为它们不是t重叠,也不可触及
Sebastian Barth 2014年

@luftgewehrindianer啊-是的,那有很大的不同。也许我误解了这个问题。您是否希望将多边形加在一起,而不必担心结果是凸面还是凹面?还是基于交集生成凸集?(暂时忽略减法。)
3Dave

@DavidLively想象两个相同颜色且没有边框描边的凸多边形。当它们重叠时,它看起来像一个新的凸面或凹面多边形。他试图找到组合形状的三角剖分。不要在两个多边形之间添加区域。
danijar 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.