插入法三维重构

9 篇文章 0 订阅
8 篇文章 1 订阅

2019-4-9  Delaunay三角剖分-逐点插入法

一:理解delaunay三角剖分原理

        关键点在于三角形生成的规则及其实现过程。生成初始三角形,将初始三角形放入临时三角形中,判断三角形是否满足delaunay三角形规则,只有满足规则三角形才会被加入Delaunay三角形链表中。否则插入新的点,生成新的临时三角形,在对新三角形进行delaunay规则判断,继续进行分割,知道满足条件,将三角形加入Delaunay三角形链表中,直到遍历所有点,完成三角剖分。

          1:delaunay三角形空圆特性:                       构建空间三角片的关键依据

          2:delaunay三角形最大化最小角;                对构建完成的三角片进行局部优化的依据

          3:具有凸多边形外壳,就是所谓凸包             n个点生成的三角形大于n个的一种理解  

耗时的地方:1:如何建立超级三角形,将所有的点包围

                      2:需要搜索临时三角形列表,确定插入点所在的三角形,进而更新插入三角形临时边

二:结合需求搭建程序函数结构

        input:已排序的顶点列表(vertices)

        output:划分完成的三角剖分结果(triangles)

        //若顶点未排序,则先进行排序 ,排序规则可利用先x大小后y大小的方法。排序的目的是什么?

        初始化超级三角形,将所有点包含其中        //如何划分超级三角形?

        初始化临时三角形列表(temp triangles),将超级三角形加入其中    //三角形,顶点,边的结构体如何建立

        初始化结果三角形列表(triangles),将超级三角形加入其中

        遍历已排序的所有点,进行delaunay三角剖分操作。按照排序索引进行遍历

                 初始化三角形边缓存数组(edge buffer)    //若插入点不满足delaunay规则,则需将插入点与原三角形的三个顶点连接,                                                                                   // 生成三个新的三角形,保存新的三个边与原三角形的边

                 遍历临时三角形列表中的所有三角形

                           计算三角形圆心和半径       // 三角形外接圆的表达,圆心及半径

                           如果该点在外接圆的右侧    //如何判断这个结果

                                   则该三角形为delaunay三角形,保存到triangles中,跳过

                           如果该点三角形在外接圆的外侧,不在右侧的情况

                                    定为不确定三角形

                           如果该点在外接圆内部

                                      该点不为delaunay三角形,删除temp中的三角形

                                       连接原三角形三个顶点,生成三条边加入edge buffer中

                   遍历完临时三角形,对edge的边进行去重   // 去重的操作方法

                   将edge buffer中生成的新边,与原三角形三个顶点生成新的三角形,加入temp triangles 列表中

         遍历完所有点后,合并triangles与temp triangles

         删除超级三角形有关的三角形

end

定义数据结构及函数功能

// 点结构体
struct Point_
{
    float x;
    float y;
    float z;
}
Point_* pts = new  Point_[p_num];
// 建立点云列表,利用索引的方式获取每个点,创建边和三角面结构体,
// 一方面 减少点复制而避免内存浪费
// 另一方面可将三角化后的点直接用于GLSL进行表面重构


// 边结构体
struct Edge_
{
    int e1;
    int e2;
}

// 三角形结构体
struct Triangle_
{
    int p1;
    int p2;
    int p3;
}

//创建点云
bool createPoints(const int n_point, PointXY* &pxy);

// 排序函数,对点集进行排序
void xySort(const void *v1,const void *v2);

// 构建超级三角形
// 利用排序后最左边和最右边的点进行构建
Triangle_  superTriangle(const float* &vertices);

// 输入三角形(三个顶点),计算外接圆的圆心及半径
int circumCircle(Triangle_ triangle, float&xc, float&yc, float&r)

// 实现delaunay三角剖分
void  DT(int nv, PointXY p[],Triangle_ temp_tri[], int &ntri)
int xySort(const void *v1,const void *v2)
{
     PointXY* p1 = (PointXY*)v1;
     PointXY* p2 = (PointXY*)v2;
     
     if(p1->x < p2->x)
         return (-1);
      else if(p1->x > p2->x)
         return (1);
      return (0);
}

 

2019-4-10 

三:实现具体函数功能

bool createPoints(const int n_point, PointXY* &pxy)
{
	//初始化
	double x, y;
	bool b_Ok = false;

     //注意添加这个函数,根据时间创建随机数,比较合理
	srand((time_t) time(NULL));

	int pn = 0;
	while(pn != n_point)
	{
		//生成新的点,并检查是否有重复的点
		do{
			b_Ok = true;
			x = rand()%500;
			y = rand()%500;
			for (int n_cp = 0; n_cp <= pn; n_cp++)
			{
				if((x == pxy[n_cp].x) && (y == pxy[n_cp].y)) b_Ok = false;
			}
		}while (!b_Ok);

		pxy[pn].x = x * 1.0;
		pxy[pn].y = y * 1.0;		
		pn++;
	}

	if(pn != n_point )
		return false;
	else
		return true;
}

四:调试修改代码

异常:三个点时,结果出现异常,不能正确保存结果。

           异常位置在哪?

1:边参数设置位置错误,需要在进行遍历每个临时三角形前就初始化为0,nedge = 0

2:输入n个点,生成的三角形一般都大于n,因此在设置临时三角形为3倍

3:删除临时三角形貌似出现异常了,暂时没找到

 

参考文献:[1]https://www.cnblogs.com/zhiyishou/p/4430017.html

                  [2]https://blog.csdn.net/qq_34719188/article/details/83216527

                  [3]https://blog.csdn.net/newthinker_wei/article/details/45598769

                  [4]http://paulbourke.net/papers/triangulate/

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值