矢量数据压缩算法“Douglas-Peucker”——递归与非递归实现(python)
思路参考
思路参考文章:GIS算法基础——矢量数据压缩道格拉斯普克压缩算法(非递归实现)
GIS算法基础——矢量数据压缩道格拉斯普克压缩算法(非递归实现)_RookGISer的博客-CSDN博客
Douglas-Peucker 算法是矢量数据压缩经典算法,算法的基本思想如下:
假设组成曲线的顶点集合为 P1、P2、…Pn,假设 P1、Pn为曲线的起始点和终止点,将其虚连成一条直线, 计算曲线内点 Pi(i=2,3,…,n-1)到直线 P1Pn的距离 Di,通过比较距离的大小得到距离最大对应的点 Pk, 判断 Dk的值与预先给定的阈值之间的大小关系。若小于阈值,则舍去曲线上的全部中间顶点;反之,若大于阈值,则保留点 Pk,并以该点为界限,将首尾两点分别与该点虚连成一条直线,形成两条新的直线段 P1Pk 和 PkPn,再重复上述的步骤确定下一批压缩后的保留点。并以此类推,直到两端点之间的曲线上的顶点到两端点虚连成的直线的最大距离小于阈值为止。
图示:
Step1:
假设有五个点,首先连接首位,即P1-P8,找出中间各点到该直线的最大距离,从图中可以看出,P3到直线P1P8的距离最大。
***当Step1的最大距离dmax 小于 阈值 时,舍弃直线中的所有点,只保留直线两个端点。
Step2:
若dmax 大于阈值,则将该点(获取最大距离的点)作为端点,重复操作,寻找dmax与阈值进行对比。若小于阈值,则将点舍弃。
通过上述操作,最终可实现数据的压缩。
递归实现思路:
1、计算出直线的方程。
2、遍历各点到直线的距离,保存最大距离与其点的索引,判断其与阈值的关系
a.若小于阈值:则该直线作为压缩后的数据。
b.若大于阈值,则该点将直线分为两段,AC CB
3、重复2的操作。
4、得到结果。
递归伪代码:
def rdp(points, epsilon):dmax = 0.0index = 0for i in range(1, len(points) - 1):d = point_line_distance(points[i], points[0], points[-1])if d > dmax:index = idmax = dif dmax >= epsilon:results = rdp(points[:index+1], epsilon)[:-1] + rdp(points[index:], epsilon)else:results = [points[0], points[-1]]return results
非递归思路(参考思路文章):
首先不使用递归,但是要做到将每个点都遍历一遍,选出最大距离的点,要对两端再进行遍历。参考文章作者提供了思路,采用“出栈入栈的操作”来实现非递归算法。
依旧以上面的图作为例子来讲解
Step1:
建立两个空栈,将首尾两个端点分别放入AB两个栈中。
Step2:
从直线中找到最大距离的点dmax(判断其与阈值的关系,若小于阈值,则直线为压缩后的数据),其索引为point3,将其放入栈B中。
此时,直线的端点从18 变为了 13
我们再次执行Step2的操作,所找到的最大距离就是13直线之间的最大距离了。
Step3:
若13之间的点的最大距离小于阈值,则B的顶端,出栈,将其放入A栈中。
之后在进行Step2的操作,所求的就是直线38之间的点。
直到最后,将B栈中的所有点都压入A中,算法结束。A栈中的点即为最终的点。
(写得不是很清楚,如果不明白可以参考首行文章,或者评论)
python伪代码
def RDP(Points,threshold):RDPFinout = []if(len(Points)<=1):RDPFinout = Pointsreturn RDPFinout# 读的数组的长度IndexsFin = len(Points)# 创建两个数组记录索引A = Stack()B = Stack()Maxindex = IndexsFin - 1# 将首位两个点坐标入栈A.push(0)B.push(Maxindex)#############while B栈不为空:maxDistanceIndex = findMaxdistanceIndex(Points, A.top(), B.top())maxDistance = findMaxdistance(Points, A.top(), B.top())if(maxDistance > threshold):#大于阈值B.push(maxDistanceIndex)else:#小于阈值A.push(B.pop())###############while A栈不为空:#输出结果,存放到数组中RDPFinout.append(Points[A.pop()])return RDPFinout
实验:
原图:
压缩后:
矢量数据压缩算法“Douglas-Peucker”——递归与非递归实现(python)相关推荐
- python创建树结构、求深度_数据结构-树以及深度、广度优先遍历(递归和非递归,python实现)...
前面我们介绍了队列.堆栈.链表,你亲自动手实践了吗?今天我们来到了树的部分,树在数据结构中是非常重要的一部分,树的应用有很多很多,树的种类也有很多很多,今天我们就先来创建一个普通的树.其他各种各样的树 ...
- 二叉树的几种递归和非递归式遍历:
二叉树的几种递归和非递归式遍历: 1 #include <fstream> 2 #include <iostream> 3 4 using namespace std; 5 6 ...
- 全排列(含递归和非递归的解法)
全排列在近几年各大网络公司的笔试中出现的比较频繁 首先来看看题目是如何要求的(百度迅雷校招笔试题). 用C++写一个函数, 如 Foo(const char *str), 打印出 str 的全排列, ...
- C#实现(递归和非递归)快速排序和简单排序
C#实现(递归和非递归)快速排序和简单排序 本人因为最近工作用到了一些排序算法,就把几个简单的排序算法,想冒泡排序,选择排序,插入排序,奇偶排序和快速排序等整理了出来,代码用C#代码实现,并且通过了测 ...
- 分别用递归和非递归方式实现二叉树先序、中序和后序遍历(java实现)
分别用递归和非递归方式实现二叉树先序.中序和后序遍历 用递归和非递归方式,分别按照二叉树先序.中序和后序打印所有的节点.我们约定:先序遍历顺序 为根.左.右;中序遍历顺序为左.根.右;后序遍历顺序为左 ...
- 汉诺塔的改编题(用栈求解,分别递归和非递归)
限制不能从最左侧的塔直接移动到最右侧,也不能从最右侧直接移动到最左侧,而是必须经过中间,求当塔有N层的时候,打印最优移动过程和最优移动总步数 例如:当塔为两层时,最上层的塔记为1,最下层的塔记为2,则 ...
- 树的先序遍历,中序遍历,后续遍历(递归和非递归实现)
前序遍历是先访问根节点再访问左子树最后访问右子树(中,左,右):中序遍历是先访问左子树再访问根节点最后访问右子树(左,中,右):后序遍历是先访问左子树再访问右子树最后访问根节点(左,右,中).---- ...
- 树与二叉树的深度优先与广度优先算法(递归与非递归)
本博客前面文章已对树与二叉树有过简单的介绍,本文主要是重点介绍有关二叉树的一些具体操作与应用 阅读本文前,可以先参考本博客 各种基本算法实现小结(三)-- 树与二叉树 和 各种基本算法实现小结( ...
- 全排列(递归与非递归实现)
全排列问题在公司笔试的时候非经常见,这里介绍其递归与非递归实现. 递归算法 1.算法简述 简单地说:就是第一个数分别以后面的数进行交换 E.g:E = (a , b , c),则 prem(E)= a ...
- 转载:二叉树的前中后和层序遍历详细图解(递归和非递归写法)
二叉树的前中后和层序遍历详细图解(递归和非递归写法) Monster_ii 2018-08-27 17:01:53 50530 收藏 403 分类专栏: 数据结构拾遗 文章标签: 二叉树 前序 中序 ...
最新文章
- 下载和安装Nginx之普通的HTTP和HTTPS服务器
- django 操作MySQL 中文乱码_Django 连接mysql数据库中文乱码
- 如何让asp.net应用程序定时自动执行代码
- Displaying Bitmaps Efficiently (一)-----Loading Large Bitmaps Efficiently(二)
- php cdi_通过MicroProfile上下文传播增强了CDI上下文和隔板
- socket异步处理问题
- 对于AES和RSA算法的结合使用以及MD5加盐注册登录时的密码加密
- 每日长难句打卡Day23
- 系统学习机器学习之神经网络(三)--GA神经网络与小波神经网络WNN
- schedule()函数的调用时机(周期性调度)
- 【吐槽】火车票一票难求啊
- mysql数据库主从停止_Mysql 主从数据库
- 服装打版软件ET2019淘宝100RMB买的
- sql_全国省市区、邮编、经纬度、城市拼音、电话区号
- coverity java_coverity检测不到代码 | 学步园
- 字符替换 英文字符串单词个数统计 python123题解
- 关于中国教育的一些思考
- 数学中 arg min是什么意思
- 黑客专用文本编辑器Emacs中文手册
- 窗函数法设计FIR滤波器参数特征表