如何在不添加额外点的情况下对带孔洞的多边形进行三角剖分?
解决带孔洞多边形的无额外点三角剖分问题
你遇到的核心问题是混淆了约束三角剖分和质量约束三角剖分的参数用法。triangle库默认行为不会主动维护约束边界(导致孔洞被忽略),而qpa这类质量参数会强制插入新顶点来满足三角形质量要求——这两者都不是你要的效果。
直接给你解决方案:使用'p'参数执行纯约束Delaunay三角剖分,这个参数会强制三角剖分仅使用你提供的原始顶点和线段,不插入任何新点,同时会正确识别你定义的孔洞区域。
修改后的完整代码
import matplotlib.pyplot as plt import numpy as np import triangle as tr def circle(N, R): i = np.arange(N) theta = i * 2 * np.pi / N pts = np.stack([np.cos(theta), np.sin(theta)], axis=1) * R seg = np.stack([i, i + 1], axis=1) % N return pts, seg # 生成外圆和内圆的顶点与闭合线段 pts0, seg0 = circle(30, 1.4) pts1, seg1 = circle(16, 0.6) # 合并顶点集,内圆线段索引偏移外圆的顶点数量 pts = np.vstack([pts0, pts1]) seg = np.vstack([seg0, seg1 + seg0.shape[0]]) # 定义带孔洞的区域:holes列表中每个元素是孔洞内部的一个点(用于标记排除区域) A = dict(vertices=pts, segments=seg, holes=[[0, 0]]) # 关键:使用'p'参数执行纯约束三角剖分,不添加任何新顶点 B = tr.triangulate(A, 'p') # 对比原始轮廓与剖分结果 tr.compare(plt, A, B) plt.show()
关键原理与注意事项
'p'参数的作用
这个参数告诉triangle库:只使用用户提供的顶点和约束线段进行三角剖分,绝对不插入新顶点,同时严格遵守孔洞边界的约束。孔洞定义的正确性
holes列表中的每个元素必须是对应孔洞内部的任意点(比如你用的原点[0,0]),库会通过这个点识别需要排除的区域。如果是多孔洞场景,只需在列表中添加每个孔洞的内部点即可,比如holes=[[0,0], [0.3,0], [-0.3,0]]。OpenCV轮廓的适配
针对实际场景中的OpenCV嵌套轮廓:- 提取每个轮廓的顶点集,注意内外轮廓的缠绕顺序(建议外轮廓顺时针,内轮廓逆时针,或统一相反,避免边界混淆)
- 为每个轮廓生成闭合的线段(类似示例中
% N的处理) - 合并所有顶点和线段,为每个内轮廓添加对应的孔洞内部点
- 同样使用
'p'参数执行剖分即可
凹多边形的处理
该方案完全支持凹多边形,只要你正确提供了凹多边形的顶点和闭合约束线段,'p'参数会自动处理边界,生成仅用原始顶点的三角剖分结果。
运行修改后的代码,你会看到三角剖分仅填充内外圆之间的环形区域,中间孔洞被正确保留,所有三角形都由原始的46个顶点组成,没有任何额外点被插入。
内容的提问来源于stack exchange,提问作者Thijser
相关产品推荐
相关产品推荐

