Skip to content

Instantly share code, notes, and snippets.

@andrewharvey
Created September 3, 2018 14:07
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/d232d361c2d653e15dc1832cf7169762 to your computer and use it in GitHub Desktop.
Save andrewharvey/d232d361c2d653e15dc1832cf7169762 to your computer and use it in GitHub Desktop.
OSRM Isochrones
#!/usr/bin/env node
var process = require('process');
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 concaveman = require('concaveman');
var turf = {
point: require('@turf/helpers').point,
polygon: require('@turf/helpers').polygon,
featureCollection: require('@turf/helpers').featureCollection,
featureEach: require('@turf/meta').featureEach,
circle: require('@turf/circle').default,
pointGrid: require('@turf/point-grid').default,
bbox: require('@turf/bbox').default
};
if (process.argv.length < 6) {
console.log('Usage: ./isochrone.js planet.osrm points.csv output.geojson distance');
process.exit(1);
}
var osrmFilePath = process.argv[2];
var inputFilePath = process.argv[3];
var outputFilePath = process.argv[4];
var distance = process.argv[5];
var debug = (process.argv.length > 6) && process.argv[6] === '--debug';
var osrm = new OSRM(osrmFilePath);
var csv = d3.csvParse(fs.readFileSync(inputFilePath, 'utf-8'));
var NUM_THREADS = 4;
var outputFeatures = [];
// for each coordinate as the origin and other nearby points as the destinations use osrm.table
async.eachOfLimit(csv, 1, function (origin, index, callback) {
console.log(`${index + 1} / ${csv.length}`)
var originPoint = turf.point([+origin.Longitude, +origin.Latitude]);
var circle = turf.circle(originPoint, distance * 2, { units: 'meters' }); // *2 just to be safe in case turf's distances aren't accurate
var grid = turf.pointGrid(turf.bbox(circle), 10, { units: 'meters', mask: circle });
async.parallelLimit(grid.features.map(function (destinationPoint) {
return function (gridCallback) {
osrm.route({
coordinates: [originPoint.geometry.coordinates, destinationPoint.geometry.coordinates],
geometries: 'geojson',
overview: 'full'
}, function (err, result) {
if (err) {
console.error(err);
gridCallback(err, null);
return;
}
if (result && result.routes.length) {
if (result.routes[0].distance <= distance) {
gridCallback(null, [
turf.point(destinationPoint.geometry.coordinates, {
distance: result.routes[0].distance
}),
{
type: 'Feature',
geometry: result.routes[0].geometry,
properties: {
distance: result.routes[0].distance
}
}
]);
return;
}
}
gridCallback(null, null);
return;
});
};
}), NUM_THREADS, function (err, results) {
if (results.length) {
var isochrone = concaveman(points.map((feature) => { return feature.geometry.coordinates; }));
var feature = turf.polygon([isochrone], { ID: csv[index].ID, Routes: csv[index].Routes });
outputFeatures.push(feature);
if (debug) {
var points = results.filter((result) => { return result && result.length }).map((result) => { return result[0]; });
var lines = results.filter((result) => { return result && result.length }).map((result) => { return result[1]; });
points.forEach((point) => { outputFeatures.push(point); });
lines.forEach((line) => { outputFeatures.push(line); });
}
callback(err)
}
});
},
function (err) {
if (err) {
console.error(err);
return;
}
fs.writeFileSync(outputFilePath, JSON.stringify(turf.featureCollection(outputFeatures)));
console.log(`Saved output to ${outputFilePath}`)
});
{
"name": "isochrone",
"version": "1.0.0",
"description": "",
"main": "isochrone.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Andrew Harvey <andrew@alantgeo.com.au>",
"license": "ISC",
"dependencies": {
"@turf/bbox": "^6.0.1",
"@turf/circle": "^6.0.1",
"@turf/helpers": "^6.1.4",
"@turf/point-grid": "^6.0.1",
"async": "^2.6.1",
"concaveman": "^1.1.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