/** * @fileoverview * * Interface with the OpenStreetMap collaborative mapping database. */ import axios from "axios"; import { isObject } from "../../util.js"; /** Replace a value for use in an Overpass query. */ export const escape = value => value.replace("'", "\\'").replace('"', '\\"').replace("\\", "\\\\"); /** * Transform a set of tag queries into an Overpass set of filters. * * @param {Object} tags A set of tag queries. * @return {string} Corresponding Overpass filter. */ export const buildFilter = tags => Object.entries(tags).filter( ([key, value]) => { return value !== undefined && value !== null; } ).map( ([key, value]) => { if (value === true) { return `[${key}]`; } if (value === false) { return `[!${key}]`; } if (value === "") { // See return `[${key}~"^$"]`; } return `[${key}="${escape(value)}"]` } ).join(""); /** * Get the appropriate tag query for matching ways that can be used by a given * public transport vehicle. * @param {string} type Type of public transport vehicle. * @return {Object} Set of tag queries. */ export const vehicleWayFilter = type => { switch (type) { case "bus": return {highway: true}; case "train": case "subway": case "light_rail": case "tram": return {railway: type}; default: throw new Error(`Unknown vehicle type: ${type}`); } }; /** * Submit a query to an Overpass endpoint. * * @see for more * information on the Overpass Query Language (Overpass QL). * @async * @param {string} query Query to send. * @param {string} [endpoint] Overpass endpoint to use. * @returns {string|Object} Results returned by the endpoint. If JSON output * is requested in the query, the result will automatically be parsed into * a JS object. */ export const runQuery = ( query, endpoint = "https://lz4.overpass-api.de/api/interpreter" ) => { console.log("Running query:", query); return axios.post(endpoint, `data=${query}`) .then(res => res.data); }; /** * Create a link to view a node. * @param {string|number} id Identifier for the node to view. * @returns {string} Link to view this node on the OSM website. */ export const viewNode = id => `https://www.osm.org/node/${id}`; /** * Determine if an OSM way is one-way or not. * * @see * @param {Object} obj OSM way object. * @returns {boolean} Whether the way is one-way. */ export const isOneWay = obj => ( obj.type === "way" && isObject(obj.tags) && (obj.tags.oneway === "yes" || obj.tags.junction === "roundabout" || obj.tags.highway === "motorway") ); /** * Determine if a node is a railway crossing or not. * * @see * @param {Object} obj OSM node object. * @return {boolean} Whether the node is a railway crossing. */ export const isRailwayCrossing = obj => ( obj.type === "node" && isObject(obj.tags) && (obj.tags.railway === "railway_crossing") ); /** * Determine if an OSM object is a public transport line (route master). * * @see * @see * @param {Object} obj OSM relation object. * @returns {boolean} Whether the relation is a public transport line. */ export const isTransportLine = obj => ( obj.type === "relation" && isObject(obj.tags) && obj.tags.type === "route_master" ); /** * Determine if a public transport route member has a valid role for * the initial segment of stops and platforms according to PTv2. * * @see * @param {string} role Role to check. * @returns {boolean} Whether the role is valid. */ export const isInitialRouteRole = role => ( role === "stop" || role === "stop_entry_only" || role === "stop_exit_only" || role === "platform" || role === "platform_entry_only" || role === "platform_exit_only" );