“先按耳切页给出的十边形坐标,从 $s=(1,5)$ 走到 $t=(7,5)$。任务是给出合法剖分、单调块、门户序列、漏斗每次改变的链,以及与独立可见图一致的最短长度;再完成本页的非对称三角机…”
形式陈述
一个凹简单多边形能否像剥洋葱一样,每次切下一块三角形,直到只剩最后一块?设输入
当前边界的连续三个顶点
在一般位置下,可以先检查
再检查其余顶点没有落入耳三角形。这个局部凸性和空三角形测试保证
初始为每个顶点计算耳标记,放入候选队列。每切掉一个耳,只重新检查它的两个相邻顶点,其余顶点的相邻三元组没有改变。这里还需一个几何引理:若凸顶点的候选三角形含其他边界顶点,它必含一个凹顶点。其他边界只能经候选底边进入这个三角形;取其中朝耳尖伸得最深的一段边界,其最高凸出点对这个凹口是凸角,对原多边形则是凹角,因此给出所需顶点。被删的耳尖是凸顶点,不会删掉这个凹顶点阻挡证书。所以非邻接的旧非耳仍被阻挡;旧耳也不会因为删除一个外部顶点而失效。只有与被删耳尖相邻的两个三元组需要重新检查。使用双向循环链表保存边界,可在
每次耳测试扫描至多
直觉
凸角只说明边界在这里向内转得合适,耳还要求这块三角形没有盖住别的边界。凹口可能从远处伸进来,所以“看起来尖尖的一角”不一定能切。
为什么算法不会卡住?先有一个基本事实:每个至少四边的简单多边形都有内部对角线。可取一个凸角
任一不加新顶点的剖分有
例子与边界
使用下列十边形,编号严格按所列顺序:
一份完整输出为
共有八个三角形。每片按逆时针方向排列,面积均为正,面积和等于原多边形面积
这个输入含非相邻共线点。核验程序采用保守测试:只有严格凸顶点可切,任何其他顶点落在候选三角形的闭区域中都阻挡该耳,因此不会产生穿过别的顶点的对角线。若输入含相邻共线顶点,可以在预处理删除不改变轮廓的中间点,记录映射;若任务要求保留每个原顶点,则需在相关三角形边上重新插入它们并细分,不能还使用删点后的
自交、带孔和零宽连接不满足简单无孔合约。带孔区域先连桥再耳切需要新的边界表示与弱简单性处理;任意连一条桥可能穿过障碍。点集的Delaunay 剖分也不能替代这里的算法,因为它可能填满凹口。
推论与应用
不变量是“已经输出的三角形内部两两不交;它们与当前剩余多边形恰好覆盖原区域”。每切下一耳,公共部分只有新对角线,因而保持不变量;最后剩一三角形,得到覆盖整个区域的剖分。方向判定既判断凸性,也核验三角形包含和边相交,必须采用一致的精确符号。
耳切的实现短,适合作为更快算法的独立参照。大输入可改用单调划分后进行线性栈剖分;两种输出对角线不必相同,但都必须通过上述覆盖与计数检查。最终剖分还给漏斗最短路提供三角形通道。
参考资料
- Joseph O’Rourke,Computational Geometry in C,第 2 版,1998,Chapter 1,尤其 Code 1.14。作者的代码与勘误索引确认耳切代码的位置;该索引列出三角剖分实现与对应章节。
- Mark de Berg 等,Computational Geometry: Algorithms and Applications,第 3 版,2008,§3.1,课程原书,对角线、三角形计数与剖分结构。
- Dave Mount,Polygon Triangulation,2026,pp.1–2,三角剖分与对偶树。