2020-07-17 10:13:25 +00:00
|
|
|
/**
|
2020-07-25 16:05:43 +00:00
|
|
|
* @fileoverview
|
2020-07-17 10:13:25 +00:00
|
|
|
*
|
|
|
|
* Interface with the OpenStreetMap collaborative mapping database.
|
|
|
|
*/
|
|
|
|
|
2021-05-11 19:39:24 +00:00
|
|
|
import axios from "axios";
|
|
|
|
import { isObject } from "../../util.js";
|
2020-07-17 10:13:25 +00:00
|
|
|
|
2022-07-05 02:40:29 +00:00
|
|
|
/** 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}`);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-07-17 10:13:25 +00:00
|
|
|
/**
|
|
|
|
* Submit a query to an Overpass endpoint.
|
|
|
|
*
|
2022-07-05 02:40:29 +00:00
|
|
|
* @see <https://wiki.osm.org/Overpass_API/Overpass_QL> for more
|
2020-07-17 10:13:25 +00:00
|
|
|
* information on the Overpass Query Language (Overpass QL).
|
|
|
|
* @async
|
2020-07-25 16:05:43 +00:00
|
|
|
* @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.
|
2020-07-17 10:13:25 +00:00
|
|
|
*/
|
2021-05-11 19:39:24 +00:00
|
|
|
export const runQuery = (
|
2020-07-17 10:13:25 +00:00
|
|
|
query,
|
2020-07-25 16:05:43 +00:00
|
|
|
endpoint = "https://lz4.overpass-api.de/api/interpreter"
|
2022-07-05 02:40:29 +00:00
|
|
|
) => {
|
|
|
|
console.log("Running query:", query);
|
|
|
|
return axios.post(endpoint, `data=${query}`)
|
|
|
|
.then(res => res.data);
|
|
|
|
};
|
2020-07-17 10:13:25 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a link to view a node.
|
2020-07-25 16:05:43 +00:00
|
|
|
* @param {string|number} id Identifier for the node to view.
|
|
|
|
* @returns {string} Link to view this node on the OSM website.
|
2020-07-17 10:13:25 +00:00
|
|
|
*/
|
2021-05-11 19:39:24 +00:00
|
|
|
export const viewNode = id => `https://www.osm.org/node/${id}`;
|
2020-07-17 10:13:25 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Determine if an OSM way is one-way or not.
|
|
|
|
*
|
2022-07-05 02:40:29 +00:00
|
|
|
* @see <https://wiki.osm.org/Key:oneway>
|
2020-07-25 16:05:43 +00:00
|
|
|
* @param {Object} obj OSM way object.
|
|
|
|
* @returns {boolean} Whether the way is one-way.
|
2020-07-17 10:13:25 +00:00
|
|
|
*/
|
2021-05-11 19:39:24 +00:00
|
|
|
export const isOneWay = obj => (
|
2020-07-25 16:05:43 +00:00
|
|
|
obj.type === "way" &&
|
|
|
|
isObject(obj.tags) &&
|
|
|
|
(obj.tags.oneway === "yes" || obj.tags.junction === "roundabout" ||
|
|
|
|
obj.tags.highway === "motorway")
|
2020-07-17 21:48:32 +00:00
|
|
|
);
|
2020-07-17 10:13:25 +00:00
|
|
|
|
2021-05-22 22:45:09 +00:00
|
|
|
/**
|
|
|
|
* Determine if a node is a railway crossing or not.
|
|
|
|
*
|
2022-07-05 02:40:29 +00:00
|
|
|
* @see <https://wiki.osm.org/Tag:railway=railway_crossing>
|
2021-05-22 22:45:09 +00:00
|
|
|
* @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")
|
|
|
|
);
|
|
|
|
|
2020-07-17 10:13:25 +00:00
|
|
|
/**
|
|
|
|
* Determine if an OSM object is a public transport line (route master).
|
|
|
|
*
|
2022-07-05 02:40:29 +00:00
|
|
|
* @see <https://wiki.osm.org/Relation:route_master>
|
|
|
|
* @see <https://wiki.osm.org/Public_transport#Route_Master_relations>
|
2020-07-25 16:05:43 +00:00
|
|
|
* @param {Object} obj OSM relation object.
|
|
|
|
* @returns {boolean} Whether the relation is a public transport line.
|
2020-07-17 10:13:25 +00:00
|
|
|
*/
|
2021-05-11 19:39:24 +00:00
|
|
|
export const isTransportLine = obj => (
|
2020-07-25 16:05:43 +00:00
|
|
|
obj.type === "relation" &&
|
|
|
|
isObject(obj.tags) &&
|
|
|
|
obj.tags.type === "route_master"
|
2020-07-17 21:48:32 +00:00
|
|
|
);
|
2022-07-05 02:40:29 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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"
|
|
|
|
);
|