diff --git a/helper/geojsonify.js b/helper/geojsonify.js index 28fa6272..8910767d 100644 --- a/helper/geojsonify.js +++ b/helper/geojsonify.js @@ -29,7 +29,8 @@ var DETAILS_PROPS = [ 'locality_id', 'locality_a', 'neighbourhood', - 'neighbourhood_id' + 'neighbourhood_id', + 'bounding_box' ]; @@ -50,11 +51,16 @@ function geojsonifyPlaces( docs ){ return !!doc; }); + // get all the bounding_box corners as well as single points + // to be used for computing the overall bounding_box for the FeatureCollection + var extentPoints = extractExtentPoints(geodata); + // convert to geojson - var geojson = GeoJSON.parse( geodata, { Point: ['lat', 'lng'] }); + var geojson = GeoJSON.parse( geodata, { Point: ['lat', 'lng'] }); + var geojsonExtentPoints = GeoJSON.parse( extentPoints, { Point: ['lat', 'lng'] }); // bounding box calculations - computeBBox(geojson); + computeBBox(geojson, geojsonExtentPoints); return geojson; } @@ -105,23 +111,56 @@ function addLabel(src, dst) { dst.label = labelGenerator(dst); } + +/** + * Collect all points from the geodata. + * If an item is a single point, just use that. + * If an item has a bounding box, add two corners of the box as individual points. + * + * @param {Array} geodata + * @returns {Array} + */ +function extractExtentPoints(geodata) { + var extentPoints = []; + geodata.forEach(function (place) { + if (place.bounding_box) { + extentPoints.push({ + lng: place.bounding_box.min_lon, + lat: place.bounding_box.min_lat + }); + extentPoints.push({ + lng: place.bounding_box.max_lon, + lat: place.bounding_box.max_lat + }); + } + else { + extentPoints.push({ + lng: place.lng, + lat: place.lat + }); + } + }); + + return extentPoints; +} + /** * Compute bbox that encompasses all features in the result set. * Set bbox property on the geojson object. * * @param {object} geojson */ -function computeBBox(geojson) { +function computeBBox(geojson, geojsonExtentPoints) { // @note: extent() sometimes throws Errors for unusual data // eg: https://github.com/pelias/pelias/issues/84 try { - var bbox = extent( geojson ); + var bbox = extent( geojsonExtentPoints ); if( !!bbox ){ geojson.bbox = bbox; } } catch( e ){ console.error( 'bbox error', e.message, e.stack ); - console.error( 'geojson', JSON.stringify( geojson, null, 2 ) ); + console.error( 'geojson', JSON.stringify( geojsonExtentPoints, null, 2 ) ); } } diff --git a/test/unit/helper/geojsonify.js b/test/unit/helper/geojsonify.js index 3ab4d975..0aa6b39c 100644 --- a/test/unit/helper/geojsonify.js +++ b/test/unit/helper/geojsonify.js @@ -207,6 +207,131 @@ module.exports.tests.search = function(test, common) { t.deepEqual(json, expected, 'all docs mapped'); t.end(); }); + + test('filtering out empty items', function (t) { + var input = [ + { + 'bounding_box': { + 'min_lat': 40.6514712164, + 'max_lat': 40.6737320588, + 'min_lon': -73.8967895508, + 'max_lon': -73.8665771484 + }, + 'locality': [ + 'New York' + ], + 'source': 'whosonfirst', + 'layer': 'neighbourhood', + 'population': 173198, + 'popularity': 495, + 'center_point': { + 'lon': -73.881319, + 'lat': 40.663303 + }, + 'name': { + 'default': 'East New York' + }, + 'source_id': '85816607', + 'category': [], + '_id': '85816607', + '_type': 'neighbourhood', + '_score': 21.434, + 'confidence': 0.888, + 'country': [ + 'United States' + ], + 'country_id': [ + '85633793' + ], + 'country_a': [ + 'USA' + ], + 'region': [ + 'New York' + ], + 'region_id': [ + '85688543' + ], + 'region_a': [ + 'NY' + ], + 'county': [ + 'Kings County' + ], + 'county_id': [ + '102082361' + ], + 'county_a': [ + null + ], + 'localadmin': [ + 'Brooklyn' + ], + 'localadmin_id': [ + '404521211' + ], + 'localadmin_a': [ + null + ], + 'locality_id': [ + '85977539' + ], + 'locality_a': [ + null + ], + 'neighbourhood': [], + 'neighbourhood_id': [] + } + ]; + + var expected = { + 'type': 'FeatureCollection', + 'bbox': [-73.8967895508, 40.6514712164, -73.8665771484, 40.6737320588], + 'features': [ + { + 'type': 'Feature', + 'properties': { + 'id': '85816607', + 'gid': 'whosonfirst:neighbourhood:85816607', + 'layer': 'neighbourhood', + 'source': 'whosonfirst', + 'name': 'East New York', + 'confidence': 0.888, + 'country': 'United States', + 'country_id': '85633793', + 'country_a': 'USA', + 'region': 'New York', + 'region_id': '85688543', + 'region_a': 'NY', + 'county': 'Kings County', + 'county_id': '102082361', + 'localadmin': 'Brooklyn', + 'localadmin_id': '404521211', + 'locality': 'New York', + 'locality_id': '85977539', + 'bounding_box': { + 'min_lat': 40.6514712164, + 'max_lat': 40.6737320588, + 'min_lon': -73.8967895508, + 'max_lon': -73.8665771484 + }, + 'label': 'East New York, Brooklyn, NY, USA' + }, + 'geometry': { + 'type': 'Point', + 'coordinates': [ + -73.881319, + 40.663303 + ] + } + } + ] + }; + + var json = geojsonify.search( input ); + t.deepEqual(json, expected, 'all wanted properties exposed'); + t.end(); + }); }; module.exports.all = function (tape, common) {