通过平铺三角形来镶嵌任意多边形

Posted

技术标签:

【中文标题】通过平铺三角形来镶嵌任意多边形【英文标题】:Tessellating an arbitrary polygon by tiling triangles 【发布时间】:2011-01-01 05:55:33 【问题描述】:

我需要使用近似均匀的三角形平铺来填充任意多边形。我该怎么做?您可以提供对现有算法的参考,甚至可以提供您自己的想法或提示。

推测如下:

多边形可能是凸面的(但如果您想出适用于凹面形状的算法,则可以加分) 多边形具有任意数量的边(3 条或更多) 应参数化细分的数量(最好是算法添加的顶点数) 多边形的边可以被算法分割 三角形的大小和形状应几乎一致(即角趋向于 60 度) 一个顶点的边数最好少而不是多。这可能会从上一点开始(即算法应该产生一个“干净的网格”)。

这不是一个容易解决的问题,我希望“启发式”解决方案可能是最有效的......(对吗?)

【问题讨论】:

这可能有助于提供一些关于您要解决的实际问题的背景知识。这是模拟中使用的网格吗?如果有,使用的是什么模拟方法? 嗯,这里逐字发布的家庭作业听起来太多了。如果你说它是或不是家庭作业会有所帮助。如果这是一个问题或某种挑战。无需再澄清了,从您发布的评论中我现在很清楚,但不是在您第一次发布您的,错误,挑战/问题/随便什么的时候。 呵呵,没关系,伙计们:)。这不是家庭作业,我基本上是在我正在处理的 3d 模拟中将形状包裹在地形高度图上。我认为记录和讨论也是一个普遍有用的问题。我实际上不希望人们过多地阅读上下文,因为他们会给出不同的答案...... 【参考方案1】:

Triangle 做你想做的事吗?

(那个网站上对算法的解释比我能想到的都好。)

【讨论】:

从我最初对网站的浏览来看,它们似乎并没有以统一的方式平铺三角形(三角形的大小不或多或少相等),但我需要一些时间来确定。还是谢谢! 实际上这看起来非常接近我的想法...我可能还可以通过等距生成点来使用 Delaunay 三角剖分...在我尝试弄清楚时暂时 +1。 “-a 开关设置了最大面积约束”,这似乎导致三角形大小大致相同。 -q 指定最小角度。 cs.cmu.edu/~quake/triangle.quality.html【参考方案2】:

实际上听起来并不复杂,从算法上讲。还是我错过了什么?

一些伪代码:

在多边形周围放置一个轴对齐的封闭正方形。 将每个正方形细分为四个子级(类似于四叉树),其中迭代次数决定了您的“镶嵌量”。 生成的每个正方形要么完全位于多边形外部(=忽略),要么完全位于多边形内部(=沿对角线分割为生成的镶嵌的两个三角形)或与多边形相交。 交集方块的具体情况留给读者作为练习。 ;-) [至少在这个时间点上。]

它会为您提供角度为 45°/45°/90° 的三角形。如果您想要尽可能接近 60°,您应该首先用六边形细分多边形的表面(六边形的大小是您的“细分量”),然后检查六个 60°/60° 中的每一个/60° 构成这些六边形的三角形。对于这些三角形,您可以对上述伪代码中的正方形执行相同的操作,除了您不需要将多边形内的三角形完全拆分,因为它们本身已经是三角形。

这有什么帮助吗?我认为,应该适用于任何多边形(凸面/凹面/有孔),因为您对相交的正方形/三角形所做的正是处理此类多边形。

【讨论】:

这也是我想到的“简单”想法之一。然而,它并没有真正在边缘上很好地平铺形状,并且镶嵌也不是那么容易参数化。 (这是我已有的两个想法之一……) (虽然比我的想法要好,所以谢谢)【参考方案3】:

正如 Jason Orendorff 指出的,您应该尝试使用三角形来生成高质量的网格。它有很多选项可供您尝试获得各向同性网格。然后,您可以尝试使用迭代算法来创建居中良好的三角剖分。更多细节在this publications page 上列出。我已经实现了 2007 年的论文“Well-Centered Planar Triangulation -- an Iterative Approach”,它在中等大小的网格上给出了不错的结果。居中良好的三角剖分是三角形的所有外心都位于相应三角形内的三角剖分。由于您想要一些稍微不同的东西,您可以简单地尝试更改所涉及的错误度量。您可以在三角形中找到“不一致”的度量,并将该错误最小化。这样的误差函数很可能是非凸的,所以描述的非线性共轭梯度优化是你能做到的。

【讨论】:

非常感谢,这看起来像我正在寻找的东西!您对算法的性能有任何指示吗?这不是太重要,我只是好奇。 您应该参考参考论文以了解它的收敛速度。在实践中,我记得它需要数百到数千次迭代。 据我所知,它更适合简单的网格。更像是 30 到 100 次迭代。【参考方案4】:

这可以使用简单的耳夹方法对凹/凸多边形完成(假设我们不需要支撑孔)。

镶嵌多边形http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.115.291 一旦边缘旋转到新状态,在三角形之间旋转边缘,其中除以周长的区域更小。

这是 2 个步骤,因此迭代地修剪“最佳”耳朵以获得更均匀的结果可能会更有效,因此您不必重新排列拓扑作为第二遍 (YMMV)。(请注意,这里使用 2 个步骤的原因是并不总是需要计算更均匀的分布)。


完全公开,我自己遇到了这个问题,当我需要一个用于实时建模应用程序的多边形快速镶嵌器时。

用 C 编写的工作实现,接受并返回 POD(float[2] 数组,填充 uint[3] 数组):

polyfill_2d.c(镶嵌)

polyfill_2d_beautify.c(调整拓扑以获得更均匀的结果)

还发了port of polyfill_2d.c to Rust

(注意,剪耳是基于 libgdx,对交叉检查进行了空间优化,可以扩展到数千个边而不会造成如此显着的性能损失,因为剪裁每只耳朵都是在检查 all-other - 积分 每次)。

【讨论】:

以上是关于通过平铺三角形来镶嵌任意多边形的主要内容,如果未能解决你的问题,请参考以下文章

多边形面积公式

求任意多边形面积 python实现

如何使用边缘和内部镶嵌因子完成三角形补丁镶嵌?

多边形面积

寻找三角形镶嵌的最近邻

如何判断一个点在多边形内