Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 47d8903
Showing
12 changed files
with
5,223 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"extends": "airbnb-base", | ||
"plugins": [ | ||
"import" | ||
], | ||
"env": { | ||
"es6": true, | ||
"node": true | ||
}, | ||
"rules": { | ||
"comma-dangle": ["error", "never"] | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
.DS_Store | ||
node_modules/ | ||
npm-debug.log | ||
yarn-error.log | ||
|
||
test/data/* | ||
!test/data/Makefile | ||
!test/data/data.md5sum |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
language: node_js | ||
dist: trusty | ||
sudo: required | ||
|
||
branches: | ||
except: | ||
- /^v[0-9]/ | ||
|
||
node_js: | ||
- 4 | ||
|
||
addons: | ||
apt: | ||
sources: | ||
- ubuntu-toolchain-r-test | ||
packages: | ||
- g++-4.8 | ||
|
||
cache: | ||
yarn: true | ||
directories: | ||
- node_modules | ||
|
||
install: | ||
- yarn | ||
|
||
script: | ||
- make test |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<!-- Generated by documentation.js. Update this documentation by updating the source code. --> | ||
|
||
### Table of Contents | ||
|
||
- [isochrone](#isochrone) | ||
|
||
## isochrone | ||
|
||
Build isochrone using start point and options | ||
|
||
**Parameters** | ||
|
||
- `startPoint` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<float>** start point [lng, lat] | ||
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** object | ||
- `options.osrm` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** [osrm](https://github.com/Project-OSRM/osrm-backend) instance | ||
- `options.radius` **[number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** distance to draw the buffer as in | ||
[@turf/buffer](https://github.com/Turfjs/turf/tree/master/packages/turf-buffer) | ||
- `options.cellSize` **[number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** the distance across each cell as in | ||
[@turf/point-grid](https://github.com/Turfjs/turf/tree/master/packages/turf-point-grid) | ||
- `options.intervals` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)>** intervals for isochrones in minutes | ||
- `options.concavity` **[number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** relative measure of concavity as in | ||
[concaveman](https://github.com/mapbox/concaveman) (optional, default `2`) | ||
- `options.lengthThreshold` **[number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** length threshold as in | ||
[concaveman](https://github.com/mapbox/concaveman) (optional, default `0`) | ||
- `options.units` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** any of the options supported by turf units (optional, default `'kilometers'`) | ||
|
||
Returns **[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)** promise with GeoJSON when resolved |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
all: | ||
yarn | ||
|
||
clean: | ||
rm -rf node_modules | ||
|
||
shm: | ||
$(MAKE) all -i -C ./test/data | ||
|
||
test: shm | ||
yarn test | ||
|
||
.PHONY: test clean shm |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# Isochrone | ||
|
||
[![npm version](https://img.shields.io/npm/v/isochrone.svg)](https://www.npmjs.com/package/isochrone) | ||
[![Build Status](https://travis-ci.org/stepankuzmin/node-isochrone.svg?branch=master)](https://travis-ci.org/stepankuzmin/node-isochrone) | ||
[![npm downloads](https://img.shields.io/npm/dt/isochrone.svg)](https://www.npmjs.com/package/galton) | ||
|
||
Isochrone maps are commonly used to depict areas of equal travel time. | ||
Build isochrones using [OSRM](http://project-osrm.org/), [Turf](http://turfjs.org/) and [concaveman](https://github.com/mapbox/concaveman). | ||
|
||
![Screenshot](https://raw.githubusercontent.com/stepankuzmin/galton/master/example.png) | ||
|
||
## Installation | ||
|
||
``` | ||
npm install -g isochrone | ||
``` | ||
|
||
## Usage | ||
|
||
```js | ||
const OSRM = require('osrm'); | ||
const isochrone = require('isochrone'); | ||
|
||
const osrm = new OSRM({ path: './monaco.osrm' }); | ||
const startPoint = [7.41337, 43.72956]; | ||
|
||
const options = { | ||
osrm, | ||
radius: 2, | ||
cellSize: 0.1, | ||
intervals: [5, 10, 15], | ||
}; | ||
|
||
isochrone(startPoint, options) | ||
.then((geojson) => { | ||
console.log(JSON.stringify(geojson)); | ||
}); | ||
``` | ||
|
||
See [API](https://github.com/stepankuzmin/node-isochrone/blob/master/API.md) for more info. |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
const buffer = require('@turf/buffer'); | ||
const concaveman = require('concaveman'); | ||
const pointGrid = require('@turf/point-grid'); | ||
const rewind = require('geojson-rewind'); | ||
|
||
const makeGrid = (startPoint, options) => { | ||
const point = { | ||
type: 'Feature', | ||
geometry: { | ||
type: 'Point', | ||
coordinates: startPoint | ||
} | ||
}; | ||
|
||
const buffered = buffer(point, options.radius, options.unit); | ||
const grid = pointGrid(buffered, options.cellSize, options.units); | ||
|
||
return grid.features.map(feature => feature.geometry.coordinates); | ||
}; | ||
|
||
const groupByInterval = (destinations, intervals, travelTime) => { | ||
const intervalGroups = intervals.reduce((acc, interval) => | ||
Object.assign({}, acc, { [interval]: [] }) | ||
, {}); | ||
|
||
const pointsByInterval = travelTime.reduce((acc, time, index) => { | ||
const timem = Math.round(time / 60); | ||
const ceil = intervals.find(interval => timem <= interval); | ||
if (ceil) { | ||
acc[ceil].push(destinations[index].location); | ||
} | ||
return acc; | ||
}, intervalGroups); | ||
|
||
return pointsByInterval; | ||
}; | ||
|
||
const makePolygon = (points, interval, options) => { | ||
const concave = concaveman(points, options.concavity, options.lengthThreshold); | ||
|
||
return { | ||
type: 'Feature', | ||
geometry: { | ||
type: 'Polygon', | ||
coordinates: [concave] | ||
}, | ||
properties: { | ||
time: parseFloat(interval) | ||
} | ||
}; | ||
}; | ||
|
||
const makePolygons = (pointsByInterval, options) => | ||
Object.keys(pointsByInterval).reduce((acc, interval) => { | ||
const points = pointsByInterval[interval]; | ||
if (points.length >= 3) { | ||
acc.push(makePolygon(points, interval, options)); | ||
} | ||
return acc; | ||
}, []); | ||
|
||
/** | ||
* Build isochrone using start point and options | ||
* | ||
* @name isochrone | ||
* @param {Array.<float>} startPoint start point [lng, lat] | ||
* @param {Object} options object | ||
* @param {Object} options.osrm - [OSRM](https://github.com/Project-OSRM/osrm-backend) instance | ||
* @param {number} options.radius - distance to draw the buffer as in | ||
* [@turf/buffer](https://github.com/Turfjs/turf/tree/master/packages/turf-buffer) | ||
* @param {number} options.cellSize - the distance across each cell as in | ||
* [@turf/point-grid](https://github.com/Turfjs/turf/tree/master/packages/turf-point-grid) | ||
* @param {Array.<number>} options.intervals - intervals for isochrones in minutes | ||
* @param {number} [options.concavity=2] - relative measure of concavity as in | ||
* [concaveman](https://github.com/mapbox/concaveman) | ||
* @param {number} [options.lengthThreshold=0] - length threshold as in | ||
* [concaveman](https://github.com/mapbox/concaveman) | ||
* @param {string} [options.units='kilometers'] - any of the options supported by turf units | ||
* @returns {Promise} GeoJSON FeatureCollection of Polygons when resolved | ||
*/ | ||
const isochrone = (startPoint, options) => { | ||
const endPoints = makeGrid(startPoint, options); | ||
const coordinates = [startPoint].concat(endPoints); | ||
|
||
return new Promise((resolve, reject) => { | ||
options.osrm.table({ sources: [0], coordinates }, (error, table) => { | ||
if (error) { | ||
reject(error); | ||
} | ||
|
||
try { | ||
const travelTime = table.durations[0] || []; | ||
const pointsByInterval = groupByInterval(table.destinations, options.intervals, travelTime); | ||
|
||
const features = makePolygons(pointsByInterval, options); | ||
const featureCollection = rewind({ type: 'FeatureCollection', features }); | ||
resolve(featureCollection); | ||
} catch (e) { | ||
reject(e); | ||
} | ||
}); | ||
}); | ||
}; | ||
|
||
module.exports = isochrone; |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
{ | ||
"name": "isochrone", | ||
"version": "5.7.0", | ||
"description": "", | ||
"author": "Stepan Kuzmin <to.stepan.kuzmin@gmail.com> (stepankuzmin.ru)", | ||
"license": "MIT", | ||
"main": "dist/bundle.js", | ||
"jsnext:main": "src/server.js", | ||
"scripts": { | ||
"commit": "git-cz", | ||
"release": "standard-version", | ||
"docs": "documentation build index.js --format md --output API.md", | ||
"lint": "eslint .", | ||
"test": "node test/index.js" | ||
}, | ||
"config": { | ||
"commitizen": { | ||
"path": "./node_modules/cz-conventional-changelog" | ||
} | ||
}, | ||
"engine-strict": true, | ||
"engines": { | ||
"node": "4" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/stepankuzmin/node-isochrone.git" | ||
}, | ||
"dependencies": { | ||
"@turf/buffer": "4.3.1", | ||
"@turf/point-grid": "4.3.0", | ||
"concaveman": "1.1.1", | ||
"geojson-rewind": "0.2.0" | ||
}, | ||
"peerDependencies": { | ||
"osrm": "5.7.0" | ||
}, | ||
"devDependencies": { | ||
"@mapbox/geojsonhint": "2.0.1", | ||
"commitizen": "2.9.6", | ||
"cz-conventional-changelog": "2.0.0", | ||
"documentation": "4.0.0-rc.1", | ||
"osrm": "5.7.0", | ||
"eslint": "3.19.0", | ||
"eslint-config-airbnb-base": "11.1.3", | ||
"eslint-plugin-import": "2.2.0", | ||
"standard-version": "4.0.0", | ||
"tape": "4.6.3" | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
DATA_NAME:=monaco | ||
DATA_URL:=https://s3.amazonaws.com/mapbox/osrm/testing/$(DATA_NAME).osm.pbf | ||
DATA_POLY_URL:=https://s3.amazonaws.com/mapbox/osrm/testing/$(DATA_NAME).poly | ||
OSRM_BUILD_DIR=../../node_modules/osrm/lib/binding | ||
PROFILE_ROOT:=../../node_modules/osrm/profiles | ||
OSRM_EXTRACT:=$(OSRM_BUILD_DIR)/osrm-extract | ||
OSRM_CONTRACT:=$(OSRM_BUILD_DIR)/osrm-contract | ||
PROFILE:=$(PROFILE_ROOT)/car.lua | ||
|
||
all: | ||
wget $(DATA_URL) -O $(DATA_NAME).osm.pbf | ||
@echo "Running osrm-extract..." | ||
$(OSRM_EXTRACT) -p $(PROFILE) $(DATA_NAME).osm.pbf | ||
@echo "Running osrm-contract..." | ||
$(OSRM_CONTRACT) $(DATA_NAME).osrm | ||
|
||
clean: | ||
-rm -r $(DATA_NAME).* | ||
|
||
.PHONY: clean all |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
2b8dd9343d5e615afc9c67bcc7028a63 monaco.osm.pbf | ||
b0788991ab3791d53c1c20b6281f81ad monaco.poly |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
const path = require('path'); | ||
const test = require('tape'); | ||
const OSRM = require('osrm'); | ||
const geojsonhint = require('@mapbox/geojsonhint'); | ||
const isochrone = require('../index'); | ||
|
||
const points = [[7.41337, 43.72956], | ||
[7.41546, 43.73077], | ||
[7.41862, 43.73216]]; | ||
|
||
const osrmPath = path.join(__dirname, './data/monaco.osrm'); | ||
const osrm = new OSRM({ path: osrmPath }); | ||
|
||
const options = { | ||
osrm, | ||
radius: 2, | ||
cellSize: 0.1, | ||
concavity: 2, | ||
intervals: [5, 10, 15], | ||
lengthThreshold: 0, | ||
units: 'kilometers' | ||
}; | ||
|
||
test('isochrone', (t) => { | ||
t.plan(3); | ||
points.forEach(point => | ||
isochrone(point, options) | ||
.then((geojson) => { | ||
const errors = geojsonhint.hint(geojson); | ||
if (errors.length > 0) { | ||
errors.forEach(error => t.comment(error.message)); | ||
t.fail('Invalid GeoJSON'); | ||
} else { | ||
t.pass('Valid GeoJSON'); | ||
} | ||
}) | ||
.catch(error => t.error(error, 'No error')) | ||
); | ||
}); |
Oops, something went wrong.