Skip to content

Instantly share code, notes, and snippets.

@andrewharvey
Created July 29, 2018 04:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andrewharvey/d46e5b55652793768a0b88f695006c36 to your computer and use it in GitHub Desktop.
Save andrewharvey/d46e5b55652793768a0b88f695006c36 to your computer and use it in GitHub Desktop.
Distance table between CSV coordinates using OSRM
#!/usr/bin/env node
process.env.UV_THREADPOOL_SIZE = Math.ceil(require('os').cpus().length * 1.5);
var OSRM = require('osrm');
var path = require('path');
var fs = require('fs');
var d3 = require('d3');
var async = require('async');
var cheapRuler = require('cheap-ruler');
var osrm = new OSRM("australia.osrm");
// see part 1 at https://gist.github.com/andrewharvey/0248034c0bf098702e13029fd4059a98
var csv = d3.csvParse(fs.readFileSync('sa1_oa_weighted_centroid.csv', 'utf-8'));
var coordinates = csv.map(function (row) {
return [+row.X, +row.Y];
});
// approximate distance between origin and destination to attempt to calculate a duration for (in kilometers)
var MAX_DISTANCE = 50;
var NUM_THREADS = 4;
var outputFile = fs.createWriteStream('durations.csv');
outputFile.on('error', function (err) { throw err; });
// for each coordinate as the origin and other nearby points as the destinations use osrm.table
async.eachOfLimit(coordinates, NUM_THREADS, function (origin, index, callback) {
var ruler = cheapRuler(origin[1], 'kilometers');
var destinationsIndex = []; // keep track of which destinations map to which source coordinates input index
// filter out destinations which are far away from the origin
var destinations = coordinates.filter(function (destination, index) {
if (ruler.distance(origin, destination) < MAX_DISTANCE) {
destinationsIndex.push(index);
return true;
}
return false;
});
// ensure the origin is the 1st coordinate pair
destinations.unshift(origin);
destinationsIndex.unshift(index);
// duration of the fastest route between all pairs of supplied coordinates
// http://project-osrm.org/docs/v5.15.2/api/#table-service
osrm.table({
coordinates: destinations,
sources: [0]
}, function(err, result) {
if (err) {
console.error(err)
callback(err)
return;
}
console.log('From origin ' + index + ' calculated ' + result.durations[0].length + ' distances')
for (i = 1; i < result.durations[0].length; i++) { // start at 1 to skip source
if (index !== destinationsIndex[i]) { // no point outputing 0 for self to self
var output = {
from: csv[index].sa1_main16,
to: csv[destinationsIndex[i]].sa1_main16,
duration: result.durations[0][i]
};
outputFile.write(`${output.from},${output.to},${output.duration}\n`);
}
}
callback(err);
});
},
function (err) {
if (err) {
console.error(err);
return;
}
outputFile.end();
console.log('Saved output to durations.csv')
});
{
"name": "duration_table",
"version": "1.0.0",
"description": "",
"main": "duration_table.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Andrew Harvey <andrew@alantgeo.com.au>",
"license": "ISC",
"dependencies": {
"async": "^2.6.1",
"cheap-ruler": "^2.5.1",
"d3": "^5.5.0",
"osrm": "^5.18.0"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment