/** * @class * Create osmOverpassAPI service instance */ class OverpassAPI{ /** * @param {Object} $http angular $http service * @param {Object} $q angular $q service * @param {Object} options */ constructor($http, $q, options) { this.url = options.url; this.$http = $http; this.$q = $q; } /** * @param {Object/String} query * http://wiki.openstreetmap.org/wiki/FR:Overpass_API * @return {Promise} $http.get */ overpass(query) { var url = this.url; var deferred = this.$q.defer(); var headers = { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' }; this.$http.post( url, 'data=' + encodeURIComponent(query), {headers: headers} ).then(function (data) { deferred.resolve(data.data); }, function (data) { deferred.reject(data); }); return deferred.promise; } /** * http://wiki.openstreetmap.org/wiki/FR:Overpass_API/Overpass_QL#By_area_.28area.29 By convention the area id can be calculated from an existing OSM way by adding 2400000000 to its OSM id, or in case of a relation by adding 3600000000 respectively. Note that area creation is subject to some extraction rules, i.e. not all ways/relations have an area counterpart (notably those that are tagged with area=no, and most multipolygons and that don't have a defined name=* will not be part of areas). * @param {String} type 'r'/'relation' or 'w'/'way' * @param {String/Number} osmId the id of the element * @return {Number} the area id */ getAreaId(type, osmId) { var id; if (typeof osmId === 'string') { id = parseInt(osmId, 10); } else { id = osmId; } if (type === 'r' || type === 'relation') { return 3600000000 + id; } else if (type === 'w' || type === 'way') { return 2400000000 + id; } } overpassToGeoJSON(query, filter) { var deferred = this.$q.defer(); var features = []; var relations = []; var result = { type: 'FeatureCollection', features: features, relations: relations }; if (filter === undefined) { filter = function () {}; } this.overpass(query).then(function (data) { //TODO check if data is XML or JSON, here it's JSON var node, feature, coordinates; var cache = {loaded:false}; function getNodeById (id) { if (!cache.loaded) { var tmp; for (var i = 0; i < data.elements.length; i++) { tmp = data.elements[i]; cache[tmp.id] = tmp; } } return cache[id]; } for (var i = 0; i < data.elements.length; i++) { node = data.elements[i]; if (node.type === 'node') { feature = { type: 'Feature', properties:node.tags, id: node.id, geometry: { type:'Point', coordinates: [node.lon, node.lat] } }; if (!filter(feature)) { features.push(feature); } } else if (node.type === 'way') { coordinates = []; feature = { type: 'Feature', properties:node.tags, id: node.id, geometry: { type:'LineString', coordinates: coordinates } }; for (var j = 0; j < node.nodes.length; j++) { coordinates.push([ getNodeById(node.nodes[j]).lon, getNodeById(node.nodes[j]).lat ]); } if (!filter(feature)) { features.push(feature); } } else if (node.type === 'relation') { result.relations.push({ ref: node.id, tags: node.tags, type: 'relation', members: node.members }); } } deferred.resolve(result); }, function (error) { deferred.reject(error); }); return deferred.promise; } } export default OverpassAPI;