http://blog.csdn.net/ACMaker/archive/2008/10/29/3176910.aspx
http://cgm.cs.mcgill.ca/~orm/rotcal.frame.html
历史:
1978年, M.I. Shamos's Ph.D. 的论文"Computational Geometry"标志着计算机科学的这一领域的诞生。 当时他发表成果的是一个寻找凸多边形直径的一个非常简单的算法, 即根据多边形的一对点距离的最大值来确定。
后来直径演化为由一对对踵点对来确定。 Shamos提出了一个简单的 O(n) 时间的算法来确定一个凸 n 角形的对踵点对。 因为他们最多只有 3n/2 对, 直径可以在 O(n) 时间内算出。
如同Toussaint后来提出的, Shamos的算法就像绕着多边形旋转一对卡壳。 因此就有了术语“旋转卡壳”。 1983年, Toussaint发表了一篇论文, 其中用同样的技术来解决许多问题。 从此, 基于此模型的新算法就确立了, 解决了许多问题。
他们包括:
- 计算距离
- 凸多边形直径
- 凸多边形宽
- 凸多边形间最大距离
- 凸多边形间最小距离
- 外接矩形
- 最小面积外接矩形
- 最小周长外接矩形
- 三角剖分
- 洋葱三角剖分
- 螺旋三角剖分
- 四边形剖分
- 凸多边形属性
- 合并凸包
- 找共切线
- 凸多边形交
- 临界切线
- 凸多边形矢量和
- 最薄截面
- 最薄横截带
凸多边形直径
我们将一个多边形上任意两点间的距离的最大值定义为多边形的直径。 确定这个直径的点对数可能多于一对。 事实上, 对于拥有 n 个顶点的多边形, 就可能有 n 对“直径点对”存在。一个多边形直径的简单例子如左图所示。 直径点对在图中显示为被平行线穿过的黑点 (红色的一对平行线). 直径用浅蓝色高亮显示。
显然, 确定一个凸多边形 P 直径的点对不可能在多边形 P 内部。 故搜索应该在边界上进行。 事实上, 由于直径是由多边形的平行切线的最远距离决定的, 所以我们只需要查询 对踵点。 Shamos (1978) 提供了一个 O(n) 时间复杂度计算n点凸包对踵点对的算法。直径通过遍历顶点列表, 得到最大距离即可。 如下是1985年发表于 Preparata 和 Shamos 文章中的 Shamos 算法的伪代码。
输入是一个多边形 P={ p1,..., pn}.
begin p0:=pn; q:=NEXT[p]; while (Area(p,NEXT[p],NEXT[q]) > Area(p,NEXT[p],q)) do q:=NEXT[q]; q0:=q; while (q != p0) do begin p:=NEXT[p]; Print(p,q); while (Area(p,NEXT[p],NEXT[q]) > Area(p,NEXT[p],q) do begin q:=NEXT[q]; if ((p,q) != (q0,p0)) then Print(p,q) else return end; if (Area(p,NEXT[p],NEXT[q]) = Area(p,NEXT[p],q)) then if ((p,q) != (q0,p0)) then Print(p,NEXT[q]) else Print(NEXT[p],q) end end.
此处
Print(p,q)
表示将
(p,q) 作为一个对踵点对输出,
Area(p,q,r)
表示三角形
pqr 的有向面积。
虽然直观上看这个过程与常规旋转卡壳算法不同, 但他们在本质上是相同的, 并且避免了所有角度的计算。
如下是一个更直观的算法:
- 计算多边形 y 方向上的端点。 我们称之为 ymin 和 ymax 。
- 通过 ymin 和 ymax 构造两条水平切线。 由于他们已经是一对对踵点, 计算他们之间的距离并维护为一个当前最大值。
- 同时旋转两条线直到其中一条与多边形的一条边重合。
- 一个新的对踵点对此时产生。 计算新的距离, 并和当前最大值比较, 大于当前最大值则更新。
- 重复步骤3和步骤4的过程直到再次产生对踵点对 (ymin,ymax) 。
- 输出确定最大直径的对踵点对。