| 
									
										
										
										
											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" | 
					
						
							|  |  |  | ); |