Skip to content

Commit

Permalink
refactor parser, improve centroid func, add fixture
Browse files Browse the repository at this point in the history
  • Loading branch information
missinglink committed Aug 10, 2016
1 parent 2e3a471 commit cd16e84
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 9 deletions.
44 changes: 44 additions & 0 deletions src/wrap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@

/**
normalize co-ordinates that lie outside of the normal ranges.
longitude wrapping simply requires adding +- 360 to the value until it comes
in to range.
for the latitude values we need to flip the longitude whenever the latitude
crosses a pole.
**/


function wrap( lat, lon ){

var point = { lat: lat, lon: lon };
var quadrant = Math.floor( Math.abs(lat) / 90) % 4;
var pole = ( lat > 0 ) ? 90 : -90;
var offset = lat % 90;

switch( quadrant ){
case 0:
point.lat = offset;
break;
case 1:
point.lat = pole - offset;
point.lon += 180;
break;
case 2:
point.lat = -offset;
point.lon += 180;
break;
case 3:
point.lat = -pole + offset;
break;
}

if( point.lon > 180 || point.lon <= -180 ){
point.lon -= Math.floor(( point.lon + 180 ) / 360) * 360;
}

return point;
}

module.exports = wrap;
6 changes: 3 additions & 3 deletions stream/centroid.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ var through = require('through2'),

// https://github.com/turf-junkyard/turf-along
// https://github.com/turf-junkyard/turf-line-distance
var UNIT = 'km';
var UNIT = 'kilometers';

function centroid(){
return through.obj( function( geojson, _, next ){
try {

// total distance in km
// total distance in meters
var dist = distance( geojson, UNIT );
geojson.properties.distance = dist;
geojson.properties.distance = (dist * 1000).toFixed(4);

// interpolate middle of path
var point = along( geojson, dist/2, UNIT );
Expand Down
4 changes: 3 additions & 1 deletion stream/decode.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
var split = require('split'),
through = require('through2'),
parser = require('./parser'),
unwrap = require('./unwrap'),
centroid = require('./centroid');

function decode( streamIn, streamOut ){
return streamIn
.pipe( split() )
.pipe( parser() )
.pipe( parser( 6 ) )
.pipe( unwrap() )
.pipe( centroid() )
.pipe( through.obj( function( obj, _, next ){
next( null, JSON.stringify( obj, null, 2 ) );
Expand Down
38 changes: 33 additions & 5 deletions stream/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,49 @@
var through = require('through2'),
polyline = require('polyline');

function parser(){
/**
note: you must select the same 'precision' value that was used when encoding
the polyline.
valhalla: 6
osrm: 5
parser expects data to be:
- newline terminated with \n
- column delimited with \0
- in the format: {encoded_polyline}\0{name1}\0{name2}...\n
**/
function parser( precision ){
return through.obj( function( row, _, next ){
var cols = row.split('\0');
try {
var names = cols.slice(1);
if( names.length ){
var geojson = polyline.toGeoJSON(cols[0]);
geojson.properties = { name: names[0] };
// must contain a polyline and at least one name
if( cols.length > 1 ){

// decode polyline
var geojson = polyline.toGeoJSON(cols[0], precision);

// select name
geojson.properties = { name: selectName(cols.slice(1)) };

this.push( geojson );
}
} catch( e ){
console.error( 'polyline parsing error', e );
}

next();
});
}

// each connected road can have one or more names
// we select one name to be the default.
function selectName( names ){
// return the longest name
// @todo: can we improve this logic?
return names.reduce( function( a, b ){
return a.length > b.length ? a : b;
});
}

module.exports = parser;
25 changes: 25 additions & 0 deletions stream/unwrap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

var through = require('through2'),
wrap = require('../src/wrap');

function unwrap(){
return through.obj( function( geojson, _, next ){
try {

// unwrap coordinates which go around the globe
geojson.coordinates = geojson.coordinates.map( function( coord ){
var w = wrap( coord[1], coord[0] );
return [ w.lon, w.lat ];
});

this.push( geojson );

} catch( e ){
console.error( 'polyline unwrap error', e );
}

next();
});
}

module.exports = unwrap;
Binary file added test/fixture/example.raw
Binary file not shown.

0 comments on commit cd16e84

Please sign in to comment.