Created
April 25, 2017 06:44
-
-
Save hleinone/7bd459b84c15ca5b6e832d0ebb20bfd7 to your computer and use it in GitHub Desktop.
Normalizes GPX file by replacing track points with exactly same coordinate with interpolated values, removing leaps with inhuman speed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var fs = require("fs"); | |
var xml2js = require("xml2js"); | |
var gpx = process.argv[2]; | |
// https://gist.github.com/wteuber/6241786 | |
Math.fmod = function(a, b) { | |
return Number((a - (Math.floor(a / b) * b)).toPrecision(8)); | |
}; | |
function clockwiseDiff(from, to) { | |
return normalizeLongitude(Math.fmod(to - from - 360, 360) + 360); | |
}; | |
function normalizeLongitude(lon) { | |
return Math.fmod(Math.fmod(lon + 180, 360) + 360, 360) - 180; | |
}; | |
fs.exists(gpx, function(exists) { | |
if (!exists) { | |
console.error("File " + gpx + " not found"); | |
return; | |
} | |
fs.readFile(gpx, "utf8", function(error, data) { | |
if (error) { | |
console.error("Reading file " + gpx + " failed: " + error); | |
return; | |
} | |
xml2js.parseString(data, function(error, result) { | |
if (error) { | |
console.error("Parsing GPX file " + gpx + " failed: " + error); | |
return; | |
} | |
var trkseg = result.gpx.trk[0].trkseg[0]; | |
var trkpts = trkseg.trkpt; | |
var trkptsGroupedByCoordinate = trkpts.reduce(function(res, elem, idx, src) { | |
var last = res[res.length - 1]; | |
if (!last || last[last.length - 1]["$"].lat != elem["$"].lat || last[last.length - 1]["$"].lon != elem["$"].lon) { | |
res.push([elem]); | |
} else { | |
last.push(elem); | |
} | |
return res; | |
}, []); | |
var trkptsInterpolated = trkptsGroupedByCoordinate.reduce(function(res, elem, idx, src) { | |
if (elem.length == 1) { | |
res.push(elem[0]); | |
} else { | |
if (idx < src.length - 1) { | |
var from = elem[0]; | |
var to = src[idx + 1][0]; | |
var fromT = new Date(from.time[0]).getTime(); | |
var toT = new Date(to.time[0]).getTime(); | |
var tDiff = toT - fromT; | |
var latDiff = new Number(to["$"].lat) - new Number(from["$"].lat); | |
var lonDiff = clockwiseDiff(new Number(from["$"].lon), new Number(to["$"].lon)); | |
var eleDiff = new Number(to.ele[0]) - new Number(from.ele[0]); | |
elem.forEach(function(item, index) { | |
if (index == 0) { | |
res.push(item); | |
} else { | |
var t = new Date(item.time[0]).getTime(); | |
var factor = (t - fromT) / tDiff; | |
// Interpolate latitude | |
item["$"].lat = new Number(from["$"].lat) + (factor * latDiff); | |
// Interpolate longitude | |
item["$"].lon = normalizeLongitude(new Number(from["$"].lon) + (factor * lonDiff)); | |
// Interpolate elevation | |
item.ele[0] = new Number(from.ele[0]) + (factor * eleDiff); | |
res.push(item); | |
} | |
}); | |
} else { | |
elem.forEach(function(item) { | |
res.push(item); | |
}); | |
} | |
} | |
return res; | |
}, []); | |
result.gpx.trk[0].trkseg[0].trkpt = trkptsInterpolated; | |
var builder = new xml2js.Builder(); | |
var xml = builder.buildObject(result); | |
console.log(xml); | |
}); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment