摘要:道格拉斯普克抽稀算法,是用来对大量冗余的图形数据点进行压缩以提取必要的数据点。经道格拉斯普克法压缩后得到的图形如图所示。但道格拉斯普克法较垂距法复杂且通常编程实现时需要采用递归方有一定的难度。
道格拉斯-普克抽稀算法,是用来对大量冗余的图形数据点进行压缩以提取必要的数据点。该算法实现抽稀的过程是:先将一条曲线首尾点虚连一条直线,求其余各点到该直线的距离,取其最大者与规定的临界值相比较,若小于临界值,则将直线两端间各点全部舍去,否则将离该直线距离最大的点保留,并将原线条分成两部分,对每部分线条再实施该抽稀过程,直到结束。抽稀结果点数随选取限差临界值的增大而减少,应用时应根据精度来选取限差临界值,以获得最好的效果。
以下转载自:垂距法与道格拉斯-普克法删除冗余顶点效率的比较
道格拉斯- 普克法可描述为:将一条曲线首末顶点虚连一条直线 ,求出其余各顶点到该直线的距离 ,选其最大者与规定的限差相比较 ,若小于等于限差 ,则将直线两端间各点全部删去;若大于限差 ,则离该直线距离最大的顶点保留 ,并以此为界 ,把曲线分为两部分 ,对这两部分重复使用上述方法 ,直至最终无法作进一步的压缩为止 (见图 3)。
道格拉斯 2 普克法有一个十分突出的优点 ,即它是一个整体算法 ,在一般情况下可保留较大弯曲形态上的特征点。经道格拉斯-普克法压缩后得到的图形如图 4所示。由于该算法可准确删除小弯曲上的定点 ,故能从体上有效地保持线要素的形态特征。正是因为道格拉斯-普克法具有这样突出的优点 ,所以已经在线要素地自动制图中得到了较广泛的应用。但道格拉斯- 普克法较垂距法复杂 ,且通常编程实现时需要采用递归方 ,有一定的难度。
转载end
以下是javascript版本的实现
</>复制代码
<span class="hljs-attr">DouglasPeucker</span>
- var points = [{
- x: 10,
- y: 10
- }, {
- x: 20,
- y: 30
- }, {
- x: 30,
- y: 12
- }, {
- x: 35,
- y: 5
- }, {
- x: 40,
- y: 22
- }, {
- x: 50,
- y: 12
- }, {
- x: 80,
- y: 40
- }];
- var Helper = {
- renderPointsTo: function(points, anchor) {
- var d;
- for (var i = 0, p, a = K(anchor); i < points.length; i++) {
- p = points[i];
- if (a) {
- a.appendChild(K("div", {}, {
- position: "absolute",
- left: p.x + "px",
- top: p.y + "px",
- width: "5px",
- height: "5px",
- backgroundColor: "green",
- fontSize: "1px"
- }));
- }
- }
- }
- };
- Helper.renderPointsTo(points, "processBefore");
- var DouglasPeucker = {
- getProcessPoints: function(points, tolerance) {
- ///
获取处理后的点 - /// 包含点的数组
- /// 取样临界值
- ///
- if (!K.isArr(points) || !points.length) { //当points不是数组或没有值时,直接返回一个空数组
- return [];
- }
- if (points.length < 3) return points; //小于3个点时不抽稀,因为1个或2个点无法进行抽稀
- var firstPoint = 0,
- lastPoint = points.length - 1; //取开始点与结束点的下标
- var pointIndexsToKeep = []; //保存需要点下标的数组
- pointIndexsToKeep.push(firstPoint);
- pointIndexsToKeep.push(lastPoint); //开始与结束不进行处理,直接保留
- while (points[firstPoint] == points[lastPoint]) { //处理闭合情况,闭合时,强制断开
- lastPoint--;
- }
- this.reduce(points, firstPoint, lastPoint, tolerance, pointIndexsToKeep); //抽稀
- var resultPoints = []; //返回的点数组
- pointIndexsToKeep.sort(function(a, b) { //排序,这个可排可不排
- return a - b;
- });
- for (var i = 0; i < pointIndexsToKeep.length; i++) {
- resultPoints.push(points[pointIndexsToKeep[i]]);
- }
- return resultPoints;
- },
- reduce: function(points, firstPoint, lastPoint, tolerance, pointIndexsToKeep) {
- ///
抽稀处理 - /// 待抽稀的数组
- /// 起点
- /// 终点
- /// 取样临界值
- /// 保留点下标的数组
- var maxDis = 0,
- idxFarthest = 0; //定义最大长度及最远点的下标
- for (var i = firstPoint, dis; i < lastPoint; i++) {
- dis = this.perpendicularDistance(points[firstPoint], points[lastPoint], points[i]); //获取当前点到起点与
- if (dis > maxDis) { //保存最远距离
- maxDis = dis;
- idxFarthest = i;
- }
- }
- if (maxDis > tolerance && idxFarthest != 0) { //如果最远距离大于临界值
- pointIndexsToKeep.push(idxFarthest);
- this.reduce(points, firstPoint, idxFarthest, tolerance, pointIndexsToKeep);
- this.reduce(points, idxFarthest, lastPoint, tolerance, pointIndexsToKeep);
- }
- },
- perpendicularDistance: function(beginPoint, endPoint, comparePoint) {
- ///
计算给出的comparePoint到beginPoint与endPoint组成的直线的垂直距离 - /// 起始点
- /// 结束点
- /// 比较点
- ///
- //Area = |(1/2)(x1y2 + x2y3 + x3y1 - x2y1 - x3y2 - x1y3)| *Area of triangle
- //Base = v((x1-x2)2+(y1-y2)2) *Base of Triangle*
- //Area = .5*Base*H *Solve for height
- //Height = Area/.5/Base
- var area = Math.abs(0.5 * (beginPoint.x * endPoint.y + endPoint.x * comparePoint.y + comparePoint.x * beginPoint.y -
- endPoint.x * beginPoint.y - comparePoint.x * endPoint.y - beginPoint.x * comparePoint.y));
- var bottom = Math.sqrt(Math.pow(beginPoint.x - endPoint.x, 2) + Math.pow(beginPoint.y - endPoint.y, 2));
- var height = area / bottom * 2;
- return height;
- }
- };
- Helper.renderPointsTo(DouglasPeucker.getProcessPoints(points, 14), "processAfter");
宣传下我的区块管理框架Magix:https://github.com/thx/magix
欢迎试用Magix、star与fork
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/80047.html
摘要:所以就利用文字的宽度除以文字个数计算个大概为该文字在中所占据的范围。在取点位坐标作为最小范围时,按照以下方式设置会比较准确。 需求背景 一般在做地图相关的需求是才会用到文字抽稀,我也是在为公司的地图引擎实现一个功能时才实现了该方法,在这里将其简化了,就在普通的 Canvas 上进行操作,并没有引入地图概念 效果 showImg(https://s2.svend.cc/post/text...
摘要:中的算法附道面试常见算法题解决方法和思路关注每日一道面试题详解面试过程通常从最初的电话面试开始,然后是现场面试,检查编程技能和文化契合度。值得记住的数组方法有和。一个好的解决方案是使用内置的方法。 JavaScript中的算法(附10道面试常见算法题解决方法和思路) 关注github每日一道面试题详解 Introduction 面试过程通常从最初的电话面试开始,然后是现场面试,检查编程...
摘要:本文对一些排序算法进行了简单分析,并给出了的代码实现。平均时间复杂度不好分析,它是冒泡排序是稳定的排序算法。冒泡排序是原地排序算法原地排序指的是空间复杂度是的排序算法。归并排序,会将数组从中间分成左右两部分。 本文对一些排序算法进行了简单分析,并给出了 javascript 的代码实现。因为本文包含了大量的排序算法,所以分析不会非常详细,适合有对排序算法有一定了解的同学。本文内容其实不...
摘要:事件中属性等于。响应的状态为或者。同步在上会产生页面假死的问题。表示声明的变量未初始化,转换为数值时为。但并非所有浏览器都支持事件捕获。它由两部分构成函数,以及创建该函数的环境。 1 介绍JavaScript的基本数据类型Number、String 、Boolean 、Null、Undefined Object 是 JavaScript 中所有对象的父对象数据封装类对象:Object、...
阅读 3504·2021-11-24 10:30
阅读 3429·2021-11-22 15:29
阅读 3787·2021-10-28 09:32
阅读 1431·2021-09-07 10:22
阅读 3428·2019-08-30 15:55
阅读 3703·2019-08-30 15:54
阅读 3583·2019-08-30 15:54
阅读 2930·2019-08-30 15:44
极致性价比!云服务器续费无忧!
Tesla A100/A800、Tesla V100S等多种GPU云主机特惠2折起,不限台数,续费同价。
NVIDIA RTX 40系,高性价比推理显卡,满足AI应用场景需要。
乌兰察布+上海青浦,满足东推西训AI场景需要