我有两个彼此重叠的 2D凸多边形。我正在寻找一种算法来减去和添加它们。结果必须是单个凹面多边形或(甚至更好)一组形成凹面结果的最大凸面多边形(例如三角形)。
(左:初始重叠的多边形。中:添加后得到的凹多边形。右:形成凹结果的一组凸多边形。出于性能原因,最好使凸多边形大于三角形。两个重叠的多边形将产生与左侧相同的图片,但重叠区域不属于所得多边形。)
我怎样才能做到这一点?
我有两个彼此重叠的 2D凸多边形。我正在寻找一种算法来减去和添加它们。结果必须是单个凹面多边形或(甚至更好)一组形成凹面结果的最大凸面多边形(例如三角形)。
(左:初始重叠的多边形。中:添加后得到的凹多边形。右:形成凹结果的一组凸多边形。出于性能原因,最好使凸多边形大于三角形。两个重叠的多边形将产生与左侧相同的图片,但重叠区域不属于所得多边形。)
我怎样才能做到这一点?
Answers:
TL; DR您需要使用BSP树实现布尔运算。
好吧,看来我们在这里谈论的是构造实体几何。我已经在商业级别实施了CSG,所以我对此了解一两件事。
关于CSG的经典论文称为“ 合并BSP树产量多面体集合操作”,老实说,这里要解释太多了,但是简单地说,该算法处理的是与二进制空间分区位于同一平面上的多边形,基本上是在构造每个多边形网格中的一棵BSP树。第二步是合并那些BSP树。您只需将一棵树插入另一棵树即可。然后,该算法将继续说明如何处理每个叶节点以划分和减去这些节点,最终形状中不需要的节点将被删除,其他节点将被赋予适当的父节点。
可是等等!那篇论文基本上是关于多边形网格和3D平面的,不是吗?
该算法可以推广到任何维度,因此在2D情况下,使用线段代替平面作为二进制分区很容易。因此,每个多边形将被转换成BSP树,而不是将两者合并。最后,您遍历结果树以生成最终的多边形,
请注意,该算法和CSG通常不会直接处理渲染和网格面,并且还没有真正准备好渲染,因此您需要提取最终BSP树的面。我还发现射线追踪是一种更容易呈现CSG结果的方法,您只需要射线穿过树即可,而不是提取并实际分割面(请记住,我们仅处理二进制分区)。
关于数值鲁棒性。值得一提的是,有两种类型的几何计算,
y = sqrt(x)
,然后y
在新操作中使用。这称为构造;问题在于数值误差会迅速累积。Sugihara和Iri [SI89]首先描述了基于平面的多边形网格表示概念。当涉及涉及更改由网格表示的实体的拓扑的任务(例如布尔表达式的求值)时,这种表示形式提供了一个重要的优势:无需构造新的主要几何信息即可获得最终的多面体
最后,我想补充一下,如果您想启动BSP CSG实施,我建议您从BSP常见问题解答开始。
如果需要凹面,只需选择两个输入面之间最接近的边,然后添加两个新边:
凸面变得稍微复杂一些:
一种方法是迭代的,因为它一次将一个顶点从第二个多边形添加到第一个多边形,将第一个多边形演化为一个包含所有内容的容器。
基本上:
这是说明第一个顶点的过程的图:
一种更快的方法是在每个多边形上找到不与另一个多边形面对的边列表,删除其他所有内容,并将其余线条的端点彼此连接。
也许其他人可以提供一些减法建议。