需求:

有时候当移动速度很慢,GPS定位的轨迹点就非常的多,这时候为了缩减数据量,需要将不突出的点去掉。

思路:

(1) 在曲线首尾两点间虚连一条直线,求出其余各点到该直线的距离。

(2)选其最大者与阈值相比较,若大于阈值,则离该直线距离最大的点保留,否则将直线两端点间各点全部舍去。
(3)依据所保留的点,将已知曲线分成两部分处理,重复第1、2步操作,迭代操作,即仍选距离最大者与阈值比较,依次取舍,直到无点可舍去,最后得到满足给定精度限差的曲线点坐标

这里使用道格拉斯-普克算法实现,易于理解。效果对比图如下:

源代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>DouglasPeucker</title>
</head>
<body>
<canvas id="drawing" style="height:300px;width:100%"></canvas>
<canvas id="drawing2" style="height:300px;width:100%"></canvas>
</body>
<script type="text/javascript" > var points1=[];
var pointsshao=[];
var pts=[];
var hval=30;//阈值 //随机生成1000个点
for(var i=0;i<1000;i++){
var oldx=i*10,oldy=Math.random()*150;
points1.push([oldx,oldy,i]);
} //求斜率
function xielv(pt1,pt2)
{
var k,b;
var canshu={};
canshu.k=(pt1[1]-pt2[1])/(pt1[0]-pt2[0]);
canshu.b=pt1[1]-canshu.k*pt1[0];
return canshu;
}
//求点到直线的距离
function distanceToline(pt,cs){
return (Math.abs(cs.k*pt[0]-pt[1]+cs.b))/Math.sqrt(cs.k*cs.k+1);
} //开始计算(道格拉斯普克算法)
pts.push(points1[0]);
countPoint(points1);
pts.push(points1[points1.length-1]); //排序
function sort(pts){
for(var i=0;i<pts.length-1;i++)
{
var a=pts[i];
var b=pts[i+1];
if(b[2]>a[2]){
pts[i]=b;
pts[i+1]=a;
for(var j=i;j>0;j--)
{
var c=pts[j-1];
if(b[2]>c[2]){
pts[j-1]=b;
pts[j]=c;
}
}
}
}
}
//对坐标点进行取舍
function countPoint(points){ var maxD=0;
var maxPoint=null;
var maxindex=0;
//大于2个点才开始计算
if(points.length>2){
var pt1=points[0];
var pt2=points[points.length-1];
var cs=xielv(pt1,pt2);
for(var i=0;i<points.length;i++){
var pt=points[i];
var dis=distanceToline(pt,cs);
//判断该线段中是否有点到由该线段端点组成的直线的距离大于限值
if(dis>maxD)
{
maxD=dis;
maxPoint=pt;
maxindex=i;
}
}
if(maxD>hval) //如果最大值就从该点位置将线段进行切分
{
var pts1=points.slice(maxindex);//中分末尾数组
var pts2=points.slice(0,maxindex+1);//中分前面数组
if(pts1.length>2 && pts2.length>2)
{
if(!countPoint(pts1) && !countPoint(pts2)){ //如果两个线段都没有超过限制就结束计算
pts.push(maxPoint);
}
}else if(pts1.length>2 && pts2.length<=2){ //计算pts1
if(!countPoint(pts1))pts.push(maxPoint); }else if(pts1.length<=2 && pts2.length>2){ //计算pts2
if(! countPoint(pts2))pts.push(maxPoint); }
} return false;
}
}
//由大到小
sort(pts);
drawWay("drawing2",pts);
drawWay("drawing",points1)
//绘制曲线
function drawWay(name,points){
var drawing=document.getElementById(name);
if(drawing.getContext){
var context=drawing.getContext("2d");
context.beginPath();
var oldx=points[0][0];
var oldy=points[0][1];
for(var i=0;i<points.length;i++){
var p=points[i];
context.moveTo(oldx,oldy);
oldx=p[0];
oldy=p[1];
context.lineTo(oldx,oldy);
}
context.closePath();
context.stroke();
}
}
</script>

道格拉斯-普克算法(JavaScript实现)的更多相关文章

  1. OpenCV 学习笔记03 凸包convexHull、道格拉斯-普克算法Douglas-Peucker algorithm、approxPloyDP 函数

    凸形状内部的任意两点的连线都应该在形状里面. 1 道格拉斯-普克算法 Douglas-Peucker algorithm 这个算法在其他文章中讲述的非常详细,此处就详细撰述. 下图是引用维基百科的.ε ...

  2. GIS矢量数据化简:一种改进的道格拉斯-普克算法以及C++实现

    GIS领域的同志都知道,传统的道格拉斯-普克算法都是递归实现.然而有时候递归的层次太深的话会出现栈溢出的情况.在此,介绍一种非递归的算法. 要将递归算法改为非递归算法,一般情况下分为两种场景.第一种是 ...

  3. 道格拉斯—普克(Douglas一Peukcer)节点抽稀算法

    Douglas一Peukcer算法由D.Douglas和T.Peueker于1973年提出,简称D一P算法,是眼下公认的线状要素化简经典算法.现有的线化简算法中,有相当一部分都是在该算法基础上进行改进 ...

  4. .net中使用 道格拉斯-普特 抽希轨迹点

    Douglas一Peukcer算法由D.Douglas和T.Peueker于1973年提出,简称D一P算法,是目前公认的线状要素化简经典算法.现有的线化简算法中,有相当一部分都是在该算法基础上进行改进 ...

  5. 数据结构与算法JavaScript (一) 栈

    序 数据结构与算法JavaScript这本书算是讲解得比较浅显的,优点就是用javascript语言把常用的数据结构给描述了下,书中很多例子来源于常见的一些面试题目,算是与时俱进,业余看了下就顺便记录 ...

  6. 《数据结构与算法JavaScript描述》

    <数据结构与算法JavaScript描述> 基本信息 作者: (美)Michael McMillan 译者: 王群锋 杜欢 丛书名: 图灵程序设计丛书 出版社:人民邮电出版社 ISBN:9 ...

  7. 翻阅《数据结构与算法javascript描述》--数组篇

    导读: 这篇文章比较长,介绍了数组常见的操作方法以及一些注意事项,最后还有几道经典的练习题(面试题). 数组的定义: JavaScript 中的数组是一种特殊的对象,用来表示偏移量的索引是该对象的属性 ...

  8. 数据结构与算法javascript描述

    <数据结构与算法javascript描述>--数组篇 导读: 这篇文章比较长,介绍了数组常见的操作方法以及一些注意事项,最后还有几道经典的练习题(面试题). 数组的定义: JavaScri ...

  9. 列表的实现-----数据结构与算法JavaScript描述 第三章

    实现一个列表 script var booklist = new List(); booklist.append('jsbook'); booklist.append('cssbook'); book ...

随机推荐

  1. 原生sql和 TP sql怎么关联?

    整合后

  2. Activiti6-快速开始

    下载 https://www.activiti.org/download-links 快速开始 https://www.activiti.org/quick-start 用户指南 https://ww ...

  3. H3C Basic NAT

  4. [转]Node.js中package.json中^和~的区别

    webpack 项目的package.json 文件列出了项目所依赖的插件和库,同时也给出了对应的版本说明,但是在版本说明前面还有个符号:'^'(插入符号)和'~'(波浪符号),总结了下他们之间的区别 ...

  5. 如何让索引只能被一个SQL使用

    有个徒弟问我,要创建一个索引,去优化一个SQL,但是创建了索引之后其他 SQL 也要用 这个索引,其他SQL慢死了,要优化的SQL又快.遇到这种问题咋搞? 一般遇到这种问题还是很少的.处理的方法很多. ...

  6. linux版本依赖

    记住, 你的模块代码一定要为每个它要连接的内核版本重新编译 -- 至少, 在缺乏 modversions 时, 这里不涉及因为它们更多的是给内核发布制作者, 而不是开发者. 模块 是紧密结合到一个特殊 ...

  7. VS2017 OpenCV3.4.2 通过Release的版本 源码编译成 x86

    官方release的OpenCV3..2版本只有64bit,由于项目需要,现在把它重新编译成x86的库. 下载源码: github官方仓库 https://github.com/opencv/open ...

  8. linux进程简单睡眠

    当一个进程睡眠, 它这样做以期望某些条件在以后会成真. 如我们之前注意到的, 任何睡 眠的进程必须在它再次醒来时检查来确保它在等待的条件真正为真. Linux 内核中睡眠的 最简单方式是一个宏定义, ...

  9. linux 存取 I/O 内存

    在一些平台上, 你可能逃过作为一个指针使用 ioremap 的返回值的惩罚. 这样的使用不 是可移植的, 并且, 更加地, 内核开发者已经努力来消除任何这样的使用. 使用 I/O 内 存的正确方式是通 ...

  10. JS事件委托(代理)学习笔记

    在开始之前我们先来熟悉一下HTML DOM addEventListener()方法,该方法用于向指定元素添加事件句柄.语法说明如下图所示: 主要想强调一下第三个参数useCapture,默认值为fa ...