UNPKG

overpass-frontend

Version:

A JavaScript (NodeJS/Browser) library to easily access data from OpenStreetMap via Overpass API or from an OSM File. The objects can directly be used with LeafletJS or exported to GeoJSON. Data will be cached in the browser memory.

144 lines (118 loc) 4.23 kB
/* global L:false */ const OverpassObject = require('./OverpassObject') const BoundingBox = require('boundingbox') const OverpassFrontend = require('./defines') const turf = require('./turf') /** * A node * @extends OverpassObject * @property {string} id ID of this object, starting with 'n'. * @property {number} osm_id Numeric id. * @property {string} type Type: 'node' * @property {object} tags OpenStreetMap tags. * @property {object} meta OpenStreetMap meta information. * @property {Point} geometry of the object * @property {object} data Data as loaded from Overpass API. * @property {bit_array} properties Which information about this object is known? * @property {object[]} memberOf List of ways and relations where this object is member of. * @property {string} memberOf.id ID of the way or relation where this way is member of. * @property {string} memberOf.role Role of this object in the relation. * @property {number} memberOf.sequence This object is the nth member in the way resp. relation. * @property {BoundingBox} bounds Bounding box of this object. * @property {Point} center Centroid of the bounding box. */ class OverpassNode extends OverpassObject { GeoJSON () { const result = { type: 'Feature', id: this.type + '/' + this.osm_id, properties: this.GeoJSONProperties() } if (this.geometry) { result.geometry = { type: 'Point', coordinates: [this.geometry.lon, this.geometry.lat] } } return result } exportOSMXML (options, document, callback) { super.exportOSMXML(options, document, (err, result) => { if (err) { return callback(err) } if (!result) { // already included return callback(null) } result.setAttribute('lat', this.geometry.lat) result.setAttribute('lon', this.geometry.lon) callback(null, result) } ) } exportOSMJSON (conf, elements, callback) { super.exportOSMJSON(conf, elements, (err, result) => { if (err) { return callback(err) } if (!result) { // already included return callback(null) } result.lat = this.geometry.lat result.lon = this.geometry.lon callback(null, result) } ) } updateData (data, options) { super.updateData(data, options) if (data.lat) { this.geometry = { lat: data.lat, lon: data.lon } this.bounds = new BoundingBox(data) this.center = this.bounds.getCenter() this.properties = this.properties | OverpassFrontend.GEOM | OverpassFrontend.BBOX | OverpassFrontend.CENTER } this.properties |= OverpassFrontend.MEMBERS // node does not have members, so it always known all of them } /** * return a leaflet feature for this object * @param {object} [options] options Options will be passed to the leaflet function * @param {string} [options.nodeFeature='CircleMarker'] Which type of object should be returned: 'Marker' (L.marker), 'Circle' (L.circle) or 'CircleMarker' (L.circleMarker). * @param {number[]} [options.shiftWorld=[0, 0]] Shift western (negative) longitudes by shiftWorld[0], eastern (positive) longitudes by shiftWorld[1] (e.g. by 360, 0 to show objects around lon=180) * @return {L.layer} */ leafletFeature (options = {}) { if (!this.geometry) { return null } if (!('shiftWorld' in options)) { options.shiftWorld = [0, 0] } const geom = { lat: this.geometry.lat, lon: this.geometry.lon + options.shiftWorld[this.geometry.lon < 0 ? 0 : 1] } switch ('nodeFeature' in options ? options.nodeFeature : null) { case 'Marker': return L.marker(geom, options) case 'Circle': return L.circle(geom, options.radius, options) case 'CircleMarker': default: return L.circleMarker(geom, options) } } intersects (bbox) { if (!this.bounds) { return 1 } if (!bbox.intersects) { // GeoJSON detected const r = turf.booleanIntersects(this.GeoJSON(), bbox) return r ? 2 : 0 } return bbox.intersects(this.bounds) ? 2 : 0 } } module.exports = OverpassNode