Skip to content

Instantly share code, notes, and snippets.

@MateoV
Created August 4, 2015 19:18
Show Gist options
  • Save MateoV/619faf5fe794466f3912 to your computer and use it in GitHub Desktop.
Save MateoV/619faf5fe794466f3912 to your computer and use it in GitHub Desktop.
Use Tile Reduce and OSM QA Tiles to find the difference between OSM roads and Tiger roads
var turf = require('turf'),
flatten = require('geojson-flatten'),
normalize = require('geojson-normalize'),
tilebelt = require('tilebelt');
module.exports = function(tileLayers, tile, done) {
// concat feature classes and normalize data
var tigerRoads = normalize(tileLayers.tiger.tiger20062014);
var osmData = normalize(tileLayers.osmdata.migeojson);
// filter out roads that are shorter than 30m and have no name
tigerRoads.features.forEach(function(road, i) {
if (filter(road)) tigerRoads.features.splice(i,1);
});
// clip features to tile
osmData = clip(osmData, tile);
tigerRoads = clip(tigerRoads, tile);
osmData = normalize(flatten(osmData));
tigerRoads = normalize(flatten(tigerRoads));
// buffer streets
var streetBuffers = turf.featurecollection([]);
streetBuffers.features = osmData.features.map(function(f){
if (f.properties.highway) {
return turf.buffer(road, 20, 'meters').features[0];
}
});
streetBuffers = normalize(turf.merge(streetBuffers));
// erase street buffer from tiger lines
var tigerDeltas = turf.featurecollection([]);
if (tigerRoads && streetBuffers) {
tigerRoads.features.forEach(function(tigerRoad){
streetBuffers.features.forEach(function(streetsRoad){
var roadDiff = turf.erase(tigerRoad, streetsRoad);
if(roadDiff && !filter(roadDiff)) tigerDeltas.features.push(roadDiff);
});
});
}
done(null, tigerDeltas);
};
function clip(lines, tile) {
lines.features = lines.features.map(function(line){
try {
var clipped = turf.intersect(line, turf.polygon(tilebelt.tileToGeoJSON(tile).coordinates));
return clipped;
} catch(e){
return;
}
});
lines.features = lines.features.filter(function(line){
if(line) return true;
});
lines.features = lines.features.filter(function(line){
if(line.geometry.type === 'LineString' || line.geometry.type === 'MultiLineString') return true;
});
return lines;
}
function filter(road) {
var length = turf.lineDistance(road, 'kilometers');
if (length < 0.03 || road.properties.fullname == '') {
return true;
} else {
return false;
}
}
var TileReduce = require('tile-reduce');
var turf = require('turf');
var bbox = [4293,6022,14];
//var area = JSON.parse(argv.area);
var opts = {
zoom: 15,
tileLayers: [
{
name: 'osmdata',
url: __dirname + '/latest.planet.mbtiles',
layers: ['osm']
},
{
name: 'tiger',
url: __dirname + '/tiger.mbtiles',
layers: ['tiger']
}
],
map: __dirname + '/difference.js'
};
var tilereduce = TileReduce(bbox, opts);
var diff = turf.featurecollection([]);
tilereduce.on('reduce', function(result){
diff.features = diff.features.concat(result.features);
});
tilereduce.on('end', function(error){
console.log(JSON.stringify(diff));
});
tilereduce.on('error', function(err){
throw err;
});
tilereduce.run();
@caioiglesias
Copy link

Shouldn't you do a reverse for loop instead of the forEach loop on this splicing ?

// filter out roads that are shorter than 30m and have no name
for (var i = tigerRoads.features.length - 1; i >= 0; i -= 1) {
    if (filter(road)) tigerRoads.features.splice(i,1);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment