(随机插入法做德劳内三角划分)递推&递归
//德劳内三角剖分 RIC算法
#include <queue>
using namespace std;
// 代表一个点
struct Point {
int X;
int Y;
};
// 代表一个三角形
struct Trangle {
Point a, Point b, Point c;
};
// 返回德劳内图形DT中某点P所在的三角形 (会用到DCEL结构)
T TriangleContaining (Polyline DT, Point P) {
//这里用一个桶来存储其中所有的点,每个桶的外边界就是一个已经剖分过的三角形
}
//找到与abc构成三角形的右边的三角形中ab边对应的点x
Point RightSite(Point a, Point b) {
//使用DCEL 既b\a边所在三角形中的另一个顶点
//没有返回null
}
//查看x是否在p、a、b三点构成的内接圆中
int InCircle(Point p, Point a, Point b, Point x) {
//一个行列式 关于 a\b\x\p的四阶行列式
//优点:没有除法,速度O(1)
return f(pabx); //大于0表示在圆内,小于表示在圆形外
}
//用ab替换px
void FlipEdge(Point a, Point b, Point p, Point x) {
//这里面要操作的结构是要改变上面的存储桶三角形所包含点的位置
}
//测试固定a、b两点,与p构成的外接圆是否为空圆(圆内不存在任何点)
//如果不为空圆,则修改为最优(使用了递归)
void STest(Point p, Point a, Point b) {
//获取从a到b直线右边的那个点(利用DCEL的双向结构)
//(与a、b所在线段构成三角形(会有左右两个)右边的那个顶点)
Point x = RightSite(a, b);
//如果不存在点x在ab右侧,即ab为多边形的边界,最简单的情况,不用处理
if(!x) return;
//查看x是否在p、a、b三点构成的内接圆中
if(InCircle(p, a, b, x) > 0) {
//用ab替换px
FlipEdge(a, b, p, x);
//测试新增加的值得怀疑的两条线
STest(p, a, x);
STest(p, x, b);
}
}
//德劳内三角形的递归做法
//测试并修复图中可疑的pa、pb、pc线(因为可能破坏结构不符合空圆要求)
void SwapTest(Point p, Point a, Point b, Point c) {
STest(p, a, b);
STest(p, b, c);
STest(p, c, a);
}
//德劳内三角剖分的递推做法
//只需改变递归做法中的反转测试
SwapTest(p, a, b, c) {
queue q = {(a, b), (b, c), (c, a)};
wahile(!q.empty()) {
(a, b) = q.dequeue();
Point x = RightSite(a, b);//find t(a,x,b) on opposite side(using DCEL)
if(!x) connect; //in case x doesnot exist
if(InCircle(p, a, b, x)) { //if x voilates in-circle condition
FlipEdge(a, b, p, x);//replace ab with px and
Q.enqueue((a, x), (x, b));//insert the 2 new triangles
}
}
}
//在已经正确的德劳内图形中插入点P
void Insert (Point p) {
//首先找到包含P这个点的三角形(P在哪个三角形内部)
Trangle T(a, b, c) = TriangleContaining(DT, p);
//链接pa、pb、pc三条线 并插入到德劳内三角剖分图形中
connect(p, a);
connect(p, b);
connect(p, c);
//测试并修复图中可疑的pa、pb、pc线(因为可能破坏结构不符合空圆要求)
SwapTest(p, a, b, c);
}
int main() {
Point a, Point b, Point c;
//假设原本是一个三角形
Polyline DT(a, b, c);
//不断地加入点构成更多的三角形。
//类似于建堆
for(int i = 2; i < points.size(); ++i) {
Insert(points[i]);
}
return 0;
}