Skip to content

Instantly share code, notes, and snippets.

@timyates
Forked from rhyolight/rdp.js
Created June 8, 2012 11:03
Show Gist options
  • Save timyates/2894998 to your computer and use it in GitHub Desktop.
Save timyates/2894998 to your computer and use it in GitHub Desktop.
Ramer-Douglas-Peucker line filtering algorithm in JavaScript
findPerpendicularDistance = ( point, line ) ->
[pointX,pointY] = point[0..1]
lineStart = x: line[0][0], y: line[0][1]
lineEnd = x: line[1][0], y: line[1][1]
slope = ( lineEnd.y - lineStart.y ) / ( lineEnd.x - lineStart.x )
intercept = lineStart.y - ( slope * lineStart.x )
Math.abs( slope * pointX - pointY + intercept ) / Math.sqrt( Math.pow( slope, 2) + 1)
douglasPeucker = ( points, epsilon ) ->
maxIndex = maxDistance = 0
for point, i in points[2..]
perpendicularDistance = findPerpendicularDistance( point, [points[1], points[points.length-1]] )
if perpendicularDistance > maxDistance
maxIndex = i + 2
maxDistance = perpendicularDistance
if maxDistance > epsilon
leftRecursiveResults = douglasPeucker points[1...maxIndex], epsilon
rightRecursiveResults = douglasPeucker points[maxIndex...], epsilon
leftRecursiveResults.concat rightRecursiveResults
else
points
function findPerpendicularDistance(point, line) {
var pointX = point[0],
pointY = point[1],
lineStart = {
x: line[0][0],
y: line[0][1]
},
lineEnd = {
x: line[1][0],
y: line[1][1]
},
slope = (lineEnd.y - lineStart.y) / (lineEnd.x - lineStart.x),
intercept = lineStart.y - (slope * lineStart.x),
result;
result = Math.abs(slope * pointX - pointY + intercept) / Math.sqrt(Math.pow(slope, 2) + 1);
return result;
}
function douglasPeucker(points, epsilon) {
var i,
maxIndex = 0,
maxDistance = 0,
perpendicularDistance,
leftRecursiveResults, rightRecursiveResults,
filteredPoints;
// find the point with the maximum distance
for (i = 2; i < points.length - 1; i++) {
perpendicularDistance = findPerpendicularDistance(points[i], [points[1], points[points.length - 1]]);
if (perpendicularDistance > maxDistance) {
maxIndex = i;
maxDistance = perpendicularDistance;
}
}
// if max distance is greater than epsilon, recursively simplify
if (maxDistance >= epsilon) {
leftRecursiveResults = douglasPeucker(points.slice(1, maxIndex), epsilon);
rightRecursiveResults = douglasPeucker(points.slice(maxIndex), epsilon);
filteredPoints = leftRecursiveResults.concat(rightRecursiveResults);
} else {
filteredPoints = points;
}
return filteredPoints;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment