From 6eb78a49196e461c9511589a0baf260351fc260c Mon Sep 17 00:00:00 2001 From: ldd Date: Thu, 21 Nov 2019 21:09:25 -0500 Subject: [PATCH] add custom linear decimator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use Ramer–Douglas–Peucker algorithm (https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm) to decimate a linear line Work in progress, consider this an idea, more than an actual commit --- src/traces/scatter/decimator.js | 47 +++++++++++++++++++++++++++++++ src/traces/scatter/line_points.js | 9 +++++- 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 src/traces/scatter/decimator.js diff --git a/src/traces/scatter/decimator.js b/src/traces/scatter/decimator.js new file mode 100644 index 00000000000..b1a85091f82 --- /dev/null +++ b/src/traces/scatter/decimator.js @@ -0,0 +1,47 @@ +'use strict'; + +var epsilon = 0.01; +function perpendicularDistance(point, startingPoint, endPoint) { + if(!point || !startingPoint || !endPoint) return -1; + var x0 = point[0]; + var y0 = point[1]; + var x1 = startingPoint[0]; + var y1 = startingPoint[1]; + var x2 = endPoint[0]; + var y2 = endPoint[1]; + + return ( + Math.abs((y2 - y1) * x0 - (x2 - x1) * y0 + x2 * y1 - y2 * x1) / + Math.sqrt(Math.pow(y2 - y1, 2) + Math.pow(x2 - x1, 2)) + ); +} + +module.exports = function douglasPeucker(points) { + // Find the point with the maximum distance + var dmax = 0; + var index = 0; + var end = points.length - 1; + for(var i = 0; i < end; i++) { + var d = perpendicularDistance(points[i], points[0], points[end]); + if(d > dmax) { + index = i; + dmax = d; + } + } + + var simplifiedPoints = []; + + // If max distance is greater than epsilon, recursively simplify + if(dmax > epsilon) { + // Recursive call + var partial1 = douglasPeucker(points.slice(0, index), epsilon); + var partial2 = douglasPeucker(points.slice(index, end + 1), epsilon); + + // Build the result list + simplifiedPoints = partial1.slice(0, -1).concat(partial2); + } else { + simplifiedPoints = [points[0], points[end]]; + } + // Return the result + return simplifiedPoints; +}; diff --git a/src/traces/scatter/line_points.js b/src/traces/scatter/line_points.js index 89964c92ccd..5ac61c76fa9 100644 --- a/src/traces/scatter/line_points.js +++ b/src/traces/scatter/line_points.js @@ -18,7 +18,7 @@ var Lib = require('../../lib'); var segmentsIntersect = Lib.segmentsIntersect; var constrain = Lib.constrain; var constants = require('./constants'); - +var linearSimplifier = require('./decimator'); module.exports = function linePoints(d, opts) { var xa = opts.xaxis; @@ -352,6 +352,13 @@ module.exports = function linePoints(d, opts) { } } + if(linear && opts.simplify) { + for(i = 0; i < len; i++) { + addPt(getPt(i)); + } + return [linearSimplifier(pts)]; + } + // loop over ALL points in this trace for(i = 0; i < len; i++) { clusterStartPt = getPt(i);