GIS矢量数据化简:一种改进的道格拉斯-普克算法以及C++实现
2013-10-05 16:46
1141 查看
既然今天有时间,就多写几篇博文算了,也为了明天出去玩好好放松一下。
GIS领域的同志都知道,传统的道格拉斯-普克算法都是递归实现。然而有时候递归的层次太深的话会出现栈溢出的情况。在此,介绍一种非递归的算法。
要将递归算法改为非递归算法,一般情况下分为两种场景。第一种是问题定义是递归的,如阶乘、斐波那契数列等,对于这类问题,改为递归算法很简单,直接用迭代来做。另外一种是过程是递归的,如本文的道格拉斯-普克算法,对于这类问题呢,一般是用栈(stack)来记录中间结果,最后得到结果。
为了保证极值点的不被舍去,将曲线在弯曲极值点分为两段处理,弯曲极值点通过中间点与相邻两个顶点的角度度量。然而传统的Douglas-Peucker算法一般在计算过程中没有考虑到记录中间最大的距离的节点,造成循环时间长、递归嵌套层次太深,从而影响了程序的运行效率。本文提出一种结合栈数据结构的分段Douglas-Peucker算法,它从曲线的一端出发,首先将第一个点和最后一个点作为改进的Douglas-Peucker算法的工作区间,然后判断最远点的距离是否大于阈值,这样完成线要素的综合化简。改进D-P算法的具体步骤如下:
(1)寻找曲线曲率最大的点,将曲线以此点为界一分为二分成两部分,对于每一部分都有点列 。然后分别处理这两段曲线。
(2)对于第一段曲线,有矢量的离散点序列 ,设 并且 ,连接 组成一条线段。生成一个栈 ,将 点入栈 。
(3)在 之间的点中寻找与 线段距离最大的点,记为 。
(4)判断 点到 的距离是否小于阈值,若否,则设 ,并将 加入到特征点序列,将 压入栈 ,用线段连接 ,回到(3)。若是,执行第(5)步。
(5)判断 是否等于 的栈顶元素,若否,则设 、 , 表示栈顶,用线段连接 ,回到(3)。若是,执行(6)。
(6)判断 是否等于 ,若否,则设 、 ( 表示 的栈顶的下一点),用线段连接 ,栈顶元素出栈,回到(3)。
(7)当栈为空时,第一段曲线计算结束。处理第二段曲线,重复(1)~(7)。
改进算法的程序流程图如下图所示。
![](http://img.blog.csdn.net/20131005163950875?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhvdXh1Z3VhbmcyMzY=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
图 改进Douglas-Peucker流程图
本文提出的改进算法虽然在编程上面比较复杂,但是能够减少中间重复循环的次数。有了上面的流程图之后,那么代码就相对简单了。
代码不是完整的,其中有调用到了另外一个函数,就是找曲线中离曲线两端点的直线的距离的最大值点,这个过程很简单,就不讲了,还有自己定义的一些数据结构,本文只是讲解这一种算法的思想,其中算法描述部分由公式,原文是在word中编辑的,如果看不懂就直接看流程图还清晰点。
GIS领域的同志都知道,传统的道格拉斯-普克算法都是递归实现。然而有时候递归的层次太深的话会出现栈溢出的情况。在此,介绍一种非递归的算法。
要将递归算法改为非递归算法,一般情况下分为两种场景。第一种是问题定义是递归的,如阶乘、斐波那契数列等,对于这类问题,改为递归算法很简单,直接用迭代来做。另外一种是过程是递归的,如本文的道格拉斯-普克算法,对于这类问题呢,一般是用栈(stack)来记录中间结果,最后得到结果。
为了保证极值点的不被舍去,将曲线在弯曲极值点分为两段处理,弯曲极值点通过中间点与相邻两个顶点的角度度量。然而传统的Douglas-Peucker算法一般在计算过程中没有考虑到记录中间最大的距离的节点,造成循环时间长、递归嵌套层次太深,从而影响了程序的运行效率。本文提出一种结合栈数据结构的分段Douglas-Peucker算法,它从曲线的一端出发,首先将第一个点和最后一个点作为改进的Douglas-Peucker算法的工作区间,然后判断最远点的距离是否大于阈值,这样完成线要素的综合化简。改进D-P算法的具体步骤如下:
(1)寻找曲线曲率最大的点,将曲线以此点为界一分为二分成两部分,对于每一部分都有点列 。然后分别处理这两段曲线。
(2)对于第一段曲线,有矢量的离散点序列 ,设 并且 ,连接 组成一条线段。生成一个栈 ,将 点入栈 。
(3)在 之间的点中寻找与 线段距离最大的点,记为 。
(4)判断 点到 的距离是否小于阈值,若否,则设 ,并将 加入到特征点序列,将 压入栈 ,用线段连接 ,回到(3)。若是,执行第(5)步。
(5)判断 是否等于 的栈顶元素,若否,则设 、 , 表示栈顶,用线段连接 ,回到(3)。若是,执行(6)。
(6)判断 是否等于 ,若否,则设 、 ( 表示 的栈顶的下一点),用线段连接 ,栈顶元素出栈,回到(3)。
(7)当栈为空时,第一段曲线计算结束。处理第二段曲线,重复(1)~(7)。
改进算法的程序流程图如下图所示。
图 改进Douglas-Peucker流程图
本文提出的改进算法虽然在编程上面比较复杂,但是能够减少中间重复循环的次数。有了上面的流程图之后,那么代码就相对简单了。
void DouglasPeucker(LineVertex *V,int &i,int &j,double e) { double dist = 9999; int f = 0; //最大距离的点的序号 stack<int> tempVertex; //STL实现的栈 tempVertex.push(j); do { //循环i和j之间距离直线ij最大的点 FindSplit(*V,i,j,&f,&dist); if (dist > e) //大于阈值 { (*V)[f].flag = true; j = f; //更新B值 tempVertex.push(f); //记录最大距离点,放入栈中存储 continue; } else { if (!tempVertex.empty() && j != tempVertex.top()) //判断后一点是否和当前栈顶相等 { i = f; j = tempVertex.top(); continue; } else { if (j != V->size()) //判断最后一个点是否和当前线段的B点重合 { i = j; if (!tempVertex.empty()) { deque<int> cont = tempVertex._Get_container(); if (cont.size() > 1) //栈中至少还有两个点 { j = cont[cont.size()-2]; } else if (cont.size() == 1) //栈中只有一个点 { j = cont[cont.size()-1]; } tempVertex.pop(); continue; } } } } } while (!tempVertex.empty()); }
代码不是完整的,其中有调用到了另外一个函数,就是找曲线中离曲线两端点的直线的距离的最大值点,这个过程很简单,就不讲了,还有自己定义的一些数据结构,本文只是讲解这一种算法的思想,其中算法描述部分由公式,原文是在word中编辑的,如果看不懂就直接看流程图还清晰点。
相关文章推荐
- GIS矢量数据化简:一种改进的道格拉斯-普克算法以及C++实现
- 一种改进的道格拉斯-普克算法以及C++实现
- C++实现道格拉斯-普克法压缩矢量数据
- 数据结构串的实现以及KMP改进算法
- 8皇后以及N皇后算法探究,回溯算法的JAVA实现,非递归,数据结构“栈”实现
- 数据结构与算法——散列表类的C++实现(探测散列表)
- 数据结构与算法——图的邻接表表示法类的C++实现
- 数据结构与算法:C++实现插入排序
- 如果系统要使用超大整数(超过long长度范围),请你设计一个数据结构来存储这种超大型数字以及设计一种算法来实现超大整数加法运算
- 【数据结构与算法】二叉树给定两个节点的最短距离(C++实现)
- 每对顶点间的最短路径算法时间复杂度改进C++实现
- C/C++数据结构通过顺序栈实现括号()匹配算法
- [算法导论] 快速排序以及最大堆的C++实现
- 数据结构与算法——表达式树类的C++实现(二叉树)
- # 数据挖掘算法 ## 18大经典DM算法 18大数据挖掘的经典算法以及代码实现,涉及到了决策分类,聚类,链接挖掘,关联挖掘,模式挖掘等等方面,后面都是相应算法的博文链接,希望能够帮助大家学。 目前
- 解决数据不平衡的smote算法简述,以及改进
- 数据挖掘-决策树ID3分类算法的C++实现
- 一种常见的数据挖掘的算法SPRINT算法的简单实现
- 二维点云数据椭圆拟合算法及C++实现
- 数字图像处理,中值滤波和均值滤波及其改进算法的C++实现