tracktracker/src/data/sources/osm.js

147 lines
4.2 KiB
JavaScript

/**
* @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 <https://github.com/drolbr/Overpass-API/issues/92>
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 <https://wiki.osm.org/Overpass_API/Overpass_QL> 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 <https://wiki.osm.org/Key:oneway>
* @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 <https://wiki.osm.org/Tag:railway=railway_crossing>
* @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 <https://wiki.osm.org/Relation:route_master>
* @see <https://wiki.osm.org/Public_transport#Route_Master_relations>
* @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 <https://wiki.openstreetmap.org/wiki/Public_transport#Service_routes>
* @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"
);