博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
道格拉斯-普克抽稀算法《转》
阅读量:7090 次
发布时间:2019-06-28

本文共 3956 字,大约阅读时间需要 13 分钟。

 
1、抽稀

通俗点讲,直接举个栗子吧:我们知道运动轨迹实际上是由很多个经纬度坐标连接而成。那么我们是否需要将所有运动时记录下来的经纬度坐标都用来绘制轨迹呢?其实是没必要的,很多数据其实是多余的,实际上将这些多余的数据剔除仍然能保证轨迹曲线形状大致不变,而且还能让曲线更平滑更节省存储空间,类似这样的过程我们就称之为抽稀。抽稀的算法很多,这里将介绍一种经典的算法:道格拉斯-普克(Douglas-Peuker)算法。

 

2、道格拉斯-普克(Douglas-Peuker)算法

还是举个栗子吧,假设在平面坐标系上有一条由N个坐标点组成的曲线,已设定一个阈值epsilon

(1)首先,将起始点与结束点用直线连接, 再找出到该直线的距离最大,同时又大于阈值epsilon的点并记录下该点的位置(这里暂且称其为最大阈值点),如图所示:

 

(2)接着,以该点为分界点,将整条曲线分割成两段(这里暂且称之为左曲线和右曲线),将这两段曲线想象成独立的曲线然后重复操作(1),找出两边的最大阈值点,如图所示:

 

(3)最后,重复操作(2)(1)直至再也找不到最大阈值点为止,然后将所有最大阈值点按顺序连接起来便可以得到一条更简化的,更平滑的,与原曲线十分近似的曲线,如图所示:

 

 

 

代码实现

先计算出距离开始、结束点距离最大的点。

public class Point {    double x;    double y;    public Point(int x, int y) {        this.x = x;        this.y = y;        System.out.print("(" + x + "," + y + ") ");    }    public static Point instance(int x, int y) {        return new Point(x, y);    }}

 

public class DouglasPeuckerUtil {    public static void main(String[] args) {        System.out.print("原始坐标:");        List
points = new ArrayList<>(); List
result = new ArrayList<>(); points.add(Point.instance(1, 1)); points.add(Point.instance(2, 2)); points.add(Point.instance(3, 4)); points.add(Point.instance(4, 1)); points.add(Point.instance(5, 0)); points.add(Point.instance(6, 3)); points.add(Point.instance(7, 5)); points.add(Point.instance(8, 2)); points.add(Point.instance(9, 1)); points.add(Point.instance(10, 6)); System.out.println(""); System.out .println("====================================================================="); System.out.print("抽稀坐标:"); result = DouglasPeucker(points, 1); for (Point p : result) { System.out.print("(" + p.x + "," + p.y + ") "); } } public static List
DouglasPeucker(List
points, int epsilon) { // 找到最大阈值点,即操作(1) double maxH = 0; int index = 0; int end = points.size(); for (int i = 1; i < end - 1; i++) { double h = H(points.get(i), points.get(0), points.get(end - 1)); if (h > maxH) { maxH = h; index = i; } } // 如果存在最大阈值点,就进行递归遍历出所有最大阈值点 List
result = new ArrayList<>(); if (maxH > epsilon) { List
leftPoints = new ArrayList<>();// 左曲线 List
rightPoints = new ArrayList<>();// 右曲线 // 分别提取出左曲线和右曲线的坐标点 for (int i = 0; i < end; i++) { if (i <= index) { leftPoints.add(points.get(i)); if (i == index) rightPoints.add(points.get(i)); } else { rightPoints.add(points.get(i)); } } // 分别保存两边遍历的结果 List
leftResult = new ArrayList<>(); List
rightResult = new ArrayList<>(); leftResult = DouglasPeucker(leftPoints, epsilon); rightResult = DouglasPeucker(rightPoints, epsilon); // 将两边的结果整合 rightResult.remove(0);//移除重复点 leftResult.addAll(rightResult); result = leftResult; } else { // 如果不存在最大阈值点则返回当前遍历的子曲线的起始点 result.add(points.get(0)); result.add(points.get(end - 1)); } return result; } /** * 计算点到直线的距离 * * @param p * @param s * @param e * @return */ public static double H(Point p, Point s, Point e) { double AB = distance(s, e); double CB = distance(p, s); double CA = distance(p, e); double S = helen(CB, CA, AB); double H = 2 * S / AB; return H; } /** * 计算两点之间的距离 * * @param p1 * @param p2 * @return */ public static double distance(Point p1, Point p2) { double x1 = p1.x; double y1 = p1.y; double x2 = p2.x; double y2 = p2.y; double xy = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); return xy; } /** * 海伦公式,已知三边求三角形面积 * * @param cB * @param cA * @param aB * @return 面积 */ public static double helen(double CB, double CA, double AB) { double p = (CB + CA + AB) / 2; double S = Math.sqrt(p * (p - CB) * (p - CA) * (p - AB)); return S; }

 

链接:https://www.jianshu.com/p/bf595477a124
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

转载于:https://www.cnblogs.com/chenjack/p/9300695.html

你可能感兴趣的文章
多线程常用方法 sleep wait join等以及对锁的控制
查看>>
MPEG-DASH新功能白皮书翻译
查看>>
关于图片在内存中的大小(k或者M)
查看>>
2018 一份"有点难"的iOS面试题(5年iOS开发)
查看>>
linux mint19-日常使用笔记
查看>>
如何快速掌握一个ui框架
查看>>
git过滤
查看>>
web开发安全框架中的Apache Shiro的应用
查看>>
赵童鞋带你入门PHP(一) 开发环境搭建
查看>>
JavaScript 七大继承全解析
查看>>
nginx正则表达式(上篇)
查看>>
Spark入门(六)--Spark的combineByKey、sortBykey
查看>>
一款Android图文识别与扫描软件
查看>>
封装的前端常用工具函数
查看>>
好程序员web前端教程:对象
查看>>
算法排序篇——选择排序与插入排序
查看>>
浮动 二 文字围绕现象 (上)
查看>>
【每日推理2019/05/25】
查看>>
React生命周期
查看>>
Java基础系列四
查看>>