Skip to content

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Reducing coordinate density in KML files. Original script by Ben Buckman.
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* */
/* Simple node js module to get distance between two coordinates. */
/* */
/* Code transformed from Chris Veness example code - please refer to his website for licensing */
/* questions. */
/* */
/* */
/* Latitude/longitude spherical geodesy formulae & scripts (c) Chris Veness 2002-2011 */
/* - www.movable-type.co.uk/scripts/latlong.html */
/* */
/* */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/** Converts numeric degrees to radians */
if(typeof(Number.prototype.toRad) === "undefined") {
Number.prototype.toRad = function () {
return this * Math.PI / 180;
}
}
// start and end are objects with latitude and longitude
//decimals (default 2) is number of decimals in the output
//return is distance in kilometers.
exports.getDistance = function(start, end, decimals) {
decimals = decimals || 2;
var earthRadius = 6371; // km
lat1 = parseFloat(start.latitude);
lat2 = parseFloat(end.latitude);
lon1 = parseFloat(start.longitude);
lon2 = parseFloat(end.longitude);
var dLat = (lat2 - lat1).toRad();
var dLon = (lon2 - lon1).toRad();
var lat1 = lat1.toRad();
var lat2 = lat2.toRad();
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = earthRadius * c;
return Math.round(d * Math.pow(10, decimals)) / Math.pow(10, decimals);
};
// reduce the coordinate density of a KML file.
// you will need the distance.js file too.
var async = require('async')
, fs = require('fs')
, path = require('path')
, distance = require('distance');
var argv = require('optimist')
.usage('Usage: $0 --in [PATH] --out [PATH] --reduce [NUM] --distance [NUM]')
.describe('in', 'source KML file')
.describe('out', 'write to new KML file')
.describe('reduce', 'Preserve 1/N coordinates. 1=all, 4=25%, 10=10%. Default 2 (50%).')
.describe('distance', 'Minimum distance between each coordinates (in Km)')
.demand(['in', 'out', 'reduce', 'distance'])
.default({'reduce': 2, 'distance':1})
.argv;
try {
if (isNaN(argv.reduce) || argv.reduce < 1 || argv.reduce % 1 !== 0) {
throw("--reduce has to be an integer >= 1");
}
if (isNaN(argv.distance) || argv.distance < 1) {
throw("--distance has to be an number >= 1");
}
}
catch(e) {
console.error(e);
process.exit(1);
}
var origXml, newXml = '';
async.series([
// make sure input file exists
function(next) {
path.exists(argv.in, function(exists){
if (exists) next();
else {
console.error("Input file %s does not exist.", argv.in);
process.exit(1);
}
});
},
// read it
function(next) {
fs.readFile(argv.in, 'utf8', function (err, data) {
if (err) throw err;
origXml = data;
next();
});
},
// parse it
function(next) {
var lines = origXml.split("\n")
, coordRegex = /-?\d+\.\d+,-?\d+\.\d+/g
, ind
, coordCounter = 0;
var curLine;
var prevLine;
for (ind = 0; ind < lines.length; ind++) {
isCoordLine = lines[ind].match(coordRegex);
if (! isCoordLine) {
newXml += lines[ind] + '\n';
} else {
if (prevLine) {
coords = isCoordLine[0].split(",");
coord1 = {'latitude':coords[0],'longitude':coords[1]};
coords = prevLine[0].split(",");
coord2 = {'latitude':coords[0], 'longitude':coords[1]};
dist = distance.getDistance(coord1, coord2);
coordCounter++;
//console.log('Distance: '+dist);
//console.log('coordCounter: ' + coordCounter);
if (dist >= argv.distance && coordCounter >= argv.reduce) {
//console.log('Adding to file...');
coordCounter=0;
newXml += lines[ind] + '\n';
} else {
//console.log('Skipping...');
}
}
prevLine = isCoordLine;
}
}
next();
},
// write
function(next) {
fs.writeFile(argv.out, newXml, 'utf8', function(err) {
if (err) throw(err);
else next();
});
}
]);
@drupol
Owner
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.