public
Last active

Reducing coordinate density in KML files. Original script by Ben Buckman.

  • Download Gist
distance.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* */
/* 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.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
// 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();
});
}
]);

Hi,

It's done.

https://gist.github.com/1709189

-¤ćol d.-
Find me on Google+ http://gplus.to/pol

On Mon, Feb 13, 2012 at 01:12, Ben Buckman, New Leaf Digital <
reply@reply.github.com

wrote:

Polzme, please add credits for my original script which this is "based on":
https://twitter.com/#!/drupol/status/164228686919376898, as you "said you
would do":https://twitter.com/#!/drupol/status/164364319205761025 two
weeks ago.
Thank you!


Reply to this email directly or view it on GitHub:
https://gist.github.com/1709189

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.