diff --git a/lib/default-profile.js b/lib/default-profile.js index 340de25f..57d7eb36 100644 --- a/lib/default-profile.js +++ b/lib/default-profile.js @@ -6,6 +6,7 @@ const parseJourneyLeg = require('../parse/journey-leg') const parseJourney = require('../parse/journey') const parseLine = require('../parse/line') const parseLocation = require('../parse/location') +const parsePolyline = require('../parse/polyline') const parseMovement = require('../parse/movement') const parseNearby = require('../parse/nearby') const parseOperator = require('../parse/operator') @@ -42,6 +43,7 @@ const defaultProfile = { parseLine, parseStationName: id, parseLocation, + parsePolyline, parseMovement, parseNearby, parseOperator, diff --git a/package.json b/package.json index de06f070..d654d719 100644 --- a/package.json +++ b/package.json @@ -32,8 +32,10 @@ "node": ">=6" }, "dependencies": { + "@mapbox/polyline": "^1.0.0", "capture-stack-trace": "^1.0.0", "fetch-ponyfill": "^6.0.0", + "gps-distance": "0.0.4", "lodash": "^4.17.5", "luxon": "^0.5.8", "p-throttle": "^1.1.0", diff --git a/parse/polyline.js b/parse/polyline.js new file mode 100644 index 00000000..5cdcff0c --- /dev/null +++ b/parse/polyline.js @@ -0,0 +1,53 @@ +'use strict' + +const {toGeoJSON} = require('@mapbox/polyline') +const distance = require('gps-distance') + +const createParsePolyline = (locations) => { + // todo: what is p.delta? + // todo: what is p.type? + // todo: what is p.crdEncS? + // todo: what is p.crdEncF? + const parsePolyline = (p) => { + const shape = toGeoJSON(p.crdEncYX) + if (shape.coordinates.length === 0) return null + + const res = shape.coordinates.map(crd => ({ + type: 'Feature', + properties: {}, + geometry: { + type: 'Point', + coordinates: crd + } + })) + + if (Array.isArray(p.ppLocRefL)) { + for (let ref of p.ppLocRefL) { + const p = res[ref.ppIdx] + const loc = locations[ref.locX] + if (p && loc) p.properties = loc + } + + // Often there is one more point right next to each point at a station. + // We filter them here if they are < 5m from each other. + for (let i = 1; i < res.length; i++) { + const p1 = res[i - 1].geometry.coordinates + const p2 = res[i].geometry.coordinates + const d = distance(p1[1], p1[0], p2[1], p2[0]) + if (d >= .005) continue + const l1 = Object.keys(res[i - 1].properties).length + const l2 = Object.keys(res[i].properties).length + if (l1 === 0 && l2 > 0) res.splice(i - 1, 1) + else if (l2 === 0 && l1 > 0) res.splice(i, 1) + } + } + + return { + type: 'FeatureCollection', + features: res + } + } + return parsePolyline +} + +module.exports = createParsePolyline