diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d514b13b08..cc6fe3a8df 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -53,3 +53,10 @@ To do this: Alternatively, if you don't have any unmerged changes, you can remove your local copy and clone `pietervdvn/MapComplete` again to start fresh. + +What not to contribute +---------------------- + +I'm currently _not_ accepting files for integration with some editor. There are hundreds of editors out there, if every single one of them needs a file in the repo, this ends up as a mess. +Furthermore, MapComplete doesn't want to encourage or discourage some editors. +At last, these files are hard to maintain and are hard to detect if they have fallen out of use. diff --git a/Customizations/AllKnownLayouts.ts b/Customizations/AllKnownLayouts.ts index 2b3ce5c651..47fbe45eed 100644 --- a/Customizations/AllKnownLayouts.ts +++ b/Customizations/AllKnownLayouts.ts @@ -37,12 +37,41 @@ export class AllKnownLayouts { return allLayers } - public static GenOverviewsForSingleLayer(callback: (layer: LayerConfig, element: BaseUIElement) => void): void { + /** + * Generates documentation for the layers. + * Inline layers are included (if the theme is public) + * @param callback + * @constructor + */ + public static GenOverviewsForSingleLayer(callback: (layer: LayerConfig, element: BaseUIElement, inlineSource: string) => void): void { const allLayers: LayerConfig[] = Array.from(AllKnownLayouts.sharedLayers.values()) .filter(layer => Constants.priviliged_layers.indexOf(layer.id) < 0) - const builtinLayerIds: Set = new Set() allLayers.forEach(l => builtinLayerIds.add(l.id)) + const inlineLayers = new Map(); + + for (const layout of Array.from(AllKnownLayouts.allKnownLayouts.values())) { + if (layout.hideFromOverview) { + continue + } + + for (const layer of layout.layers) { + + if (Constants.priviliged_layers.indexOf(layer.id) >= 0) { + continue + } + if (builtinLayerIds.has(layer.id)) { + continue + } + if(layer.source.geojsonSource !== undefined){ + // Not an OSM-source + continue + } + allLayers.push(layer) + builtinLayerIds.add(layer.id) + inlineLayers.set(layer.id, layout.id) + } + } const themesPerLayer = new Map() @@ -52,6 +81,7 @@ export class AllKnownLayouts { } for (const layer of layout.layers) { if (!builtinLayerIds.has(layer.id)) { + // This is an inline layer continue } if (!themesPerLayer.has(layer.id)) { @@ -79,10 +109,14 @@ export class AllKnownLayouts { allLayers.forEach((layer) => { const element = layer.GenerateDocumentation(themesPerLayer.get(layer.id), layerIsNeededBy, DependencyCalculator.getLayerDependencies(layer)) - callback(layer, element) + callback(layer, element, inlineLayers.get(layer.id)) }) } + /** + * Generates the documentation for the layers overview page + * @constructor + */ public static GenLayerOverviewText(): BaseUIElement { for (const id of Constants.priviliged_layers) { if (!AllKnownLayouts.sharedLayers.has(id)) { @@ -171,7 +205,7 @@ export class AllKnownLayouts { private static AllLayouts(): Map { const dict: Map = new Map(); for (const layoutConfigJson of known_themes.themes) { - const layout = new LayoutConfig( layoutConfigJson, true) + const layout = new LayoutConfig(layoutConfigJson, true) dict.set(layout.id, layout) for (let i = 0; i < layout.layers.length; i++) { let layer = layout.layers[i]; diff --git a/Docs/BuiltinIndex.md b/Docs/BuiltinIndex.md index 45660d4cbc..fce8d62d3f 100644 --- a/Docs/BuiltinIndex.md +++ b/Docs/BuiltinIndex.md @@ -110,6 +110,7 @@ - food - nature_reserve - observation_tower + - playground - recycling @@ -155,6 +156,7 @@ - bicycle_library - bicycle_rental + - bike_shop - bike_themed_object - cafe_pub - food diff --git a/Docs/BuiltinLayers.md b/Docs/BuiltinLayers.md index 9fdb5cd435..2d7dc9a08c 100644 --- a/Docs/BuiltinLayers.md +++ b/Docs/BuiltinLayers.md @@ -101,13 +101,12 @@ Meta layer showing the current location of the user. Add this to your theme and + - This layer is shown at zoomlevel **0** and higher - **This layer is included automatically in every theme. This layer might contain no points** - This layer cannot be toggled in the filter view. If you import this layer in your theme, override `title` to make this toggleable. - Not visible in the layer selection by default. If you want to make this layer toggable, override `name` -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/gps_location/gps_location.json) - Basic tags for this layer @@ -145,14 +144,13 @@ Meta layer which contains the previous locations of the user as single points. T + - This layer is shown at zoomlevel **0** and higher - **This layer is included automatically in every theme. This layer might contain no points** - This layer cannot be toggled in the filter view. If you import this layer in your theme, override `title` to make this toggleable. - Not visible in the layer selection by default. If you want to make this layer toggable, override `name` - Not rendered on the map by default. If you want to rendering this on the map, override `mapRenderings` -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/gps_location_history/gps_location_history.json) - Basic tags for this layer @@ -190,13 +188,12 @@ Meta layer showing the home location of the user. The home location can be set i + - This layer is shown at zoomlevel **0** and higher - **This layer is included automatically in every theme. This layer might contain no points** - This layer cannot be toggled in the filter view. If you import this layer in your theme, override `title` to make this toggleable. - Not visible in the layer selection by default. If you want to make this layer toggable, override `name` -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/home_location/home_location.json) - Basic tags for this layer @@ -234,13 +231,12 @@ Meta layer showing the previous locations of the user as single line. Add this t + - This layer is shown at zoomlevel **0** and higher - **This layer is included automatically in every theme. This layer might contain no points** - This layer is not visible by default and must be enabled in the filter by the user. - Not rendered on the map by default. If you want to rendering this on the map, override `mapRenderings` -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/gps_track/gps_track.json) - Basic tags for this layer @@ -328,11 +324,10 @@ This is a priviliged meta_layer which exports _every_ point in OSM. This only wo + - This layer is shown at zoomlevel **18** and higher - Not rendered on the map by default. If you want to rendering this on the map, override `mapRenderings` -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/type_node/type_node.json) - Basic tags for this layer @@ -370,11 +365,10 @@ This layer shows notes on OpenStreetMap. Having this layer in your theme will tr + - This layer is shown at zoomlevel **10** and higher - This layer is loaded from an external source, namely `https://api.openstreetmap.org/api/0.6/notes.json?limit=10000&closed=7&bbox={x_min},{y_min},{x_max},{y_max}` -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/note/note.json) - Basic tags for this layer @@ -462,11 +456,10 @@ Layer used in the importHelper + - This layer is shown at zoomlevel **0** and higher - Not visible in the layer selection by default. If you want to make this layer toggable, override `name` -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/import_candidate/import_candidate.json) - Basic tags for this layer @@ -514,11 +507,10 @@ If the import-button moves OSM points, the imported way points or conflates, a p + - This layer is shown at zoomlevel **1** and higher - This layer can **not** be included in a theme. It is solely used by [special renderings](SpecialRenderings.md) showing a minimap with custom data. -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/conflation/conflation.json) - Basic tags for this layer @@ -556,11 +548,10 @@ Special meta-style which will show one single line, either on the left or on the + - This layer is shown at zoomlevel **0** and higher - This layer can **not** be included in a theme. It is solely used by [special renderings](SpecialRenderings.md) showing a minimap with custom data. -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/left_right_style/left_right_style.json) - Basic tags for this layer @@ -598,11 +589,10 @@ Layer rendering the little scissors for the minimap in the 'splitRoadWizard' + - This layer is shown at zoomlevel **1** and higher - This layer can **not** be included in a theme. It is solely used by [special renderings](SpecialRenderings.md) showing a minimap with custom data. -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/split_point/split_point.json) - Basic tags for this layer @@ -642,11 +632,10 @@ The icon on the button is the default icon of the layer, but can be customized b + - This layer is shown at zoomlevel **0** and higher - This layer can **not** be included in a theme. It is solely used by [special renderings](SpecialRenderings.md) showing a minimap with custom data. -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/current_view/current_view.json) - Basic tags for this layer @@ -684,11 +673,10 @@ The default rendering for a locationInput which snaps onto another object + - This layer is shown at zoomlevel **0** and higher - This layer can **not** be included in a theme. It is solely used by [special renderings](SpecialRenderings.md) showing a minimap with custom data. -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/matchpoint/matchpoint.json) - Basic tags for this layer diff --git a/Docs/Layers/address.md b/Docs/Layers/address.md index 8942bbdb28..92e43ca079 100644 --- a/Docs/Layers/address.md +++ b/Docs/Layers/address.md @@ -12,20 +12,9 @@ Addresses -## Table of contents - -1. [address](#address) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [housenumber](#housenumber) - + [street](#street) - + [fixme](#fixme) - - - + - This layer is shown at zoomlevel **18** and higher - This layer will automatically load [named_streets](./named_streets.md) into the layout as it depends on it: A calculated tag loads features from this layer (calculatedTag[0] which calculates the value for _closest_3_street_names) @@ -40,8 +29,6 @@ Addresses - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/address/address.json) - Basic tags for this layer diff --git a/Docs/Layers/all_streets.md b/Docs/Layers/all_streets.md index b71a3a4e4f..b914abf36b 100644 --- a/Docs/Layers/all_streets.md +++ b/Docs/Layers/all_streets.md @@ -1,62 +1,124 @@ -all_streets + + + all_streets ============= -## Table of contents - -1. [all_streets](#all_streets) - * [Themes using this layer](#themes-using-this-layer) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [lit](#lit) -- Not rendered on the map by default. If you want to rendering this on the map, override `mapRenderings` + -#### Themes using this layer - -- [cyclestreets](https://mapcomplete.osm.be/cyclestreets) -- [street_lighting](https://mapcomplete.osm.be/street_lighting) - -[Go to the source code](../assets/layers/all_streets/all_streets.json) +Layer to mark any street as cyclestreet -Basic tags for this layer + + + + - This layer is shown at zoomlevel **18** and higher + + + + +#### Themes using this layer + + + + + + - [cyclestreets](https://mapcomplete.osm.be/cyclestreets) + - [street_lighting](https://mapcomplete.osm.be/street_lighting) + + + + + Basic tags for this layer --------------------------- Elements must have the all of following tags to be shown on this layer: -- highway!~^$ -- service!~^driveway$ -- highway!~^platform$ -Supported attributes + + - highway=residential|highway=tertiary|highway=unclassified + + +[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22highway%22%3D%22residential%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22tertiary%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22unclassified%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) + + + + Supported attributes ---------------------- **Warning** This quick overview is incomplete + + attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ -[](https://taginfo.openstreetmap.org/keys/lit#values) [lit](https://wiki.openstreetmap.org/wiki/Key:lit) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:lit%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:lit%3Dno) [24/7](https://wiki.openstreetmap.org/wiki/Tag:lit%3D24/7) +[](https://taginfo.openstreetmap.org/keys/cyclestreet#values) [cyclestreet](https://wiki.openstreetmap.org/wiki/Key:cyclestreet) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:cyclestreet%3Dyes) [yes](https://wiki.openstreetmap.org/wiki/Tag:cyclestreet%3Dyes) [](https://wiki.openstreetmap.org/wiki/Tag:cyclestreet%3D) [](https://wiki.openstreetmap.org/wiki/Tag:cyclestreet%3D) +[](https://taginfo.openstreetmap.org/keys/cyclestreet:start_date#values) [cyclestreet:start_date](https://wiki.openstreetmap.org/wiki/Key:cyclestreet:start_date) | [date](../SpecialInputElements.md#date) | -### lit -The question is **Is this street lit?** -- **This street is lit** corresponds with lit - =yes -- **This street is not lit** corresponds with - lit=no -- **This street is lit at night** corresponds - with lit - =sunset-sunrise_This option - cannot be chosen as answer_ -- **This street is lit 24/7** corresponds with - lit=24/7 -This document is autogenerated from assets/layers/all_streets/all_streets.json \ No newline at end of file +### images + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### is_cyclestreet + + + +The question is **Is the street {name} a cyclestreet?** + + + + + + - **This street is a cyclestreet (and has a speed limit of 30 km/h)** corresponds with cyclestreet=yes&maxspeed=30&overtaking:motor_vehicle=no + - **This street is a cyclestreet** corresponds with cyclestreet=yes + - **This street will become a cyclstreet soon** corresponds with proposed:cyclestreet=yes + - **This street is not a cyclestreet** corresponds with + + + + +### future_cyclestreet + + + +The question is **When will this street become a cyclestreet?** + +This rendering asks information about the property [cyclestreet:start_date](https://wiki.openstreetmap.org/wiki/Key:cyclestreet:start_date) +This is rendered with `This street will become a cyclestreet at {cyclestreet:start_date}` + + + +### questions + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### minimap + + + +_This tagrendering has no question and is thus read-only_ + + + +This document is autogenerated from [assets/themes/cyclestreets/cyclestreets.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/cyclestreets/cyclestreets.json) \ No newline at end of file diff --git a/Docs/Layers/ambulancestation.md b/Docs/Layers/ambulancestation.md index b758afd5fc..284323f517 100644 --- a/Docs/Layers/ambulancestation.md +++ b/Docs/Layers/ambulancestation.md @@ -12,24 +12,9 @@ An ambulance station is an area for storage of ambulance vehicles, medical equip -## Table of contents - -1. [ambulancestation](#ambulancestation) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [ambulance-name](#ambulance-name) - + [ambulance-street](#ambulance-street) - + [ambulance-place](#ambulance-place) - + [ambulance-agency](#ambulance-agency) - + [ambulance-operator-type](#ambulance-operator-type) - + [images](#images) - - - - + - This layer is shown at zoomlevel **12** and higher @@ -44,8 +29,6 @@ An ambulance station is an area for storage of ambulance vehicles, medical equip - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/ambulancestation/ambulancestation.json) - Basic tags for this layer diff --git a/Docs/Layers/artwork.md b/Docs/Layers/artwork.md index 9912357991..dd57515e31 100644 --- a/Docs/Layers/artwork.md +++ b/Docs/Layers/artwork.md @@ -12,23 +12,9 @@ Diverse pieces of artwork -## Table of contents - -1. [artwork](#artwork) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [artwork-artwork_type](#artwork-artwork_type) - + [artwork-artist_name](#artwork-artist_name) - + [artwork-website](#artwork-website) - + [artwork-wikidata](#artwork-wikidata) - - - - + - This layer is shown at zoomlevel **12** and higher @@ -43,8 +29,6 @@ Diverse pieces of artwork - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/artwork/artwork.json) - Basic tags for this layer diff --git a/Docs/Layers/assen.md b/Docs/Layers/assen.md deleted file mode 100644 index 4e2f170d04..0000000000 --- a/Docs/Layers/assen.md +++ /dev/null @@ -1,38 +0,0 @@ -assen -======= - -## Table of contents - -1. [assen](#assen) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [all_tags](#all_tags) - - -- This layer is loaded from an external source, namely `https://robinlinde.github.io/tiles/assen_street_lighting/{z}/{x}/{y}.json` -- This layer will automatically load [street_lamps](./street_lamps.md) into the layout as it depends on it: A - calculated tag loads features from this layer (calculatedTag[0] which calculates the value for _ - closest_osm_street_lamp) - -[Go to the source code](../assets/layers/assen/assen.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- Lichtmastnummer~^..*$ - -Supported attributes ----------------------- - -### all_tags - -_This tagrendering has no question and is thus read-only_ - -This document is autogenerated from assets/layers/assen/assen.json \ No newline at end of file diff --git a/Docs/Layers/barrier.md b/Docs/Layers/barrier.md index a9d7c930ab..d5e9a8431a 100644 --- a/Docs/Layers/barrier.md +++ b/Docs/Layers/barrier.md @@ -12,25 +12,9 @@ Obstacles while cycling, such as bollards and cycle barriers -## Table of contents - -1. [barrier](#barrier) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [bicycle=yes/no](#bicycle=yesno) - + [barrier_type](#barrier_type) - + [Bollard type](#bollard-type) - + [Cycle barrier type](#cycle-barrier-type) - + [MaxWidth](#maxwidth) - + [Space between barrier (cyclebarrier)](#space-between-barrier-(cyclebarrier)) - + [Width of opening (cyclebarrier)](#width-of-opening-(cyclebarrier)) - + [Overlap (cyclebarrier)](#overlap-(cyclebarrier)) - - - + - This layer is shown at zoomlevel **17** and higher - This layer will automatically load [cycleways_and_roads](./cycleways_and_roads.md) into the layout as it depends on it: a preset snaps to this layer (presets[0]) - This layer will automatically load [cycleways_and_roads](./cycleways_and_roads.md) into the layout as it depends on it: a preset snaps to this layer (presets[1]) @@ -47,8 +31,6 @@ Obstacles while cycling, such as bollards and cycle barriers - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/barrier/barrier.json) - Basic tags for this layer diff --git a/Docs/Layers/bench.md b/Docs/Layers/bench.md index 5dcaeaaaea..dfc1b7d439 100644 --- a/Docs/Layers/bench.md +++ b/Docs/Layers/bench.md @@ -12,25 +12,9 @@ A bench is a wooden, metal, stone, ... surface where a human can sit. This layer -## Table of contents - -1. [bench](#bench) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [bench-backrest](#bench-backrest) - + [bench-seats](#bench-seats) - + [bench-material](#bench-material) - + [bench-direction](#bench-direction) - + [bench-colour](#bench-colour) - + [bench-survey:date](#bench-surveydate) - - - - + - This layer is shown at zoomlevel **17** and higher @@ -46,8 +30,6 @@ A bench is a wooden, metal, stone, ... surface where a human can sit. This layer - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/bench/bench.json) - Basic tags for this layer diff --git a/Docs/Layers/bench_at_pt.md b/Docs/Layers/bench_at_pt.md index 1adc09b3d1..bb4a6c34a2 100644 --- a/Docs/Layers/bench_at_pt.md +++ b/Docs/Layers/bench_at_pt.md @@ -12,21 +12,9 @@ A layer showing all public-transport-stops which do have a bench -## Table of contents - -1. [bench_at_pt](#bench_at_pt) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [bench_at_pt-name](#bench_at_pt-name) - + [bench_at_pt-bench_type](#bench_at_pt-bench_type) - - - - + - This layer is shown at zoomlevel **14** and higher @@ -41,8 +29,6 @@ A layer showing all public-transport-stops which do have a bench - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/bench_at_pt/bench_at_pt.json) - Basic tags for this layer diff --git a/Docs/Layers/bicycle_library.md b/Docs/Layers/bicycle_library.md index 411ee00db9..01fb44463d 100644 --- a/Docs/Layers/bicycle_library.md +++ b/Docs/Layers/bicycle_library.md @@ -12,27 +12,9 @@ A facility where bicycles can be lent for longer period of times -## Table of contents - -1. [bicycle_library](#bicycle_library) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [bicycle_library-name](#bicycle_library-name) - + [website](#website) - + [phone](#phone) - + [email](#email) - + [opening_hours](#opening_hours) - + [bicycle_library-charge](#bicycle_library-charge) - + [bicycle-library-target-group](#bicycle-library-target-group) - + [description](#description) - - - - + - This layer is shown at zoomlevel **8** and higher @@ -48,8 +30,6 @@ A facility where bicycles can be lent for longer period of times - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/bicycle_library/bicycle_library.json) - Basic tags for this layer diff --git a/Docs/Layers/bicycle_rental.md b/Docs/Layers/bicycle_rental.md index a4da7fd789..d15437c32c 100644 --- a/Docs/Layers/bicycle_rental.md +++ b/Docs/Layers/bicycle_rental.md @@ -12,41 +12,9 @@ Bicycle rental stations -## Table of contents - -1. [bicycle_rental](#bicycle_rental) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [bicycle_rental_type](#bicycle_rental_type) - + [website](#website) - + [email](#email) - + [phone](#phone) - + [opening_hours](#opening_hours) - + [payment-options](#payment-options) - + [payment-options-advanced](#payment-options-advanced) - + [bicycle-types](#bicycle-types) - + [rental-capacity-bicycle-type](#rental-capacity-bicycle-type) - + [questions](#questions) - + [rental-capacity-bicycle-type](#rental-capacity-bicycle-type) - + [questions](#questions) - + [rental-capacity-bicycle-type](#rental-capacity-bicycle-type) - + [questions](#questions) - + [rental-capacity-bicycle-type](#rental-capacity-bicycle-type) - + [questions](#questions) - + [rental-capacity-bicycle-type](#rental-capacity-bicycle-type) - + [questions](#questions) - + [rental-capacity-bicycle-type](#rental-capacity-bicycle-type) - + [questions](#questions) - + [rental-capacity-bicycle-type](#rental-capacity-bicycle-type) - + [questions](#questions) - - - - + - This layer is shown at zoomlevel **12** and higher @@ -61,8 +29,6 @@ Bicycle rental stations - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/bicycle_rental/bicycle_rental.json) - Basic tags for this layer @@ -257,20 +223,10 @@ This is rendered with `{rental} is rented here` -The question is **How much [object Object] can be rented here? ** +The question is **How much city bikes can be rented here? ** This rendering asks information about the property [capacity:city_bike](https://wiki.openstreetmap.org/wiki/Key:capacity:city_bike) -This is rendered with `{capacity:city_bike} [object Object] can be rented here` - - - -### questions - - - -_This tagrendering has no question and is thus read-only_ - - +This is rendered with `{capacity:city_bike} city bikes can be rented here` @@ -278,20 +234,10 @@ _This tagrendering has no question and is thus read-only_ -The question is **How much [object Object] can be rented here? ** +The question is **How much electrical bikes can be rented here? ** This rendering asks information about the property [capacity:ebike](https://wiki.openstreetmap.org/wiki/Key:capacity:ebike) -This is rendered with `{capacity:ebike} [object Object] can be rented here` - - - -### questions - - - -_This tagrendering has no question and is thus read-only_ - - +This is rendered with `{capacity:ebike} electrical bikes can be rented here` @@ -299,20 +245,10 @@ _This tagrendering has no question and is thus read-only_ -The question is **How much [object Object] can be rented here? ** +The question is **How much bikes for children can be rented here? ** This rendering asks information about the property [capacity:kid_bike](https://wiki.openstreetmap.org/wiki/Key:capacity:kid_bike) -This is rendered with `{capacity:kid_bike} [object Object] can be rented here` - - - -### questions - - - -_This tagrendering has no question and is thus read-only_ - - +This is rendered with `{capacity:kid_bike} bikes for children can be rented here` @@ -320,20 +256,10 @@ _This tagrendering has no question and is thus read-only_ -The question is **How much [object Object] can be rented here? ** +The question is **How much BMX bikes can be rented here? ** This rendering asks information about the property [capacity:bmx](https://wiki.openstreetmap.org/wiki/Key:capacity:bmx) -This is rendered with `{capacity:bmx} [object Object] can be rented here` - - - -### questions - - - -_This tagrendering has no question and is thus read-only_ - - +This is rendered with `{capacity:bmx} BMX bikes can be rented here` @@ -341,20 +267,10 @@ _This tagrendering has no question and is thus read-only_ -The question is **How much [object Object] can be rented here? ** +The question is **How much mountainbike can be rented here? ** This rendering asks information about the property [capacity:mtb](https://wiki.openstreetmap.org/wiki/Key:capacity:mtb) -This is rendered with `{capacity:mtb} [object Object] can be rented here` - - - -### questions - - - -_This tagrendering has no question and is thus read-only_ - - +This is rendered with `{capacity:mtb} mountainbike can be rented here` @@ -362,20 +278,10 @@ _This tagrendering has no question and is thus read-only_ -The question is **How much [object Object] can be rented here? ** +The question is **How much bicycle panniers can be rented here? ** This rendering asks information about the property [capacity:bicycle_pannier](https://wiki.openstreetmap.org/wiki/Key:capacity:bicycle_pannier) -This is rendered with `{capacity:bicycle_pannier} [object Object] can be rented here` - - - -### questions - - - -_This tagrendering has no question and is thus read-only_ - - +This is rendered with `{capacity:bicycle_pannier} bicycle panniers can be rented here` @@ -383,19 +289,9 @@ _This tagrendering has no question and is thus read-only_ -The question is **How much [object Object] can be rented here? ** +The question is **How much tandem can be rented here? ** This rendering asks information about the property [capacity:tandem_bicycle](https://wiki.openstreetmap.org/wiki/Key:capacity:tandem_bicycle) -This is rendered with `{capacity:tandem_bicycle} [object Object] can be rented here` - - - -### questions - - - -_This tagrendering has no question and is thus read-only_ - - +This is rendered with `{capacity:tandem_bicycle} tandem can be rented here` This document is autogenerated from [assets/layers/bicycle_rental/bicycle_rental.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/bicycle_rental/bicycle_rental.json) \ No newline at end of file diff --git a/Docs/Layers/bicycle_tube_vending_machine.md b/Docs/Layers/bicycle_tube_vending_machine.md index e1763f18ae..ea47507c93 100644 --- a/Docs/Layers/bicycle_tube_vending_machine.md +++ b/Docs/Layers/bicycle_tube_vending_machine.md @@ -12,25 +12,9 @@ A layer showing vending machines for bicycle tubes (either purpose-built bicycle -## Table of contents - -1. [bicycle_tube_vending_machine](#bicycle_tube_vending_machine) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [Still in use?](#still-in-use) - + [bicycle_tube_vending_machine-charge](#bicycle_tube_vending_machine-charge) - + [vending-machine-payment-methods](#vending-machine-payment-methods) - + [bicycle_tube_vending_machine-brand](#bicycle_tube_vending_machine-brand) - + [bicycle_tube_vending_machine-operator](#bicycle_tube_vending_machine-operator) - + [bicycle_tube_vending_maching-other-items](#bicycle_tube_vending_maching-other-items) - - - - + - This layer is shown at zoomlevel **13** and higher @@ -45,8 +29,6 @@ A layer showing vending machines for bicycle tubes (either purpose-built bicycle - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/bicycle_tube_vending_machine/bicycle_tube_vending_machine.json) - Basic tags for this layer diff --git a/Docs/Layers/bike_cafe.md b/Docs/Layers/bike_cafe.md index 2c4f0142f5..c7e07882c5 100644 --- a/Docs/Layers/bike_cafe.md +++ b/Docs/Layers/bike_cafe.md @@ -12,27 +12,9 @@ A bike café is a café geared towards cyclists, for example with services such -## Table of contents - -1. [bike_cafe](#bike_cafe) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [bike_cafe-name](#bike_cafe-name) - + [bike_cafe-bike-pump](#bike_cafe-bike-pump) - + [bike_cafe-repair-tools](#bike_cafe-repair-tools) - + [bike_cafe-repair-service](#bike_cafe-repair-service) - + [bike_cafe-website](#bike_cafe-website) - + [bike_cafe-phone](#bike_cafe-phone) - + [bike_cafe-email](#bike_cafe-email) - + [bike_cafe-opening_hours](#bike_cafe-opening_hours) - - - - + - This layer is shown at zoomlevel **13** and higher @@ -47,8 +29,6 @@ A bike café is a café geared towards cyclists, for example with services such - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/bike_cafe/bike_cafe.json) - Basic tags for this layer diff --git a/Docs/Layers/bike_cleaning.md b/Docs/Layers/bike_cleaning.md index d19a00e772..f1fffea816 100644 --- a/Docs/Layers/bike_cleaning.md +++ b/Docs/Layers/bike_cleaning.md @@ -12,21 +12,9 @@ A layer showing facilities where one can clean their bike -## Table of contents - -1. [bike_cleaning](#bike_cleaning) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [bike_cleaning-service:bicycle:cleaning:charge](#bike_cleaning-servicebicycle:cleaning:charge) - + [bike_cleaning-charge](#bike_cleaning-charge) - - - - + - This layer is shown at zoomlevel **13** and higher @@ -41,8 +29,6 @@ A layer showing facilities where one can clean their bike - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/bike_cleaning/bike_cleaning.json) - Basic tags for this layer diff --git a/Docs/Layers/bike_parking.md b/Docs/Layers/bike_parking.md index 3fa0875ffe..b4bf1c4c38 100644 --- a/Docs/Layers/bike_parking.md +++ b/Docs/Layers/bike_parking.md @@ -12,26 +12,9 @@ A layer showing where you can park your bike -## Table of contents - -1. [bike_parking](#bike_parking) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [Bicycle parking type](#bicycle-parking-type) - + [Underground?](#underground) - + [Is covered?](#is-covered) - + [Capacity](#capacity) - + [Access](#access) - + [Cargo bike spaces?](#cargo-bike-spaces) - + [Cargo bike capacity?](#cargo-bike-capacity) - - - - + - This layer is shown at zoomlevel **17** and higher @@ -46,8 +29,6 @@ A layer showing where you can park your bike - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/bike_parking/bike_parking.json) - Basic tags for this layer diff --git a/Docs/Layers/bike_repair_station.md b/Docs/Layers/bike_repair_station.md index 15279c0d91..69a39283c9 100644 --- a/Docs/Layers/bike_repair_station.md +++ b/Docs/Layers/bike_repair_station.md @@ -12,33 +12,9 @@ A layer showing bicycle pumps and bicycle repair tool stands -## Table of contents - -1. [bike_repair_station](#bike_repair_station) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [bike_repair_station-available-services](#bike_repair_station-available-services) - + [Operational status](#operational-status) - + [bike_repair_station-opening_hours](#bike_repair_station-opening_hours) - + [access](#access) - + [bike_repair_station-operator](#bike_repair_station-operator) - + [bike_repair_station-email](#bike_repair_station-email) - + [bike_repair_station-phone](#bike_repair_station-phone) - + [bike_repair_station-bike-chain-tool](#bike_repair_station-bike-chain-tool) - + [bike_repair_station-bike-stand](#bike_repair_station-bike-stand) - + [Email maintainer](#email-maintainer) - + [bike_repair_station-valves](#bike_repair_station-valves) - + [bike_repair_station-electrical_pump](#bike_repair_station-electrical_pump) - + [bike_repair_station-manometer](#bike_repair_station-manometer) - + [level](#level) - - - - + - This layer is shown at zoomlevel **13** and higher @@ -53,8 +29,6 @@ A layer showing bicycle pumps and bicycle repair tool stands - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/bike_repair_station/bike_repair_station.json) - Basic tags for this layer diff --git a/Docs/Layers/bike_shop.md b/Docs/Layers/bike_shop.md index db81de920a..dc89d8c22d 100644 --- a/Docs/Layers/bike_shop.md +++ b/Docs/Layers/bike_shop.md @@ -12,35 +12,9 @@ A shop specifically selling bicycles or related items -## Table of contents - -1. [bike_shop](#bike_shop) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [bike_shop-is-bicycle_shop](#bike_shop-is-bicycle_shop) - + [bike_shop-name](#bike_shop-name) - + [bike_shop-website](#bike_shop-website) - + [bike_shop-phone](#bike_shop-phone) - + [bike_shop-email](#bike_shop-email) - + [bike_shop-opening_hours](#bike_shop-opening_hours) - + [description](#description) - + [bike_shop-access](#bike_shop-access) - + [bike_repair_sells-bikes](#bike_repair_sells-bikes) - + [bike_repair_repairs-bikes](#bike_repair_repairs-bikes) - + [bike_repair_rents-bikes](#bike_repair_rents-bikes) - + [bike_repair_second-hand-bikes](#bike_repair_second-hand-bikes) - + [bike_repair_bike-pump-service](#bike_repair_bike-pump-service) - + [bike_repair_tools-service](#bike_repair_tools-service) - + [bike_repair_bike-wash](#bike_repair_bike-wash) - + [bike_cleaning-service:bicycle:cleaning:charge](#bike_cleaning-servicebicycle:cleaning:charge) - - - - + - This layer is shown at zoomlevel **13** and higher @@ -55,8 +29,6 @@ A shop specifically selling bicycles or related items - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/bike_shop/bike_shop.json) - Basic tags for this layer @@ -169,14 +141,14 @@ This is rendered with `{email}` -### bike_shop-opening_hours +### opening_hours -The question is **When is this shop opened?** +The question is **What are the opening hours of {title()}?** This rendering asks information about the property [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) -This is rendered with `{opening_hours_table(opening_hours)}` +This is rendered with `

Opening hours

{opening_hours_table(opening_hours)}` @@ -198,7 +170,7 @@ This is rendered with `{description}` _This tagrendering has no question and is thus read-only_ This rendering asks information about the property [access](https://wiki.openstreetmap.org/wiki/Key:access) -This is rendered with `Enkel voor {access}` +This is rendered with `Only accessible to {access}` diff --git a/Docs/Layers/bike_themed_object.md b/Docs/Layers/bike_themed_object.md index 4e7129bac7..2884b5fc07 100644 --- a/Docs/Layers/bike_themed_object.md +++ b/Docs/Layers/bike_themed_object.md @@ -12,24 +12,9 @@ A layer with bike-themed objects but who don't match any other layer -## Table of contents - -1. [bike_themed_object](#bike_themed_object) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [description](#description) - + [website](#website) - + [email](#email) - + [phone](#phone) - + [opening_hours](#opening_hours) - - - - + - This layer is shown at zoomlevel **13** and higher @@ -44,8 +29,6 @@ A layer with bike-themed objects but who don't match any other layer - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/bike_themed_object/bike_themed_object.json) - Basic tags for this layer diff --git a/Docs/Layers/binocular.md b/Docs/Layers/binocular.md index fb06b4b920..743d20f71d 100644 --- a/Docs/Layers/binocular.md +++ b/Docs/Layers/binocular.md @@ -12,21 +12,9 @@ Binoculas -## Table of contents - -1. [binocular](#binocular) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [binocular-charge](#binocular-charge) - + [binocular-direction](#binocular-direction) - - - - + - This layer is shown at zoomlevel **0** and higher @@ -41,8 +29,6 @@ Binoculas - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/binocular/binocular.json) - Basic tags for this layer diff --git a/Docs/Layers/birdhide.md b/Docs/Layers/birdhide.md index 87d99425fe..2152b24486 100644 --- a/Docs/Layers/birdhide.md +++ b/Docs/Layers/birdhide.md @@ -12,22 +12,9 @@ A birdhide -## Table of contents - -1. [birdhide](#birdhide) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [bird-hide-shelter-or-wall](#bird-hide-shelter-or-wall) - + [bird-hide-wheelchair](#bird-hide-wheelchair) - + [birdhide-operator](#birdhide-operator) - - - - + - This layer is shown at zoomlevel **14** and higher @@ -42,8 +29,6 @@ A birdhide - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/birdhide/birdhide.json) - Basic tags for this layer diff --git a/Docs/Layers/brugge.md b/Docs/Layers/brugge.md deleted file mode 100644 index fdddb6acd6..0000000000 --- a/Docs/Layers/brugge.md +++ /dev/null @@ -1,73 +0,0 @@ -brugge -======== - -## Table of contents - -1. [brugge](#brugge) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [status](#status) - + [has closeby](#has-closeby) - + [openbaar](#openbaar) - + [addr](#addr) - + [oh](#oh) - - -- This layer is loaded from an external source, namely `https://raw.githubusercontent.com/pietervdvn/pietervdvn.github.io/master/aeds_brugge.json` -- This layer will automatically load [defibrillator](./defibrillator.md) into the layout as it depends on it: A - calculated tag loads features from this layer (calculatedTag[0] which calculates the value for _closest_osm_aed) - -[Go to the source code](../assets/layers/brugge/brugge.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- Brugs volgnummer~^..*$ - -Supported attributes ----------------------- - - - -**Warning** This quick overview is incomplete - -attribute | type | values which are supported by this layer ------------ | ------ | ------------------------------------------ -[](https://taginfo.openstreetmap.org/keys/status#values) [status](https://wiki.openstreetmap.org/wiki/Key:status) | Multiple choice | [oud](https://wiki.openstreetmap.org/wiki/Tag:status%3Doud) -[](https://taginfo.openstreetmap.org/keys/Lokaal AED#values) [Lokaal AED](https://wiki.openstreetmap.org/wiki/Key:Lokaal AED) | Multiple choice | - -### status - -_This tagrendering has no question and is thus read-only_ - -- **
Dit datapunt is verouderd
** corresponds - with status - =oud - -### has closeby - -_This tagrendering has no question and is thus read-only_ - -### openbaar - -_This tagrendering has no question and is thus read-only_ - -- **Bevindt zich in een openbaar gebouw: {Openbare AED Gebouw} in lokaal {Lokaal AED}** corresponds with - Lokaal AED~^..*$ - -### addr - -_This tagrendering has no question and is thus read-only_ - -### oh - -_This tagrendering has no question and is thus read-only_ - -This document is autogenerated from assets/layers/brugge/brugge.json \ No newline at end of file diff --git a/Docs/Layers/cafe_pub.md b/Docs/Layers/cafe_pub.md index 5bbe7c791f..7fb6e3a368 100644 --- a/Docs/Layers/cafe_pub.md +++ b/Docs/Layers/cafe_pub.md @@ -12,29 +12,9 @@ A layer showing cafés and pubs where one can gather around a drink. The layer a -## Table of contents - -1. [cafe_pub](#cafe_pub) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [Name](#name) - + [Classification](#classification) - + [opening_hours](#opening_hours) - + [website](#website) - + [email](#email) - + [phone](#phone) - + [payment-options](#payment-options) - + [wheelchair-access](#wheelchair-access) - + [service:electricity](#serviceelectricity) - + [dog-access](#dog-access) - - - - + - This layer is shown at zoomlevel **0** and higher @@ -49,8 +29,6 @@ A layer showing cafés and pubs where one can gather around a drink. The layer a - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/cafe_pub/cafe_pub.json) - Basic tags for this layer diff --git a/Docs/Layers/caravansites.md b/Docs/Layers/caravansites.md index a46f676c71..99d105517a 100644 --- a/Docs/Layers/caravansites.md +++ b/Docs/Layers/caravansites.md @@ -1,196 +1,306 @@ -caravansites + + + caravansites ============== - + camper sites -## Table of contents - -1. [caravansites](#caravansites) - * [Themes using this layer](#themes-using-this-layer) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [images](#images) - + [caravansites-name](#caravansites-name) - + [caravansites-fee](#caravansites-fee) - + [caravansites-charge](#caravansites-charge) - + [caravansites-sanitary-dump](#caravansites-sanitary-dump) - + [caravansites-capacity](#caravansites-capacity) - + [caravansites-internet](#caravansites-internet) - + [caravansites-internet-fee](#caravansites-internet-fee) - + [caravansites-toilets](#caravansites-toilets) - + [caravansites-website](#caravansites-website) - + [caravansites-long-term](#caravansites-long-term) - + [caravansites-description](#caravansites-description) - + [questions](#questions) - + [reviews](#reviews) - -#### Themes using this layer - -- [campersite](https://mapcomplete.osm.be/campersite) - -[Go to the source code](../assets/layers/caravansites/caravansites.json) -Basic tags for this layer + + + - This layer is shown at zoomlevel **10** and higher + + + + +#### Themes using this layer + + + + + + - [campersite](https://mapcomplete.osm.be/campersite) + + + + + Basic tags for this layer --------------------------- Elements must have the all of following tags to be shown on this layer: -- tourism - =caravan_site -- permanent_camping!~^only$ -Supported attributes + + - tourism=caravan_site + - permanent_camping!~^only$ + + +[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22tourism%22%3D%22caravan_site%22%5D%5B%22permanent_camping%22!~%22%5Eonly%24%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) + + + + Supported attributes ---------------------- **Warning** This quick overview is incomplete + + attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ -[](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/fee#values) [fee](https://wiki.openstreetmap.org/wiki/Key:fee) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:fee%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:fee%3Dno) -[](https://taginfo.openstreetmap.org/keys/charge#values) [charge](https://wiki.openstreetmap.org/wiki/Key:charge) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/charge#values) [charge](https://wiki.openstreetmap.org/wiki/Key:charge) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/sanitary_dump_station#values) [sanitary_dump_station](https://wiki.openstreetmap.org/wiki/Key:sanitary_dump_station) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:sanitary_dump_station%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:sanitary_dump_station%3Dno) -[](https://taginfo.openstreetmap.org/keys/capacity#values) [capacity](https://wiki.openstreetmap.org/wiki/Key:capacity) | [pnat](../SpecialInputElements.md#pnat) | +[](https://taginfo.openstreetmap.org/keys/capacity#values) [capacity](https://wiki.openstreetmap.org/wiki/Key:capacity) | [pnat](../SpecialInputElements.md#pnat) | [](https://taginfo.openstreetmap.org/keys/internet_access#values) [internet_access](https://wiki.openstreetmap.org/wiki/Key:internet_access) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:internet_access%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:internet_access%3Dno) [](https://taginfo.openstreetmap.org/keys/internet_access:fee#values) [internet_access:fee](https://wiki.openstreetmap.org/wiki/Key:internet_access:fee) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:internet_access:fee%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:internet_access:fee%3Dno) [](https://taginfo.openstreetmap.org/keys/toilets#values) [toilets](https://wiki.openstreetmap.org/wiki/Key:toilets) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:toilets%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:toilets%3Dno) -[](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | +[](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | [](https://taginfo.openstreetmap.org/keys/permanent_camping#values) [permanent_camping](https://wiki.openstreetmap.org/wiki/Key:permanent_camping) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:permanent_camping%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:permanent_camping%3Dno) [only](https://wiki.openstreetmap.org/wiki/Tag:permanent_camping%3Donly) -[](https://taginfo.openstreetmap.org/keys/description#values) [description](https://wiki.openstreetmap.org/wiki/Key:description) | [text](../SpecialInputElements.md#text) | +[](https://taginfo.openstreetmap.org/keys/description#values) [description](https://wiki.openstreetmap.org/wiki/Key:description) | [text](../SpecialInputElements.md#text) | +[](https://taginfo.openstreetmap.org/keys/operator#values) [operator](https://wiki.openstreetmap.org/wiki/Key:operator) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/power_supply#values) [power_supply](https://wiki.openstreetmap.org/wiki/Key:power_supply) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:power_supply%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:power_supply%3Dno) + + + + +### images + -### images _This tagrendering has no question and is thus read-only_ -### caravansites-name + + + + +### caravansites-name + + The question is **What is this place called?** -This rendering asks information about the property [name](https://wiki.openstreetmap.org/wiki/Key:name) +This rendering asks information about the property [name](https://wiki.openstreetmap.org/wiki/Key:name) This is rendered with `This place is called {name}` -### caravansites-fee + + +### caravansites-fee + + The question is **Does this place charge a fee?** -- **You need to pay for use** corresponds with - fee=yes -- **Can be used for free** corresponds with - fee=no -- **Can be used for free** corresponds with - fee=no_This option cannot be chosen - as answer_ -### caravansites-charge + + + + - **You need to pay for use** corresponds with fee=yes + - **Can be used for free** corresponds with fee=no + + + + +### caravansites-charge + + The question is **How much does this place charge?** -This rendering asks information about the property [charge](https://wiki.openstreetmap.org/wiki/Key:charge) +This rendering asks information about the property [charge](https://wiki.openstreetmap.org/wiki/Key:charge) This is rendered with `This place charges {charge}` -### caravansites-sanitary-dump + + +### caravansites-sanitary-dump + + The question is **Does this place have a sanitary dump station?** -- **This place has a sanitary dump station** corresponds - with sanitary_dump_station - =yes -- **This place does not have a sanitary dump station** corresponds - with sanitary_dump_station - =no -### caravansites-capacity + + + + - **This place has a sanitary dump station** corresponds with sanitary_dump_station=yes + - **This place does not have a sanitary dump station** corresponds with sanitary_dump_station=no + + + + +### caravansites-capacity + + The question is **How many campers can stay here? (skip if there is no obvious number of spaces or allowed vehicles)** -This rendering asks information about the property [capacity](https://wiki.openstreetmap.org/wiki/Key:capacity) +This rendering asks information about the property [capacity](https://wiki.openstreetmap.org/wiki/Key:capacity) This is rendered with `{capacity} campers can use this place at the same time` -### caravansites-internet + + +### caravansites-internet + + The question is **Does this place provide internet access?** -- **There is internet access** corresponds - with internet_access - =yes -- **There is internet access** corresponds - with internet_access - =wifi - |internet_access - =wlan_This option cannot - be chosen as answer_ -- **There is no internet access** corresponds - with internet_access - =no -### caravansites-internet-fee + + + + - **There is internet access** corresponds with internet_access=yes + - **There is internet access** corresponds with internet_access=wifi|internet_access=wlan_This option cannot be chosen as answer_ + - **There is no internet access** corresponds with internet_access=no + + + + +### caravansites-internet-fee + + The question is **Do you have to pay for the internet access?** -- **You need to pay extra for internet access** corresponds - with internet_access:fee - =yes -- **You do not need to pay extra for internet access** corresponds - with internet_access:fee - =no -### caravansites-toilets + + + + - **You need to pay extra for internet access** corresponds with internet_access:fee=yes + - **You do not need to pay extra for internet access** corresponds with internet_access:fee=no + + + + +### caravansites-toilets + + The question is **Does this place have toilets?** -- **This place has toilets** corresponds with - toilets=yes -- **This place does not have toilets** corresponds - with toilets - =no -### caravansites-website + + + + - **This place has toilets** corresponds with toilets=yes + - **This place does not have toilets** corresponds with toilets=no + + + + +### caravansites-website + + The question is **Does this place have a website?** -This rendering asks information about the property [website](https://wiki.openstreetmap.org/wiki/Key:website) +This rendering asks information about the property [website](https://wiki.openstreetmap.org/wiki/Key:website) This is rendered with `Official website: {website}` -### caravansites-long-term + + +### caravansites-long-term + + The question is **Does this place offer spots for long term rental?** -- **Yes, there are some spots for long term rental, but you can also stay on a daily basis** corresponds - with permanent_camping - =yes -- **No, there are no permanent guests here** corresponds - with permanent_camping - =no -- **It is only possible to stay here if you have a long term contract(this place will disappear from this map if you - choose this)** corresponds with - permanent_camping= - only -### caravansites-description -The question is **Would you like to add a general description of this place? (Do not repeat information previously asked -or shown above. Please keep it objective - opinions go into the reviews)** -This rendering asks information about the property [description](https://wiki.openstreetmap.org/wiki/Key:description) + + - **Yes, there are some spots for long term rental, but you can also stay on a daily basis** corresponds with permanent_camping=yes + - **No, there are no permanent guests here** corresponds with permanent_camping=no + - **It is only possible to stay here if you have a long term contract(this place will disappear from this map if you choose this)** corresponds with permanent_camping=only + + + + +### caravansites-description + + + +The question is **Would you like to add a general description of this place? (Do not repeat information previously asked or shown above. Please keep it objective - opinions go into the reviews)** + +This rendering asks information about the property [description](https://wiki.openstreetmap.org/wiki/Key:description) This is rendered with `More details about this place: {description}` -### questions + + +### questions + + _This tagrendering has no question and is thus read-only_ -### reviews + + + + +### reviews + + _This tagrendering has no question and is thus read-only_ -This document is autogenerated from assets/layers/caravansites/caravansites.json \ No newline at end of file + + + + +### operator + + + +The question is **Who operates this place?** + +This rendering asks information about the property [operator](https://wiki.openstreetmap.org/wiki/Key:operator) +This is rendered with `This place is operated by {operator}` + + + +### power_supply + + + +The question is **Does this place have a power supply?** + + + + + + - **This place has a power supply** corresponds with power_supply=yes + - **This place does not have power supply** corresponds with power_supply=no + + + + +### questions + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### minimap + + + +_This tagrendering has no question and is thus read-only_ + + + +This document is autogenerated from [assets/themes/campersite/campersite.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/campersite/campersite.json) \ No newline at end of file diff --git a/Docs/Layers/charging_station.md b/Docs/Layers/charging_station.md index e518c60447..e0b3838a49 100644 --- a/Docs/Layers/charging_station.md +++ b/Docs/Layers/charging_station.md @@ -12,105 +12,9 @@ A charging station -## Table of contents - -1. [charging_station](#charging_station) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [Type](#type) - + [access](#access) - + [capacity](#capacity) - + [Available_charging_stations (generated)](#available_charging_stations-(generated)) - + [plugs-0](#plugs-0) - + [plugs-1](#plugs-1) - + [plugs-2](#plugs-2) - + [plugs-3](#plugs-3) - + [plugs-4](#plugs-4) - + [plugs-5](#plugs-5) - + [plugs-6](#plugs-6) - + [plugs-7](#plugs-7) - + [plugs-8](#plugs-8) - + [plugs-9](#plugs-9) - + [plugs-10](#plugs-10) - + [plugs-11](#plugs-11) - + [plugs-12](#plugs-12) - + [plugs-13](#plugs-13) - + [plugs-14](#plugs-14) - + [plugs-15](#plugs-15) - + [voltage-0](#voltage-0) - + [current-0](#current-0) - + [power-output-0](#power-output-0) - + [voltage-1](#voltage-1) - + [current-1](#current-1) - + [power-output-1](#power-output-1) - + [voltage-2](#voltage-2) - + [current-2](#current-2) - + [power-output-2](#power-output-2) - + [voltage-3](#voltage-3) - + [current-3](#current-3) - + [power-output-3](#power-output-3) - + [voltage-4](#voltage-4) - + [current-4](#current-4) - + [power-output-4](#power-output-4) - + [voltage-5](#voltage-5) - + [current-5](#current-5) - + [power-output-5](#power-output-5) - + [voltage-6](#voltage-6) - + [current-6](#current-6) - + [power-output-6](#power-output-6) - + [voltage-7](#voltage-7) - + [current-7](#current-7) - + [power-output-7](#power-output-7) - + [voltage-8](#voltage-8) - + [current-8](#current-8) - + [power-output-8](#power-output-8) - + [voltage-9](#voltage-9) - + [current-9](#current-9) - + [power-output-9](#power-output-9) - + [voltage-10](#voltage-10) - + [current-10](#current-10) - + [power-output-10](#power-output-10) - + [voltage-11](#voltage-11) - + [current-11](#current-11) - + [power-output-11](#power-output-11) - + [voltage-12](#voltage-12) - + [current-12](#current-12) - + [power-output-12](#power-output-12) - + [voltage-13](#voltage-13) - + [current-13](#current-13) - + [power-output-13](#power-output-13) - + [voltage-14](#voltage-14) - + [current-14](#current-14) - + [power-output-14](#power-output-14) - + [voltage-15](#voltage-15) - + [current-15](#current-15) - + [power-output-15](#power-output-15) - + [OH](#oh) - + [fee](#fee) - + [charge](#charge) - + [payment-options-advanced](#payment-options-advanced) - + [Authentication](#authentication) - + [Auth phone](#auth-phone) - + [maxstay](#maxstay) - + [Network](#network) - + [Operator](#operator) - + [phone](#phone) - + [email](#email) - + [website](#website) - + [level](#level) - + [ref](#ref) - + [Operational status](#operational-status) - + [Parking:fee](#parkingfee) - + [questions](#questions) - + [questions](#questions) - - - - + - This layer is shown at zoomlevel **10** and higher @@ -125,8 +29,6 @@ A charging station - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/charging_station/charging_station.json) - Basic tags for this layer diff --git a/Docs/Layers/climbing.md b/Docs/Layers/climbing.md index 3a77e5d9bb..4d89002e30 100644 --- a/Docs/Layers/climbing.md +++ b/Docs/Layers/climbing.md @@ -1,4 +1,6 @@ -climbing + + + climbing ========== @@ -7,125 +9,378 @@ climbing A climbing opportunity -## Table of contents - -1. [climbing](#climbing) - * [Themes using this layer](#themes-using-this-layer) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [images](#images) - + [questions](#questions) - + [minimap](#minimap) - + [Contained routes length hist](#contained-routes-length-hist) - + [Contained routes hist](#contained-routes-hist) - + [Contained_climbing_routes](#contained_climbing_routes) - + [name](#name) - + [Type](#type) - + [Rock type (crag/rock/cliff only)](#rock-type-(cragrock/cliff-only)) - + [reviews](#reviews) - - -- This layer will automatically load [climbing_route](./climbing_route.md) into the layout as it depends on it: A - calculated tag loads features from this layer (calculatedTag[0] which calculates the value for _ - contained_climbing_routes_properties) - -#### Themes using this layer - -- [climbing](https://mapcomplete.osm.be/climbing) - -[Go to the source code](../assets/layers/climbing/climbing.json) -Basic tags for this layer + + + - This layer is shown at zoomlevel **10** and higher + - This layer will automatically load [climbing](./climbing.md) into the layout as it depends on it: A calculated tag loads features from this layer (calculatedTag[0] which calculates the value for _embedding_feature_properties) + - This layer will automatically load [climbing_route](./climbing_route.md) into the layout as it depends on it: A calculated tag loads features from this layer (calculatedTag[8] which calculates the value for _contained_climbing_routes_properties) + - This layer is needed as dependency for layer [climbing_club](#climbing_club) + - This layer is needed as dependency for layer [climbing_gym](#climbing_gym) + - This layer is needed as dependency for layer [climbing_route](#climbing_route) + - This layer is needed as dependency for layer [climbing](#climbing) + - This layer is needed as dependency for layer [maybe_climbing](#maybe_climbing) + + + + +#### Themes using this layer + + + + + + - [climbing](https://mapcomplete.osm.be/climbing) + + + + + Basic tags for this layer --------------------------- Elements must have the all of following tags to be shown on this layer: -- sport - =climbing -- climbing!~^route$ -- leisure!~^sports_centre$ -- climbing!~^route_top$ -- climbing!~^route_bottom$ -Supported attributes + + - sport=climbing + - climbing!~^route$ + - leisure!~^sports_centre$ + - climbing!~^route_top$ + - climbing!~^route_bottom$ + + +[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22sport%22%3D%22climbing%22%5D%5B%22climbing%22!~%22%5Eroute%24%22%5D%5B%22climbing%22!~%22%5Eroute_top%24%22%5D%5B%22climbing%22!~%22%5Eroute_bottom%24%22%5D%5B%22leisure%22!~%22%5Esports_centre%24%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) + + + + Supported attributes ---------------------- **Warning** This quick overview is incomplete + + attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://wiki.openstreetmap.org/wiki/Tag:name%3D) [](https://taginfo.openstreetmap.org/keys/climbing#values) [climbing](https://wiki.openstreetmap.org/wiki/Key:climbing) | Multiple choice | [boulder](https://wiki.openstreetmap.org/wiki/Tag:climbing%3Dboulder) [crag](https://wiki.openstreetmap.org/wiki/Tag:climbing%3Dcrag) [area](https://wiki.openstreetmap.org/wiki/Tag:climbing%3Darea) [](https://taginfo.openstreetmap.org/keys/rock#values) [rock](https://wiki.openstreetmap.org/wiki/Key:rock) | [string](../SpecialInputElements.md#string) | [limestone](https://wiki.openstreetmap.org/wiki/Tag:rock%3Dlimestone) +[](https://taginfo.openstreetmap.org/keys/url#values) [url](https://wiki.openstreetmap.org/wiki/Key:url) | [url](../SpecialInputElements.md#url) | +[](https://taginfo.openstreetmap.org/keys/_embedding_feature:access#values) [_embedding_feature:access](https://wiki.openstreetmap.org/wiki/Key:_embedding_feature:access) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dyes) [permit](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dpermit) [customers](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dcustomers) [members](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dmembers) [no](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dno) +[](https://taginfo.openstreetmap.org/keys/access#values) [access](https://wiki.openstreetmap.org/wiki/Key:access) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:access%3Dyes) [permit](https://wiki.openstreetmap.org/wiki/Tag:access%3Dpermit) [customers](https://wiki.openstreetmap.org/wiki/Tag:access%3Dcustomers) [members](https://wiki.openstreetmap.org/wiki/Tag:access%3Dmembers) [no](https://wiki.openstreetmap.org/wiki/Tag:access%3Dno) +[](https://taginfo.openstreetmap.org/keys/access:description#values) [access:description](https://wiki.openstreetmap.org/wiki/Key:access:description) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/climbing:length#values) [climbing:length](https://wiki.openstreetmap.org/wiki/Key:climbing:length) | [pnat](../SpecialInputElements.md#pnat) | +[](https://taginfo.openstreetmap.org/keys/climbing:grade:french:min#values) [climbing:grade:french:min](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french:min) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/climbing:grade:french:max#values) [climbing:grade:french:max](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french:max) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/climbing:boulder#values) [climbing:boulder](https://wiki.openstreetmap.org/wiki/Key:climbing:boulder) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:boulder%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:boulder%3Dno) [limited](https://wiki.openstreetmap.org/wiki/Tag:climbing:boulder%3Dlimited) +[](https://taginfo.openstreetmap.org/keys/climbing:toprope#values) [climbing:toprope](https://wiki.openstreetmap.org/wiki/Key:climbing:toprope) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:toprope%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:toprope%3Dno) +[](https://taginfo.openstreetmap.org/keys/climbing:sport#values) [climbing:sport](https://wiki.openstreetmap.org/wiki/Key:climbing:sport) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:sport%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:sport%3Dno) +[](https://taginfo.openstreetmap.org/keys/climbing:traditional#values) [climbing:traditional](https://wiki.openstreetmap.org/wiki/Key:climbing:traditional) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:traditional%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:traditional%3Dno) +[](https://taginfo.openstreetmap.org/keys/climbing:speed#values) [climbing:speed](https://wiki.openstreetmap.org/wiki/Key:climbing:speed) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:speed%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:speed%3Dno) + + + + +### images + -### images _This tagrendering has no question and is thus read-only_ -### questions + + + + +### questions + + _This tagrendering has no question and is thus read-only_ -### minimap + + + + +### minimap + + _This tagrendering has no question and is thus read-only_ -### Contained routes length hist + + + + +### Contained routes length hist + + _This tagrendering has no question and is thus read-only_ -### Contained routes hist + + + + +### Contained routes hist + + _This tagrendering has no question and is thus read-only_ -### Contained_climbing_routes + + + + +### Contained_climbing_routes + + _This tagrendering has no question and is thus read-only_ -### name + + + + +### name + + The question is **What is the name of this climbing opportunity?** -This rendering asks information about the property [name](https://wiki.openstreetmap.org/wiki/Key:name) +This rendering asks information about the property [name](https://wiki.openstreetmap.org/wiki/Key:name) This is rendered with `{name}` -- **This climbing opportunity doesn't have a name** corresponds - with noname - =yes -### Type + + - **This climbing opportunity doesn't have a name** corresponds with noname=yes + + + + +### Type + + The question is **What kind of climbing opportunity is this?** -- **A climbing boulder - a single rock or cliff with one or a few climbing routes which can be climbed safely without - rope** corresponds with climbing - =boulder -- **A climbing crag - a single rock or cliff with at least a few climbing routes** corresponds - with climbing - =crag -- **A climbing area with one or more climbing crags and/or boulders** corresponds - with climbing - =area -### Rock type (crag/rock/cliff only) + + + + - **A climbing boulder - a single rock or cliff with one or a few climbing routes which can be climbed safely without rope** corresponds with climbing=boulder + - **A climbing crag - a single rock or cliff with at least a few climbing routes** corresponds with climbing=crag + - **A climbing area with one or more climbing crags and/or boulders** corresponds with climbing=area + + + + +### Rock type (crag/rock/cliff only) + + The question is **What is the rock type here?** -This rendering asks information about the property [rock](https://wiki.openstreetmap.org/wiki/Key:rock) +This rendering asks information about the property [rock](https://wiki.openstreetmap.org/wiki/Key:rock) This is rendered with `The rock type is {rock}` -- **Limestone** corresponds with rock - =limestone -### reviews + + - **Limestone** corresponds with rock=limestone + + + + +### reviews + + _This tagrendering has no question and is thus read-only_ -This document is autogenerated from assets/layers/climbing/climbing.json \ No newline at end of file + + + + +### Website + + + +The question is **Is there a (unofficial) website with more informations (e.g. topos)?** + +This rendering asks information about the property [url](https://wiki.openstreetmap.org/wiki/Key:url) +This is rendered with `{url}` + + + +### Access from containing feature + + + +_This tagrendering has no question and is thus read-only_ + + + + + + - **The containing feature states that this is publicly accessible
{_embedding_feature:access:description}** corresponds with _embedding_feature:access=yes + - **The containing feature states that a permit is needed to access
{_embedding_feature:access:description}** corresponds with _embedding_feature:access=permit + - **The containing feature states that this is only accessible to customers
{_embedding_feature:access:description}** corresponds with _embedding_feature:access=customers + - **The containing feature states that this is only accessible to club members
{_embedding_feature:access:description}** corresponds with _embedding_feature:access=members + - **Not accessible as stated by the containing feature** corresponds with _embedding_feature:access=no + + + + +### Access + + + +The question is **Who can access here?** + + + + + + - **Publicly accessible to anyone** corresponds with access=yes + - **You need a permit to access here** corresponds with access=permit + - **Only customers** corresponds with access=customers + - **Only club members** corresponds with access=members + - **Not accessible** corresponds with access=no + + + + +### Access description (without _embedding_feature:access:description) + + + +_This tagrendering has no question and is thus read-only_ + +This rendering asks information about the property [access:description](https://wiki.openstreetmap.org/wiki/Key:access:description) +This is rendered with `{access:description}` + + + +### Avg length? + + + +The question is **What is the (average) length of the routes in meters?** + +This rendering asks information about the property [climbing:length](https://wiki.openstreetmap.org/wiki/Key:climbing:length) +This is rendered with `The routes are {canonical(climbing:length)} long on average` + + + +### Difficulty-min + + + +The question is **What is the grade of the easiest route here, according to the french classification system?** + +This rendering asks information about the property [climbing:grade:french:min](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french:min) +This is rendered with `The lowest grade is {climbing:grade:french:min} according to the french/belgian system` + + + +### Difficulty-max + + + +The question is **What is the highest grade route here, according to the french classification system?** + +This rendering asks information about the property [climbing:grade:french:max](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french:max) +This is rendered with `The highest grade is {climbing:grade:french:max} according to the french/belgian system` + + + +### Boldering? + + + +The question is **Is bouldering possible here?** + + + + + + - **Bouldering is possible here** corresponds with climbing:boulder=yes + - **Bouldering is not possible here** corresponds with climbing:boulder=no + - **Bouldering is possible, allthough there are only a few routes** corresponds with climbing:boulder=limited + - **There are {climbing:boulder} boulder routes** corresponds with climbing:boulder~^..*$_This option cannot be chosen as answer_ + + + + +### Toproping? + + + +The question is **Is toprope climbing possible here?** + + + + + + - **Toprope climbing is possible here** corresponds with climbing:toprope=yes + - **Toprope climbing is not possible here** corresponds with climbing:toprope=no + - **There are {climbing:toprope} toprope routes** corresponds with climbing:toprope~^..*$_This option cannot be chosen as answer_ + + + + +### Sportclimbing? + + + +The question is **Is sport climbing possible here on fixed anchors?** + + + + + + - **Sport climbing is possible here** corresponds with climbing:sport=yes + - **Sport climbing is not possible here** corresponds with climbing:sport=no + - **There are {climbing:sport} sport climbing routes** corresponds with climbing:sport~^..*$_This option cannot be chosen as answer_ + + + + +### Traditional climbing? + + + +The question is **Is traditional climbing possible here (using own gear e.g. chocks)?** + + + + + + - **Traditional climbing is possible here** corresponds with climbing:traditional=yes + - **Traditional climbing is not possible here** corresponds with climbing:traditional=no + - **There are {climbing:traditional} traditional climbing routes** corresponds with climbing:traditional~^..*$_This option cannot be chosen as answer_ + + + + +### Speed climbing? + + + +The question is **Is there a speed climbing wall?** + + + + + + - **There is a speed climbing wall** corresponds with climbing:speed=yes + - **There is no speed climbing wall** corresponds with climbing:speed=no + - **There are {climbing:speed} speed climbing walls** corresponds with climbing:speed~^..*$_This option cannot be chosen as answer_ + + +This document is autogenerated from [assets/themes/climbing/climbing.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/climbing/climbing.json) \ No newline at end of file diff --git a/Docs/Layers/climbing_club.md b/Docs/Layers/climbing_club.md index 562cb6137f..622a32de47 100644 --- a/Docs/Layers/climbing_club.md +++ b/Docs/Layers/climbing_club.md @@ -1,109 +1,339 @@ -climbing_club + + + climbing_club =============== -A climbing club or organisations - -## Table of contents - -1. [climbing_club](#climbing_club) - * [Themes using this layer](#themes-using-this-layer) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [climbing_club-name](#climbing_club-name) - + [minimap](#minimap) - + [website](#website) - + [email](#email) - + [phone](#phone) - + [opening_hours](#opening_hours) - -#### Themes using this layer - -- [climbing](https://mapcomplete.osm.be/climbing) - -[Go to the source code](../assets/layers/climbing_club/climbing_club.json) +A climbing club or organisation -Basic tags for this layer + + + + - This layer is shown at zoomlevel **10** and higher + - This layer will automatically load [climbing](./climbing.md) into the layout as it depends on it: A calculated tag loads features from this layer (calculatedTag[0] which calculates the value for _embedding_feature_properties) + + + + +#### Themes using this layer + + + + + + - [climbing](https://mapcomplete.osm.be/climbing) + + + + + Basic tags for this layer --------------------------- Elements must have the all of following tags to be shown on this layer: -- club - =climbing - |sport - =climbing&office~^..*$|club~ - ^..*$ -Supported attributes + + - club=climbing|sport=climbing&office~^..*$|club~^..*$ + + +[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22club%22%3D%22climbing%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22sport%22%3D%22climbing%22%5D%5B%22club%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22sport%22%3D%22climbing%22%5D%5B%22office%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) + + + + Supported attributes ---------------------- **Warning** This quick overview is incomplete + + attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ -[](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | -[](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | -[](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | -[](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | -[](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | +[](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | +[](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | +[](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | +[](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | +[](https://taginfo.openstreetmap.org/keys/url#values) [url](https://wiki.openstreetmap.org/wiki/Key:url) | [url](../SpecialInputElements.md#url) | +[](https://taginfo.openstreetmap.org/keys/_embedding_feature:access#values) [_embedding_feature:access](https://wiki.openstreetmap.org/wiki/Key:_embedding_feature:access) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dyes) [permit](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dpermit) [customers](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dcustomers) [members](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dmembers) [no](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dno) +[](https://taginfo.openstreetmap.org/keys/access#values) [access](https://wiki.openstreetmap.org/wiki/Key:access) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:access%3Dyes) [permit](https://wiki.openstreetmap.org/wiki/Tag:access%3Dpermit) [customers](https://wiki.openstreetmap.org/wiki/Tag:access%3Dcustomers) [members](https://wiki.openstreetmap.org/wiki/Tag:access%3Dmembers) [no](https://wiki.openstreetmap.org/wiki/Tag:access%3Dno) +[](https://taginfo.openstreetmap.org/keys/access:description#values) [access:description](https://wiki.openstreetmap.org/wiki/Key:access:description) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/climbing:length#values) [climbing:length](https://wiki.openstreetmap.org/wiki/Key:climbing:length) | [pnat](../SpecialInputElements.md#pnat) | +[](https://taginfo.openstreetmap.org/keys/climbing:grade:french:min#values) [climbing:grade:french:min](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french:min) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/climbing:grade:french:max#values) [climbing:grade:french:max](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french:max) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/climbing:boulder#values) [climbing:boulder](https://wiki.openstreetmap.org/wiki/Key:climbing:boulder) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:boulder%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:boulder%3Dno) [limited](https://wiki.openstreetmap.org/wiki/Tag:climbing:boulder%3Dlimited) +[](https://taginfo.openstreetmap.org/keys/climbing:toprope#values) [climbing:toprope](https://wiki.openstreetmap.org/wiki/Key:climbing:toprope) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:toprope%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:toprope%3Dno) +[](https://taginfo.openstreetmap.org/keys/climbing:sport#values) [climbing:sport](https://wiki.openstreetmap.org/wiki/Key:climbing:sport) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:sport%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:sport%3Dno) +[](https://taginfo.openstreetmap.org/keys/climbing:traditional#values) [climbing:traditional](https://wiki.openstreetmap.org/wiki/Key:climbing:traditional) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:traditional%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:traditional%3Dno) +[](https://taginfo.openstreetmap.org/keys/climbing:speed#values) [climbing:speed](https://wiki.openstreetmap.org/wiki/Key:climbing:speed) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:speed%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:speed%3Dno) + + + + +### climbing_club-name + -### climbing_club-name The question is **What is the name of this climbing club or NGO?** -This rendering asks information about the property [name](https://wiki.openstreetmap.org/wiki/Key:name) +This rendering asks information about the property [name](https://wiki.openstreetmap.org/wiki/Key:name) This is rendered with `{name}` -### minimap + + +### minimap + + _This tagrendering has no question and is thus read-only_ -### website -The question is **What is the website of {name}?** -This rendering asks information about the property [website](https://wiki.openstreetmap.org/wiki/Key:website) + + +### website + + + +The question is **What is the website of {title()}?** + +This rendering asks information about the property [website](https://wiki.openstreetmap.org/wiki/Key:website) This is rendered with `{website}` -- **{contact:website}** corresponds with contact:website~^..*$_This - option cannot be chosen as answer_ -### email -The question is **What is the email address of {name}?** + - **{contact:website}** corresponds with contact:website~^..*$_This option cannot be chosen as answer_ -This rendering asks information about the property [email](https://wiki.openstreetmap.org/wiki/Key:email) + + + +### email + + + +The question is **What is the email address of {title()}?** + +This rendering asks information about the property [email](https://wiki.openstreetmap.org/wiki/Key:email) This is rendered with `{email}` -- **{contact:email}** corresponds with contact:email~^..*$_This - option cannot be chosen as answer_ -### phone -The question is **What is the phone number of {name}?** + - **{contact:email}** corresponds with contact:email~^..*$_This option cannot be chosen as answer_ -This rendering asks information about the property [phone](https://wiki.openstreetmap.org/wiki/Key:phone) + + + +### phone + + + +The question is **What is the phone number of {title()}?** + +This rendering asks information about the property [phone](https://wiki.openstreetmap.org/wiki/Key:phone) This is rendered with `{phone}` -- **{contact:phone}** corresponds with contact:phone~^..*$_This option cannot be - chosen as answer_ -### opening_hours -The question is **What are the opening hours of {name}?** + - **{contact:phone}** corresponds with contact:phone~^..*$_This option cannot be chosen as answer_ -This rendering asks information about the -property [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) + + + +### opening_hours + + + +The question is **What are the opening hours of {title()}?** + +This rendering asks information about the property [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) This is rendered with `

Opening hours

{opening_hours_table(opening_hours)}` -This document is autogenerated from assets/layers/climbing_club/climbing_club.json \ No newline at end of file + + +### Website + + + +The question is **Is there a (unofficial) website with more informations (e.g. topos)?** + +This rendering asks information about the property [url](https://wiki.openstreetmap.org/wiki/Key:url) +This is rendered with `{url}` + + + +### Access from containing feature + + + +_This tagrendering has no question and is thus read-only_ + + + + + + - **The containing feature states that this is publicly accessible
{_embedding_feature:access:description}** corresponds with _embedding_feature:access=yes + - **The containing feature states that a permit is needed to access
{_embedding_feature:access:description}** corresponds with _embedding_feature:access=permit + - **The containing feature states that this is only accessible to customers
{_embedding_feature:access:description}** corresponds with _embedding_feature:access=customers + - **The containing feature states that this is only accessible to club members
{_embedding_feature:access:description}** corresponds with _embedding_feature:access=members + - **Not accessible as stated by the containing feature** corresponds with _embedding_feature:access=no + + + + +### Access + + + +The question is **Who can access here?** + + + + + + - **Publicly accessible to anyone** corresponds with access=yes + - **You need a permit to access here** corresponds with access=permit + - **Only customers** corresponds with access=customers + - **Only club members** corresponds with access=members + - **Not accessible** corresponds with access=no + + + + +### Access description (without _embedding_feature:access:description) + + + +_This tagrendering has no question and is thus read-only_ + +This rendering asks information about the property [access:description](https://wiki.openstreetmap.org/wiki/Key:access:description) +This is rendered with `{access:description}` + + + +### Avg length? + + + +The question is **What is the (average) length of the routes in meters?** + +This rendering asks information about the property [climbing:length](https://wiki.openstreetmap.org/wiki/Key:climbing:length) +This is rendered with `The routes are {canonical(climbing:length)} long on average` + + + +### Difficulty-min + + + +The question is **What is the grade of the easiest route here, according to the french classification system?** + +This rendering asks information about the property [climbing:grade:french:min](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french:min) +This is rendered with `The lowest grade is {climbing:grade:french:min} according to the french/belgian system` + + + +### Difficulty-max + + + +The question is **What is the highest grade route here, according to the french classification system?** + +This rendering asks information about the property [climbing:grade:french:max](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french:max) +This is rendered with `The highest grade is {climbing:grade:french:max} according to the french/belgian system` + + + +### Boldering? + + + +The question is **Is bouldering possible here?** + + + + + + - **Bouldering is possible here** corresponds with climbing:boulder=yes + - **Bouldering is not possible here** corresponds with climbing:boulder=no + - **Bouldering is possible, allthough there are only a few routes** corresponds with climbing:boulder=limited + - **There are {climbing:boulder} boulder routes** corresponds with climbing:boulder~^..*$_This option cannot be chosen as answer_ + + + + +### Toproping? + + + +The question is **Is toprope climbing possible here?** + + + + + + - **Toprope climbing is possible here** corresponds with climbing:toprope=yes + - **Toprope climbing is not possible here** corresponds with climbing:toprope=no + - **There are {climbing:toprope} toprope routes** corresponds with climbing:toprope~^..*$_This option cannot be chosen as answer_ + + + + +### Sportclimbing? + + + +The question is **Is sport climbing possible here on fixed anchors?** + + + + + + - **Sport climbing is possible here** corresponds with climbing:sport=yes + - **Sport climbing is not possible here** corresponds with climbing:sport=no + - **There are {climbing:sport} sport climbing routes** corresponds with climbing:sport~^..*$_This option cannot be chosen as answer_ + + + + +### Traditional climbing? + + + +The question is **Is traditional climbing possible here (using own gear e.g. chocks)?** + + + + + + - **Traditional climbing is possible here** corresponds with climbing:traditional=yes + - **Traditional climbing is not possible here** corresponds with climbing:traditional=no + - **There are {climbing:traditional} traditional climbing routes** corresponds with climbing:traditional~^..*$_This option cannot be chosen as answer_ + + + + +### Speed climbing? + + + +The question is **Is there a speed climbing wall?** + + + + + + - **There is a speed climbing wall** corresponds with climbing:speed=yes + - **There is no speed climbing wall** corresponds with climbing:speed=no + - **There are {climbing:speed} speed climbing walls** corresponds with climbing:speed~^..*$_This option cannot be chosen as answer_ + + +This document is autogenerated from [assets/themes/climbing/climbing.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/climbing/climbing.json) \ No newline at end of file diff --git a/Docs/Layers/climbing_gym.md b/Docs/Layers/climbing_gym.md index 14a8611191..16993bf7ab 100644 --- a/Docs/Layers/climbing_gym.md +++ b/Docs/Layers/climbing_gym.md @@ -1,4 +1,6 @@ -climbing_gym + + + climbing_gym ============== @@ -7,117 +9,362 @@ climbing_gym A climbing gym -## Table of contents - -1. [climbing_gym](#climbing_gym) - * [Themes using this layer](#themes-using-this-layer) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [images](#images) - + [questions](#questions) - + [minimap](#minimap) - + [name](#name) - + [website](#website) - + [phone](#phone) - + [email](#email) - + [opening_hours](#opening_hours) - + [reviews](#reviews) - -#### Themes using this layer - -- [climbing](https://mapcomplete.osm.be/climbing) - -[Go to the source code](../assets/layers/climbing_gym/climbing_gym.json) -Basic tags for this layer + + + - This layer is shown at zoomlevel **10** and higher + - This layer will automatically load [climbing](./climbing.md) into the layout as it depends on it: A calculated tag loads features from this layer (calculatedTag[0] which calculates the value for _embedding_feature_properties) + + + + +#### Themes using this layer + + + + + + - [climbing](https://mapcomplete.osm.be/climbing) + + + + + Basic tags for this layer --------------------------- Elements must have the all of following tags to be shown on this layer: -- sport - =climbing -- leisure - =sports_centre -Supported attributes + + - sport=climbing + - leisure=sports_centre + + +[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22sport%22%3D%22climbing%22%5D%5B%22leisure%22%3D%22sports_centre%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) + + + + Supported attributes ---------------------- **Warning** This quick overview is incomplete + + attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ -[](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | -[](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | -[](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | -[](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | -[](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | +[](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | +[](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | +[](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | +[](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | +[](https://taginfo.openstreetmap.org/keys/url#values) [url](https://wiki.openstreetmap.org/wiki/Key:url) | [url](../SpecialInputElements.md#url) | +[](https://taginfo.openstreetmap.org/keys/_embedding_feature:access#values) [_embedding_feature:access](https://wiki.openstreetmap.org/wiki/Key:_embedding_feature:access) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dyes) [permit](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dpermit) [customers](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dcustomers) [members](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dmembers) [no](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dno) +[](https://taginfo.openstreetmap.org/keys/access#values) [access](https://wiki.openstreetmap.org/wiki/Key:access) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:access%3Dyes) [permit](https://wiki.openstreetmap.org/wiki/Tag:access%3Dpermit) [customers](https://wiki.openstreetmap.org/wiki/Tag:access%3Dcustomers) [members](https://wiki.openstreetmap.org/wiki/Tag:access%3Dmembers) [no](https://wiki.openstreetmap.org/wiki/Tag:access%3Dno) +[](https://taginfo.openstreetmap.org/keys/access:description#values) [access:description](https://wiki.openstreetmap.org/wiki/Key:access:description) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/climbing:length#values) [climbing:length](https://wiki.openstreetmap.org/wiki/Key:climbing:length) | [pnat](../SpecialInputElements.md#pnat) | +[](https://taginfo.openstreetmap.org/keys/climbing:grade:french:min#values) [climbing:grade:french:min](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french:min) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/climbing:grade:french:max#values) [climbing:grade:french:max](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french:max) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/climbing:boulder#values) [climbing:boulder](https://wiki.openstreetmap.org/wiki/Key:climbing:boulder) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:boulder%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:boulder%3Dno) [limited](https://wiki.openstreetmap.org/wiki/Tag:climbing:boulder%3Dlimited) +[](https://taginfo.openstreetmap.org/keys/climbing:toprope#values) [climbing:toprope](https://wiki.openstreetmap.org/wiki/Key:climbing:toprope) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:toprope%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:toprope%3Dno) +[](https://taginfo.openstreetmap.org/keys/climbing:sport#values) [climbing:sport](https://wiki.openstreetmap.org/wiki/Key:climbing:sport) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:sport%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:sport%3Dno) +[](https://taginfo.openstreetmap.org/keys/climbing:traditional#values) [climbing:traditional](https://wiki.openstreetmap.org/wiki/Key:climbing:traditional) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:traditional%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:traditional%3Dno) +[](https://taginfo.openstreetmap.org/keys/climbing:speed#values) [climbing:speed](https://wiki.openstreetmap.org/wiki/Key:climbing:speed) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:speed%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:speed%3Dno) + + + + +### images + -### images _This tagrendering has no question and is thus read-only_ -### questions + + + + +### questions + + _This tagrendering has no question and is thus read-only_ -### minimap + + + + +### minimap + + _This tagrendering has no question and is thus read-only_ -### name + + + + +### name + + The question is **What is the name of this climbing gym?** -This rendering asks information about the property [name](https://wiki.openstreetmap.org/wiki/Key:name) +This rendering asks information about the property [name](https://wiki.openstreetmap.org/wiki/Key:name) This is rendered with `{name}` -### website -The question is **What is the website of {name}?** -This rendering asks information about the property [website](https://wiki.openstreetmap.org/wiki/Key:website) +### website + + + +The question is **What is the website of {title()}?** + +This rendering asks information about the property [website](https://wiki.openstreetmap.org/wiki/Key:website) This is rendered with `{website}` -- **{contact:website}** corresponds with contact:website~^..*$_This - option cannot be chosen as answer_ -### phone -The question is **What is the phone number of {name}?** + - **{contact:website}** corresponds with contact:website~^..*$_This option cannot be chosen as answer_ -This rendering asks information about the property [phone](https://wiki.openstreetmap.org/wiki/Key:phone) + + + +### phone + + + +The question is **What is the phone number of {title()}?** + +This rendering asks information about the property [phone](https://wiki.openstreetmap.org/wiki/Key:phone) This is rendered with `{phone}` -- **{contact:phone}** corresponds with contact:phone~^..*$_This option cannot be - chosen as answer_ -### email -The question is **What is the email address of {name}?** + - **{contact:phone}** corresponds with contact:phone~^..*$_This option cannot be chosen as answer_ -This rendering asks information about the property [email](https://wiki.openstreetmap.org/wiki/Key:email) + + + +### email + + + +The question is **What is the email address of {title()}?** + +This rendering asks information about the property [email](https://wiki.openstreetmap.org/wiki/Key:email) This is rendered with `{email}` -- **{contact:email}** corresponds with contact:email~^..*$_This - option cannot be chosen as answer_ -### opening_hours -The question is **What are the opening hours of {name}?** + - **{contact:email}** corresponds with contact:email~^..*$_This option cannot be chosen as answer_ -This rendering asks information about the -property [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) + + + +### opening_hours + + + +The question is **What are the opening hours of {title()}?** + +This rendering asks information about the property [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) This is rendered with `

Opening hours

{opening_hours_table(opening_hours)}` -### reviews + + +### reviews + + _This tagrendering has no question and is thus read-only_ -This document is autogenerated from assets/layers/climbing_gym/climbing_gym.json \ No newline at end of file + + + + +### Website + + + +The question is **Is there a (unofficial) website with more informations (e.g. topos)?** + +This rendering asks information about the property [url](https://wiki.openstreetmap.org/wiki/Key:url) +This is rendered with `{url}` + + + +### Access from containing feature + + + +_This tagrendering has no question and is thus read-only_ + + + + + + - **The containing feature states that this is publicly accessible
{_embedding_feature:access:description}** corresponds with _embedding_feature:access=yes + - **The containing feature states that a permit is needed to access
{_embedding_feature:access:description}** corresponds with _embedding_feature:access=permit + - **The containing feature states that this is only accessible to customers
{_embedding_feature:access:description}** corresponds with _embedding_feature:access=customers + - **The containing feature states that this is only accessible to club members
{_embedding_feature:access:description}** corresponds with _embedding_feature:access=members + - **Not accessible as stated by the containing feature** corresponds with _embedding_feature:access=no + + + + +### Access + + + +The question is **Who can access here?** + + + + + + - **Publicly accessible to anyone** corresponds with access=yes + - **You need a permit to access here** corresponds with access=permit + - **Only customers** corresponds with access=customers + - **Only club members** corresponds with access=members + - **Not accessible** corresponds with access=no + + + + +### Access description (without _embedding_feature:access:description) + + + +_This tagrendering has no question and is thus read-only_ + +This rendering asks information about the property [access:description](https://wiki.openstreetmap.org/wiki/Key:access:description) +This is rendered with `{access:description}` + + + +### Avg length? + + + +The question is **What is the (average) length of the routes in meters?** + +This rendering asks information about the property [climbing:length](https://wiki.openstreetmap.org/wiki/Key:climbing:length) +This is rendered with `The routes are {canonical(climbing:length)} long on average` + + + +### Difficulty-min + + + +The question is **What is the grade of the easiest route here, according to the french classification system?** + +This rendering asks information about the property [climbing:grade:french:min](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french:min) +This is rendered with `The lowest grade is {climbing:grade:french:min} according to the french/belgian system` + + + +### Difficulty-max + + + +The question is **What is the highest grade route here, according to the french classification system?** + +This rendering asks information about the property [climbing:grade:french:max](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french:max) +This is rendered with `The highest grade is {climbing:grade:french:max} according to the french/belgian system` + + + +### Boldering? + + + +The question is **Is bouldering possible here?** + + + + + + - **Bouldering is possible here** corresponds with climbing:boulder=yes + - **Bouldering is not possible here** corresponds with climbing:boulder=no + - **Bouldering is possible, allthough there are only a few routes** corresponds with climbing:boulder=limited + - **There are {climbing:boulder} boulder routes** corresponds with climbing:boulder~^..*$_This option cannot be chosen as answer_ + + + + +### Toproping? + + + +The question is **Is toprope climbing possible here?** + + + + + + - **Toprope climbing is possible here** corresponds with climbing:toprope=yes + - **Toprope climbing is not possible here** corresponds with climbing:toprope=no + - **There are {climbing:toprope} toprope routes** corresponds with climbing:toprope~^..*$_This option cannot be chosen as answer_ + + + + +### Sportclimbing? + + + +The question is **Is sport climbing possible here on fixed anchors?** + + + + + + - **Sport climbing is possible here** corresponds with climbing:sport=yes + - **Sport climbing is not possible here** corresponds with climbing:sport=no + - **There are {climbing:sport} sport climbing routes** corresponds with climbing:sport~^..*$_This option cannot be chosen as answer_ + + + + +### Traditional climbing? + + + +The question is **Is traditional climbing possible here (using own gear e.g. chocks)?** + + + + + + - **Traditional climbing is possible here** corresponds with climbing:traditional=yes + - **Traditional climbing is not possible here** corresponds with climbing:traditional=no + - **There are {climbing:traditional} traditional climbing routes** corresponds with climbing:traditional~^..*$_This option cannot be chosen as answer_ + + + + +### Speed climbing? + + + +The question is **Is there a speed climbing wall?** + + + + + + - **There is a speed climbing wall** corresponds with climbing:speed=yes + - **There is no speed climbing wall** corresponds with climbing:speed=no + - **There are {climbing:speed} speed climbing walls** corresponds with climbing:speed~^..*$_This option cannot be chosen as answer_ + + +This document is autogenerated from [assets/themes/climbing/climbing.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/climbing/climbing.json) \ No newline at end of file diff --git a/Docs/Layers/climbing_route.md b/Docs/Layers/climbing_route.md index c60b3159ca..ffd8afe5c0 100644 --- a/Docs/Layers/climbing_route.md +++ b/Docs/Layers/climbing_route.md @@ -1,139 +1,376 @@ -climbing_route + + + climbing_route ================ - - -## Table of contents - -1. [climbing_route](#climbing_route) - * [Themes using this layer](#themes-using-this-layer) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [images](#images) - + [questions](#questions) - + [minimap](#minimap) - + [Name](#name) - + [Length](#length) - + [Difficulty](#difficulty) - + [Bolts](#bolts) - + [Description](#description) - + [Rock type](#rock-type) - + [reviews](#reviews) - - -- This layer is needed as dependency for layer [climbing](#climbing) - -#### Themes using this layer - -- [climbing](https://mapcomplete.osm.be/climbing) - -[Go to the source code](../assets/layers/climbing_route/climbing_route.json) + -Basic tags for this layer + + + + - This layer is shown at zoomlevel **18** and higher + - This layer will automatically load [climbing](./climbing.md) into the layout as it depends on it: A calculated tag loads features from this layer (calculatedTag[0] which calculates the value for _embedding_feature_properties) + - This layer is needed as dependency for layer [climbing](#climbing) + + + + +#### Themes using this layer + + + + + + - [climbing](https://mapcomplete.osm.be/climbing) + + + + + Basic tags for this layer --------------------------- Elements must have the all of following tags to be shown on this layer: -- climbing - =route -Supported attributes + + - climbing=route + + +[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22climbing%22%3D%22route%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) + + + + Supported attributes ---------------------- **Warning** This quick overview is incomplete + + attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://wiki.openstreetmap.org/wiki/Tag:name%3D) -[](https://taginfo.openstreetmap.org/keys/climbing:length#values) [climbing:length](https://wiki.openstreetmap.org/wiki/Key:climbing:length) | [pnat](../SpecialInputElements.md#pnat) | -[](https://taginfo.openstreetmap.org/keys/climbing:grade:french#values) [climbing:grade:french](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french) | [string](../SpecialInputElements.md#string) | -[](https://taginfo.openstreetmap.org/keys/climbing:bolts#values) [climbing:bolts](https://wiki.openstreetmap.org/wiki/Key:climbing:bolts) | [pnat](../SpecialInputElements.md#pnat) | -[](https://taginfo.openstreetmap.org/keys/description#values) [description](https://wiki.openstreetmap.org/wiki/Key:description) | [string](../SpecialInputElements.md#string) | -[](https://taginfo.openstreetmap.org/keys/_embedding_features_with_rock:rock#values) [_embedding_features_with_rock:rock](https://wiki.openstreetmap.org/wiki/Key:_embedding_features_with_rock:rock) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/climbing:length#values) [climbing:length](https://wiki.openstreetmap.org/wiki/Key:climbing:length) | [pnat](../SpecialInputElements.md#pnat) | +[](https://taginfo.openstreetmap.org/keys/climbing:grade:french#values) [climbing:grade:french](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/climbing:bolts#values) [climbing:bolts](https://wiki.openstreetmap.org/wiki/Key:climbing:bolts) | [pnat](../SpecialInputElements.md#pnat) | +[](https://taginfo.openstreetmap.org/keys/description#values) [description](https://wiki.openstreetmap.org/wiki/Key:description) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/_embedding_features_with_rock:rock#values) [_embedding_features_with_rock:rock](https://wiki.openstreetmap.org/wiki/Key:_embedding_features_with_rock:rock) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/url#values) [url](https://wiki.openstreetmap.org/wiki/Key:url) | [url](../SpecialInputElements.md#url) | +[](https://taginfo.openstreetmap.org/keys/_embedding_feature:access#values) [_embedding_feature:access](https://wiki.openstreetmap.org/wiki/Key:_embedding_feature:access) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dyes) [permit](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dpermit) [customers](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dcustomers) [members](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dmembers) [no](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dno) +[](https://taginfo.openstreetmap.org/keys/access#values) [access](https://wiki.openstreetmap.org/wiki/Key:access) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:access%3Dyes) [permit](https://wiki.openstreetmap.org/wiki/Tag:access%3Dpermit) [customers](https://wiki.openstreetmap.org/wiki/Tag:access%3Dcustomers) [members](https://wiki.openstreetmap.org/wiki/Tag:access%3Dmembers) [no](https://wiki.openstreetmap.org/wiki/Tag:access%3Dno) +[](https://taginfo.openstreetmap.org/keys/access:description#values) [access:description](https://wiki.openstreetmap.org/wiki/Key:access:description) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/climbing:length#values) [climbing:length](https://wiki.openstreetmap.org/wiki/Key:climbing:length) | [pnat](../SpecialInputElements.md#pnat) | +[](https://taginfo.openstreetmap.org/keys/climbing:grade:french:min#values) [climbing:grade:french:min](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french:min) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/climbing:grade:french:max#values) [climbing:grade:french:max](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french:max) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/climbing:boulder#values) [climbing:boulder](https://wiki.openstreetmap.org/wiki/Key:climbing:boulder) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:boulder%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:boulder%3Dno) [limited](https://wiki.openstreetmap.org/wiki/Tag:climbing:boulder%3Dlimited) +[](https://taginfo.openstreetmap.org/keys/climbing:toprope#values) [climbing:toprope](https://wiki.openstreetmap.org/wiki/Key:climbing:toprope) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:toprope%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:toprope%3Dno) +[](https://taginfo.openstreetmap.org/keys/climbing:sport#values) [climbing:sport](https://wiki.openstreetmap.org/wiki/Key:climbing:sport) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:sport%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:sport%3Dno) +[](https://taginfo.openstreetmap.org/keys/climbing:traditional#values) [climbing:traditional](https://wiki.openstreetmap.org/wiki/Key:climbing:traditional) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:traditional%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:traditional%3Dno) +[](https://taginfo.openstreetmap.org/keys/climbing:speed#values) [climbing:speed](https://wiki.openstreetmap.org/wiki/Key:climbing:speed) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:speed%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:speed%3Dno) + + + + +### images + -### images _This tagrendering has no question and is thus read-only_ -### questions + + + + +### questions + + _This tagrendering has no question and is thus read-only_ -### minimap + + + + +### minimap + + _This tagrendering has no question and is thus read-only_ -### Name + + + + +### Name + + The question is **What is the name of this climbing route?** -This rendering asks information about the property [name](https://wiki.openstreetmap.org/wiki/Key:name) +This rendering asks information about the property [name](https://wiki.openstreetmap.org/wiki/Key:name) This is rendered with `{name}` -- **This climbing route doesn't have a name** corresponds - with noname - =yes -### Length + + - **This climbing route doesn't have a name** corresponds with noname=yes + + + + +### Length + + The question is **How long is this climbing route (in meters)?** -This rendering asks information about the -property [climbing:length](https://wiki.openstreetmap.org/wiki/Key:climbing:length) +This rendering asks information about the property [climbing:length](https://wiki.openstreetmap.org/wiki/Key:climbing:length) This is rendered with `This route is {canonical(climbing:length)} long` -### Difficulty -The question is **What is the difficulty of this climbing route according to the french/belgian system?** -This rendering asks information about the -property [climbing:grade:french](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french) -This is rendered with `The difficulty is {climbing:grade:french} according to the french/belgian system` +### Difficulty -### Bolts -The question is **How much bolts does this route have before reaching the moulinette?** -This rendering asks information about the -property [climbing:bolts](https://wiki.openstreetmap.org/wiki/Key:climbing:bolts) +The question is **What is the grade of this climbing route according to the french/belgian system?** + +This rendering asks information about the property [climbing:grade:french](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french) +This is rendered with `The grade is {climbing:grade:french} according to the french/belgian system` + + + +### Bolts + + + +The question is **How many bolts does this route have before reaching the anchor?** + +This rendering asks information about the property [climbing:bolts](https://wiki.openstreetmap.org/wiki/Key:climbing:bolts) This is rendered with `This route has {climbing:bolts} bolts` -- **This route is not bolted** corresponds - with climbing:bolted - =no_This option cannot be - chosen as answer_ -- **This route is not bolted** corresponds - with climbing:bolted - =no&climbing: - bolts= -### Description + + - **This route is not bolted** corresponds with climbing:bolted=no_This option cannot be chosen as answer_ + - **This route is not bolted** corresponds with climbing:bolted=no&climbing:bolts= + + + + +### Description + + The question is **Is there other relevant info?** -This rendering asks information about the property [description](https://wiki.openstreetmap.org/wiki/Key:description) +This rendering asks information about the property [description](https://wiki.openstreetmap.org/wiki/Key:description) This is rendered with `

Description


{description}` -### Rock type + + +### Rock type + + _This tagrendering has no question and is thus read-only_ -This rendering asks information about the -property [_embedding_features_with_rock:rock](https://wiki.openstreetmap.org/wiki/Key:_embedding_features_with_rock:rock) -This is rendered -with `The rock type is {_embedding_features_with_rock:rock} as stated on the surrounding crag` +This rendering asks information about the property [_embedding_features_with_rock:rock](https://wiki.openstreetmap.org/wiki/Key:_embedding_features_with_rock:rock) +This is rendered with `The rock type is {_embedding_features_with_rock:rock} as stated on the surrounding crag` + + + +### reviews + -### reviews _This tagrendering has no question and is thus read-only_ -This document is autogenerated from assets/layers/climbing_route/climbing_route.json \ No newline at end of file + + + + +### Website + + + +The question is **Is there a (unofficial) website with more informations (e.g. topos)?** + +This rendering asks information about the property [url](https://wiki.openstreetmap.org/wiki/Key:url) +This is rendered with `{url}` + + + +### Access from containing feature + + + +_This tagrendering has no question and is thus read-only_ + + + + + + - **The containing feature states that this is publicly accessible
{_embedding_feature:access:description}** corresponds with _embedding_feature:access=yes + - **The containing feature states that a permit is needed to access
{_embedding_feature:access:description}** corresponds with _embedding_feature:access=permit + - **The containing feature states that this is only accessible to customers
{_embedding_feature:access:description}** corresponds with _embedding_feature:access=customers + - **The containing feature states that this is only accessible to club members
{_embedding_feature:access:description}** corresponds with _embedding_feature:access=members + - **Not accessible as stated by the containing feature** corresponds with _embedding_feature:access=no + + + + +### Access + + + +The question is **Who can access here?** + + + + + + - **Publicly accessible to anyone** corresponds with access=yes + - **You need a permit to access here** corresponds with access=permit + - **Only customers** corresponds with access=customers + - **Only club members** corresponds with access=members + - **Not accessible** corresponds with access=no + + + + +### Access description (without _embedding_feature:access:description) + + + +_This tagrendering has no question and is thus read-only_ + +This rendering asks information about the property [access:description](https://wiki.openstreetmap.org/wiki/Key:access:description) +This is rendered with `{access:description}` + + + +### Avg length? + + + +The question is **What is the (average) length of the routes in meters?** + +This rendering asks information about the property [climbing:length](https://wiki.openstreetmap.org/wiki/Key:climbing:length) +This is rendered with `The routes are {canonical(climbing:length)} long on average` + + + +### Difficulty-min + + + +The question is **What is the grade of the easiest route here, according to the french classification system?** + +This rendering asks information about the property [climbing:grade:french:min](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french:min) +This is rendered with `The lowest grade is {climbing:grade:french:min} according to the french/belgian system` + + + +### Difficulty-max + + + +The question is **What is the highest grade route here, according to the french classification system?** + +This rendering asks information about the property [climbing:grade:french:max](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french:max) +This is rendered with `The highest grade is {climbing:grade:french:max} according to the french/belgian system` + + + +### Boldering? + + + +The question is **Is bouldering possible here?** + + + + + + - **Bouldering is possible here** corresponds with climbing:boulder=yes + - **Bouldering is not possible here** corresponds with climbing:boulder=no + - **Bouldering is possible, allthough there are only a few routes** corresponds with climbing:boulder=limited + - **There are {climbing:boulder} boulder routes** corresponds with climbing:boulder~^..*$_This option cannot be chosen as answer_ + + + + +### Toproping? + + + +The question is **Is toprope climbing possible here?** + + + + + + - **Toprope climbing is possible here** corresponds with climbing:toprope=yes + - **Toprope climbing is not possible here** corresponds with climbing:toprope=no + - **There are {climbing:toprope} toprope routes** corresponds with climbing:toprope~^..*$_This option cannot be chosen as answer_ + + + + +### Sportclimbing? + + + +The question is **Is sport climbing possible here on fixed anchors?** + + + + + + - **Sport climbing is possible here** corresponds with climbing:sport=yes + - **Sport climbing is not possible here** corresponds with climbing:sport=no + - **There are {climbing:sport} sport climbing routes** corresponds with climbing:sport~^..*$_This option cannot be chosen as answer_ + + + + +### Traditional climbing? + + + +The question is **Is traditional climbing possible here (using own gear e.g. chocks)?** + + + + + + - **Traditional climbing is possible here** corresponds with climbing:traditional=yes + - **Traditional climbing is not possible here** corresponds with climbing:traditional=no + - **There are {climbing:traditional} traditional climbing routes** corresponds with climbing:traditional~^..*$_This option cannot be chosen as answer_ + + + + +### Speed climbing? + + + +The question is **Is there a speed climbing wall?** + + + + + + - **There is a speed climbing wall** corresponds with climbing:speed=yes + - **There is no speed climbing wall** corresponds with climbing:speed=no + - **There are {climbing:speed} speed climbing walls** corresponds with climbing:speed~^..*$_This option cannot be chosen as answer_ + + +This document is autogenerated from [assets/themes/climbing/climbing.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/climbing/climbing.json) \ No newline at end of file diff --git a/Docs/Layers/cluster_style.md b/Docs/Layers/cluster_style.md index 10d8d13a37..8e37cae340 100644 --- a/Docs/Layers/cluster_style.md +++ b/Docs/Layers/cluster_style.md @@ -12,18 +12,9 @@ The style for the clustering in all themes. Enable `debug=true` to peak into clu -## Table of contents - -1. [cluster_style](#cluster_style) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [all_tags](#all_tags) - - - + - This layer is shown at zoomlevel **0** and higher - Not visible in the layer selection by default. If you want to make this layer toggable, override `name` @@ -38,8 +29,6 @@ The style for the clustering in all themes. Enable `debug=true` to peak into clu - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/cluster_style/cluster_style.json) - Basic tags for this layer diff --git a/Docs/Layers/conflation.md b/Docs/Layers/conflation.md deleted file mode 100644 index d5f0480cdc..0000000000 --- a/Docs/Layers/conflation.md +++ /dev/null @@ -1,39 +0,0 @@ -conflation -============ - - - - - -If the import-button moves OSM points, the imported way points or conflates, a preview is shown. This layer defines how -this preview is rendered. This layer cannot be included in a theme. - -## Table of contents - -1. [conflation](#conflation) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - -[Go to the source code](../assets/layers/conflation/conflation.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- move - =yes - |newpoint - =yes - -Supported attributes ----------------------- - - - -This document is autogenerated from assets/layers/conflation/conflation.json \ No newline at end of file diff --git a/Docs/Layers/crab_address.md b/Docs/Layers/crab_address.md index 5a0f274962..dd23caa61b 100644 --- a/Docs/Layers/crab_address.md +++ b/Docs/Layers/crab_address.md @@ -12,18 +12,9 @@ Address data for Flanders by the governement, suited for import into OpenStreetM -## Table of contents - -1. [crab_address](#crab_address) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [render_crab](#render_crab) - - - + - This layer is shown at zoomlevel **0** and higher - This layer is loaded from an external source, namely `https://raw.githubusercontent.com/pietervdvn/MapComplete-data/main/CRAB_2021_10_26/tile_{z}_{x}_{y}.geojson` @@ -38,8 +29,6 @@ Address data for Flanders by the governement, suited for import into OpenStreetM - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/crab_address/crab_address.json) - Basic tags for this layer diff --git a/Docs/Layers/crossings.md b/Docs/Layers/crossings.md index 8eb2c1a2fa..8a4a8c041e 100644 --- a/Docs/Layers/crossings.md +++ b/Docs/Layers/crossings.md @@ -12,25 +12,9 @@ Crossings for pedestrians and cyclists -## Table of contents - -1. [crossings](#crossings) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [crossing-type](#crossing-type) - + [crossing-is-zebra](#crossing-is-zebra) - + [crossing-bicycle-allowed](#crossing-bicycle-allowed) - + [crossing-has-island](#crossing-has-island) - + [crossing-tactile](#crossing-tactile) - + [crossing-button](#crossing-button) - + [crossing-right-turn-through-red](#crossing-right-turn-through-red) - + [crossing-continue-through-red](#crossing-continue-through-red) - - - + - This layer is shown at zoomlevel **17** and higher - This layer will automatically load [cycleways_and_roads](./cycleways_and_roads.md) into the layout as it depends on it: a preset snaps to this layer (presets[0]) - This layer will automatically load [cycleways_and_roads](./cycleways_and_roads.md) into the layout as it depends on it: a preset snaps to this layer (presets[1]) @@ -47,8 +31,6 @@ Crossings for pedestrians and cyclists - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/crossings/crossings.json) - Basic tags for this layer diff --git a/Docs/Layers/cultural_places_without_etymology.md b/Docs/Layers/cultural_places_without_etymology.md new file mode 100644 index 0000000000..2a0bb034a8 --- /dev/null +++ b/Docs/Layers/cultural_places_without_etymology.md @@ -0,0 +1,162 @@ + + + cultural_places_without_etymology +=================================== + + + + + +All objects which have an etymology known + + + + + + + - This layer is shown at zoomlevel **18** and higher + + + + +#### Themes using this layer + + + + + + - [etymology](https://mapcomplete.osm.be/etymology) + + + + + Basic tags for this layer +--------------------------- + + + +Elements must have the all of following tags to be shown on this layer: + + + + - name~^..*$ + - amenity=arts_centre|amenity=cinema|amenity=community_centre|amenity=library|amenity=theatre + + +[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22arts_centre%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22cinema%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22community_centre%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22library%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22theatre%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) + + + + Supported attributes +---------------------- + + + +**Warning** This quick overview is incomplete + + + +attribute | type | values which are supported by this layer +----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/name:etymology:wikidata#values) [name:etymology:wikidata](https://wiki.openstreetmap.org/wiki/Key:name:etymology:wikidata) | [wikidata](../SpecialInputElements.md#wikidata) | +[](https://taginfo.openstreetmap.org/keys/name:etymology#values) [name:etymology](https://wiki.openstreetmap.org/wiki/Key:name:etymology) | [string](../SpecialInputElements.md#string) | [unknown](https://wiki.openstreetmap.org/wiki/Tag:name:etymology%3Dunknown) + + + + +### etymology-images-from-wikipedia + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### wikipedia-etymology + + + +The question is **What is the Wikidata-item that this object is named after?** + +This rendering asks information about the property [name:etymology:wikidata](https://wiki.openstreetmap.org/wiki/Key:name:etymology:wikidata) +This is rendered with `

Wikipedia article of the name giver

{wikipedia(name:etymology:wikidata):max-height:20rem}` + + + +### zoeken op inventaris onroerend erfgoed + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### simple etymology + + + +The question is **What is this object named after?
This might be written on the street name sign** + +This rendering asks information about the property [name:etymology](https://wiki.openstreetmap.org/wiki/Key:name:etymology) +This is rendered with `Named after {name:etymology}` + + + + - **The origin of this name is unknown in all literature** corresponds with name:etymology=unknown + + + + +### questions + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### street-name-sign-image + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### minimap + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### etymology_multi_apply + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### wikipedia + + + +_This tagrendering has no question and is thus read-only_ + + + +This document is autogenerated from [assets/themes/etymology/etymology.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/etymology/etymology.json) \ No newline at end of file diff --git a/Docs/Layers/current_view.md b/Docs/Layers/current_view.md deleted file mode 100644 index 2425feeca5..0000000000 --- a/Docs/Layers/current_view.md +++ /dev/null @@ -1,44 +0,0 @@ -current_view -============== - - - - - -A meta-layer which contains one single feature, namely the BBOX of the current map view. This can be used to trigger -special actions. If a popup is defined for this layer, this popup will be accessible via an extra button on screen. - -The icon on the button is the default icon of the layer, but can be customized by detecting 'button=yes'. - -## Table of contents - -1. [current_view](#current_view) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - - -- This layer is not visible by default and must be enabled in the filter by the user. -- Not visible in the layer selection by default. If you want to make this layer toggable, override `name` -- Not rendered on the map by default. If you want to rendering this on the map, override `mapRenderings` - -[Go to the source code](../assets/layers/current_view/current_view.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- current_view - =yes - -Supported attributes ----------------------- - - - -This document is autogenerated from assets/layers/current_view/current_view.json \ No newline at end of file diff --git a/Docs/Layers/cycle_highways.md b/Docs/Layers/cycle_highways.md deleted file mode 100644 index f190ce448b..0000000000 --- a/Docs/Layers/cycle_highways.md +++ /dev/null @@ -1,107 +0,0 @@ -cycle_highways -================ - -## Table of contents - -1. [cycle_highways](#cycle_highways) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [cycle_highways-name](#cycle_highways-name) - + [cycle_highways-ref](#cycle_highways-ref) - + [cycle_highways-state](#cycle_highways-state) - + [cycle-highway-length](#cycle-highway-length) - + [website](#website) - + [all_tags](#all_tags) - - -- Not rendered on the map by default. If you want to rendering this on the map, override `mapRenderings` - -[Go to the source code](../assets/layers/cycle_highways/cycle_highways.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- cycle_network - =BE-VLG: - cycle_highway - -Supported attributes ----------------------- - - - -**Warning** This quick overview is incomplete - -attribute | type | values which are supported by this layer ------------ | ------ | ------------------------------------------ -[](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | -[](https://taginfo.openstreetmap.org/keys/ref#values) [ref](https://wiki.openstreetmap.org/wiki/Key:ref) | [string](../SpecialInputElements.md#string) | -[](https://taginfo.openstreetmap.org/keys/state#values) [state](https://wiki.openstreetmap.org/wiki/Key:state) | [string](../SpecialInputElements.md#string) | [proposed](https://wiki.openstreetmap.org/wiki/Tag:state%3Dproposed) [proposed](https://wiki.openstreetmap.org/wiki/Tag:state%3Dproposed) [proposed](https://wiki.openstreetmap.org/wiki/Tag:state%3Dproposed) [temporary](https://wiki.openstreetmap.org/wiki/Tag:state%3Dtemporary) [](https://wiki.openstreetmap.org/wiki/Tag:state%3D) -[](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | - -### cycle_highways-name - -The question is **What is the name of this cycle highway?** - -This rendering asks information about the property [name](https://wiki.openstreetmap.org/wiki/Key:name) -This is rendered with `The name is {name}` - -### cycle_highways-ref - -The question is **What is the reference number of this cycle highway?** - -This rendering asks information about the property [ref](https://wiki.openstreetmap.org/wiki/Key:ref) -This is rendered with `Referentienummer is {ref}` - -### cycle_highways-state - -The question is **What is the state of this link?** - -This rendering asks information about the property [state](https://wiki.openstreetmap.org/wiki/Key:state) -This is rendered with `The current state of this link is {state}` - -- **This is a proposed route which can be cycled** corresponds - with state - =proposed -- **This is a proposed route which has missing links (thus: some parts don't even have a building permit yet)** - corresponds with state - =proposed - &note:state - =has_highway_no -- **This is a proposed route which has some links which are under construction** corresponds - with state - =proposed - &note:state - = - has_highway_under_construction -- **This is a temporary deviation** corresponds - with state - =temporary -- **This link is operational and signposted** corresponds with - -### cycle-highway-length - -_This tagrendering has no question and is thus read-only_ - -### website - -The question is **What is the website of {name}?** - -This rendering asks information about the property [website](https://wiki.openstreetmap.org/wiki/Key:website) -This is rendered with `{website}` - -- **{contact:website}** corresponds with contact:website~^..*$_This - option cannot be chosen as answer_ - -### all_tags - -_This tagrendering has no question and is thus read-only_ - -This document is autogenerated from assets/layers/cycle_highways/cycle_highways.json \ No newline at end of file diff --git a/Docs/Layers/cycleways_and_roads.md b/Docs/Layers/cycleways_and_roads.md index 25db981c39..bf812cea5e 100644 --- a/Docs/Layers/cycleways_and_roads.md +++ b/Docs/Layers/cycleways_and_roads.md @@ -12,32 +12,9 @@ All infrastructure that someone can cycle over, accompanied with questions about -## Table of contents - -1. [cycleways_and_roads](#cycleways_and_roads) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [Cycleway type for a road](#cycleway-type-for-a-road) - + [is lit?](#is-lit) - + [Is this a cyclestreet? (For a road)](#is-this-a-cyclestreet-(for-a-road)) - + [Maxspeed (for road)](#maxspeed-(for-road)) - + [Cycleway:surface](#cyclewaysurface) - + [Cycleway:smoothness](#cyclewaysmoothness) - + [Surface of the road](#surface-of-the-road) - + [Surface of the street](#surface-of-the-street) - + [width:carriageway](#widthcarriageway) - + [cycleway-lane-track-traffic-signs](#cycleway-lane-track-traffic-signs) - + [cycleway-traffic-signs](#cycleway-traffic-signs) - + [cycleway-traffic-signs-supplementary](#cycleway-traffic-signs-supplementary) - + [cycleways_and_roads-cycleway:buffer](#cycleways_and_roads-cyclewaybuffer) - + [cyclelan-segregation](#cyclelan-segregation) - + [cycleway-segregation](#cycleway-segregation) - - - + - This layer is shown at zoomlevel **16** and higher - This layer is needed as dependency for layer [barrier](#barrier) - This layer is needed as dependency for layer [crossings](#crossings) @@ -54,8 +31,6 @@ All infrastructure that someone can cycle over, accompanied with questions about - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/cycleways_and_roads/cycleways_and_roads.json) - Basic tags for this layer diff --git a/Docs/Layers/defibrillator.md b/Docs/Layers/defibrillator.md index dc04ad735c..2716008ae0 100644 --- a/Docs/Layers/defibrillator.md +++ b/Docs/Layers/defibrillator.md @@ -12,33 +12,9 @@ A layer showing defibrillators which can be used in case of emergency. This cont -## Table of contents - -1. [defibrillator](#defibrillator) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [defibrillator-indoors](#defibrillator-indoors) - + [defibrillator-access](#defibrillator-access) - + [defibrillator-defibrillator](#defibrillator-defibrillator) - + [defibrillator-level](#defibrillator-level) - + [defibrillator-defibrillator:location](#defibrillator-defibrillatorlocation) - + [defibrillator-defibrillator:location:en](#defibrillator-defibrillatorlocation:en) - + [defibrillator-defibrillator:location:fr](#defibrillator-defibrillatorlocation:fr) - + [wheelchair-access](#wheelchair-access) - + [defibrillator-ref](#defibrillator-ref) - + [defibrillator-email](#defibrillator-email) - + [defibrillator-phone](#defibrillator-phone) - + [defibrillator-opening_hours](#defibrillator-opening_hours) - + [defibrillator-description](#defibrillator-description) - + [defibrillator-survey:date](#defibrillator-surveydate) - + [defibrillator-fixme](#defibrillator-fixme) - - - + - This layer is shown at zoomlevel **12** and higher - This layer will automatically load [walls_and_buildings](./walls_and_buildings.md) into the layout as it depends on it: a preset snaps to this layer (presets[1]) @@ -54,8 +30,6 @@ A layer showing defibrillators which can be used in case of emergency. This cont - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/defibrillator/defibrillator.json) - Basic tags for this layer diff --git a/Docs/Layers/direction.md b/Docs/Layers/direction.md index 04b086b9ae..9b419f3a81 100644 --- a/Docs/Layers/direction.md +++ b/Docs/Layers/direction.md @@ -12,17 +12,9 @@ This layer visualizes directions -## Table of contents - -1. [direction](#direction) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - - - + - This layer is shown at zoomlevel **16** and higher - This layer cannot be toggled in the filter view. If you import this layer in your theme, override `title` to make this toggleable. @@ -38,8 +30,6 @@ This layer visualizes directions - [surveillance](https://mapcomplete.osm.be/surveillance) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/direction/direction.json) - Basic tags for this layer diff --git a/Docs/Layers/drinking_water.md b/Docs/Layers/drinking_water.md index e139ea2280..df7a790fd2 100644 --- a/Docs/Layers/drinking_water.md +++ b/Docs/Layers/drinking_water.md @@ -12,21 +12,9 @@ A layer showing drinking water fountains -## Table of contents - -1. [drinking_water](#drinking_water) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [Still in use?](#still-in-use) - + [Bottle refill](#bottle-refill) - + [render-closest-drinking-water](#render-closest-drinking-water) - - - + - This layer is shown at zoomlevel **13** and higher - This layer will automatically load [drinking_water](./drinking_water.md) into the layout as it depends on it: A calculated tag loads features from this layer (calculatedTag[0] which calculates the value for _closest_other_drinking_water) - This layer is needed as dependency for layer [drinking_water](#drinking_water) @@ -45,8 +33,6 @@ A layer showing drinking water fountains - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/drinking_water/drinking_water.json) - Basic tags for this layer diff --git a/Docs/Layers/dumpstations.md b/Docs/Layers/dumpstations.md index 5b4414abef..12bed82549 100644 --- a/Docs/Layers/dumpstations.md +++ b/Docs/Layers/dumpstations.md @@ -1,145 +1,233 @@ -dumpstations + + + dumpstations ============== - + Sanitary dump stations -## Table of contents - -1. [dumpstations](#dumpstations) - * [Themes using this layer](#themes-using-this-layer) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [images](#images) - + [dumpstations-fee](#dumpstations-fee) - + [dumpstations-charge](#dumpstations-charge) - + [dumpstations-waterpoint](#dumpstations-waterpoint) - + [dumpstations-grey-water](#dumpstations-grey-water) - + [dumpstations-chemical-waste](#dumpstations-chemical-waste) - + [dumpstations-access](#dumpstations-access) - + [dumpstations-network](#dumpstations-network) - -#### Themes using this layer - -- [campersite](https://mapcomplete.osm.be/campersite) - -[Go to the source code](../assets/layers/dumpstations/dumpstations.json) -Basic tags for this layer + + + - This layer is shown at zoomlevel **10** and higher + + + + +#### Themes using this layer + + + + + + - [campersite](https://mapcomplete.osm.be/campersite) + + + + + Basic tags for this layer --------------------------- Elements must have the all of following tags to be shown on this layer: -- amenity - = - sanitary_dump_station -- vehicle!~^no$ -Supported attributes + + - amenity=sanitary_dump_station + - vehicle!~^no$ + + +[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22sanitary_dump_station%22%5D%5B%22vehicle%22!~%22%5Eno%24%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) + + + + Supported attributes ---------------------- **Warning** This quick overview is incomplete + + attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ [](https://taginfo.openstreetmap.org/keys/fee#values) [fee](https://wiki.openstreetmap.org/wiki/Key:fee) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:fee%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:fee%3Dno) -[](https://taginfo.openstreetmap.org/keys/charge#values) [charge](https://wiki.openstreetmap.org/wiki/Key:charge) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/charge#values) [charge](https://wiki.openstreetmap.org/wiki/Key:charge) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/water_point#values) [water_point](https://wiki.openstreetmap.org/wiki/Key:water_point) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:water_point%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:water_point%3Dno) [](https://taginfo.openstreetmap.org/keys/sanitary_dump_station:grey_water#values) [sanitary_dump_station:grey_water](https://wiki.openstreetmap.org/wiki/Key:sanitary_dump_station:grey_water) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:sanitary_dump_station:grey_water%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:sanitary_dump_station:grey_water%3Dno) [](https://taginfo.openstreetmap.org/keys/sanitary_dump_station:chemical_toilet#values) [sanitary_dump_station:chemical_toilet](https://wiki.openstreetmap.org/wiki/Key:sanitary_dump_station:chemical_toilet) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:sanitary_dump_station:chemical_toilet%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:sanitary_dump_station:chemical_toilet%3Dno) [](https://taginfo.openstreetmap.org/keys/access#values) [access](https://wiki.openstreetmap.org/wiki/Key:access) | Multiple choice | [network](https://wiki.openstreetmap.org/wiki/Tag:access%3Dnetwork) [customers](https://wiki.openstreetmap.org/wiki/Tag:access%3Dcustomers) [yes](https://wiki.openstreetmap.org/wiki/Tag:access%3Dyes) -[](https://taginfo.openstreetmap.org/keys/network#values) [network](https://wiki.openstreetmap.org/wiki/Key:network) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/network#values) [network](https://wiki.openstreetmap.org/wiki/Key:network) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/operator#values) [operator](https://wiki.openstreetmap.org/wiki/Key:operator) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/power_supply#values) [power_supply](https://wiki.openstreetmap.org/wiki/Key:power_supply) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:power_supply%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:power_supply%3Dno) + + + + +### images + -### images _This tagrendering has no question and is thus read-only_ -### dumpstations-fee + + + + +### dumpstations-fee + + The question is **Does this place charge a fee?** -- **You need to pay for use** corresponds with - fee=yes -- **Can be used for free** corresponds with - fee=no -### dumpstations-charge + + + + - **You need to pay for use** corresponds with fee=yes + - **Can be used for free** corresponds with fee=no + + + + +### dumpstations-charge + + The question is **How much does this place charge?** -This rendering asks information about the property [charge](https://wiki.openstreetmap.org/wiki/Key:charge) +This rendering asks information about the property [charge](https://wiki.openstreetmap.org/wiki/Key:charge) This is rendered with `This place charges {charge}` -### dumpstations-waterpoint + + +### dumpstations-waterpoint + + The question is **Does this place have a water point?** -- **This place has a water point** corresponds - with water_point - =yes -- **This place does not have a water point** corresponds - with water_point - =no -### dumpstations-grey-water + + + + - **This place has a water point** corresponds with water_point=yes + - **This place does not have a water point** corresponds with water_point=no + + + + +### dumpstations-grey-water + + The question is **Can you dispose of grey water here?** -- **You can dispose of grey water here** corresponds - with - sanitary_dump_station:grey_water - =yes -- **You cannot dispose of gray water here** corresponds - with - sanitary_dump_station:grey_water - =no -### dumpstations-chemical-waste + + + + - **You can dispose of grey water here** corresponds with sanitary_dump_station:grey_water=yes + - **You cannot dispose of gray water here** corresponds with sanitary_dump_station:grey_water=no + + + + +### dumpstations-chemical-waste + + The question is **Can you dispose of chemical toilet waste here?** -- **You can dispose of chemical toilet waste here** corresponds - with - sanitary_dump_station:chemical_toilet - =yes -- **You cannot dispose of chemical toilet waste here** corresponds - with - sanitary_dump_station:chemical_toilet - =no -### dumpstations-access + + + + - **You can dispose of chemical toilet waste here** corresponds with sanitary_dump_station:chemical_toilet=yes + - **You cannot dispose of chemical toilet waste here** corresponds with sanitary_dump_station:chemical_toilet=no + + + + +### dumpstations-access + + The question is **Who can use this dump station?** -- **You need a network key/code to use this** corresponds - with access - =network -- **You need to be a customer of camping/campersite to use this place** corresponds - with access - =customers -- **Anyone can use this dump station** corresponds - with access - =public_This option cannot be - chosen as answer_ -- **Anyone can use this dump station** corresponds - with access - =yes -### dumpstations-network + + + + - **You need a network key/code to use this** corresponds with access=network + - **You need to be a customer of camping/campersite to use this place** corresponds with access=customers + - **Anyone can use this dump station** corresponds with access=public_This option cannot be chosen as answer_ + - **Anyone can use this dump station** corresponds with access=yes + + + + +### dumpstations-network + + The question is **What network is this place a part of? (skip if none)** -This rendering asks information about the property [network](https://wiki.openstreetmap.org/wiki/Key:network) +This rendering asks information about the property [network](https://wiki.openstreetmap.org/wiki/Key:network) This is rendered with `This station is part of network {network}` -This document is autogenerated from assets/layers/dumpstations/dumpstations.json \ No newline at end of file + + +### operator + + + +The question is **Who operates this place?** + +This rendering asks information about the property [operator](https://wiki.openstreetmap.org/wiki/Key:operator) +This is rendered with `This place is operated by {operator}` + + + +### power_supply + + + +The question is **Does this place have a power supply?** + + + + + + - **This place has a power supply** corresponds with power_supply=yes + - **This place does not have power supply** corresponds with power_supply=no + + + + +### questions + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### minimap + + + +_This tagrendering has no question and is thus read-only_ + + + +This document is autogenerated from [assets/themes/campersite/campersite.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/campersite/campersite.json) \ No newline at end of file diff --git a/Docs/Layers/education_institutions_without_etymology.md b/Docs/Layers/education_institutions_without_etymology.md new file mode 100644 index 0000000000..b4555ec049 --- /dev/null +++ b/Docs/Layers/education_institutions_without_etymology.md @@ -0,0 +1,162 @@ + + + education_institutions_without_etymology +========================================== + + + + + +All objects which have an etymology known + + + + + + + - This layer is shown at zoomlevel **18** and higher + + + + +#### Themes using this layer + + + + + + - [etymology](https://mapcomplete.osm.be/etymology) + + + + + Basic tags for this layer +--------------------------- + + + +Elements must have the all of following tags to be shown on this layer: + + + + - name~^..*$ + - amenity=school|amenity=kindergarten|amenity=university|amenity=college|landuse=education + + +[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22school%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22kindergarten%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22university%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22college%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22landuse%22%3D%22education%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) + + + + Supported attributes +---------------------- + + + +**Warning** This quick overview is incomplete + + + +attribute | type | values which are supported by this layer +----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/name:etymology:wikidata#values) [name:etymology:wikidata](https://wiki.openstreetmap.org/wiki/Key:name:etymology:wikidata) | [wikidata](../SpecialInputElements.md#wikidata) | +[](https://taginfo.openstreetmap.org/keys/name:etymology#values) [name:etymology](https://wiki.openstreetmap.org/wiki/Key:name:etymology) | [string](../SpecialInputElements.md#string) | [unknown](https://wiki.openstreetmap.org/wiki/Tag:name:etymology%3Dunknown) + + + + +### etymology-images-from-wikipedia + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### wikipedia-etymology + + + +The question is **What is the Wikidata-item that this object is named after?** + +This rendering asks information about the property [name:etymology:wikidata](https://wiki.openstreetmap.org/wiki/Key:name:etymology:wikidata) +This is rendered with `

Wikipedia article of the name giver

{wikipedia(name:etymology:wikidata):max-height:20rem}` + + + +### zoeken op inventaris onroerend erfgoed + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### simple etymology + + + +The question is **What is this object named after?
This might be written on the street name sign** + +This rendering asks information about the property [name:etymology](https://wiki.openstreetmap.org/wiki/Key:name:etymology) +This is rendered with `Named after {name:etymology}` + + + + - **The origin of this name is unknown in all literature** corresponds with name:etymology=unknown + + + + +### questions + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### street-name-sign-image + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### minimap + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### etymology_multi_apply + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### wikipedia + + + +_This tagrendering has no question and is thus read-only_ + + + +This document is autogenerated from [assets/themes/etymology/etymology.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/etymology/etymology.json) \ No newline at end of file diff --git a/Docs/Layers/entrance.md b/Docs/Layers/entrance.md index fa867ae210..fe78376551 100644 --- a/Docs/Layers/entrance.md +++ b/Docs/Layers/entrance.md @@ -12,22 +12,9 @@ A layer showing entrances and offering capabilities to survey some advanced data -## Table of contents - -1. [entrance](#entrance) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [Entrance type](#entrance-type) - + [Door_type](#door_type) - + [automatic_door](#automatic_door) - + [width](#width) - - - + - This layer is shown at zoomlevel **14** and higher - This layer will automatically load [walls_and_buildings](./walls_and_buildings.md) into the layout as it depends on it: a preset snaps to this layer (presets[0]) - This layer will automatically load [pedestrian_path](./pedestrian_path.md) into the layout as it depends on it: a preset snaps to this layer (presets[0]) @@ -44,8 +31,6 @@ A layer showing entrances and offering capabilities to survey some advanced data - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/entrance/entrance.json) - Basic tags for this layer diff --git a/Docs/Layers/etymology.md b/Docs/Layers/etymology.md index 79bedbca64..f2766a3ec2 100644 --- a/Docs/Layers/etymology.md +++ b/Docs/Layers/etymology.md @@ -12,27 +12,9 @@ All objects which have an etymology known -## Table of contents - -1. [etymology](#etymology) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [etymology-images-from-wikipedia](#etymology-images-from-wikipedia) - + [wikipedia-etymology](#wikipedia-etymology) - + [zoeken op inventaris onroerend erfgoed](#zoeken-op-inventaris-onroerend-erfgoed) - + [simple etymology](#simple-etymology) - + [questions](#questions) - + [street-name-sign-image](#street-name-sign-image) - + [minimap](#minimap) - + [etymology_multi_apply](#etymology_multi_apply) - + [wikipedia](#wikipedia) - - - - + - This layer is shown at zoomlevel **12** and higher @@ -47,8 +29,6 @@ All objects which have an etymology known - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/etymology/etymology.json) - Basic tags for this layer diff --git a/Docs/Layers/extinguisher.md b/Docs/Layers/extinguisher.md index a671eb662a..394ec9bf1b 100644 --- a/Docs/Layers/extinguisher.md +++ b/Docs/Layers/extinguisher.md @@ -12,20 +12,9 @@ Map layer to show fire extinguishers. -## Table of contents - -1. [extinguisher](#extinguisher) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [extinguisher-location](#extinguisher-location) - + [images](#images) - - - - + - This layer is shown at zoomlevel **14** and higher @@ -40,8 +29,6 @@ Map layer to show fire extinguishers. - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/extinguisher/extinguisher.json) - Basic tags for this layer diff --git a/Docs/Layers/facadegardens.md b/Docs/Layers/facadegardens.md index e29139bfa4..c207a738c8 100644 --- a/Docs/Layers/facadegardens.md +++ b/Docs/Layers/facadegardens.md @@ -1,138 +1,200 @@ -facadegardens + + + facadegardens =============== - + Facade gardens -## Table of contents - -1. [facadegardens](#facadegardens) - * [Themes using this layer](#themes-using-this-layer) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [images](#images) - + [facadegardens-direction](#facadegardens-direction) - + [facadegardens-sunshine](#facadegardens-sunshine) - + [facadegardens-rainbarrel](#facadegardens-rainbarrel) - + [facadegardens-start_date](#facadegardens-start_date) - + [facadegardens-edible](#facadegardens-edible) - + [facadegardens-plants](#facadegardens-plants) - + [facadegardens-description](#facadegardens-description) - -#### Themes using this layer - -- [facadegardens](https://mapcomplete.osm.be/facadegardens) - -[Go to the source code](../assets/layers/facadegardens/facadegardens.json) -Basic tags for this layer + + + - This layer is shown at zoomlevel **12** and higher + + + + +#### Themes using this layer + + + + + + - [facadegardens](https://mapcomplete.osm.be/facadegardens) + + + + + Basic tags for this layer --------------------------- Elements must have the all of following tags to be shown on this layer: -- leisure - =garden -- garden:type - =facade_garden -Supported attributes + + - leisure=garden + - garden:type=facade_garden + + +[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22garden%3Atype%22%3D%22facade_garden%22%5D%5B%22leisure%22%3D%22garden%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) + + + + Supported attributes ---------------------- **Warning** This quick overview is incomplete + + attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ -[](https://taginfo.openstreetmap.org/keys/direction#values) [direction](https://wiki.openstreetmap.org/wiki/Key:direction) | [direction](../SpecialInputElements.md#direction) | +[](https://taginfo.openstreetmap.org/keys/direction#values) [direction](https://wiki.openstreetmap.org/wiki/Key:direction) | [direction](../SpecialInputElements.md#direction) | [](https://taginfo.openstreetmap.org/keys/direct_sunlight#values) [direct_sunlight](https://wiki.openstreetmap.org/wiki/Key:direct_sunlight) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:direct_sunlight%3Dyes) [partial](https://wiki.openstreetmap.org/wiki/Tag:direct_sunlight%3Dpartial) [no](https://wiki.openstreetmap.org/wiki/Tag:direct_sunlight%3Dno) [](https://taginfo.openstreetmap.org/keys/rain_barrel#values) [rain_barrel](https://wiki.openstreetmap.org/wiki/Key:rain_barrel) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:rain_barrel%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:rain_barrel%3Dno) -[](https://taginfo.openstreetmap.org/keys/start_date#values) [start_date](https://wiki.openstreetmap.org/wiki/Key:start_date) | [text](../SpecialInputElements.md#text) | +[](https://taginfo.openstreetmap.org/keys/start_date#values) [start_date](https://wiki.openstreetmap.org/wiki/Key:start_date) | [text](../SpecialInputElements.md#text) | [](https://taginfo.openstreetmap.org/keys/edible#values) [edible](https://wiki.openstreetmap.org/wiki/Key:edible) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:edible%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:edible%3Dno) [](https://taginfo.openstreetmap.org/keys/plant#values) [plant](https://wiki.openstreetmap.org/wiki/Key:plant) | Multiple choice | [vine](https://wiki.openstreetmap.org/wiki/Tag:plant%3Dvine) [flower](https://wiki.openstreetmap.org/wiki/Tag:plant%3Dflower) [shrub](https://wiki.openstreetmap.org/wiki/Tag:plant%3Dshrub) [groundcover](https://wiki.openstreetmap.org/wiki/Tag:plant%3Dgroundcover) -[](https://taginfo.openstreetmap.org/keys/description#values) [description](https://wiki.openstreetmap.org/wiki/Key:description) | [text](../SpecialInputElements.md#text) | +[](https://taginfo.openstreetmap.org/keys/description#values) [description](https://wiki.openstreetmap.org/wiki/Key:description) | [text](../SpecialInputElements.md#text) | + + + + +### images + -### images _This tagrendering has no question and is thus read-only_ -### facadegardens-direction + + + + +### facadegardens-direction + + The question is **What is the orientation of the garden?** -This rendering asks information about the property [direction](https://wiki.openstreetmap.org/wiki/Key:direction) +This rendering asks information about the property [direction](https://wiki.openstreetmap.org/wiki/Key:direction) This is rendered with `Orientation: {direction} (where 0=N and 90=O)` -### facadegardens-sunshine + + +### facadegardens-sunshine + + The question is **Is the garden shaded or sunny?** -- **The garden is in full sun** corresponds - with direct_sunlight - =yes -- **The garden is in partial shade** corresponds - with direct_sunlight - =partial -- **The garden is in the shade** corresponds - with direct_sunlight - =no -### facadegardens-rainbarrel + + + + - **The garden is in full sun** corresponds with direct_sunlight=yes + - **The garden is in partial shade** corresponds with direct_sunlight=partial + - **The garden is in the shade** corresponds with direct_sunlight=no + + + + +### facadegardens-rainbarrel + + The question is **Is there a water barrel installed for the garden?** -- **There is a rain barrel** corresponds - with rain_barrel - =yes -- **There is no rain barrel** corresponds - with rain_barrel - =no -### facadegardens-start_date + + + + - **There is a rain barrel** corresponds with rain_barrel=yes + - **There is no rain barrel** corresponds with rain_barrel=no + + + + +### facadegardens-start_date + + The question is **When was the garden constructed? (a year is sufficient)** -This rendering asks information about the property [start_date](https://wiki.openstreetmap.org/wiki/Key:start_date) +This rendering asks information about the property [start_date](https://wiki.openstreetmap.org/wiki/Key:start_date) This is rendered with `Construction date of the garden: {start_date}` -### facadegardens-edible + + +### facadegardens-edible + + The question is **Are there any edible plants?** -- **There are edible plants** corresponds with - edible=yes -- **There are no edible plants** corresponds - with edible - =no -### facadegardens-plants + + + + - **There are edible plants** corresponds with edible=yes + - **There are no edible plants** corresponds with edible=no + + + + +### facadegardens-plants + + The question is **What kinds of plants grow here?** -- **There are vines** corresponds with plant - =vine -- **There are flowering plants** corresponds - with plant - =flower -- **There are shrubs** corresponds with - plant=shrub -- **There are groundcovering plants** corresponds - with plant - =groundcover -### facadegardens-description + + + + - **There are vines** corresponds with plant=vine + - **There are flowering plants** corresponds with plant=flower + - **There are shrubs** corresponds with plant=shrub + - **There are groundcovering plants** corresponds with plant=groundcover + + + + +### facadegardens-description + + The question is **Extra describing info about the garden (if needed and not yet described above)** -This rendering asks information about the property [description](https://wiki.openstreetmap.org/wiki/Key:description) +This rendering asks information about the property [description](https://wiki.openstreetmap.org/wiki/Key:description) This is rendered with `More details: {description}` -This document is autogenerated from assets/layers/facadegardens/facadegardens.json \ No newline at end of file + + +### questions + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### minimap + + + +_This tagrendering has no question and is thus read-only_ + + + +This document is autogenerated from [assets/themes/facadegardens/facadegardens.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/facadegardens/facadegardens.json) \ No newline at end of file diff --git a/Docs/Layers/fietsstraat.md b/Docs/Layers/fietsstraat.md index 327223b219..37ff789bcd 100644 --- a/Docs/Layers/fietsstraat.md +++ b/Docs/Layers/fietsstraat.md @@ -1,4 +1,6 @@ -fietsstraat + + + fietsstraat ============= @@ -7,38 +9,115 @@ fietsstraat A cyclestreet is a street where motorized traffic is not allowed to overtake a cyclist -## Table of contents - -1. [fietsstraat](#fietsstraat) - * [Themes using this layer](#themes-using-this-layer) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [images](#images) - -#### Themes using this layer - -- [cyclestreets](https://mapcomplete.osm.be/cyclestreets) - -[Go to the source code](../assets/layers/fietsstraat/fietsstraat.json) -Basic tags for this layer + + + - This layer is shown at zoomlevel **7** and higher + + + + +#### Themes using this layer + + + + + + - [cyclestreets](https://mapcomplete.osm.be/cyclestreets) + + + + + Basic tags for this layer --------------------------- Elements must have the all of following tags to be shown on this layer: -- cyclestreet - =yes -Supported attributes + + - cyclestreet=yes + + +[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22cyclestreet%22%3D%22yes%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) + + + + Supported attributes ---------------------- -### images + + +**Warning** This quick overview is incomplete + + + +attribute | type | values which are supported by this layer +----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/cyclestreet#values) [cyclestreet](https://wiki.openstreetmap.org/wiki/Key:cyclestreet) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:cyclestreet%3Dyes) [yes](https://wiki.openstreetmap.org/wiki/Tag:cyclestreet%3Dyes) [](https://wiki.openstreetmap.org/wiki/Tag:cyclestreet%3D) [](https://wiki.openstreetmap.org/wiki/Tag:cyclestreet%3D) +[](https://taginfo.openstreetmap.org/keys/cyclestreet:start_date#values) [cyclestreet:start_date](https://wiki.openstreetmap.org/wiki/Key:cyclestreet:start_date) | [date](../SpecialInputElements.md#date) | + + + + +### images + + _This tagrendering has no question and is thus read-only_ -This document is autogenerated from assets/layers/fietsstraat/fietsstraat.json \ No newline at end of file + + + + +### is_cyclestreet + + + +The question is **Is the street {name} a cyclestreet?** + + + + + + - **This street is a cyclestreet (and has a speed limit of 30 km/h)** corresponds with cyclestreet=yes&maxspeed=30&overtaking:motor_vehicle=no + - **This street is a cyclestreet** corresponds with cyclestreet=yes + - **This street will become a cyclstreet soon** corresponds with proposed:cyclestreet=yes + - **This street is not a cyclestreet** corresponds with + + + + +### future_cyclestreet + + + +The question is **When will this street become a cyclestreet?** + +This rendering asks information about the property [cyclestreet:start_date](https://wiki.openstreetmap.org/wiki/Key:cyclestreet:start_date) +This is rendered with `This street will become a cyclestreet at {cyclestreet:start_date}` + + + +### questions + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### minimap + + + +_This tagrendering has no question and is thus read-only_ + + + +This document is autogenerated from [assets/themes/cyclestreets/cyclestreets.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/cyclestreets/cyclestreets.json) \ No newline at end of file diff --git a/Docs/Layers/fire_station.md b/Docs/Layers/fire_station.md index 3c3a784cad..36a76ced97 100644 --- a/Docs/Layers/fire_station.md +++ b/Docs/Layers/fire_station.md @@ -12,24 +12,9 @@ Map layer to show fire stations. -## Table of contents - -1. [fire_station](#fire_station) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [station-name](#station-name) - + [station-street](#station-street) - + [station-place](#station-place) - + [station-agency](#station-agency) - + [station-operator](#station-operator) - + [images](#images) - - - - + - This layer is shown at zoomlevel **12** and higher @@ -44,8 +29,6 @@ Map layer to show fire stations. - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/fire_station/fire_station.json) - Basic tags for this layer diff --git a/Docs/Layers/food.md b/Docs/Layers/food.md index 390468ab90..b6f2ad1ff3 100644 --- a/Docs/Layers/food.md +++ b/Docs/Layers/food.md @@ -12,39 +12,9 @@ A layer showing restaurants and fast-food amenities (with a special rendering fo -## Table of contents - -1. [food](#food) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [Name](#name) - + [Fastfood vs restaurant](#fastfood-vs-restaurant) - + [opening_hours](#opening_hours) - + [website](#website) - + [email](#email) - + [phone](#phone) - + [payment-options](#payment-options) - + [wheelchair-access](#wheelchair-access) - + [Cuisine](#cuisine) - + [Takeaway](#takeaway) - + [Vegetarian (no friture)](#vegetarian-(no-friture)) - + [Vegan (no friture)](#vegan-(no-friture)) - + [halal (no friture)](#halal-(no-friture)) - + [friture-vegetarian](#friture-vegetarian) - + [friture-vegan](#friture-vegan) - + [friture-oil](#friture-oil) - + [friture-take-your-container](#friture-take-your-container) - + [service:electricity](#serviceelectricity) - + [dog-access](#dog-access) - + [reviews](#reviews) - - - - + - This layer is shown at zoomlevel **12** and higher @@ -60,8 +30,6 @@ A layer showing restaurants and fast-food amenities (with a special rendering fo - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/food/food.json) - Basic tags for this layer diff --git a/Docs/Layers/forest.md b/Docs/Layers/forest.md deleted file mode 100644 index 6688ee8c4a..0000000000 --- a/Docs/Layers/forest.md +++ /dev/null @@ -1,50 +0,0 @@ -forest -======== - - - - - -Een bos is een verzameling bomen, al dan niet als productiehout. - -## Table of contents - -1. [forest](#forest) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [images](#images) - - -- This layer will automatically load [parks](./parks.md) into the layout as it depends on it: A calculated tag loads - features from this layer (calculatedTag[0] which calculates the value for _overlapWithUpperLayers) -- This layer will automatically load [nature_reserve_buurtnatuur](./nature_reserve_buurtnatuur.md) into the layout as - it depends on it: A calculated tag loads features from this layer (calculatedTag[0] which calculates the value for _ - overlapWithUpperLayers) - -[Go to the source code](../assets/layers/forest/forest.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- landuse - =forest - |natural - =wood - |natural - =scrub - -Supported attributes ----------------------- - -### images - -_This tagrendering has no question and is thus read-only_ - -This document is autogenerated from assets/layers/forest/forest.json \ No newline at end of file diff --git a/Docs/Layers/friture.md b/Docs/Layers/friture.md new file mode 100644 index 0000000000..cf8d6024f0 --- /dev/null +++ b/Docs/Layers/friture.md @@ -0,0 +1,445 @@ + + + friture +========= + + + + + +A layer showing restaurants and fast-food amenities (with a special rendering for friteries) + + + + + + + - This layer is shown at zoomlevel **12** and higher + + + + +#### Themes using this layer + + + + + + - [fritures](https://mapcomplete.osm.be/fritures) + + + + + Basic tags for this layer +--------------------------- + + + +Elements must have the all of following tags to be shown on this layer: + + + + - cuisine=friture + - amenity=fast_food|amenity=restaurant + + +[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22cuisine%22%3D%22friture%22%5D%5B%22amenity%22%3D%22fast_food%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22cuisine%22%3D%22friture%22%5D%5B%22amenity%22%3D%22restaurant%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) + + + + Supported attributes +---------------------- + + + +**Warning** This quick overview is incomplete + + + +attribute | type | values which are supported by this layer +----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/amenity#values) [amenity](https://wiki.openstreetmap.org/wiki/Key:amenity) | Multiple choice | [fast_food](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dfast_food) [restaurant](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Drestaurant) +[](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | +[](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | +[](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | +[](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | +[](https://taginfo.openstreetmap.org/keys/wheelchair#values) [wheelchair](https://wiki.openstreetmap.org/wiki/Key:wheelchair) | Multiple choice | [designated](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Ddesignated) [yes](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Dyes) [limited](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Dlimited) [no](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Dno) +[](https://taginfo.openstreetmap.org/keys/cuisine#values) [cuisine](https://wiki.openstreetmap.org/wiki/Key:cuisine) | [string](../SpecialInputElements.md#string) | [pizza](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dpizza) [friture](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dfriture) [pasta](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dpasta) [kebab](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dkebab) [sandwich](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dsandwich) [burger](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dburger) [sushi](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dsushi) [coffee](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dcoffee) [italian](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Ditalian) [french](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dfrench) [chinese](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dchinese) [greek](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dgreek) [indian](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dindian) [turkish](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dturkish) [thai](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dthai) +[](https://taginfo.openstreetmap.org/keys/takeaway#values) [takeaway](https://wiki.openstreetmap.org/wiki/Key:takeaway) | Multiple choice | [only](https://wiki.openstreetmap.org/wiki/Tag:takeaway%3Donly) [yes](https://wiki.openstreetmap.org/wiki/Tag:takeaway%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:takeaway%3Dno) +[](https://taginfo.openstreetmap.org/keys/diet:vegetarian#values) [diet:vegetarian](https://wiki.openstreetmap.org/wiki/Key:diet:vegetarian) | Multiple choice | [no](https://wiki.openstreetmap.org/wiki/Tag:diet:vegetarian%3Dno) [limited](https://wiki.openstreetmap.org/wiki/Tag:diet:vegetarian%3Dlimited) [yes](https://wiki.openstreetmap.org/wiki/Tag:diet:vegetarian%3Dyes) [only](https://wiki.openstreetmap.org/wiki/Tag:diet:vegetarian%3Donly) +[](https://taginfo.openstreetmap.org/keys/diet:vegan#values) [diet:vegan](https://wiki.openstreetmap.org/wiki/Key:diet:vegan) | Multiple choice | [no](https://wiki.openstreetmap.org/wiki/Tag:diet:vegan%3Dno) [limited](https://wiki.openstreetmap.org/wiki/Tag:diet:vegan%3Dlimited) [yes](https://wiki.openstreetmap.org/wiki/Tag:diet:vegan%3Dyes) [only](https://wiki.openstreetmap.org/wiki/Tag:diet:vegan%3Donly) +[](https://taginfo.openstreetmap.org/keys/diet:halal#values) [diet:halal](https://wiki.openstreetmap.org/wiki/Key:diet:halal) | Multiple choice | [no](https://wiki.openstreetmap.org/wiki/Tag:diet:halal%3Dno) [limited](https://wiki.openstreetmap.org/wiki/Tag:diet:halal%3Dlimited) [yes](https://wiki.openstreetmap.org/wiki/Tag:diet:halal%3Dyes) [only](https://wiki.openstreetmap.org/wiki/Tag:diet:halal%3Donly) +[](https://taginfo.openstreetmap.org/keys/diet:vegetarian#values) [diet:vegetarian](https://wiki.openstreetmap.org/wiki/Key:diet:vegetarian) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:diet:vegetarian%3Dyes) [limited](https://wiki.openstreetmap.org/wiki/Tag:diet:vegetarian%3Dlimited) [no](https://wiki.openstreetmap.org/wiki/Tag:diet:vegetarian%3Dno) +[](https://taginfo.openstreetmap.org/keys/diet:vegan#values) [diet:vegan](https://wiki.openstreetmap.org/wiki/Key:diet:vegan) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:diet:vegan%3Dyes) [limited](https://wiki.openstreetmap.org/wiki/Tag:diet:vegan%3Dlimited) [no](https://wiki.openstreetmap.org/wiki/Tag:diet:vegan%3Dno) +[](https://taginfo.openstreetmap.org/keys/friture:oil#values) [friture:oil](https://wiki.openstreetmap.org/wiki/Key:friture:oil) | Multiple choice | [vegetable](https://wiki.openstreetmap.org/wiki/Tag:friture:oil%3Dvegetable) [animal](https://wiki.openstreetmap.org/wiki/Tag:friture:oil%3Danimal) +[](https://taginfo.openstreetmap.org/keys/reusable_packaging:accept#values) [reusable_packaging:accept](https://wiki.openstreetmap.org/wiki/Key:reusable_packaging:accept) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:reusable_packaging:accept%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:reusable_packaging:accept%3Dno) [only](https://wiki.openstreetmap.org/wiki/Tag:reusable_packaging:accept%3Donly) +[](https://taginfo.openstreetmap.org/keys/service:electricity#values) [service:electricity](https://wiki.openstreetmap.org/wiki/Key:service:electricity) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:service:electricity%3Dyes) [limited](https://wiki.openstreetmap.org/wiki/Tag:service:electricity%3Dlimited) [ask](https://wiki.openstreetmap.org/wiki/Tag:service:electricity%3Dask) [no](https://wiki.openstreetmap.org/wiki/Tag:service:electricity%3Dno) +[](https://taginfo.openstreetmap.org/keys/dog#values) [dog](https://wiki.openstreetmap.org/wiki/Key:dog) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:dog%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:dog%3Dno) [leashed](https://wiki.openstreetmap.org/wiki/Tag:dog%3Dleashed) [unleashed](https://wiki.openstreetmap.org/wiki/Tag:dog%3Dunleashed) + + + + +### images + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### Name + + + +The question is **What is the name of this restaurant?** + +This rendering asks information about the property [name](https://wiki.openstreetmap.org/wiki/Key:name) +This is rendered with `The name of this restaurant is {name}` + + + +### Fastfood vs restaurant + + + +The question is **What type of business is this?** + + + + + + - **This is a fastfood-business, focussed on fast service. If seating is available, these are rather limited and functional.** corresponds with amenity=fast_food + - **A restaurant, focussed on creating a nice experience where one is served at the table** corresponds with amenity=restaurant + + + + +### opening_hours + + + +The question is **What are the opening hours of {title()}?** + +This rendering asks information about the property [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) +This is rendered with `

Opening hours

{opening_hours_table(opening_hours)}` + + + +### website + + + +The question is **What is the website of {title()}?** + +This rendering asks information about the property [website](https://wiki.openstreetmap.org/wiki/Key:website) +This is rendered with `{website}` + + + + - **{contact:website}** corresponds with contact:website~^..*$_This option cannot be chosen as answer_ + + + + +### email + + + +The question is **What is the email address of {title()}?** + +This rendering asks information about the property [email](https://wiki.openstreetmap.org/wiki/Key:email) +This is rendered with `{email}` + + + + - **{contact:email}** corresponds with contact:email~^..*$_This option cannot be chosen as answer_ + + + + +### phone + + + +The question is **What is the phone number of {title()}?** + +This rendering asks information about the property [phone](https://wiki.openstreetmap.org/wiki/Key:phone) +This is rendered with `{phone}` + + + + - **{contact:phone}** corresponds with contact:phone~^..*$_This option cannot be chosen as answer_ + + + + +### payment-options + + + +The question is **Which methods of payment are accepted here?** + + + + + + - **Cash is accepted here** corresponds with payment:cash=yesUnselecting this answer will add payment:cash=no + - **Payment cards are accepted here** corresponds with payment:cards=yesUnselecting this answer will add payment:cards=no + + + + +### wheelchair-access + + + +The question is **Is this place accessible with a wheelchair?** + + + + + + - **This place is specially adapted for wheelchair users** corresponds with wheelchair=designated + - **This place is easily reachable with a wheelchair** corresponds with wheelchair=yes + - **It is possible to reach this place in a wheelchair, but it is not easy** corresponds with wheelchair=limited + - **This place is not reachable with a wheelchair** corresponds with wheelchair=no + + + + +### Cuisine + + + +The question is **Which food is served here?** + +This rendering asks information about the property [cuisine](https://wiki.openstreetmap.org/wiki/Key:cuisine) +This is rendered with `This place mostly serves {cuisine}` + + + + - **This is a pizzeria** corresponds with cuisine=pizza + - **This is a friture** corresponds with cuisine=friture + - **Mainly serves pasta** corresponds with cuisine=pasta + - **This is kebab shop** corresponds with cuisine=kebab + - **This is a sandwichbar** corresponds with cuisine=sandwich + - **Burgers are served here** corresponds with cuisine=burger + - **Sushi is served here** corresponds with cuisine=sushi + - **Coffee is served here** corresponds with cuisine=coffee + - **This is an italian restaurant (which serves more then pasta and pizza)** corresponds with cuisine=italian + - **French dishes are served here** corresponds with cuisine=french + - **Chinese dishes are served here** corresponds with cuisine=chinese + - **Greek dishes are served here** corresponds with cuisine=greek + - **Indian dishes are served here** corresponds with cuisine=indian + - **Turkish dishes are served here** corresponds with cuisine=turkish + - **Thai dishes are served here** corresponds with cuisine=thai + + + + +### Takeaway + + + +The question is **Does this place offer takea-way?** + + + + + + - **This is a take-away only business** corresponds with takeaway=only + - **Take-away is possible here** corresponds with takeaway=yes + - **Take-away is not possible here** corresponds with takeaway=no + + + + +### Vegetarian (no friture) + + + +The question is **Does this restaurant have a vegetarian option?** + + + + + + - **No vegetarian options are available** corresponds with diet:vegetarian=no + - **Some vegetarian options are available** corresponds with diet:vegetarian=limited + - **Vegetarian options are available** corresponds with diet:vegetarian=yes + - **All dishes are vegetarian** corresponds with diet:vegetarian=only + + + + +### Vegan (no friture) + + + +The question is **Does this business serve vegan meals?** + + + + + + - **No vegan options available** corresponds with diet:vegan=no + - **Some vegan options are available** corresponds with diet:vegan=limited + - **Vegan options are available** corresponds with diet:vegan=yes + - **All dishes are vegan** corresponds with diet:vegan=only + + + + +### halal (no friture) + + + +The question is **Does this restaurant offer a halal menu?** + + + + + + - **There are no halal options available** corresponds with diet:halal=no + - **There is a small halal menu** corresponds with diet:halal=limited + - **There is a halal menu** corresponds with diet:halal=yes + - **Only halal options are available** corresponds with diet:halal=only + + + + +### friture-vegetarian + + + +The question is **Does this fries shop have vegetarian snacks?** + + + + + + - **Vegetarian snacks are available** corresponds with diet:vegetarian=yes + - **Only a small selection of snacks are vegetarian** corresponds with diet:vegetarian=limited + - **No vegetarian snacks are available** corresponds with diet:vegetarian=no + + + + +### friture-vegan + + + +The question is **Does this fries shop have vegan snacks?** + + + + + + - **Vegan snacks are available** corresponds with diet:vegan=yes + - **A small selection of vegan snacks are available** corresponds with diet:vegan=limited + - **No vegan snacks are available** corresponds with diet:vegan=no + + + + +### friture-oil + + + +The question is **Does this fries shop use vegetable or animal cooking?** + + + + + + - **Vegetable oil** corresponds with friture:oil=vegetable + - **Animal oil** corresponds with friture:oil=animal + + + + +### friture-take-your-container + + + +The question is **If you bring your own container (such as a cooking pot and small pots), is it used to package your order?
** + + + + + + - **You can bring your own containers to get your order, saving on single-use packaging material and thus waste** corresponds with reusable_packaging:accept=yes + - **Bringing your own container is not allowed** corresponds with reusable_packaging:accept=no + - **You must bring your own container to order here.** corresponds with reusable_packaging:accept=only + + + + +### service:electricity + + + +The question is **Does this amenity have electrical outlets, available to customers when they are inside?** + + + + + + - **There are plenty of domestic sockets available to customers seated indoors, where they can charge their electronics** corresponds with service:electricity=yes + - **There are a few domestic sockets available to customers seated indoors, where they can charge their electronics** corresponds with service:electricity=limited + - **There are no sockets available indoors to customers, but charging might be possible if the staff is asked** corresponds with service:electricity=ask + - **There are a no domestic sockets available to customers seated indoors** corresponds with service:electricity=no + + + + +### dog-access + + + +The question is **Are dogs allowed in this business?** + + + + + + - **Dogs are allowed** corresponds with dog=yes + - **Dogs are not allowed** corresponds with dog=no + - **Dogs are allowed, but they have to be leashed** corresponds with dog=leashed + - **Dogs are allowed and can run around freely** corresponds with dog=unleashed + + + + +### reviews + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### questions + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### minimap + + + +_This tagrendering has no question and is thus read-only_ + + + +This document is autogenerated from [assets/themes/fritures/fritures.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/fritures/fritures.json) \ No newline at end of file diff --git a/Docs/Layers/fruitboom.md b/Docs/Layers/fruitboom.md deleted file mode 100644 index e1ded5c7c3..0000000000 --- a/Docs/Layers/fruitboom.md +++ /dev/null @@ -1,77 +0,0 @@ -fruitboom -=========== - - - - - -Een boom - -## Table of contents - -1. [fruitboom](#fruitboom) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [fruitboom-species:nl](#fruitboom-speciesnl) - + [fruitboom-taxon](#fruitboom-taxon) - + [fruitboom-description](#fruitboom-description) - + [fruitboom-ref](#fruitboom-ref) - -[Go to the source code](../assets/layers/fruitboom/fruitboom.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- natural - =tree - -Supported attributes ----------------------- - - - -**Warning** This quick overview is incomplete - -attribute | type | values which are supported by this layer ------------ | ------ | ------------------------------------------ -[](https://taginfo.openstreetmap.org/keys/species:nl#values) [species:nl](https://wiki.openstreetmap.org/wiki/Key:species:nl) | [string](../SpecialInputElements.md#string) | -[](https://taginfo.openstreetmap.org/keys/taxon#values) [taxon](https://wiki.openstreetmap.org/wiki/Key:taxon) | [string](../SpecialInputElements.md#string) | -[](https://taginfo.openstreetmap.org/keys/description#values) [description](https://wiki.openstreetmap.org/wiki/Key:description) | [string](../SpecialInputElements.md#string) | -[](https://taginfo.openstreetmap.org/keys/ref#values) [ref](https://wiki.openstreetmap.org/wiki/Key:ref) | [string](../SpecialInputElements.md#string) | - -### fruitboom-species:nl - -The question is **Wat is de soort van deze boom (in het Nederlands)?** - -This rendering asks information about the property [species:nl](https://wiki.openstreetmap.org/wiki/Key:species:nl) -This is rendered with `De soort is {species:nl}` - -### fruitboom-taxon - -The question is **Wat is het taxon (ras) van deze boom?** - -This rendering asks information about the property [taxon](https://wiki.openstreetmap.org/wiki/Key:taxon) -This is rendered with `Het ras (taxon) van deze boom is {taxon}` - -### fruitboom-description - -The question is **Welke beschrijving past bij deze boom?** - -This rendering asks information about the property [description](https://wiki.openstreetmap.org/wiki/Key:description) -This is rendered with `Beschrijving: {description}` - -### fruitboom-ref - -The question is **Is er een refernetienummer?** - -This rendering asks information about the property [ref](https://wiki.openstreetmap.org/wiki/Key:ref) -This is rendered with `Referentienummer: {ref}` - -This document is autogenerated from assets/layers/fruitboom/fruitboom.json \ No newline at end of file diff --git a/Docs/Layers/generic_osm_object.md b/Docs/Layers/generic_osm_object.md deleted file mode 100644 index eccc852941..0000000000 --- a/Docs/Layers/generic_osm_object.md +++ /dev/null @@ -1,45 +0,0 @@ -generic_osm_object -==================== - -## Table of contents - -1. [generic_osm_object](#generic_osm_object) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [all_tags](#all_tags) - - -- Not rendered on the map by default. If you want to rendering this on the map, override `mapRenderings` -- This layer is needed as dependency for layer [grb](#grb) - -[Go to the source code](../assets/layers/generic_osm_object/generic_osm_object.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- id~^..*$ -- -- -- -- type!~^boundary$ -- -- |level - =0 -- layer - =0| - -Supported attributes ----------------------- - -### all_tags - -_This tagrendering has no question and is thus read-only_ - -This document is autogenerated from assets/layers/generic_osm_object/generic_osm_object.json \ No newline at end of file diff --git a/Docs/Layers/ghost_bike.md b/Docs/Layers/ghost_bike.md index 0788cb4cb1..6cfaffb53a 100644 --- a/Docs/Layers/ghost_bike.md +++ b/Docs/Layers/ghost_bike.md @@ -12,24 +12,9 @@ A layer showing memorials for cyclists, killed in road accidents -## Table of contents - -1. [ghost_bike](#ghost_bike) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [ghost-bike-explanation](#ghost-bike-explanation) - + [images](#images) - + [ghost_bike-name](#ghost_bike-name) - + [ghost_bike-source](#ghost_bike-source) - + [ghost_bike-inscription](#ghost_bike-inscription) - + [ghost_bike-start_date](#ghost_bike-start_date) - - - - + - This layer is shown at zoomlevel **0** and higher @@ -44,8 +29,6 @@ A layer showing memorials for cyclists, killed in road accidents - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/ghost_bike/ghost_bike.json) - Basic tags for this layer diff --git a/Docs/Layers/gps_location.md b/Docs/Layers/gps_location.md deleted file mode 100644 index 2e196b1b84..0000000000 --- a/Docs/Layers/gps_location.md +++ /dev/null @@ -1,44 +0,0 @@ -gps_location -============== - - - - - -Meta layer showing the current location of the user. Add this to your theme and override the icon to change the -appearance of the current location. The object will always have `id=gps` and will have _all_ the properties included in -the [`Coordinates`-object](https://developer.mozilla.org/en-US/docs/Web/API/GeolocationCoordinates) returned by the -browser. - -## Table of contents - -1. [gps_location](#gps_location) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - - -- This layer cannot be toggled in the filter view. If you import this layer in your theme, override `title` to make this - toggleable. -- Not visible in the layer selection by default. If you want to make this layer toggable, override `name` - -[Go to the source code](../assets/layers/gps_location/gps_location.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- id - =gps - -Supported attributes ----------------------- - - - -This document is autogenerated from assets/layers/gps_location/gps_location.json \ No newline at end of file diff --git a/Docs/Layers/gps_location_history.md b/Docs/Layers/gps_location_history.md deleted file mode 100644 index cdfe7f6103..0000000000 --- a/Docs/Layers/gps_location_history.md +++ /dev/null @@ -1,43 +0,0 @@ -gps_location_history -====================== - - - - - -Meta layer which contains the previous locations of the user as single points. This is mainly for technical reasons, -e.g. to keep match the distance to the modified object - -## Table of contents - -1. [gps_location_history](#gps_location_history) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - - -- This layer cannot be toggled in the filter view. If you import this layer in your theme, override `title` to make this - toggleable. -- Not visible in the layer selection by default. If you want to make this layer toggable, override `name` -- Not rendered on the map by default. If you want to rendering this on the map, override `mapRenderings` - -[Go to the source code](../assets/layers/gps_location_history/gps_location_history.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- user:location - =yes - -Supported attributes ----------------------- - - - -This document is autogenerated from assets/layers/gps_location_history/gps_location_history.json \ No newline at end of file diff --git a/Docs/Layers/gps_track.md b/Docs/Layers/gps_track.md deleted file mode 100644 index d10ccff474..0000000000 --- a/Docs/Layers/gps_track.md +++ /dev/null @@ -1,59 +0,0 @@ -gps_track -=========== - - - - - -Meta layer showing the previous locations of the user as single line. Add this to your theme and override the icon to -change the appearance of the current location. - -## Table of contents - -1. [gps_track](#gps_track) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [Privacy notice](#privacy-notice) - + [export_as_gpx](#export_as_gpx) - + [minimap](#minimap) - + [delete](#delete) - - -- This layer is not visible by default and must be enabled in the filter by the user. -- Not rendered on the map by default. If you want to rendering this on the map, override `mapRenderings` - -[Go to the source code](../assets/layers/gps_track/gps_track.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- id - =location_track - -Supported attributes ----------------------- - -### Privacy notice - -_This tagrendering has no question and is thus read-only_ - -### export_as_gpx - -_This tagrendering has no question and is thus read-only_ - -### minimap - -_This tagrendering has no question and is thus read-only_ - -### delete - -_This tagrendering has no question and is thus read-only_ - -This document is autogenerated from assets/layers/gps_track/gps_track.json \ No newline at end of file diff --git a/Docs/Layers/grass_in_parks.md b/Docs/Layers/grass_in_parks.md index a73c659d20..c974348487 100644 --- a/Docs/Layers/grass_in_parks.md +++ b/Docs/Layers/grass_in_parks.md @@ -12,21 +12,9 @@ Searches for all accessible grass patches within public parks - these are 'groen -## Table of contents - -1. [grass_in_parks](#grass_in_parks) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [explanation](#explanation) - + [grass-in-parks-reviews](#grass-in-parks-reviews) - - - - + - This layer is shown at zoomlevel **0** and higher @@ -40,8 +28,6 @@ Searches for all accessible grass patches within public parks - these are 'groen - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/grass_in_parks/grass_in_parks.json) - Basic tags for this layer diff --git a/Docs/Layers/grb.md b/Docs/Layers/grb.md deleted file mode 100644 index 6e339fdf10..0000000000 --- a/Docs/Layers/grb.md +++ /dev/null @@ -1,98 +0,0 @@ -grb -===== - - - - - -Geometry which comes from GRB with tools to import them - -## Table of contents - -1. [grb](#grb) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [Import-button](#import-button) - + [Building info](#building-info) - + [overlapping building address](#overlapping-building-address) - + [grb_address_diff](#grb_address_diff) - + [overlapping building type](#overlapping-building-type) - + [apply-id](#apply-id) - + [apply-building-type](#apply-building-type) - - -- This layer is loaded from an external source, namely `https://betadata.grbosm.site/grb?bbox={x_min},{y_min},{x_max},{y_max}` -- This layer will automatically load [osm-buildings](./osm-buildings.md) into the layout as it depends on it: a - tagrendering needs this layer (Import-button) -- This layer will automatically load [type_node](./type_node.md) into the layout as it depends on it: a tagrendering - needs this layer (Import-button) -- This layer will automatically load [osm-buildings](./osm-buildings.md) into the layout as it depends on it: A - calculated tag loads features from this layer (calculatedTag[0] which calculates the value for _ - overlaps_with_buildings) -- This layer will automatically load [generic_osm_object](./generic_osm_object.md) into the layout as it depends on - it: A calculated tag loads features from this layer (calculatedTag[18] which calculates the value for _ - intersects_with_other_features) - -[Go to the source code](../assets/layers/grb/grb.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- HUISNR~^..*$ -- man_made!~^mast$ - -Supported attributes ----------------------- - -### Import-button - -_This tagrendering has no question and is thus read-only_ - -- **{conflate_button(osm-buildings,building=$_target_building_type; source:geometry:date=$_grb_date; source:geometry: - ref=$_grb_ref; addr:street=$addr:street; addr:housenumber=$addr:housenumber, Replace the geometry in OpenStreetMap and - add the address,,_osm_obj:id)}** corresponds with _overlap_percentage>50&_reverse_overlap_percentage>50&_ - overlaps_with!~^$&addr:street~^..*$&addr:housenumber~^..*$&addr:street!=&addr:housenumber!= -- **{conflate_button(osm-buildings,building=$_target_building_type; source:geometry:date=$_grb_date; source:geometry: - ref=$_grb_ref, Replace the geometry in OpenStreetMap,,_osm_obj:id)}** corresponds with _overlap_percentage>50&_ - reverse_overlap_percentage>50&_overlaps_with!~^$ - -### Building info - -_This tagrendering has no question and is thus read-only_ - -### overlapping building address - -_This tagrendering has no question and is thus read-only_ - -- **The overlapping openstreetmap-building has address {_osm_obj:addr:street} {_osm_obj:addr:housenumber}** corresponds - with _osm_obj:addr:street~^..*$&_osm_obj:addr:housenumber~^..*$ -- **The overlapping building only has a street known: {_osm_obj:addr:street}** corresponds with _osm_obj:addr:street~ - ^..*$ -- **The overlapping building only has a housenumber known: {_osm_obj:addr:housenumber}** corresponds with _osm_obj:addr: - housenumber~^..*$ -- **No overlapping OpenStreetMap-building found** corresponds with - -### grb_address_diff - -_This tagrendering has no question and is thus read-only_ - -### overlapping building type - -_This tagrendering has no question and is thus read-only_ - -### apply-id - -_This tagrendering has no question and is thus read-only_ - -### apply-building-type - -_This tagrendering has no question and is thus read-only_ - -This document is autogenerated from assets/layers/grb/grb.json \ No newline at end of file diff --git a/Docs/Layers/hackerspaces.md b/Docs/Layers/hackerspaces.md index cfc1dd152d..3c0e8953dd 100644 --- a/Docs/Layers/hackerspaces.md +++ b/Docs/Layers/hackerspaces.md @@ -1,4 +1,6 @@ -hackerspaces + + + hackerspaces ============== @@ -7,150 +9,219 @@ hackerspaces Hackerspace -## Table of contents - -1. [hackerspaces](#hackerspaces) - * [Themes using this layer](#themes-using-this-layer) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [is_makerspace](#is_makerspace) - + [hackerspaces-name](#hackerspaces-name) - + [website](#website) - + [email](#email) - + [phone](#phone) - + [hackerspaces-opening_hours](#hackerspaces-opening_hours) - + [wheelchair-access](#wheelchair-access) - + [hs-club-mate](#hs-club-mate) - + [hackerspaces-start_date](#hackerspaces-start_date) - -#### Themes using this layer - -- [hackerspaces](https://mapcomplete.osm.be/hackerspaces) - -[Go to the source code](../assets/layers/hackerspaces/hackerspaces.json) -Basic tags for this layer + + + - This layer is shown at zoomlevel **8** and higher + + + + +#### Themes using this layer + + + + + + - [hackerspaces](https://mapcomplete.osm.be/hackerspaces) + + + + + Basic tags for this layer --------------------------- Elements must have the all of following tags to be shown on this layer: -- leisure - =hackerspace -Supported attributes + + - leisure=hackerspace + + +[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22leisure%22%3D%22hackerspace%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) + + + + Supported attributes ---------------------- **Warning** This quick overview is incomplete + + attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ [](https://taginfo.openstreetmap.org/keys/hackerspace#values) [hackerspace](https://wiki.openstreetmap.org/wiki/Key:hackerspace) | Multiple choice | [makerspace](https://wiki.openstreetmap.org/wiki/Tag:hackerspace%3Dmakerspace) [](https://wiki.openstreetmap.org/wiki/Tag:hackerspace%3D) -[](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | -[](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | -[](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | -[](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | +[](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | +[](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | +[](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | [](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | [24/7](https://wiki.openstreetmap.org/wiki/Tag:opening_hours%3D24/7) [](https://taginfo.openstreetmap.org/keys/wheelchair#values) [wheelchair](https://wiki.openstreetmap.org/wiki/Key:wheelchair) | Multiple choice | [designated](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Ddesignated) [yes](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Dyes) [limited](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Dlimited) [no](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Dno) [](https://taginfo.openstreetmap.org/keys/drink:club-mate#values) [drink:club-mate](https://wiki.openstreetmap.org/wiki/Key:drink:club-mate) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:drink:club-mate%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:drink:club-mate%3Dno) -[](https://taginfo.openstreetmap.org/keys/start_date#values) [start_date](https://wiki.openstreetmap.org/wiki/Key:start_date) | [date](../SpecialInputElements.md#date) | +[](https://taginfo.openstreetmap.org/keys/start_date#values) [start_date](https://wiki.openstreetmap.org/wiki/Key:start_date) | [date](../SpecialInputElements.md#date) | + + + + +### is_makerspace + -### is_makerspace The question is **Is this a hackerspace or a makerspace?** -- **This is a makerspace** corresponds - with hackerspace - =makerspace -- **This is a traditional (software oriented) hackerspace** corresponds with -### hackerspaces-name + + + + - **This is a makerspace** corresponds with hackerspace=makerspace + - **This is a traditional (software oriented) hackerspace** corresponds with + + + + +### hackerspaces-name + + The question is **What is the name of this hackerspace?** -This rendering asks information about the property [name](https://wiki.openstreetmap.org/wiki/Key:name) +This rendering asks information about the property [name](https://wiki.openstreetmap.org/wiki/Key:name) This is rendered with `This hackerspace is named {name}` -### website -The question is **What is the website of {name}?** -This rendering asks information about the property [website](https://wiki.openstreetmap.org/wiki/Key:website) +### website + + + +The question is **What is the website of {title()}?** + +This rendering asks information about the property [website](https://wiki.openstreetmap.org/wiki/Key:website) This is rendered with `{website}` -- **{contact:website}** corresponds with contact:website~^..*$_This - option cannot be chosen as answer_ -### email -The question is **What is the email address of {name}?** + - **{contact:website}** corresponds with contact:website~^..*$_This option cannot be chosen as answer_ -This rendering asks information about the property [email](https://wiki.openstreetmap.org/wiki/Key:email) + + + +### email + + + +The question is **What is the email address of {title()}?** + +This rendering asks information about the property [email](https://wiki.openstreetmap.org/wiki/Key:email) This is rendered with `{email}` -- **{contact:email}** corresponds with contact:email~^..*$_This - option cannot be chosen as answer_ -### phone -The question is **What is the phone number of {name}?** + - **{contact:email}** corresponds with contact:email~^..*$_This option cannot be chosen as answer_ -This rendering asks information about the property [phone](https://wiki.openstreetmap.org/wiki/Key:phone) + + + +### phone + + + +The question is **What is the phone number of {title()}?** + +This rendering asks information about the property [phone](https://wiki.openstreetmap.org/wiki/Key:phone) This is rendered with `{phone}` -- **{contact:phone}** corresponds with contact:phone~^..*$_This option cannot be - chosen as answer_ -### hackerspaces-opening_hours + + - **{contact:phone}** corresponds with contact:phone~^..*$_This option cannot be chosen as answer_ + + + + +### hackerspaces-opening_hours + + The question is **When is this hackerspace opened?** -This rendering asks information about the -property [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) +This rendering asks information about the property [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) This is rendered with `{opening_hours_table()}` -- **Opened 24/7** corresponds with - opening_hours=24/7 -### wheelchair-access + + - **Opened 24/7** corresponds with opening_hours=24/7 + + + + +### wheelchair-access + + The question is **Is this place accessible with a wheelchair?** -- **This place is specially adapted for wheelchair users** corresponds - with wheelchair - =designated -- **This place is easily reachable with a wheelchair** corresponds - with wheelchair - =yes -- **It is possible to reach this place in a wheelchair, but it is not easy** corresponds - with wheelchair - =limited -- **This place is not reachable with a wheelchair** corresponds - with wheelchair - =no -### hs-club-mate + + + + - **This place is specially adapted for wheelchair users** corresponds with wheelchair=designated + - **This place is easily reachable with a wheelchair** corresponds with wheelchair=yes + - **It is possible to reach this place in a wheelchair, but it is not easy** corresponds with wheelchair=limited + - **This place is not reachable with a wheelchair** corresponds with wheelchair=no + + + + +### hs-club-mate + + The question is **Does this hackerspace serve Club Mate?** -- **This hackerspace serves club mate** corresponds - with drink:club-mate - =yes -- **This hackerspace does not serve club mate** corresponds - with drink:club-mate - =no -### hackerspaces-start_date + + + + - **This hackerspace serves club mate** corresponds with drink:club-mate=yes + - **This hackerspace does not serve club mate** corresponds with drink:club-mate=no + + + + +### hackerspaces-start_date + + The question is **When was this hackerspace founded?** -This rendering asks information about the property [start_date](https://wiki.openstreetmap.org/wiki/Key:start_date) +This rendering asks information about the property [start_date](https://wiki.openstreetmap.org/wiki/Key:start_date) This is rendered with `This hackerspace was founded at {start_date}` -This document is autogenerated from assets/layers/hackerspaces/hackerspaces.json \ No newline at end of file + + +### questions + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### minimap + + + +_This tagrendering has no question and is thus read-only_ + + + +This document is autogenerated from [assets/themes/hackerspaces/hackerspaces.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/hackerspaces/hackerspaces.json) \ No newline at end of file diff --git a/Docs/Layers/health_and_social_places_without_etymology.md b/Docs/Layers/health_and_social_places_without_etymology.md new file mode 100644 index 0000000000..0fba7b0537 --- /dev/null +++ b/Docs/Layers/health_and_social_places_without_etymology.md @@ -0,0 +1,162 @@ + + + health_and_social_places_without_etymology +============================================ + + + + + +All objects which have an etymology known + + + + + + + - This layer is shown at zoomlevel **18** and higher + + + + +#### Themes using this layer + + + + + + - [etymology](https://mapcomplete.osm.be/etymology) + + + + + Basic tags for this layer +--------------------------- + + + +Elements must have the all of following tags to be shown on this layer: + + + + - name~^..*$ + - amenity=clinic|amenity=hospital|amenity=social_facility + + +[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22clinic%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22hospital%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22social_facility%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) + + + + Supported attributes +---------------------- + + + +**Warning** This quick overview is incomplete + + + +attribute | type | values which are supported by this layer +----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/name:etymology:wikidata#values) [name:etymology:wikidata](https://wiki.openstreetmap.org/wiki/Key:name:etymology:wikidata) | [wikidata](../SpecialInputElements.md#wikidata) | +[](https://taginfo.openstreetmap.org/keys/name:etymology#values) [name:etymology](https://wiki.openstreetmap.org/wiki/Key:name:etymology) | [string](../SpecialInputElements.md#string) | [unknown](https://wiki.openstreetmap.org/wiki/Tag:name:etymology%3Dunknown) + + + + +### etymology-images-from-wikipedia + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### wikipedia-etymology + + + +The question is **What is the Wikidata-item that this object is named after?** + +This rendering asks information about the property [name:etymology:wikidata](https://wiki.openstreetmap.org/wiki/Key:name:etymology:wikidata) +This is rendered with `

Wikipedia article of the name giver

{wikipedia(name:etymology:wikidata):max-height:20rem}` + + + +### zoeken op inventaris onroerend erfgoed + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### simple etymology + + + +The question is **What is this object named after?
This might be written on the street name sign** + +This rendering asks information about the property [name:etymology](https://wiki.openstreetmap.org/wiki/Key:name:etymology) +This is rendered with `Named after {name:etymology}` + + + + - **The origin of this name is unknown in all literature** corresponds with name:etymology=unknown + + + + +### questions + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### street-name-sign-image + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### minimap + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### etymology_multi_apply + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### wikipedia + + + +_This tagrendering has no question and is thus read-only_ + + + +This document is autogenerated from [assets/themes/etymology/etymology.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/etymology/etymology.json) \ No newline at end of file diff --git a/Docs/Layers/home_location.md b/Docs/Layers/home_location.md deleted file mode 100644 index c8b3734a2b..0000000000 --- a/Docs/Layers/home_location.md +++ /dev/null @@ -1,42 +0,0 @@ -home_location -=============== - - - - - -Meta layer showing the home location of the user. The home location can be set in -the [profile settings](https://www.openstreetmap.org/profile/edit) of OpenStreetMap. - -## Table of contents - -1. [home_location](#home_location) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - - -- This layer cannot be toggled in the filter view. If you import this layer in your theme, override `title` to make this - toggleable. -- Not visible in the layer selection by default. If you want to make this layer toggable, override `name` - -[Go to the source code](../assets/layers/home_location/home_location.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- user:home - =yes - -Supported attributes ----------------------- - - - -This document is autogenerated from assets/layers/home_location/home_location.json \ No newline at end of file diff --git a/Docs/Layers/hydrant.md b/Docs/Layers/hydrant.md index e9c7eb2a66..afa91e07b6 100644 --- a/Docs/Layers/hydrant.md +++ b/Docs/Layers/hydrant.md @@ -12,22 +12,9 @@ Map layer to show fire hydrants. -## Table of contents - -1. [hydrant](#hydrant) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [hydrant-color](#hydrant-color) - + [hydrant-type](#hydrant-type) - + [hydrant-state](#hydrant-state) - + [images](#images) - - - - + - This layer is shown at zoomlevel **14** and higher @@ -42,8 +29,6 @@ Map layer to show fire hydrants. - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/hydrant/hydrant.json) - Basic tags for this layer diff --git a/Docs/Layers/information_board.md b/Docs/Layers/information_board.md index 8de2ba32ea..6c29b93378 100644 --- a/Docs/Layers/information_board.md +++ b/Docs/Layers/information_board.md @@ -12,19 +12,9 @@ A layer showing touristical, road side information boards (e.g. giving informati -## Table of contents - -1. [information_board](#information_board) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - - - - + - This layer is shown at zoomlevel **12** and higher @@ -39,8 +29,6 @@ A layer showing touristical, road side information boards (e.g. giving informati - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/information_board/information_board.json) - Basic tags for this layer diff --git a/Docs/Layers/left_right_style.md b/Docs/Layers/left_right_style.md deleted file mode 100644 index 471b5c9f65..0000000000 --- a/Docs/Layers/left_right_style.md +++ /dev/null @@ -1,45 +0,0 @@ -left_right_style -================== - - - - - -Special meta-style which will show one single line, either on the left or on the right depending on the id. This is used -in the small popups with left_right roads. Cannot be included in a theme - -## Table of contents - -1. [left_right_style](#left_right_style) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - - -- This layer cannot be toggled in the filter view. If you import this layer in your theme, override `title` to make this - toggleable. -- Not visible in the layer selection by default. If you want to make this layer toggable, override `name` -- Not rendered on the map by default. If you want to rendering this on the map, override `mapRenderings` - -[Go to the source code](../assets/layers/left_right_style/left_right_style.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- id - =left - |id - =right - -Supported attributes ----------------------- - - - -This document is autogenerated from assets/layers/left_right_style/left_right_style.json \ No newline at end of file diff --git a/Docs/Layers/lit_streets.md b/Docs/Layers/lit_streets.md index 158f4e997d..6568031604 100644 --- a/Docs/Layers/lit_streets.md +++ b/Docs/Layers/lit_streets.md @@ -1,62 +1,103 @@ -lit_streets + + + lit_streets ============= -## Table of contents - -1. [lit_streets](#lit_streets) - * [Themes using this layer](#themes-using-this-layer) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [lit](#lit) - - -- Not rendered on the map by default. If you want to rendering this on the map, override `mapRenderings` - -#### Themes using this layer - -- [street_lighting](https://mapcomplete.osm.be/street_lighting) - -[Go to the source code](../assets/layers/lit_streets/lit_streets.json) -Basic tags for this layer + + + + + + + - This layer is shown at zoomlevel **0** and higher + - Not rendered on the map by default. If you want to rendering this on the map, override `mapRenderings` + + + + +#### Themes using this layer + + + + + + - [street_lighting](https://mapcomplete.osm.be/street_lighting) + + + + + Basic tags for this layer --------------------------- Elements must have the all of following tags to be shown on this layer: -- highway!~^$ -- lit!~^no$ -- lit!~^$ -- service!~^driveway$ -Supported attributes + + - highway~^..*$ + - lit!~^no$ + - lit~^..*$ + - service!~^driveway$ + + +[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22highway%22%5D%5B%22lit%22!~%22%5Eno%24%22%5D%5B%22lit%22%5D%5B%22service%22!~%22%5Edriveway%24%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) + + + + Supported attributes ---------------------- **Warning** This quick overview is incomplete + + attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ [](https://taginfo.openstreetmap.org/keys/lit#values) [lit](https://wiki.openstreetmap.org/wiki/Key:lit) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:lit%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:lit%3Dno) [24/7](https://wiki.openstreetmap.org/wiki/Tag:lit%3D24/7) -### lit + + + +### lit + + The question is **Is this street lit?** -- **This street is lit** corresponds with lit - =yes -- **This street is not lit** corresponds with - lit=no -- **This street is lit at night** corresponds - with lit - =sunset-sunrise_This option - cannot be chosen as answer_ -- **This street is lit 24/7** corresponds with - lit=24/7 -This document is autogenerated from assets/layers/lit_streets/lit_streets.json \ No newline at end of file + + + + - **This street is lit** corresponds with lit=yes + - **This street is not lit** corresponds with lit=no + - **This street is lit at night** corresponds with lit=sunset-sunrise_This option cannot be chosen as answer_ + - **This street is lit 24/7** corresponds with lit=24/7 + + + + +### questions + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### minimap + + + +_This tagrendering has no question and is thus read-only_ + + + +This document is autogenerated from [assets/themes/street_lighting/street_lighting.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/street_lighting/street_lighting.json) \ No newline at end of file diff --git a/Docs/Layers/map.md b/Docs/Layers/map.md index c75905e74c..d7d7ad33f2 100644 --- a/Docs/Layers/map.md +++ b/Docs/Layers/map.md @@ -12,21 +12,9 @@ A map, meant for tourists which is permanently installed in the public space -## Table of contents - -1. [map](#map) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [map-map_source](#map-map_source) - + [map-attribution](#map-attribution) - - - - + - This layer is shown at zoomlevel **12** and higher @@ -42,8 +30,6 @@ A map, meant for tourists which is permanently installed in the public space - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/map/map.json) - Basic tags for this layer diff --git a/Docs/Layers/matchpoint.md b/Docs/Layers/matchpoint.md deleted file mode 100644 index 5fd22c6ca5..0000000000 --- a/Docs/Layers/matchpoint.md +++ /dev/null @@ -1,45 +0,0 @@ -matchpoint -============ - - - - - -The default rendering for a locationInput which snaps onto another object - -## Table of contents - -1. [matchpoint](#matchpoint) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - - -- This layer cannot be toggled in the filter view. If you import this layer in your theme, override `title` to make this - toggleable. -- Not visible in the layer selection by default. If you want to make this layer toggable, override `name` - -[Go to the source code](../assets/layers/matchpoint/matchpoint.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - - - - -Supported attributes ----------------------- - - - -This document is autogenerated from assets/layers/matchpoint/matchpoint.json \ No newline at end of file diff --git a/Docs/Layers/maybe_climbing.md b/Docs/Layers/maybe_climbing.md index f3940462bc..c73eba560c 100644 --- a/Docs/Layers/maybe_climbing.md +++ b/Docs/Layers/maybe_climbing.md @@ -1,4 +1,6 @@ -maybe_climbing + + + maybe_climbing ================ @@ -7,67 +9,284 @@ maybe_climbing A climbing opportunity? -## Table of contents - -1. [maybe_climbing](#maybe_climbing) - * [Themes using this layer](#themes-using-this-layer) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [minimap](#minimap) - + [climbing-opportunity-name](#climbing-opportunity-name) - + [climbing-possible](#climbing-possible) - -#### Themes using this layer - -- [climbing](https://mapcomplete.osm.be/climbing) - -[Go to the source code](../assets/layers/maybe_climbing/maybe_climbing.json) -Basic tags for this layer + + + - This layer is shown at zoomlevel **19** and higher + - This layer will automatically load [climbing](./climbing.md) into the layout as it depends on it: A calculated tag loads features from this layer (calculatedTag[0] which calculates the value for _embedding_feature_properties) + + + + +#### Themes using this layer + + + + + + - [climbing](https://mapcomplete.osm.be/climbing) + + + + + Basic tags for this layer --------------------------- Elements must have the all of following tags to be shown on this layer: -- leisure - =sports_centre - |barrier - =wall - |barrier - =retaining_wall - |natural - =cliff - |natural - =rock - |natural - =stone -- -Supported attributes + + - leisure=sports_centre|barrier=wall|barrier=retaining_wall|natural=cliff|natural=rock|natural=stone + - + + +[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B!%22climbing%22%5D%5B%22barrier%22%3D%22wall%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B!%22climbing%22%5D%5B%22barrier%22%3D%22retaining_wall%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B!%22climbing%22%5D%5B%22leisure%22%3D%22sports_centre%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B!%22climbing%22%5D%5B%22natural%22%3D%22cliff%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B!%22climbing%22%5D%5B%22natural%22%3D%22rock%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B!%22climbing%22%5D%5B%22natural%22%3D%22stone%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) + + + + Supported attributes ---------------------- -### minimap + + +**Warning** This quick overview is incomplete + + + +attribute | type | values which are supported by this layer +----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/url#values) [url](https://wiki.openstreetmap.org/wiki/Key:url) | [url](../SpecialInputElements.md#url) | +[](https://taginfo.openstreetmap.org/keys/_embedding_feature:access#values) [_embedding_feature:access](https://wiki.openstreetmap.org/wiki/Key:_embedding_feature:access) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dyes) [permit](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dpermit) [customers](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dcustomers) [members](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dmembers) [no](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dno) +[](https://taginfo.openstreetmap.org/keys/access#values) [access](https://wiki.openstreetmap.org/wiki/Key:access) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:access%3Dyes) [permit](https://wiki.openstreetmap.org/wiki/Tag:access%3Dpermit) [customers](https://wiki.openstreetmap.org/wiki/Tag:access%3Dcustomers) [members](https://wiki.openstreetmap.org/wiki/Tag:access%3Dmembers) [no](https://wiki.openstreetmap.org/wiki/Tag:access%3Dno) +[](https://taginfo.openstreetmap.org/keys/access:description#values) [access:description](https://wiki.openstreetmap.org/wiki/Key:access:description) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/climbing:length#values) [climbing:length](https://wiki.openstreetmap.org/wiki/Key:climbing:length) | [pnat](../SpecialInputElements.md#pnat) | +[](https://taginfo.openstreetmap.org/keys/climbing:grade:french:min#values) [climbing:grade:french:min](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french:min) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/climbing:grade:french:max#values) [climbing:grade:french:max](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french:max) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/climbing:boulder#values) [climbing:boulder](https://wiki.openstreetmap.org/wiki/Key:climbing:boulder) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:boulder%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:boulder%3Dno) [limited](https://wiki.openstreetmap.org/wiki/Tag:climbing:boulder%3Dlimited) +[](https://taginfo.openstreetmap.org/keys/climbing:toprope#values) [climbing:toprope](https://wiki.openstreetmap.org/wiki/Key:climbing:toprope) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:toprope%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:toprope%3Dno) +[](https://taginfo.openstreetmap.org/keys/climbing:sport#values) [climbing:sport](https://wiki.openstreetmap.org/wiki/Key:climbing:sport) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:sport%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:sport%3Dno) +[](https://taginfo.openstreetmap.org/keys/climbing:traditional#values) [climbing:traditional](https://wiki.openstreetmap.org/wiki/Key:climbing:traditional) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:traditional%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:traditional%3Dno) +[](https://taginfo.openstreetmap.org/keys/climbing:speed#values) [climbing:speed](https://wiki.openstreetmap.org/wiki/Key:climbing:speed) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:speed%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:speed%3Dno) + + + + +### minimap + + _This tagrendering has no question and is thus read-only_ -### climbing-opportunity-name + + + + +### climbing-opportunity-name + + _This tagrendering has no question and is thus read-only_ -### climbing-possible + + + + +### climbing-possible + + The question is **Is climbing possible here?** -- **Climbing is not possible here** corresponds with sport!~^climbing$_This option cannot be chosen as answer_ -- **Climbing is possible here** corresponds - with sport - =climbing -- **Climbing is not possible here** corresponds - with climbing - =no -This document is autogenerated from assets/layers/maybe_climbing/maybe_climbing.json \ No newline at end of file + + + + - **Climbing is possible here** corresponds with sport=climbing + - **Climbing is not possible here** corresponds with climbing=no + - **Climbing is not possible here** corresponds with sport!~^climbing$_This option cannot be chosen as answer_ + + + + +### Website + + + +The question is **Is there a (unofficial) website with more informations (e.g. topos)?** + +This rendering asks information about the property [url](https://wiki.openstreetmap.org/wiki/Key:url) +This is rendered with `{url}` + + + +### Access from containing feature + + + +_This tagrendering has no question and is thus read-only_ + + + + + + - **The containing feature states that this is publicly accessible
{_embedding_feature:access:description}** corresponds with _embedding_feature:access=yes + - **The containing feature states that a permit is needed to access
{_embedding_feature:access:description}** corresponds with _embedding_feature:access=permit + - **The containing feature states that this is only accessible to customers
{_embedding_feature:access:description}** corresponds with _embedding_feature:access=customers + - **The containing feature states that this is only accessible to club members
{_embedding_feature:access:description}** corresponds with _embedding_feature:access=members + - **Not accessible as stated by the containing feature** corresponds with _embedding_feature:access=no + + + + +### Access + + + +The question is **Who can access here?** + + + + + + - **Publicly accessible to anyone** corresponds with access=yes + - **You need a permit to access here** corresponds with access=permit + - **Only customers** corresponds with access=customers + - **Only club members** corresponds with access=members + - **Not accessible** corresponds with access=no + + + + +### Access description (without _embedding_feature:access:description) + + + +_This tagrendering has no question and is thus read-only_ + +This rendering asks information about the property [access:description](https://wiki.openstreetmap.org/wiki/Key:access:description) +This is rendered with `{access:description}` + + + +### Avg length? + + + +The question is **What is the (average) length of the routes in meters?** + +This rendering asks information about the property [climbing:length](https://wiki.openstreetmap.org/wiki/Key:climbing:length) +This is rendered with `The routes are {canonical(climbing:length)} long on average` + + + +### Difficulty-min + + + +The question is **What is the grade of the easiest route here, according to the french classification system?** + +This rendering asks information about the property [climbing:grade:french:min](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french:min) +This is rendered with `The lowest grade is {climbing:grade:french:min} according to the french/belgian system` + + + +### Difficulty-max + + + +The question is **What is the highest grade route here, according to the french classification system?** + +This rendering asks information about the property [climbing:grade:french:max](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french:max) +This is rendered with `The highest grade is {climbing:grade:french:max} according to the french/belgian system` + + + +### Boldering? + + + +The question is **Is bouldering possible here?** + + + + + + - **Bouldering is possible here** corresponds with climbing:boulder=yes + - **Bouldering is not possible here** corresponds with climbing:boulder=no + - **Bouldering is possible, allthough there are only a few routes** corresponds with climbing:boulder=limited + - **There are {climbing:boulder} boulder routes** corresponds with climbing:boulder~^..*$_This option cannot be chosen as answer_ + + + + +### Toproping? + + + +The question is **Is toprope climbing possible here?** + + + + + + - **Toprope climbing is possible here** corresponds with climbing:toprope=yes + - **Toprope climbing is not possible here** corresponds with climbing:toprope=no + - **There are {climbing:toprope} toprope routes** corresponds with climbing:toprope~^..*$_This option cannot be chosen as answer_ + + + + +### Sportclimbing? + + + +The question is **Is sport climbing possible here on fixed anchors?** + + + + + + - **Sport climbing is possible here** corresponds with climbing:sport=yes + - **Sport climbing is not possible here** corresponds with climbing:sport=no + - **There are {climbing:sport} sport climbing routes** corresponds with climbing:sport~^..*$_This option cannot be chosen as answer_ + + + + +### Traditional climbing? + + + +The question is **Is traditional climbing possible here (using own gear e.g. chocks)?** + + + + + + - **Traditional climbing is possible here** corresponds with climbing:traditional=yes + - **Traditional climbing is not possible here** corresponds with climbing:traditional=no + - **There are {climbing:traditional} traditional climbing routes** corresponds with climbing:traditional~^..*$_This option cannot be chosen as answer_ + + + + +### Speed climbing? + + + +The question is **Is there a speed climbing wall?** + + + + + + - **There is a speed climbing wall** corresponds with climbing:speed=yes + - **There is no speed climbing wall** corresponds with climbing:speed=no + - **There are {climbing:speed} speed climbing walls** corresponds with climbing:speed~^..*$_This option cannot be chosen as answer_ + + +This document is autogenerated from [assets/themes/climbing/climbing.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/climbing/climbing.json) \ No newline at end of file diff --git a/Docs/Layers/named_streets.md b/Docs/Layers/named_streets.md index 31690af773..f729fc5132 100644 --- a/Docs/Layers/named_streets.md +++ b/Docs/Layers/named_streets.md @@ -12,17 +12,9 @@ Hidden layer with all streets which have a name. Useful to detect addresses -## Table of contents - -1. [named_streets](#named_streets) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - - - + - This layer is shown at zoomlevel **18** and higher - This layer is not visible by default and must be enabled in the filter by the user. - This layer cannot be toggled in the filter view. If you import this layer in your theme, override `title` to make this toggleable. - This layer is not visible by default and the visibility cannot be toggled, effectively resulting in a fully hidden layer. This can be useful, e.g. to calculate some metatags. If you want to render this layer (e.g. for debugging), enable it by setting the URL-parameter layer-=true @@ -42,8 +34,6 @@ Hidden layer with all streets which have a name. Useful to detect addresses - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/named_streets/named_streets.json) - Basic tags for this layer diff --git a/Docs/Layers/nature_reserve.md b/Docs/Layers/nature_reserve.md index 5898a47465..2d0427d71f 100644 --- a/Docs/Layers/nature_reserve.md +++ b/Docs/Layers/nature_reserve.md @@ -12,31 +12,9 @@ A nature reserve is an area where nature can take its course -## Table of contents - -1. [nature_reserve](#nature_reserve) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [Access tag](#access-tag) - + [Operator tag](#operator-tag) - + [Name tag](#name-tag) - + [Dogs?](#dogs) - + [website](#website) - + [Curator](#curator) - + [Email](#email) - + [phone](#phone) - + [Non-editable description](#non-editable-description) - + [Editable description](#editable-description) - + [Surface area](#surface-area) - + [wikipedia](#wikipedia) - - - - + - This layer is shown at zoomlevel **12** and higher @@ -51,8 +29,6 @@ A nature reserve is an area where nature can take its course - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/nature_reserve/nature_reserve.json) - Basic tags for this layer diff --git a/Docs/Layers/nature_reserve_buurtnatuur.md b/Docs/Layers/nature_reserve_buurtnatuur.md deleted file mode 100644 index 3f2a9cf681..0000000000 --- a/Docs/Layers/nature_reserve_buurtnatuur.md +++ /dev/null @@ -1,46 +0,0 @@ -nature_reserve_buurtnatuur -============================ - - - - - -Een natuurgebied is een gebied waar actief ruimte gemaakt word voor de natuur. Typisch zijn deze in beheer van -Natuurpunt of het Agentschap Natuur en Bos of zijn deze erkend door de overheid. - -## Table of contents - -1. [nature_reserve_buurtnatuur](#nature_reserve_buurtnatuur) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [images](#images) - - -- This layer is needed as dependency for layer [parks](#parks) -- This layer is needed as dependency for layer [forest](#forest) - -[Go to the source code](../assets/layers/nature_reserve_buurtnatuur/nature_reserve_buurtnatuur.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- leisure - =nature_reserve - |boundary - =protected_area - -Supported attributes ----------------------- - -### images - -_This tagrendering has no question and is thus read-only_ - -This document is autogenerated from assets/layers/nature_reserve_buurtnatuur/nature_reserve_buurtnatuur.json \ No newline at end of file diff --git a/Docs/Layers/node.md b/Docs/Layers/node.md deleted file mode 100644 index a767e1f35e..0000000000 --- a/Docs/Layers/node.md +++ /dev/null @@ -1,60 +0,0 @@ -node -====== - -## Table of contents - -1. [node](#node) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [node-survey:date](#node-surveydate) - + [node-expected_rcn_route_relations](#node-expected_rcn_route_relations) - + [images](#images) - -[Go to the source code](../assets/layers/node/node.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- rcn_ref~^..*$ - -Supported attributes ----------------------- - - - -**Warning** This quick overview is incomplete - -attribute | type | values which are supported by this layer ------------ | ------ | ------------------------------------------ -[](https://taginfo.openstreetmap.org/keys/survey:date#values) [survey:date](https://wiki.openstreetmap.org/wiki/Key:survey:date) | [date](../SpecialInputElements.md#date) | [](https://wiki.openstreetmap.org/wiki/Tag:survey:date%3D) -[](https://taginfo.openstreetmap.org/keys/expected_rcn_route_relations#values) [expected_rcn_route_relations](https://wiki.openstreetmap.org/wiki/Key:expected_rcn_route_relations) | [int](../SpecialInputElements.md#int) | - -### node-survey:date - -The question is **When was this cycle node last surveyed?** - -This rendering asks information about the property [survey:date](https://wiki.openstreetmap.org/wiki/Key:survey:date) -This is rendered with `This cycle node was last surveyed on {survey:date}` - -- **Surveyed today!** corresponds with survey:date= - -### node-expected_rcn_route_relations - -The question is **How many other cycle nodes does this node link to?** - -This rendering asks information about the -property [expected_rcn_route_relations](https://wiki.openstreetmap.org/wiki/Key:expected_rcn_route_relations) -This is rendered with `This node links to {expected_rcn_route_relations} other cycle nodes.` - -### images - -_This tagrendering has no question and is thus read-only_ - -This document is autogenerated from assets/layers/node/node.json \ No newline at end of file diff --git a/Docs/Layers/node2node.md b/Docs/Layers/node2node.md deleted file mode 100644 index c8a7247525..0000000000 --- a/Docs/Layers/node2node.md +++ /dev/null @@ -1,58 +0,0 @@ -node2node -=========== - -## Table of contents - -1. [node2node](#node2node) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [node2node-survey:date](#node2node-surveydate) - + [export_as_gpx](#export_as_gpx) - - -- Not rendered on the map by default. If you want to rendering this on the map, override `mapRenderings` - -[Go to the source code](../assets/layers/node2node/node2node.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- network - =rcn -- network:type - =node_network -- route - =bicycle - -Supported attributes ----------------------- - - - -**Warning** This quick overview is incomplete - -attribute | type | values which are supported by this layer ------------ | ------ | ------------------------------------------ -[](https://taginfo.openstreetmap.org/keys/survey:date#values) [survey:date](https://wiki.openstreetmap.org/wiki/Key:survey:date) | [date](../SpecialInputElements.md#date) | [](https://wiki.openstreetmap.org/wiki/Tag:survey:date%3D) - -### node2node-survey:date - -The question is **When was this node to node link last surveyed?** - -This rendering asks information about the property [survey:date](https://wiki.openstreetmap.org/wiki/Key:survey:date) -This is rendered with `This node to node link was last surveyed on {survey:date}` - -- **Surveyed today!** corresponds with survey:date= - -### export_as_gpx - -_This tagrendering has no question and is thus read-only_ - -This document is autogenerated from assets/layers/node2node/node2node.json \ No newline at end of file diff --git a/Docs/Layers/note_import.md b/Docs/Layers/note_import.md index 87e9cf6fcb..43ffa283bf 100644 --- a/Docs/Layers/note_import.md +++ b/Docs/Layers/note_import.md @@ -12,24 +12,9 @@ Template for note note imports. -## Table of contents - -1. [note_import](#note_import) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [conversation](#conversation) - + [Intro](#intro) - + [import](#import) - + [close_note_](#close_note_) - + [close_note_mapped](#close_note_mapped) - + [comment](#comment) - + [add_image](#add_image) - - - + - This layer is shown at zoomlevel **10** and higher - This layer is loaded from an external source, namely `https://api.openstreetmap.org/api/0.6/notes.json?closed=0&bbox={x_min},{y_min},{x_max},{y_max}` - This layer will automatically load [public_bookcase](./public_bookcase.md) into the layout as it depends on it: a tagrendering needs this layer (import) @@ -45,8 +30,6 @@ Template for note note imports. - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/note_import/note_import.json) - Basic tags for this layer diff --git a/Docs/Layers/observation_tower.md b/Docs/Layers/observation_tower.md index 39728c7da6..e018e652fd 100644 --- a/Docs/Layers/observation_tower.md +++ b/Docs/Layers/observation_tower.md @@ -12,30 +12,9 @@ Towers with a panoramic view -## Table of contents - -1. [observation_tower](#observation_tower) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [name](#name) - + [Height](#height) - + [access](#access) - + [Fee](#fee) - + [payment-options](#payment-options) - + [website](#website) - + [step_count](#step_count) - + [elevator](#elevator) - + [Operator](#operator) - + [wheelchair-access](#wheelchair-access) - + [wikipedia](#wikipedia) - - - - + - This layer is shown at zoomlevel **8** and higher @@ -50,8 +29,6 @@ Towers with a panoramic view - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/observation_tower/observation_tower.json) - Basic tags for this layer diff --git a/Docs/Layers/orchards.md b/Docs/Layers/orchards.md deleted file mode 100644 index e25d58bf1c..0000000000 --- a/Docs/Layers/orchards.md +++ /dev/null @@ -1,37 +0,0 @@ -orchards -========== - - - - - -## Table of contents - -1. [orchards](#orchards) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [images](#images) - -[Go to the source code](../assets/layers/orchards/orchards.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- landuse - =orchard - -Supported attributes ----------------------- - -### images - -_This tagrendering has no question and is thus read-only_ - -This document is autogenerated from assets/layers/orchards/orchards.json \ No newline at end of file diff --git a/Docs/Layers/osm-buildings-fixme.md b/Docs/Layers/osm-buildings-fixme.md deleted file mode 100644 index e9f6d27065..0000000000 --- a/Docs/Layers/osm-buildings-fixme.md +++ /dev/null @@ -1,143 +0,0 @@ -osm-buildings-fixme -===================== - -## Table of contents - -1. [osm-buildings-fixme](#osm-buildings-fixme) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [building type](#building-type) - + [grb-housenumber](#grb-housenumber) - + [grb-unit](#grb-unit) - + [grb-street](#grb-street) - + [grb-fixme](#grb-fixme) - + [grb-min-level](#grb-min-level) - + [fix_verdieping](#fix_verdieping) - + [all_tags](#all_tags) - -[Go to the source code](../assets/layers/osm-buildings-fixme/osm-buildings-fixme.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- building~^..*$ -- fixme~^..*$ - -Supported attributes ----------------------- - - - -**Warning** This quick overview is incomplete - -attribute | type | values which are supported by this layer ------------ | ------ | ------------------------------------------ -[](https://taginfo.openstreetmap.org/keys/building#values) [building](https://wiki.openstreetmap.org/wiki/Key:building) | [string](../SpecialInputElements.md#string) | [house](https://wiki.openstreetmap.org/wiki/Tag:building%3Dhouse) [detached](https://wiki.openstreetmap.org/wiki/Tag:building%3Ddetached) [semidetached_house](https://wiki.openstreetmap.org/wiki/Tag:building%3Dsemidetached_house) [apartments](https://wiki.openstreetmap.org/wiki/Tag:building%3Dapartments) [office](https://wiki.openstreetmap.org/wiki/Tag:building%3Doffice) [apartments](https://wiki.openstreetmap.org/wiki/Tag:building%3Dapartments) [shed](https://wiki.openstreetmap.org/wiki/Tag:building%3Dshed) [garage](https://wiki.openstreetmap.org/wiki/Tag:building%3Dgarage) [garages](https://wiki.openstreetmap.org/wiki/Tag:building%3Dgarages) [yes](https://wiki.openstreetmap.org/wiki/Tag:building%3Dyes) -[](https://taginfo.openstreetmap.org/keys/addr:housenumber#values) [addr:housenumber](https://wiki.openstreetmap.org/wiki/Key:addr:housenumber) | [string](../SpecialInputElements.md#string) | [](https://wiki.openstreetmap.org/wiki/Tag:addr:housenumber%3D) [](https://wiki.openstreetmap.org/wiki/Tag:addr:housenumber%3D) [](https://wiki.openstreetmap.org/wiki/Tag:addr:housenumber%3D) -[](https://taginfo.openstreetmap.org/keys/addr:unit#values) [addr:unit](https://wiki.openstreetmap.org/wiki/Key:addr:unit) | [string](../SpecialInputElements.md#string) | [](https://wiki.openstreetmap.org/wiki/Tag:addr:unit%3D) -[](https://taginfo.openstreetmap.org/keys/addr:street#values) [addr:street](https://wiki.openstreetmap.org/wiki/Key:addr:street) | [string](../SpecialInputElements.md#string) | -[](https://taginfo.openstreetmap.org/keys/fixme#values) [fixme](https://wiki.openstreetmap.org/wiki/Key:fixme) | [string](../SpecialInputElements.md#string) | [](https://wiki.openstreetmap.org/wiki/Tag:fixme%3D) -[](https://taginfo.openstreetmap.org/keys/building:min_level#values) [building:min_level](https://wiki.openstreetmap.org/wiki/Key:building:min_level) | [pnat](../SpecialInputElements.md#pnat) | - -### building type - -The question is **What kind of building is this?** - -This rendering asks information about the property [building](https://wiki.openstreetmap.org/wiki/Key:building) -This is rendered with `The building type is {building}` - -- **A normal house** corresponds with - building=house -- **A house detached from other building** corresponds - with building - =detached -- **A house sharing only one wall with another house** corresponds - with building - = - semidetached_house -- **An apartment building - highrise for living** corresponds - with building - =apartments -- **An office building - highrise for work** corresponds - with building - =office -- **An apartment building** corresponds with - building=apartments -- **A small shed, e.g. in a garden** corresponds - with building - =shed -- **A single garage to park a car** corresponds - with building - =garage -- **A building containing only garages; typically they are all identical** corresponds - with building - =garages -- **A building - no specification** corresponds - with building - =yes - -### grb-housenumber - -The question is **Wat is het huisnummer?** - -This rendering asks information about the -property [addr:housenumber](https://wiki.openstreetmap.org/wiki/Key:addr:housenumber) -This is rendered with `Het huisnummer is {addr:housenumber}` - -- **Geen huisnummer** corresponds - with not:addr:housenumber - =yes -- **Het huisnummer is {_grbNumber}, wat overeenkomt met het GRB** corresponds with addr:housenumber= -- **Dit gebouw heeft geen nummer, net zoals in het GRB** corresponds - with not:addr:housenumber - =yes - -### grb-unit - -The question is **Wat is de wooneenheid-aanduiding?** - -This rendering asks information about the property [addr:unit](https://wiki.openstreetmap.org/wiki/Key:addr:unit) -This is rendered with `De wooneenheid-aanduiding is {addr:unit} ` - -- **Geen wooneenheid-nummer** corresponds with - -### grb-street - -The question is **Wat is de straat?** - -This rendering asks information about the property [addr:street](https://wiki.openstreetmap.org/wiki/Key:addr:street) -This is rendered with `De straat is {addr:street}` - -### grb-fixme - -The question is **Wat zegt de fixme?** - -This rendering asks information about the property [fixme](https://wiki.openstreetmap.org/wiki/Key:fixme) -This is rendered with `De fixme is {fixme}` - -- **Geen fixme** corresponds with - -### grb-min-level - -The question is **Hoeveel verdiepingen ontbreken?** - -This rendering asks information about the -property [building:min_level](https://wiki.openstreetmap.org/wiki/Key:building:min_level) -This is rendered with `Dit gebouw begint maar op de {building:min_level} verdieping` - -### fix_verdieping - -_This tagrendering has no question and is thus read-only_ - -### all_tags - -_This tagrendering has no question and is thus read-only_ - -This document is autogenerated from assets/layers/osm-buildings-fixme/osm-buildings-fixme.json \ No newline at end of file diff --git a/Docs/Layers/osm-buildings.md b/Docs/Layers/osm-buildings.md deleted file mode 100644 index f5562c9dc4..0000000000 --- a/Docs/Layers/osm-buildings.md +++ /dev/null @@ -1,51 +0,0 @@ -osm-buildings -=============== - -## Table of contents - -1. [osm-buildings](#osm-buildings) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [apply_streetname](#apply_streetname) - - -- Not rendered on the map by default. If you want to rendering this on the map, override `mapRenderings` -- This layer will automatically load [crab_address](./crab_address.md) into the layout as it depends on it: A - calculated tag loads features from this layer (calculatedTag[0] which calculates the value for _ - embedded_crab_addresses) -- This layer will automatically load [named_streets](./named_streets.md) into the layout as it depends on it: A - calculated tag loads features from this layer (calculatedTag[3] which calculates the value for _nearby_street_names) -- This layer is needed as dependency for layer [grb](#grb) -- This layer is needed as dependency for layer [grb](#grb) - -[Go to the source code](../assets/layers/osm-buildings/osm-buildings.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- building~^..*$ -- addr:housenumber~^..*$ -- - -Supported attributes ----------------------- - -### apply_streetname - -_This tagrendering has no question and is thus read-only_ - -- **No nearby street has the same name. The CRAB-name is {_name_to_apply}** corresponds - with _spelling_is_correct - =false -- **There are multiple streetnames applicable here** corresponds - with _singular_import - =false - -This document is autogenerated from assets/layers/osm-buildings/osm-buildings.json \ No newline at end of file diff --git a/Docs/Layers/parking.md b/Docs/Layers/parking.md index 97808febc0..61f6b2c501 100644 --- a/Docs/Layers/parking.md +++ b/Docs/Layers/parking.md @@ -12,19 +12,9 @@ A layer showing car parkings -## Table of contents - -1. [parking](#parking) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - - - - + - This layer is shown at zoomlevel **12** and higher @@ -39,8 +29,6 @@ A layer showing car parkings - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/parking/parking.json) - Basic tags for this layer diff --git a/Docs/Layers/parks.md b/Docs/Layers/parks.md deleted file mode 100644 index 800d653f08..0000000000 --- a/Docs/Layers/parks.md +++ /dev/null @@ -1,48 +0,0 @@ -parks -======= - - - - - -Een park is een publiek toegankelijke, groene ruimte binnen de stad. Ze is typisch ingericht voor recreatief gebruik, -met (verharde) wandelpaden, zitbanken, vuilnisbakken, een gezellig vijvertje, ... - -## Table of contents - -1. [parks](#parks) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [images](#images) - - -- This layer will automatically load [nature_reserve_buurtnatuur](./nature_reserve_buurtnatuur.md) into the layout as - it depends on it: A calculated tag loads features from this layer (calculatedTag[0] which calculates the value for _ - overlapWithUpperLayers) -- This layer is needed as dependency for layer [forest](#forest) - -[Go to the source code](../assets/layers/parks/parks.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- leisure - =park - |landuse - =village_green - -Supported attributes ----------------------- - -### images - -_This tagrendering has no question and is thus read-only_ - -This document is autogenerated from assets/layers/parks/parks.json \ No newline at end of file diff --git a/Docs/Layers/parks_and_forests_without_etymology.md b/Docs/Layers/parks_and_forests_without_etymology.md new file mode 100644 index 0000000000..f9baee3bf8 --- /dev/null +++ b/Docs/Layers/parks_and_forests_without_etymology.md @@ -0,0 +1,162 @@ + + + parks_and_forests_without_etymology +===================================== + + + + + +All objects which have an etymology known + + + + + + + - This layer is shown at zoomlevel **18** and higher + + + + +#### Themes using this layer + + + + + + - [etymology](https://mapcomplete.osm.be/etymology) + + + + + Basic tags for this layer +--------------------------- + + + +Elements must have the all of following tags to be shown on this layer: + + + + - name~^..*$ + - leisure=park|landuse=forest + + +[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22landuse%22%3D%22forest%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22leisure%22%3D%22park%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) + + + + Supported attributes +---------------------- + + + +**Warning** This quick overview is incomplete + + + +attribute | type | values which are supported by this layer +----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/name:etymology:wikidata#values) [name:etymology:wikidata](https://wiki.openstreetmap.org/wiki/Key:name:etymology:wikidata) | [wikidata](../SpecialInputElements.md#wikidata) | +[](https://taginfo.openstreetmap.org/keys/name:etymology#values) [name:etymology](https://wiki.openstreetmap.org/wiki/Key:name:etymology) | [string](../SpecialInputElements.md#string) | [unknown](https://wiki.openstreetmap.org/wiki/Tag:name:etymology%3Dunknown) + + + + +### etymology-images-from-wikipedia + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### wikipedia-etymology + + + +The question is **What is the Wikidata-item that this object is named after?** + +This rendering asks information about the property [name:etymology:wikidata](https://wiki.openstreetmap.org/wiki/Key:name:etymology:wikidata) +This is rendered with `

Wikipedia article of the name giver

{wikipedia(name:etymology:wikidata):max-height:20rem}` + + + +### zoeken op inventaris onroerend erfgoed + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### simple etymology + + + +The question is **What is this object named after?
This might be written on the street name sign** + +This rendering asks information about the property [name:etymology](https://wiki.openstreetmap.org/wiki/Key:name:etymology) +This is rendered with `Named after {name:etymology}` + + + + - **The origin of this name is unknown in all literature** corresponds with name:etymology=unknown + + + + +### questions + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### street-name-sign-image + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### minimap + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### etymology_multi_apply + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### wikipedia + + + +_This tagrendering has no question and is thus read-only_ + + + +This document is autogenerated from [assets/themes/etymology/etymology.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/etymology/etymology.json) \ No newline at end of file diff --git a/Docs/Layers/pedestrian_path.md b/Docs/Layers/pedestrian_path.md index 6539d04c77..748945885d 100644 --- a/Docs/Layers/pedestrian_path.md +++ b/Docs/Layers/pedestrian_path.md @@ -12,17 +12,9 @@ Pedestrian footpaths, especially used for indoor navigation and snapping entranc -## Table of contents - -1. [pedestrian_path](#pedestrian_path) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - - - + - This layer is shown at zoomlevel **18** and higher - This layer is needed as dependency for layer [entrance](#entrance) @@ -38,8 +30,6 @@ Pedestrian footpaths, especially used for indoor navigation and snapping entranc - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/pedestrian_path/pedestrian_path.json) - Basic tags for this layer diff --git a/Docs/Layers/picnic_table.md b/Docs/Layers/picnic_table.md index 0e5b6301d9..a0cc5ece81 100644 --- a/Docs/Layers/picnic_table.md +++ b/Docs/Layers/picnic_table.md @@ -12,20 +12,9 @@ The layer showing picnic tables -## Table of contents - -1. [picnic_table](#picnic_table) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [picnic_table-material](#picnic_table-material) - - - - + - This layer is shown at zoomlevel **12** and higher @@ -41,8 +30,6 @@ The layer showing picnic tables - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/picnic_table/picnic_table.json) - Basic tags for this layer diff --git a/Docs/Layers/play_forest.md b/Docs/Layers/play_forest.md index e3dbe112c3..570732415d 100644 --- a/Docs/Layers/play_forest.md +++ b/Docs/Layers/play_forest.md @@ -12,25 +12,9 @@ Een speelbos is een vrij toegankelijke zone in een bos -## Table of contents - -1. [play_forest](#play_forest) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [play_forest-operator](#play_forest-operator) - + [play_forest-opening_hours](#play_forest-opening_hours) - + [play_forest-email](#play_forest-email) - + [play_forest-phone](#play_forest-phone) - + [questions](#questions) - + [play_forest-reviews](#play_forest-reviews) - - - - + - This layer is shown at zoomlevel **13** and higher @@ -44,8 +28,6 @@ Een speelbos is een vrij toegankelijke zone in een bos - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/play_forest/play_forest.json) - Basic tags for this layer diff --git a/Docs/Layers/playground.md b/Docs/Layers/playground.md index fe3c54bc02..0a2bd9e74c 100644 --- a/Docs/Layers/playground.md +++ b/Docs/Layers/playground.md @@ -12,31 +12,9 @@ Playgrounds -## Table of contents - -1. [playground](#playground) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [playground-surface](#playground-surface) - + [playground-lit](#playground-lit) - + [playground-min_age](#playground-min_age) - + [playground-max_age](#playground-max_age) - + [playground-operator](#playground-operator) - + [playground-access](#playground-access) - + [playground-email](#playground-email) - + [playground-phone](#playground-phone) - + [Playground-wheelchair](#playground-wheelchair) - + [playground-opening_hours](#playground-opening_hours) - + [questions](#questions) - + [playground-reviews](#playground-reviews) - - - - + - This layer is shown at zoomlevel **13** and higher @@ -51,8 +29,6 @@ Playgrounds - [playgrounds](https://mapcomplete.osm.be/playgrounds) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/playground/playground.json) - Basic tags for this layer @@ -88,6 +64,7 @@ attribute | type | values which are supported by this layer [](https://taginfo.openstreetmap.org/keys/min_age#values) [min_age](https://wiki.openstreetmap.org/wiki/Key:min_age) | [pnat](../SpecialInputElements.md#pnat) | [](https://taginfo.openstreetmap.org/keys/max_age#values) [max_age](https://wiki.openstreetmap.org/wiki/Key:max_age) | [pnat](../SpecialInputElements.md#pnat) | [](https://taginfo.openstreetmap.org/keys/operator#values) [operator](https://wiki.openstreetmap.org/wiki/Key:operator) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | [](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | [](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | [](https://taginfo.openstreetmap.org/keys/wheelchair#values) [wheelchair](https://wiki.openstreetmap.org/wiki/Key:wheelchair) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Dyes) [limited](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Dlimited) [no](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Dno) @@ -197,6 +174,22 @@ The question is **Is this playground accessible to the general public?** +### website + + + +The question is **What is the website of {title()}?** + +This rendering asks information about the property [website](https://wiki.openstreetmap.org/wiki/Key:website) +This is rendered with `{website}` + + + + - **{contact:website}** corresponds with contact:website~^..*$_This option cannot be chosen as answer_ + + + + ### playground-email diff --git a/Docs/Layers/postal_code_boundary.md b/Docs/Layers/postal_code_boundary.md deleted file mode 100644 index d5ec722a4c..0000000000 --- a/Docs/Layers/postal_code_boundary.md +++ /dev/null @@ -1,39 +0,0 @@ -postal_code_boundary -====================== - -## Table of contents - -1. [postal_code_boundary](#postal_code_boundary) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [postal_code](#postal_code) - - -- This layer is needed as dependency for layer [town_hall](#town_hall) - -[Go to the source code](../assets/layers/postal_code_boundary/postal_code_boundary.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- boundary - =postal_code - |bounary - =administrative - &postal_code~^..*$ - -Supported attributes ----------------------- - -### postal_code - -_This tagrendering has no question and is thus read-only_ - -This document is autogenerated from assets/layers/postal_code_boundary/postal_code_boundary.json \ No newline at end of file diff --git a/Docs/Layers/postboxes.md b/Docs/Layers/postboxes.md index 3edae41ea2..68d08387f2 100644 --- a/Docs/Layers/postboxes.md +++ b/Docs/Layers/postboxes.md @@ -1,4 +1,6 @@ -postboxes + + + postboxes =========== @@ -7,43 +9,66 @@ postboxes The layer showing postboxes. -## Table of contents - -1. [postboxes](#postboxes) - * [Themes using this layer](#themes-using-this-layer) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [images](#images) - + [minimap](#minimap) - -#### Themes using this layer - -- [postboxes](https://mapcomplete.osm.be/postboxes) - -[Go to the source code](../assets/layers/postboxes/postboxes.json) -Basic tags for this layer + + + - This layer is shown at zoomlevel **12** and higher + + + + +#### Themes using this layer + + + + + + - [postboxes](https://mapcomplete.osm.be/postboxes) + + + + + Basic tags for this layer --------------------------- Elements must have the all of following tags to be shown on this layer: -- amenity - =post_box -Supported attributes + + - amenity=post_box + + +[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22post_box%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) + + + + Supported attributes ---------------------- -### images + + + + +### images + + _This tagrendering has no question and is thus read-only_ -### minimap + + + + +### minimap + + _This tagrendering has no question and is thus read-only_ -This document is autogenerated from assets/layers/postboxes/postboxes.json \ No newline at end of file + + +This document is autogenerated from [assets/themes/postboxes/postboxes.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/postboxes/postboxes.json) \ No newline at end of file diff --git a/Docs/Layers/postoffices.md b/Docs/Layers/postoffices.md index 3bde0835ef..f11400b1de 100644 --- a/Docs/Layers/postoffices.md +++ b/Docs/Layers/postoffices.md @@ -1,70 +1,99 @@ -postoffices + + + postoffices ============= - + A layer showing post offices. -## Table of contents - -1. [postoffices](#postoffices) - * [Themes using this layer](#themes-using-this-layer) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [images](#images) - + [minimap](#minimap) - + [OH](#oh) - -#### Themes using this layer - -- [postboxes](https://mapcomplete.osm.be/postboxes) - -[Go to the source code](../assets/layers/postoffices/postoffices.json) -Basic tags for this layer + + + - This layer is shown at zoomlevel **12** and higher + + + + +#### Themes using this layer + + + + + + - [postboxes](https://mapcomplete.osm.be/postboxes) + + + + + Basic tags for this layer --------------------------- Elements must have the all of following tags to be shown on this layer: -- amenity - =post_office -Supported attributes + + - amenity=post_office + + +[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22post_office%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) + + + + Supported attributes ---------------------- **Warning** This quick overview is incomplete + + attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ [](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | [24/7](https://wiki.openstreetmap.org/wiki/Tag:opening_hours%3D24/7) -### images + + + +### images + + _This tagrendering has no question and is thus read-only_ -### minimap + + + + +### minimap + + _This tagrendering has no question and is thus read-only_ -### OH + + + + +### OH + + The question is **What are the opening hours for this post office?** -This rendering asks information about the -property [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) +This rendering asks information about the property [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) This is rendered with `Opening Hours: {opening_hours_table()}` -- **24/7 opened (including holidays)** corresponds - with opening_hours - =24/7 -This document is autogenerated from assets/layers/postoffices/postoffices.json \ No newline at end of file + + - **24/7 opened (including holidays)** corresponds with opening_hours=24/7 + + +This document is autogenerated from [assets/themes/postboxes/postboxes.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/postboxes/postboxes.json) \ No newline at end of file diff --git a/Docs/Layers/public_bookcase.md b/Docs/Layers/public_bookcase.md index 1355e599af..59605bd70e 100644 --- a/Docs/Layers/public_bookcase.md +++ b/Docs/Layers/public_bookcase.md @@ -12,28 +12,9 @@ A streetside cabinet with books, accessible to anyone -## Table of contents - -1. [public_bookcase](#public_bookcase) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [public_bookcase-name](#public_bookcase-name) - + [public_bookcase-capacity](#public_bookcase-capacity) - + [bookcase-booktypes](#bookcase-booktypes) - + [bookcase-is-indoors](#bookcase-is-indoors) - + [bookcase-is-accessible](#bookcase-is-accessible) - + [public_bookcase-operator](#public_bookcase-operator) - + [public_bookcase-brand](#public_bookcase-brand) - + [public_bookcase-ref](#public_bookcase-ref) - + [public_bookcase-start_date](#public_bookcase-start_date) - + [public_bookcase-website](#public_bookcase-website) - - - + - This layer is shown at zoomlevel **10** and higher - This layer is needed as dependency for layer [note_import](#note_import) @@ -49,8 +30,6 @@ A streetside cabinet with books, accessible to anyone - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/public_bookcase/public_bookcase.json) - Basic tags for this layer diff --git a/Docs/Layers/raw_inspire_polygons.md b/Docs/Layers/raw_inspire_polygons.md deleted file mode 100644 index c38230aa27..0000000000 --- a/Docs/Layers/raw_inspire_polygons.md +++ /dev/null @@ -1,39 +0,0 @@ -raw_inspire_polygons -====================== - -## Table of contents - -1. [raw_inspire_polygons](#raw_inspire_polygons) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - - -- This layer cannot be toggled in the filter view. If you import this layer in your theme, override `title` to make this - toggleable. -- Not visible in the layer selection by default. If you want to make this layer toggable, override `name` -- Not rendered on the map by default. If you want to rendering this on the map, override `mapRenderings` -- This layer is loaded from an external source, namely `https://osm-uk-addresses.russss.dev/inspire/{z}/{x}/{y}.json` -- This layer will automatically load [address](./address.md) into the layout as it depends on it: A calculated tag - loads features from this layer (calculatedTag[0] which calculates the value for _has_address) -- This layer is needed as dependency for layer [to_import](#to_import) - -[Go to the source code](../assets/layers/raw_inspire_polygons/raw_inspire_polygons.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- inspireid~^..*$ - -Supported attributes ----------------------- - - - -This document is autogenerated from assets/layers/raw_inspire_polygons/raw_inspire_polygons.json \ No newline at end of file diff --git a/Docs/Layers/recycling.md b/Docs/Layers/recycling.md index 9b3326456d..c6ed6f1f2f 100644 --- a/Docs/Layers/recycling.md +++ b/Docs/Layers/recycling.md @@ -12,28 +12,9 @@ A layer with recycling containers and centres -## Table of contents - -1. [recycling](#recycling) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [recycling-type](#recycling-type) - + [recycling-centre-name](#recycling-centre-name) - + [container-location](#container-location) - + [recycling-accepts](#recycling-accepts) - + [operator](#operator) - + [website](#website) - + [email](#email) - + [phone](#phone) - + [opening_hours](#opening_hours) - - - - + - This layer is shown at zoomlevel **12** and higher @@ -48,8 +29,6 @@ A layer with recycling containers and centres - [waste](https://mapcomplete.osm.be/waste) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/recycling/recycling.json) - Basic tags for this layer diff --git a/Docs/Layers/service_ways.md b/Docs/Layers/service_ways.md deleted file mode 100644 index 189b979416..0000000000 --- a/Docs/Layers/service_ways.md +++ /dev/null @@ -1,39 +0,0 @@ -service_ways -============== - - - - - -A seperate layer with service roads, as to remove them from the intersection testing - -## Table of contents - -1. [service_ways](#service_ways) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - - -- Not rendered on the map by default. If you want to rendering this on the map, override `mapRenderings` - -[Go to the source code](../assets/layers/service_ways/service_ways.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- highway - =service - -Supported attributes ----------------------- - - - -This document is autogenerated from assets/layers/service_ways/service_ways.json \ No newline at end of file diff --git a/Docs/Layers/shadow.md b/Docs/Layers/shadow.md deleted file mode 100644 index 1cd41fafe1..0000000000 --- a/Docs/Layers/shadow.md +++ /dev/null @@ -1,37 +0,0 @@ -shadow -======== - -## Table of contents - -1. [shadow](#shadow) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - - -- This layer cannot be toggled in the filter view. If you import this layer in your theme, override `title` to make this - toggleable. -- Not visible in the layer selection by default. If you want to make this layer toggable, override `name` -- Not rendered on the map by default. If you want to rendering this on the map, override `mapRenderings` -- This layer is loaded from an external source, namely `https://raw.githubusercontent.com/pietervdvn/MapComplete/master/assets/themes/speelplekken/shadow.geojson` - -[Go to the source code](../assets/layers/shadow/shadow.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- shadow - =yes - -Supported attributes ----------------------- - - - -This document is autogenerated from assets/layers/shadow/shadow.json \ No newline at end of file diff --git a/Docs/Layers/shops.md b/Docs/Layers/shops.md index 79ab56905a..b00a3b1030 100644 --- a/Docs/Layers/shops.md +++ b/Docs/Layers/shops.md @@ -12,28 +12,9 @@ A shop -## Table of contents - -1. [shops](#shops) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [shops-name](#shops-name) - + [shops-shop](#shops-shop) - + [shops-phone](#shops-phone) - + [shops-website](#shops-website) - + [shops-email](#shops-email) - + [shops-opening_hours](#shops-opening_hours) - + [payment-options](#payment-options) - + [questions](#questions) - + [reviews](#reviews) - - - - + - This layer is shown at zoomlevel **16** and higher @@ -48,8 +29,6 @@ A shop - [shops](https://mapcomplete.osm.be/shops) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/shops/shops.json) - Basic tags for this layer diff --git a/Docs/Layers/sidewalks.md b/Docs/Layers/sidewalks.md deleted file mode 100644 index 42a9de872c..0000000000 --- a/Docs/Layers/sidewalks.md +++ /dev/null @@ -1,118 +0,0 @@ -sidewalks -=========== - - - - - -Layer showing sidewalks of highways - -## Table of contents - -1. [sidewalks](#sidewalks) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [streetname](#streetname) - + [left-sidewalk_minimap](#left-sidewalk_minimap) - + [left-has_sidewalk](#left-has_sidewalk) - + [left-sidewalk_width](#left-sidewalk_width) - + [questions](#questions) - + [right-sidewalk_minimap](#right-sidewalk_minimap) - + [right-has_sidewalk](#right-has_sidewalk) - + [right-sidewalk_width](#right-sidewalk_width) - + [questions](#questions) - -[Go to the source code](../assets/layers/sidewalks/sidewalks.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- highway - =residential - |highway - =unclassified - |highway - =tertiary - |highway - =secondary - -Supported attributes ----------------------- - - - -**Warning** This quick overview is incomplete - -attribute | type | values which are supported by this layer ------------ | ------ | ------------------------------------------ -[](https://taginfo.openstreetmap.org/keys/sidewalk:left#values) [sidewalk:left](https://wiki.openstreetmap.org/wiki/Key:sidewalk:left) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:sidewalk:left%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:sidewalk:left%3Dno) -[](https://taginfo.openstreetmap.org/keys/sidewalk:left:width#values) [sidewalk:left:width](https://wiki.openstreetmap.org/wiki/Key:sidewalk:left:width) | [length](../SpecialInputElements.md#length) | -[](https://taginfo.openstreetmap.org/keys/sidewalk:right#values) [sidewalk:right](https://wiki.openstreetmap.org/wiki/Key:sidewalk:right) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:sidewalk:right%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:sidewalk:right%3Dno) -[](https://taginfo.openstreetmap.org/keys/sidewalk:right:width#values) [sidewalk:right:width](https://wiki.openstreetmap.org/wiki/Key:sidewalk:right:width) | [length](../SpecialInputElements.md#length) | - -### streetname - -_This tagrendering has no question and is thus read-only_ - -### left-sidewalk_minimap - -_This tagrendering has no question and is thus read-only_ - -### left-has_sidewalk - -The question is **Is there a sidewalk on this side of the road?** - -- **Yes, there is a sidewalk on this side of the road** corresponds - with sidewalk:left - =yes -- **No, there is no seperated sidewalk to walk on** corresponds - with sidewalk:left - =no - -### left-sidewalk_width - -The question is **What is the width of the sidewalk on this side of the road?** - -This rendering asks information about the -property [sidewalk:left:width](https://wiki.openstreetmap.org/wiki/Key:sidewalk:left:width) -This is rendered with `This sidewalk is {sidewalk:left:width}m wide` - -### questions - -_This tagrendering has no question and is thus read-only_ - -### right-sidewalk_minimap - -_This tagrendering has no question and is thus read-only_ - -### right-has_sidewalk - -The question is **Is there a sidewalk on this side of the road?** - -- **Yes, there is a sidewalk on this side of the road** corresponds - with sidewalk:right - =yes -- **No, there is no seperated sidewalk to walk on** corresponds - with sidewalk:right - =no - -### right-sidewalk_width - -The question is **What is the width of the sidewalk on this side of the road?** - -This rendering asks information about the -property [sidewalk:right:width](https://wiki.openstreetmap.org/wiki/Key:sidewalk:right:width) -This is rendered with `This sidewalk is {sidewalk:right:width}m wide` - -### questions - -_This tagrendering has no question and is thus read-only_ - -This document is autogenerated from assets/layers/sidewalks/sidewalks.json \ No newline at end of file diff --git a/Docs/Layers/slow_roads.md b/Docs/Layers/slow_roads.md index 1a5b5761b6..8c9fce9b01 100644 --- a/Docs/Layers/slow_roads.md +++ b/Docs/Layers/slow_roads.md @@ -12,22 +12,9 @@ All carfree roads -## Table of contents - -1. [slow_roads](#slow_roads) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [explanation](#explanation) - + [slow_roads-surface](#slow_roads-surface) - + [slow_road_is_lit](#slow_road_is_lit) - - - - + - This layer is shown at zoomlevel **16** and higher @@ -41,8 +28,6 @@ All carfree roads - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/slow_roads/slow_roads.json) - Basic tags for this layer diff --git a/Docs/Layers/split_point.md b/Docs/Layers/split_point.md deleted file mode 100644 index 8164c272d8..0000000000 --- a/Docs/Layers/split_point.md +++ /dev/null @@ -1,36 +0,0 @@ -split_point -============= - - - - - -Layer rendering the little scissors for the minimap in the 'splitRoadWizard' - -## Table of contents - -1. [split_point](#split_point) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - -[Go to the source code](../assets/layers/split_point/split_point.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- _split_point - =yes - -Supported attributes ----------------------- - - - -This document is autogenerated from assets/layers/split_point/split_point.json \ No newline at end of file diff --git a/Docs/Layers/sport_pitch.md b/Docs/Layers/sport_pitch.md index 87355e3f22..a0fe1fa2da 100644 --- a/Docs/Layers/sport_pitch.md +++ b/Docs/Layers/sport_pitch.md @@ -12,28 +12,9 @@ A sport pitch -## Table of contents - -1. [sport_pitch](#sport_pitch) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [sport_pitch-sport](#sport_pitch-sport) - + [sport_pitch-surface](#sport_pitch-surface) - + [sport-pitch-access](#sport-pitch-access) - + [sport-pitch-reservation](#sport-pitch-reservation) - + [sport_pitch-phone](#sport_pitch-phone) - + [sport_pitch-email](#sport_pitch-email) - + [sport_pitch-opening_hours](#sport_pitch-opening_hours) - + [questions](#questions) - + [sport-pitch-reviews](#sport-pitch-reviews) - - - - + - This layer is shown at zoomlevel **12** and higher @@ -48,8 +29,6 @@ A sport pitch - [sport_pitches](https://mapcomplete.osm.be/sport_pitches) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/sport_pitch/sport_pitch.json) - Basic tags for this layer diff --git a/Docs/Layers/sport_places_without_etymology.md b/Docs/Layers/sport_places_without_etymology.md new file mode 100644 index 0000000000..d195f23e0f --- /dev/null +++ b/Docs/Layers/sport_places_without_etymology.md @@ -0,0 +1,162 @@ + + + sport_places_without_etymology +================================ + + + + + +All objects which have an etymology known + + + + + + + - This layer is shown at zoomlevel **18** and higher + + + + +#### Themes using this layer + + + + + + - [etymology](https://mapcomplete.osm.be/etymology) + + + + + Basic tags for this layer +--------------------------- + + + +Elements must have the all of following tags to be shown on this layer: + + + + - name~^..*$ + - leisure=sports_centre|leisure=stadium|leisure=swimming_pool + + +[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22leisure%22%3D%22sports_centre%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22leisure%22%3D%22stadium%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22leisure%22%3D%22swimming_pool%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) + + + + Supported attributes +---------------------- + + + +**Warning** This quick overview is incomplete + + + +attribute | type | values which are supported by this layer +----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/name:etymology:wikidata#values) [name:etymology:wikidata](https://wiki.openstreetmap.org/wiki/Key:name:etymology:wikidata) | [wikidata](../SpecialInputElements.md#wikidata) | +[](https://taginfo.openstreetmap.org/keys/name:etymology#values) [name:etymology](https://wiki.openstreetmap.org/wiki/Key:name:etymology) | [string](../SpecialInputElements.md#string) | [unknown](https://wiki.openstreetmap.org/wiki/Tag:name:etymology%3Dunknown) + + + + +### etymology-images-from-wikipedia + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### wikipedia-etymology + + + +The question is **What is the Wikidata-item that this object is named after?** + +This rendering asks information about the property [name:etymology:wikidata](https://wiki.openstreetmap.org/wiki/Key:name:etymology:wikidata) +This is rendered with `

Wikipedia article of the name giver

{wikipedia(name:etymology:wikidata):max-height:20rem}` + + + +### zoeken op inventaris onroerend erfgoed + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### simple etymology + + + +The question is **What is this object named after?
This might be written on the street name sign** + +This rendering asks information about the property [name:etymology](https://wiki.openstreetmap.org/wiki/Key:name:etymology) +This is rendered with `Named after {name:etymology}` + + + + - **The origin of this name is unknown in all literature** corresponds with name:etymology=unknown + + + + +### questions + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### street-name-sign-image + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### minimap + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### etymology_multi_apply + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### wikipedia + + + +_This tagrendering has no question and is thus read-only_ + + + +This document is autogenerated from [assets/themes/etymology/etymology.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/etymology/etymology.json) \ No newline at end of file diff --git a/Docs/Layers/street_lamps.md b/Docs/Layers/street_lamps.md index 14bd158598..83f42657c0 100644 --- a/Docs/Layers/street_lamps.md +++ b/Docs/Layers/street_lamps.md @@ -12,26 +12,9 @@ A layer showing street lights -## Table of contents - -1. [street_lamps](#street_lamps) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [ref](#ref) - + [support](#support) - + [lamp_mount](#lamp_mount) - + [method](#method) - + [colour](#colour) - + [count](#count) - + [lit](#lit) - + [direction](#direction) - - - - + - This layer is shown at zoomlevel **0** and higher @@ -46,8 +29,6 @@ A layer showing street lights - [street_lighting](https://mapcomplete.osm.be/street_lighting) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/street_lamps/street_lamps.json) - Basic tags for this layer diff --git a/Docs/Layers/streets_without_etymology.md b/Docs/Layers/streets_without_etymology.md new file mode 100644 index 0000000000..2f098fc418 --- /dev/null +++ b/Docs/Layers/streets_without_etymology.md @@ -0,0 +1,163 @@ + + + streets_without_etymology +=========================== + + + + + +All objects which have an etymology known + + + + + + + - This layer is shown at zoomlevel **18** and higher + + + + +#### Themes using this layer + + + + + + - [etymology](https://mapcomplete.osm.be/etymology) + + + + + Basic tags for this layer +--------------------------- + + + +Elements must have the all of following tags to be shown on this layer: + + + + - name~^..*$ + - highway~^..*$ + - highway!~^bus_stop$ + + +[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22name%22%5D%5B%22highway%22%5D%5B%22highway%22!~%22%5Ebus_stop%24%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) + + + + Supported attributes +---------------------- + + + +**Warning** This quick overview is incomplete + + + +attribute | type | values which are supported by this layer +----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/name:etymology:wikidata#values) [name:etymology:wikidata](https://wiki.openstreetmap.org/wiki/Key:name:etymology:wikidata) | [wikidata](../SpecialInputElements.md#wikidata) | +[](https://taginfo.openstreetmap.org/keys/name:etymology#values) [name:etymology](https://wiki.openstreetmap.org/wiki/Key:name:etymology) | [string](../SpecialInputElements.md#string) | [unknown](https://wiki.openstreetmap.org/wiki/Tag:name:etymology%3Dunknown) + + + + +### etymology-images-from-wikipedia + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### wikipedia-etymology + + + +The question is **What is the Wikidata-item that this object is named after?** + +This rendering asks information about the property [name:etymology:wikidata](https://wiki.openstreetmap.org/wiki/Key:name:etymology:wikidata) +This is rendered with `

Wikipedia article of the name giver

{wikipedia(name:etymology:wikidata):max-height:20rem}` + + + +### zoeken op inventaris onroerend erfgoed + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### simple etymology + + + +The question is **What is this object named after?
This might be written on the street name sign** + +This rendering asks information about the property [name:etymology](https://wiki.openstreetmap.org/wiki/Key:name:etymology) +This is rendered with `Named after {name:etymology}` + + + + - **The origin of this name is unknown in all literature** corresponds with name:etymology=unknown + + + + +### questions + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### street-name-sign-image + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### minimap + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### etymology_multi_apply + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### wikipedia + + + +_This tagrendering has no question and is thus read-only_ + + + +This document is autogenerated from [assets/themes/etymology/etymology.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/etymology/etymology.json) \ No newline at end of file diff --git a/Docs/Layers/surveillance_camera.md b/Docs/Layers/surveillance_camera.md index 428e106fbf..3790ee7f02 100644 --- a/Docs/Layers/surveillance_camera.md +++ b/Docs/Layers/surveillance_camera.md @@ -12,26 +12,9 @@ This layer shows surveillance cameras and allows a contributor to update informa -## Table of contents - -1. [surveillance_camera](#surveillance_camera) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [Camera type: fixed; panning; dome](#camera-type-fixed;-panning;-dome) - + [camera_direction](#camera_direction) - + [Operator](#operator) - + [Surveillance type: public, outdoor, indoor](#surveillance-type-public,-outdoor,-indoor) - + [is_indoor](#is_indoor) - + [Level](#level) - + [Surveillance:zone](#surveillancezone) - + [camera:mount](#cameramount) - - - + - This layer is shown at zoomlevel **12** and higher - This layer will automatically load [walls_and_buildings](./walls_and_buildings.md) into the layout as it depends on it: a preset snaps to this layer (presets[1]) @@ -47,8 +30,6 @@ This layer shows surveillance cameras and allows a contributor to update informa - [surveillance](https://mapcomplete.osm.be/surveillance) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/surveillance_camera/surveillance_camera.json) - Basic tags for this layer diff --git a/Docs/Layers/to_import.md b/Docs/Layers/to_import.md deleted file mode 100644 index ca546e45ff..0000000000 --- a/Docs/Layers/to_import.md +++ /dev/null @@ -1,73 +0,0 @@ -to_import -=========== - - - - - -Alamat - -## Table of contents - -1. [to_import](#to_import) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [uk_addresses_explanation](#uk_addresses_explanation) - + [uk_addresses_embedding_outline](#uk_addresses_embedding_outline) - + [uk_addresses_import_button](#uk_addresses_import_button) - - -- This layer is loaded from an external source, namely `https://osm-uk-addresses.russss.dev/addresses/{z}/{x}/{y}.json` -- This layer will automatically load [address](./address.md) into the layout as it depends on it: a tagrendering - needs this layer (uk_addresses_import_button) -- This layer will automatically load [address](./address.md) into the layout as it depends on it: A calculated tag - loads features from this layer (calculatedTag[0] which calculates the value for _embedding_object) -- This layer will automatically load [raw_inspire_polygons](./raw_inspire_polygons.md) into the layout as it depends - on it: A calculated tag loads features from this layer (calculatedTag[3] which calculates the value for _ - embedding_inspire_polygon_has_address) - -[Go to the source code](../assets/layers/to_import/to_import.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- inspireid~^..*$ - -Supported attributes ----------------------- - - - -**Warning** This quick overview is incomplete - -attribute | type | values which are supported by this layer ------------ | ------ | ------------------------------------------ -[](https://taginfo.openstreetmap.org/keys/_embedding_object:id#values) [_embedding_object:id](https://wiki.openstreetmap.org/wiki/Key:_embedding_object:id) | Multiple choice | [true](https://wiki.openstreetmap.org/wiki/Tag:_embedding_object:id%3Dtrue) [false](https://wiki.openstreetmap.org/wiki/Tag:_embedding_object:id%3Dfalse) - -### uk_addresses_explanation - -_This tagrendering has no question and is thus read-only_ - -### uk_addresses_embedding_outline - -_This tagrendering has no question and is thus read-only_ - -- **The INSPIRE-polygon containing this point has at least one address contained** corresponds - with _embedding_object:id - =true -- **The INSPIRE-polygon containing this point has no addresses contained** corresponds - with _embedding_object:id - =false - -### uk_addresses_import_button - -_This tagrendering has no question and is thus read-only_ - -This document is autogenerated from assets/layers/to_import/to_import.json \ No newline at end of file diff --git a/Docs/Layers/toekomstige_fietsstraat.md b/Docs/Layers/toekomstige_fietsstraat.md index d411f8e986..207964b304 100644 --- a/Docs/Layers/toekomstige_fietsstraat.md +++ b/Docs/Layers/toekomstige_fietsstraat.md @@ -1,4 +1,6 @@ -toekomstige_fietsstraat + + + toekomstige_fietsstraat ========================= @@ -7,38 +9,115 @@ toekomstige_fietsstraat This street will become a cyclestreet soon -## Table of contents - -1. [toekomstige_fietsstraat](#toekomstige_fietsstraat) - * [Themes using this layer](#themes-using-this-layer) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [images](#images) - -#### Themes using this layer - -- [cyclestreets](https://mapcomplete.osm.be/cyclestreets) - -[Go to the source code](../assets/layers/toekomstige_fietsstraat/toekomstige_fietsstraat.json) -Basic tags for this layer + + + - This layer is shown at zoomlevel **9** and higher + + + + +#### Themes using this layer + + + + + + - [cyclestreets](https://mapcomplete.osm.be/cyclestreets) + + + + + Basic tags for this layer --------------------------- Elements must have the all of following tags to be shown on this layer: -- proposed:cyclestreet - =yes -Supported attributes + + - proposed:cyclestreet=yes + + +[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22proposed%3Acyclestreet%22%3D%22yes%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) + + + + Supported attributes ---------------------- -### images + + +**Warning** This quick overview is incomplete + + + +attribute | type | values which are supported by this layer +----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/cyclestreet#values) [cyclestreet](https://wiki.openstreetmap.org/wiki/Key:cyclestreet) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:cyclestreet%3Dyes) [yes](https://wiki.openstreetmap.org/wiki/Tag:cyclestreet%3Dyes) [](https://wiki.openstreetmap.org/wiki/Tag:cyclestreet%3D) [](https://wiki.openstreetmap.org/wiki/Tag:cyclestreet%3D) +[](https://taginfo.openstreetmap.org/keys/cyclestreet:start_date#values) [cyclestreet:start_date](https://wiki.openstreetmap.org/wiki/Key:cyclestreet:start_date) | [date](../SpecialInputElements.md#date) | + + + + +### images + + _This tagrendering has no question and is thus read-only_ -This document is autogenerated from assets/layers/toekomstige_fietsstraat/toekomstige_fietsstraat.json \ No newline at end of file + + + + +### is_cyclestreet + + + +The question is **Is the street {name} a cyclestreet?** + + + + + + - **This street is a cyclestreet (and has a speed limit of 30 km/h)** corresponds with cyclestreet=yes&maxspeed=30&overtaking:motor_vehicle=no + - **This street is a cyclestreet** corresponds with cyclestreet=yes + - **This street will become a cyclstreet soon** corresponds with proposed:cyclestreet=yes + - **This street is not a cyclestreet** corresponds with + + + + +### future_cyclestreet + + + +The question is **When will this street become a cyclestreet?** + +This rendering asks information about the property [cyclestreet:start_date](https://wiki.openstreetmap.org/wiki/Key:cyclestreet:start_date) +This is rendered with `This street will become a cyclestreet at {cyclestreet:start_date}` + + + +### questions + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### minimap + + + +_This tagrendering has no question and is thus read-only_ + + + +This document is autogenerated from [assets/themes/cyclestreets/cyclestreets.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/cyclestreets/cyclestreets.json) \ No newline at end of file diff --git a/Docs/Layers/toilet.md b/Docs/Layers/toilet.md index ed17f345ab..eef814a450 100644 --- a/Docs/Layers/toilet.md +++ b/Docs/Layers/toilet.md @@ -12,32 +12,9 @@ A layer showing (public) toilets -## Table of contents - -1. [toilet](#toilet) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [toilet-access](#toilet-access) - + [toilets-fee](#toilets-fee) - + [toilet-charge](#toilet-charge) - + [payment-options](#payment-options) - + [Opening-hours](#opening-hours) - + [toilets-wheelchair](#toilets-wheelchair) - + [toilets-type](#toilets-type) - + [toilets-changing-table](#toilets-changing-table) - + [toilet-changing_table:location](#toilet-changing_tablelocation) - + [toilet-handwashing](#toilet-handwashing) - + [toilet-has-paper](#toilet-has-paper) - + [level](#level) - + [description](#description) - - - - + - This layer is shown at zoomlevel **12** and higher @@ -53,8 +30,6 @@ A layer showing (public) toilets - [toilets](https://mapcomplete.osm.be/toilets) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/toilet/toilet.json) - Basic tags for this layer diff --git a/Docs/Layers/toursistic_places_without_etymology.md b/Docs/Layers/toursistic_places_without_etymology.md new file mode 100644 index 0000000000..bbc3402fc5 --- /dev/null +++ b/Docs/Layers/toursistic_places_without_etymology.md @@ -0,0 +1,162 @@ + + + toursistic_places_without_etymology +===================================== + + + + + +All objects which have an etymology known + + + + + + + - This layer is shown at zoomlevel **18** and higher + + + + +#### Themes using this layer + + + + + + - [etymology](https://mapcomplete.osm.be/etymology) + + + + + Basic tags for this layer +--------------------------- + + + +Elements must have the all of following tags to be shown on this layer: + + + + - name~^..*$ + - tourism=aquarium|tourism=museum|tourism=theme_park|tourism=zoo + + +[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22tourism%22%3D%22aquarium%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22tourism%22%3D%22museum%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22tourism%22%3D%22theme_park%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22tourism%22%3D%22zoo%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) + + + + Supported attributes +---------------------- + + + +**Warning** This quick overview is incomplete + + + +attribute | type | values which are supported by this layer +----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/name:etymology:wikidata#values) [name:etymology:wikidata](https://wiki.openstreetmap.org/wiki/Key:name:etymology:wikidata) | [wikidata](../SpecialInputElements.md#wikidata) | +[](https://taginfo.openstreetmap.org/keys/name:etymology#values) [name:etymology](https://wiki.openstreetmap.org/wiki/Key:name:etymology) | [string](../SpecialInputElements.md#string) | [unknown](https://wiki.openstreetmap.org/wiki/Tag:name:etymology%3Dunknown) + + + + +### etymology-images-from-wikipedia + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### wikipedia-etymology + + + +The question is **What is the Wikidata-item that this object is named after?** + +This rendering asks information about the property [name:etymology:wikidata](https://wiki.openstreetmap.org/wiki/Key:name:etymology:wikidata) +This is rendered with `

Wikipedia article of the name giver

{wikipedia(name:etymology:wikidata):max-height:20rem}` + + + +### zoeken op inventaris onroerend erfgoed + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### simple etymology + + + +The question is **What is this object named after?
This might be written on the street name sign** + +This rendering asks information about the property [name:etymology](https://wiki.openstreetmap.org/wiki/Key:name:etymology) +This is rendered with `Named after {name:etymology}` + + + + - **The origin of this name is unknown in all literature** corresponds with name:etymology=unknown + + + + +### questions + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### street-name-sign-image + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### minimap + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### etymology_multi_apply + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### wikipedia + + + +_This tagrendering has no question and is thus read-only_ + + + +This document is autogenerated from [assets/themes/etymology/etymology.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/etymology/etymology.json) \ No newline at end of file diff --git a/Docs/Layers/town_hall.md b/Docs/Layers/town_hall.md deleted file mode 100644 index 54230f32a6..0000000000 --- a/Docs/Layers/town_hall.md +++ /dev/null @@ -1,41 +0,0 @@ -town_hall -=========== - - - - - -## Table of contents - -1. [town_hall](#town_hall) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - - -- This layer will automatically load [postal_code_boundary](./postal_code_boundary.md) into the layout as it depends - on it: A calculated tag loads features from this layer (calculatedTag[0] which calculates the value for _ - postal_code_properties) - -[Go to the source code](../assets/layers/town_hall/town_hall.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- amenity - =townhall - |building - =church - -Supported attributes ----------------------- - - - -This document is autogenerated from assets/layers/town_hall/town_hall.json \ No newline at end of file diff --git a/Docs/Layers/trail.md b/Docs/Layers/trail.md index 6d37dd4b2a..e73b829440 100644 --- a/Docs/Layers/trail.md +++ b/Docs/Layers/trail.md @@ -12,25 +12,9 @@ Aangeduide wandeltochten -## Table of contents - -1. [trail](#trail) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [trail-length](#trail-length) - + [Name](#name) - + [Operator tag](#operator-tag) - + [Color](#color) - + [Wheelchair access](#wheelchair-access) - + [pushchair access](#pushchair-access) - - - - + - This layer is shown at zoomlevel **12** and higher @@ -44,8 +28,6 @@ Aangeduide wandeltochten - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/trail/trail.json) - Basic tags for this layer diff --git a/Docs/Layers/tree_node.md b/Docs/Layers/tree_node.md index 459e75a4e8..a182942ac9 100644 --- a/Docs/Layers/tree_node.md +++ b/Docs/Layers/tree_node.md @@ -12,27 +12,9 @@ A layer showing trees -## Table of contents - -1. [tree_node](#tree_node) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [tree-height](#tree-height) - + [tree-leaf_type](#tree-leaf_type) - + [tree-denotation](#tree-denotation) - + [tree-decidouous](#tree-decidouous) - + [tree_node-name](#tree_node-name) - + [tree-heritage](#tree-heritage) - + [tree_node-ref:OnroerendErfgoed](#tree_node-refonroerenderfgoed) - + [tree_node-wikidata](#tree_node-wikidata) - - - - + - This layer is shown at zoomlevel **16** and higher @@ -47,8 +29,6 @@ A layer showing trees - [trees](https://mapcomplete.osm.be/trees) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/tree_node/tree_node.json) - Basic tags for this layer diff --git a/Docs/Layers/type_node.md b/Docs/Layers/type_node.md deleted file mode 100644 index d584c121f5..0000000000 --- a/Docs/Layers/type_node.md +++ /dev/null @@ -1,42 +0,0 @@ -type_node -=========== - - - - - -This is a priviliged meta_layer which exports _every_ point in OSM. This only works if zoomed below the point that the -full tile is loaded (and not loaded via Overpass). Note that this point will also contain a property `parent_ways` which -contains all the ways this node is part of as a list. This is mainly used for extremely specialized themes, which do -advanced conflations. Expert use only. - -## Table of contents - -1. [type_node](#type_node) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - - -- Not rendered on the map by default. If you want to rendering this on the map, override `mapRenderings` -- This layer is needed as dependency for layer [grb](#grb) - -[Go to the source code](../assets/layers/type_node/type_node.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- id~^node\/.*$ - -Supported attributes ----------------------- - - - -This document is autogenerated from assets/layers/type_node/type_node.json \ No newline at end of file diff --git a/Docs/Layers/viewpoint.md b/Docs/Layers/viewpoint.md index 1eef4684b9..b2bac8d415 100644 --- a/Docs/Layers/viewpoint.md +++ b/Docs/Layers/viewpoint.md @@ -12,20 +12,9 @@ A nice viewpoint or nice view. Ideal to add an image if no other category fits -## Table of contents - -1. [viewpoint](#viewpoint) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [viewpoint-description](#viewpoint-description) - - - - + - This layer is shown at zoomlevel **14** and higher @@ -39,8 +28,6 @@ A nice viewpoint or nice view. Ideal to add an image if no other category fits - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/viewpoint/viewpoint.json) - Basic tags for this layer diff --git a/Docs/Layers/village_green.md b/Docs/Layers/village_green.md index 0eadc8fbc5..f38e8d236d 100644 --- a/Docs/Layers/village_green.md +++ b/Docs/Layers/village_green.md @@ -7,26 +7,14 @@ -A layer showing village-green (which are communal green areas, but not quite parks" - - - - -## Table of contents - -1. [village_green](#village_green) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [village_green-explanation](#village_green-explanation) - + [village_green-reviews](#village_green-reviews) +A layer showing village-green (which are communal green areas, but not quite parks) + - This layer is shown at zoomlevel **0** and higher @@ -40,8 +28,6 @@ A layer showing village-green (which are communal green areas, but not quite par - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/village_green/village_green.json) - Basic tags for this layer diff --git a/Docs/Layers/visitor_information_centre.md b/Docs/Layers/visitor_information_centre.md index 513aa11463..932e14c08d 100644 --- a/Docs/Layers/visitor_information_centre.md +++ b/Docs/Layers/visitor_information_centre.md @@ -12,18 +12,9 @@ A visitor center offers information about a specific attraction or place of inte -## Table of contents - -1. [visitor_information_centre](#visitor_information_centre) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - - - - + - This layer is shown at zoomlevel **12** and higher @@ -37,8 +28,6 @@ A visitor center offers information about a specific attraction or place of inte - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/visitor_information_centre/visitor_information_centre.json) - Basic tags for this layer diff --git a/Docs/Layers/walking_routes.md b/Docs/Layers/walking_routes.md deleted file mode 100644 index 81cf103077..0000000000 --- a/Docs/Layers/walking_routes.md +++ /dev/null @@ -1,111 +0,0 @@ -walking_routes -================ - - - - - -Walking routes by 'provincie Antwerpen' - -## Table of contents - -1. [walking_routes](#walking_routes) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [walk-length](#walk-length) - + [walk-type](#walk-type) - + [walk-description](#walk-description) - + [walk-operator](#walk-operator) - + [walk-operator-email](#walk-operator-email) - + [questions](#questions) - + [reviews](#reviews) - - -- Not rendered on the map by default. If you want to rendering this on the map, override `mapRenderings` -- This layer is loaded from an external source, namely `https://raw.githubusercontent.com/pietervdvn/MapComplete-data/main/speelplekken_cache/speelplekken_{layer}_{z}_{x}_{y}.geojson` - -[Go to the source code](../assets/layers/walking_routes/walking_routes.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- type - =route -- route - =foot -- operator~^[pP]rovincie Antwerpen$ - -Supported attributes ----------------------- - - - -**Warning** This quick overview is incomplete - -attribute | type | values which are supported by this layer ------------ | ------ | ------------------------------------------ -[](https://taginfo.openstreetmap.org/keys/route#values) [route](https://wiki.openstreetmap.org/wiki/Key:route) | Multiple choice | [iwn](https://wiki.openstreetmap.org/wiki/Tag:route%3Diwn) [nwn](https://wiki.openstreetmap.org/wiki/Tag:route%3Dnwn) [rwn](https://wiki.openstreetmap.org/wiki/Tag:route%3Drwn) [lwn](https://wiki.openstreetmap.org/wiki/Tag:route%3Dlwn) -[](https://taginfo.openstreetmap.org/keys/description#values) [description](https://wiki.openstreetmap.org/wiki/Key:description) | [text](../SpecialInputElements.md#text) | -[](https://taginfo.openstreetmap.org/keys/operator#values) [operator](https://wiki.openstreetmap.org/wiki/Key:operator) | [string](../SpecialInputElements.md#string) | -[](https://taginfo.openstreetmap.org/keys/operator:email#values) [operator:email](https://wiki.openstreetmap.org/wiki/Key:operator:email) | [email](../SpecialInputElements.md#email) | - -### walk-length - -_This tagrendering has no question and is thus read-only_ - -### walk-type - -_This tagrendering has no question and is thus read-only_ - -- **Dit is een internationale wandelroute** corresponds - with route - =iwn -- **Dit is een nationale wandelroute** corresponds - with route - =nwn -- **Dit is een regionale wandelroute** corresponds - with route - =rwn -- **Dit is een lokale wandelroute** corresponds - with route - =lwn - -### walk-description - -The question is **Geef een korte beschrijving van de wandeling (max 255 tekens)** - -This rendering asks information about the property [description](https://wiki.openstreetmap.org/wiki/Key:description) -This is rendered with `

Korte beschrijving:

{description}` - -### walk-operator - -The question is **Wie beheert deze wandeling en plaatst dus de signalisatiebordjes?** - -This rendering asks information about the property [operator](https://wiki.openstreetmap.org/wiki/Key:operator) -This is rendered with `Signalisatie geplaatst door {operator}` - -### walk-operator-email - -The question is **Naar wie kan men emailen bij problemen rond signalisatie?** - -This rendering asks information about the -property [operator:email](https://wiki.openstreetmap.org/wiki/Key:operator:email) -This is rendered -with `Bij problemen met signalisatie kan men emailen naar {operator:email}` - -### questions - -_This tagrendering has no question and is thus read-only_ - -### reviews - -_This tagrendering has no question and is thus read-only_ - -This document is autogenerated from assets/layers/walking_routes/walking_routes.json \ No newline at end of file diff --git a/Docs/Layers/walls_and_buildings.md b/Docs/Layers/walls_and_buildings.md index 9d4ed1e8b6..bb24335506 100644 --- a/Docs/Layers/walls_and_buildings.md +++ b/Docs/Layers/walls_and_buildings.md @@ -12,17 +12,9 @@ Special builtin layer providing all walls and buildings. This layer is useful in -## Table of contents - -1. [walls_and_buildings](#walls_and_buildings) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - - - + - This layer is shown at zoomlevel **18** and higher - This layer is not visible by default and must be enabled in the filter by the user. - Not visible in the layer selection by default. If you want to make this layer toggable, override `name` - Not rendered on the map by default. If you want to rendering this on the map, override `mapRenderings` @@ -45,8 +37,6 @@ Special builtin layer providing all walls and buildings. This layer is useful in - [surveillance](https://mapcomplete.osm.be/surveillance) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/walls_and_buildings/walls_and_buildings.json) - Basic tags for this layer diff --git a/Docs/Layers/waste_basket.md b/Docs/Layers/waste_basket.md index 300dea778f..a8386f4194 100644 --- a/Docs/Layers/waste_basket.md +++ b/Docs/Layers/waste_basket.md @@ -12,20 +12,9 @@ This is a public waste basket, thrash can, where you can throw away your thrash. -## Table of contents - -1. [waste_basket](#waste_basket) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [waste-basket-waste-types](#waste-basket-waste-types) - + [dispensing_dog_bags](#dispensing_dog_bags) - - - - + - This layer is shown at zoomlevel **17** and higher @@ -41,8 +30,6 @@ This is a public waste basket, thrash can, where you can throw away your thrash. - [waste_basket](https://mapcomplete.osm.be/waste_basket) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/waste_basket/waste_basket.json) - Basic tags for this layer diff --git a/Docs/Layers/waste_disposal.md b/Docs/Layers/waste_disposal.md index 1af2b86e4b..e045ca33f0 100644 --- a/Docs/Layers/waste_disposal.md +++ b/Docs/Layers/waste_disposal.md @@ -12,20 +12,9 @@ Waste Disposal Bin, medium to large bin for disposal of (household) waste -## Table of contents - -1. [waste_disposal](#waste_disposal) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [access](#access) - + [disposal-location](#disposal-location) - - - - + - This layer is shown at zoomlevel **18** and higher @@ -40,8 +29,6 @@ Waste Disposal Bin, medium to large bin for disposal of (household) waste - [waste](https://mapcomplete.osm.be/waste) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/waste_disposal/waste_disposal.json) - Basic tags for this layer diff --git a/Docs/Layers/watermill.md b/Docs/Layers/watermill.md index f3ad0ce21f..6d1e624eb9 100644 --- a/Docs/Layers/watermill.md +++ b/Docs/Layers/watermill.md @@ -12,21 +12,9 @@ Watermolens -## Table of contents - -1. [watermill](#watermill) - * [Themes using this layer](#themes-using-this-layer) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [images](#images) - + [Access tag](#access-tag) - + [Operator tag](#operator-tag) - - - - + - This layer is shown at zoomlevel **12** and higher @@ -40,8 +28,6 @@ Watermolens - [personal](https://mapcomplete.osm.be/personal) -[Go to the source code](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/watermill/watermill.json) - Basic tags for this layer diff --git a/Docs/Layers/windturbine.md b/Docs/Layers/windturbine.md index f8873bf9ef..110fe27418 100644 --- a/Docs/Layers/windturbine.md +++ b/Docs/Layers/windturbine.md @@ -1,96 +1,150 @@ -windturbine + + + windturbine ============= -## Table of contents - -1. [windturbine](#windturbine) - * [Themes using this layer](#themes-using-this-layer) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - + [turbine-output](#turbine-output) - + [turbine-operator](#turbine-operator) - + [turbine-height](#turbine-height) - + [turbine-diameter](#turbine-diameter) - + [turbine-start-date](#turbine-start-date) - + [images](#images) - -#### Themes using this layer - -- [openwindpowermap](https://mapcomplete.osm.be/openwindpowermap) - -[Go to the source code](../assets/layers/windturbine/windturbine.json) -Basic tags for this layer + + + - This layer is shown at zoomlevel **10** and higher + + + + +#### Themes using this layer + + + + + + - [openwindpowermap](https://mapcomplete.osm.be/openwindpowermap) + + + + + Basic tags for this layer --------------------------- Elements must have the all of following tags to be shown on this layer: -- generator:source - =wind -Supported attributes + + - generator:source=wind + + +[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22generator%3Asource%22%3D%22wind%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) + + + + Supported attributes ---------------------- **Warning** This quick overview is incomplete + + attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ -[](https://taginfo.openstreetmap.org/keys/generator:output:electricity#values) [generator:output:electricity](https://wiki.openstreetmap.org/wiki/Key:generator:output:electricity) | [pfloat](../SpecialInputElements.md#pfloat) | -[](https://taginfo.openstreetmap.org/keys/operator#values) [operator](https://wiki.openstreetmap.org/wiki/Key:operator) | [string](../SpecialInputElements.md#string) | -[](https://taginfo.openstreetmap.org/keys/height#values) [height](https://wiki.openstreetmap.org/wiki/Key:height) | [pfloat](../SpecialInputElements.md#pfloat) | -[](https://taginfo.openstreetmap.org/keys/rotor:diameter#values) [rotor:diameter](https://wiki.openstreetmap.org/wiki/Key:rotor:diameter) | [float](../SpecialInputElements.md#float) | -[](https://taginfo.openstreetmap.org/keys/start_date#values) [start_date](https://wiki.openstreetmap.org/wiki/Key:start_date) | [date](../SpecialInputElements.md#date) | +[](https://taginfo.openstreetmap.org/keys/generator:output:electricity#values) [generator:output:electricity](https://wiki.openstreetmap.org/wiki/Key:generator:output:electricity) | [pfloat](../SpecialInputElements.md#pfloat) | +[](https://taginfo.openstreetmap.org/keys/operator#values) [operator](https://wiki.openstreetmap.org/wiki/Key:operator) | [string](../SpecialInputElements.md#string) | +[](https://taginfo.openstreetmap.org/keys/height#values) [height](https://wiki.openstreetmap.org/wiki/Key:height) | [pfloat](../SpecialInputElements.md#pfloat) | +[](https://taginfo.openstreetmap.org/keys/rotor:diameter#values) [rotor:diameter](https://wiki.openstreetmap.org/wiki/Key:rotor:diameter) | [float](../SpecialInputElements.md#float) | +[](https://taginfo.openstreetmap.org/keys/start_date#values) [start_date](https://wiki.openstreetmap.org/wiki/Key:start_date) | [date](../SpecialInputElements.md#date) | + + + + +### turbine-output + -### turbine-output The question is **What is the power output of this wind turbine? (e.g. 2.3 MW)** -This rendering asks information about the -property [generator:output:electricity](https://wiki.openstreetmap.org/wiki/Key:generator:output:electricity) +This rendering asks information about the property [generator:output:electricity](https://wiki.openstreetmap.org/wiki/Key:generator:output:electricity) This is rendered with `The power output of this wind turbine is {generator:output:electricity}.` -### turbine-operator + + +### turbine-operator + + The question is **Who operates this wind turbine?** -This rendering asks information about the property [operator](https://wiki.openstreetmap.org/wiki/Key:operator) +This rendering asks information about the property [operator](https://wiki.openstreetmap.org/wiki/Key:operator) This is rendered with `This wind turbine is operated by {operator}.` -### turbine-height + + +### turbine-height + + The question is **What is the total height of this wind turbine (including rotor radius), in metres?** -This rendering asks information about the property [height](https://wiki.openstreetmap.org/wiki/Key:height) +This rendering asks information about the property [height](https://wiki.openstreetmap.org/wiki/Key:height) This is rendered with `The total height (including rotor radius) of this wind turbine is {height} metres.` -### turbine-diameter + + +### turbine-diameter + + The question is **What is the rotor diameter of this wind turbine, in metres?** -This rendering asks information about the -property [rotor:diameter](https://wiki.openstreetmap.org/wiki/Key:rotor:diameter) +This rendering asks information about the property [rotor:diameter](https://wiki.openstreetmap.org/wiki/Key:rotor:diameter) This is rendered with `The rotor diameter of this wind turbine is {rotor:diameter} metres.` -### turbine-start-date + + +### turbine-start-date + + The question is **When did this wind turbine go into operation?** -This rendering asks information about the property [start_date](https://wiki.openstreetmap.org/wiki/Key:start_date) +This rendering asks information about the property [start_date](https://wiki.openstreetmap.org/wiki/Key:start_date) This is rendered with `This wind turbine went into operation on/in {start_date}.` -### images + + +### images + + _This tagrendering has no question and is thus read-only_ -This document is autogenerated from assets/layers/windturbine/windturbine.json \ No newline at end of file + + + + +### questions + + + +_This tagrendering has no question and is thus read-only_ + + + + + +### minimap + + + +_This tagrendering has no question and is thus read-only_ + + + +This document is autogenerated from [assets/themes/openwindpowermap/openwindpowermap.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/openwindpowermap/openwindpowermap.json) \ No newline at end of file diff --git a/Docs/Layers/wrong_postal_code.md b/Docs/Layers/wrong_postal_code.md deleted file mode 100644 index 572aaedfb8..0000000000 --- a/Docs/Layers/wrong_postal_code.md +++ /dev/null @@ -1,34 +0,0 @@ -wrong_postal_code -=================== - -## Table of contents - -1. [wrong_postal_code](#wrong_postal_code) - -- [Basic tags for this layer](#basic-tags-for-this-layer) -- [Supported attributes](#supported-attributes) - - -- Not visible in the layer selection by default. If you want to make this layer toggable, override `name` -- Not rendered on the map by default. If you want to rendering this on the map, override `mapRenderings` - -[Go to the source code](../assets/layers/wrong_postal_code/wrong_postal_code.json) - - - -Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - -- boundary~^..*$ -- addr:postcode~^..*$ - -Supported attributes ----------------------- - - - -This document is autogenerated from assets/layers/wrong_postal_code/wrong_postal_code.json \ No newline at end of file diff --git a/Docs/Misc/SidewalksMapComplete.png b/Docs/Misc/SidewalksMapComplete.png new file mode 100644 index 0000000000..1373b041c9 Binary files /dev/null and b/Docs/Misc/SidewalksMapComplete.png differ diff --git a/Docs/Schemas/AndOrTagConfigJsonJSC.ts b/Docs/Schemas/AndOrTagConfigJsonJSC.ts index 6600f85021..3da8b5b091 100644 --- a/Docs/Schemas/AndOrTagConfigJsonJSC.ts +++ b/Docs/Schemas/AndOrTagConfigJsonJSC.ts @@ -1,37 +1,37 @@ export default { - "$ref": "#/definitions/AndOrTagConfigJson", - "definitions": { - "AndOrTagConfigJson": { - "type": "object", - "properties": { - "and": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - } - }, - "or": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - } + "$ref": "#/definitions/AndOrTagConfigJson", + "definitions": { + "AndOrTagConfigJson": { + "type": "object", + "properties": { + "and": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + }, + "or": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + } + } } - } - } - }, - "$schema": "http://json-schema.org/draft-07/schema#" + }, + "$schema": "http://json-schema.org/draft-07/schema#" } \ No newline at end of file diff --git a/Docs/Schemas/DeleteConfigJsonJSC.ts b/Docs/Schemas/DeleteConfigJsonJSC.ts index bdc96c0c48..eb67718d7b 100644 --- a/Docs/Schemas/DeleteConfigJsonJSC.ts +++ b/Docs/Schemas/DeleteConfigJsonJSC.ts @@ -1,91 +1,91 @@ export default { - "type": "object", - "properties": { - "extraDeleteReasons": { - "description": "*\nBy default, three reasons to delete a point are shown:\n\n- The point does not exist anymore\n- The point was a testing point\n- THe point could not be found\n\nHowever, for some layers, there might be different or more specific reasons for deletion which can be user friendly to set, e.g.:\n\n- the shop has closed\n- the climbing route has been closed of for nature conservation reasons\n- ...\n\nThese reasons can be stated here and will be shown in the list of options the user can choose from", - "type": "array", - "items": { - "type": "object", - "properties": { - "explanation": { - "description": "The text that will be shown to the user - translatable" - }, - "changesetMessage": { - "description": "The text that will be uploaded into the changeset or will be used in the fixme in case of a soft deletion\nShould be a few words, in english", - "type": "string" - } + "type": "object", + "properties": { + "extraDeleteReasons": { + "description": "*\nBy default, three reasons to delete a point are shown:\n\n- The point does not exist anymore\n- The point was a testing point\n- THe point could not be found\n\nHowever, for some layers, there might be different or more specific reasons for deletion which can be user friendly to set, e.g.:\n\n- the shop has closed\n- the climbing route has been closed of for nature conservation reasons\n- ...\n\nThese reasons can be stated here and will be shown in the list of options the user can choose from", + "type": "array", + "items": { + "type": "object", + "properties": { + "explanation": { + "description": "The text that will be shown to the user - translatable" + }, + "changesetMessage": { + "description": "The text that will be uploaded into the changeset or will be used in the fixme in case of a soft deletion\nShould be a few words, in english", + "type": "string" + } + }, + "required": [ + "changesetMessage", + "explanation" + ] + } }, - "required": [ - "changesetMessage", - "explanation" - ] - } - }, - "nonDeleteMappings": { - "description": "In some cases, a (starting) contributor might wish to delete a feature even though deletion is not appropriate.\n(The most relevant case are small paths running over private property. These should be marked as 'private' instead of deleted, as the community might trace the path again from aerial imagery, gettting us back to the original situation).\n\nBy adding a 'nonDeleteMapping', an option can be added into the list which will retag the feature.\nIt is important that the feature will be retagged in such a way that it won't be picked up by the layer anymore!", - "type": "array", - "items": { - "type": "object", - "properties": { - "if": { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - "then": {} + "nonDeleteMappings": { + "description": "In some cases, a (starting) contributor might wish to delete a feature even though deletion is not appropriate.\n(The most relevant case are small paths running over private property. These should be marked as 'private' instead of deleted, as the community might trace the path again from aerial imagery, gettting us back to the original situation).\n\nBy adding a 'nonDeleteMapping', an option can be added into the list which will retag the feature.\nIt is important that the feature will be retagged in such a way that it won't be picked up by the layer anymore!", + "type": "array", + "items": { + "type": "object", + "properties": { + "if": { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + "then": {} + }, + "required": [ + "if", + "then" + ] + } }, - "required": [ - "if", - "then" - ] - } - }, - "softDeletionTags": { - "description": "In some cases, the contributor is not allowed to delete the current feature (e.g. because it isn't a point, the point is referenced by a relation or the user isn't experienced enough).\nTo still offer the user a 'delete'-option, the feature is retagged with these tags. This is a soft deletion, as the point isn't actually removed from OSM but rather marked as 'disused'\nIt is important that the feature will be retagged in such a way that it won't be picked up by the layer anymore!\n\nExample (note that \"amenity=\" erases the 'amenity'-key alltogether):\n```\n{\n \"and\": [\"disussed:amenity=public_bookcase\", \"amenity=\"]\n}\n```\n\nor (notice the use of the ':='-tag to copy the old value of 'shop=*' into 'disused:shop='):\n```\n{\n \"and\": [\"disused:shop:={shop}\", \"shop=\"]\n}\n```", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - }, - "neededChangesets": { - "description": "*\nBy default, the contributor needs 20 previous changesets to delete points edited by others.\nFor some small features (e.g. bicycle racks) this is too much and this requirement can be lowered or dropped, which can be done here.", - "type": "number" - } - }, - "definitions": { - "AndOrTagConfigJson": { - "type": "object", - "properties": { - "and": { - "type": "array", - "items": { + "softDeletionTags": { + "description": "In some cases, the contributor is not allowed to delete the current feature (e.g. because it isn't a point, the point is referenced by a relation or the user isn't experienced enough).\nTo still offer the user a 'delete'-option, the feature is retagged with these tags. This is a soft deletion, as the point isn't actually removed from OSM but rather marked as 'disused'\nIt is important that the feature will be retagged in such a way that it won't be picked up by the layer anymore!\n\nExample (note that \"amenity=\" erases the 'amenity'-key alltogether):\n```\n{\n \"and\": [\"disussed:amenity=public_bookcase\", \"amenity=\"]\n}\n```\n\nor (notice the use of the ':='-tag to copy the old value of 'shop=*' into 'disused:shop='):\n```\n{\n \"and\": [\"disused:shop:={shop}\", \"shop=\"]\n}\n```", "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } ] - } }, - "or": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - } + "neededChangesets": { + "description": "*\nBy default, the contributor needs 20 previous changesets to delete points edited by others.\nFor some small features (e.g. bicycle racks) this is too much and this requirement can be lowered or dropped, which can be done here.", + "type": "number" } - } - } - }, - "$schema": "http://json-schema.org/draft-07/schema#" + }, + "definitions": { + "AndOrTagConfigJson": { + "type": "object", + "properties": { + "and": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + }, + "or": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + } + } + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" } \ No newline at end of file diff --git a/Docs/Schemas/ExtraLinkConfigJsonJSC.ts b/Docs/Schemas/ExtraLinkConfigJsonJSC.ts index b3175e1c4a..1c751bf9ad 100644 --- a/Docs/Schemas/ExtraLinkConfigJsonJSC.ts +++ b/Docs/Schemas/ExtraLinkConfigJsonJSC.ts @@ -1,64 +1,64 @@ export default { - "type": "object", - "properties": { - "icon": { - "type": "string" - }, - "text": {}, - "href": { - "type": "string" - }, - "newTab": { - "type": "boolean" - }, - "requirements": { - "type": "array", - "items": { - "enum": [ - "iframe", - "no-iframe", - "no-welcome-message", - "welcome-message" - ], - "type": "string" - } - } - }, - "required": [ - "href" - ], - "definitions": { - "AndOrTagConfigJson": { - "type": "object", - "properties": { - "and": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - } + "type": "object", + "properties": { + "icon": { + "type": "string" }, - "or": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { + "text": {}, + "href": { + "type": "string" + }, + "newTab": { + "type": "boolean" + }, + "requirements": { + "type": "array", + "items": { + "enum": [ + "iframe", + "no-iframe", + "no-welcome-message", + "welcome-message" + ], "type": "string" - } - ] - } + } } - } - } - }, - "$schema": "http://json-schema.org/draft-07/schema#" + }, + "required": [ + "href" + ], + "definitions": { + "AndOrTagConfigJson": { + "type": "object", + "properties": { + "and": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + }, + "or": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + } + } + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" } \ No newline at end of file diff --git a/Docs/Schemas/FilterConfigJsonJSC.ts b/Docs/Schemas/FilterConfigJsonJSC.ts index fc54409ec8..d8c787f83f 100644 --- a/Docs/Schemas/FilterConfigJsonJSC.ts +++ b/Docs/Schemas/FilterConfigJsonJSC.ts @@ -1,90 +1,90 @@ export default { - "type": "object", - "properties": { - "id": { - "description": "An id/name for this filter, used to set the URL parameters", - "type": "string" - }, - "options": { - "description": "The options for a filter\nIf there are multiple options these will be a list of radio buttons\nIf there is only one option this will be a checkbox\nFiltering is done based on the given osmTags that are compared to the objects in that layer.", - "type": "array", - "items": { - "type": "object", - "properties": { - "question": {}, - "osmTags": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - }, - "default": { - "type": "boolean" - }, - "fields": { + "type": "object", + "properties": { + "id": { + "description": "An id/name for this filter, used to set the URL parameters", + "type": "string" + }, + "options": { + "description": "The options for a filter\nIf there are multiple options these will be a list of radio buttons\nIf there is only one option this will be a checkbox\nFiltering is done based on the given osmTags that are compared to the objects in that layer.", "type": "array", "items": { - "type": "object", - "properties": { - "name": { - "type": "string" + "type": "object", + "properties": { + "question": {}, + "osmTags": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "default": { + "type": "boolean" + }, + "fields": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } }, - "type": { - "type": "string" - } - }, - "required": [ - "name" - ] + "required": [ + "question" + ] } - } - }, - "required": [ - "question" - ] - } - } - }, - "required": [ - "id", - "options" - ], - "definitions": { - "AndOrTagConfigJson": { - "type": "object", - "properties": { - "and": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - } - }, - "or": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - } } - } - } - }, - "$schema": "http://json-schema.org/draft-07/schema#" + }, + "required": [ + "id", + "options" + ], + "definitions": { + "AndOrTagConfigJson": { + "type": "object", + "properties": { + "and": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + }, + "or": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + } + } + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" } \ No newline at end of file diff --git a/Docs/Schemas/LayerConfigJsonJSC.ts b/Docs/Schemas/LayerConfigJsonJSC.ts index 86bccc5dbf..1153ffb2d3 100644 --- a/Docs/Schemas/LayerConfigJsonJSC.ts +++ b/Docs/Schemas/LayerConfigJsonJSC.ts @@ -1,1125 +1,1125 @@ export default { - "description": "Configuration for a single layer", - "type": "object", - "properties": { - "id": { - "description": "The id of this layer.\nThis should be a simple, lowercase, human readable string that is used to identify the layer.", - "type": "string" - }, - "name": { - "description": "The name of this layer\nUsed in the layer control panel and the 'Personal theme'.\n\nIf not given, will be hidden (and thus not toggable) in the layer control" - }, - "description": { - "description": "A description for this layer.\nShown in the layer selections and in the personel theme" - }, - "source": { - "description": "This determines where the data for the layer is fetched: from OSM or from an external geojson dataset.\n\nIf no 'geojson' is defined, data will be fetched from overpass and the OSM-API.\n\nEvery source _must_ define which tags _must_ be present in order to be picked up.", - "anyOf": [ - { - "allOf": [ - { - "type": "object", - "properties": { - "osmTags": { - "description": "Every source must set which tags have to be present in order to load the given layer.", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - }, - "maxCacheAge": { - "description": "The maximum amount of seconds that a tile is allowed to linger in the cache", - "type": "number" - } - }, - "required": [ - "osmTags" - ] - }, - { - "type": "object", - "properties": { - "overpassScript": { - "type": "string" - } - } - } - ] - }, - { - "allOf": [ - { - "type": "object", - "properties": { - "osmTags": { - "description": "Every source must set which tags have to be present in order to load the given layer.", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - }, - "maxCacheAge": { - "description": "The maximum amount of seconds that a tile is allowed to linger in the cache", - "type": "number" - } - }, - "required": [ - "osmTags" - ] - }, - { - "type": "object", - "properties": { - "geoJson": { - "description": "The actual source of the data to load, if loaded via geojson.\n\n# A single geojson-file\nsource: {geoJson: \"https://my.source.net/some-geo-data.geojson\"}\n fetches a geojson from a third party source\n\n# A tiled geojson source\nsource: {geoJson: \"https://my.source.net/some-tile-geojson-{layer}-{z}-{x}-{y}.geojson\", geoJsonZoomLevel: 14}\n to use a tiled geojson source. The web server must offer multiple geojsons. {z}, {x} and {y} are substituted by the location; {layer} is substituted with the id of the loaded layer\n\nSome API's use a BBOX instead of a tile, this can be used by specifying {y_min}, {y_max}, {x_min} and {x_max}", - "type": "string" - }, - "geoJsonZoomLevel": { - "description": "To load a tiled geojson layer, set the zoomlevel of the tiles", - "type": "number" - }, - "isOsmCache": { - "description": "Indicates that the upstream geojson data is OSM-derived.\nUseful for e.g. merging or for scripts generating this cache", - "type": "boolean" - }, - "mercatorCrs": { - "description": "Some API's use a mercator-projection (EPSG:900913) instead of WGS84. Set the flag `mercatorCrs: true` in the source for this", - "type": "boolean" - }, - "idKey": { - "description": "Some API's have an id-field, but give it a different name.\nSetting this key will rename this field into 'id'", - "type": "string" - } - }, - "required": [ - "geoJson" - ] - } - ] - } - ] - }, - "calculatedTags": { - "description": "A list of extra tags to calculate, specified as \"keyToAssignTo=javascript-expression\".\nThere are a few extra functions available. Refer to Docs/CalculatedTags.md for more information\nThe functions will be run in order, e.g.\n[\n \"_max_overlap_m2=Math.max(...feat.overlapsWith(\"someOtherLayer\").map(o => o.overlap))\n \"_max_overlap_ratio=Number(feat._max_overlap_m2)/feat.area\n]\n\nThe specified tags are evaluated lazily. E.g. if a calculated tag is only used in the popup (e.g. the number of nearby features),\nthe expensive calculation will only be performed then for that feature. This avoids clogging up the contributors PC when all features are loaded.\n\nIf a tag has to be evaluated strictly, use ':=' instead:\n\n[\n\"_some_key:=some_javascript_expression\"\n]", - "type": "array", - "items": { - "type": "string" - } - }, - "doNotDownload": { - "description": "If set, this layer will not query overpass; but it'll still match the tags above which are by chance returned by other layers.\nWorks well together with 'passAllFeatures', to add decoration", - "type": "boolean" - }, - "isShown": { - "description": "This tag rendering should either be 'yes' or 'no'. If 'no' is returned, then the feature will be hidden from view.\nThis is useful to hide certain features from view.\n\nImportant: hiding features does not work dynamically, but is only calculated when the data is first renders.\nThis implies that it is not possible to hide a feature after a tagging change\n\nThe default value is 'yes'", - "$ref": "#/definitions/TagRenderingConfigJson" - }, - "forceLoad": { - "description": "Advanced option - might be set by the theme compiler\n\nIf true, this data will _always_ be loaded, even if the theme is disabled", - "type": "boolean" - }, - "minzoom": { - "description": "The minimum needed zoomlevel required before loading of the data start\nDefault: 0", - "type": "number" - }, - "shownByDefault": { - "description": "Indicates if this layer is shown by default;\ncan be used to hide a layer from start, or to load the layer but only to show it where appropriate (e.g. for snapping to it)", - "type": "boolean" - }, - "minzoomVisible": { - "description": "The zoom level at which point the data is hidden again\nDefault: 100 (thus: always visible", - "type": "number" - }, - "title": { - "description": "The title shown in a popup for elements of this layer.", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - }, - "titleIcons": { - "description": "Small icons shown next to the title.\nIf not specified, the OsmLink and wikipedia links will be used by default.\nUse an empty array to hide them.\nNote that \"defaults\" will insert all the default titleIcons (which are added automatically)\n\nType: icon[]", - "anyOf": [ - { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - } - }, - { - "type": "array", - "items": [ - { - "type": "string", - "enum": [ - "defaults" - ] - } - ], - "minItems": 1, - "maxItems": 1 - } - ] - }, - "mapRendering": { - "description": "Visualisation of the items on the map", - "anyOf": [ - { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/default_4" - }, - { - "$ref": "#/definitions/default_5" - } - ] - } - }, - { - "type": "null" - } - ] - }, - "passAllFeatures": { - "description": "If set, this layer will pass all the features it receives onto the next layer.\nThis is ideal for decoration, e.g. directionss on cameras", - "type": "boolean" - }, - "presets": { - "description": "Presets for this layer.\nA preset shows up when clicking the map on a without data (or when right-clicking/long-pressing);\nit will prompt the user to add a new point.\n\nThe most important aspect are the tags, which define which tags the new point will have;\nThe title is shown in the dialog, along with the first sentence of the description.\n\nUpon confirmation, the full description is shown beneath the buttons - perfect to add pictures and examples.\n\nNote: the icon of the preset is determined automatically based on the tags and the icon above. Don't worry about that!\nNB: if no presets are defined, the popup to add new points doesn't show up at all", - "type": "array", - "items": { - "type": "object", - "properties": { - "title": { - "description": "The title - shown on the 'add-new'-button." - }, - "tags": { - "description": "The tags to add. It determines the icon too", - "type": "array", - "items": { - "type": "string" - } - }, - "description": { - "description": "The _first sentence_ of the description is shown on the button of the `add` menu.\nThe full description is shown in the confirmation dialog.\n\n(The first sentence is until the first '.'-character in the description)" - }, - "exampleImages": { - "description": "Example images, which show real-life pictures of what such a feature might look like\n\nType: image", - "type": "array", - "items": { - "type": "string" - } - }, - "preciseInput": { - "description": "If set, the user will prompted to confirm the location before actually adding the data.\nThis will be with a 'drag crosshair'-method.\n\nIf 'preferredBackgroundCategory' is set, the element will attempt to pick a background layer of that category.", - "anyOf": [ - { - "type": "object", - "properties": { - "preferredBackground": { - "description": "The type of background picture", - "anyOf": [ - { - "type": "array", - "items": { - "type": "string" - } - }, - { - "type": "string" - } - ] - }, - "snapToLayer": { - "description": "If specified, these layers will be shown to and the new point will be snapped towards it", - "anyOf": [ - { - "type": "array", - "items": { - "type": "string" - } - }, - { - "type": "string" - } - ] - }, - "maxSnapDistance": { - "description": "If specified, a new point will only be snapped if it is within this range.\nDistance in meter\n\nDefault: 10", - "type": "number" - } - }, - "required": [ - "preferredBackground" - ] - }, - { - "enum": [ - true - ], - "type": "boolean" - } - ] - } - }, - "required": [ - "tags", - "title" - ] - } - }, - "tagRenderings": { - "description": "All the tag renderings.\nA tag rendering is a block that either shows the known value or asks a question.\n\nRefer to the class `TagRenderingConfigJson` to see the possibilities.\n\nNote that we can also use a string here - where the string refers to a tag rendering defined in `assets/questions/questions.json`,\nwhere a few very general questions are defined e.g. website, phone number, ...\n\nA special value is 'questions', which indicates the location of the questions box. If not specified, it'll be appended to the bottom of the featureInfobox.\n\nAt last, one can define a group of renderings where parts of all strings will be replaced by multiple other strings.\nThis is mainly create questions for a 'left' and a 'right' side of the road.\nThese will be grouped and questions will be asked together", - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/QuestionableTagRenderingConfigJson" - }, - { - "type": "object", - "properties": { - "builtin": { - "type": "string" - }, - "override": {} - }, - "required": [ - "builtin", - "override" - ] - }, - { - "$ref": "#/definitions/default<(string|QuestionableTagRenderingConfigJson|{builtin:string;override:any;})[]>" - }, - { - "type": "string" - } - ] - } - }, - "filter": { - "description": "All the extra questions for filtering", - "anyOf": [ - { - "type": "array", - "items": { - "$ref": "#/definitions/default_1" - } - }, - { - "type": "object", - "properties": { - "sameAs": { - "type": "string" - } - }, - "required": [ - "sameAs" - ] - } - ] - }, - "deletion": { - "description": "This block defines under what circumstances the delete dialog is shown for objects of this layer.\nIf set, a dialog is shown to the user to (soft) delete the point.\nThe dialog is built to be user friendly and to prevent mistakes.\nIf deletion is not possible, the dialog will hide itself and show the reason of non-deletability instead.\n\nTo configure, the following values are possible:\n\n- false: never ever show the delete button\n- true: show the default delete button\n- undefined: use the mapcomplete default to show deletion or not. Currently, this is the same as 'false' but this will change in the future\n- or: a hash with options (see below)\n\n The delete dialog\n =================\n\n\n\n#### Hard deletion if enough experience\n\nA feature can only be deleted from OpenStreetMap by mapcomplete if:\n\n- It is a node\n- No ways or relations use the node\n- The logged-in user has enough experience OR the user is the only one to have edited the point previously\n- The logged-in user has no unread messages (or has a ton of experience)\n- The user did not select one of the 'non-delete-options' (see below)\n\nIn all other cases, a 'soft deletion' is used.\n\n#### Soft deletion\n\nA 'soft deletion' is when the point isn't deleted from OSM but retagged so that it'll won't how up in the mapcomplete theme anymore.\nThis makes it look like it was deleted, without doing damage. A fixme will be added to the point.\n\nNote that a soft deletion is _only_ possible if these tags are provided by the theme creator, as they'll be different for every theme\n\n#### No-delete options\n\nIn some cases, the contributor might want to delete something for the wrong reason (e.g. someone who wants to have a path removed \"because the path is on their private property\").\nHowever, the path exists in reality and should thus be on OSM - otherwise the next contributor will pass by and notice \"hey, there is a path missing here! Let me redraw it in OSM!)\n\nThe correct approach is to retag the feature in such a way that it is semantically correct *and* that it doesn't show up on the theme anymore.\nA no-delete option is offered as 'reason to delete it', but secretly retags.", - "anyOf": [ - { - "$ref": "#/definitions/DeleteConfigJson" - }, - { - "type": "boolean" - } - ] - }, - "allowMove": { - "description": "Indicates if a point can be moved and configures the modalities.\n\nA feature can be moved by MapComplete if:\n\n- It is a point\n- The point is _not_ part of a way or a a relation.\n\nOff by default. Can be enabled by setting this flag or by configuring.", - "anyOf": [ - { - "$ref": "#/definitions/default_3" - }, - { - "type": "boolean" - } - ] - }, - "allowSplit": { - "description": "IF set, a 'split this road' button is shown", - "type": "boolean" - }, - "units": { - "description": "In some cases, a value is represented in a certain unit (such as meters for heigt/distance/..., km/h for speed, ...)\n\nSometimes, multiple denominations are possible (e.g. km/h vs mile/h; megawatt vs kilowatt vs gigawatt for power generators, ...)\n\nThis brings in some troubles, as there are multiple ways to write it (no denomitation, 'm' vs 'meter' 'metre', ...)\n\nNot only do we want to write consistent data to OSM, we also want to present this consistently to the user.\nThis is handled by defining units.\n\n# Rendering\n\nTo render a value with long (human) denomination, use {canonical(key)}\n\n# Usage\n\nFirst of all, you define which keys have units applied, for example:\n\n```\nunits: [\n appliesTo: [\"maxspeed\", \"maxspeed:hgv\", \"maxspeed:bus\"]\n applicableUnits: [\n ...\n ]\n]\n```\n\nApplicableUnits defines which is the canonical extension, how it is presented to the user, ...:\n\n```\napplicableUnits: [\n{\n canonicalDenomination: \"km/h\",\n alternativeDenomination: [\"km/u\", \"kmh\", \"kph\"]\n default: true,\n human: {\n en: \"kilometer/hour\",\n nl: \"kilometer/uur\"\n },\n humanShort: {\n en: \"km/h\",\n nl: \"km/u\"\n }\n},\n{\n canoncialDenomination: \"mph\",\n ... similar for miles an hour ...\n}\n]\n```\n\n\nIf this is defined, then every key which the denominations apply to (`maxspeed`, `maxspeed:hgv` and `maxspeed:bus`) will be rewritten at the metatagging stage:\nevery value will be parsed and the canonical extension will be added add presented to the other parts of the code.\n\nAlso, if a freeform text field is used, an extra dropdown with applicable denominations will be given", - "type": "array", - "items": { - "$ref": "#/definitions/default_2" - } - }, - "syncSelection": { - "description": "If set, synchronizes wether or not this layer is selected.\n\nno: Do not sync at all, always revert to default\nlocal: keep selection on local storage\ntheme-only: sync via OSM, but this layer will only be toggled in this theme\nglobal: all layers with this ID will be synced accross all themes", - "enum": [ - "global", - "local", - "no", - "theme-only" - ], - "type": "string" - } - }, - "required": [ - "id", - "mapRendering", - "source" - ], - "definitions": { - "AndOrTagConfigJson": { - "type": "object", - "properties": { - "and": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - } - }, - "or": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - } - } - } - }, - "ApplicableUnitJson": { - "type": "object", - "properties": { - "canonicalDenomination": { - "description": "The canonical value which will be added to the text.\ne.g. \"m\" for meters\nIf the user inputs '42', the canonical value will be added and it'll become '42m'", - "type": "string" - }, - "canonicalDenominationSingular": { - "description": "The canonical denomination in the case that the unit is precisely '1'", - "type": "string" - }, - "alternativeDenomination": { - "description": "A list of alternative values which can occur in the OSM database - used for parsing.", - "type": "array", - "items": { - "type": "string" - } - }, - "human": { - "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"meter\",\n \"fr\": \"metre\"\n}" - }, - "humanSingular": { - "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"minute\",\n \"nl\": \"minuut\"x²\n}" - }, - "prefix": { - "description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field", - "type": "boolean" - }, - "default": { - "description": "The default interpretation - only one can be set.\nIf none is set, the first unit will be considered the default interpretation of a value without a unit", - "type": "boolean" - } - }, - "required": [ - "canonicalDenomination" - ] - }, - "TagRenderingConfigJson": { - "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRenerdering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", - "type": "object", - "properties": { + "description": "Configuration for a single layer", + "type": "object", + "properties": { "id": { - "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", - "type": "string" - }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, - "labels": { - "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", - "type": "array", - "items": { + "description": "The id of this layer.\nThis should be a simple, lowercase, human readable string that is used to identify the layer.", "type": "string" - } }, - "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + "name": { + "description": "The name of this layer\nUsed in the layer control panel and the 'Personal theme'.\n\nIf not given, will be hidden (and thus not toggable) in the layer control" }, - "condition": { - "description": "Only show this tagrendering (or question) if the object also matches the following tags.\n\nThis is useful to ask a follow-up question. E.g. if there is a diaper table, then ask a follow-up question on diaper tables...", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] + "description": { + "description": "A description for this layer.\nShown in the layer selections and in the personel theme" }, - "freeform": { - "description": "Allow freeform text input from the user", - "type": "object", - "properties": { - "key": { - "description": "If this key is present, then 'render' is used to display the value.\nIf this is undefined, the rendering is _always_ shown", - "type": "string" - } - }, - "required": [ - "key" - ] - }, - "mappings": { - "description": "Allows fixed-tag inputs, shown either as radiobuttons or as checkboxes", - "type": "array", - "items": { - "type": "object", - "properties": { - "if": { - "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - }, - "then": { - "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" - }, - "icon": { - "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", - "anyOf": [ - { - "type": "object", - "properties": { - "path": { - "description": "The path to the icon\nType: icon", - "type": "string" - }, - "class": { - "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", - "type": "string" - } - }, - "required": [ - "class", - "path" + "source": { + "description": "This determines where the data for the layer is fetched: from OSM or from an external geojson dataset.\n\nIf no 'geojson' is defined, data will be fetched from overpass and the OSM-API.\n\nEvery source _must_ define which tags _must_ be present in order to be picked up.", + "anyOf": [ + { + "allOf": [ + { + "type": "object", + "properties": { + "osmTags": { + "description": "Every source must set which tags have to be present in order to load the given layer.", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "maxCacheAge": { + "description": "The maximum amount of seconds that a tile is allowed to linger in the cache", + "type": "number" + } + }, + "required": [ + "osmTags" + ] + }, + { + "type": "object", + "properties": { + "overpassScript": { + "type": "string" + } + } + } ] - }, - { - "type": "string" - } - ] - } - }, - "required": [ - "if", - "then" + }, + { + "allOf": [ + { + "type": "object", + "properties": { + "osmTags": { + "description": "Every source must set which tags have to be present in order to load the given layer.", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "maxCacheAge": { + "description": "The maximum amount of seconds that a tile is allowed to linger in the cache", + "type": "number" + } + }, + "required": [ + "osmTags" + ] + }, + { + "type": "object", + "properties": { + "geoJson": { + "description": "The actual source of the data to load, if loaded via geojson.\n\n# A single geojson-file\nsource: {geoJson: \"https://my.source.net/some-geo-data.geojson\"}\n fetches a geojson from a third party source\n\n# A tiled geojson source\nsource: {geoJson: \"https://my.source.net/some-tile-geojson-{layer}-{z}-{x}-{y}.geojson\", geoJsonZoomLevel: 14}\n to use a tiled geojson source. The web server must offer multiple geojsons. {z}, {x} and {y} are substituted by the location; {layer} is substituted with the id of the loaded layer\n\nSome API's use a BBOX instead of a tile, this can be used by specifying {y_min}, {y_max}, {x_min} and {x_max}", + "type": "string" + }, + "geoJsonZoomLevel": { + "description": "To load a tiled geojson layer, set the zoomlevel of the tiles", + "type": "number" + }, + "isOsmCache": { + "description": "Indicates that the upstream geojson data is OSM-derived.\nUseful for e.g. merging or for scripts generating this cache", + "type": "boolean" + }, + "mercatorCrs": { + "description": "Some API's use a mercator-projection (EPSG:900913) instead of WGS84. Set the flag `mercatorCrs: true` in the source for this", + "type": "boolean" + }, + "idKey": { + "description": "Some API's have an id-field, but give it a different name.\nSetting this key will rename this field into 'id'", + "type": "string" + } + }, + "required": [ + "geoJson" + ] + } + ] + } ] - } - } - } - }, - "T": { - "type": "object" - }, - "default_4": { - "description": "The PointRenderingConfig gives all details onto how to render a single point of a feature.\n\nThis can be used if:\n\n- The feature is a point\n- To render something at the centroid of an area, or at the start, end or projected centroid of a way", - "type": "object", - "properties": { - "location": { - "description": "All the locations that this point should be rendered at.\nUsing `location: [\"point\", \"centroid\"] will always render centerpoint", - "type": "array", - "items": { - "type": "string" - } }, - "icon": { - "description": "The icon for an element.\nNote that this also doubles as the icon for this layer (rendered with the overpass-tags) ánd the icon in the presets.\n\nThe result of the icon is rendered as follows:\nthe resulting string is interpreted as a _list_ of items, separated by \";\". The bottommost layer is the first layer.\nAs a result, on could use a generic pin, then overlay it with a specific icon.\nTo make things even more practical, one can use all SVG's from the folder \"assets/svg\" and _substitute the color_ in it.\nE.g. to draw a red pin, use \"pin:#f00\", to have a green circle with your icon on top, use `circle:#0f0;`\n\nType: icon", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" + "calculatedTags": { + "description": "A list of extra tags to calculate, specified as \"keyToAssignTo=javascript-expression\".\nThere are a few extra functions available. Refer to Docs/CalculatedTags.md for more information\nThe functions will be run in order, e.g.\n[\n \"_max_overlap_m2=Math.max(...feat.overlapsWith(\"someOtherLayer\").map(o => o.overlap))\n \"_max_overlap_ratio=Number(feat._max_overlap_m2)/feat.area\n]\n\nThe specified tags are evaluated lazily. E.g. if a calculated tag is only used in the popup (e.g. the number of nearby features),\nthe expensive calculation will only be performed then for that feature. This avoids clogging up the contributors PC when all features are loaded.\n\nIf a tag has to be evaluated strictly, use ':=' instead:\n\n[\n\"_some_key:=some_javascript_expression\"\n]", + "type": "array", + "items": { + "type": "string" } - ] }, - "iconBadges": { - "description": "A list of extra badges to show next to the icon as small badge\nThey will be added as a 25% height icon at the bottom right of the icon, with all the badges in a flex layout.\n\nNote: strings are interpreted as icons, so layering and substituting is supported. You can use `circle:white;./my_icon.svg` to add a background circle", - "type": "array", - "items": { - "type": "object", - "properties": { - "if": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - }, - "then": { - "description": "Badge to show\nType: icon", - "anyOf": [ - { + "doNotDownload": { + "description": "If set, this layer will not query overpass; but it'll still match the tags above which are by chance returned by other layers.\nWorks well together with 'passAllFeatures', to add decoration", + "type": "boolean" + }, + "isShown": { + "description": "This tag rendering should either be 'yes' or 'no'. If 'no' is returned, then the feature will be hidden from view.\nThis is useful to hide certain features from view.\n\nImportant: hiding features does not work dynamically, but is only calculated when the data is first renders.\nThis implies that it is not possible to hide a feature after a tagging change\n\nThe default value is 'yes'", + "$ref": "#/definitions/TagRenderingConfigJson" + }, + "forceLoad": { + "description": "Advanced option - might be set by the theme compiler\n\nIf true, this data will _always_ be loaded, even if the theme is disabled", + "type": "boolean" + }, + "minzoom": { + "description": "The minimum needed zoomlevel required before loading of the data start\nDefault: 0", + "type": "number" + }, + "shownByDefault": { + "description": "Indicates if this layer is shown by default;\ncan be used to hide a layer from start, or to load the layer but only to show it where appropriate (e.g. for snapping to it)", + "type": "boolean" + }, + "minzoomVisible": { + "description": "The zoom level at which point the data is hidden again\nDefault: 100 (thus: always visible", + "type": "number" + }, + "title": { + "description": "The title shown in a popup for elements of this layer.", + "anyOf": [ + { "$ref": "#/definitions/TagRenderingConfigJson" - }, - { + }, + { "type": "string" - } - ] - } - }, - "required": [ - "if", - "then" - ] - } - }, - "iconSize": { - "description": "A string containing \"width,height\" or \"width,height,anchorpoint\" where anchorpoint is any of 'center', 'top', 'bottom', 'left', 'right', 'bottomleft','topright', ...\nDefault is '40,40,center'", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - }, - "rotation": { - "description": "The rotation of an icon, useful for e.g. directions.\nUsage: as if it were a css property for 'rotate', thus has to end with 'deg', e.g. `90deg`, `{direction}deg`, `calc(90deg - {camera:direction}deg)``", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - }, - "label": { - "description": "A HTML-fragment that is shown below the icon, for example:\n
{name}
\n\nIf the icon is undefined, then the label is shown in the center of the feature.\nNote that, if the wayhandling hides the icon then no label is shown as well.", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - } - }, - "required": [ - "location" - ] - }, - "default_5": { - "description": "The LineRenderingConfig gives all details onto how to render a single line of a feature.\n\nThis can be used if:\n\n- The feature is a line\n- The feature is an area", - "type": "object", - "properties": { - "color": { - "description": "The color for way-elements and SVG-elements.\nIf the value starts with \"--\", the style of the body element will be queried for the corresponding variable instead", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - }, - "width": { - "description": "The stroke-width for way-elements", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": [ - "string", - "number" - ] - } - ] - }, - "dashArray": { - "description": "A dasharray, e.g. \"5 6\"\nThe dasharray defines 'pixels of line, pixels of gap, pixels of line, pixels of gap',\nDefault value: \"\" (empty string == full line)", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - }, - "lineCap": { - "description": "The form at the end of a line", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - }, - "fill": { - "description": "Wehter or not to fill polygons", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "enum": [ - "no", - "yes" - ], - "type": "string" - } - ] - }, - "fillColor": { - "description": "The color to fill a polygon with.\nIf undefined, this will be slightly more opaque version of the stroke line", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - }, - "offset": { - "description": "The number of pixels this line should be moved.\nUse a positive numbe to move to the right, a negative to move to the left (left/right as defined by the drawing direction of the line).\n\nIMPORTANT: MapComplete will already normalize 'key:both:property' and 'key:both' into the corresponding 'key:left' and 'key:right' tagging (same for 'sidewalk=left/right/both' which is rewritten to 'sidewalk:left' and 'sidewalk:right')\nThis simplifies programming. Refer to the CalculatedTags.md-documentation for more details", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "number" - } - ] - } - } - }, - "QuestionableTagRenderingConfigJson": { - "description": "A QuestionableTagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nIf the desired tags are missing and a question is defined, a question will be shown instead.", - "type": "object", - "properties": { - "question": { - "description": "If it turns out that this tagRendering doesn't match _any_ value, then we show this question.\nIf undefined, the question is never asked and this tagrendering is read-only" - }, - "freeform": { - "description": "Allow freeform text input from the user", - "type": "object", - "properties": { - "key": { - "type": "string" - }, - "type": { - "description": "The type of the text-field, e.g. 'string', 'nat', 'float', 'date',...\nSee Docs/SpecialInputElements.md and UI/Input/ValidatedTextField.ts for supported values", - "type": "string" - }, - "placeholder": { - "description": "A (translated) text that is shown (as gray text) within the textfield" - }, - "helperArgs": { - "description": "Extra parameters to initialize the input helper arguments.\nFor semantics, see the 'SpecialInputElements.md'", - "type": "array", - "items": {} - }, - "addExtraTags": { - "description": "If a value is added with the textfield, these extra tag is addded.\nUseful to add a 'fixme=freeform textfield used - to be checked'", - "type": "array", - "items": { - "type": "string" - } - }, - "inline": { - "description": "When set, influences the way a question is asked.\nInstead of showing a full-widht text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.", - "type": "boolean" - }, - "default": { - "description": "default value to enter if no previous tagging is present.\nNormally undefined (aka do not enter anything)", - "type": "string" - } - }, - "required": [ - "key" - ] - }, - "multiAnswer": { - "description": "If true, use checkboxes instead of radio buttons when asking the question", - "type": "boolean" - }, - "mappings": { - "description": "Allows fixed-tag inputs, shown either as radiobuttons or as checkboxes", - "type": "array", - "items": { - "type": "object", - "properties": { - "if": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - }, - "then": { - "description": "Shown if the 'if is fulfilled\nType: rendered" - }, - "icon": { - "description": "An extra icon supporting the choice\nType: icon", - "anyOf": [ - { - "type": "object", - "properties": { - "path": { - "description": "The path to the icon\nType: icon", - "type": "string" - }, - "class": { - "description": "Size of the image", - "type": "string" - } - }, - "required": [ - "class", - "path" - ] - }, - { - "type": "string" - } - ] - }, - "hideInAnswer": { - "description": "In some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation).\n\nIn the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user.\nIn this case, one of the mappings can be hiden by setting this flag.\n\nTo demonstrate an example making a default assumption:\n\nmappings: [\n {\n if: \"access=\", -- no access tag present, we assume accessible\n then: \"Accessible to the general public\",\n hideInAnswer: true\n },\n {\n if: \"access=yes\",\n then: \"Accessible to the general public\", -- the user selected this, we add that to OSM\n },\n {\n if: \"access=no\",\n then: \"Not accessible to the public\"\n }\n]\n\n\nFor example, for an operator, we have `operator=Agentschap Natuur en Bos`, which is often abbreviated to `operator=ANB`.\nThen, we would add two mappings:\n{\n if: \"operator=Agentschap Natuur en Bos\" -- the non-abbreviated version which should be uploaded\n then: \"Maintained by Agentschap Natuur en Bos\"\n},\n{\n if: \"operator=ANB\", -- we don't want to upload abbreviations\n then: \"Maintained by Agentschap Natuur en Bos\"\n hideInAnswer: true\n}\n\nHide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate.\nKeep in mind that this is reverse logic: it will be hidden in the answer if the condition is true, it will thus only show in the case of a mismatch\n\ne.g., for toilets: if \"wheelchair=no\", we know there is no wheelchair dedicated room.\nFor the location of the changing table, the option \"in the wheelchair accessible toilet is weird\", so we write:\n\n{\n \"question\": \"Where is the changing table located?\"\n \"mappings\": [\n {\"if\":\"changing_table:location=female\",\"then\":\"In the female restroom\"},\n {\"if\":\"changing_table:location=male\",\"then\":\"In the male restroom\"},\n {\"if\":\"changing_table:location=wheelchair\",\"then\":\"In the wheelchair accessible restroom\", \"hideInAnswer\": \"wheelchair=no\"},\n \n ]\n}\n\nAlso have a look for the meta-tags\n{\n if: \"operator=Agentschap Natuur en Bos\",\n then: \"Maintained by Agentschap Natuur en Bos\",\n hideInAnswer: \"_country!=be\"\n}", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": [ - "string", - "boolean" - ] - } - ] - }, - "ifnot": { - "description": "Only applicable if 'multiAnswer' is set.\nThis is for situations such as:\n`accepts:coins=no` where one can select all the possible payment methods. However, we want to make explicit that some options _were not_ selected.\nThis can be done with `ifnot`\nNote that we can not explicitly render this negative case to the user, we cannot show `does _not_ accept coins`.\nIf this is important to your usecase, consider using multiple radiobutton-fields without `multiAnswer`", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - }, - "addExtraTags": { - "description": "If chosen as answer, these tags will be applied as well onto the object.\nNot compatible with multiAnswer", - "type": "array", - "items": { - "type": "string" } - } - }, - "required": [ - "if", - "then" ] - } }, - "id": { - "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", - "type": "string" - }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, - "labels": { - "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", - "type": "array", - "items": { - "type": "string" - } - }, - "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" - }, - "condition": { - "description": "Only show this tagrendering (or question) if the object also matches the following tags.\n\nThis is useful to ask a follow-up question. E.g. if there is a diaper table, then ask a follow-up question on diaper tables...", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - } - } - }, - "default<(string|QuestionableTagRenderingConfigJson|{builtin:string;override:any;})[]>": { - "type": "object", - "properties": { - "rewrite": { - "type": "object", - "properties": { - "sourceString": { - "type": "array", - "items": { - "type": "string" - } - }, - "into": { - "type": "array", - "items": { - "type": "array", - "items": {} - } - } - }, - "required": [ - "into", - "sourceString" - ] - }, - "renderings": { - "type": "array", - "items": { + "titleIcons": { + "description": "Small icons shown next to the title.\nIf not specified, the OsmLink and wikipedia links will be used by default.\nUse an empty array to hide them.\nNote that \"defaults\" will insert all the default titleIcons (which are added automatically)\n\nType: icon[]", "anyOf": [ - { - "$ref": "#/definitions/QuestionableTagRenderingConfigJson" - }, - { + { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + } + }, + { + "type": "array", + "items": [ + { + "type": "string", + "enum": [ + "defaults" + ] + } + ], + "minItems": 1, + "maxItems": 1 + } + ] + }, + "mapRendering": { + "description": "Visualisation of the items on the map", + "anyOf": [ + { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/default_4" + }, + { + "$ref": "#/definitions/default_5" + } + ] + } + }, + { + "type": "null" + } + ] + }, + "passAllFeatures": { + "description": "If set, this layer will pass all the features it receives onto the next layer.\nThis is ideal for decoration, e.g. directionss on cameras", + "type": "boolean" + }, + "presets": { + "description": "Presets for this layer.\nA preset shows up when clicking the map on a without data (or when right-clicking/long-pressing);\nit will prompt the user to add a new point.\n\nThe most important aspect are the tags, which define which tags the new point will have;\nThe title is shown in the dialog, along with the first sentence of the description.\n\nUpon confirmation, the full description is shown beneath the buttons - perfect to add pictures and examples.\n\nNote: the icon of the preset is determined automatically based on the tags and the icon above. Don't worry about that!\nNB: if no presets are defined, the popup to add new points doesn't show up at all", + "type": "array", + "items": { "type": "object", "properties": { - "builtin": { - "type": "string" - }, - "override": {} + "title": { + "description": "The title - shown on the 'add-new'-button." + }, + "tags": { + "description": "The tags to add. It determines the icon too", + "type": "array", + "items": { + "type": "string" + } + }, + "description": { + "description": "The _first sentence_ of the description is shown on the button of the `add` menu.\nThe full description is shown in the confirmation dialog.\n\n(The first sentence is until the first '.'-character in the description)" + }, + "exampleImages": { + "description": "Example images, which show real-life pictures of what such a feature might look like\n\nType: image", + "type": "array", + "items": { + "type": "string" + } + }, + "preciseInput": { + "description": "If set, the user will prompted to confirm the location before actually adding the data.\nThis will be with a 'drag crosshair'-method.\n\nIf 'preferredBackgroundCategory' is set, the element will attempt to pick a background layer of that category.", + "anyOf": [ + { + "type": "object", + "properties": { + "preferredBackground": { + "description": "The type of background picture", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "snapToLayer": { + "description": "If specified, these layers will be shown to and the new point will be snapped towards it", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "maxSnapDistance": { + "description": "If specified, a new point will only be snapped if it is within this range.\nDistance in meter\n\nDefault: 10", + "type": "number" + } + }, + "required": [ + "preferredBackground" + ] + }, + { + "enum": [ + true + ], + "type": "boolean" + } + ] + } }, "required": [ - "builtin", - "override" + "tags", + "title" ] - }, - { - "type": "string" - } - ] - } - } - }, - "required": [ - "renderings", - "rewrite" - ] - }, - "default_1": { - "type": "object", - "properties": { - "id": { - "description": "An id/name for this filter, used to set the URL parameters", - "type": "string" - }, - "options": { - "description": "The options for a filter\nIf there are multiple options these will be a list of radio buttons\nIf there is only one option this will be a checkbox\nFiltering is done based on the given osmTags that are compared to the objects in that layer.", - "type": "array", - "items": { - "type": "object", - "properties": { - "question": {}, - "osmTags": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - }, - "default": { - "type": "boolean" - }, - "fields": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "type": { - "type": "string" - } - }, - "required": [ - "name" - ] - } - } - }, - "required": [ - "question" - ] - } - } - }, - "required": [ - "id", - "options" - ] - }, - "DeleteConfigJson": { - "type": "object", - "properties": { - "extraDeleteReasons": { - "description": "*\nBy default, three reasons to delete a point are shown:\n\n- The point does not exist anymore\n- The point was a testing point\n- THe point could not be found\n\nHowever, for some layers, there might be different or more specific reasons for deletion which can be user friendly to set, e.g.:\n\n- the shop has closed\n- the climbing route has been closed of for nature conservation reasons\n- ...\n\nThese reasons can be stated here and will be shown in the list of options the user can choose from", - "type": "array", - "items": { - "type": "object", - "properties": { - "explanation": { - "description": "The text that will be shown to the user - translatable" - }, - "changesetMessage": { - "description": "The text that will be uploaded into the changeset or will be used in the fixme in case of a soft deletion\nShould be a few words, in english", - "type": "string" - } - }, - "required": [ - "changesetMessage", - "explanation" - ] - } - }, - "nonDeleteMappings": { - "description": "In some cases, a (starting) contributor might wish to delete a feature even though deletion is not appropriate.\n(The most relevant case are small paths running over private property. These should be marked as 'private' instead of deleted, as the community might trace the path again from aerial imagery, gettting us back to the original situation).\n\nBy adding a 'nonDeleteMapping', an option can be added into the list which will retag the feature.\nIt is important that the feature will be retagged in such a way that it won't be picked up by the layer anymore!", - "type": "array", - "items": { - "type": "object", - "properties": { - "if": { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - "then": {} - }, - "required": [ - "if", - "then" - ] - } - }, - "softDeletionTags": { - "description": "In some cases, the contributor is not allowed to delete the current feature (e.g. because it isn't a point, the point is referenced by a relation or the user isn't experienced enough).\nTo still offer the user a 'delete'-option, the feature is retagged with these tags. This is a soft deletion, as the point isn't actually removed from OSM but rather marked as 'disused'\nIt is important that the feature will be retagged in such a way that it won't be picked up by the layer anymore!\n\nExample (note that \"amenity=\" erases the 'amenity'-key alltogether):\n```\n{\n \"and\": [\"disussed:amenity=public_bookcase\", \"amenity=\"]\n}\n```\n\nor (notice the use of the ':='-tag to copy the old value of 'shop=*' into 'disused:shop='):\n```\n{\n \"and\": [\"disused:shop:={shop}\", \"shop=\"]\n}\n```", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" } - ] }, - "neededChangesets": { - "description": "*\nBy default, the contributor needs 20 previous changesets to delete points edited by others.\nFor some small features (e.g. bicycle racks) this is too much and this requirement can be lowered or dropped, which can be done here.", - "type": "number" - } - } - }, - "default_3": { - "type": "object", - "properties": { - "enableImproveAccuracy": { - "description": "One default reason to move a point is to improve accuracy.\nSet to false to disable this reason", - "type": "boolean" + "tagRenderings": { + "description": "All the tag renderings.\nA tag rendering is a block that either shows the known value or asks a question.\n\nRefer to the class `TagRenderingConfigJson` to see the possibilities.\n\nNote that we can also use a string here - where the string refers to a tag rendering defined in `assets/questions/questions.json`,\nwhere a few very general questions are defined e.g. website, phone number, ...\n\nA special value is 'questions', which indicates the location of the questions box. If not specified, it'll be appended to the bottom of the featureInfobox.\n\nAt last, one can define a group of renderings where parts of all strings will be replaced by multiple other strings.\nThis is mainly create questions for a 'left' and a 'right' side of the road.\nThese will be grouped and questions will be asked together", + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/QuestionableTagRenderingConfigJson" + }, + { + "type": "object", + "properties": { + "builtin": { + "type": "string" + }, + "override": {} + }, + "required": [ + "builtin", + "override" + ] + }, + { + "$ref": "#/definitions/default<(string|QuestionableTagRenderingConfigJson|{builtin:string;override:any;})[]>" + }, + { + "type": "string" + } + ] + } }, - "enableRelocation": { - "description": "One default reason to move a point is because it has relocated\nSet to false to disable this reason", - "type": "boolean" - } - } - }, - "default_2": { - "type": "object", - "properties": { - "appliesToKey": { - "description": "Every key from this list will be normalized", - "type": "array", - "items": { + "filter": { + "description": "All the extra questions for filtering", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/definitions/default_1" + } + }, + { + "type": "object", + "properties": { + "sameAs": { + "type": "string" + } + }, + "required": [ + "sameAs" + ] + } + ] + }, + "deletion": { + "description": "This block defines under what circumstances the delete dialog is shown for objects of this layer.\nIf set, a dialog is shown to the user to (soft) delete the point.\nThe dialog is built to be user friendly and to prevent mistakes.\nIf deletion is not possible, the dialog will hide itself and show the reason of non-deletability instead.\n\nTo configure, the following values are possible:\n\n- false: never ever show the delete button\n- true: show the default delete button\n- undefined: use the mapcomplete default to show deletion or not. Currently, this is the same as 'false' but this will change in the future\n- or: a hash with options (see below)\n\n The delete dialog\n =================\n\n\n\n#### Hard deletion if enough experience\n\nA feature can only be deleted from OpenStreetMap by mapcomplete if:\n\n- It is a node\n- No ways or relations use the node\n- The logged-in user has enough experience OR the user is the only one to have edited the point previously\n- The logged-in user has no unread messages (or has a ton of experience)\n- The user did not select one of the 'non-delete-options' (see below)\n\nIn all other cases, a 'soft deletion' is used.\n\n#### Soft deletion\n\nA 'soft deletion' is when the point isn't deleted from OSM but retagged so that it'll won't how up in the mapcomplete theme anymore.\nThis makes it look like it was deleted, without doing damage. A fixme will be added to the point.\n\nNote that a soft deletion is _only_ possible if these tags are provided by the theme creator, as they'll be different for every theme\n\n#### No-delete options\n\nIn some cases, the contributor might want to delete something for the wrong reason (e.g. someone who wants to have a path removed \"because the path is on their private property\").\nHowever, the path exists in reality and should thus be on OSM - otherwise the next contributor will pass by and notice \"hey, there is a path missing here! Let me redraw it in OSM!)\n\nThe correct approach is to retag the feature in such a way that it is semantically correct *and* that it doesn't show up on the theme anymore.\nA no-delete option is offered as 'reason to delete it', but secretly retags.", + "anyOf": [ + { + "$ref": "#/definitions/DeleteConfigJson" + }, + { + "type": "boolean" + } + ] + }, + "allowMove": { + "description": "Indicates if a point can be moved and configures the modalities.\n\nA feature can be moved by MapComplete if:\n\n- It is a point\n- The point is _not_ part of a way or a a relation.\n\nOff by default. Can be enabled by setting this flag or by configuring.", + "anyOf": [ + { + "$ref": "#/definitions/default_3" + }, + { + "type": "boolean" + } + ] + }, + "allowSplit": { + "description": "IF set, a 'split this road' button is shown", + "type": "boolean" + }, + "units": { + "description": "In some cases, a value is represented in a certain unit (such as meters for heigt/distance/..., km/h for speed, ...)\n\nSometimes, multiple denominations are possible (e.g. km/h vs mile/h; megawatt vs kilowatt vs gigawatt for power generators, ...)\n\nThis brings in some troubles, as there are multiple ways to write it (no denomitation, 'm' vs 'meter' 'metre', ...)\n\nNot only do we want to write consistent data to OSM, we also want to present this consistently to the user.\nThis is handled by defining units.\n\n# Rendering\n\nTo render a value with long (human) denomination, use {canonical(key)}\n\n# Usage\n\nFirst of all, you define which keys have units applied, for example:\n\n```\nunits: [\n appliesTo: [\"maxspeed\", \"maxspeed:hgv\", \"maxspeed:bus\"]\n applicableUnits: [\n ...\n ]\n]\n```\n\nApplicableUnits defines which is the canonical extension, how it is presented to the user, ...:\n\n```\napplicableUnits: [\n{\n canonicalDenomination: \"km/h\",\n alternativeDenomination: [\"km/u\", \"kmh\", \"kph\"]\n default: true,\n human: {\n en: \"kilometer/hour\",\n nl: \"kilometer/uur\"\n },\n humanShort: {\n en: \"km/h\",\n nl: \"km/u\"\n }\n},\n{\n canoncialDenomination: \"mph\",\n ... similar for miles an hour ...\n}\n]\n```\n\n\nIf this is defined, then every key which the denominations apply to (`maxspeed`, `maxspeed:hgv` and `maxspeed:bus`) will be rewritten at the metatagging stage:\nevery value will be parsed and the canonical extension will be added add presented to the other parts of the code.\n\nAlso, if a freeform text field is used, an extra dropdown with applicable denominations will be given", + "type": "array", + "items": { + "$ref": "#/definitions/default_2" + } + }, + "syncSelection": { + "description": "If set, synchronizes wether or not this layer is selected.\n\nno: Do not sync at all, always revert to default\nlocal: keep selection on local storage\ntheme-only: sync via OSM, but this layer will only be toggled in this theme\nglobal: all layers with this ID will be synced accross all themes", + "enum": [ + "global", + "local", + "no", + "theme-only" + ], "type": "string" - } - }, - "eraseInvalidValues": { - "description": "If set, invalid values will be erased in the MC application (but not in OSM of course!)\nBe careful with setting this", - "type": "boolean" - }, - "applicableUnits": { - "description": "The possible denominations", - "type": "array", - "items": { - "$ref": "#/definitions/ApplicableUnitJson" - } } - }, - "required": [ - "applicableUnits", - "appliesToKey" - ] - } - }, - "$schema": "http://json-schema.org/draft-07/schema#" + }, + "required": [ + "id", + "mapRendering", + "source" + ], + "definitions": { + "AndOrTagConfigJson": { + "type": "object", + "properties": { + "and": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + }, + "or": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + } + } + }, + "ApplicableUnitJson": { + "type": "object", + "properties": { + "canonicalDenomination": { + "description": "The canonical value which will be added to the text.\ne.g. \"m\" for meters\nIf the user inputs '42', the canonical value will be added and it'll become '42m'", + "type": "string" + }, + "canonicalDenominationSingular": { + "description": "The canonical denomination in the case that the unit is precisely '1'", + "type": "string" + }, + "alternativeDenomination": { + "description": "A list of alternative values which can occur in the OSM database - used for parsing.", + "type": "array", + "items": { + "type": "string" + } + }, + "human": { + "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"meter\",\n \"fr\": \"metre\"\n}" + }, + "humanSingular": { + "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"minute\",\n \"nl\": \"minuut\"x²\n}" + }, + "prefix": { + "description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field", + "type": "boolean" + }, + "default": { + "description": "The default interpretation - only one can be set.\nIf none is set, the first unit will be considered the default interpretation of a value without a unit", + "type": "boolean" + } + }, + "required": [ + "canonicalDenomination" + ] + }, + "TagRenderingConfigJson": { + "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRenerdering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", + "type": "object", + "properties": { + "id": { + "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", + "type": "string" + }, + "group": { + "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", + "type": "string" + }, + "labels": { + "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", + "type": "array", + "items": { + "type": "string" + } + }, + "render": { + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + }, + "condition": { + "description": "Only show this tagrendering (or question) if the object also matches the following tags.\n\nThis is useful to ask a follow-up question. E.g. if there is a diaper table, then ask a follow-up question on diaper tables...", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "freeform": { + "description": "Allow freeform text input from the user", + "type": "object", + "properties": { + "key": { + "description": "If this key is present, then 'render' is used to display the value.\nIf this is undefined, the rendering is _always_ shown", + "type": "string" + } + }, + "required": [ + "key" + ] + }, + "mappings": { + "description": "Allows fixed-tag inputs, shown either as radiobuttons or as checkboxes", + "type": "array", + "items": { + "type": "object", + "properties": { + "if": { + "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "then": { + "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" + }, + "icon": { + "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "class", + "path" + ] + }, + { + "type": "string" + } + ] + } + }, + "required": [ + "if", + "then" + ] + } + } + } + }, + "T": { + "type": "object" + }, + "default_4": { + "description": "The PointRenderingConfig gives all details onto how to render a single point of a feature.\n\nThis can be used if:\n\n- The feature is a point\n- To render something at the centroid of an area, or at the start, end or projected centroid of a way", + "type": "object", + "properties": { + "location": { + "description": "All the locations that this point should be rendered at.\nUsing `location: [\"point\", \"centroid\"] will always render centerpoint", + "type": "array", + "items": { + "type": "string" + } + }, + "icon": { + "description": "The icon for an element.\nNote that this also doubles as the icon for this layer (rendered with the overpass-tags) ánd the icon in the presets.\n\nThe result of the icon is rendered as follows:\nthe resulting string is interpreted as a _list_ of items, separated by \";\". The bottommost layer is the first layer.\nAs a result, on could use a generic pin, then overlay it with a specific icon.\nTo make things even more practical, one can use all SVG's from the folder \"assets/svg\" and _substitute the color_ in it.\nE.g. to draw a red pin, use \"pin:#f00\", to have a green circle with your icon on top, use `circle:#0f0;`\n\nType: icon", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "iconBadges": { + "description": "A list of extra badges to show next to the icon as small badge\nThey will be added as a 25% height icon at the bottom right of the icon, with all the badges in a flex layout.\n\nNote: strings are interpreted as icons, so layering and substituting is supported. You can use `circle:white;./my_icon.svg` to add a background circle", + "type": "array", + "items": { + "type": "object", + "properties": { + "if": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "then": { + "description": "Badge to show\nType: icon", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + } + }, + "required": [ + "if", + "then" + ] + } + }, + "iconSize": { + "description": "A string containing \"width,height\" or \"width,height,anchorpoint\" where anchorpoint is any of 'center', 'top', 'bottom', 'left', 'right', 'bottomleft','topright', ...\nDefault is '40,40,center'", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "rotation": { + "description": "The rotation of an icon, useful for e.g. directions.\nUsage: as if it were a css property for 'rotate', thus has to end with 'deg', e.g. `90deg`, `{direction}deg`, `calc(90deg - {camera:direction}deg)``", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "label": { + "description": "A HTML-fragment that is shown below the icon, for example:\n
{name}
\n\nIf the icon is undefined, then the label is shown in the center of the feature.\nNote that, if the wayhandling hides the icon then no label is shown as well.", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + } + }, + "required": [ + "location" + ] + }, + "default_5": { + "description": "The LineRenderingConfig gives all details onto how to render a single line of a feature.\n\nThis can be used if:\n\n- The feature is a line\n- The feature is an area", + "type": "object", + "properties": { + "color": { + "description": "The color for way-elements and SVG-elements.\nIf the value starts with \"--\", the style of the body element will be queried for the corresponding variable instead", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "width": { + "description": "The stroke-width for way-elements", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": [ + "string", + "number" + ] + } + ] + }, + "dashArray": { + "description": "A dasharray, e.g. \"5 6\"\nThe dasharray defines 'pixels of line, pixels of gap, pixels of line, pixels of gap',\nDefault value: \"\" (empty string == full line)", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "lineCap": { + "description": "The form at the end of a line", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "fill": { + "description": "Wehter or not to fill polygons", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "enum": [ + "no", + "yes" + ], + "type": "string" + } + ] + }, + "fillColor": { + "description": "The color to fill a polygon with.\nIf undefined, this will be slightly more opaque version of the stroke line", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "offset": { + "description": "The number of pixels this line should be moved.\nUse a positive numbe to move to the right, a negative to move to the left (left/right as defined by the drawing direction of the line).\n\nIMPORTANT: MapComplete will already normalize 'key:both:property' and 'key:both' into the corresponding 'key:left' and 'key:right' tagging (same for 'sidewalk=left/right/both' which is rewritten to 'sidewalk:left' and 'sidewalk:right')\nThis simplifies programming. Refer to the CalculatedTags.md-documentation for more details", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "number" + } + ] + } + } + }, + "QuestionableTagRenderingConfigJson": { + "description": "A QuestionableTagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nIf the desired tags are missing and a question is defined, a question will be shown instead.", + "type": "object", + "properties": { + "question": { + "description": "If it turns out that this tagRendering doesn't match _any_ value, then we show this question.\nIf undefined, the question is never asked and this tagrendering is read-only" + }, + "freeform": { + "description": "Allow freeform text input from the user", + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "type": { + "description": "The type of the text-field, e.g. 'string', 'nat', 'float', 'date',...\nSee Docs/SpecialInputElements.md and UI/Input/ValidatedTextField.ts for supported values", + "type": "string" + }, + "placeholder": { + "description": "A (translated) text that is shown (as gray text) within the textfield" + }, + "helperArgs": { + "description": "Extra parameters to initialize the input helper arguments.\nFor semantics, see the 'SpecialInputElements.md'", + "type": "array", + "items": {} + }, + "addExtraTags": { + "description": "If a value is added with the textfield, these extra tag is addded.\nUseful to add a 'fixme=freeform textfield used - to be checked'", + "type": "array", + "items": { + "type": "string" + } + }, + "inline": { + "description": "When set, influences the way a question is asked.\nInstead of showing a full-widht text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.", + "type": "boolean" + }, + "default": { + "description": "default value to enter if no previous tagging is present.\nNormally undefined (aka do not enter anything)", + "type": "string" + } + }, + "required": [ + "key" + ] + }, + "multiAnswer": { + "description": "If true, use checkboxes instead of radio buttons when asking the question", + "type": "boolean" + }, + "mappings": { + "description": "Allows fixed-tag inputs, shown either as radiobuttons or as checkboxes", + "type": "array", + "items": { + "type": "object", + "properties": { + "if": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "then": { + "description": "Shown if the 'if is fulfilled\nType: rendered" + }, + "icon": { + "description": "An extra icon supporting the choice\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "Size of the image", + "type": "string" + } + }, + "required": [ + "class", + "path" + ] + }, + { + "type": "string" + } + ] + }, + "hideInAnswer": { + "description": "In some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation).\n\nIn the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user.\nIn this case, one of the mappings can be hiden by setting this flag.\n\nTo demonstrate an example making a default assumption:\n\nmappings: [\n {\n if: \"access=\", -- no access tag present, we assume accessible\n then: \"Accessible to the general public\",\n hideInAnswer: true\n },\n {\n if: \"access=yes\",\n then: \"Accessible to the general public\", -- the user selected this, we add that to OSM\n },\n {\n if: \"access=no\",\n then: \"Not accessible to the public\"\n }\n]\n\n\nFor example, for an operator, we have `operator=Agentschap Natuur en Bos`, which is often abbreviated to `operator=ANB`.\nThen, we would add two mappings:\n{\n if: \"operator=Agentschap Natuur en Bos\" -- the non-abbreviated version which should be uploaded\n then: \"Maintained by Agentschap Natuur en Bos\"\n},\n{\n if: \"operator=ANB\", -- we don't want to upload abbreviations\n then: \"Maintained by Agentschap Natuur en Bos\"\n hideInAnswer: true\n}\n\nHide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate.\nKeep in mind that this is reverse logic: it will be hidden in the answer if the condition is true, it will thus only show in the case of a mismatch\n\ne.g., for toilets: if \"wheelchair=no\", we know there is no wheelchair dedicated room.\nFor the location of the changing table, the option \"in the wheelchair accessible toilet is weird\", so we write:\n\n{\n \"question\": \"Where is the changing table located?\"\n \"mappings\": [\n {\"if\":\"changing_table:location=female\",\"then\":\"In the female restroom\"},\n {\"if\":\"changing_table:location=male\",\"then\":\"In the male restroom\"},\n {\"if\":\"changing_table:location=wheelchair\",\"then\":\"In the wheelchair accessible restroom\", \"hideInAnswer\": \"wheelchair=no\"},\n \n ]\n}\n\nAlso have a look for the meta-tags\n{\n if: \"operator=Agentschap Natuur en Bos\",\n then: \"Maintained by Agentschap Natuur en Bos\",\n hideInAnswer: \"_country!=be\"\n}", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": [ + "string", + "boolean" + ] + } + ] + }, + "ifnot": { + "description": "Only applicable if 'multiAnswer' is set.\nThis is for situations such as:\n`accepts:coins=no` where one can select all the possible payment methods. However, we want to make explicit that some options _were not_ selected.\nThis can be done with `ifnot`\nNote that we can not explicitly render this negative case to the user, we cannot show `does _not_ accept coins`.\nIf this is important to your usecase, consider using multiple radiobutton-fields without `multiAnswer`", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "addExtraTags": { + "description": "If chosen as answer, these tags will be applied as well onto the object.\nNot compatible with multiAnswer", + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "if", + "then" + ] + } + }, + "id": { + "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", + "type": "string" + }, + "group": { + "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", + "type": "string" + }, + "labels": { + "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", + "type": "array", + "items": { + "type": "string" + } + }, + "render": { + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + }, + "condition": { + "description": "Only show this tagrendering (or question) if the object also matches the following tags.\n\nThis is useful to ask a follow-up question. E.g. if there is a diaper table, then ask a follow-up question on diaper tables...", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + } + }, + "default<(string|QuestionableTagRenderingConfigJson|{builtin:string;override:any;})[]>": { + "type": "object", + "properties": { + "rewrite": { + "type": "object", + "properties": { + "sourceString": { + "type": "array", + "items": { + "type": "string" + } + }, + "into": { + "type": "array", + "items": { + "type": "array", + "items": {} + } + } + }, + "required": [ + "into", + "sourceString" + ] + }, + "renderings": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/QuestionableTagRenderingConfigJson" + }, + { + "type": "object", + "properties": { + "builtin": { + "type": "string" + }, + "override": {} + }, + "required": [ + "builtin", + "override" + ] + }, + { + "type": "string" + } + ] + } + } + }, + "required": [ + "renderings", + "rewrite" + ] + }, + "default_1": { + "type": "object", + "properties": { + "id": { + "description": "An id/name for this filter, used to set the URL parameters", + "type": "string" + }, + "options": { + "description": "The options for a filter\nIf there are multiple options these will be a list of radio buttons\nIf there is only one option this will be a checkbox\nFiltering is done based on the given osmTags that are compared to the objects in that layer.", + "type": "array", + "items": { + "type": "object", + "properties": { + "question": {}, + "osmTags": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "default": { + "type": "boolean" + }, + "fields": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + }, + "required": [ + "question" + ] + } + } + }, + "required": [ + "id", + "options" + ] + }, + "DeleteConfigJson": { + "type": "object", + "properties": { + "extraDeleteReasons": { + "description": "*\nBy default, three reasons to delete a point are shown:\n\n- The point does not exist anymore\n- The point was a testing point\n- THe point could not be found\n\nHowever, for some layers, there might be different or more specific reasons for deletion which can be user friendly to set, e.g.:\n\n- the shop has closed\n- the climbing route has been closed of for nature conservation reasons\n- ...\n\nThese reasons can be stated here and will be shown in the list of options the user can choose from", + "type": "array", + "items": { + "type": "object", + "properties": { + "explanation": { + "description": "The text that will be shown to the user - translatable" + }, + "changesetMessage": { + "description": "The text that will be uploaded into the changeset or will be used in the fixme in case of a soft deletion\nShould be a few words, in english", + "type": "string" + } + }, + "required": [ + "changesetMessage", + "explanation" + ] + } + }, + "nonDeleteMappings": { + "description": "In some cases, a (starting) contributor might wish to delete a feature even though deletion is not appropriate.\n(The most relevant case are small paths running over private property. These should be marked as 'private' instead of deleted, as the community might trace the path again from aerial imagery, gettting us back to the original situation).\n\nBy adding a 'nonDeleteMapping', an option can be added into the list which will retag the feature.\nIt is important that the feature will be retagged in such a way that it won't be picked up by the layer anymore!", + "type": "array", + "items": { + "type": "object", + "properties": { + "if": { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + "then": {} + }, + "required": [ + "if", + "then" + ] + } + }, + "softDeletionTags": { + "description": "In some cases, the contributor is not allowed to delete the current feature (e.g. because it isn't a point, the point is referenced by a relation or the user isn't experienced enough).\nTo still offer the user a 'delete'-option, the feature is retagged with these tags. This is a soft deletion, as the point isn't actually removed from OSM but rather marked as 'disused'\nIt is important that the feature will be retagged in such a way that it won't be picked up by the layer anymore!\n\nExample (note that \"amenity=\" erases the 'amenity'-key alltogether):\n```\n{\n \"and\": [\"disussed:amenity=public_bookcase\", \"amenity=\"]\n}\n```\n\nor (notice the use of the ':='-tag to copy the old value of 'shop=*' into 'disused:shop='):\n```\n{\n \"and\": [\"disused:shop:={shop}\", \"shop=\"]\n}\n```", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "neededChangesets": { + "description": "*\nBy default, the contributor needs 20 previous changesets to delete points edited by others.\nFor some small features (e.g. bicycle racks) this is too much and this requirement can be lowered or dropped, which can be done here.", + "type": "number" + } + } + }, + "default_3": { + "type": "object", + "properties": { + "enableImproveAccuracy": { + "description": "One default reason to move a point is to improve accuracy.\nSet to false to disable this reason", + "type": "boolean" + }, + "enableRelocation": { + "description": "One default reason to move a point is because it has relocated\nSet to false to disable this reason", + "type": "boolean" + } + } + }, + "default_2": { + "type": "object", + "properties": { + "appliesToKey": { + "description": "Every key from this list will be normalized", + "type": "array", + "items": { + "type": "string" + } + }, + "eraseInvalidValues": { + "description": "If set, invalid values will be erased in the MC application (but not in OSM of course!)\nBe careful with setting this", + "type": "boolean" + }, + "applicableUnits": { + "description": "The possible denominations", + "type": "array", + "items": { + "$ref": "#/definitions/ApplicableUnitJson" + } + } + }, + "required": [ + "applicableUnits", + "appliesToKey" + ] + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" } \ No newline at end of file diff --git a/Docs/Schemas/LayoutConfigJsonJSC.ts b/Docs/Schemas/LayoutConfigJsonJSC.ts index 1367601236..f80e08e10f 100644 --- a/Docs/Schemas/LayoutConfigJsonJSC.ts +++ b/Docs/Schemas/LayoutConfigJsonJSC.ts @@ -1,1483 +1,1483 @@ export default { - "description": "Defines the entire theme.\n\nA theme is the collection of the layers that are shown; the intro text, the icon, ...\nIt more or less defines the entire experience.\n\nMost of the fields defined here are metadata about the theme, such as its name, description, supported languages, default starting location, ...\n\nThe main chunk of the json will however be the 'layers'-array, where the details of your layers are.\n\nGeneral remark: a type (string | any) indicates either a fixed or a translatable string.", - "type": "object", - "properties": { - "id": { - "description": "The id of this layout.\n\nThis is used as hashtag in the changeset message, which will read something like \"Adding data with #mapcomplete for theme #\"\nMake sure it is something decent and descriptive, it should be a simple, lowercase string.\n\nOn official themes, it'll become the name of the page, e.g.\n'cyclestreets' which become 'cyclestreets.html'", - "type": "string" - }, - "credits": { - "description": "Who helped to create this theme and should be attributed?", - "type": "string" - }, - "maintainer": { - "description": "Who does maintain this preset?", - "type": "string" - }, - "version": { - "description": "A version number, either semantically or by date.\nShould be sortable, where the higher value is the later version", - "type": "string" - }, - "mustHaveLanguage": { - "description": "Only used in 'generateLayerOverview': if present, every translation will be checked to make sure it is fully translated.\n\nThis must be a list of two-letter, lowercase codes which identifies the language, e.g. \"en\", \"nl\", ...", - "type": "array", - "items": { - "type": "string" - } - }, - "title": { - "description": "The title, as shown in the welcome message and the more-screen." - }, - "shortDescription": { - "description": "A short description, showed as social description and in the 'more theme'-buttons.\nNote that if this one is not defined, the first sentence of 'description' is used" - }, - "description": { - "description": "The description, as shown in the welcome message and the more-screen" - }, - "descriptionTail": { - "description": "A part of the description, shown under the login-button." - }, - "icon": { - "description": "The icon representing this theme.\nUsed as logo in the more-screen and (for official themes) as favicon, webmanifest logo, ...\nEither a URL or a base64 encoded value (which should include 'data:image/svg+xml;base64)\n\nType: icon", - "type": "string" - }, - "socialImage": { - "description": "Link to a 'social image' which is included as og:image-tag on official themes.\nUseful to share the theme on social media.\nSee https://www.h3xed.com/web-and-internet/how-to-use-og-image-meta-tag-facebook-reddit for more information$\n\nType: image", - "type": "string" - }, - "startZoom": { - "description": "Default location and zoom to start.\nNote that this is barely used. Once the user has visited mapcomplete at least once, the previous location of the user will be used", - "type": "number" - }, - "startLat": { - "type": "number" - }, - "startLon": { - "type": "number" - }, - "widenFactor": { - "description": "When a query is run, the data within bounds of the visible map is loaded.\nHowever, users tend to pan and zoom a lot. It is pretty annoying if every single pan means a reloading of the data.\nFor this, the bounds are widened in order to make a small pan still within bounds of the loaded data.\n\nIF widenfactor is 1, this feature is disabled. A recommended value is between 1 and 3", - "type": "number" - }, - "overpassMaxZoom": { - "description": "At low zoom levels, overpass is used to query features.\nAt high zoom level, the OSM api is used to fetch one or more BBOX aligning with a slippy tile.\nThe overpassMaxZoom controls the flipoverpoint: if the zoom is this or lower, overpass is used.", - "type": "number" - }, - "osmApiTileSize": { - "description": "When the OSM-api is used to fetch features, it does so in a tiled fashion.\nThese tiles are using a ceratin zoom level, that can be controlled here\nDefault: overpassMaxZoom + 1", - "type": "number" - }, - "overrideAll": { - "description": "An override applied on all layers of the theme.\n\nE.g.: if there are two layers defined:\n```\n\"layers\":[\n {\"title\": ..., \"tagRenderings\": [...], \"osmSource\":{\"tags\": ...}},\n {\"title\", ..., \"tagRenderings\", [...], \"osmSource\":{\"tags\" ...}}\n]\n```\n\nand overrideAll is specified:\n```\n\"overrideAll\": {\n \"osmSource\":{\"geoJsonSource\":\"xyz\"}\n}\nthen the result will be that all the layers will have these properties applied and result in:\n\"layers\":[\n {\"title\": ..., \"tagRenderings\": [...], \"osmSource\":{\"tags\": ..., \"geoJsonSource\":\"xyz\"}},\n {\"title\", ..., \"tagRenderings\", [...], \"osmSource\":{\"tags\" ..., \"geoJsonSource\":\"xyz\"}}\n]\n```\n\nIf the overrideAll contains a list where the keys starts with a plus, the values will be appended (instead of discarding the old list), for example\n\n\"overrideAll\": {\n \"+tagRenderings\": [ { ... some tagrendering ... }]\n}\n\nIn the above scenario, `sometagrendering` will be added at the beginning of the tagrenderings of every layer" - }, - "defaultBackgroundId": { - "description": "The id of the default background. BY default: vanilla OSM", - "type": "string" - }, - "tileLayerSources": { - "description": "Define some (overlay) slippy map tilesources", - "type": "array", - "items": { - "$ref": "#/definitions/default_6" - } - }, - "layers": { - "description": "The layers to display.\n\nEvery layer contains a description of which feature to display - the overpassTags which are queried.\nInstead of running one query for every layer, the query is fused.\n\nAfterwards, every layer is given the list of features.\nEvery layer takes away the features that match with them*, and give the leftovers to the next layers.\n\nThis implies that the _order_ of the layers is important in the case of features with the same tags;\nas the later layers might never receive their feature.\n\n*layers can also remove 'leftover'-features if the leftovers overlap with a feature in the layer itself\n\nNote that builtin layers can be reused. Either put in the name of the layer to reuse, or use {builtin: \"layername\", override: ...}\n\nThe 'override'-object will be copied over the original values of the layer, which allows to change certain aspects of the layer\n\nFor example: If you would like to use layer nature reserves, but only from a specific operator (eg. Natuurpunt) you would use the following in your theme:\n\n```\n\"layer\": {\n \"builtin\": \"nature_reserve\",\n \"override\": {\"source\": \n {\"osmTags\": {\n \"+and\":[\"operator=Natuurpunt\"]\n }\n }\n }\n}\n```\n\nIt's also possible to load multiple layers at once, for example, if you would like for both drinking water and benches to start at the zoomlevel at 12, you would use the following:\n\n```\n\"layer\": {\n \"builtin\": [\"benches\", \"drinking_water\"],\n \"override\": {\"minzoom\": 12}\n}\n```", - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/LayerConfigJson" - }, - { - "type": "object", - "properties": { - "builtin": { - "anyOf": [ - { - "type": "array", - "items": { - "type": "string" - } - }, - { - "type": "string" - } - ] - }, - "override": {}, - "hideTagRenderingsWithLabels": { - "description": "TagRenderings with any of these labels will be removed from the layer.\nNote that the 'id' and 'group' are considered labels too", - "type": "array", - "items": { - "type": "string" - } - } - }, - "required": [ - "builtin", - "override" - ] - }, - { + "description": "Defines the entire theme.\n\nA theme is the collection of the layers that are shown; the intro text, the icon, ...\nIt more or less defines the entire experience.\n\nMost of the fields defined here are metadata about the theme, such as its name, description, supported languages, default starting location, ...\n\nThe main chunk of the json will however be the 'layers'-array, where the details of your layers are.\n\nGeneral remark: a type (string | any) indicates either a fixed or a translatable string.", + "type": "object", + "properties": { + "id": { + "description": "The id of this layout.\n\nThis is used as hashtag in the changeset message, which will read something like \"Adding data with #mapcomplete for theme #\"\nMake sure it is something decent and descriptive, it should be a simple, lowercase string.\n\nOn official themes, it'll become the name of the page, e.g.\n'cyclestreets' which become 'cyclestreets.html'", "type": "string" - } - ] - } - }, - "clustering": { - "description": "If defined, data will be clustered.\nDefaults to {maxZoom: 16, minNeeded: 500}", - "anyOf": [ - { - "type": "object", - "properties": { - "maxZoom": { - "description": "All zoom levels above 'maxzoom' are not clustered anymore.\nDefaults to 18", - "type": "number" - }, - "minNeededElements": { - "description": "The number of elements per tile needed to start clustering\nIf clustering is defined, defaults to 250", - "type": "number" - } - } }, - { - "enum": [ - false - ], - "type": "boolean" - } - ] - }, - "customCss": { - "description": "The URL of a custom CSS stylesheet to modify the layout", - "type": "string" - }, - "hideFromOverview": { - "description": "If set to true, this layout will not be shown in the overview with more themes", - "type": "boolean" - }, - "lockLocation": { - "description": "If set to true, the basemap will not scroll outside of the area visible on initial zoom.\nIf set to [[lon, lat], [lon, lat]], the map will not scroll outside of those bounds.\nOff by default, which will enable panning to the entire world", - "anyOf": [ - { - "type": "array", - "items": [ - { - "type": "array", - "items": [ - { - "type": "number" - }, - { - "type": "number" - } - ], - "minItems": 2, - "maxItems": 2 - }, - { - "type": "array", - "items": [ - { - "type": "number" - }, - { - "type": "number" - } - ], - "minItems": 2, - "maxItems": 2 - } - ], - "minItems": 2, - "maxItems": 2 + "credits": { + "description": "Who helped to create this theme and should be attributed?", + "type": "string" }, - { - "type": "array", - "items": { + "maintainer": { + "description": "Who does maintain this preset?", + "type": "string" + }, + "version": { + "description": "A version number, either semantically or by date.\nShould be sortable, where the higher value is the later version", + "type": "string" + }, + "mustHaveLanguage": { + "description": "Only used in 'generateLayerOverview': if present, every translation will be checked to make sure it is fully translated.\n\nThis must be a list of two-letter, lowercase codes which identifies the language, e.g. \"en\", \"nl\", ...", "type": "array", "items": { - "type": "number" - } - } - } - ] - }, - "extraLink": { - "description": "Adds an additional button on the top-left of the application.\nThis can link to an arbitrary location.\n\nNote that {lat},{lon},{zoom}, {language} and {theme} will be replaced\n\nDefault: {icon: \"./assets/svg/pop-out.svg\", href: 'https://mapcomplete.osm.be/{theme}.html?lat={lat}&lon={lon}&z={zoom}, requirements: [\"iframe\",\"no-welcome-message]},", - "$ref": "#/definitions/default" - }, - "enableUserBadge": { - "description": "If set to false, disables logging in.\nThe userbadge will be hidden, all login-buttons will be hidden and editing will be disabled", - "type": "boolean" - }, - "enableShareScreen": { - "description": "If false, hides the tab 'share'-tab in the welcomeMessage", - "type": "boolean" - }, - "enableMoreQuests": { - "description": "Hides the tab with more themes in the welcomeMessage", - "type": "boolean" - }, - "enableLayers": { - "description": "If false, the layer selection/filter view will be hidden\nThe corresponding URL-parameter is 'fs-filters' instead of 'fs-layers'", - "type": "boolean" - }, - "enableSearch": { - "description": "If set to false, hides the search bar", - "type": "boolean" - }, - "enableAddNewPoints": { - "description": "If set to false, the ability to add new points or nodes will be disabled.\nEditing already existing features will still be possible", - "type": "boolean" - }, - "enableGeolocation": { - "description": "If set to false, the 'geolocation'-button will be hidden.", - "type": "boolean" - }, - "enableBackgroundLayerSelection": { - "description": "Enable switching the backgroundlayer.\nIf false, the quickswitch-buttons are removed (bottom left) and the dropdown in the layer selection is removed as well", - "type": "boolean" - }, - "enableShowAllQuestions": { - "description": "If set to true, will show _all_ unanswered questions in a popup instead of just the next one", - "type": "boolean" - }, - "enableDownload": { - "description": "If set to true, download button for the data will be shown (offers downloading as geojson and csv)", - "type": "boolean" - }, - "enablePdfDownload": { - "description": "If set to true, exporting a pdf is enabled", - "type": "boolean" - }, - "enableNoteImports": { - "description": "If true, notes will be loaded and parsed. If a note is an import (as created by the import_helper.html-tool from mapcomplete),\nthese notes will be shown if a relevant layer is present.", - "type": "boolean" - }, - "overpassUrl": { - "description": "Set one or more overpass URLs to use for this theme..", - "anyOf": [ - { - "type": "array", - "items": { - "type": "string" - } - }, - { - "type": "string" - } - ] - }, - "overpassTimeout": { - "description": "Set a different timeout for overpass queries - in seconds. Default: 30s", - "type": "number" - } - }, - "required": [ - "description", - "icon", - "id", - "layers", - "maintainer", - "startLat", - "startLon", - "startZoom", - "title", - "version" - ], - "definitions": { - "AndOrTagConfigJson": { - "type": "object", - "properties": { - "and": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { "type": "string" - } - ] - } - }, - "or": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - } - } - } - }, - "ApplicableUnitJson": { - "type": "object", - "properties": { - "canonicalDenomination": { - "description": "The canonical value which will be added to the text.\ne.g. \"m\" for meters\nIf the user inputs '42', the canonical value will be added and it'll become '42m'", - "type": "string" - }, - "canonicalDenominationSingular": { - "description": "The canonical denomination in the case that the unit is precisely '1'", - "type": "string" - }, - "alternativeDenomination": { - "description": "A list of alternative values which can occur in the OSM database - used for parsing.", - "type": "array", - "items": { - "type": "string" - } - }, - "human": { - "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"meter\",\n \"fr\": \"metre\"\n}" - }, - "humanSingular": { - "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"minute\",\n \"nl\": \"minuut\"x²\n}" - }, - "prefix": { - "description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field", - "type": "boolean" - }, - "default": { - "description": "The default interpretation - only one can be set.\nIf none is set, the first unit will be considered the default interpretation of a value without a unit", - "type": "boolean" - } - }, - "required": [ - "canonicalDenomination" - ] - }, - "TagRenderingConfigJson": { - "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRenerdering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", - "type": "object", - "properties": { - "id": { - "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", - "type": "string" - }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, - "labels": { - "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", - "type": "array", - "items": { - "type": "string" - } - }, - "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" - }, - "condition": { - "description": "Only show this tagrendering (or question) if the object also matches the following tags.\n\nThis is useful to ask a follow-up question. E.g. if there is a diaper table, then ask a follow-up question on diaper tables...", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" } - ] - }, - "freeform": { - "description": "Allow freeform text input from the user", - "type": "object", - "properties": { - "key": { - "description": "If this key is present, then 'render' is used to display the value.\nIf this is undefined, the rendering is _always_ shown", - "type": "string" - } - }, - "required": [ - "key" - ] - }, - "mappings": { - "description": "Allows fixed-tag inputs, shown either as radiobuttons or as checkboxes", - "type": "array", - "items": { - "type": "object", - "properties": { - "if": { - "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - }, - "then": { - "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" - }, - "icon": { - "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", - "anyOf": [ - { - "type": "object", - "properties": { - "path": { - "description": "The path to the icon\nType: icon", - "type": "string" - }, - "class": { - "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", - "type": "string" - } - }, - "required": [ - "class", - "path" - ] - }, - { - "type": "string" - } - ] - } - }, - "required": [ - "if", - "then" - ] - } - } - } - }, - "T": { - "type": "object" - }, - "default_4": { - "description": "The PointRenderingConfig gives all details onto how to render a single point of a feature.\n\nThis can be used if:\n\n- The feature is a point\n- To render something at the centroid of an area, or at the start, end or projected centroid of a way", - "type": "object", - "properties": { - "location": { - "description": "All the locations that this point should be rendered at.\nUsing `location: [\"point\", \"centroid\"] will always render centerpoint", - "type": "array", - "items": { - "type": "string" - } - }, - "icon": { - "description": "The icon for an element.\nNote that this also doubles as the icon for this layer (rendered with the overpass-tags) ánd the icon in the presets.\n\nThe result of the icon is rendered as follows:\nthe resulting string is interpreted as a _list_ of items, separated by \";\". The bottommost layer is the first layer.\nAs a result, on could use a generic pin, then overlay it with a specific icon.\nTo make things even more practical, one can use all SVG's from the folder \"assets/svg\" and _substitute the color_ in it.\nE.g. to draw a red pin, use \"pin:#f00\", to have a green circle with your icon on top, use `circle:#0f0;`\n\nType: icon", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - }, - "iconBadges": { - "description": "A list of extra badges to show next to the icon as small badge\nThey will be added as a 25% height icon at the bottom right of the icon, with all the badges in a flex layout.\n\nNote: strings are interpreted as icons, so layering and substituting is supported. You can use `circle:white;./my_icon.svg` to add a background circle", - "type": "array", - "items": { - "type": "object", - "properties": { - "if": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - }, - "then": { - "description": "Badge to show\nType: icon", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - } - }, - "required": [ - "if", - "then" - ] - } - }, - "iconSize": { - "description": "A string containing \"width,height\" or \"width,height,anchorpoint\" where anchorpoint is any of 'center', 'top', 'bottom', 'left', 'right', 'bottomleft','topright', ...\nDefault is '40,40,center'", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - }, - "rotation": { - "description": "The rotation of an icon, useful for e.g. directions.\nUsage: as if it were a css property for 'rotate', thus has to end with 'deg', e.g. `90deg`, `{direction}deg`, `calc(90deg - {camera:direction}deg)``", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - }, - "label": { - "description": "A HTML-fragment that is shown below the icon, for example:\n
{name}
\n\nIf the icon is undefined, then the label is shown in the center of the feature.\nNote that, if the wayhandling hides the icon then no label is shown as well.", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - } - }, - "required": [ - "location" - ] - }, - "default_5": { - "description": "The LineRenderingConfig gives all details onto how to render a single line of a feature.\n\nThis can be used if:\n\n- The feature is a line\n- The feature is an area", - "type": "object", - "properties": { - "color": { - "description": "The color for way-elements and SVG-elements.\nIf the value starts with \"--\", the style of the body element will be queried for the corresponding variable instead", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - }, - "width": { - "description": "The stroke-width for way-elements", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": [ - "string", - "number" - ] - } - ] - }, - "dashArray": { - "description": "A dasharray, e.g. \"5 6\"\nThe dasharray defines 'pixels of line, pixels of gap, pixels of line, pixels of gap',\nDefault value: \"\" (empty string == full line)", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - }, - "lineCap": { - "description": "The form at the end of a line", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - }, - "fill": { - "description": "Wehter or not to fill polygons", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "enum": [ - "no", - "yes" - ], - "type": "string" - } - ] - }, - "fillColor": { - "description": "The color to fill a polygon with.\nIf undefined, this will be slightly more opaque version of the stroke line", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - }, - "offset": { - "description": "The number of pixels this line should be moved.\nUse a positive numbe to move to the right, a negative to move to the left (left/right as defined by the drawing direction of the line).\n\nIMPORTANT: MapComplete will already normalize 'key:both:property' and 'key:both' into the corresponding 'key:left' and 'key:right' tagging (same for 'sidewalk=left/right/both' which is rewritten to 'sidewalk:left' and 'sidewalk:right')\nThis simplifies programming. Refer to the CalculatedTags.md-documentation for more details", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "number" - } - ] - } - } - }, - "QuestionableTagRenderingConfigJson": { - "description": "A QuestionableTagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nIf the desired tags are missing and a question is defined, a question will be shown instead.", - "type": "object", - "properties": { - "question": { - "description": "If it turns out that this tagRendering doesn't match _any_ value, then we show this question.\nIf undefined, the question is never asked and this tagrendering is read-only" - }, - "freeform": { - "description": "Allow freeform text input from the user", - "type": "object", - "properties": { - "key": { - "type": "string" - }, - "type": { - "description": "The type of the text-field, e.g. 'string', 'nat', 'float', 'date',...\nSee Docs/SpecialInputElements.md and UI/Input/ValidatedTextField.ts for supported values", - "type": "string" - }, - "placeholder": { - "description": "A (translated) text that is shown (as gray text) within the textfield" - }, - "helperArgs": { - "description": "Extra parameters to initialize the input helper arguments.\nFor semantics, see the 'SpecialInputElements.md'", - "type": "array", - "items": {} - }, - "addExtraTags": { - "description": "If a value is added with the textfield, these extra tag is addded.\nUseful to add a 'fixme=freeform textfield used - to be checked'", - "type": "array", - "items": { - "type": "string" - } - }, - "inline": { - "description": "When set, influences the way a question is asked.\nInstead of showing a full-widht text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.", - "type": "boolean" - }, - "default": { - "description": "default value to enter if no previous tagging is present.\nNormally undefined (aka do not enter anything)", - "type": "string" - } - }, - "required": [ - "key" - ] - }, - "multiAnswer": { - "description": "If true, use checkboxes instead of radio buttons when asking the question", - "type": "boolean" - }, - "mappings": { - "description": "Allows fixed-tag inputs, shown either as radiobuttons or as checkboxes", - "type": "array", - "items": { - "type": "object", - "properties": { - "if": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - }, - "then": { - "description": "Shown if the 'if is fulfilled\nType: rendered" - }, - "icon": { - "description": "An extra icon supporting the choice\nType: icon", - "anyOf": [ - { - "type": "object", - "properties": { - "path": { - "description": "The path to the icon\nType: icon", - "type": "string" - }, - "class": { - "description": "Size of the image", - "type": "string" - } - }, - "required": [ - "class", - "path" - ] - }, - { - "type": "string" - } - ] - }, - "hideInAnswer": { - "description": "In some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation).\n\nIn the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user.\nIn this case, one of the mappings can be hiden by setting this flag.\n\nTo demonstrate an example making a default assumption:\n\nmappings: [\n {\n if: \"access=\", -- no access tag present, we assume accessible\n then: \"Accessible to the general public\",\n hideInAnswer: true\n },\n {\n if: \"access=yes\",\n then: \"Accessible to the general public\", -- the user selected this, we add that to OSM\n },\n {\n if: \"access=no\",\n then: \"Not accessible to the public\"\n }\n]\n\n\nFor example, for an operator, we have `operator=Agentschap Natuur en Bos`, which is often abbreviated to `operator=ANB`.\nThen, we would add two mappings:\n{\n if: \"operator=Agentschap Natuur en Bos\" -- the non-abbreviated version which should be uploaded\n then: \"Maintained by Agentschap Natuur en Bos\"\n},\n{\n if: \"operator=ANB\", -- we don't want to upload abbreviations\n then: \"Maintained by Agentschap Natuur en Bos\"\n hideInAnswer: true\n}\n\nHide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate.\nKeep in mind that this is reverse logic: it will be hidden in the answer if the condition is true, it will thus only show in the case of a mismatch\n\ne.g., for toilets: if \"wheelchair=no\", we know there is no wheelchair dedicated room.\nFor the location of the changing table, the option \"in the wheelchair accessible toilet is weird\", so we write:\n\n{\n \"question\": \"Where is the changing table located?\"\n \"mappings\": [\n {\"if\":\"changing_table:location=female\",\"then\":\"In the female restroom\"},\n {\"if\":\"changing_table:location=male\",\"then\":\"In the male restroom\"},\n {\"if\":\"changing_table:location=wheelchair\",\"then\":\"In the wheelchair accessible restroom\", \"hideInAnswer\": \"wheelchair=no\"},\n \n ]\n}\n\nAlso have a look for the meta-tags\n{\n if: \"operator=Agentschap Natuur en Bos\",\n then: \"Maintained by Agentschap Natuur en Bos\",\n hideInAnswer: \"_country!=be\"\n}", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": [ - "string", - "boolean" - ] - } - ] - }, - "ifnot": { - "description": "Only applicable if 'multiAnswer' is set.\nThis is for situations such as:\n`accepts:coins=no` where one can select all the possible payment methods. However, we want to make explicit that some options _were not_ selected.\nThis can be done with `ifnot`\nNote that we can not explicitly render this negative case to the user, we cannot show `does _not_ accept coins`.\nIf this is important to your usecase, consider using multiple radiobutton-fields without `multiAnswer`", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - }, - "addExtraTags": { - "description": "If chosen as answer, these tags will be applied as well onto the object.\nNot compatible with multiAnswer", - "type": "array", - "items": { - "type": "string" - } - } - }, - "required": [ - "if", - "then" - ] - } - }, - "id": { - "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", - "type": "string" - }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, - "labels": { - "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", - "type": "array", - "items": { - "type": "string" - } - }, - "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" - }, - "condition": { - "description": "Only show this tagrendering (or question) if the object also matches the following tags.\n\nThis is useful to ask a follow-up question. E.g. if there is a diaper table, then ask a follow-up question on diaper tables...", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - } - } - }, - "default<(string|QuestionableTagRenderingConfigJson|{builtin:string;override:any;})[]>": { - "type": "object", - "properties": { - "rewrite": { - "type": "object", - "properties": { - "sourceString": { - "type": "array", - "items": { - "type": "string" - } - }, - "into": { - "type": "array", - "items": { - "type": "array", - "items": {} - } - } - }, - "required": [ - "into", - "sourceString" - ] - }, - "renderings": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/QuestionableTagRenderingConfigJson" - }, - { - "type": "object", - "properties": { - "builtin": { - "type": "string" - }, - "override": {} - }, - "required": [ - "builtin", - "override" - ] - }, - { - "type": "string" - } - ] - } - } - }, - "required": [ - "renderings", - "rewrite" - ] - }, - "default_1": { - "type": "object", - "properties": { - "id": { - "description": "An id/name for this filter, used to set the URL parameters", - "type": "string" - }, - "options": { - "description": "The options for a filter\nIf there are multiple options these will be a list of radio buttons\nIf there is only one option this will be a checkbox\nFiltering is done based on the given osmTags that are compared to the objects in that layer.", - "type": "array", - "items": { - "type": "object", - "properties": { - "question": {}, - "osmTags": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - }, - "default": { - "type": "boolean" - }, - "fields": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "type": { - "type": "string" - } - }, - "required": [ - "name" - ] - } - } - }, - "required": [ - "question" - ] - } - } - }, - "required": [ - "id", - "options" - ] - }, - "DeleteConfigJson": { - "type": "object", - "properties": { - "extraDeleteReasons": { - "description": "*\nBy default, three reasons to delete a point are shown:\n\n- The point does not exist anymore\n- The point was a testing point\n- THe point could not be found\n\nHowever, for some layers, there might be different or more specific reasons for deletion which can be user friendly to set, e.g.:\n\n- the shop has closed\n- the climbing route has been closed of for nature conservation reasons\n- ...\n\nThese reasons can be stated here and will be shown in the list of options the user can choose from", - "type": "array", - "items": { - "type": "object", - "properties": { - "explanation": { - "description": "The text that will be shown to the user - translatable" - }, - "changesetMessage": { - "description": "The text that will be uploaded into the changeset or will be used in the fixme in case of a soft deletion\nShould be a few words, in english", - "type": "string" - } - }, - "required": [ - "changesetMessage", - "explanation" - ] - } - }, - "nonDeleteMappings": { - "description": "In some cases, a (starting) contributor might wish to delete a feature even though deletion is not appropriate.\n(The most relevant case are small paths running over private property. These should be marked as 'private' instead of deleted, as the community might trace the path again from aerial imagery, gettting us back to the original situation).\n\nBy adding a 'nonDeleteMapping', an option can be added into the list which will retag the feature.\nIt is important that the feature will be retagged in such a way that it won't be picked up by the layer anymore!", - "type": "array", - "items": { - "type": "object", - "properties": { - "if": { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - "then": {} - }, - "required": [ - "if", - "then" - ] - } - }, - "softDeletionTags": { - "description": "In some cases, the contributor is not allowed to delete the current feature (e.g. because it isn't a point, the point is referenced by a relation or the user isn't experienced enough).\nTo still offer the user a 'delete'-option, the feature is retagged with these tags. This is a soft deletion, as the point isn't actually removed from OSM but rather marked as 'disused'\nIt is important that the feature will be retagged in such a way that it won't be picked up by the layer anymore!\n\nExample (note that \"amenity=\" erases the 'amenity'-key alltogether):\n```\n{\n \"and\": [\"disussed:amenity=public_bookcase\", \"amenity=\"]\n}\n```\n\nor (notice the use of the ':='-tag to copy the old value of 'shop=*' into 'disused:shop='):\n```\n{\n \"and\": [\"disused:shop:={shop}\", \"shop=\"]\n}\n```", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - }, - "neededChangesets": { - "description": "*\nBy default, the contributor needs 20 previous changesets to delete points edited by others.\nFor some small features (e.g. bicycle racks) this is too much and this requirement can be lowered or dropped, which can be done here.", - "type": "number" - } - } - }, - "default_3": { - "type": "object", - "properties": { - "enableImproveAccuracy": { - "description": "One default reason to move a point is to improve accuracy.\nSet to false to disable this reason", - "type": "boolean" - }, - "enableRelocation": { - "description": "One default reason to move a point is because it has relocated\nSet to false to disable this reason", - "type": "boolean" - } - } - }, - "default_2": { - "type": "object", - "properties": { - "appliesToKey": { - "description": "Every key from this list will be normalized", - "type": "array", - "items": { - "type": "string" - } - }, - "eraseInvalidValues": { - "description": "If set, invalid values will be erased in the MC application (but not in OSM of course!)\nBe careful with setting this", - "type": "boolean" - }, - "applicableUnits": { - "description": "The possible denominations", - "type": "array", - "items": { - "$ref": "#/definitions/ApplicableUnitJson" - } - } - }, - "required": [ - "applicableUnits", - "appliesToKey" - ] - }, - "default_6": { - "description": "Configuration for a tilesource config", - "type": "object", - "properties": { - "id": { - "description": "Id of this overlay, used in the URL-parameters to set the state", - "type": "string" - }, - "source": { - "description": "The path, where {x}, {y} and {z} will be substituted", - "type": "string" - }, - "isOverlay": { - "description": "Wether or not this is an overlay. Default: true", - "type": "boolean" - }, - "name": { - "description": "How this will be shown in the selection menu.\nMake undefined if this may not be toggled" - }, - "minZoom": { - "description": "Only visible at this or a higher zoom level", - "type": "number" - }, - "maxZoom": { - "description": "Only visible at this or a lower zoom level", - "type": "number" - }, - "defaultState": { - "description": "The default state, set to false to hide by default", - "type": "boolean" - } - }, - "required": [ - "defaultState", - "id", - "source" - ] - }, - "LayerConfigJson": { - "description": "Configuration for a single layer", - "type": "object", - "properties": { - "id": { - "description": "The id of this layer.\nThis should be a simple, lowercase, human readable string that is used to identify the layer.", - "type": "string" - }, - "name": { - "description": "The name of this layer\nUsed in the layer control panel and the 'Personal theme'.\n\nIf not given, will be hidden (and thus not toggable) in the layer control" - }, - "description": { - "description": "A description for this layer.\nShown in the layer selections and in the personel theme" - }, - "source": { - "description": "This determines where the data for the layer is fetched: from OSM or from an external geojson dataset.\n\nIf no 'geojson' is defined, data will be fetched from overpass and the OSM-API.\n\nEvery source _must_ define which tags _must_ be present in order to be picked up.", - "anyOf": [ - { - "allOf": [ - { - "type": "object", - "properties": { - "osmTags": { - "description": "Every source must set which tags have to be present in order to load the given layer.", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - }, - "maxCacheAge": { - "description": "The maximum amount of seconds that a tile is allowed to linger in the cache", - "type": "number" - } - }, - "required": [ - "osmTags" - ] - }, - { - "type": "object", - "properties": { - "overpassScript": { - "type": "string" - } - } - } - ] - }, - { - "allOf": [ - { - "type": "object", - "properties": { - "osmTags": { - "description": "Every source must set which tags have to be present in order to load the given layer.", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - }, - "maxCacheAge": { - "description": "The maximum amount of seconds that a tile is allowed to linger in the cache", - "type": "number" - } - }, - "required": [ - "osmTags" - ] - }, - { - "type": "object", - "properties": { - "geoJson": { - "description": "The actual source of the data to load, if loaded via geojson.\n\n# A single geojson-file\nsource: {geoJson: \"https://my.source.net/some-geo-data.geojson\"}\n fetches a geojson from a third party source\n\n# A tiled geojson source\nsource: {geoJson: \"https://my.source.net/some-tile-geojson-{layer}-{z}-{x}-{y}.geojson\", geoJsonZoomLevel: 14}\n to use a tiled geojson source. The web server must offer multiple geojsons. {z}, {x} and {y} are substituted by the location; {layer} is substituted with the id of the loaded layer\n\nSome API's use a BBOX instead of a tile, this can be used by specifying {y_min}, {y_max}, {x_min} and {x_max}", - "type": "string" - }, - "geoJsonZoomLevel": { - "description": "To load a tiled geojson layer, set the zoomlevel of the tiles", - "type": "number" - }, - "isOsmCache": { - "description": "Indicates that the upstream geojson data is OSM-derived.\nUseful for e.g. merging or for scripts generating this cache", - "type": "boolean" - }, - "mercatorCrs": { - "description": "Some API's use a mercator-projection (EPSG:900913) instead of WGS84. Set the flag `mercatorCrs: true` in the source for this", - "type": "boolean" - }, - "idKey": { - "description": "Some API's have an id-field, but give it a different name.\nSetting this key will rename this field into 'id'", - "type": "string" - } - }, - "required": [ - "geoJson" - ] - } - ] - } - ] - }, - "calculatedTags": { - "description": "A list of extra tags to calculate, specified as \"keyToAssignTo=javascript-expression\".\nThere are a few extra functions available. Refer to Docs/CalculatedTags.md for more information\nThe functions will be run in order, e.g.\n[\n \"_max_overlap_m2=Math.max(...feat.overlapsWith(\"someOtherLayer\").map(o => o.overlap))\n \"_max_overlap_ratio=Number(feat._max_overlap_m2)/feat.area\n]\n\nThe specified tags are evaluated lazily. E.g. if a calculated tag is only used in the popup (e.g. the number of nearby features),\nthe expensive calculation will only be performed then for that feature. This avoids clogging up the contributors PC when all features are loaded.\n\nIf a tag has to be evaluated strictly, use ':=' instead:\n\n[\n\"_some_key:=some_javascript_expression\"\n]", - "type": "array", - "items": { - "type": "string" - } - }, - "doNotDownload": { - "description": "If set, this layer will not query overpass; but it'll still match the tags above which are by chance returned by other layers.\nWorks well together with 'passAllFeatures', to add decoration", - "type": "boolean" - }, - "isShown": { - "description": "This tag rendering should either be 'yes' or 'no'. If 'no' is returned, then the feature will be hidden from view.\nThis is useful to hide certain features from view.\n\nImportant: hiding features does not work dynamically, but is only calculated when the data is first renders.\nThis implies that it is not possible to hide a feature after a tagging change\n\nThe default value is 'yes'", - "$ref": "#/definitions/TagRenderingConfigJson" - }, - "forceLoad": { - "description": "Advanced option - might be set by the theme compiler\n\nIf true, this data will _always_ be loaded, even if the theme is disabled", - "type": "boolean" - }, - "minzoom": { - "description": "The minimum needed zoomlevel required before loading of the data start\nDefault: 0", - "type": "number" - }, - "shownByDefault": { - "description": "Indicates if this layer is shown by default;\ncan be used to hide a layer from start, or to load the layer but only to show it where appropriate (e.g. for snapping to it)", - "type": "boolean" - }, - "minzoomVisible": { - "description": "The zoom level at which point the data is hidden again\nDefault: 100 (thus: always visible", - "type": "number" }, "title": { - "description": "The title shown in a popup for elements of this layer.", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] + "description": "The title, as shown in the welcome message and the more-screen." }, - "titleIcons": { - "description": "Small icons shown next to the title.\nIf not specified, the OsmLink and wikipedia links will be used by default.\nUse an empty array to hide them.\nNote that \"defaults\" will insert all the default titleIcons (which are added automatically)\n\nType: icon[]", - "anyOf": [ - { - "type": "array", - "items": { + "shortDescription": { + "description": "A short description, showed as social description and in the 'more theme'-buttons.\nNote that if this one is not defined, the first sentence of 'description' is used" + }, + "description": { + "description": "The description, as shown in the welcome message and the more-screen" + }, + "descriptionTail": { + "description": "A part of the description, shown under the login-button." + }, + "icon": { + "description": "The icon representing this theme.\nUsed as logo in the more-screen and (for official themes) as favicon, webmanifest logo, ...\nEither a URL or a base64 encoded value (which should include 'data:image/svg+xml;base64)\n\nType: icon", + "type": "string" + }, + "socialImage": { + "description": "Link to a 'social image' which is included as og:image-tag on official themes.\nUseful to share the theme on social media.\nSee https://www.h3xed.com/web-and-internet/how-to-use-og-image-meta-tag-facebook-reddit for more information$\n\nType: image", + "type": "string" + }, + "startZoom": { + "description": "Default location and zoom to start.\nNote that this is barely used. Once the user has visited mapcomplete at least once, the previous location of the user will be used", + "type": "number" + }, + "startLat": { + "type": "number" + }, + "startLon": { + "type": "number" + }, + "widenFactor": { + "description": "When a query is run, the data within bounds of the visible map is loaded.\nHowever, users tend to pan and zoom a lot. It is pretty annoying if every single pan means a reloading of the data.\nFor this, the bounds are widened in order to make a small pan still within bounds of the loaded data.\n\nIF widenfactor is 1, this feature is disabled. A recommended value is between 1 and 3", + "type": "number" + }, + "overpassMaxZoom": { + "description": "At low zoom levels, overpass is used to query features.\nAt high zoom level, the OSM api is used to fetch one or more BBOX aligning with a slippy tile.\nThe overpassMaxZoom controls the flipoverpoint: if the zoom is this or lower, overpass is used.", + "type": "number" + }, + "osmApiTileSize": { + "description": "When the OSM-api is used to fetch features, it does so in a tiled fashion.\nThese tiles are using a ceratin zoom level, that can be controlled here\nDefault: overpassMaxZoom + 1", + "type": "number" + }, + "overrideAll": { + "description": "An override applied on all layers of the theme.\n\nE.g.: if there are two layers defined:\n```\n\"layers\":[\n {\"title\": ..., \"tagRenderings\": [...], \"osmSource\":{\"tags\": ...}},\n {\"title\", ..., \"tagRenderings\", [...], \"osmSource\":{\"tags\" ...}}\n]\n```\n\nand overrideAll is specified:\n```\n\"overrideAll\": {\n \"osmSource\":{\"geoJsonSource\":\"xyz\"}\n}\nthen the result will be that all the layers will have these properties applied and result in:\n\"layers\":[\n {\"title\": ..., \"tagRenderings\": [...], \"osmSource\":{\"tags\": ..., \"geoJsonSource\":\"xyz\"}},\n {\"title\", ..., \"tagRenderings\", [...], \"osmSource\":{\"tags\" ..., \"geoJsonSource\":\"xyz\"}}\n]\n```\n\nIf the overrideAll contains a list where the keys starts with a plus, the values will be appended (instead of discarding the old list), for example\n\n\"overrideAll\": {\n \"+tagRenderings\": [ { ... some tagrendering ... }]\n}\n\nIn the above scenario, `sometagrendering` will be added at the beginning of the tagrenderings of every layer" + }, + "defaultBackgroundId": { + "description": "The id of the default background. BY default: vanilla OSM", + "type": "string" + }, + "tileLayerSources": { + "description": "Define some (overlay) slippy map tilesources", + "type": "array", + "items": { + "$ref": "#/definitions/default_6" + } + }, + "layers": { + "description": "The layers to display.\n\nEvery layer contains a description of which feature to display - the overpassTags which are queried.\nInstead of running one query for every layer, the query is fused.\n\nAfterwards, every layer is given the list of features.\nEvery layer takes away the features that match with them*, and give the leftovers to the next layers.\n\nThis implies that the _order_ of the layers is important in the case of features with the same tags;\nas the later layers might never receive their feature.\n\n*layers can also remove 'leftover'-features if the leftovers overlap with a feature in the layer itself\n\nNote that builtin layers can be reused. Either put in the name of the layer to reuse, or use {builtin: \"layername\", override: ...}\n\nThe 'override'-object will be copied over the original values of the layer, which allows to change certain aspects of the layer\n\nFor example: If you would like to use layer nature reserves, but only from a specific operator (eg. Natuurpunt) you would use the following in your theme:\n\n```\n\"layer\": {\n \"builtin\": \"nature_reserve\",\n \"override\": {\"source\": \n {\"osmTags\": {\n \"+and\":[\"operator=Natuurpunt\"]\n }\n }\n }\n}\n```\n\nIt's also possible to load multiple layers at once, for example, if you would like for both drinking water and benches to start at the zoomlevel at 12, you would use the following:\n\n```\n\"layer\": {\n \"builtin\": [\"benches\", \"drinking_water\"],\n \"override\": {\"minzoom\": 12}\n}\n```", + "type": "array", + "items": { "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } + { + "$ref": "#/definitions/LayerConfigJson" + }, + { + "type": "object", + "properties": { + "builtin": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "override": {}, + "hideTagRenderingsWithLabels": { + "description": "TagRenderings with any of these labels will be removed from the layer.\nNote that the 'id' and 'group' are considered labels too", + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "builtin", + "override" + ] + }, + { + "type": "string" + } ] - } - }, - { - "type": "array", - "items": [ + } + }, + "clustering": { + "description": "If defined, data will be clustered.\nDefaults to {maxZoom: 16, minNeeded: 500}", + "anyOf": [ { - "type": "string", - "enum": [ - "defaults" - ] - } - ], - "minItems": 1, - "maxItems": 1 - } - ] - }, - "mapRendering": { - "description": "Visualisation of the items on the map", - "anyOf": [ - { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/default_4" - }, - { - "$ref": "#/definitions/default_5" - } - ] - } - }, - { - "type": "null" - } - ] - }, - "passAllFeatures": { - "description": "If set, this layer will pass all the features it receives onto the next layer.\nThis is ideal for decoration, e.g. directionss on cameras", - "type": "boolean" - }, - "presets": { - "description": "Presets for this layer.\nA preset shows up when clicking the map on a without data (or when right-clicking/long-pressing);\nit will prompt the user to add a new point.\n\nThe most important aspect are the tags, which define which tags the new point will have;\nThe title is shown in the dialog, along with the first sentence of the description.\n\nUpon confirmation, the full description is shown beneath the buttons - perfect to add pictures and examples.\n\nNote: the icon of the preset is determined automatically based on the tags and the icon above. Don't worry about that!\nNB: if no presets are defined, the popup to add new points doesn't show up at all", - "type": "array", - "items": { - "type": "object", - "properties": { - "title": { - "description": "The title - shown on the 'add-new'-button." - }, - "tags": { - "description": "The tags to add. It determines the icon too", - "type": "array", - "items": { - "type": "string" - } - }, - "description": { - "description": "The _first sentence_ of the description is shown on the button of the `add` menu.\nThe full description is shown in the confirmation dialog.\n\n(The first sentence is until the first '.'-character in the description)" - }, - "exampleImages": { - "description": "Example images, which show real-life pictures of what such a feature might look like\n\nType: image", - "type": "array", - "items": { - "type": "string" - } - }, - "preciseInput": { - "description": "If set, the user will prompted to confirm the location before actually adding the data.\nThis will be with a 'drag crosshair'-method.\n\nIf 'preferredBackgroundCategory' is set, the element will attempt to pick a background layer of that category.", - "anyOf": [ - { "type": "object", "properties": { - "preferredBackground": { - "description": "The type of background picture", - "anyOf": [ - { - "type": "array", - "items": { - "type": "string" - } - }, - { - "type": "string" - } - ] - }, - "snapToLayer": { - "description": "If specified, these layers will be shown to and the new point will be snapped towards it", - "anyOf": [ - { - "type": "array", - "items": { - "type": "string" - } - }, - { - "type": "string" - } - ] - }, - "maxSnapDistance": { - "description": "If specified, a new point will only be snapped if it is within this range.\nDistance in meter\n\nDefault: 10", - "type": "number" - } - }, - "required": [ - "preferredBackground" - ] - }, - { + "maxZoom": { + "description": "All zoom levels above 'maxzoom' are not clustered anymore.\nDefaults to 18", + "type": "number" + }, + "minNeededElements": { + "description": "The number of elements per tile needed to start clustering\nIf clustering is defined, defaults to 250", + "type": "number" + } + } + }, + { "enum": [ - true + false ], "type": "boolean" - } - ] - } + } + ] + }, + "customCss": { + "description": "The URL of a custom CSS stylesheet to modify the layout", + "type": "string" + }, + "hideFromOverview": { + "description": "If set to true, this layout will not be shown in the overview with more themes", + "type": "boolean" + }, + "lockLocation": { + "description": "If set to true, the basemap will not scroll outside of the area visible on initial zoom.\nIf set to [[lon, lat], [lon, lat]], the map will not scroll outside of those bounds.\nOff by default, which will enable panning to the entire world", + "anyOf": [ + { + "type": "array", + "items": [ + { + "type": "array", + "items": [ + { + "type": "number" + }, + { + "type": "number" + } + ], + "minItems": 2, + "maxItems": 2 + }, + { + "type": "array", + "items": [ + { + "type": "number" + }, + { + "type": "number" + } + ], + "minItems": 2, + "maxItems": 2 + } + ], + "minItems": 2, + "maxItems": 2 + }, + { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "number" + } + } + } + ] + }, + "extraLink": { + "description": "Adds an additional button on the top-left of the application.\nThis can link to an arbitrary location.\n\nNote that {lat},{lon},{zoom}, {language} and {theme} will be replaced\n\nDefault: {icon: \"./assets/svg/pop-out.svg\", href: 'https://mapcomplete.osm.be/{theme}.html?lat={lat}&lon={lon}&z={zoom}, requirements: [\"iframe\",\"no-welcome-message]},", + "$ref": "#/definitions/default" + }, + "enableUserBadge": { + "description": "If set to false, disables logging in.\nThe userbadge will be hidden, all login-buttons will be hidden and editing will be disabled", + "type": "boolean" + }, + "enableShareScreen": { + "description": "If false, hides the tab 'share'-tab in the welcomeMessage", + "type": "boolean" + }, + "enableMoreQuests": { + "description": "Hides the tab with more themes in the welcomeMessage", + "type": "boolean" + }, + "enableLayers": { + "description": "If false, the layer selection/filter view will be hidden\nThe corresponding URL-parameter is 'fs-filters' instead of 'fs-layers'", + "type": "boolean" + }, + "enableSearch": { + "description": "If set to false, hides the search bar", + "type": "boolean" + }, + "enableAddNewPoints": { + "description": "If set to false, the ability to add new points or nodes will be disabled.\nEditing already existing features will still be possible", + "type": "boolean" + }, + "enableGeolocation": { + "description": "If set to false, the 'geolocation'-button will be hidden.", + "type": "boolean" + }, + "enableBackgroundLayerSelection": { + "description": "Enable switching the backgroundlayer.\nIf false, the quickswitch-buttons are removed (bottom left) and the dropdown in the layer selection is removed as well", + "type": "boolean" + }, + "enableShowAllQuestions": { + "description": "If set to true, will show _all_ unanswered questions in a popup instead of just the next one", + "type": "boolean" + }, + "enableDownload": { + "description": "If set to true, download button for the data will be shown (offers downloading as geojson and csv)", + "type": "boolean" + }, + "enablePdfDownload": { + "description": "If set to true, exporting a pdf is enabled", + "type": "boolean" + }, + "enableNoteImports": { + "description": "If true, notes will be loaded and parsed. If a note is an import (as created by the import_helper.html-tool from mapcomplete),\nthese notes will be shown if a relevant layer is present.", + "type": "boolean" + }, + "overpassUrl": { + "description": "Set one or more overpass URLs to use for this theme..", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "overpassTimeout": { + "description": "Set a different timeout for overpass queries - in seconds. Default: 30s", + "type": "number" + } + }, + "required": [ + "description", + "icon", + "id", + "layers", + "maintainer", + "startLat", + "startLon", + "startZoom", + "title", + "version" + ], + "definitions": { + "AndOrTagConfigJson": { + "type": "object", + "properties": { + "and": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + }, + "or": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + } + } + }, + "ApplicableUnitJson": { + "type": "object", + "properties": { + "canonicalDenomination": { + "description": "The canonical value which will be added to the text.\ne.g. \"m\" for meters\nIf the user inputs '42', the canonical value will be added and it'll become '42m'", + "type": "string" + }, + "canonicalDenominationSingular": { + "description": "The canonical denomination in the case that the unit is precisely '1'", + "type": "string" + }, + "alternativeDenomination": { + "description": "A list of alternative values which can occur in the OSM database - used for parsing.", + "type": "array", + "items": { + "type": "string" + } + }, + "human": { + "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"meter\",\n \"fr\": \"metre\"\n}" + }, + "humanSingular": { + "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"minute\",\n \"nl\": \"minuut\"x²\n}" + }, + "prefix": { + "description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field", + "type": "boolean" + }, + "default": { + "description": "The default interpretation - only one can be set.\nIf none is set, the first unit will be considered the default interpretation of a value without a unit", + "type": "boolean" + } }, "required": [ - "tags", - "title" + "canonicalDenomination" ] - } }, - "tagRenderings": { - "description": "All the tag renderings.\nA tag rendering is a block that either shows the known value or asks a question.\n\nRefer to the class `TagRenderingConfigJson` to see the possibilities.\n\nNote that we can also use a string here - where the string refers to a tag rendering defined in `assets/questions/questions.json`,\nwhere a few very general questions are defined e.g. website, phone number, ...\n\nA special value is 'questions', which indicates the location of the questions box. If not specified, it'll be appended to the bottom of the featureInfobox.\n\nAt last, one can define a group of renderings where parts of all strings will be replaced by multiple other strings.\nThis is mainly create questions for a 'left' and a 'right' side of the road.\nThese will be grouped and questions will be asked together", - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/QuestionableTagRenderingConfigJson" - }, - { - "type": "object", - "properties": { - "builtin": { + "TagRenderingConfigJson": { + "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRenerdering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", + "type": "object", + "properties": { + "id": { + "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", "type": "string" - }, - "override": {} }, - "required": [ - "builtin", - "override" - ] - }, - { - "$ref": "#/definitions/default<(string|QuestionableTagRenderingConfigJson|{builtin:string;override:any;})[]>" - }, - { - "type": "string" - } - ] - } - }, - "filter": { - "description": "All the extra questions for filtering", - "anyOf": [ - { - "type": "array", - "items": { - "$ref": "#/definitions/default_1" - } - }, - { - "type": "object", - "properties": { - "sameAs": { - "type": "string" + "group": { + "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", + "type": "string" + }, + "labels": { + "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", + "type": "array", + "items": { + "type": "string" + } + }, + "render": { + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + }, + "condition": { + "description": "Only show this tagrendering (or question) if the object also matches the following tags.\n\nThis is useful to ask a follow-up question. E.g. if there is a diaper table, then ask a follow-up question on diaper tables...", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "freeform": { + "description": "Allow freeform text input from the user", + "type": "object", + "properties": { + "key": { + "description": "If this key is present, then 'render' is used to display the value.\nIf this is undefined, the rendering is _always_ shown", + "type": "string" + } + }, + "required": [ + "key" + ] + }, + "mappings": { + "description": "Allows fixed-tag inputs, shown either as radiobuttons or as checkboxes", + "type": "array", + "items": { + "type": "object", + "properties": { + "if": { + "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "then": { + "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" + }, + "icon": { + "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "class", + "path" + ] + }, + { + "type": "string" + } + ] + } + }, + "required": [ + "if", + "then" + ] + } } - }, - "required": [ - "sameAs" - ] } - ] }, - "deletion": { - "description": "This block defines under what circumstances the delete dialog is shown for objects of this layer.\nIf set, a dialog is shown to the user to (soft) delete the point.\nThe dialog is built to be user friendly and to prevent mistakes.\nIf deletion is not possible, the dialog will hide itself and show the reason of non-deletability instead.\n\nTo configure, the following values are possible:\n\n- false: never ever show the delete button\n- true: show the default delete button\n- undefined: use the mapcomplete default to show deletion or not. Currently, this is the same as 'false' but this will change in the future\n- or: a hash with options (see below)\n\n The delete dialog\n =================\n\n\n\n#### Hard deletion if enough experience\n\nA feature can only be deleted from OpenStreetMap by mapcomplete if:\n\n- It is a node\n- No ways or relations use the node\n- The logged-in user has enough experience OR the user is the only one to have edited the point previously\n- The logged-in user has no unread messages (or has a ton of experience)\n- The user did not select one of the 'non-delete-options' (see below)\n\nIn all other cases, a 'soft deletion' is used.\n\n#### Soft deletion\n\nA 'soft deletion' is when the point isn't deleted from OSM but retagged so that it'll won't how up in the mapcomplete theme anymore.\nThis makes it look like it was deleted, without doing damage. A fixme will be added to the point.\n\nNote that a soft deletion is _only_ possible if these tags are provided by the theme creator, as they'll be different for every theme\n\n#### No-delete options\n\nIn some cases, the contributor might want to delete something for the wrong reason (e.g. someone who wants to have a path removed \"because the path is on their private property\").\nHowever, the path exists in reality and should thus be on OSM - otherwise the next contributor will pass by and notice \"hey, there is a path missing here! Let me redraw it in OSM!)\n\nThe correct approach is to retag the feature in such a way that it is semantically correct *and* that it doesn't show up on the theme anymore.\nA no-delete option is offered as 'reason to delete it', but secretly retags.", - "anyOf": [ - { - "$ref": "#/definitions/DeleteConfigJson" + "T": { + "type": "object" + }, + "default_4": { + "description": "The PointRenderingConfig gives all details onto how to render a single point of a feature.\n\nThis can be used if:\n\n- The feature is a point\n- To render something at the centroid of an area, or at the start, end or projected centroid of a way", + "type": "object", + "properties": { + "location": { + "description": "All the locations that this point should be rendered at.\nUsing `location: [\"point\", \"centroid\"] will always render centerpoint", + "type": "array", + "items": { + "type": "string" + } + }, + "icon": { + "description": "The icon for an element.\nNote that this also doubles as the icon for this layer (rendered with the overpass-tags) ánd the icon in the presets.\n\nThe result of the icon is rendered as follows:\nthe resulting string is interpreted as a _list_ of items, separated by \";\". The bottommost layer is the first layer.\nAs a result, on could use a generic pin, then overlay it with a specific icon.\nTo make things even more practical, one can use all SVG's from the folder \"assets/svg\" and _substitute the color_ in it.\nE.g. to draw a red pin, use \"pin:#f00\", to have a green circle with your icon on top, use `circle:#0f0;`\n\nType: icon", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "iconBadges": { + "description": "A list of extra badges to show next to the icon as small badge\nThey will be added as a 25% height icon at the bottom right of the icon, with all the badges in a flex layout.\n\nNote: strings are interpreted as icons, so layering and substituting is supported. You can use `circle:white;./my_icon.svg` to add a background circle", + "type": "array", + "items": { + "type": "object", + "properties": { + "if": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "then": { + "description": "Badge to show\nType: icon", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + } + }, + "required": [ + "if", + "then" + ] + } + }, + "iconSize": { + "description": "A string containing \"width,height\" or \"width,height,anchorpoint\" where anchorpoint is any of 'center', 'top', 'bottom', 'left', 'right', 'bottomleft','topright', ...\nDefault is '40,40,center'", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "rotation": { + "description": "The rotation of an icon, useful for e.g. directions.\nUsage: as if it were a css property for 'rotate', thus has to end with 'deg', e.g. `90deg`, `{direction}deg`, `calc(90deg - {camera:direction}deg)``", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "label": { + "description": "A HTML-fragment that is shown below the icon, for example:\n
{name}
\n\nIf the icon is undefined, then the label is shown in the center of the feature.\nNote that, if the wayhandling hides the icon then no label is shown as well.", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + } }, - { - "type": "boolean" - } - ] + "required": [ + "location" + ] }, - "allowMove": { - "description": "Indicates if a point can be moved and configures the modalities.\n\nA feature can be moved by MapComplete if:\n\n- It is a point\n- The point is _not_ part of a way or a a relation.\n\nOff by default. Can be enabled by setting this flag or by configuring.", - "anyOf": [ - { - "$ref": "#/definitions/default_3" + "default_5": { + "description": "The LineRenderingConfig gives all details onto how to render a single line of a feature.\n\nThis can be used if:\n\n- The feature is a line\n- The feature is an area", + "type": "object", + "properties": { + "color": { + "description": "The color for way-elements and SVG-elements.\nIf the value starts with \"--\", the style of the body element will be queried for the corresponding variable instead", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "width": { + "description": "The stroke-width for way-elements", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": [ + "string", + "number" + ] + } + ] + }, + "dashArray": { + "description": "A dasharray, e.g. \"5 6\"\nThe dasharray defines 'pixels of line, pixels of gap, pixels of line, pixels of gap',\nDefault value: \"\" (empty string == full line)", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "lineCap": { + "description": "The form at the end of a line", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "fill": { + "description": "Wehter or not to fill polygons", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "enum": [ + "no", + "yes" + ], + "type": "string" + } + ] + }, + "fillColor": { + "description": "The color to fill a polygon with.\nIf undefined, this will be slightly more opaque version of the stroke line", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "offset": { + "description": "The number of pixels this line should be moved.\nUse a positive numbe to move to the right, a negative to move to the left (left/right as defined by the drawing direction of the line).\n\nIMPORTANT: MapComplete will already normalize 'key:both:property' and 'key:both' into the corresponding 'key:left' and 'key:right' tagging (same for 'sidewalk=left/right/both' which is rewritten to 'sidewalk:left' and 'sidewalk:right')\nThis simplifies programming. Refer to the CalculatedTags.md-documentation for more details", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "number" + } + ] + } + } + }, + "QuestionableTagRenderingConfigJson": { + "description": "A QuestionableTagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nIf the desired tags are missing and a question is defined, a question will be shown instead.", + "type": "object", + "properties": { + "question": { + "description": "If it turns out that this tagRendering doesn't match _any_ value, then we show this question.\nIf undefined, the question is never asked and this tagrendering is read-only" + }, + "freeform": { + "description": "Allow freeform text input from the user", + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "type": { + "description": "The type of the text-field, e.g. 'string', 'nat', 'float', 'date',...\nSee Docs/SpecialInputElements.md and UI/Input/ValidatedTextField.ts for supported values", + "type": "string" + }, + "placeholder": { + "description": "A (translated) text that is shown (as gray text) within the textfield" + }, + "helperArgs": { + "description": "Extra parameters to initialize the input helper arguments.\nFor semantics, see the 'SpecialInputElements.md'", + "type": "array", + "items": {} + }, + "addExtraTags": { + "description": "If a value is added with the textfield, these extra tag is addded.\nUseful to add a 'fixme=freeform textfield used - to be checked'", + "type": "array", + "items": { + "type": "string" + } + }, + "inline": { + "description": "When set, influences the way a question is asked.\nInstead of showing a full-widht text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.", + "type": "boolean" + }, + "default": { + "description": "default value to enter if no previous tagging is present.\nNormally undefined (aka do not enter anything)", + "type": "string" + } + }, + "required": [ + "key" + ] + }, + "multiAnswer": { + "description": "If true, use checkboxes instead of radio buttons when asking the question", + "type": "boolean" + }, + "mappings": { + "description": "Allows fixed-tag inputs, shown either as radiobuttons or as checkboxes", + "type": "array", + "items": { + "type": "object", + "properties": { + "if": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "then": { + "description": "Shown if the 'if is fulfilled\nType: rendered" + }, + "icon": { + "description": "An extra icon supporting the choice\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "Size of the image", + "type": "string" + } + }, + "required": [ + "class", + "path" + ] + }, + { + "type": "string" + } + ] + }, + "hideInAnswer": { + "description": "In some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation).\n\nIn the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user.\nIn this case, one of the mappings can be hiden by setting this flag.\n\nTo demonstrate an example making a default assumption:\n\nmappings: [\n {\n if: \"access=\", -- no access tag present, we assume accessible\n then: \"Accessible to the general public\",\n hideInAnswer: true\n },\n {\n if: \"access=yes\",\n then: \"Accessible to the general public\", -- the user selected this, we add that to OSM\n },\n {\n if: \"access=no\",\n then: \"Not accessible to the public\"\n }\n]\n\n\nFor example, for an operator, we have `operator=Agentschap Natuur en Bos`, which is often abbreviated to `operator=ANB`.\nThen, we would add two mappings:\n{\n if: \"operator=Agentschap Natuur en Bos\" -- the non-abbreviated version which should be uploaded\n then: \"Maintained by Agentschap Natuur en Bos\"\n},\n{\n if: \"operator=ANB\", -- we don't want to upload abbreviations\n then: \"Maintained by Agentschap Natuur en Bos\"\n hideInAnswer: true\n}\n\nHide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate.\nKeep in mind that this is reverse logic: it will be hidden in the answer if the condition is true, it will thus only show in the case of a mismatch\n\ne.g., for toilets: if \"wheelchair=no\", we know there is no wheelchair dedicated room.\nFor the location of the changing table, the option \"in the wheelchair accessible toilet is weird\", so we write:\n\n{\n \"question\": \"Where is the changing table located?\"\n \"mappings\": [\n {\"if\":\"changing_table:location=female\",\"then\":\"In the female restroom\"},\n {\"if\":\"changing_table:location=male\",\"then\":\"In the male restroom\"},\n {\"if\":\"changing_table:location=wheelchair\",\"then\":\"In the wheelchair accessible restroom\", \"hideInAnswer\": \"wheelchair=no\"},\n \n ]\n}\n\nAlso have a look for the meta-tags\n{\n if: \"operator=Agentschap Natuur en Bos\",\n then: \"Maintained by Agentschap Natuur en Bos\",\n hideInAnswer: \"_country!=be\"\n}", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": [ + "string", + "boolean" + ] + } + ] + }, + "ifnot": { + "description": "Only applicable if 'multiAnswer' is set.\nThis is for situations such as:\n`accepts:coins=no` where one can select all the possible payment methods. However, we want to make explicit that some options _were not_ selected.\nThis can be done with `ifnot`\nNote that we can not explicitly render this negative case to the user, we cannot show `does _not_ accept coins`.\nIf this is important to your usecase, consider using multiple radiobutton-fields without `multiAnswer`", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "addExtraTags": { + "description": "If chosen as answer, these tags will be applied as well onto the object.\nNot compatible with multiAnswer", + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "if", + "then" + ] + } + }, + "id": { + "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", + "type": "string" + }, + "group": { + "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", + "type": "string" + }, + "labels": { + "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", + "type": "array", + "items": { + "type": "string" + } + }, + "render": { + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + }, + "condition": { + "description": "Only show this tagrendering (or question) if the object also matches the following tags.\n\nThis is useful to ask a follow-up question. E.g. if there is a diaper table, then ask a follow-up question on diaper tables...", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + } + }, + "default<(string|QuestionableTagRenderingConfigJson|{builtin:string;override:any;})[]>": { + "type": "object", + "properties": { + "rewrite": { + "type": "object", + "properties": { + "sourceString": { + "type": "array", + "items": { + "type": "string" + } + }, + "into": { + "type": "array", + "items": { + "type": "array", + "items": {} + } + } + }, + "required": [ + "into", + "sourceString" + ] + }, + "renderings": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/QuestionableTagRenderingConfigJson" + }, + { + "type": "object", + "properties": { + "builtin": { + "type": "string" + }, + "override": {} + }, + "required": [ + "builtin", + "override" + ] + }, + { + "type": "string" + } + ] + } + } }, - { - "type": "boolean" + "required": [ + "renderings", + "rewrite" + ] + }, + "default_1": { + "type": "object", + "properties": { + "id": { + "description": "An id/name for this filter, used to set the URL parameters", + "type": "string" + }, + "options": { + "description": "The options for a filter\nIf there are multiple options these will be a list of radio buttons\nIf there is only one option this will be a checkbox\nFiltering is done based on the given osmTags that are compared to the objects in that layer.", + "type": "array", + "items": { + "type": "object", + "properties": { + "question": {}, + "osmTags": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "default": { + "type": "boolean" + }, + "fields": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + }, + "required": [ + "question" + ] + } + } + }, + "required": [ + "id", + "options" + ] + }, + "DeleteConfigJson": { + "type": "object", + "properties": { + "extraDeleteReasons": { + "description": "*\nBy default, three reasons to delete a point are shown:\n\n- The point does not exist anymore\n- The point was a testing point\n- THe point could not be found\n\nHowever, for some layers, there might be different or more specific reasons for deletion which can be user friendly to set, e.g.:\n\n- the shop has closed\n- the climbing route has been closed of for nature conservation reasons\n- ...\n\nThese reasons can be stated here and will be shown in the list of options the user can choose from", + "type": "array", + "items": { + "type": "object", + "properties": { + "explanation": { + "description": "The text that will be shown to the user - translatable" + }, + "changesetMessage": { + "description": "The text that will be uploaded into the changeset or will be used in the fixme in case of a soft deletion\nShould be a few words, in english", + "type": "string" + } + }, + "required": [ + "changesetMessage", + "explanation" + ] + } + }, + "nonDeleteMappings": { + "description": "In some cases, a (starting) contributor might wish to delete a feature even though deletion is not appropriate.\n(The most relevant case are small paths running over private property. These should be marked as 'private' instead of deleted, as the community might trace the path again from aerial imagery, gettting us back to the original situation).\n\nBy adding a 'nonDeleteMapping', an option can be added into the list which will retag the feature.\nIt is important that the feature will be retagged in such a way that it won't be picked up by the layer anymore!", + "type": "array", + "items": { + "type": "object", + "properties": { + "if": { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + "then": {} + }, + "required": [ + "if", + "then" + ] + } + }, + "softDeletionTags": { + "description": "In some cases, the contributor is not allowed to delete the current feature (e.g. because it isn't a point, the point is referenced by a relation or the user isn't experienced enough).\nTo still offer the user a 'delete'-option, the feature is retagged with these tags. This is a soft deletion, as the point isn't actually removed from OSM but rather marked as 'disused'\nIt is important that the feature will be retagged in such a way that it won't be picked up by the layer anymore!\n\nExample (note that \"amenity=\" erases the 'amenity'-key alltogether):\n```\n{\n \"and\": [\"disussed:amenity=public_bookcase\", \"amenity=\"]\n}\n```\n\nor (notice the use of the ':='-tag to copy the old value of 'shop=*' into 'disused:shop='):\n```\n{\n \"and\": [\"disused:shop:={shop}\", \"shop=\"]\n}\n```", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "neededChangesets": { + "description": "*\nBy default, the contributor needs 20 previous changesets to delete points edited by others.\nFor some small features (e.g. bicycle racks) this is too much and this requirement can be lowered or dropped, which can be done here.", + "type": "number" + } } - ] }, - "allowSplit": { - "description": "IF set, a 'split this road' button is shown", - "type": "boolean" + "default_3": { + "type": "object", + "properties": { + "enableImproveAccuracy": { + "description": "One default reason to move a point is to improve accuracy.\nSet to false to disable this reason", + "type": "boolean" + }, + "enableRelocation": { + "description": "One default reason to move a point is because it has relocated\nSet to false to disable this reason", + "type": "boolean" + } + } }, - "units": { - "description": "In some cases, a value is represented in a certain unit (such as meters for heigt/distance/..., km/h for speed, ...)\n\nSometimes, multiple denominations are possible (e.g. km/h vs mile/h; megawatt vs kilowatt vs gigawatt for power generators, ...)\n\nThis brings in some troubles, as there are multiple ways to write it (no denomitation, 'm' vs 'meter' 'metre', ...)\n\nNot only do we want to write consistent data to OSM, we also want to present this consistently to the user.\nThis is handled by defining units.\n\n# Rendering\n\nTo render a value with long (human) denomination, use {canonical(key)}\n\n# Usage\n\nFirst of all, you define which keys have units applied, for example:\n\n```\nunits: [\n appliesTo: [\"maxspeed\", \"maxspeed:hgv\", \"maxspeed:bus\"]\n applicableUnits: [\n ...\n ]\n]\n```\n\nApplicableUnits defines which is the canonical extension, how it is presented to the user, ...:\n\n```\napplicableUnits: [\n{\n canonicalDenomination: \"km/h\",\n alternativeDenomination: [\"km/u\", \"kmh\", \"kph\"]\n default: true,\n human: {\n en: \"kilometer/hour\",\n nl: \"kilometer/uur\"\n },\n humanShort: {\n en: \"km/h\",\n nl: \"km/u\"\n }\n},\n{\n canoncialDenomination: \"mph\",\n ... similar for miles an hour ...\n}\n]\n```\n\n\nIf this is defined, then every key which the denominations apply to (`maxspeed`, `maxspeed:hgv` and `maxspeed:bus`) will be rewritten at the metatagging stage:\nevery value will be parsed and the canonical extension will be added add presented to the other parts of the code.\n\nAlso, if a freeform text field is used, an extra dropdown with applicable denominations will be given", - "type": "array", - "items": { - "$ref": "#/definitions/default_2" - } + "default_2": { + "type": "object", + "properties": { + "appliesToKey": { + "description": "Every key from this list will be normalized", + "type": "array", + "items": { + "type": "string" + } + }, + "eraseInvalidValues": { + "description": "If set, invalid values will be erased in the MC application (but not in OSM of course!)\nBe careful with setting this", + "type": "boolean" + }, + "applicableUnits": { + "description": "The possible denominations", + "type": "array", + "items": { + "$ref": "#/definitions/ApplicableUnitJson" + } + } + }, + "required": [ + "applicableUnits", + "appliesToKey" + ] }, - "syncSelection": { - "description": "If set, synchronizes wether or not this layer is selected.\n\nno: Do not sync at all, always revert to default\nlocal: keep selection on local storage\ntheme-only: sync via OSM, but this layer will only be toggled in this theme\nglobal: all layers with this ID will be synced accross all themes", - "enum": [ - "global", - "local", - "no", - "theme-only" - ], - "type": "string" + "default_6": { + "description": "Configuration for a tilesource config", + "type": "object", + "properties": { + "id": { + "description": "Id of this overlay, used in the URL-parameters to set the state", + "type": "string" + }, + "source": { + "description": "The path, where {x}, {y} and {z} will be substituted", + "type": "string" + }, + "isOverlay": { + "description": "Wether or not this is an overlay. Default: true", + "type": "boolean" + }, + "name": { + "description": "How this will be shown in the selection menu.\nMake undefined if this may not be toggled" + }, + "minZoom": { + "description": "Only visible at this or a higher zoom level", + "type": "number" + }, + "maxZoom": { + "description": "Only visible at this or a lower zoom level", + "type": "number" + }, + "defaultState": { + "description": "The default state, set to false to hide by default", + "type": "boolean" + } + }, + "required": [ + "defaultState", + "id", + "source" + ] + }, + "LayerConfigJson": { + "description": "Configuration for a single layer", + "type": "object", + "properties": { + "id": { + "description": "The id of this layer.\nThis should be a simple, lowercase, human readable string that is used to identify the layer.", + "type": "string" + }, + "name": { + "description": "The name of this layer\nUsed in the layer control panel and the 'Personal theme'.\n\nIf not given, will be hidden (and thus not toggable) in the layer control" + }, + "description": { + "description": "A description for this layer.\nShown in the layer selections and in the personel theme" + }, + "source": { + "description": "This determines where the data for the layer is fetched: from OSM or from an external geojson dataset.\n\nIf no 'geojson' is defined, data will be fetched from overpass and the OSM-API.\n\nEvery source _must_ define which tags _must_ be present in order to be picked up.", + "anyOf": [ + { + "allOf": [ + { + "type": "object", + "properties": { + "osmTags": { + "description": "Every source must set which tags have to be present in order to load the given layer.", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "maxCacheAge": { + "description": "The maximum amount of seconds that a tile is allowed to linger in the cache", + "type": "number" + } + }, + "required": [ + "osmTags" + ] + }, + { + "type": "object", + "properties": { + "overpassScript": { + "type": "string" + } + } + } + ] + }, + { + "allOf": [ + { + "type": "object", + "properties": { + "osmTags": { + "description": "Every source must set which tags have to be present in order to load the given layer.", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "maxCacheAge": { + "description": "The maximum amount of seconds that a tile is allowed to linger in the cache", + "type": "number" + } + }, + "required": [ + "osmTags" + ] + }, + { + "type": "object", + "properties": { + "geoJson": { + "description": "The actual source of the data to load, if loaded via geojson.\n\n# A single geojson-file\nsource: {geoJson: \"https://my.source.net/some-geo-data.geojson\"}\n fetches a geojson from a third party source\n\n# A tiled geojson source\nsource: {geoJson: \"https://my.source.net/some-tile-geojson-{layer}-{z}-{x}-{y}.geojson\", geoJsonZoomLevel: 14}\n to use a tiled geojson source. The web server must offer multiple geojsons. {z}, {x} and {y} are substituted by the location; {layer} is substituted with the id of the loaded layer\n\nSome API's use a BBOX instead of a tile, this can be used by specifying {y_min}, {y_max}, {x_min} and {x_max}", + "type": "string" + }, + "geoJsonZoomLevel": { + "description": "To load a tiled geojson layer, set the zoomlevel of the tiles", + "type": "number" + }, + "isOsmCache": { + "description": "Indicates that the upstream geojson data is OSM-derived.\nUseful for e.g. merging or for scripts generating this cache", + "type": "boolean" + }, + "mercatorCrs": { + "description": "Some API's use a mercator-projection (EPSG:900913) instead of WGS84. Set the flag `mercatorCrs: true` in the source for this", + "type": "boolean" + }, + "idKey": { + "description": "Some API's have an id-field, but give it a different name.\nSetting this key will rename this field into 'id'", + "type": "string" + } + }, + "required": [ + "geoJson" + ] + } + ] + } + ] + }, + "calculatedTags": { + "description": "A list of extra tags to calculate, specified as \"keyToAssignTo=javascript-expression\".\nThere are a few extra functions available. Refer to Docs/CalculatedTags.md for more information\nThe functions will be run in order, e.g.\n[\n \"_max_overlap_m2=Math.max(...feat.overlapsWith(\"someOtherLayer\").map(o => o.overlap))\n \"_max_overlap_ratio=Number(feat._max_overlap_m2)/feat.area\n]\n\nThe specified tags are evaluated lazily. E.g. if a calculated tag is only used in the popup (e.g. the number of nearby features),\nthe expensive calculation will only be performed then for that feature. This avoids clogging up the contributors PC when all features are loaded.\n\nIf a tag has to be evaluated strictly, use ':=' instead:\n\n[\n\"_some_key:=some_javascript_expression\"\n]", + "type": "array", + "items": { + "type": "string" + } + }, + "doNotDownload": { + "description": "If set, this layer will not query overpass; but it'll still match the tags above which are by chance returned by other layers.\nWorks well together with 'passAllFeatures', to add decoration", + "type": "boolean" + }, + "isShown": { + "description": "This tag rendering should either be 'yes' or 'no'. If 'no' is returned, then the feature will be hidden from view.\nThis is useful to hide certain features from view.\n\nImportant: hiding features does not work dynamically, but is only calculated when the data is first renders.\nThis implies that it is not possible to hide a feature after a tagging change\n\nThe default value is 'yes'", + "$ref": "#/definitions/TagRenderingConfigJson" + }, + "forceLoad": { + "description": "Advanced option - might be set by the theme compiler\n\nIf true, this data will _always_ be loaded, even if the theme is disabled", + "type": "boolean" + }, + "minzoom": { + "description": "The minimum needed zoomlevel required before loading of the data start\nDefault: 0", + "type": "number" + }, + "shownByDefault": { + "description": "Indicates if this layer is shown by default;\ncan be used to hide a layer from start, or to load the layer but only to show it where appropriate (e.g. for snapping to it)", + "type": "boolean" + }, + "minzoomVisible": { + "description": "The zoom level at which point the data is hidden again\nDefault: 100 (thus: always visible", + "type": "number" + }, + "title": { + "description": "The title shown in a popup for elements of this layer.", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "titleIcons": { + "description": "Small icons shown next to the title.\nIf not specified, the OsmLink and wikipedia links will be used by default.\nUse an empty array to hide them.\nNote that \"defaults\" will insert all the default titleIcons (which are added automatically)\n\nType: icon[]", + "anyOf": [ + { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + } + }, + { + "type": "array", + "items": [ + { + "type": "string", + "enum": [ + "defaults" + ] + } + ], + "minItems": 1, + "maxItems": 1 + } + ] + }, + "mapRendering": { + "description": "Visualisation of the items on the map", + "anyOf": [ + { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/default_4" + }, + { + "$ref": "#/definitions/default_5" + } + ] + } + }, + { + "type": "null" + } + ] + }, + "passAllFeatures": { + "description": "If set, this layer will pass all the features it receives onto the next layer.\nThis is ideal for decoration, e.g. directionss on cameras", + "type": "boolean" + }, + "presets": { + "description": "Presets for this layer.\nA preset shows up when clicking the map on a without data (or when right-clicking/long-pressing);\nit will prompt the user to add a new point.\n\nThe most important aspect are the tags, which define which tags the new point will have;\nThe title is shown in the dialog, along with the first sentence of the description.\n\nUpon confirmation, the full description is shown beneath the buttons - perfect to add pictures and examples.\n\nNote: the icon of the preset is determined automatically based on the tags and the icon above. Don't worry about that!\nNB: if no presets are defined, the popup to add new points doesn't show up at all", + "type": "array", + "items": { + "type": "object", + "properties": { + "title": { + "description": "The title - shown on the 'add-new'-button." + }, + "tags": { + "description": "The tags to add. It determines the icon too", + "type": "array", + "items": { + "type": "string" + } + }, + "description": { + "description": "The _first sentence_ of the description is shown on the button of the `add` menu.\nThe full description is shown in the confirmation dialog.\n\n(The first sentence is until the first '.'-character in the description)" + }, + "exampleImages": { + "description": "Example images, which show real-life pictures of what such a feature might look like\n\nType: image", + "type": "array", + "items": { + "type": "string" + } + }, + "preciseInput": { + "description": "If set, the user will prompted to confirm the location before actually adding the data.\nThis will be with a 'drag crosshair'-method.\n\nIf 'preferredBackgroundCategory' is set, the element will attempt to pick a background layer of that category.", + "anyOf": [ + { + "type": "object", + "properties": { + "preferredBackground": { + "description": "The type of background picture", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "snapToLayer": { + "description": "If specified, these layers will be shown to and the new point will be snapped towards it", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "maxSnapDistance": { + "description": "If specified, a new point will only be snapped if it is within this range.\nDistance in meter\n\nDefault: 10", + "type": "number" + } + }, + "required": [ + "preferredBackground" + ] + }, + { + "enum": [ + true + ], + "type": "boolean" + } + ] + } + }, + "required": [ + "tags", + "title" + ] + } + }, + "tagRenderings": { + "description": "All the tag renderings.\nA tag rendering is a block that either shows the known value or asks a question.\n\nRefer to the class `TagRenderingConfigJson` to see the possibilities.\n\nNote that we can also use a string here - where the string refers to a tag rendering defined in `assets/questions/questions.json`,\nwhere a few very general questions are defined e.g. website, phone number, ...\n\nA special value is 'questions', which indicates the location of the questions box. If not specified, it'll be appended to the bottom of the featureInfobox.\n\nAt last, one can define a group of renderings where parts of all strings will be replaced by multiple other strings.\nThis is mainly create questions for a 'left' and a 'right' side of the road.\nThese will be grouped and questions will be asked together", + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/QuestionableTagRenderingConfigJson" + }, + { + "type": "object", + "properties": { + "builtin": { + "type": "string" + }, + "override": {} + }, + "required": [ + "builtin", + "override" + ] + }, + { + "$ref": "#/definitions/default<(string|QuestionableTagRenderingConfigJson|{builtin:string;override:any;})[]>" + }, + { + "type": "string" + } + ] + } + }, + "filter": { + "description": "All the extra questions for filtering", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/definitions/default_1" + } + }, + { + "type": "object", + "properties": { + "sameAs": { + "type": "string" + } + }, + "required": [ + "sameAs" + ] + } + ] + }, + "deletion": { + "description": "This block defines under what circumstances the delete dialog is shown for objects of this layer.\nIf set, a dialog is shown to the user to (soft) delete the point.\nThe dialog is built to be user friendly and to prevent mistakes.\nIf deletion is not possible, the dialog will hide itself and show the reason of non-deletability instead.\n\nTo configure, the following values are possible:\n\n- false: never ever show the delete button\n- true: show the default delete button\n- undefined: use the mapcomplete default to show deletion or not. Currently, this is the same as 'false' but this will change in the future\n- or: a hash with options (see below)\n\n The delete dialog\n =================\n\n\n\n#### Hard deletion if enough experience\n\nA feature can only be deleted from OpenStreetMap by mapcomplete if:\n\n- It is a node\n- No ways or relations use the node\n- The logged-in user has enough experience OR the user is the only one to have edited the point previously\n- The logged-in user has no unread messages (or has a ton of experience)\n- The user did not select one of the 'non-delete-options' (see below)\n\nIn all other cases, a 'soft deletion' is used.\n\n#### Soft deletion\n\nA 'soft deletion' is when the point isn't deleted from OSM but retagged so that it'll won't how up in the mapcomplete theme anymore.\nThis makes it look like it was deleted, without doing damage. A fixme will be added to the point.\n\nNote that a soft deletion is _only_ possible if these tags are provided by the theme creator, as they'll be different for every theme\n\n#### No-delete options\n\nIn some cases, the contributor might want to delete something for the wrong reason (e.g. someone who wants to have a path removed \"because the path is on their private property\").\nHowever, the path exists in reality and should thus be on OSM - otherwise the next contributor will pass by and notice \"hey, there is a path missing here! Let me redraw it in OSM!)\n\nThe correct approach is to retag the feature in such a way that it is semantically correct *and* that it doesn't show up on the theme anymore.\nA no-delete option is offered as 'reason to delete it', but secretly retags.", + "anyOf": [ + { + "$ref": "#/definitions/DeleteConfigJson" + }, + { + "type": "boolean" + } + ] + }, + "allowMove": { + "description": "Indicates if a point can be moved and configures the modalities.\n\nA feature can be moved by MapComplete if:\n\n- It is a point\n- The point is _not_ part of a way or a a relation.\n\nOff by default. Can be enabled by setting this flag or by configuring.", + "anyOf": [ + { + "$ref": "#/definitions/default_3" + }, + { + "type": "boolean" + } + ] + }, + "allowSplit": { + "description": "IF set, a 'split this road' button is shown", + "type": "boolean" + }, + "units": { + "description": "In some cases, a value is represented in a certain unit (such as meters for heigt/distance/..., km/h for speed, ...)\n\nSometimes, multiple denominations are possible (e.g. km/h vs mile/h; megawatt vs kilowatt vs gigawatt for power generators, ...)\n\nThis brings in some troubles, as there are multiple ways to write it (no denomitation, 'm' vs 'meter' 'metre', ...)\n\nNot only do we want to write consistent data to OSM, we also want to present this consistently to the user.\nThis is handled by defining units.\n\n# Rendering\n\nTo render a value with long (human) denomination, use {canonical(key)}\n\n# Usage\n\nFirst of all, you define which keys have units applied, for example:\n\n```\nunits: [\n appliesTo: [\"maxspeed\", \"maxspeed:hgv\", \"maxspeed:bus\"]\n applicableUnits: [\n ...\n ]\n]\n```\n\nApplicableUnits defines which is the canonical extension, how it is presented to the user, ...:\n\n```\napplicableUnits: [\n{\n canonicalDenomination: \"km/h\",\n alternativeDenomination: [\"km/u\", \"kmh\", \"kph\"]\n default: true,\n human: {\n en: \"kilometer/hour\",\n nl: \"kilometer/uur\"\n },\n humanShort: {\n en: \"km/h\",\n nl: \"km/u\"\n }\n},\n{\n canoncialDenomination: \"mph\",\n ... similar for miles an hour ...\n}\n]\n```\n\n\nIf this is defined, then every key which the denominations apply to (`maxspeed`, `maxspeed:hgv` and `maxspeed:bus`) will be rewritten at the metatagging stage:\nevery value will be parsed and the canonical extension will be added add presented to the other parts of the code.\n\nAlso, if a freeform text field is used, an extra dropdown with applicable denominations will be given", + "type": "array", + "items": { + "$ref": "#/definitions/default_2" + } + }, + "syncSelection": { + "description": "If set, synchronizes wether or not this layer is selected.\n\nno: Do not sync at all, always revert to default\nlocal: keep selection on local storage\ntheme-only: sync via OSM, but this layer will only be toggled in this theme\nglobal: all layers with this ID will be synced accross all themes", + "enum": [ + "global", + "local", + "no", + "theme-only" + ], + "type": "string" + } + }, + "required": [ + "id", + "mapRendering", + "source" + ] + }, + "default": { + "type": "object", + "properties": { + "icon": { + "type": "string" + }, + "text": {}, + "href": { + "type": "string" + }, + "newTab": { + "type": "boolean" + }, + "requirements": { + "type": "array", + "items": { + "enum": [ + "iframe", + "no-iframe", + "no-welcome-message", + "welcome-message" + ], + "type": "string" + } + } + }, + "required": [ + "href" + ] } - }, - "required": [ - "id", - "mapRendering", - "source" - ] }, - "default": { - "type": "object", - "properties": { - "icon": { - "type": "string" - }, - "text": {}, - "href": { - "type": "string" - }, - "newTab": { - "type": "boolean" - }, - "requirements": { - "type": "array", - "items": { - "enum": [ - "iframe", - "no-iframe", - "no-welcome-message", - "welcome-message" - ], - "type": "string" - } - } - }, - "required": [ - "href" - ] - } - }, - "$schema": "http://json-schema.org/draft-07/schema#" + "$schema": "http://json-schema.org/draft-07/schema#" } \ No newline at end of file diff --git a/Docs/Schemas/LineRenderingConfigJsonJSC.ts b/Docs/Schemas/LineRenderingConfigJsonJSC.ts index 07e394d907..1c35298ec3 100644 --- a/Docs/Schemas/LineRenderingConfigJsonJSC.ts +++ b/Docs/Schemas/LineRenderingConfigJsonJSC.ts @@ -1,261 +1,261 @@ export default { - "description": "The LineRenderingConfig gives all details onto how to render a single line of a feature.\n\nThis can be used if:\n\n- The feature is a line\n- The feature is an area", - "type": "object", - "properties": { - "color": { - "description": "The color for way-elements and SVG-elements.\nIf the value starts with \"--\", the style of the body element will be queried for the corresponding variable instead", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - }, - "width": { - "description": "The stroke-width for way-elements", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": [ - "string", - "number" - ] - } - ] - }, - "dashArray": { - "description": "A dasharray, e.g. \"5 6\"\nThe dasharray defines 'pixels of line, pixels of gap, pixels of line, pixels of gap',\nDefault value: \"\" (empty string == full line)", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - }, - "lineCap": { - "description": "The form at the end of a line", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - }, - "fill": { - "description": "Wehter or not to fill polygons", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "enum": [ - "no", - "yes" - ], - "type": "string" - } - ] - }, - "fillColor": { - "description": "The color to fill a polygon with.\nIf undefined, this will be slightly more opaque version of the stroke line", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - }, - "offset": { - "description": "The number of pixels this line should be moved.\nUse a positive numbe to move to the right, a negative to move to the left (left/right as defined by the drawing direction of the line).\n\nIMPORTANT: MapComplete will already normalize 'key:both:property' and 'key:both' into the corresponding 'key:left' and 'key:right' tagging (same for 'sidewalk=left/right/both' which is rewritten to 'sidewalk:left' and 'sidewalk:right')\nThis simplifies programming. Refer to the CalculatedTags.md-documentation for more details", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "number" - } - ] - } - }, - "definitions": { - "AndOrTagConfigJson": { - "type": "object", - "properties": { - "and": { - "type": "array", - "items": { + "description": "The LineRenderingConfig gives all details onto how to render a single line of a feature.\n\nThis can be used if:\n\n- The feature is a line\n- The feature is an area", + "type": "object", + "properties": { + "color": { + "description": "The color for way-elements and SVG-elements.\nIf the value starts with \"--\", the style of the body element will be queried for the corresponding variable instead", "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } ] - } }, - "or": { - "type": "array", - "items": { + "width": { + "description": "The stroke-width for way-elements", "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": [ + "string", + "number" + ] + } + ] + }, + "dashArray": { + "description": "A dasharray, e.g. \"5 6\"\nThe dasharray defines 'pixels of line, pixels of gap, pixels of line, pixels of gap',\nDefault value: \"\" (empty string == full line)", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "lineCap": { + "description": "The form at the end of a line", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "fill": { + "description": "Wehter or not to fill polygons", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "enum": [ + "no", + "yes" + ], + "type": "string" + } + ] + }, + "fillColor": { + "description": "The color to fill a polygon with.\nIf undefined, this will be slightly more opaque version of the stroke line", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "offset": { + "description": "The number of pixels this line should be moved.\nUse a positive numbe to move to the right, a negative to move to the left (left/right as defined by the drawing direction of the line).\n\nIMPORTANT: MapComplete will already normalize 'key:both:property' and 'key:both' into the corresponding 'key:left' and 'key:right' tagging (same for 'sidewalk=left/right/both' which is rewritten to 'sidewalk:left' and 'sidewalk:right')\nThis simplifies programming. Refer to the CalculatedTags.md-documentation for more details", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "number" + } ] - } } - } }, - "ApplicableUnitJson": { - "type": "object", - "properties": { - "canonicalDenomination": { - "description": "The canonical value which will be added to the text.\ne.g. \"m\" for meters\nIf the user inputs '42', the canonical value will be added and it'll become '42m'", - "type": "string" - }, - "canonicalDenominationSingular": { - "description": "The canonical denomination in the case that the unit is precisely '1'", - "type": "string" - }, - "alternativeDenomination": { - "description": "A list of alternative values which can occur in the OSM database - used for parsing.", - "type": "array", - "items": { - "type": "string" - } - }, - "human": { - "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"meter\",\n \"fr\": \"metre\"\n}" - }, - "humanSingular": { - "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"minute\",\n \"nl\": \"minuut\"x²\n}" - }, - "prefix": { - "description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field", - "type": "boolean" - }, - "default": { - "description": "The default interpretation - only one can be set.\nIf none is set, the first unit will be considered the default interpretation of a value without a unit", - "type": "boolean" - } - }, - "required": [ - "canonicalDenomination" - ] - }, - "TagRenderingConfigJson": { - "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRenerdering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", - "type": "object", - "properties": { - "id": { - "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", - "type": "string" - }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, - "labels": { - "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", - "type": "array", - "items": { - "type": "string" - } - }, - "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" - }, - "condition": { - "description": "Only show this tagrendering (or question) if the object also matches the following tags.\n\nThis is useful to ask a follow-up question. E.g. if there is a diaper table, then ask a follow-up question on diaper tables...", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - }, - "freeform": { - "description": "Allow freeform text input from the user", - "type": "object", - "properties": { - "key": { - "description": "If this key is present, then 'render' is used to display the value.\nIf this is undefined, the rendering is _always_ shown", - "type": "string" - } - }, - "required": [ - "key" - ] - }, - "mappings": { - "description": "Allows fixed-tag inputs, shown either as radiobuttons or as checkboxes", - "type": "array", - "items": { + "definitions": { + "AndOrTagConfigJson": { "type": "object", "properties": { - "if": { - "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { + "and": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + }, + "or": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + } + } + }, + "ApplicableUnitJson": { + "type": "object", + "properties": { + "canonicalDenomination": { + "description": "The canonical value which will be added to the text.\ne.g. \"m\" for meters\nIf the user inputs '42', the canonical value will be added and it'll become '42m'", "type": "string" - } - ] - }, - "then": { - "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" - }, - "icon": { - "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", - "anyOf": [ - { - "type": "object", - "properties": { - "path": { - "description": "The path to the icon\nType: icon", - "type": "string" - }, - "class": { - "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", - "type": "string" - } - }, - "required": [ - "class", - "path" - ] - }, - { + }, + "canonicalDenominationSingular": { + "description": "The canonical denomination in the case that the unit is precisely '1'", "type": "string" - } - ] - } + }, + "alternativeDenomination": { + "description": "A list of alternative values which can occur in the OSM database - used for parsing.", + "type": "array", + "items": { + "type": "string" + } + }, + "human": { + "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"meter\",\n \"fr\": \"metre\"\n}" + }, + "humanSingular": { + "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"minute\",\n \"nl\": \"minuut\"x²\n}" + }, + "prefix": { + "description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field", + "type": "boolean" + }, + "default": { + "description": "The default interpretation - only one can be set.\nIf none is set, the first unit will be considered the default interpretation of a value without a unit", + "type": "boolean" + } }, "required": [ - "if", - "then" + "canonicalDenomination" ] - } + }, + "TagRenderingConfigJson": { + "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRenerdering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", + "type": "object", + "properties": { + "id": { + "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", + "type": "string" + }, + "group": { + "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", + "type": "string" + }, + "labels": { + "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", + "type": "array", + "items": { + "type": "string" + } + }, + "render": { + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + }, + "condition": { + "description": "Only show this tagrendering (or question) if the object also matches the following tags.\n\nThis is useful to ask a follow-up question. E.g. if there is a diaper table, then ask a follow-up question on diaper tables...", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "freeform": { + "description": "Allow freeform text input from the user", + "type": "object", + "properties": { + "key": { + "description": "If this key is present, then 'render' is used to display the value.\nIf this is undefined, the rendering is _always_ shown", + "type": "string" + } + }, + "required": [ + "key" + ] + }, + "mappings": { + "description": "Allows fixed-tag inputs, shown either as radiobuttons or as checkboxes", + "type": "array", + "items": { + "type": "object", + "properties": { + "if": { + "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "then": { + "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" + }, + "icon": { + "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "class", + "path" + ] + }, + { + "type": "string" + } + ] + } + }, + "required": [ + "if", + "then" + ] + } + } + } } - } - } - }, - "$schema": "http://json-schema.org/draft-07/schema#" + }, + "$schema": "http://json-schema.org/draft-07/schema#" } \ No newline at end of file diff --git a/Docs/Schemas/MoveConfigJsonJSC.ts b/Docs/Schemas/MoveConfigJsonJSC.ts index 23f191109b..0d7dede65a 100644 --- a/Docs/Schemas/MoveConfigJsonJSC.ts +++ b/Docs/Schemas/MoveConfigJsonJSC.ts @@ -1,84 +1,84 @@ export default { - "type": "object", - "properties": { - "enableImproveAccuracy": { - "description": "One default reason to move a point is to improve accuracy.\nSet to false to disable this reason", - "type": "boolean" - }, - "enableRelocation": { - "description": "One default reason to move a point is because it has relocated\nSet to false to disable this reason", - "type": "boolean" - } - }, - "definitions": { - "AndOrTagConfigJson": { - "type": "object", - "properties": { - "and": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - } + "type": "object", + "properties": { + "enableImproveAccuracy": { + "description": "One default reason to move a point is to improve accuracy.\nSet to false to disable this reason", + "type": "boolean" }, - "or": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - } + "enableRelocation": { + "description": "One default reason to move a point is because it has relocated\nSet to false to disable this reason", + "type": "boolean" } - } }, - "ApplicableUnitJson": { - "type": "object", - "properties": { - "canonicalDenomination": { - "description": "The canonical value which will be added to the text.\ne.g. \"m\" for meters\nIf the user inputs '42', the canonical value will be added and it'll become '42m'", - "type": "string" + "definitions": { + "AndOrTagConfigJson": { + "type": "object", + "properties": { + "and": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + }, + "or": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + } + } }, - "canonicalDenominationSingular": { - "description": "The canonical denomination in the case that the unit is precisely '1'", - "type": "string" - }, - "alternativeDenomination": { - "description": "A list of alternative values which can occur in the OSM database - used for parsing.", - "type": "array", - "items": { - "type": "string" - } - }, - "human": { - "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"meter\",\n \"fr\": \"metre\"\n}" - }, - "humanSingular": { - "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"minute\",\n \"nl\": \"minuut\"x²\n}" - }, - "prefix": { - "description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field", - "type": "boolean" - }, - "default": { - "description": "The default interpretation - only one can be set.\nIf none is set, the first unit will be considered the default interpretation of a value without a unit", - "type": "boolean" + "ApplicableUnitJson": { + "type": "object", + "properties": { + "canonicalDenomination": { + "description": "The canonical value which will be added to the text.\ne.g. \"m\" for meters\nIf the user inputs '42', the canonical value will be added and it'll become '42m'", + "type": "string" + }, + "canonicalDenominationSingular": { + "description": "The canonical denomination in the case that the unit is precisely '1'", + "type": "string" + }, + "alternativeDenomination": { + "description": "A list of alternative values which can occur in the OSM database - used for parsing.", + "type": "array", + "items": { + "type": "string" + } + }, + "human": { + "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"meter\",\n \"fr\": \"metre\"\n}" + }, + "humanSingular": { + "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"minute\",\n \"nl\": \"minuut\"x²\n}" + }, + "prefix": { + "description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field", + "type": "boolean" + }, + "default": { + "description": "The default interpretation - only one can be set.\nIf none is set, the first unit will be considered the default interpretation of a value without a unit", + "type": "boolean" + } + }, + "required": [ + "canonicalDenomination" + ] } - }, - "required": [ - "canonicalDenomination" - ] - } - }, - "$schema": "http://json-schema.org/draft-07/schema#" + }, + "$schema": "http://json-schema.org/draft-07/schema#" } \ No newline at end of file diff --git a/Docs/Schemas/PointRenderingConfigJsonJSC.ts b/Docs/Schemas/PointRenderingConfigJsonJSC.ts index 55d09eb381..371378c9ed 100644 --- a/Docs/Schemas/PointRenderingConfigJsonJSC.ts +++ b/Docs/Schemas/PointRenderingConfigJsonJSC.ts @@ -1,265 +1,265 @@ export default { - "description": "The PointRenderingConfig gives all details onto how to render a single point of a feature.\n\nThis can be used if:\n\n- The feature is a point\n- To render something at the centroid of an area, or at the start, end or projected centroid of a way", - "type": "object", - "properties": { - "location": { - "description": "All the locations that this point should be rendered at.\nUsing `location: [\"point\", \"centroid\"] will always render centerpoint", - "type": "array", - "items": { - "type": "string" - } - }, - "icon": { - "description": "The icon for an element.\nNote that this also doubles as the icon for this layer (rendered with the overpass-tags) ánd the icon in the presets.\n\nThe result of the icon is rendered as follows:\nthe resulting string is interpreted as a _list_ of items, separated by \";\". The bottommost layer is the first layer.\nAs a result, on could use a generic pin, then overlay it with a specific icon.\nTo make things even more practical, one can use all SVG's from the folder \"assets/svg\" and _substitute the color_ in it.\nE.g. to draw a red pin, use \"pin:#f00\", to have a green circle with your icon on top, use `circle:#0f0;`\n\nType: icon", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - }, - "iconBadges": { - "description": "A list of extra badges to show next to the icon as small badge\nThey will be added as a 25% height icon at the bottom right of the icon, with all the badges in a flex layout.\n\nNote: strings are interpreted as icons, so layering and substituting is supported. You can use `circle:white;./my_icon.svg` to add a background circle", - "type": "array", - "items": { - "type": "object", - "properties": { - "if": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { + "description": "The PointRenderingConfig gives all details onto how to render a single point of a feature.\n\nThis can be used if:\n\n- The feature is a point\n- To render something at the centroid of an area, or at the start, end or projected centroid of a way", + "type": "object", + "properties": { + "location": { + "description": "All the locations that this point should be rendered at.\nUsing `location: [\"point\", \"centroid\"] will always render centerpoint", + "type": "array", + "items": { "type": "string" - } - ] - }, - "then": { - "description": "Badge to show\nType: icon", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - } - }, - "required": [ - "if", - "then" - ] - } - }, - "iconSize": { - "description": "A string containing \"width,height\" or \"width,height,anchorpoint\" where anchorpoint is any of 'center', 'top', 'bottom', 'left', 'right', 'bottomleft','topright', ...\nDefault is '40,40,center'", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - }, - "rotation": { - "description": "The rotation of an icon, useful for e.g. directions.\nUsage: as if it were a css property for 'rotate', thus has to end with 'deg', e.g. `90deg`, `{direction}deg`, `calc(90deg - {camera:direction}deg)``", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - }, - "label": { - "description": "A HTML-fragment that is shown below the icon, for example:\n
{name}
\n\nIf the icon is undefined, then the label is shown in the center of the feature.\nNote that, if the wayhandling hides the icon then no label is shown as well.", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - } - }, - "required": [ - "location" - ], - "definitions": { - "AndOrTagConfigJson": { - "type": "object", - "properties": { - "and": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - } - }, - "or": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - } - } - } - }, - "ApplicableUnitJson": { - "type": "object", - "properties": { - "canonicalDenomination": { - "description": "The canonical value which will be added to the text.\ne.g. \"m\" for meters\nIf the user inputs '42', the canonical value will be added and it'll become '42m'", - "type": "string" - }, - "canonicalDenominationSingular": { - "description": "The canonical denomination in the case that the unit is precisely '1'", - "type": "string" - }, - "alternativeDenomination": { - "description": "A list of alternative values which can occur in the OSM database - used for parsing.", - "type": "array", - "items": { - "type": "string" - } - }, - "human": { - "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"meter\",\n \"fr\": \"metre\"\n}" - }, - "humanSingular": { - "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"minute\",\n \"nl\": \"minuut\"x²\n}" - }, - "prefix": { - "description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field", - "type": "boolean" - }, - "default": { - "description": "The default interpretation - only one can be set.\nIf none is set, the first unit will be considered the default interpretation of a value without a unit", - "type": "boolean" - } - }, - "required": [ - "canonicalDenomination" - ] - }, - "TagRenderingConfigJson": { - "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRenerdering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", - "type": "object", - "properties": { - "id": { - "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", - "type": "string" - }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, - "labels": { - "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", - "type": "array", - "items": { - "type": "string" - } - }, - "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" - }, - "condition": { - "description": "Only show this tagrendering (or question) if the object also matches the following tags.\n\nThis is useful to ask a follow-up question. E.g. if there is a diaper table, then ask a follow-up question on diaper tables...", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" } - ] }, - "freeform": { - "description": "Allow freeform text input from the user", - "type": "object", - "properties": { - "key": { - "description": "If this key is present, then 'render' is used to display the value.\nIf this is undefined, the rendering is _always_ shown", - "type": "string" + "icon": { + "description": "The icon for an element.\nNote that this also doubles as the icon for this layer (rendered with the overpass-tags) ánd the icon in the presets.\n\nThe result of the icon is rendered as follows:\nthe resulting string is interpreted as a _list_ of items, separated by \";\". The bottommost layer is the first layer.\nAs a result, on could use a generic pin, then overlay it with a specific icon.\nTo make things even more practical, one can use all SVG's from the folder \"assets/svg\" and _substitute the color_ in it.\nE.g. to draw a red pin, use \"pin:#f00\", to have a green circle with your icon on top, use `circle:#0f0;`\n\nType: icon", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "iconBadges": { + "description": "A list of extra badges to show next to the icon as small badge\nThey will be added as a 25% height icon at the bottom right of the icon, with all the badges in a flex layout.\n\nNote: strings are interpreted as icons, so layering and substituting is supported. You can use `circle:white;./my_icon.svg` to add a background circle", + "type": "array", + "items": { + "type": "object", + "properties": { + "if": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "then": { + "description": "Badge to show\nType: icon", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + } + }, + "required": [ + "if", + "then" + ] } - }, - "required": [ - "key" - ] }, - "mappings": { - "description": "Allows fixed-tag inputs, shown either as radiobuttons or as checkboxes", - "type": "array", - "items": { + "iconSize": { + "description": "A string containing \"width,height\" or \"width,height,anchorpoint\" where anchorpoint is any of 'center', 'top', 'bottom', 'left', 'right', 'bottomleft','topright', ...\nDefault is '40,40,center'", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "rotation": { + "description": "The rotation of an icon, useful for e.g. directions.\nUsage: as if it were a css property for 'rotate', thus has to end with 'deg', e.g. `90deg`, `{direction}deg`, `calc(90deg - {camera:direction}deg)``", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "label": { + "description": "A HTML-fragment that is shown below the icon, for example:\n
{name}
\n\nIf the icon is undefined, then the label is shown in the center of the feature.\nNote that, if the wayhandling hides the icon then no label is shown as well.", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + } + }, + "required": [ + "location" + ], + "definitions": { + "AndOrTagConfigJson": { "type": "object", "properties": { - "if": { - "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { + "and": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + }, + "or": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + } + } + }, + "ApplicableUnitJson": { + "type": "object", + "properties": { + "canonicalDenomination": { + "description": "The canonical value which will be added to the text.\ne.g. \"m\" for meters\nIf the user inputs '42', the canonical value will be added and it'll become '42m'", "type": "string" - } - ] - }, - "then": { - "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" - }, - "icon": { - "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", - "anyOf": [ - { - "type": "object", - "properties": { - "path": { - "description": "The path to the icon\nType: icon", - "type": "string" - }, - "class": { - "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", - "type": "string" - } - }, - "required": [ - "class", - "path" - ] - }, - { + }, + "canonicalDenominationSingular": { + "description": "The canonical denomination in the case that the unit is precisely '1'", "type": "string" - } - ] - } + }, + "alternativeDenomination": { + "description": "A list of alternative values which can occur in the OSM database - used for parsing.", + "type": "array", + "items": { + "type": "string" + } + }, + "human": { + "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"meter\",\n \"fr\": \"metre\"\n}" + }, + "humanSingular": { + "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"minute\",\n \"nl\": \"minuut\"x²\n}" + }, + "prefix": { + "description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field", + "type": "boolean" + }, + "default": { + "description": "The default interpretation - only one can be set.\nIf none is set, the first unit will be considered the default interpretation of a value without a unit", + "type": "boolean" + } }, "required": [ - "if", - "then" + "canonicalDenomination" ] - } + }, + "TagRenderingConfigJson": { + "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRenerdering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", + "type": "object", + "properties": { + "id": { + "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", + "type": "string" + }, + "group": { + "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", + "type": "string" + }, + "labels": { + "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", + "type": "array", + "items": { + "type": "string" + } + }, + "render": { + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + }, + "condition": { + "description": "Only show this tagrendering (or question) if the object also matches the following tags.\n\nThis is useful to ask a follow-up question. E.g. if there is a diaper table, then ask a follow-up question on diaper tables...", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "freeform": { + "description": "Allow freeform text input from the user", + "type": "object", + "properties": { + "key": { + "description": "If this key is present, then 'render' is used to display the value.\nIf this is undefined, the rendering is _always_ shown", + "type": "string" + } + }, + "required": [ + "key" + ] + }, + "mappings": { + "description": "Allows fixed-tag inputs, shown either as radiobuttons or as checkboxes", + "type": "array", + "items": { + "type": "object", + "properties": { + "if": { + "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "then": { + "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" + }, + "icon": { + "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "class", + "path" + ] + }, + { + "type": "string" + } + ] + } + }, + "required": [ + "if", + "then" + ] + } + } + } } - } - } - }, - "$schema": "http://json-schema.org/draft-07/schema#" + }, + "$schema": "http://json-schema.org/draft-07/schema#" } \ No newline at end of file diff --git a/Docs/Schemas/QuestionableTagRenderingConfigJsonJSC.ts b/Docs/Schemas/QuestionableTagRenderingConfigJsonJSC.ts index ca2ffe2820..0fcdb00e0b 100644 --- a/Docs/Schemas/QuestionableTagRenderingConfigJsonJSC.ts +++ b/Docs/Schemas/QuestionableTagRenderingConfigJsonJSC.ts @@ -1,335 +1,335 @@ export default { - "description": "A QuestionableTagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nIf the desired tags are missing and a question is defined, a question will be shown instead.", - "type": "object", - "properties": { - "question": { - "description": "If it turns out that this tagRendering doesn't match _any_ value, then we show this question.\nIf undefined, the question is never asked and this tagrendering is read-only" - }, - "freeform": { - "description": "Allow freeform text input from the user", - "type": "object", - "properties": { - "key": { - "type": "string" - }, - "type": { - "description": "The type of the text-field, e.g. 'string', 'nat', 'float', 'date',...\nSee Docs/SpecialInputElements.md and UI/Input/ValidatedTextField.ts for supported values", - "type": "string" - }, - "placeholder": { - "description": "A (translated) text that is shown (as gray text) within the textfield" - }, - "helperArgs": { - "description": "Extra parameters to initialize the input helper arguments.\nFor semantics, see the 'SpecialInputElements.md'", - "type": "array", - "items": {} - }, - "addExtraTags": { - "description": "If a value is added with the textfield, these extra tag is addded.\nUseful to add a 'fixme=freeform textfield used - to be checked'", - "type": "array", - "items": { - "type": "string" - } - }, - "inline": { - "description": "When set, influences the way a question is asked.\nInstead of showing a full-widht text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.", - "type": "boolean" - }, - "default": { - "description": "default value to enter if no previous tagging is present.\nNormally undefined (aka do not enter anything)", - "type": "string" - } - }, - "required": [ - "key" - ] - }, - "multiAnswer": { - "description": "If true, use checkboxes instead of radio buttons when asking the question", - "type": "boolean" - }, - "mappings": { - "description": "Allows fixed-tag inputs, shown either as radiobuttons or as checkboxes", - "type": "array", - "items": { - "type": "object", - "properties": { - "if": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - }, - "then": { - "description": "Shown if the 'if is fulfilled\nType: rendered" - }, - "icon": { - "description": "An extra icon supporting the choice\nType: icon", - "anyOf": [ - { - "type": "object", - "properties": { - "path": { - "description": "The path to the icon\nType: icon", - "type": "string" - }, - "class": { - "description": "Size of the image", - "type": "string" - } - }, - "required": [ - "class", - "path" - ] - }, - { - "type": "string" - } - ] - }, - "hideInAnswer": { - "description": "In some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation).\n\nIn the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user.\nIn this case, one of the mappings can be hiden by setting this flag.\n\nTo demonstrate an example making a default assumption:\n\nmappings: [\n {\n if: \"access=\", -- no access tag present, we assume accessible\n then: \"Accessible to the general public\",\n hideInAnswer: true\n },\n {\n if: \"access=yes\",\n then: \"Accessible to the general public\", -- the user selected this, we add that to OSM\n },\n {\n if: \"access=no\",\n then: \"Not accessible to the public\"\n }\n]\n\n\nFor example, for an operator, we have `operator=Agentschap Natuur en Bos`, which is often abbreviated to `operator=ANB`.\nThen, we would add two mappings:\n{\n if: \"operator=Agentschap Natuur en Bos\" -- the non-abbreviated version which should be uploaded\n then: \"Maintained by Agentschap Natuur en Bos\"\n},\n{\n if: \"operator=ANB\", -- we don't want to upload abbreviations\n then: \"Maintained by Agentschap Natuur en Bos\"\n hideInAnswer: true\n}\n\nHide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate.\nKeep in mind that this is reverse logic: it will be hidden in the answer if the condition is true, it will thus only show in the case of a mismatch\n\ne.g., for toilets: if \"wheelchair=no\", we know there is no wheelchair dedicated room.\nFor the location of the changing table, the option \"in the wheelchair accessible toilet is weird\", so we write:\n\n{\n \"question\": \"Where is the changing table located?\"\n \"mappings\": [\n {\"if\":\"changing_table:location=female\",\"then\":\"In the female restroom\"},\n {\"if\":\"changing_table:location=male\",\"then\":\"In the male restroom\"},\n {\"if\":\"changing_table:location=wheelchair\",\"then\":\"In the wheelchair accessible restroom\", \"hideInAnswer\": \"wheelchair=no\"},\n \n ]\n}\n\nAlso have a look for the meta-tags\n{\n if: \"operator=Agentschap Natuur en Bos\",\n then: \"Maintained by Agentschap Natuur en Bos\",\n hideInAnswer: \"_country!=be\"\n}", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": [ - "string", - "boolean" - ] - } - ] - }, - "ifnot": { - "description": "Only applicable if 'multiAnswer' is set.\nThis is for situations such as:\n`accepts:coins=no` where one can select all the possible payment methods. However, we want to make explicit that some options _were not_ selected.\nThis can be done with `ifnot`\nNote that we can not explicitly render this negative case to the user, we cannot show `does _not_ accept coins`.\nIf this is important to your usecase, consider using multiple radiobutton-fields without `multiAnswer`", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - }, - "addExtraTags": { - "description": "If chosen as answer, these tags will be applied as well onto the object.\nNot compatible with multiAnswer", - "type": "array", - "items": { - "type": "string" - } - } - }, - "required": [ - "if", - "then" - ] - } - }, - "id": { - "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", - "type": "string" - }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, - "labels": { - "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", - "type": "array", - "items": { - "type": "string" - } - }, - "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" - }, - "condition": { - "description": "Only show this tagrendering (or question) if the object also matches the following tags.\n\nThis is useful to ask a follow-up question. E.g. if there is a diaper table, then ask a follow-up question on diaper tables...", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - } - }, - "definitions": { - "AndOrTagConfigJson": { - "type": "object", - "properties": { - "and": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - } - }, - "or": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - } - } - } - }, - "ApplicableUnitJson": { - "type": "object", - "properties": { - "canonicalDenomination": { - "description": "The canonical value which will be added to the text.\ne.g. \"m\" for meters\nIf the user inputs '42', the canonical value will be added and it'll become '42m'", - "type": "string" - }, - "canonicalDenominationSingular": { - "description": "The canonical denomination in the case that the unit is precisely '1'", - "type": "string" - }, - "alternativeDenomination": { - "description": "A list of alternative values which can occur in the OSM database - used for parsing.", - "type": "array", - "items": { - "type": "string" - } - }, - "human": { - "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"meter\",\n \"fr\": \"metre\"\n}" - }, - "humanSingular": { - "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"minute\",\n \"nl\": \"minuut\"x²\n}" - }, - "prefix": { - "description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field", - "type": "boolean" - }, - "default": { - "description": "The default interpretation - only one can be set.\nIf none is set, the first unit will be considered the default interpretation of a value without a unit", - "type": "boolean" - } - }, - "required": [ - "canonicalDenomination" - ] - }, - "TagRenderingConfigJson": { - "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRenerdering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", - "type": "object", - "properties": { - "id": { - "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", - "type": "string" - }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, - "labels": { - "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", - "type": "array", - "items": { - "type": "string" - } - }, - "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" - }, - "condition": { - "description": "Only show this tagrendering (or question) if the object also matches the following tags.\n\nThis is useful to ask a follow-up question. E.g. if there is a diaper table, then ask a follow-up question on diaper tables...", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] + "description": "A QuestionableTagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nIf the desired tags are missing and a question is defined, a question will be shown instead.", + "type": "object", + "properties": { + "question": { + "description": "If it turns out that this tagRendering doesn't match _any_ value, then we show this question.\nIf undefined, the question is never asked and this tagrendering is read-only" }, "freeform": { - "description": "Allow freeform text input from the user", - "type": "object", - "properties": { - "key": { - "description": "If this key is present, then 'render' is used to display the value.\nIf this is undefined, the rendering is _always_ shown", - "type": "string" - } - }, - "required": [ - "key" - ] - }, - "mappings": { - "description": "Allows fixed-tag inputs, shown either as radiobuttons or as checkboxes", - "type": "array", - "items": { + "description": "Allow freeform text input from the user", "type": "object", "properties": { - "if": { - "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { + "key": { "type": "string" - } - ] - }, - "then": { - "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" - }, - "icon": { - "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", - "anyOf": [ - { - "type": "object", - "properties": { - "path": { - "description": "The path to the icon\nType: icon", - "type": "string" - }, - "class": { - "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", - "type": "string" - } - }, - "required": [ - "class", - "path" - ] - }, - { + }, + "type": { + "description": "The type of the text-field, e.g. 'string', 'nat', 'float', 'date',...\nSee Docs/SpecialInputElements.md and UI/Input/ValidatedTextField.ts for supported values", "type": "string" - } - ] - } + }, + "placeholder": { + "description": "A (translated) text that is shown (as gray text) within the textfield" + }, + "helperArgs": { + "description": "Extra parameters to initialize the input helper arguments.\nFor semantics, see the 'SpecialInputElements.md'", + "type": "array", + "items": {} + }, + "addExtraTags": { + "description": "If a value is added with the textfield, these extra tag is addded.\nUseful to add a 'fixme=freeform textfield used - to be checked'", + "type": "array", + "items": { + "type": "string" + } + }, + "inline": { + "description": "When set, influences the way a question is asked.\nInstead of showing a full-widht text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.", + "type": "boolean" + }, + "default": { + "description": "default value to enter if no previous tagging is present.\nNormally undefined (aka do not enter anything)", + "type": "string" + } }, "required": [ - "if", - "then" + "key" + ] + }, + "multiAnswer": { + "description": "If true, use checkboxes instead of radio buttons when asking the question", + "type": "boolean" + }, + "mappings": { + "description": "Allows fixed-tag inputs, shown either as radiobuttons or as checkboxes", + "type": "array", + "items": { + "type": "object", + "properties": { + "if": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "then": { + "description": "Shown if the 'if is fulfilled\nType: rendered" + }, + "icon": { + "description": "An extra icon supporting the choice\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "Size of the image", + "type": "string" + } + }, + "required": [ + "class", + "path" + ] + }, + { + "type": "string" + } + ] + }, + "hideInAnswer": { + "description": "In some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation).\n\nIn the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user.\nIn this case, one of the mappings can be hiden by setting this flag.\n\nTo demonstrate an example making a default assumption:\n\nmappings: [\n {\n if: \"access=\", -- no access tag present, we assume accessible\n then: \"Accessible to the general public\",\n hideInAnswer: true\n },\n {\n if: \"access=yes\",\n then: \"Accessible to the general public\", -- the user selected this, we add that to OSM\n },\n {\n if: \"access=no\",\n then: \"Not accessible to the public\"\n }\n]\n\n\nFor example, for an operator, we have `operator=Agentschap Natuur en Bos`, which is often abbreviated to `operator=ANB`.\nThen, we would add two mappings:\n{\n if: \"operator=Agentschap Natuur en Bos\" -- the non-abbreviated version which should be uploaded\n then: \"Maintained by Agentschap Natuur en Bos\"\n},\n{\n if: \"operator=ANB\", -- we don't want to upload abbreviations\n then: \"Maintained by Agentschap Natuur en Bos\"\n hideInAnswer: true\n}\n\nHide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate.\nKeep in mind that this is reverse logic: it will be hidden in the answer if the condition is true, it will thus only show in the case of a mismatch\n\ne.g., for toilets: if \"wheelchair=no\", we know there is no wheelchair dedicated room.\nFor the location of the changing table, the option \"in the wheelchair accessible toilet is weird\", so we write:\n\n{\n \"question\": \"Where is the changing table located?\"\n \"mappings\": [\n {\"if\":\"changing_table:location=female\",\"then\":\"In the female restroom\"},\n {\"if\":\"changing_table:location=male\",\"then\":\"In the male restroom\"},\n {\"if\":\"changing_table:location=wheelchair\",\"then\":\"In the wheelchair accessible restroom\", \"hideInAnswer\": \"wheelchair=no\"},\n \n ]\n}\n\nAlso have a look for the meta-tags\n{\n if: \"operator=Agentschap Natuur en Bos\",\n then: \"Maintained by Agentschap Natuur en Bos\",\n hideInAnswer: \"_country!=be\"\n}", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": [ + "string", + "boolean" + ] + } + ] + }, + "ifnot": { + "description": "Only applicable if 'multiAnswer' is set.\nThis is for situations such as:\n`accepts:coins=no` where one can select all the possible payment methods. However, we want to make explicit that some options _were not_ selected.\nThis can be done with `ifnot`\nNote that we can not explicitly render this negative case to the user, we cannot show `does _not_ accept coins`.\nIf this is important to your usecase, consider using multiple radiobutton-fields without `multiAnswer`", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "addExtraTags": { + "description": "If chosen as answer, these tags will be applied as well onto the object.\nNot compatible with multiAnswer", + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "if", + "then" + ] + } + }, + "id": { + "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", + "type": "string" + }, + "group": { + "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", + "type": "string" + }, + "labels": { + "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", + "type": "array", + "items": { + "type": "string" + } + }, + "render": { + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + }, + "condition": { + "description": "Only show this tagrendering (or question) if the object also matches the following tags.\n\nThis is useful to ask a follow-up question. E.g. if there is a diaper table, then ask a follow-up question on diaper tables...", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } ] - } } - } - } - }, - "$schema": "http://json-schema.org/draft-07/schema#" + }, + "definitions": { + "AndOrTagConfigJson": { + "type": "object", + "properties": { + "and": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + }, + "or": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + } + } + }, + "ApplicableUnitJson": { + "type": "object", + "properties": { + "canonicalDenomination": { + "description": "The canonical value which will be added to the text.\ne.g. \"m\" for meters\nIf the user inputs '42', the canonical value will be added and it'll become '42m'", + "type": "string" + }, + "canonicalDenominationSingular": { + "description": "The canonical denomination in the case that the unit is precisely '1'", + "type": "string" + }, + "alternativeDenomination": { + "description": "A list of alternative values which can occur in the OSM database - used for parsing.", + "type": "array", + "items": { + "type": "string" + } + }, + "human": { + "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"meter\",\n \"fr\": \"metre\"\n}" + }, + "humanSingular": { + "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"minute\",\n \"nl\": \"minuut\"x²\n}" + }, + "prefix": { + "description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field", + "type": "boolean" + }, + "default": { + "description": "The default interpretation - only one can be set.\nIf none is set, the first unit will be considered the default interpretation of a value without a unit", + "type": "boolean" + } + }, + "required": [ + "canonicalDenomination" + ] + }, + "TagRenderingConfigJson": { + "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRenerdering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", + "type": "object", + "properties": { + "id": { + "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", + "type": "string" + }, + "group": { + "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", + "type": "string" + }, + "labels": { + "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", + "type": "array", + "items": { + "type": "string" + } + }, + "render": { + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + }, + "condition": { + "description": "Only show this tagrendering (or question) if the object also matches the following tags.\n\nThis is useful to ask a follow-up question. E.g. if there is a diaper table, then ask a follow-up question on diaper tables...", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "freeform": { + "description": "Allow freeform text input from the user", + "type": "object", + "properties": { + "key": { + "description": "If this key is present, then 'render' is used to display the value.\nIf this is undefined, the rendering is _always_ shown", + "type": "string" + } + }, + "required": [ + "key" + ] + }, + "mappings": { + "description": "Allows fixed-tag inputs, shown either as radiobuttons or as checkboxes", + "type": "array", + "items": { + "type": "object", + "properties": { + "if": { + "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "then": { + "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" + }, + "icon": { + "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "class", + "path" + ] + }, + { + "type": "string" + } + ] + } + }, + "required": [ + "if", + "then" + ] + } + } + } + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" } \ No newline at end of file diff --git a/Docs/Schemas/RewritableConfigJsonJSC.ts b/Docs/Schemas/RewritableConfigJsonJSC.ts index 26134d0222..9ddb180381 100644 --- a/Docs/Schemas/RewritableConfigJsonJSC.ts +++ b/Docs/Schemas/RewritableConfigJsonJSC.ts @@ -1,208 +1,208 @@ export default { - "type": "object", - "properties": { - "rewrite": { - "type": "object", - "properties": { - "sourceString": { - "type": "array", - "items": { - "type": "string" - } - }, - "into": { - "type": "array", - "items": { - "type": "array", - "items": {} - } - } - }, - "required": [ - "into", - "sourceString" - ] - }, - "renderings": { - "$ref": "#/definitions/T" - } - }, - "required": [ - "renderings", - "rewrite" - ], - "definitions": { - "AndOrTagConfigJson": { - "type": "object", - "properties": { - "and": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - } - }, - "or": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - } - } - } - }, - "ApplicableUnitJson": { - "type": "object", - "properties": { - "canonicalDenomination": { - "description": "The canonical value which will be added to the text.\ne.g. \"m\" for meters\nIf the user inputs '42', the canonical value will be added and it'll become '42m'", - "type": "string" - }, - "canonicalDenominationSingular": { - "description": "The canonical denomination in the case that the unit is precisely '1'", - "type": "string" - }, - "alternativeDenomination": { - "description": "A list of alternative values which can occur in the OSM database - used for parsing.", - "type": "array", - "items": { - "type": "string" - } - }, - "human": { - "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"meter\",\n \"fr\": \"metre\"\n}" - }, - "humanSingular": { - "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"minute\",\n \"nl\": \"minuut\"x²\n}" - }, - "prefix": { - "description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field", - "type": "boolean" - }, - "default": { - "description": "The default interpretation - only one can be set.\nIf none is set, the first unit will be considered the default interpretation of a value without a unit", - "type": "boolean" - } - }, - "required": [ - "canonicalDenomination" - ] - }, - "TagRenderingConfigJson": { - "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRenerdering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", - "type": "object", - "properties": { - "id": { - "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", - "type": "string" - }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, - "labels": { - "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", - "type": "array", - "items": { - "type": "string" - } - }, - "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" - }, - "condition": { - "description": "Only show this tagrendering (or question) if the object also matches the following tags.\n\nThis is useful to ask a follow-up question. E.g. if there is a diaper table, then ask a follow-up question on diaper tables...", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - }, - "freeform": { - "description": "Allow freeform text input from the user", - "type": "object", - "properties": { - "key": { - "description": "If this key is present, then 'render' is used to display the value.\nIf this is undefined, the rendering is _always_ shown", - "type": "string" - } - }, - "required": [ - "key" - ] - }, - "mappings": { - "description": "Allows fixed-tag inputs, shown either as radiobuttons or as checkboxes", - "type": "array", - "items": { + "type": "object", + "properties": { + "rewrite": { "type": "object", "properties": { - "if": { - "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - }, - "then": { - "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" - }, - "icon": { - "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", - "anyOf": [ - { - "type": "object", - "properties": { - "path": { - "description": "The path to the icon\nType: icon", + "sourceString": { + "type": "array", + "items": { "type": "string" - }, - "class": { - "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", - "type": "string" - } - }, - "required": [ - "class", - "path" - ] - }, - { - "type": "string" - } - ] - } + } + }, + "into": { + "type": "array", + "items": { + "type": "array", + "items": {} + } + } }, "required": [ - "if", - "then" + "into", + "sourceString" ] - } + }, + "renderings": { + "$ref": "#/definitions/T" } - } }, - "T": { - "type": "object" - } - }, - "$schema": "http://json-schema.org/draft-07/schema#" + "required": [ + "renderings", + "rewrite" + ], + "definitions": { + "AndOrTagConfigJson": { + "type": "object", + "properties": { + "and": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + }, + "or": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + } + } + }, + "ApplicableUnitJson": { + "type": "object", + "properties": { + "canonicalDenomination": { + "description": "The canonical value which will be added to the text.\ne.g. \"m\" for meters\nIf the user inputs '42', the canonical value will be added and it'll become '42m'", + "type": "string" + }, + "canonicalDenominationSingular": { + "description": "The canonical denomination in the case that the unit is precisely '1'", + "type": "string" + }, + "alternativeDenomination": { + "description": "A list of alternative values which can occur in the OSM database - used for parsing.", + "type": "array", + "items": { + "type": "string" + } + }, + "human": { + "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"meter\",\n \"fr\": \"metre\"\n}" + }, + "humanSingular": { + "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"minute\",\n \"nl\": \"minuut\"x²\n}" + }, + "prefix": { + "description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field", + "type": "boolean" + }, + "default": { + "description": "The default interpretation - only one can be set.\nIf none is set, the first unit will be considered the default interpretation of a value without a unit", + "type": "boolean" + } + }, + "required": [ + "canonicalDenomination" + ] + }, + "TagRenderingConfigJson": { + "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRenerdering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", + "type": "object", + "properties": { + "id": { + "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", + "type": "string" + }, + "group": { + "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", + "type": "string" + }, + "labels": { + "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", + "type": "array", + "items": { + "type": "string" + } + }, + "render": { + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + }, + "condition": { + "description": "Only show this tagrendering (or question) if the object also matches the following tags.\n\nThis is useful to ask a follow-up question. E.g. if there is a diaper table, then ask a follow-up question on diaper tables...", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "freeform": { + "description": "Allow freeform text input from the user", + "type": "object", + "properties": { + "key": { + "description": "If this key is present, then 'render' is used to display the value.\nIf this is undefined, the rendering is _always_ shown", + "type": "string" + } + }, + "required": [ + "key" + ] + }, + "mappings": { + "description": "Allows fixed-tag inputs, shown either as radiobuttons or as checkboxes", + "type": "array", + "items": { + "type": "object", + "properties": { + "if": { + "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "then": { + "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" + }, + "icon": { + "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "class", + "path" + ] + }, + { + "type": "string" + } + ] + } + }, + "required": [ + "if", + "then" + ] + } + } + } + }, + "T": { + "type": "object" + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" } \ No newline at end of file diff --git a/Docs/Schemas/TagRenderingConfigJsonJSC.ts b/Docs/Schemas/TagRenderingConfigJsonJSC.ts index 9d4e22b6a0..11afa40fc2 100644 --- a/Docs/Schemas/TagRenderingConfigJsonJSC.ts +++ b/Docs/Schemas/TagRenderingConfigJsonJSC.ts @@ -1,134 +1,134 @@ export default { - "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRenerdering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", - "type": "object", - "properties": { - "id": { - "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", - "type": "string" - }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, - "labels": { - "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", - "type": "array", - "items": { - "type": "string" - } - }, - "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" - }, - "condition": { - "description": "Only show this tagrendering (or question) if the object also matches the following tags.\n\nThis is useful to ask a follow-up question. E.g. if there is a diaper table, then ask a follow-up question on diaper tables...", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" + "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRenerdering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", + "type": "object", + "properties": { + "id": { + "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", + "type": "string" }, - { - "type": "string" - } - ] - }, - "freeform": { - "description": "Allow freeform text input from the user", - "type": "object", - "properties": { - "key": { - "description": "If this key is present, then 'render' is used to display the value.\nIf this is undefined, the rendering is _always_ shown", - "type": "string" - } - }, - "required": [ - "key" - ] - }, - "mappings": { - "description": "Allows fixed-tag inputs, shown either as radiobuttons or as checkboxes", - "type": "array", - "items": { - "type": "object", - "properties": { - "if": { - "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { + "group": { + "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", + "type": "string" + }, + "labels": { + "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", + "type": "array", + "items": { "type": "string" - } - ] - }, - "then": { - "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" - }, - "icon": { - "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", + } + }, + "render": { + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + }, + "condition": { + "description": "Only show this tagrendering (or question) if the object also matches the following tags.\n\nThis is useful to ask a follow-up question. E.g. if there is a diaper table, then ask a follow-up question on diaper tables...", "anyOf": [ - { + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "freeform": { + "description": "Allow freeform text input from the user", + "type": "object", + "properties": { + "key": { + "description": "If this key is present, then 'render' is used to display the value.\nIf this is undefined, the rendering is _always_ shown", + "type": "string" + } + }, + "required": [ + "key" + ] + }, + "mappings": { + "description": "Allows fixed-tag inputs, shown either as radiobuttons or as checkboxes", + "type": "array", + "items": { "type": "object", "properties": { - "path": { - "description": "The path to the icon\nType: icon", - "type": "string" - }, - "class": { - "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", - "type": "string" - } + "if": { + "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "then": { + "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" + }, + "icon": { + "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "class", + "path" + ] + }, + { + "type": "string" + } + ] + } }, "required": [ - "class", - "path" + "if", + "then" ] - }, - { - "type": "string" - } - ] - } - }, - "required": [ - "if", - "then" - ] - } - } - }, - "definitions": { - "AndOrTagConfigJson": { - "type": "object", - "properties": { - "and": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - } - }, - "or": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - } + } } - } - } - }, - "$schema": "http://json-schema.org/draft-07/schema#" + }, + "definitions": { + "AndOrTagConfigJson": { + "type": "object", + "properties": { + "and": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + }, + "or": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + } + } + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" } \ No newline at end of file diff --git a/Docs/Schemas/TilesourceConfigJsonJSC.ts b/Docs/Schemas/TilesourceConfigJsonJSC.ts index 7f9e0d3194..e9120cab1a 100644 --- a/Docs/Schemas/TilesourceConfigJsonJSC.ts +++ b/Docs/Schemas/TilesourceConfigJsonJSC.ts @@ -1,770 +1,770 @@ export default { - "description": "Configuration for a tilesource config", - "type": "object", - "properties": { - "id": { - "description": "Id of this overlay, used in the URL-parameters to set the state", - "type": "string" - }, - "source": { - "description": "The path, where {x}, {y} and {z} will be substituted", - "type": "string" - }, - "isOverlay": { - "description": "Wether or not this is an overlay. Default: true", - "type": "boolean" - }, - "name": { - "description": "How this will be shown in the selection menu.\nMake undefined if this may not be toggled" - }, - "minZoom": { - "description": "Only visible at this or a higher zoom level", - "type": "number" - }, - "maxZoom": { - "description": "Only visible at this or a lower zoom level", - "type": "number" - }, - "defaultState": { - "description": "The default state, set to false to hide by default", - "type": "boolean" - } - }, - "required": [ - "defaultState", - "id", - "source" - ], - "definitions": { - "AndOrTagConfigJson": { - "type": "object", - "properties": { - "and": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - } - }, - "or": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - } - } - } - }, - "ApplicableUnitJson": { - "type": "object", - "properties": { - "canonicalDenomination": { - "description": "The canonical value which will be added to the text.\ne.g. \"m\" for meters\nIf the user inputs '42', the canonical value will be added and it'll become '42m'", - "type": "string" - }, - "canonicalDenominationSingular": { - "description": "The canonical denomination in the case that the unit is precisely '1'", - "type": "string" - }, - "alternativeDenomination": { - "description": "A list of alternative values which can occur in the OSM database - used for parsing.", - "type": "array", - "items": { - "type": "string" - } - }, - "human": { - "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"meter\",\n \"fr\": \"metre\"\n}" - }, - "humanSingular": { - "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"minute\",\n \"nl\": \"minuut\"x²\n}" - }, - "prefix": { - "description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field", - "type": "boolean" - }, - "default": { - "description": "The default interpretation - only one can be set.\nIf none is set, the first unit will be considered the default interpretation of a value without a unit", - "type": "boolean" - } - }, - "required": [ - "canonicalDenomination" - ] - }, - "TagRenderingConfigJson": { - "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRenerdering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", - "type": "object", - "properties": { + "description": "Configuration for a tilesource config", + "type": "object", + "properties": { "id": { - "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", - "type": "string" - }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, - "labels": { - "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", - "type": "array", - "items": { + "description": "Id of this overlay, used in the URL-parameters to set the state", "type": "string" - } }, - "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" - }, - "condition": { - "description": "Only show this tagrendering (or question) if the object also matches the following tags.\n\nThis is useful to ask a follow-up question. E.g. if there is a diaper table, then ask a follow-up question on diaper tables...", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - }, - "freeform": { - "description": "Allow freeform text input from the user", - "type": "object", - "properties": { - "key": { - "description": "If this key is present, then 'render' is used to display the value.\nIf this is undefined, the rendering is _always_ shown", - "type": "string" - } - }, - "required": [ - "key" - ] - }, - "mappings": { - "description": "Allows fixed-tag inputs, shown either as radiobuttons or as checkboxes", - "type": "array", - "items": { - "type": "object", - "properties": { - "if": { - "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - }, - "then": { - "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" - }, - "icon": { - "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", - "anyOf": [ - { - "type": "object", - "properties": { - "path": { - "description": "The path to the icon\nType: icon", - "type": "string" - }, - "class": { - "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", - "type": "string" - } - }, - "required": [ - "class", - "path" - ] - }, - { - "type": "string" - } - ] - } - }, - "required": [ - "if", - "then" - ] - } - } - } - }, - "T": { - "type": "object" - }, - "default_4": { - "description": "The PointRenderingConfig gives all details onto how to render a single point of a feature.\n\nThis can be used if:\n\n- The feature is a point\n- To render something at the centroid of an area, or at the start, end or projected centroid of a way", - "type": "object", - "properties": { - "location": { - "description": "All the locations that this point should be rendered at.\nUsing `location: [\"point\", \"centroid\"] will always render centerpoint", - "type": "array", - "items": { + "source": { + "description": "The path, where {x}, {y} and {z} will be substituted", "type": "string" - } }, - "icon": { - "description": "The icon for an element.\nNote that this also doubles as the icon for this layer (rendered with the overpass-tags) ánd the icon in the presets.\n\nThe result of the icon is rendered as follows:\nthe resulting string is interpreted as a _list_ of items, separated by \";\". The bottommost layer is the first layer.\nAs a result, on could use a generic pin, then overlay it with a specific icon.\nTo make things even more practical, one can use all SVG's from the folder \"assets/svg\" and _substitute the color_ in it.\nE.g. to draw a red pin, use \"pin:#f00\", to have a green circle with your icon on top, use `circle:#0f0;`\n\nType: icon", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] + "isOverlay": { + "description": "Wether or not this is an overlay. Default: true", + "type": "boolean" }, - "iconBadges": { - "description": "A list of extra badges to show next to the icon as small badge\nThey will be added as a 25% height icon at the bottom right of the icon, with all the badges in a flex layout.\n\nNote: strings are interpreted as icons, so layering and substituting is supported. You can use `circle:white;./my_icon.svg` to add a background circle", - "type": "array", - "items": { - "type": "object", - "properties": { - "if": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - }, - "then": { - "description": "Badge to show\nType: icon", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - } - }, - "required": [ - "if", - "then" - ] - } + "name": { + "description": "How this will be shown in the selection menu.\nMake undefined if this may not be toggled" }, - "iconSize": { - "description": "A string containing \"width,height\" or \"width,height,anchorpoint\" where anchorpoint is any of 'center', 'top', 'bottom', 'left', 'right', 'bottomleft','topright', ...\nDefault is '40,40,center'", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] + "minZoom": { + "description": "Only visible at this or a higher zoom level", + "type": "number" }, - "rotation": { - "description": "The rotation of an icon, useful for e.g. directions.\nUsage: as if it were a css property for 'rotate', thus has to end with 'deg', e.g. `90deg`, `{direction}deg`, `calc(90deg - {camera:direction}deg)``", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] + "maxZoom": { + "description": "Only visible at this or a lower zoom level", + "type": "number" }, - "label": { - "description": "A HTML-fragment that is shown below the icon, for example:\n
{name}
\n\nIf the icon is undefined, then the label is shown in the center of the feature.\nNote that, if the wayhandling hides the icon then no label is shown as well.", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] + "defaultState": { + "description": "The default state, set to false to hide by default", + "type": "boolean" } - }, - "required": [ - "location" - ] }, - "default_5": { - "description": "The LineRenderingConfig gives all details onto how to render a single line of a feature.\n\nThis can be used if:\n\n- The feature is a line\n- The feature is an area", - "type": "object", - "properties": { - "color": { - "description": "The color for way-elements and SVG-elements.\nIf the value starts with \"--\", the style of the body element will be queried for the corresponding variable instead", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - }, - "width": { - "description": "The stroke-width for way-elements", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": [ - "string", - "number" - ] - } - ] - }, - "dashArray": { - "description": "A dasharray, e.g. \"5 6\"\nThe dasharray defines 'pixels of line, pixels of gap, pixels of line, pixels of gap',\nDefault value: \"\" (empty string == full line)", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - }, - "lineCap": { - "description": "The form at the end of a line", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - }, - "fill": { - "description": "Wehter or not to fill polygons", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "enum": [ - "no", - "yes" - ], - "type": "string" - } - ] - }, - "fillColor": { - "description": "The color to fill a polygon with.\nIf undefined, this will be slightly more opaque version of the stroke line", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "string" - } - ] - }, - "offset": { - "description": "The number of pixels this line should be moved.\nUse a positive numbe to move to the right, a negative to move to the left (left/right as defined by the drawing direction of the line).\n\nIMPORTANT: MapComplete will already normalize 'key:both:property' and 'key:both' into the corresponding 'key:left' and 'key:right' tagging (same for 'sidewalk=left/right/both' which is rewritten to 'sidewalk:left' and 'sidewalk:right')\nThis simplifies programming. Refer to the CalculatedTags.md-documentation for more details", - "anyOf": [ - { - "$ref": "#/definitions/TagRenderingConfigJson" - }, - { - "type": "number" - } - ] - } - } - }, - "QuestionableTagRenderingConfigJson": { - "description": "A QuestionableTagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nIf the desired tags are missing and a question is defined, a question will be shown instead.", - "type": "object", - "properties": { - "question": { - "description": "If it turns out that this tagRendering doesn't match _any_ value, then we show this question.\nIf undefined, the question is never asked and this tagrendering is read-only" - }, - "freeform": { - "description": "Allow freeform text input from the user", - "type": "object", - "properties": { - "key": { - "type": "string" - }, - "type": { - "description": "The type of the text-field, e.g. 'string', 'nat', 'float', 'date',...\nSee Docs/SpecialInputElements.md and UI/Input/ValidatedTextField.ts for supported values", - "type": "string" - }, - "placeholder": { - "description": "A (translated) text that is shown (as gray text) within the textfield" - }, - "helperArgs": { - "description": "Extra parameters to initialize the input helper arguments.\nFor semantics, see the 'SpecialInputElements.md'", - "type": "array", - "items": {} - }, - "addExtraTags": { - "description": "If a value is added with the textfield, these extra tag is addded.\nUseful to add a 'fixme=freeform textfield used - to be checked'", - "type": "array", - "items": { - "type": "string" - } - }, - "inline": { - "description": "When set, influences the way a question is asked.\nInstead of showing a full-widht text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.", - "type": "boolean" - }, - "default": { - "description": "default value to enter if no previous tagging is present.\nNormally undefined (aka do not enter anything)", - "type": "string" - } - }, - "required": [ - "key" - ] - }, - "multiAnswer": { - "description": "If true, use checkboxes instead of radio buttons when asking the question", - "type": "boolean" - }, - "mappings": { - "description": "Allows fixed-tag inputs, shown either as radiobuttons or as checkboxes", - "type": "array", - "items": { - "type": "object", - "properties": { - "if": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - }, - "then": { - "description": "Shown if the 'if is fulfilled\nType: rendered" - }, - "icon": { - "description": "An extra icon supporting the choice\nType: icon", - "anyOf": [ - { - "type": "object", - "properties": { - "path": { - "description": "The path to the icon\nType: icon", - "type": "string" - }, - "class": { - "description": "Size of the image", - "type": "string" - } - }, - "required": [ - "class", - "path" - ] - }, - { - "type": "string" - } - ] - }, - "hideInAnswer": { - "description": "In some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation).\n\nIn the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user.\nIn this case, one of the mappings can be hiden by setting this flag.\n\nTo demonstrate an example making a default assumption:\n\nmappings: [\n {\n if: \"access=\", -- no access tag present, we assume accessible\n then: \"Accessible to the general public\",\n hideInAnswer: true\n },\n {\n if: \"access=yes\",\n then: \"Accessible to the general public\", -- the user selected this, we add that to OSM\n },\n {\n if: \"access=no\",\n then: \"Not accessible to the public\"\n }\n]\n\n\nFor example, for an operator, we have `operator=Agentschap Natuur en Bos`, which is often abbreviated to `operator=ANB`.\nThen, we would add two mappings:\n{\n if: \"operator=Agentschap Natuur en Bos\" -- the non-abbreviated version which should be uploaded\n then: \"Maintained by Agentschap Natuur en Bos\"\n},\n{\n if: \"operator=ANB\", -- we don't want to upload abbreviations\n then: \"Maintained by Agentschap Natuur en Bos\"\n hideInAnswer: true\n}\n\nHide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate.\nKeep in mind that this is reverse logic: it will be hidden in the answer if the condition is true, it will thus only show in the case of a mismatch\n\ne.g., for toilets: if \"wheelchair=no\", we know there is no wheelchair dedicated room.\nFor the location of the changing table, the option \"in the wheelchair accessible toilet is weird\", so we write:\n\n{\n \"question\": \"Where is the changing table located?\"\n \"mappings\": [\n {\"if\":\"changing_table:location=female\",\"then\":\"In the female restroom\"},\n {\"if\":\"changing_table:location=male\",\"then\":\"In the male restroom\"},\n {\"if\":\"changing_table:location=wheelchair\",\"then\":\"In the wheelchair accessible restroom\", \"hideInAnswer\": \"wheelchair=no\"},\n \n ]\n}\n\nAlso have a look for the meta-tags\n{\n if: \"operator=Agentschap Natuur en Bos\",\n then: \"Maintained by Agentschap Natuur en Bos\",\n hideInAnswer: \"_country!=be\"\n}", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": [ - "string", - "boolean" - ] - } - ] - }, - "ifnot": { - "description": "Only applicable if 'multiAnswer' is set.\nThis is for situations such as:\n`accepts:coins=no` where one can select all the possible payment methods. However, we want to make explicit that some options _were not_ selected.\nThis can be done with `ifnot`\nNote that we can not explicitly render this negative case to the user, we cannot show `does _not_ accept coins`.\nIf this is important to your usecase, consider using multiple radiobutton-fields without `multiAnswer`", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - }, - "addExtraTags": { - "description": "If chosen as answer, these tags will be applied as well onto the object.\nNot compatible with multiAnswer", - "type": "array", - "items": { - "type": "string" - } - } - }, - "required": [ - "if", - "then" - ] - } - }, - "id": { - "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", - "type": "string" - }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, - "labels": { - "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", - "type": "array", - "items": { - "type": "string" - } - }, - "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" - }, - "condition": { - "description": "Only show this tagrendering (or question) if the object also matches the following tags.\n\nThis is useful to ask a follow-up question. E.g. if there is a diaper table, then ask a follow-up question on diaper tables...", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - } - } - }, - "default<(string|QuestionableTagRenderingConfigJson|{builtin:string;override:any;})[]>": { - "type": "object", - "properties": { - "rewrite": { - "type": "object", - "properties": { - "sourceString": { - "type": "array", - "items": { - "type": "string" - } - }, - "into": { - "type": "array", - "items": { - "type": "array", - "items": {} - } - } - }, - "required": [ - "into", - "sourceString" - ] - }, - "renderings": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/QuestionableTagRenderingConfigJson" - }, - { - "type": "object", - "properties": { - "builtin": { - "type": "string" - }, - "override": {} - }, - "required": [ - "builtin", - "override" - ] - }, - { - "type": "string" - } - ] - } - } - }, - "required": [ - "renderings", - "rewrite" - ] - }, - "default_1": { - "type": "object", - "properties": { - "id": { - "description": "An id/name for this filter, used to set the URL parameters", - "type": "string" - }, - "options": { - "description": "The options for a filter\nIf there are multiple options these will be a list of radio buttons\nIf there is only one option this will be a checkbox\nFiltering is done based on the given osmTags that are compared to the objects in that layer.", - "type": "array", - "items": { - "type": "object", - "properties": { - "question": {}, - "osmTags": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - }, - "default": { - "type": "boolean" - }, - "fields": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "type": { - "type": "string" - } - }, - "required": [ - "name" - ] - } - } - }, - "required": [ - "question" - ] - } - } - }, - "required": [ + "required": [ + "defaultState", "id", - "options" - ] - }, - "DeleteConfigJson": { - "type": "object", - "properties": { - "extraDeleteReasons": { - "description": "*\nBy default, three reasons to delete a point are shown:\n\n- The point does not exist anymore\n- The point was a testing point\n- THe point could not be found\n\nHowever, for some layers, there might be different or more specific reasons for deletion which can be user friendly to set, e.g.:\n\n- the shop has closed\n- the climbing route has been closed of for nature conservation reasons\n- ...\n\nThese reasons can be stated here and will be shown in the list of options the user can choose from", - "type": "array", - "items": { + "source" + ], + "definitions": { + "AndOrTagConfigJson": { "type": "object", "properties": { - "explanation": { - "description": "The text that will be shown to the user - translatable" - }, - "changesetMessage": { - "description": "The text that will be uploaded into the changeset or will be used in the fixme in case of a soft deletion\nShould be a few words, in english", - "type": "string" - } - }, - "required": [ - "changesetMessage", - "explanation" - ] - } - }, - "nonDeleteMappings": { - "description": "In some cases, a (starting) contributor might wish to delete a feature even though deletion is not appropriate.\n(The most relevant case are small paths running over private property. These should be marked as 'private' instead of deleted, as the community might trace the path again from aerial imagery, gettting us back to the original situation).\n\nBy adding a 'nonDeleteMapping', an option can be added into the list which will retag the feature.\nIt is important that the feature will be retagged in such a way that it won't be picked up by the layer anymore!", - "type": "array", - "items": { - "type": "object", - "properties": { - "if": { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - "then": {} - }, - "required": [ - "if", - "then" - ] - } - }, - "softDeletionTags": { - "description": "In some cases, the contributor is not allowed to delete the current feature (e.g. because it isn't a point, the point is referenced by a relation or the user isn't experienced enough).\nTo still offer the user a 'delete'-option, the feature is retagged with these tags. This is a soft deletion, as the point isn't actually removed from OSM but rather marked as 'disused'\nIt is important that the feature will be retagged in such a way that it won't be picked up by the layer anymore!\n\nExample (note that \"amenity=\" erases the 'amenity'-key alltogether):\n```\n{\n \"and\": [\"disussed:amenity=public_bookcase\", \"amenity=\"]\n}\n```\n\nor (notice the use of the ':='-tag to copy the old value of 'shop=*' into 'disused:shop='):\n```\n{\n \"and\": [\"disused:shop:={shop}\", \"shop=\"]\n}\n```", - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" + "and": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + }, + "or": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + } } - ] }, - "neededChangesets": { - "description": "*\nBy default, the contributor needs 20 previous changesets to delete points edited by others.\nFor some small features (e.g. bicycle racks) this is too much and this requirement can be lowered or dropped, which can be done here.", - "type": "number" + "ApplicableUnitJson": { + "type": "object", + "properties": { + "canonicalDenomination": { + "description": "The canonical value which will be added to the text.\ne.g. \"m\" for meters\nIf the user inputs '42', the canonical value will be added and it'll become '42m'", + "type": "string" + }, + "canonicalDenominationSingular": { + "description": "The canonical denomination in the case that the unit is precisely '1'", + "type": "string" + }, + "alternativeDenomination": { + "description": "A list of alternative values which can occur in the OSM database - used for parsing.", + "type": "array", + "items": { + "type": "string" + } + }, + "human": { + "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"meter\",\n \"fr\": \"metre\"\n}" + }, + "humanSingular": { + "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"minute\",\n \"nl\": \"minuut\"x²\n}" + }, + "prefix": { + "description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field", + "type": "boolean" + }, + "default": { + "description": "The default interpretation - only one can be set.\nIf none is set, the first unit will be considered the default interpretation of a value without a unit", + "type": "boolean" + } + }, + "required": [ + "canonicalDenomination" + ] + }, + "TagRenderingConfigJson": { + "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRenerdering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", + "type": "object", + "properties": { + "id": { + "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", + "type": "string" + }, + "group": { + "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", + "type": "string" + }, + "labels": { + "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", + "type": "array", + "items": { + "type": "string" + } + }, + "render": { + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + }, + "condition": { + "description": "Only show this tagrendering (or question) if the object also matches the following tags.\n\nThis is useful to ask a follow-up question. E.g. if there is a diaper table, then ask a follow-up question on diaper tables...", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "freeform": { + "description": "Allow freeform text input from the user", + "type": "object", + "properties": { + "key": { + "description": "If this key is present, then 'render' is used to display the value.\nIf this is undefined, the rendering is _always_ shown", + "type": "string" + } + }, + "required": [ + "key" + ] + }, + "mappings": { + "description": "Allows fixed-tag inputs, shown either as radiobuttons or as checkboxes", + "type": "array", + "items": { + "type": "object", + "properties": { + "if": { + "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "then": { + "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" + }, + "icon": { + "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "class", + "path" + ] + }, + { + "type": "string" + } + ] + } + }, + "required": [ + "if", + "then" + ] + } + } + } + }, + "T": { + "type": "object" + }, + "default_4": { + "description": "The PointRenderingConfig gives all details onto how to render a single point of a feature.\n\nThis can be used if:\n\n- The feature is a point\n- To render something at the centroid of an area, or at the start, end or projected centroid of a way", + "type": "object", + "properties": { + "location": { + "description": "All the locations that this point should be rendered at.\nUsing `location: [\"point\", \"centroid\"] will always render centerpoint", + "type": "array", + "items": { + "type": "string" + } + }, + "icon": { + "description": "The icon for an element.\nNote that this also doubles as the icon for this layer (rendered with the overpass-tags) ánd the icon in the presets.\n\nThe result of the icon is rendered as follows:\nthe resulting string is interpreted as a _list_ of items, separated by \";\". The bottommost layer is the first layer.\nAs a result, on could use a generic pin, then overlay it with a specific icon.\nTo make things even more practical, one can use all SVG's from the folder \"assets/svg\" and _substitute the color_ in it.\nE.g. to draw a red pin, use \"pin:#f00\", to have a green circle with your icon on top, use `circle:#0f0;`\n\nType: icon", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "iconBadges": { + "description": "A list of extra badges to show next to the icon as small badge\nThey will be added as a 25% height icon at the bottom right of the icon, with all the badges in a flex layout.\n\nNote: strings are interpreted as icons, so layering and substituting is supported. You can use `circle:white;./my_icon.svg` to add a background circle", + "type": "array", + "items": { + "type": "object", + "properties": { + "if": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "then": { + "description": "Badge to show\nType: icon", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + } + }, + "required": [ + "if", + "then" + ] + } + }, + "iconSize": { + "description": "A string containing \"width,height\" or \"width,height,anchorpoint\" where anchorpoint is any of 'center', 'top', 'bottom', 'left', 'right', 'bottomleft','topright', ...\nDefault is '40,40,center'", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "rotation": { + "description": "The rotation of an icon, useful for e.g. directions.\nUsage: as if it were a css property for 'rotate', thus has to end with 'deg', e.g. `90deg`, `{direction}deg`, `calc(90deg - {camera:direction}deg)``", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "label": { + "description": "A HTML-fragment that is shown below the icon, for example:\n
{name}
\n\nIf the icon is undefined, then the label is shown in the center of the feature.\nNote that, if the wayhandling hides the icon then no label is shown as well.", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + } + }, + "required": [ + "location" + ] + }, + "default_5": { + "description": "The LineRenderingConfig gives all details onto how to render a single line of a feature.\n\nThis can be used if:\n\n- The feature is a line\n- The feature is an area", + "type": "object", + "properties": { + "color": { + "description": "The color for way-elements and SVG-elements.\nIf the value starts with \"--\", the style of the body element will be queried for the corresponding variable instead", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "width": { + "description": "The stroke-width for way-elements", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": [ + "string", + "number" + ] + } + ] + }, + "dashArray": { + "description": "A dasharray, e.g. \"5 6\"\nThe dasharray defines 'pixels of line, pixels of gap, pixels of line, pixels of gap',\nDefault value: \"\" (empty string == full line)", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "lineCap": { + "description": "The form at the end of a line", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "fill": { + "description": "Wehter or not to fill polygons", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "enum": [ + "no", + "yes" + ], + "type": "string" + } + ] + }, + "fillColor": { + "description": "The color to fill a polygon with.\nIf undefined, this will be slightly more opaque version of the stroke line", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "offset": { + "description": "The number of pixels this line should be moved.\nUse a positive numbe to move to the right, a negative to move to the left (left/right as defined by the drawing direction of the line).\n\nIMPORTANT: MapComplete will already normalize 'key:both:property' and 'key:both' into the corresponding 'key:left' and 'key:right' tagging (same for 'sidewalk=left/right/both' which is rewritten to 'sidewalk:left' and 'sidewalk:right')\nThis simplifies programming. Refer to the CalculatedTags.md-documentation for more details", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "number" + } + ] + } + } + }, + "QuestionableTagRenderingConfigJson": { + "description": "A QuestionableTagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nIf the desired tags are missing and a question is defined, a question will be shown instead.", + "type": "object", + "properties": { + "question": { + "description": "If it turns out that this tagRendering doesn't match _any_ value, then we show this question.\nIf undefined, the question is never asked and this tagrendering is read-only" + }, + "freeform": { + "description": "Allow freeform text input from the user", + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "type": { + "description": "The type of the text-field, e.g. 'string', 'nat', 'float', 'date',...\nSee Docs/SpecialInputElements.md and UI/Input/ValidatedTextField.ts for supported values", + "type": "string" + }, + "placeholder": { + "description": "A (translated) text that is shown (as gray text) within the textfield" + }, + "helperArgs": { + "description": "Extra parameters to initialize the input helper arguments.\nFor semantics, see the 'SpecialInputElements.md'", + "type": "array", + "items": {} + }, + "addExtraTags": { + "description": "If a value is added with the textfield, these extra tag is addded.\nUseful to add a 'fixme=freeform textfield used - to be checked'", + "type": "array", + "items": { + "type": "string" + } + }, + "inline": { + "description": "When set, influences the way a question is asked.\nInstead of showing a full-widht text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.", + "type": "boolean" + }, + "default": { + "description": "default value to enter if no previous tagging is present.\nNormally undefined (aka do not enter anything)", + "type": "string" + } + }, + "required": [ + "key" + ] + }, + "multiAnswer": { + "description": "If true, use checkboxes instead of radio buttons when asking the question", + "type": "boolean" + }, + "mappings": { + "description": "Allows fixed-tag inputs, shown either as radiobuttons or as checkboxes", + "type": "array", + "items": { + "type": "object", + "properties": { + "if": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "then": { + "description": "Shown if the 'if is fulfilled\nType: rendered" + }, + "icon": { + "description": "An extra icon supporting the choice\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "Size of the image", + "type": "string" + } + }, + "required": [ + "class", + "path" + ] + }, + { + "type": "string" + } + ] + }, + "hideInAnswer": { + "description": "In some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation).\n\nIn the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user.\nIn this case, one of the mappings can be hiden by setting this flag.\n\nTo demonstrate an example making a default assumption:\n\nmappings: [\n {\n if: \"access=\", -- no access tag present, we assume accessible\n then: \"Accessible to the general public\",\n hideInAnswer: true\n },\n {\n if: \"access=yes\",\n then: \"Accessible to the general public\", -- the user selected this, we add that to OSM\n },\n {\n if: \"access=no\",\n then: \"Not accessible to the public\"\n }\n]\n\n\nFor example, for an operator, we have `operator=Agentschap Natuur en Bos`, which is often abbreviated to `operator=ANB`.\nThen, we would add two mappings:\n{\n if: \"operator=Agentschap Natuur en Bos\" -- the non-abbreviated version which should be uploaded\n then: \"Maintained by Agentschap Natuur en Bos\"\n},\n{\n if: \"operator=ANB\", -- we don't want to upload abbreviations\n then: \"Maintained by Agentschap Natuur en Bos\"\n hideInAnswer: true\n}\n\nHide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate.\nKeep in mind that this is reverse logic: it will be hidden in the answer if the condition is true, it will thus only show in the case of a mismatch\n\ne.g., for toilets: if \"wheelchair=no\", we know there is no wheelchair dedicated room.\nFor the location of the changing table, the option \"in the wheelchair accessible toilet is weird\", so we write:\n\n{\n \"question\": \"Where is the changing table located?\"\n \"mappings\": [\n {\"if\":\"changing_table:location=female\",\"then\":\"In the female restroom\"},\n {\"if\":\"changing_table:location=male\",\"then\":\"In the male restroom\"},\n {\"if\":\"changing_table:location=wheelchair\",\"then\":\"In the wheelchair accessible restroom\", \"hideInAnswer\": \"wheelchair=no\"},\n \n ]\n}\n\nAlso have a look for the meta-tags\n{\n if: \"operator=Agentschap Natuur en Bos\",\n then: \"Maintained by Agentschap Natuur en Bos\",\n hideInAnswer: \"_country!=be\"\n}", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": [ + "string", + "boolean" + ] + } + ] + }, + "ifnot": { + "description": "Only applicable if 'multiAnswer' is set.\nThis is for situations such as:\n`accepts:coins=no` where one can select all the possible payment methods. However, we want to make explicit that some options _were not_ selected.\nThis can be done with `ifnot`\nNote that we can not explicitly render this negative case to the user, we cannot show `does _not_ accept coins`.\nIf this is important to your usecase, consider using multiple radiobutton-fields without `multiAnswer`", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "addExtraTags": { + "description": "If chosen as answer, these tags will be applied as well onto the object.\nNot compatible with multiAnswer", + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "if", + "then" + ] + } + }, + "id": { + "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", + "type": "string" + }, + "group": { + "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", + "type": "string" + }, + "labels": { + "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", + "type": "array", + "items": { + "type": "string" + } + }, + "render": { + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + }, + "condition": { + "description": "Only show this tagrendering (or question) if the object also matches the following tags.\n\nThis is useful to ask a follow-up question. E.g. if there is a diaper table, then ask a follow-up question on diaper tables...", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + } + }, + "default<(string|QuestionableTagRenderingConfigJson|{builtin:string;override:any;})[]>": { + "type": "object", + "properties": { + "rewrite": { + "type": "object", + "properties": { + "sourceString": { + "type": "array", + "items": { + "type": "string" + } + }, + "into": { + "type": "array", + "items": { + "type": "array", + "items": {} + } + } + }, + "required": [ + "into", + "sourceString" + ] + }, + "renderings": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/QuestionableTagRenderingConfigJson" + }, + { + "type": "object", + "properties": { + "builtin": { + "type": "string" + }, + "override": {} + }, + "required": [ + "builtin", + "override" + ] + }, + { + "type": "string" + } + ] + } + } + }, + "required": [ + "renderings", + "rewrite" + ] + }, + "default_1": { + "type": "object", + "properties": { + "id": { + "description": "An id/name for this filter, used to set the URL parameters", + "type": "string" + }, + "options": { + "description": "The options for a filter\nIf there are multiple options these will be a list of radio buttons\nIf there is only one option this will be a checkbox\nFiltering is done based on the given osmTags that are compared to the objects in that layer.", + "type": "array", + "items": { + "type": "object", + "properties": { + "question": {}, + "osmTags": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "default": { + "type": "boolean" + }, + "fields": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + }, + "required": [ + "question" + ] + } + } + }, + "required": [ + "id", + "options" + ] + }, + "DeleteConfigJson": { + "type": "object", + "properties": { + "extraDeleteReasons": { + "description": "*\nBy default, three reasons to delete a point are shown:\n\n- The point does not exist anymore\n- The point was a testing point\n- THe point could not be found\n\nHowever, for some layers, there might be different or more specific reasons for deletion which can be user friendly to set, e.g.:\n\n- the shop has closed\n- the climbing route has been closed of for nature conservation reasons\n- ...\n\nThese reasons can be stated here and will be shown in the list of options the user can choose from", + "type": "array", + "items": { + "type": "object", + "properties": { + "explanation": { + "description": "The text that will be shown to the user - translatable" + }, + "changesetMessage": { + "description": "The text that will be uploaded into the changeset or will be used in the fixme in case of a soft deletion\nShould be a few words, in english", + "type": "string" + } + }, + "required": [ + "changesetMessage", + "explanation" + ] + } + }, + "nonDeleteMappings": { + "description": "In some cases, a (starting) contributor might wish to delete a feature even though deletion is not appropriate.\n(The most relevant case are small paths running over private property. These should be marked as 'private' instead of deleted, as the community might trace the path again from aerial imagery, gettting us back to the original situation).\n\nBy adding a 'nonDeleteMapping', an option can be added into the list which will retag the feature.\nIt is important that the feature will be retagged in such a way that it won't be picked up by the layer anymore!", + "type": "array", + "items": { + "type": "object", + "properties": { + "if": { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + "then": {} + }, + "required": [ + "if", + "then" + ] + } + }, + "softDeletionTags": { + "description": "In some cases, the contributor is not allowed to delete the current feature (e.g. because it isn't a point, the point is referenced by a relation or the user isn't experienced enough).\nTo still offer the user a 'delete'-option, the feature is retagged with these tags. This is a soft deletion, as the point isn't actually removed from OSM but rather marked as 'disused'\nIt is important that the feature will be retagged in such a way that it won't be picked up by the layer anymore!\n\nExample (note that \"amenity=\" erases the 'amenity'-key alltogether):\n```\n{\n \"and\": [\"disussed:amenity=public_bookcase\", \"amenity=\"]\n}\n```\n\nor (notice the use of the ':='-tag to copy the old value of 'shop=*' into 'disused:shop='):\n```\n{\n \"and\": [\"disused:shop:={shop}\", \"shop=\"]\n}\n```", + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + }, + "neededChangesets": { + "description": "*\nBy default, the contributor needs 20 previous changesets to delete points edited by others.\nFor some small features (e.g. bicycle racks) this is too much and this requirement can be lowered or dropped, which can be done here.", + "type": "number" + } + } + }, + "default_3": { + "type": "object", + "properties": { + "enableImproveAccuracy": { + "description": "One default reason to move a point is to improve accuracy.\nSet to false to disable this reason", + "type": "boolean" + }, + "enableRelocation": { + "description": "One default reason to move a point is because it has relocated\nSet to false to disable this reason", + "type": "boolean" + } + } + }, + "default_2": { + "type": "object", + "properties": { + "appliesToKey": { + "description": "Every key from this list will be normalized", + "type": "array", + "items": { + "type": "string" + } + }, + "eraseInvalidValues": { + "description": "If set, invalid values will be erased in the MC application (but not in OSM of course!)\nBe careful with setting this", + "type": "boolean" + }, + "applicableUnits": { + "description": "The possible denominations", + "type": "array", + "items": { + "$ref": "#/definitions/ApplicableUnitJson" + } + } + }, + "required": [ + "applicableUnits", + "appliesToKey" + ] } - } }, - "default_3": { - "type": "object", - "properties": { - "enableImproveAccuracy": { - "description": "One default reason to move a point is to improve accuracy.\nSet to false to disable this reason", - "type": "boolean" - }, - "enableRelocation": { - "description": "One default reason to move a point is because it has relocated\nSet to false to disable this reason", - "type": "boolean" - } - } - }, - "default_2": { - "type": "object", - "properties": { - "appliesToKey": { - "description": "Every key from this list will be normalized", - "type": "array", - "items": { - "type": "string" - } - }, - "eraseInvalidValues": { - "description": "If set, invalid values will be erased in the MC application (but not in OSM of course!)\nBe careful with setting this", - "type": "boolean" - }, - "applicableUnits": { - "description": "The possible denominations", - "type": "array", - "items": { - "$ref": "#/definitions/ApplicableUnitJson" - } - } - }, - "required": [ - "applicableUnits", - "appliesToKey" - ] - } - }, - "$schema": "http://json-schema.org/draft-07/schema#" + "$schema": "http://json-schema.org/draft-07/schema#" } \ No newline at end of file diff --git a/Docs/Schemas/UnitConfigJsonJSC.ts b/Docs/Schemas/UnitConfigJsonJSC.ts index 9e8fa3c0d1..8c141bffe5 100644 --- a/Docs/Schemas/UnitConfigJsonJSC.ts +++ b/Docs/Schemas/UnitConfigJsonJSC.ts @@ -1,98 +1,98 @@ export default { - "type": "object", - "properties": { - "appliesToKey": { - "description": "Every key from this list will be normalized", - "type": "array", - "items": { - "type": "string" - } - }, - "eraseInvalidValues": { - "description": "If set, invalid values will be erased in the MC application (but not in OSM of course!)\nBe careful with setting this", - "type": "boolean" - }, - "applicableUnits": { - "description": "The possible denominations", - "type": "array", - "items": { - "$ref": "#/definitions/ApplicableUnitJson" - } - } - }, - "required": [ - "applicableUnits", - "appliesToKey" - ], - "definitions": { - "AndOrTagConfigJson": { - "type": "object", - "properties": { - "and": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { + "type": "object", + "properties": { + "appliesToKey": { + "description": "Every key from this list will be normalized", + "type": "array", + "items": { "type": "string" - } - ] - } + } }, - "or": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/AndOrTagConfigJson" - }, - { - "type": "string" - } - ] - } + "eraseInvalidValues": { + "description": "If set, invalid values will be erased in the MC application (but not in OSM of course!)\nBe careful with setting this", + "type": "boolean" + }, + "applicableUnits": { + "description": "The possible denominations", + "type": "array", + "items": { + "$ref": "#/definitions/ApplicableUnitJson" + } } - } }, - "ApplicableUnitJson": { - "type": "object", - "properties": { - "canonicalDenomination": { - "description": "The canonical value which will be added to the text.\ne.g. \"m\" for meters\nIf the user inputs '42', the canonical value will be added and it'll become '42m'", - "type": "string" + "required": [ + "applicableUnits", + "appliesToKey" + ], + "definitions": { + "AndOrTagConfigJson": { + "type": "object", + "properties": { + "and": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + }, + "or": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/AndOrTagConfigJson" + }, + { + "type": "string" + } + ] + } + } + } }, - "canonicalDenominationSingular": { - "description": "The canonical denomination in the case that the unit is precisely '1'", - "type": "string" - }, - "alternativeDenomination": { - "description": "A list of alternative values which can occur in the OSM database - used for parsing.", - "type": "array", - "items": { - "type": "string" - } - }, - "human": { - "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"meter\",\n \"fr\": \"metre\"\n}" - }, - "humanSingular": { - "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"minute\",\n \"nl\": \"minuut\"x²\n}" - }, - "prefix": { - "description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field", - "type": "boolean" - }, - "default": { - "description": "The default interpretation - only one can be set.\nIf none is set, the first unit will be considered the default interpretation of a value without a unit", - "type": "boolean" + "ApplicableUnitJson": { + "type": "object", + "properties": { + "canonicalDenomination": { + "description": "The canonical value which will be added to the text.\ne.g. \"m\" for meters\nIf the user inputs '42', the canonical value will be added and it'll become '42m'", + "type": "string" + }, + "canonicalDenominationSingular": { + "description": "The canonical denomination in the case that the unit is precisely '1'", + "type": "string" + }, + "alternativeDenomination": { + "description": "A list of alternative values which can occur in the OSM database - used for parsing.", + "type": "array", + "items": { + "type": "string" + } + }, + "human": { + "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"meter\",\n \"fr\": \"metre\"\n}" + }, + "humanSingular": { + "description": "The value for humans in the dropdown. This should not use abbreviations and should be translated, e.g.\n{\n \"en\": \"minute\",\n \"nl\": \"minuut\"x²\n}" + }, + "prefix": { + "description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field", + "type": "boolean" + }, + "default": { + "description": "The default interpretation - only one can be set.\nIf none is set, the first unit will be considered the default interpretation of a value without a unit", + "type": "boolean" + } + }, + "required": [ + "canonicalDenomination" + ] } - }, - "required": [ - "canonicalDenomination" - ] - } - }, - "$schema": "http://json-schema.org/draft-07/schema#" + }, + "$schema": "http://json-schema.org/draft-07/schema#" } \ No newline at end of file diff --git a/Docs/SpecialRenderings.md b/Docs/SpecialRenderings.md index 8ad63a77a7..b268df9983 100644 --- a/Docs/SpecialRenderings.md +++ b/Docs/SpecialRenderings.md @@ -5,9 +5,24 @@ +In a tagrendering, some special values are substituted by an advanced UI-element. This allows advanced features and visualizations to be reused by custom themes or even to query third-party API's. + +General usage is `{func_name()}`, `{func_name(arg, someotherarg)}` or `{func_name(args):cssStyle}`. Note that you _do not_ need to use quotes around your arguments, the comma is enough to separate them. This also implies you cannot use a comma in your args + + + +#### Using expanded syntax + + + +Instead of using `{"render": {"en": "{some_special_visualisation(some_arg, some other really long message, more args)} , "nl": "{some_special_visualisation(some_arg, een boodschap in een andere taal, more args)}}, one can also write + +{"render":{"special":{"type":"some_special_visualisation","argname":"some_arg","message":{"en":"some other really long message","nl":"een boodschap in een andere taal"},"other_arg_name":"more args"}}} + ## Table of contents 1. [Special tag renderings](#special-tag-renderings) + * [Using expanded syntax](#using-expanded-syntax) + [all_tags](#all_tags) * [Example usage of all_tags](#example-usage-of-all_tags) + [image_carousel](#image_carousel) @@ -65,10 +80,6 @@ -In a tagrendering, some special values are substituted by an advanced UI-element. This allows advanced features and visualizations to be reused by custom themes or even to query third-party API's. - -General usage is `{func_name()}`, `{func_name(arg, someotherarg)}` or `{func_name(args):cssStyle}`. Note that you _do not_ need to use quotes around your arguments, the comma is enough to separate them. This also implies you cannot use a comma in your args - ### all_tags @@ -87,7 +98,7 @@ General usage is `{func_name()}`, `{func_name(arg, someotherarg)}` or `{func_nam name | default | description ------ | --------- | ------------- -image key/prefix (multiple values allowed if comma-seperated) | image,mapillary,image,wikidata,wikimedia_commons,image,image | The keys given to the images, e.g. if image is given, the first picture URL will be added as image, the second as image:0, the third as image:1, etc... +image_key | image,mapillary,image,wikidata,wikimedia_commons,image,image | The keys given to the images, e.g. if image is given, the first picture URL will be added as image, the second as image:0, the third as image:1, etc... Multiple values are allowed if ';'-separated #### Example usage of image_carousel @@ -312,11 +323,12 @@ icon | ./assets/svg/addSmall.svg | A nice icon to show in the button snap_onto_layers | _undefined_ | If a way of the given layer(s) is closeby, will snap the new point onto this way (similar as preset might snap). To show multiple layers to snap onto, use a `;`-seperated list max_snap_distance | 5 | The maximum distance that the imported point will be moved to snap onto a way in an already existing layer (in meters). This is previewed to the contributor, similar to the 'add new point'-action of MapComplete note_id | _undefined_ | If given, this key will be read. The corresponding note on OSM will be closed, stating 'imported' +location_picker | photo | Chooses the background for the precise location picker, options are 'map', 'photo' or 'osmbasedmap' or 'none' if the precise input picker should be disabled #### Example usage of import_button - `{import_button(,,Import this data into OpenStreetMap,./assets/svg/addSmall.svg,,5,)}` + `{import_button(,,Import this data into OpenStreetMap,./assets/svg/addSmall.svg,,5,,photo)}` diff --git a/Docs/TagInfo/mapcomplete_entrances.json b/Docs/TagInfo/mapcomplete_entrances.json index d9962fafd3..c133427845 100644 --- a/Docs/TagInfo/mapcomplete_entrances.json +++ b/Docs/TagInfo/mapcomplete_entrances.json @@ -12,22 +12,22 @@ "tags": [ { "key": "highway", - "description": "The MapComplete theme Entrances has a layer Pedestrain paths showing features with this tag", + "description": "The MapComplete theme Entrances has a layer Pedestrian paths showing features with this tag", "value": "footway" }, { "key": "highway", - "description": "The MapComplete theme Entrances has a layer Pedestrain paths showing features with this tag", + "description": "The MapComplete theme Entrances has a layer Pedestrian paths showing features with this tag", "value": "path" }, { "key": "highway", - "description": "The MapComplete theme Entrances has a layer Pedestrain paths showing features with this tag", + "description": "The MapComplete theme Entrances has a layer Pedestrian paths showing features with this tag", "value": "corridor" }, { "key": "highway", - "description": "The MapComplete theme Entrances has a layer Pedestrain paths showing features with this tag", + "description": "The MapComplete theme Entrances has a layer Pedestrian paths showing features with this tag", "value": "steps" }, { diff --git a/Docs/TagInfo/mapcomplete_hailhydrant.json b/Docs/TagInfo/mapcomplete_hailhydrant.json index 65f073a2fd..8aedd27ba4 100644 --- a/Docs/TagInfo/mapcomplete_hailhydrant.json +++ b/Docs/TagInfo/mapcomplete_hailhydrant.json @@ -1,7 +1,7 @@ { "data_format": 1, "project": { - "name": "MapComplete Hydrants, Extinguishers, Fire stations, and Ambulance stations.", + "name": "MapComplete Hydrants, Extinguishers, Fire stations, and Ambulance stations", "description": "Map to show hydrants, extinguishers, fire stations, and ambulance stations.", "project_url": "https://mapcomplete.osm.be/hailhydrant", "doc_url": "https://github.com/pietervdvn/MapComplete/tree/master/assets/themes/", @@ -12,80 +12,80 @@ "tags": [ { "key": "emergency", - "description": "The MapComplete theme Hydrants, Extinguishers, Fire stations, and Ambulance stations. has a layer Map of hydrants showing features with this tag", + "description": "The MapComplete theme Hydrants, Extinguishers, Fire stations, and Ambulance stations has a layer Map of hydrants showing features with this tag", "value": "fire_hydrant" }, { "key": "colour", - "description": "Layer 'Map of hydrants' shows and asks freeform values for key 'colour' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')" + "description": "Layer 'Map of hydrants' shows and asks freeform values for key 'colour' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')" }, { "key": "colour", - "description": "Layer 'Map of hydrants' shows with a fixed text, namely 'The hydrant color is unknown.' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.') Picking this answer will delete the key colour.", + "description": "Layer 'Map of hydrants' shows with a fixed text, namely 'The hydrant color is unknown.' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations') Picking this answer will delete the key colour.", "value": "" }, { "key": "colour", - "description": "Layer 'Map of hydrants' shows colour=yellow with a fixed text, namely 'The hydrant color is yellow.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')", + "description": "Layer 'Map of hydrants' shows colour=yellow with a fixed text, namely 'The hydrant color is yellow.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')", "value": "yellow" }, { "key": "colour", - "description": "Layer 'Map of hydrants' shows colour=red with a fixed text, namely 'The hydrant color is red.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')", + "description": "Layer 'Map of hydrants' shows colour=red with a fixed text, namely 'The hydrant color is red.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')", "value": "red" }, { "key": "fire_hydrant:type", - "description": "Layer 'Map of hydrants' shows and asks freeform values for key 'fire_hydrant:type' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')" + "description": "Layer 'Map of hydrants' shows and asks freeform values for key 'fire_hydrant:type' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')" }, { "key": "fire_hydrant:type", - "description": "Layer 'Map of hydrants' shows with a fixed text, namely 'The hydrant type is unknown.' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.') Picking this answer will delete the key fire_hydrant:type.", + "description": "Layer 'Map of hydrants' shows with a fixed text, namely 'The hydrant type is unknown.' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations') Picking this answer will delete the key fire_hydrant:type.", "value": "" }, { "key": "fire_hydrant:type", - "description": "Layer 'Map of hydrants' shows fire_hydrant:type=pillar with a fixed text, namely 'Pillar type.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')", + "description": "Layer 'Map of hydrants' shows fire_hydrant:type=pillar with a fixed text, namely 'Pillar type.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')", "value": "pillar" }, { "key": "fire_hydrant:type", - "description": "Layer 'Map of hydrants' shows fire_hydrant:type=pipe with a fixed text, namely 'Pipe type.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')", + "description": "Layer 'Map of hydrants' shows fire_hydrant:type=pipe with a fixed text, namely 'Pipe type.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')", "value": "pipe" }, { "key": "fire_hydrant:type", - "description": "Layer 'Map of hydrants' shows fire_hydrant:type=wall with a fixed text, namely 'Wall type.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')", + "description": "Layer 'Map of hydrants' shows fire_hydrant:type=wall with a fixed text, namely 'Wall type.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')", "value": "wall" }, { "key": "fire_hydrant:type", - "description": "Layer 'Map of hydrants' shows fire_hydrant:type=underground with a fixed text, namely 'Underground type.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')", + "description": "Layer 'Map of hydrants' shows fire_hydrant:type=underground with a fixed text, namely 'Underground type.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')", "value": "underground" }, { "key": "emergency", - "description": "Layer 'Map of hydrants' shows emergency=fire_hydrant with a fixed text, namely 'The hydrant is (fully or partially) working' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')", + "description": "Layer 'Map of hydrants' shows emergency=fire_hydrant with a fixed text, namely 'The hydrant is (fully or partially) working' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')", "value": "fire_hydrant" }, { "key": "disused:emergency", - "description": "Layer 'Map of hydrants' shows disused:emergency=fire_hydrant with a fixed text, namely 'The hydrant is unavailable' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')", + "description": "Layer 'Map of hydrants' shows disused:emergency=fire_hydrant with a fixed text, namely 'The hydrant is unavailable' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')", "value": "fire_hydrant" }, { "key": "emergency", - "description": "Layer 'Map of hydrants' shows disused:emergency=fire_hydrant with a fixed text, namely 'The hydrant is unavailable' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.') Picking this answer will delete the key emergency.", + "description": "Layer 'Map of hydrants' shows disused:emergency=fire_hydrant with a fixed text, namely 'The hydrant is unavailable' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations') Picking this answer will delete the key emergency.", "value": "" }, { "key": "removed:emergency", - "description": "Layer 'Map of hydrants' shows removed:emergency=fire_hydrant with a fixed text, namely 'The hydrant has been removed' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')", + "description": "Layer 'Map of hydrants' shows removed:emergency=fire_hydrant with a fixed text, namely 'The hydrant has been removed' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')", "value": "fire_hydrant" }, { "key": "emergency", - "description": "Layer 'Map of hydrants' shows removed:emergency=fire_hydrant with a fixed text, namely 'The hydrant has been removed' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.') Picking this answer will delete the key emergency.", + "description": "Layer 'Map of hydrants' shows removed:emergency=fire_hydrant with a fixed text, namely 'The hydrant has been removed' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations') Picking this answer will delete the key emergency.", "value": "" }, { @@ -106,21 +106,21 @@ }, { "key": "emergency", - "description": "The MapComplete theme Hydrants, Extinguishers, Fire stations, and Ambulance stations. has a layer Map of fire extinguishers. showing features with this tag", + "description": "The MapComplete theme Hydrants, Extinguishers, Fire stations, and Ambulance stations has a layer Map of fire extinguishers. showing features with this tag", "value": "fire_extinguisher" }, { "key": "location", - "description": "Layer 'Map of fire extinguishers.' shows and asks freeform values for key 'location' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')" + "description": "Layer 'Map of fire extinguishers.' shows and asks freeform values for key 'location' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')" }, { "key": "location", - "description": "Layer 'Map of fire extinguishers.' shows location=indoor with a fixed text, namely 'Found indoors.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')", + "description": "Layer 'Map of fire extinguishers.' shows location=indoor with a fixed text, namely 'Found indoors.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')", "value": "indoor" }, { "key": "location", - "description": "Layer 'Map of fire extinguishers.' shows location=outdoor with a fixed text, namely 'Found outdoors.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')", + "description": "Layer 'Map of fire extinguishers.' shows location=outdoor with a fixed text, namely 'Found outdoors.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')", "value": "outdoor" }, { @@ -141,57 +141,57 @@ }, { "key": "amenity", - "description": "The MapComplete theme Hydrants, Extinguishers, Fire stations, and Ambulance stations. has a layer Map of fire stations showing features with this tag", + "description": "The MapComplete theme Hydrants, Extinguishers, Fire stations, and Ambulance stations has a layer Map of fire stations showing features with this tag", "value": "fire_station" }, { "key": "name", - "description": "Layer 'Map of fire stations' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')" + "description": "Layer 'Map of fire stations' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')" }, { "key": "addr:street", - "description": "Layer 'Map of fire stations' shows and asks freeform values for key 'addr:street' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')" + "description": "Layer 'Map of fire stations' shows and asks freeform values for key 'addr:street' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')" }, { "key": "addr:place", - "description": "Layer 'Map of fire stations' shows and asks freeform values for key 'addr:place' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')" + "description": "Layer 'Map of fire stations' shows and asks freeform values for key 'addr:place' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')" }, { "key": "operator", - "description": "Layer 'Map of fire stations' shows and asks freeform values for key 'operator' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')" + "description": "Layer 'Map of fire stations' shows and asks freeform values for key 'operator' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')" }, { "key": "operator", - "description": "Layer 'Map of fire stations' shows operator=Bureau of Fire Protection&operator:type=government with a fixed text, namely 'Bureau of Fire Protection' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')", + "description": "Layer 'Map of fire stations' shows operator=Bureau of Fire Protection&operator:type=government with a fixed text, namely 'Bureau of Fire Protection' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')", "value": "Bureau of Fire Protection" }, { "key": "operator:type", - "description": "Layer 'Map of fire stations' shows operator=Bureau of Fire Protection&operator:type=government with a fixed text, namely 'Bureau of Fire Protection' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')", + "description": "Layer 'Map of fire stations' shows operator=Bureau of Fire Protection&operator:type=government with a fixed text, namely 'Bureau of Fire Protection' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')", "value": "government" }, { "key": "operator:type", - "description": "Layer 'Map of fire stations' shows and asks freeform values for key 'operator:type' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')" + "description": "Layer 'Map of fire stations' shows and asks freeform values for key 'operator:type' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')" }, { "key": "operator:type", - "description": "Layer 'Map of fire stations' shows operator:type=government with a fixed text, namely 'The station is operated by the government.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')", + "description": "Layer 'Map of fire stations' shows operator:type=government with a fixed text, namely 'The station is operated by the government.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')", "value": "government" }, { "key": "operator:type", - "description": "Layer 'Map of fire stations' shows operator:type=community with a fixed text, namely 'The station is operated by a community-based, or informal organization.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')", + "description": "Layer 'Map of fire stations' shows operator:type=community with a fixed text, namely 'The station is operated by a community-based, or informal organization.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')", "value": "community" }, { "key": "operator:type", - "description": "Layer 'Map of fire stations' shows operator:type=ngo with a fixed text, namely 'The station is operated by a formal group of volunteers.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')", + "description": "Layer 'Map of fire stations' shows operator:type=ngo with a fixed text, namely 'The station is operated by a formal group of volunteers.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')", "value": "ngo" }, { "key": "operator:type", - "description": "Layer 'Map of fire stations' shows operator:type=private with a fixed text, namely 'The station is privately operated.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')", + "description": "Layer 'Map of fire stations' shows operator:type=private with a fixed text, namely 'The station is privately operated.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')", "value": "private" }, { @@ -212,47 +212,47 @@ }, { "key": "emergency", - "description": "The MapComplete theme Hydrants, Extinguishers, Fire stations, and Ambulance stations. has a layer Map of ambulance stations showing features with this tag", + "description": "The MapComplete theme Hydrants, Extinguishers, Fire stations, and Ambulance stations has a layer Map of ambulance stations showing features with this tag", "value": "ambulance_station" }, { "key": "name", - "description": "Layer 'Map of ambulance stations' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')" + "description": "Layer 'Map of ambulance stations' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')" }, { "key": "addr:street", - "description": "Layer 'Map of ambulance stations' shows and asks freeform values for key 'addr:street' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')" + "description": "Layer 'Map of ambulance stations' shows and asks freeform values for key 'addr:street' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')" }, { "key": "addr:place", - "description": "Layer 'Map of ambulance stations' shows and asks freeform values for key 'addr:place' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')" + "description": "Layer 'Map of ambulance stations' shows and asks freeform values for key 'addr:place' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')" }, { "key": "operator", - "description": "Layer 'Map of ambulance stations' shows and asks freeform values for key 'operator' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')" + "description": "Layer 'Map of ambulance stations' shows and asks freeform values for key 'operator' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')" }, { "key": "operator:type", - "description": "Layer 'Map of ambulance stations' shows and asks freeform values for key 'operator:type' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')" + "description": "Layer 'Map of ambulance stations' shows and asks freeform values for key 'operator:type' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')" }, { "key": "operator:type", - "description": "Layer 'Map of ambulance stations' shows operator:type=government with a fixed text, namely 'The station is operated by the government.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')", + "description": "Layer 'Map of ambulance stations' shows operator:type=government with a fixed text, namely 'The station is operated by the government.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')", "value": "government" }, { "key": "operator:type", - "description": "Layer 'Map of ambulance stations' shows operator:type=community with a fixed text, namely 'The station is operated by a community-based, or informal organization.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')", + "description": "Layer 'Map of ambulance stations' shows operator:type=community with a fixed text, namely 'The station is operated by a community-based, or informal organization.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')", "value": "community" }, { "key": "operator:type", - "description": "Layer 'Map of ambulance stations' shows operator:type=ngo with a fixed text, namely 'The station is operated by a formal group of volunteers.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')", + "description": "Layer 'Map of ambulance stations' shows operator:type=ngo with a fixed text, namely 'The station is operated by a formal group of volunteers.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')", "value": "ngo" }, { "key": "operator:type", - "description": "Layer 'Map of ambulance stations' shows operator:type=private with a fixed text, namely 'The station is privately operated.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations.')", + "description": "Layer 'Map of ambulance stations' shows operator:type=private with a fixed text, namely 'The station is privately operated.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')", "value": "private" }, { diff --git a/Docs/TagInfo/mapcomplete_personal.json b/Docs/TagInfo/mapcomplete_personal.json index 8dbda3dd80..91d6a0cbd9 100644 --- a/Docs/TagInfo/mapcomplete_personal.json +++ b/Docs/TagInfo/mapcomplete_personal.json @@ -5391,22 +5391,22 @@ }, { "key": "highway", - "description": "The MapComplete theme Personal theme has a layer Pedestrain paths showing features with this tag", + "description": "The MapComplete theme Personal theme has a layer Pedestrian paths showing features with this tag", "value": "footway" }, { "key": "highway", - "description": "The MapComplete theme Personal theme has a layer Pedestrain paths showing features with this tag", + "description": "The MapComplete theme Personal theme has a layer Pedestrian paths showing features with this tag", "value": "path" }, { "key": "highway", - "description": "The MapComplete theme Personal theme has a layer Pedestrain paths showing features with this tag", + "description": "The MapComplete theme Personal theme has a layer Pedestrian paths showing features with this tag", "value": "corridor" }, { "key": "highway", - "description": "The MapComplete theme Personal theme has a layer Pedestrain paths showing features with this tag", + "description": "The MapComplete theme Personal theme has a layer Pedestrian paths showing features with this tag", "value": "steps" }, { @@ -5608,6 +5608,14 @@ "description": "Layer 'Playgrounds' shows access=private with a fixed text, namely 'Not accessible' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", "value": "private" }, + { + "key": "website", + "description": "Layer 'Playgrounds' shows and asks freeform values for key 'website' (in the MapComplete.osm.be theme 'Personal theme')" + }, + { + "key": "contact:website", + "description": "Layer 'Playgrounds' shows contact:website~^..*$ with a fixed text, namely '{contact:website}' (in the MapComplete.osm.be theme 'Personal theme')" + }, { "key": "email", "description": "Layer 'Playgrounds' shows and asks freeform values for key 'email' (in the MapComplete.osm.be theme 'Personal theme')" diff --git a/Docs/TagInfo/mapcomplete_playgrounds.json b/Docs/TagInfo/mapcomplete_playgrounds.json index e36d61e10b..a36e73f08c 100644 --- a/Docs/TagInfo/mapcomplete_playgrounds.json +++ b/Docs/TagInfo/mapcomplete_playgrounds.json @@ -122,6 +122,14 @@ "description": "Layer 'Playgrounds' shows access=private with a fixed text, namely 'Not accessible' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Playgrounds')", "value": "private" }, + { + "key": "website", + "description": "Layer 'Playgrounds' shows and asks freeform values for key 'website' (in the MapComplete.osm.be theme 'Playgrounds')" + }, + { + "key": "contact:website", + "description": "Layer 'Playgrounds' shows contact:website~^..*$ with a fixed text, namely '{contact:website}' (in the MapComplete.osm.be theme 'Playgrounds')" + }, { "key": "email", "description": "Layer 'Playgrounds' shows and asks freeform values for key 'email' (in the MapComplete.osm.be theme 'Playgrounds')" diff --git a/Docs/Tools/GenerateSeries.ts b/Docs/Tools/GenerateSeries.ts index 1c0a4d0432..ca68ff1ded 100644 --- a/Docs/Tools/GenerateSeries.ts +++ b/Docs/Tools/GenerateSeries.ts @@ -181,6 +181,9 @@ class ChangesetDataTools { cs.properties.metadata.host = new URL(cs.properties.metadata.host).host } catch (e) { + } + if(cs.properties.metadata["answer"] > 100){ + console.log("Lots of answers for https://osm.org/changeset/"+cs.id) } return cs } diff --git a/Docs/URL_Parameters.md b/Docs/URL_Parameters.md index c1eb483760..de23e49552 100644 --- a/Docs/URL_Parameters.md +++ b/Docs/URL_Parameters.md @@ -9,6 +9,8 @@ 1. [URL-parameters and URL-hash](#url-parameters-and-url-hash) - [What is a URL parameter?](#what-is-a-url-parameter) + - [language](#language) + - [fs-translation-mode](#fs-translation-mode) - [fs-userbadge](#fs-userbadge) - [fs-search](#fs-search) - [fs-background](#fs-background) @@ -60,6 +62,20 @@ Finally, the URL-hash is the part after the `#`. It is `node/1234` in this case. + language +---------- + + The language to display mapcomplete in. Will be ignored in case a logged-in-user did set their language before. If the specified language does not exist, it will default to the first language in the theme. No default value set + + + + fs-translation-mode +--------------------- + + If set, will show a translation button next to every string. The default value is _false_ + + + fs-userbadge -------------- diff --git a/Logic/Actors/GeoLocationHandler.ts b/Logic/Actors/GeoLocationHandler.ts index 7d3aca2c31..8eba88e44d 100644 --- a/Logic/Actors/GeoLocationHandler.ts +++ b/Logic/Actors/GeoLocationHandler.ts @@ -5,6 +5,7 @@ import {VariableUiElement} from "../../UI/Base/VariableUIElement"; import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"; import {QueryParameters} from "../Web/QueryParameters"; import FeatureSource from "../FeatureSource/FeatureSource"; +import {BBox} from "../BBox"; export interface GeoLocationPointProperties { id: "gps", @@ -20,7 +21,7 @@ export interface GeoLocationPointProperties { export default class GeoLocationHandler extends VariableUiElement { - private readonly currentLocation: FeatureSource + private readonly currentLocation?: FeatureSource /** * Wether or not the geolocation is active, aka the user requested the current location @@ -71,7 +72,7 @@ export default class GeoLocationHandler extends VariableUiElement { constructor( state: { selectedElement: UIEventSource; - currentUserLocation: FeatureSource, + currentUserLocation?: FeatureSource, leafletMap: UIEventSource, layoutToUse: LayoutConfig, featureSwitchGeolocation: UIEventSource @@ -217,14 +218,14 @@ export default class GeoLocationHandler extends VariableUiElement { } } - self.currentLocation.features.setData([{feature, freshness: new Date()}]) + self.currentLocation?.features?.setData([{feature, freshness: new Date()}]) const timeSinceRequest = (new Date().getTime() - (self._lastUserRequest?.getTime() ?? 0)) / 1000; if (timeSinceRequest < 30) { - self.MoveToCurrentLoction(16); + self.MoveToCurrentLocation(16); } else if (self._isLocked.data) { - self.MoveToCurrentLoction(); + self.MoveToCurrentLocation(); } }); @@ -235,9 +236,13 @@ export default class GeoLocationHandler extends VariableUiElement { const self = this; if (self._isActive.data) { - self.MoveToCurrentLoction(16); + self.MoveToCurrentLocation(16); return; } + + if(typeof navigator === "undefined"){ + return + } try { navigator?.permissions @@ -264,7 +269,57 @@ export default class GeoLocationHandler extends VariableUiElement { } } - private MoveToCurrentLoction(targetZoom?: number) { + /** + * Moves to the currently loaded location. + * + * // Should move to any location + * let resultingLocation = undefined + * let resultingzoom = 1 + * const state = { + * selectedElement: new UIEventSource(undefined); + * currentUserLocation: undefined , + * leafletMap: new UIEventSource({getZoom: () => resultingzoom; setView: (loc, zoom) => {resultingLocation = loc; resultingzoom = zoom}), + * layoutToUse: new LayoutConfig({ + * id: 'test', + * title: {"en":"test"} + * description: "A testing theme", + * layers: [] + * }), + * featureSwitchGeolocation : new UIEventSource(true) + * } + * const handler = new GeoLocationHandler(state) + * handler._currentGPSLocation.setData( {latitude : 51.3, longitude: 4.1}) + * handler.MoveToCurrentLocation() + * resultingLocation // => [51.3, 4.1] + * handler._currentGPSLocation.setData( {latitude : 60, longitude: 60) // out of bounds + * handler.MoveToCurrentLocation() + * resultingLocation // => [60, 60] + * + * // should refuse to move if out of bounds + * let resultingLocation = undefined + * let resultingzoom = 1 + * const state = { + * selectedElement: new UIEventSource(undefined); + * currentUserLocation: undefined , + * leafletMap: new UIEventSource({getZoom: () => resultingzoom; setView: (loc, zoom) => {resultingLocation = loc; resultingzoom = zoom}), + * layoutToUse: new LayoutConfig({ + * id: 'test', + * title: {"en":"test"} + * "lockLocation": [ [ 2.1, 50.4], [6.4, 51.54 ]], + * description: "A testing theme", + * layers: [] + * }), + * featureSwitchGeolocation : new UIEventSource(true) + * } + * const handler = new GeoLocationHandler(state) + * handler._currentGPSLocation.setData( {latitude : 51.3, longitude: 4.1}) + * handler.MoveToCurrentLocation() + * resultingLocation // => [51.3, 4.1] + * handler._currentGPSLocation.setData( {latitude : 60, longitude: 60) // out of bounds + * handler.MoveToCurrentLocation() + * resultingLocation // => [51.3, 4.1] + */ + private MoveToCurrentLocation(targetZoom?: number) { const location = this._currentGPSLocation.data; this._lastUserRequest = undefined; @@ -282,11 +337,7 @@ export default class GeoLocationHandler extends VariableUiElement { if (b) { if (b !== true) { // B is an array with our locklocation - inRange = - b[0][0] <= location.latitude && - location.latitude <= b[1][0] && - b[0][1] <= location.longitude && - location.longitude <= b[1][1]; + inRange = new BBox(b).contains([location.longitude, location.latitude]) } } if (!inRange) { @@ -312,7 +363,7 @@ export default class GeoLocationHandler extends VariableUiElement { return ""; } if (this._currentGPSLocation.data !== undefined) { - this.MoveToCurrentLoction(16); + this.MoveToCurrentLocation(16); } if (self._isActive.data) { diff --git a/Logic/ElementStorage.ts b/Logic/ElementStorage.ts index b64ac18efc..1ab5dc9bc1 100644 --- a/Logic/ElementStorage.ts +++ b/Logic/ElementStorage.ts @@ -49,6 +49,29 @@ export class ElementStorage { return this._elements.has(id); } + addAlias(oldId: string, newId: string){ + if (newId === undefined) { + // We removed the node/way/relation with type 'type' and id 'oldId' on openstreetmap! + const element = this.getEventSourceById(oldId); + element.data._deleted = "yes" + element.ping(); + return; + } + + if (oldId == newId) { + return undefined; + } + const element = this.getEventSourceById( oldId); + if (element === undefined) { + // Element to rewrite not found, probably a node or relation that is not rendered + return undefined + } + element.data.id = newId; + this.addElementById(newId, element); + this.ContainingFeatures.set(newId, this.ContainingFeatures.get( oldId)) + element.ping(); + } + private addOrGetById(elementId: string, newProperties: any): UIEventSource { if (!this._elements.has(elementId)) { const eventSource = new UIEventSource(newProperties, "tags of " + elementId); diff --git a/Logic/Osm/Actions/ChangeDescription.ts b/Logic/Osm/Actions/ChangeDescription.ts index 42df3f4a04..1346e62011 100644 --- a/Logic/Osm/Actions/ChangeDescription.ts +++ b/Logic/Osm/Actions/ChangeDescription.ts @@ -71,6 +71,110 @@ export interface ChangeDescription { export class ChangeDescriptionTools { + /** + * Rewrites all the ids in a changeDescription + * + * // should rewrite the id of the changed object + * const change = { + * id: -1234, + * type: "node", + * meta:{ + * theme:"test", + * changeType: "answer" + * }, + * tags:[ + * { + * k: "key", + * v: "value" + * } + * ] + * } + * } + * const mapping = new Map([["node/-1234", "node/42"]]) + * const rewritten = ChangeDescriptionTools.rewriteIds(change, mapping) + * rewritten.id // => 42 + * + * // should rewrite ids in nodes of a way + * const change = { + * type: "way", + * id: 789, + * changes: { + * nodes: [-1, -2, -3, 68453], + * coordinates: [] + * }, + * meta:{ + * theme:"test", + * changeType: "create" + * } + * } + * const mapping = new Map([["node/-1", "node/42"],["node/-2", "node/43"],["node/-3", "node/44"]]) + * const rewritten = ChangeDescriptionTools.rewriteIds(change, mapping) + * rewritten.id // => 789 + * rewritten.changes["nodes"] // => [42,43,44, 68453] + * + * // should rewrite ids in relationship members + * const change = { + * type: "way", + * id: 789, + * changes: { + * members: [{type: "way", ref: -1, role: "outer"},{type: "way", ref: 48, role: "outer"}], + * }, + * meta:{ + * theme:"test", + * changeType: "create" + * } + * } + * const mapping = new Map([["way/-1", "way/42"],["node/-2", "node/43"],["node/-3", "node/44"]]) + * const rewritten = ChangeDescriptionTools.rewriteIds(change, mapping) + * rewritten.id // => 789 + * rewritten.changes["members"] // => [{type: "way", ref: 42, role: "outer"},{type: "way", ref: 48, role: "outer"}] + * + */ + public static rewriteIds(change: ChangeDescription, mappings: Map): ChangeDescription { + const key = change.type + "/" + change.id + + const wayHasChangedNode = ((change.changes ?? {})["nodes"] ?? []).some(id => mappings.has("node/" + id)); + const relationHasChangedMembers = ((change.changes ?? {})["members"] ?? []) + .some((obj:{type: string, ref: number}) => mappings.has(obj.type+"/" + obj.ref)); + + const hasSomeChange = mappings.has(key) + || wayHasChangedNode || relationHasChangedMembers + if(hasSomeChange){ + change = {...change} + } + + if (mappings.has(key)) { + const [_, newId] = mappings.get(key).split("/") + change.id = Number.parseInt(newId) + } + if(wayHasChangedNode){ + change.changes = {...change.changes} + change.changes["nodes"] = change.changes["nodes"].map(id => { + const key = "node/"+id + if(!mappings.has(key)){ + return id + } + const [_, newId] = mappings.get(key).split("/") + return Number.parseInt(newId) + }) + } + if(relationHasChangedMembers){ + change.changes = {...change.changes} + change.changes["members"] = change.changes["members"].map( + (obj:{type: string, ref: number}) => { + const key = obj.type+"/"+obj.ref; + if(!mappings.has(key)){ + return obj + } + const [_, newId] = mappings.get(key).split("/") + return {...obj, ref: Number.parseInt(newId)} + } + ) + } + + return change + } + public static getGeojsonGeometry(change: ChangeDescription): any { switch (change.type) { case "node": diff --git a/Logic/Osm/Actions/CreateNewNodeAction.ts b/Logic/Osm/Actions/CreateNewNodeAction.ts index 844463ec11..7a545c7e01 100644 --- a/Logic/Osm/Actions/CreateNewNodeAction.ts +++ b/Logic/Osm/Actions/CreateNewNodeAction.ts @@ -51,22 +51,6 @@ export default class CreateNewNodeAction extends OsmCreateAction { } } - public static registerIdRewrites(mappings: Map) { - const toAdd: [string, number][] = [] - - this.previouslyCreatedPoints.forEach((oldId, key) => { - if (!mappings.has("node/" + oldId)) { - return; - } - - const newId = Number(mappings.get("node/" + oldId).substr("node/".length)) - toAdd.push([key, newId]) - }) - for (const [key, newId] of toAdd) { - CreateNewNodeAction.previouslyCreatedPoints.set(key, newId) - } - } - async CreateChangeDescriptions(changes: Changes): Promise { if (this._reusePreviouslyCreatedPoint) { diff --git a/Logic/Osm/Changes.ts b/Logic/Osm/Changes.ts index 362d12853b..17b93b9ae9 100644 --- a/Logic/Osm/Changes.ts +++ b/Logic/Osm/Changes.ts @@ -2,7 +2,7 @@ import {OsmNode, OsmObject, OsmRelation, OsmWay} from "./OsmObject"; import {UIEventSource} from "../UIEventSource"; import Constants from "../../Models/Constants"; import OsmChangeAction from "./Actions/OsmChangeAction"; -import {ChangeDescription} from "./Actions/ChangeDescription"; +import {ChangeDescription, ChangeDescriptionTools} from "./Actions/ChangeDescription"; import {Utils} from "../../Utils"; import {LocalStorageSource} from "../Web/LocalStorageSource"; import SimpleMetaTagger from "../SimpleMetaTagger"; @@ -142,11 +142,7 @@ export class Changes { this.allChanges.data.push(...changes) this.allChanges.ping() } - - public registerIdRewrites(mappings: Map): void { - CreateNewNodeAction.registerIdRewrites(mappings) - } - + private calculateDistanceToChanges(change: OsmChangeAction, changeDescriptions: ChangeDescription[]) { const locations = this.historicalUserLocations?.features?.data @@ -226,17 +222,6 @@ export class Changes { } console.log("Got the fresh objects!", osmObjects, "pending: ", pending) - const changes: { - newObjects: OsmObject[], - modifiedObjects: OsmObject[] - deletedObjects: OsmObject[] - } = self.CreateChangesetObjects(pending, osmObjects) - if (changes.newObjects.length + changes.deletedObjects.length + changes.modifiedObjects.length === 0) { - console.log("No changes to be made") - return true - } - - const perType = Array.from( Utils.Hist(pending.filter(descr => descr.meta.changeType !== undefined && descr.meta.changeType !== null) .map(descr => descr.meta.changeType)), ([key, count]) => ( @@ -303,7 +288,19 @@ export class Changes { ] await this._changesetHandler.UploadChangeset( - (csId) => Changes.createChangesetFor("" + csId, changes), + (csId, remappings) =>{ + if(remappings.size > 0){ + console.log("Rewriting pending changes from", pending, "with", remappings) + pending = pending.map(ch => ChangeDescriptionTools.rewriteIds(ch, remappings)) + console.log("Result is", pending) + } + const changes: { + newObjects: OsmObject[], + modifiedObjects: OsmObject[] + deletedObjects: OsmObject[] + } = self.CreateChangesetObjects(pending, osmObjects) + return Changes.createChangesetFor("" + csId, changes) + }, metatags, openChangeset ) diff --git a/Logic/Osm/ChangesetHandler.ts b/Logic/Osm/ChangesetHandler.ts index d96ec14b9c..13723c4491 100644 --- a/Logic/Osm/ChangesetHandler.ts +++ b/Logic/Osm/ChangesetHandler.ts @@ -23,6 +23,14 @@ export class ChangesetHandler { private readonly auth: any; private readonly backend: string; + + /** + * Contains previously rewritten IDs + * @private + */ + private readonly _remappings = new Map() + + /** * Use 'osmConnection.CreateChangesetHandler' instead * @param dryRun @@ -50,6 +58,7 @@ export class ChangesetHandler { } + /** * Creates a new list which contains every key at most once * @@ -104,7 +113,7 @@ export class ChangesetHandler { * */ public async UploadChangeset( - generateChangeXML: (csid: number) => string, + generateChangeXML: (csid: number, remappings: Map) => string, extraMetaTags: ChangesetTag[], openChangeset: UIEventSource): Promise { @@ -120,7 +129,7 @@ export class ChangesetHandler { this.userDetails.ping(); } if (this._dryRun.data) { - const changesetXML = generateChangeXML(123456); + const changesetXML = generateChangeXML(123456, this._remappings); console.log("Metatags are", extraMetaTags) console.log(changesetXML); return; @@ -131,7 +140,7 @@ export class ChangesetHandler { try { const csId = await this.OpenChangeset(extraMetaTags) openChangeset.setData(csId); - const changeset = generateChangeXML(csId); + const changeset = generateChangeXML(csId, this._remappings); console.trace("Opened a new changeset (openChangeset.data is undefined):", changeset); const changes = await this.UploadChange(csId, changeset) const hasSpecialMotivationChanges = ChangesetHandler.rewriteMetaTags(extraMetaTags, changes) @@ -162,7 +171,7 @@ export class ChangesetHandler { const rewritings = await this.UploadChange( csId, - generateChangeXML(csId)) + generateChangeXML(csId, this._remappings)) const rewrittenTags = this.RewriteTagsOf(extraMetaTags, rewritings, oldChangesetMeta) await this.UpdateTags(csId, rewrittenTags) @@ -239,57 +248,67 @@ export class ChangesetHandler { } - private handleIdRewrite(node: any, type: string): [string, string] { + /** + * Updates the id in the AllElements store, returns the new ID + * @param node: the XML-element, e.g. + * @param type + * @private + */ + private static parseIdRewrite(node: any, type: string): [string, string] { const oldId = parseInt(node.attributes.old_id.value); if (node.attributes.new_id === undefined) { - // We just removed this point! - const element = this.allElements.getEventSourceById("node/" + oldId); - element.data._deleted = "yes" - element.ping(); - return; + return [type+"/"+oldId, undefined]; } const newId = parseInt(node.attributes.new_id.value); + // The actual mapping const result: [string, string] = [type + "/" + oldId, type + "/" + newId] - if (!(oldId !== undefined && newId !== undefined && - !isNaN(oldId) && !isNaN(newId))) { + if(oldId === newId){ return undefined; } - if (oldId == newId) { - return undefined; - } - const element = this.allElements.getEventSourceById("node/" + oldId); - if (element === undefined) { - // Element to rewrite not found, probably a node or relation that is not rendered - return undefined - } - element.data.id = type + "/" + newId; - this.allElements.addElementById(type + "/" + newId, element); - this.allElements.ContainingFeatures.set(type + "/" + newId, this.allElements.ContainingFeatures.get(type + "/" + oldId)) - element.ping(); return result; } + /** + * Given a diff-result XML of the form + * + * + * + * , + * will: + * + * - create a mapping `{'node/-1' --> "node/9650458521", 'way/-2' --> "way/9650458521"} + * - Call this.changes.registerIdRewrites + * - Call handleIdRewrites as needed + * @param response + * @private + */ private parseUploadChangesetResponse(response: XMLDocument): Map { const nodes = response.getElementsByTagName("node"); - const mappings = new Map() + const mappings : [string, string][]= [] for (const node of Array.from(nodes)) { - const mapping = this.handleIdRewrite(node, "node") + const mapping = ChangesetHandler.parseIdRewrite(node, "node") if (mapping !== undefined) { - mappings.set(mapping[0], mapping[1]) + mappings.push(mapping) } } const ways = response.getElementsByTagName("way"); for (const way of Array.from(ways)) { - const mapping = this.handleIdRewrite(way, "way") + const mapping = ChangesetHandler.parseIdRewrite(way, "way") if (mapping !== undefined) { - mappings.set(mapping[0], mapping[1]) + mappings.push(mapping) } } - this.changes.registerIdRewrites(mappings) - return mappings + for (const mapping of mappings) { + const [oldId, newId] = mapping + this.allElements.addAlias(oldId, newId); + if(newId !== undefined) { + this._remappings.set(mapping[0], mapping[1]) + } + } + return new Map(mappings) } @@ -335,7 +354,6 @@ export class ChangesetHandler { tags: ChangesetTag[]) { tags = ChangesetHandler.removeDuplicateMetaTags(tags) - console.trace("Updating tags of " + csId) const self = this; return new Promise(function (resolve, reject) { @@ -351,7 +369,7 @@ export class ChangesetHandler { ``].join("") }, function (err, response) { if (response === undefined) { - console.log("err", err); + console.error("Updating the tags of changeset "+csId+" failed:", err); reject(err) } else { resolve(response); @@ -397,7 +415,7 @@ export class ChangesetHandler { ``].join("") }, function (err, response) { if (response === undefined) { - console.log("err", err); + console.error("Opening a changeset failed:", err); reject(err) } else { resolve(Number(response)); @@ -421,7 +439,7 @@ export class ChangesetHandler { content: changesetXML }, function (err, response) { if (response == null) { - console.log("err", err); + console.error("Uploading an actual change failed", err); reject(err); } const changes = self.parseUploadChangesetResponse(response); diff --git a/Logic/State/UserRelatedState.ts b/Logic/State/UserRelatedState.ts index 6d6f8ae892..d18f536187 100644 --- a/Logic/State/UserRelatedState.ts +++ b/Logic/State/UserRelatedState.ts @@ -11,7 +11,8 @@ import SelectedElementTagsUpdater from "../Actors/SelectedElementTagsUpdater"; import {Changes} from "../Osm/Changes"; import ChangeToElementsActor from "../Actors/ChangeToElementsActor"; import PendingChangesUploader from "../Actors/PendingChangesUploader"; - +import * as translators from "../../assets/translators.json" + /** * The part of the state which keeps track of user-related stuff, e.g. the OSM-connection, * which layers they enabled, ... @@ -36,6 +37,8 @@ export default class UserRelatedState extends ElementsState { */ public favouriteLayers: UIEventSource; + public readonly isTranslator : UIEventSource; + constructor(layoutToUse: LayoutConfig, options?: { attemptLogin: true | boolean }) { super(layoutToUse); @@ -50,14 +53,25 @@ export default class UserRelatedState extends ElementsState { osmConfiguration: <'osm' | 'osm-test'>this.featureSwitchApiURL.data, attemptLogin: options?.attemptLogin }) - - + this.isTranslator = this.osmConnection.userDetails.map(ud => { + if(!ud.loggedIn){ + return false; + } + const name= ud.name.toLowerCase().replace(/\s+/g, '') + return translators.contributors.some(c => c.contributor.toLowerCase().replace(/\s+/g, '') === name) + }) + this.isTranslator.addCallbackAndRunD(ud => { + if(ud){ + Locale.showLinkToWeblate.setData(true) + } + }); + this.changes = new Changes(this, layoutToUse?.isLeftRightSensitive() ?? false) new ChangeToElementsActor(this.changes, this.allElements) new PendingChangesUploader(this.changes, this.selectedElement); - + this.mangroveIdentity = new MangroveIdentity( this.osmConnection.GetLongPreference("identity", "mangrove") ); @@ -108,6 +122,9 @@ export default class UserRelatedState extends ElementsState { if (layoutToUse === undefined) { return; } + if(Locale.showLinkToWeblate.data){ + return true; // Disable auto switching as we are in translators mode + } if (this.layoutToUse.language.indexOf(currentLanguage) < 0) { console.log( "Resetting language to", diff --git a/Logic/Tags/And.ts b/Logic/Tags/And.ts index fa79d3eda0..5a2eecbc9c 100644 --- a/Logic/Tags/And.ts +++ b/Logic/Tags/And.ts @@ -148,12 +148,6 @@ export class And extends TagsFilter { return result; } - AsJson() { - return { - and: this.and.map(a => a.AsJson()) - } - } - optimize(): TagsFilter | boolean { if(this.and.length === 0){ return true diff --git a/Logic/Tags/Or.ts b/Logic/Tags/Or.ts index 07f50629bd..4d3ab20e02 100644 --- a/Logic/Tags/Or.ts +++ b/Logic/Tags/Or.ts @@ -85,12 +85,6 @@ export class Or extends TagsFilter { return result; } - AsJson() { - return { - or: this.or.map(o => o.AsJson()) - } - } - optimize(): TagsFilter | boolean { if(this.or.length === 0){ diff --git a/Logic/Tags/TagUtils.ts b/Logic/Tags/TagUtils.ts index d72008136a..9ff07534f6 100644 --- a/Logic/Tags/TagUtils.ts +++ b/Logic/Tags/TagUtils.ts @@ -11,7 +11,7 @@ import {isRegExp} from "util"; import * as key_counts from "../../assets/key_totals.json" export class TagUtils { - private static keyCounts : {keys: any, tags: any} = key_counts["default"] ?? key_counts + private static keyCounts: { keys: any, tags: any } = key_counts["default"] ?? key_counts private static comparators : [string, (a: number, b: number) => boolean][] = [ @@ -167,9 +167,37 @@ export class TagUtils { return new Tag(tag[0], tag[1]); } + /** + * Returns wether or not a keys is (probably) a valid key. + * + * // should accept common keys + * TagUtils.isValidKey("name") // => true + * TagUtils.isValidKey("image:0") // => true + * TagUtils.isValidKey("alt_name") // => true + * + * // should refuse short keys + * TagUtils.isValidKey("x") // => false + * TagUtils.isValidKey("xy") // => false + * + * // should refuse a string with >255 characters + * let a255 = "" + * for(let i = 0; i < 255; i++) { a255 += "a"; } + * a255.length // => 255 + * TagUtils.isValidKey(a255) // => true + * TagUtils.isValidKey("a"+a255) // => false + * + * // Should refuse unexpected characters + * TagUtils.isValidKey("with space") // => false + * TagUtils.isValidKey("some$type") // => false + * TagUtils.isValidKey("_name") // => false + */ + public static isValidKey(key: string): boolean { + return key.match(/^[a-z][a-z0-9:_]{2,253}[a-z0-9]$/) !== null + } + /** * Parses a tag configuration (a json) into a TagsFilter - * + * * TagUtils.Tag("key=value") // => new Tag("key", "value") * TagUtils.Tag("key=") // => new Tag("key", "") * TagUtils.Tag("key!=") // => new RegexTag("key", "^..*$") @@ -182,6 +210,9 @@ export class TagUtils { * TagUtils.Tag("xyz!~\\[\\]") // => new RegexTag("xyz", /^\[\]$/, true) * TagUtils.Tag("tags~(^|.*;)amenity=public_bookcase($|;.*)") // => new RegexTag("tags", /(^|.*;)amenity=public_bookcase($|;.*)/) * TagUtils.Tag("service:bicycle:.*~~*") // => new RegexTag(/^service:bicycle:.*$/, /^..*$/) + * + * TagUtils.Tag("xyz<5").matchesProperties({xyz: 4}) // => true + * TagUtils.Tag("xyz<5").matchesProperties({xyz: 5}) // => false */ public static Tag(json: AndOrTagConfigJson | string, context: string = ""): TagsFilter { try { @@ -196,7 +227,7 @@ export class TagUtils { * INLINE sort of the given list */ public static sortFilters(filters: TagsFilter [], usePopularity: boolean): void { - filters.sort((a,b) => TagUtils.order(a, b, usePopularity)) + filters.sort((a, b) => TagUtils.order(a, b, usePopularity)) } public static toString(f: TagsFilter, toplevel = true): string { @@ -208,10 +239,10 @@ export class TagUtils { } else { r = f.asHumanString(false, false, {}) } - if(toplevel){ + if (toplevel) { r = r.trim() } - + return r } @@ -232,8 +263,8 @@ export class TagUtils { } throw "At " + context + ": unrecognized tag" } - - + + const tag = json as string; for (const [operator, comparator] of TagUtils.comparators) { if (tag.indexOf(operator) >= 0) { @@ -244,12 +275,19 @@ export class TagUtils { val = new Date(split[1].trim()).getTime() } - const f = (value: string | undefined) => { + const f = (value: string | number | undefined) => { if (value === undefined) { return false; } - let b = Number(value?.trim()) - if (isNaN(b)) { + let b: number + if (typeof value === "number") { + b = value + } else if (typeof b === "string") { + b = Number(value?.trim()) + } else { + b = Number(value) + } + if (isNaN(b) && typeof value === "string") { b = Utils.ParseDate(value).getTime() if (isNaN(b)) { return false @@ -278,8 +316,8 @@ export class TagUtils { split[1] = "..*" } return new RegexTag( - new RegExp("^"+split[0]+"$"), - new RegExp("^"+ split[1]+"$") + new RegExp("^" + split[0] + "$"), + new RegExp("^" + split[1] + "$") ); } if (tag.indexOf("!:=") >= 0) { @@ -343,32 +381,32 @@ export class TagUtils { } private static GetCount(key: string, value?: string) { - if(key === undefined) { + if (key === undefined) { return undefined } const tag = TagUtils.keyCounts.tags[key] - if(tag !== undefined && tag[value] !== undefined) { + if (tag !== undefined && tag[value] !== undefined) { return tag[value] } return TagUtils.keyCounts.keys[key] } - + private static order(a: TagsFilter, b: TagsFilter, usePopularity: boolean): number { const rta = a instanceof RegexTag const rtb = b instanceof RegexTag - if(rta !== rtb) { + if (rta !== rtb) { // Regex tags should always go at the end: these use a lot of computation at the overpass side, avoiding it is better - if(rta) { + if (rta) { return 1 // b < a - }else { + } else { return -1 } } if (a["key"] !== undefined && b["key"] !== undefined) { - if(usePopularity) { + if (usePopularity) { const countA = TagUtils.GetCount(a["key"], a["value"]) const countB = TagUtils.GetCount(b["key"], b["value"]) - if(countA !== undefined && countB !== undefined) { + if (countA !== undefined && countB !== undefined) { return countA - countB } } @@ -392,5 +430,5 @@ export class TagUtils { } return " (" + joined + ") " } - + } \ No newline at end of file diff --git a/Logic/Tags/TagsFilter.ts b/Logic/Tags/TagsFilter.ts index c505fe1174..f3794436f5 100644 --- a/Logic/Tags/TagsFilter.ts +++ b/Logic/Tags/TagsFilter.ts @@ -26,8 +26,6 @@ export abstract class TagsFilter { */ abstract asChange(properties: any): { k: string, v: string }[] - abstract AsJson() ; - /** * Returns an optimized version (or self) of this tagsFilter */ diff --git a/Logic/Web/QueryParameters.ts b/Logic/Web/QueryParameters.ts index 6dc084305a..02a76dce5a 100644 --- a/Logic/Web/QueryParameters.ts +++ b/Logic/Web/QueryParameters.ts @@ -91,8 +91,10 @@ export class QueryParameters { parts.push(encodeURIComponent(key) + "=" + encodeURIComponent(QueryParameters.knownSources[key].data)) } - // Don't pollute the history every time a parameter changes - history.replaceState(null, "", "?" + parts.join("&") + Hash.Current()); + if(!Utils.runningFromConsole){ + // Don't pollute the history every time a parameter changes + history.replaceState(null, "", "?" + parts.join("&") + Hash.Current()); + } } } \ No newline at end of file diff --git a/Models/Constants.ts b/Models/Constants.ts index 8220054fb3..117f31cd01 100644 --- a/Models/Constants.ts +++ b/Models/Constants.ts @@ -2,7 +2,7 @@ import {Utils} from "../Utils"; export default class Constants { - public static vNumber = "0.17.2"; + public static vNumber = "0.18.0"; public static ImgurApiKey = '7070e7167f0a25a' public static readonly mapillary_client_token_v4 = "MLY|4441509239301885|b40ad2d3ea105435bd40c7e76993ae85" diff --git a/Models/Denomination.ts b/Models/Denomination.ts index f3722b661e..45f2e5be26 100644 --- a/Models/Denomination.ts +++ b/Models/Denomination.ts @@ -73,12 +73,25 @@ export class Denomination { * en: "meter" * } * }, "test") - * unit.canonicalValue("42m") // =>"42 m" + * unit.canonicalValue("42m") // =>"42 m" * unit.canonicalValue("42") // =>"42 m" * unit.canonicalValue("42 m") // =>"42 m" * unit.canonicalValue("42 meter") // =>"42 m" * * + * // Should be trimmed if canonical is empty + * const unit = new Denomination({ + * canonicalDenomination: "", + * alternativeDenomination: ["meter","m"], + * 'default': true, + * human: { + * en: "meter" + * } + * }, "test") + * unit.canonicalValue("42m") // =>"42" + * unit.canonicalValue("42") // =>"42" + * unit.canonicalValue("42 m") // =>"42" + * unit.canonicalValue("42 meter") // =>"42" */ public canonicalValue(value: string, actAsDefault?: boolean) : string { if (value === undefined) { @@ -89,9 +102,9 @@ export class Denomination { return null; } if (stripped === "1" && this._canonicalSingular !== undefined) { - return "1 " + this._canonicalSingular + return ("1 " + this._canonicalSingular).trim() } - return stripped + " " + this.canonical; + return (stripped + " " + this.canonical).trim(); } /** diff --git a/Models/ThemeConfig/Conversion/Conversion.ts b/Models/ThemeConfig/Conversion/Conversion.ts index 75f1683f2a..f947ed916e 100644 --- a/Models/ThemeConfig/Conversion/Conversion.ts +++ b/Models/ThemeConfig/Conversion/Conversion.ts @@ -9,27 +9,27 @@ export interface DesugaringContext { export abstract class Conversion { public readonly modifiedAttributes: string[]; - protected readonly doc: string; public readonly name: string - + protected readonly doc: string; + constructor(doc: string, modifiedAttributes: string[] = [], name: string) { this.modifiedAttributes = modifiedAttributes; this.doc = doc + "\n\nModified attributes are\n" + modifiedAttributes.join(", "); - this.name = name + this.name = name } public static strict(fixed: { errors?: string[], warnings?: string[], information?: string[], result?: T }): T { - - fixed.information?.forEach(i => console.log(" ", i)) - const yellow = (s) => "\x1b[33m"+s+"\x1b[0m" - const red = s => '\x1b[31m'+s+'\x1b[0m' - fixed.warnings?.forEach(w => console.warn(red(` `), yellow (w))) - if (fixed?.errors !== undefined && fixed?.errors?.length > 0) { - fixed.errors?.forEach(e => console.error(red(`ERR `+e))) + fixed.information?.forEach(i => console.log(" ", i)) + const yellow = (s) => "\x1b[33m" + s + "\x1b[0m" + const red = s => '\x1b[31m' + s + '\x1b[0m' + fixed.warnings?.forEach(w => console.warn(red(` `), yellow(w))) + + if (fixed?.errors !== undefined && fixed?.errors?.length > 0) { + fixed.errors?.forEach(e => console.error(red(`ERR ` + e))) throw "Detected one or more errors, stopping now" } - + return fixed.result; } @@ -38,43 +38,104 @@ export abstract class Conversion { return DesugaringStep.strict(fixed) } + public andThenF(f: (tout:TOut) => X ): Conversion{ + return new Pipe( + this, + new Pure(f) + ) + } + abstract convert(json: TIn, context: string): { result: TOut, errors?: string[], warnings?: string[], information?: string[] } +} - public convertAll(jsons: TIn[], context: string): { result: TOut[], errors: string[], warnings: string[], information?: string[] } { - if(jsons === undefined || jsons === null){ - throw "convertAll received undefined or null - don't do this (at "+context+")" - } - const result = [] - const errors = [] - const warnings = [] - const information = [] - for (let i = 0; i < jsons.length; i++) { - const json = jsons[i]; - const r = this.convert(json, context + "[" + i + "]") - result.push(r.result) - errors.push(...r.errors ?? []) - warnings.push(...r.warnings ?? []) - information.push(...r.information ?? []) +export abstract class DesugaringStep extends Conversion { + +} + +class Pipe extends Conversion { + private readonly _step0: Conversion; + private readonly _step1: Conversion; + constructor(step0: Conversion, step1: Conversion) { + super("Merges two steps with different types", [], `Pipe(${step0.name}, ${step1.name})`); + this._step0 = step0; + this._step1 = step1; + } + + convert(json: TIn, context: string): { result: TOut; errors?: string[]; warnings?: string[]; information?: string[] } { + + const r0 = this._step0.convert(json, context); + const {result, errors, information, warnings } = r0; + if(result === undefined && errors.length > 0){ + return { + ...r0, + result: undefined + }; } + + const r = this._step1.convert(result, context); + errors.push(...r.errors) + information.push(...r.information) + warnings.push(...r.warnings) return { - result, + result: r.result, errors, warnings, information } } +} + +class Pure extends Conversion { + private readonly _f: (t: TIn) => TOut; + constructor(f: ((t:TIn) => TOut)) { + super("Wrapper around a pure function",[], "Pure"); + this._f = f; + } + + convert(json: TIn, context: string): { result: TOut; errors?: string[]; warnings?: string[]; information?: string[] } { + return {result: this._f(json)}; + } + +} + +export class Each extends Conversion { + private readonly _step: Conversion; + + constructor(step: Conversion) { + super("Applies the given step on every element of the list", [], "OnEach(" + step.name + ")"); + this._step = step; + } + + convert(values: X[], context: string): { result: Y[]; errors?: string[]; warnings?: string[]; information?: string[] } { + if (values === undefined || values === null) { + return {result: undefined} + } + const information: string[] = [] + const warnings: string[] = [] + const errors: string[] = [] + const step = this._step + const result: Y[] = [] + for (let i = 0; i < values.length; i++) { + const r = step.convert(values[i], context + "[" + i + "]") + information.push(...r.information) + warnings.push(...r.warnings) + errors.push(...r.errors) + result.push(r.result) + } + return { + information, errors, warnings, + result + }; + } } -export abstract class DesugaringStep extends Conversion { -} - -export class OnEvery extends DesugaringStep { +export class On extends DesugaringStep { private readonly key: string; - private readonly step: DesugaringStep; + private readonly step: Conversion; - constructor(key: string, step: DesugaringStep) { - super("Applies " + step.name + " onto every object of the list `key`", [key], "OnEvery("+step.name+")"); + constructor(key: string, step: Conversion) { + super("Applies " + step.name + " onto property `"+key+"`", [key], `On(${key}, ${step.name})`); this.step = step; this.key = key; } @@ -83,47 +144,44 @@ export class OnEvery extends DesugaringStep { json = {...json} const step = this.step const key = this.key; - const r = step.convertAll((json[key]), context + "." + key) + const value: P = json[key] + if (value === undefined || value === null) { + return { result: json }; + } + const r = step.convert(value, context + "." + key) json[key] = r.result return { ...r, result: json, }; + } } -export class OnEveryConcat extends DesugaringStep { - private readonly key: string; - private readonly step: Conversion; +export class Concat extends Conversion { + private readonly _step: Conversion; - constructor(key: string, step: Conversion) { - super(`Applies ${step.name} onto every object of the list \`${key}\`. The results are concatenated and used as new list`, [key], - "OnEvery("+key+").Concat("+step.name+")"); - this.step = step; - this.key = key; + constructor(step: Conversion) { + super("Executes the given step, flattens the resulting list", [], "Concat(" + step.name + ")"); + this._step = step; } - convert(json: T, context: string): { result: T; errors?: string[]; warnings?: string[], information?: string[] } { - json = {...json} - const step = this.step - const key = this.key; - const values = json[key] + convert(values: X[], context: string): { result: T[]; errors?: string[]; warnings?: string[]; information?: string[] } { if (values === undefined || values === null) { // Move on - nothing to see here! return { - result: json, + result: undefined, } } - const r = step.convertAll((values), context + "." + key) - const vals: X[][] = r.result - - json[key] = [].concat(...vals) - + const r = new Each(this._step).convert(values, context) + const vals: T[][] = r.result + + const flattened: T[] = [].concat(...vals) + return { ...r, - result: json, + result: flattened, }; - } } @@ -133,7 +191,7 @@ export class Fuse extends DesugaringStep { constructor(doc: string, ...steps: DesugaringStep[]) { super((doc ?? "") + "This fused pipeline of the following steps: " + steps.map(s => s.name).join(", "), Utils.Dedup([].concat(...steps.map(step => step.modifiedAttributes))), - "Fuse of "+steps.map(s => s.name).join(", ") + "Fuse of " + steps.map(s => s.name).join(", ") ); this.steps = Utils.NoNull(steps); } @@ -144,7 +202,7 @@ export class Fuse extends DesugaringStep { const information = [] for (let i = 0; i < this.steps.length; i++) { const step = this.steps[i]; - let r = step.convert(json, "While running step " +step.name + ": " + context) + let r = step.convert(json, "While running step " + step.name + ": " + context) errors.push(...r.errors ?? []) warnings.push(...r.warnings ?? []) information.push(...r.information ?? []) @@ -169,7 +227,7 @@ export class SetDefault extends DesugaringStep { private readonly _overrideEmptyString: boolean; constructor(key: string, value: any, overrideEmptyString = false) { - super("Sets " + key + " to a default value if undefined", [], "SetDefault of "+key); + super("Sets " + key + " to a default value if undefined", [], "SetDefault of " + key); this.key = key; this.value = value; this._overrideEmptyString = overrideEmptyString; diff --git a/Models/ThemeConfig/Conversion/LegacyJsonConvert.ts b/Models/ThemeConfig/Conversion/LegacyJsonConvert.ts index c1bbcec37d..547f8c57b4 100644 --- a/Models/ThemeConfig/Conversion/LegacyJsonConvert.ts +++ b/Models/ThemeConfig/Conversion/LegacyJsonConvert.ts @@ -2,7 +2,7 @@ import {LayoutConfigJson} from "../Json/LayoutConfigJson"; import {Utils} from "../../../Utils"; import LineRenderingConfigJson from "../Json/LineRenderingConfigJson"; import {LayerConfigJson} from "../Json/LayerConfigJson"; -import {DesugaringStep, Fuse, OnEvery} from "./Conversion"; +import {DesugaringStep, Each, Fuse, On} from "./Conversion"; export class UpdateLegacyLayer extends DesugaringStep { @@ -159,7 +159,7 @@ export class FixLegacyTheme extends Fuse { super( "Fixes a legacy theme to the modern JSON format geared to humans. Syntactic sugars are kept (i.e. no tagRenderings are expandend, no dependencies are automatically gathered)", new UpdateLegacyTheme(), - new OnEvery("layers", new UpdateLegacyLayer()) + new On("layers",new Each( new UpdateLegacyLayer())) ); } } diff --git a/Models/ThemeConfig/Conversion/PrepareLayer.ts b/Models/ThemeConfig/Conversion/PrepareLayer.ts index 79a2eaafe8..8e41251345 100644 --- a/Models/ThemeConfig/Conversion/PrepareLayer.ts +++ b/Models/ThemeConfig/Conversion/PrepareLayer.ts @@ -1,15 +1,18 @@ -import {Conversion, DesugaringContext, Fuse, OnEveryConcat, SetDefault} from "./Conversion"; +import {Concat, Conversion, DesugaringContext, DesugaringStep, Each, Fuse, On, SetDefault} from "./Conversion"; import {LayerConfigJson} from "../Json/LayerConfigJson"; import {TagRenderingConfigJson} from "../Json/TagRenderingConfigJson"; import {Utils} from "../../../Utils"; import RewritableConfigJson from "../Json/RewritableConfigJson"; +import SpecialVisualizations from "../../../UI/SpecialVisualizations"; import Translations from "../../../UI/i18n/Translations"; +import {Translation} from "../../../UI/i18n/Translation"; +import * as tagrenderingconfigmeta from "../../../assets/tagrenderingconfigmeta.json" class ExpandTagRendering extends Conversion { private readonly _state: DesugaringContext; constructor(state: DesugaringContext) { - super("Converts a tagRenderingSpec into the full tagRendering", [], "ExpandTagRendering"); + super("Converts a tagRenderingSpec into the full tagRendering, e.g. by substituting the tagRendering by the shared-question", [], "ExpandTagRendering"); this._state = state; } @@ -135,138 +138,6 @@ class ExpandTagRendering extends Conversion { - - - private _expandSubTagRenderings; - - constructor(state: DesugaringContext) { - super( - "Converts a rewrite config for tagRenderings into the expanded form", [], - "ExpandGroupRewrite" - ); - this._expandSubTagRenderings = new ExpandTagRendering(state) - } - - convert(json: - { - rewrite: - { sourceString: string; into: string[] }[]; renderings: (string | { builtin: string; override: any } | TagRenderingConfigJson)[] - } | TagRenderingConfigJson, context: string): { result: TagRenderingConfigJson[]; errors: string[]; warnings?: string[] } { - - if (json["rewrite"] === undefined) { - return {result: [json], errors: [], warnings: []} - } - let config = <{ - rewrite: - { sourceString: string[]; into: (string | any)[][] }; - renderings: (string | { builtin: string; override: any } | TagRenderingConfigJson)[] - }>json; - - - { - const errors = [] - - if (!Array.isArray(config.rewrite.sourceString)) { - let extra = ""; - if (typeof config.rewrite.sourceString === "string") { - extra = `
Try "sourceString": [ "${config.rewrite.sourceString}" ] instead (note the [ and ])` - } - const msg = context + "
Invalid format: a rewrite block is defined, but the 'sourceString' should be an array of strings, but it is a " + typeof config.rewrite.sourceString + extra - errors.push(msg) - } - - - const expectedLength = config.rewrite.sourceString.length - for (let i = 0; i < config.rewrite.into.length; i++) { - const targets = config.rewrite.into[i]; - if (!Array.isArray(targets)) { - errors.push(`${context}.rewrite.into[${i}] should be an array of values, but it is a ` + typeof targets) - } else if (targets.length !== expectedLength) { - errors.push(`${context}.rewrite.into[${i}]:
The rewrite specified ${config.rewrite.sourceString} as sourcestring, which consists of ${expectedLength} values. The target ${JSON.stringify(targets)} has ${targets.length} items`) - if (typeof targets[0] !== "string") { - errors.push(context + ".rewrite.into[" + i + "]: expected a string as first rewrite value values, but got " + targets[0]) - - } - } - } - - if (errors.length > 0) { - return { - errors, - warnings: [], - result: undefined - } - } - } - - const subRenderingsRes = <{ result: TagRenderingConfigJson[][], errors, warnings }>this._expandSubTagRenderings.convertAll(config.renderings, context); - const subRenderings: TagRenderingConfigJson[] = [].concat(...subRenderingsRes.result); - const errors = subRenderingsRes.errors; - const warnings = subRenderingsRes.warnings; - - - const rewrittenPerGroup = new Map() - - // The actual rewriting - const sourceStrings = config.rewrite.sourceString; - for (const targets of config.rewrite.into) { - const groupName = targets[0]; - if (typeof groupName !== "string") { - throw "The first string of 'targets' should always be a string" - } - const trs: TagRenderingConfigJson[] = [] - - for (const tr of subRenderings) { - let rewritten = tr; - for (let i = 0; i < sourceStrings.length; i++) { - const source = sourceStrings[i] - const target = targets[i] // This is a string OR a translation - rewritten = ExpandRewrite.RewriteParts(source, target, rewritten) - } - rewritten.group = rewritten.group ?? groupName - trs.push(rewritten) - } - - if (rewrittenPerGroup.has(groupName)) { - rewrittenPerGroup.get(groupName).push(...trs) - } else { - rewrittenPerGroup.set(groupName, trs) - - } - } - - // Add questions box for this category - rewrittenPerGroup.forEach((group, groupName) => { - group.push({ - id: "questions", - group: groupName - }) - }) - - - rewrittenPerGroup.forEach((group, _) => { - group.forEach(tr => { - if (tr.id === undefined || tr.id === "") { - errors.push("A tagrendering has an empty ID after expanding the tag; the tagrendering is: " + JSON.stringify(tr)) - } - }) - }) - - return { - result: [].concat(...Array.from(rewrittenPerGroup.values())), - errors, warnings - }; - } - -} - export class ExpandRewrite extends Conversion, T[]> { constructor() { @@ -283,10 +154,15 @@ export class ExpandRewrite extends Conversion, T[ * "someKey": "somevalue {xyz}" * } * ExpandRewrite.RewriteParts("{xyz}", "rewritten", spec) // => {"someKey": "somevalue rewritten"} + * + * // should substitute all occurances in strings + * const spec = { + * "someKey": "The left|right side has {key:left|right}" + * } + * ExpandRewrite.RewriteParts("left|right", "left", spec) // => {"someKey": "The left side has {key:left}"} * */ public static RewriteParts(keyToRewrite: string, target: string | any, tr: T): T { - const targetIsTranslation = Translations.isProbablyATranslation(target) function replaceRecursive(obj: string | any, target) { @@ -297,7 +173,10 @@ export class ExpandRewrite extends Conversion, T[ if (typeof obj === "string") { // This is a simple string - we do a simple replace - return obj.replace(keyToRewrite, target) + while(obj.indexOf(keyToRewrite) >= 0){ + obj = obj.replace(keyToRewrite, target) + } + return obj } if (Array.isArray(obj)) { // This is a list of items @@ -417,17 +296,173 @@ export class ExpandRewrite extends Conversion, T[ } +/** + * Converts a 'special' translation into a regular translation which uses parameters + * E.g. + * + * const tr = { + * "special": + * } + */ +export class RewriteSpecial extends DesugaringStep { + constructor() { + super("Converts a 'special' translation into a regular translation which uses parameters", ["special"],"RewriteSpecial"); + } + + /** + * Does the heavy lifting and conversion + * + * // should not do anything if no 'special'-key is present + * RewriteSpecial.convertIfNeeded({"en": "xyz", "nl": "abc"}, [], "test") // => {"en": "xyz", "nl": "abc"} + * + * // should handle a simple special case + * RewriteSpecial.convertIfNeeded({"special": {"type":"image_carousel"}}, [], "test") // => {'*': "{image_carousel()}"} + * + * // should handle special case with a parameter + * RewriteSpecial.convertIfNeeded({"special": {"type":"image_carousel", "image_key": "some_image_key"}}, [], "test") // => {'*': "{image_carousel(some_image_key)}"} + * + * // should handle special case with a translated parameter + * const spec = {"special": {"type":"image_upload", "label": {"en": "Add a picture to this object", "nl": "Voeg een afbeelding toe"}}} + * const r = RewriteSpecial.convertIfNeeded(spec, [], "test") + * r // => {"en": "{image_upload(,Add a picture to this object)}", "nl": "{image_upload(,Voeg een afbeelding toe)}" } + * + * // should warn for unexpected keys + * const errors = [] + * RewriteSpecial.convertIfNeeded({"special": {type: "image_carousel"}, "en": "xyz"}, errors, "test") // => {'*': "{image_carousel()}"} + * errors // => ["At test: Unexpected key in a special block: en"] + * + * // should give an error on unknown visualisations + * const errors = [] + * RewriteSpecial.convertIfNeeded({"special": {type: "qsdf"}}, errors, "test") // => undefined + * errors.length // => 1 + * errors[0].indexOf("Special visualisation 'qsdf' not found") >= 0 // => true + * + * // should give an error is 'type' is missing + * const errors = [] + * RewriteSpecial.convertIfNeeded({"special": {}}, errors, "test") // => undefined + * errors // => ["A 'special'-block should define 'type' to indicate which visualisation should be used"] + */ + private static convertIfNeeded(input: (object & {special : {type: string}}) | any, errors: string[], context: string): any { + const special = input["special"] + if(special === undefined){ + return input + } + + for (const wrongKey of Object.keys(input).filter(k => k !== "special")) { + errors.push(`At ${context}: Unexpected key in a special block: ${wrongKey}`) + } + + const type = special["type"] + if(type === undefined){ + errors.push("A 'special'-block should define 'type' to indicate which visualisation should be used") + return undefined + } + const vis = SpecialVisualizations.specialVisualizations.find(sp => sp.funcName === type) + if(vis === undefined){ + const options = Utils.sortedByLevenshteinDistance(type, SpecialVisualizations.specialVisualizations, sp => sp.funcName) + errors.push(`Special visualisation '${type}' not found. Did you perhaps mean ${options[0].funcName}, ${options[1].funcName} or ${options[2].funcName}?\n\tFor all known special visualisations, please see https://github.com/pietervdvn/MapComplete/blob/develop/Docs/SpecialRenderings.md`) + return undefined + } + + const argNamesList = vis.args.map(a => a.name) + const argNames = new Set(argNamesList) + // Check for obsolete and misspelled arguments + errors.push(...Object.keys(special) + .filter(k => !argNames.has(k)) + .filter(k => k !== "type") + .map(wrongArg => { + const byDistance = Utils.sortedByLevenshteinDistance(wrongArg, argNamesList, x => x) + return `Unexpected argument with name '${wrongArg}'. Did you mean ${byDistance[0]}?\n\tAll known arguments are ${ argNamesList.join(", ")}` ; + })) + + // Check that all obligated arguments are present. They are obligated if they don't have a preset value + for (const arg of vis.args) { + if (arg.required !== true) { + continue; + } + const param = special[arg.name] + if(param === undefined){ + errors.push(`Obligated parameter '${arg.name}' not found`) + } + } + + const foundLanguages = new Set() + const translatedArgs = argNamesList.map(nm => special[nm]) + .filter(v => v !== undefined) + .filter(v => Translations.isProbablyATranslation(v)) + for (const translatedArg of translatedArgs) { + for (const ln of Object.keys(translatedArg)) { + foundLanguages.add(ln) + } + } + + if(foundLanguages.size === 0){ + const args= argNamesList.map(nm => special[nm] ?? "").join(",") + return {'*': `{${type}(${args})}` + } + } + + const result = {} + const languages = Array.from(foundLanguages) + languages.sort() + for (const ln of languages) { + const args = [] + for (const argName of argNamesList) { + const v = special[argName] ?? "" + if(Translations.isProbablyATranslation(v)){ + args.push(new Translation(v).textFor(ln)) + }else{ + args.push(v) + } + } + result[ln] = `{${type}(${args.join(",")})}` + } + return result + } + + /** + * const tr = { + * render: {special: {type: "image_carousel", image_key: "image" }}, + * mappings: [ + * { + * if: "other_image_key", + * then: {special: {type: "image_carousel", image_key: "other_image_key"}} + * } + * ] + * } + * const result = new RewriteSpecial().convert(tr,"test").result + * const expected = {render: {'*': "{image_carousel(image)}"}, mappings: [{if: "other_image_key", then: {'*': "{image_carousel(other_image_key)}"}} ]} + * result // => expected + */ + convert(json: TagRenderingConfigJson, context: string): { result: TagRenderingConfigJson; errors?: string[]; warnings?: string[]; information?: string[] } { + const errors = [] + json = Utils.Clone(json) + const paths : {path: string[], type?: any, typeHint?: string}[] = tagrenderingconfigmeta["default"] ?? tagrenderingconfigmeta + for (const path of paths) { + if(path.typeHint !== "rendered"){ + continue + } + Utils.WalkPath(path.path, json, ((leaf, travelled) => RewriteSpecial.convertIfNeeded(leaf, errors, travelled.join(".")))) + } + + return { + result:json, + errors + }; + } + +} + export class PrepareLayer extends Fuse { - - constructor(state: DesugaringContext) { super( "Fully prepares and expands a layer for the LayerConfig.", - new OnEveryConcat("tagRenderings", new ExpandGroupRewrite(state)), - new OnEveryConcat("tagRenderings", new ExpandTagRendering(state)), - new OnEveryConcat("mapRendering", new ExpandRewrite()), + new On("tagRenderings", new Each(new RewriteSpecial())), + new On("tagRenderings", new Concat(new ExpandRewrite()).andThenF(Utils.Flatten)), + new On("tagRenderings", new Concat(new ExpandTagRendering(state))), + new On("mapRendering", new Concat(new ExpandRewrite()).andThenF(Utils.Flatten)), new SetDefault("titleIcons", ["defaults"]), - new OnEveryConcat("titleIcons", new ExpandTagRendering(state)) + new On("titleIcons", new Concat(new ExpandTagRendering(state))) ); } } \ No newline at end of file diff --git a/Models/ThemeConfig/Conversion/PrepareTheme.ts b/Models/ThemeConfig/Conversion/PrepareTheme.ts index 5c210cec74..be7af4abd5 100644 --- a/Models/ThemeConfig/Conversion/PrepareTheme.ts +++ b/Models/ThemeConfig/Conversion/PrepareTheme.ts @@ -1,15 +1,15 @@ -import {Conversion, DesugaringContext, DesugaringStep, Fuse, OnEvery, OnEveryConcat, SetDefault} from "./Conversion"; +import {Concat, Conversion, DesugaringContext, DesugaringStep, Each, Fuse, On, SetDefault} from "./Conversion"; import {LayoutConfigJson} from "../Json/LayoutConfigJson"; import {PrepareLayer} from "./PrepareLayer"; import {LayerConfigJson} from "../Json/LayerConfigJson"; import {Utils} from "../../../Utils"; import Constants from "../../Constants"; -import {AllKnownLayouts} from "../../../Customizations/AllKnownLayouts"; import CreateNoteImportLayer from "./CreateNoteImportLayer"; import LayerConfig from "../LayerConfig"; import {TagRenderingConfigJson} from "../Json/TagRenderingConfigJson"; import {SubstitutedTranslation} from "../../../UI/SubstitutedTranslation"; import DependencyCalculator from "../DependencyCalculator"; +import Translations from "../../../UI/i18n/Translations"; class SubstituteLayer extends Conversion<(string | LayerConfigJson), LayerConfigJson[]> { private readonly _state: DesugaringContext; @@ -280,6 +280,72 @@ export class AddMiniMap extends DesugaringStep { } } +class AddContextToTransltionsInLayout extends DesugaringStep { + + constructor() { + super("Adds context to translations, including the prefix 'themes:json.id'; this is to make sure terms in an 'overrides' or inline layer are linkable too",["_context"], "AddContextToTranlationsInLayout"); + } + + convert(json: LayoutConfigJson, context: string): { result: LayoutConfigJson; errors?: string[]; warnings?: string[]; information?: string[] } { + const conversion = new AddContextToTranslations("themes:") + return conversion.convert(json, json.id); + } + +} + +class AddContextToTranslations extends DesugaringStep { + private readonly _prefix: string; + + constructor(prefix = "") { + super("Adds a '_context' to every object that is probably a translation", ["_context"], "AddContextToTranslation"); + this._prefix = prefix; + } + + /** + * const theme = { + * layers: [ + * { + * builtin: ["abc"], + * override: { + * title:{ + * en: "Some title" + * } + * } + * } + * ] + * } + * const rewritten = new AddContextToTranslations("prefix:").convert(theme, "context").result + * const expected = { + * layers: [ + * { + * builtin: ["abc"], + * override: { + * title:{ + * _context: "prefix:context.layers.0.override.title" + * en: "Some title" + * } + * } + * } + * ] + * } + * rewritten // => expected + */ + convert(json: T, context: string): { result: T; errors?: string[]; warnings?: string[]; information?: string[] } { + + const result = Utils.WalkJson(json, (leaf, path) => { + if(typeof leaf === "object"){ + return {...leaf, _context: this._prefix + context+"."+ path.join(".")} + }else{ + return leaf + } + }, obj => obj !== undefined && obj !== null && Translations.isProbablyATranslation(obj)) + + return { + result + }; + } + +} class ApplyOverrideAll extends DesugaringStep { @@ -328,8 +394,13 @@ class AddDependencyLayersToTheme extends DesugaringStep { const dependencies: { neededLayer: string, reason: string, context?: string, neededBy: string }[] = [] for (const layerConfig of alreadyLoaded) { - const layerDeps = DependencyCalculator.getLayerDependencies(new LayerConfig(layerConfig)) - dependencies.push(...layerDeps) + try{ + const layerDeps = DependencyCalculator.getLayerDependencies(new LayerConfig(layerConfig)) + dependencies.push(...layerDeps) + }catch(e){ + console.error(e) + throw "Detecting layer dependencies for "+layerConfig.id+" failed due to "+e + } } for (const dependency of dependencies) { @@ -455,20 +526,21 @@ export class PrepareTheme extends Fuse { constructor(state: DesugaringContext) { super( "Fully prepares and expands a theme", + new AddContextToTransltionsInLayout(), new PreparePersonalTheme(state), new WarnForUnsubstitutedLayersInTheme(), - new OnEveryConcat("layers", new SubstituteLayer(state)), + new On("layers", new Concat(new SubstituteLayer(state))), new SetDefault("socialImage", "assets/SocialImage.png", true), // We expand all tagrenderings first... - new OnEvery("layers", new PrepareLayer(state)), + new On("layers", new Each(new PrepareLayer(state))), // Then we apply the override all new ApplyOverrideAll(), // And then we prepare all the layers _again_ in case that an override all contained unexpanded tagrenderings! - new OnEvery("layers", new PrepareLayer(state)), + new On("layers", new Each(new PrepareLayer(state))), new AddDefaultLayers(state), new AddDependencyLayersToTheme(state), new AddImportLayers(), - new OnEvery("layers", new AddMiniMap(state)) + new On("layers", new Each(new AddMiniMap(state))) ); } } \ No newline at end of file diff --git a/Models/ThemeConfig/Conversion/Validation.ts b/Models/ThemeConfig/Conversion/Validation.ts index c983ca9362..b735c9bc79 100644 --- a/Models/ThemeConfig/Conversion/Validation.ts +++ b/Models/ThemeConfig/Conversion/Validation.ts @@ -1,4 +1,4 @@ -import {DesugaringStep, Fuse, OnEvery} from "./Conversion"; +import {DesugaringStep, Each, Fuse, On} from "./Conversion"; import {LayerConfigJson} from "../Json/LayerConfigJson"; import LayerConfig from "../LayerConfig"; import {Utils} from "../../../Utils"; @@ -17,11 +17,12 @@ import {QuestionableTagRenderingConfigJson} from "../Json/QuestionableTagRenderi class ValidateLanguageCompleteness extends DesugaringStep { + private readonly _languages: string[]; constructor(...languages: string[]) { super("Checks that the given object is fully translated in the specified languages", [], "ValidateLanguageCompleteness"); - this._languages = languages; + this._languages = languages ?? ["en"]; } convert(obj: any, context: string): { result: LayerConfig; errors: string[] } { @@ -29,7 +30,7 @@ class ValidateLanguageCompleteness extends DesugaringStep { const translations = Translation.ExtractAllTranslationsFrom( obj ) - for (const neededLanguage of this._languages ?? ["en"]) { + for (const neededLanguage of this._languages) { translations .filter(t => t.tr.translations[neededLanguage] === undefined && t.tr.translations["*"] === undefined) .forEach(missing => { @@ -173,7 +174,7 @@ export class ValidateThemeAndLayers extends Fuse { constructor(knownImagePaths: Set, path: string, isBuiltin: boolean, sharedTagRenderings: Map) { super("Validates a theme and the contained layers", new ValidateTheme(knownImagePaths, path, isBuiltin, sharedTagRenderings), - new OnEvery("layers", new ValidateLayer(undefined, false)) + new On("layers", new Each(new ValidateLayer(undefined, false))) ); } } @@ -510,7 +511,7 @@ export class ValidateLayer extends DesugaringStep { } } if (json.tagRenderings !== undefined) { - const r = new OnEvery("tagRenderings", new ValidateTagRenderings(json)).convert(json, context) + const r = new On("tagRenderings", new Each(new ValidateTagRenderings(json))).convert(json, context) warnings.push(...(r.warnings??[])) errors.push(...(r.errors??[])) information.push(...(r.information??[])) diff --git a/Models/ThemeConfig/ExtraLinkConfig.ts b/Models/ThemeConfig/ExtraLinkConfig.ts index 641029f6fb..9c792ab113 100644 --- a/Models/ThemeConfig/ExtraLinkConfig.ts +++ b/Models/ThemeConfig/ExtraLinkConfig.ts @@ -11,7 +11,7 @@ export default class ExtraLinkConfig { constructor(configJson: ExtraLinkConfigJson, context) { this.icon = configJson.icon - this.text = Translations.T(configJson.text) + this.text = Translations.T(configJson.text, "themes:"+context+".text") this.href = configJson.href this.newTab = configJson.newTab this.requirements = new Set(configJson.requirements) diff --git a/Models/ThemeConfig/FilterConfig.ts b/Models/ThemeConfig/FilterConfig.ts index b9060b3cd6..a76a67a233 100644 --- a/Models/ThemeConfig/FilterConfig.ts +++ b/Models/ThemeConfig/FilterConfig.ts @@ -38,7 +38,7 @@ export default class FilterConfig { this.id = json.id; let defaultSelection : number = undefined this.options = json.options.map((option, i) => { - const ctx = `${context}.options[${i}]`; + const ctx = `${context}.options.${i}`; const question = Translations.T( option.question, `${ctx}.question` @@ -68,6 +68,15 @@ export default class FilterConfig { } }) + for (const field of fields) { + question.OnEveryLanguage((txt, language) => { + if(txt.indexOf("{"+field.name+"}")<0){ + throw "Error in filter with fields at "+context+".question."+language+": The question text should contain every field, but it doesn't contain `{"+field+"}`: "+txt + } + return txt + }) + } + if(option.default){ if(defaultSelection === undefined){ defaultSelection = i; diff --git a/Models/ThemeConfig/Json/FilterConfigJson.ts b/Models/ThemeConfig/Json/FilterConfigJson.ts index 493bf74c90..bd03200f3b 100644 --- a/Models/ThemeConfig/Json/FilterConfigJson.ts +++ b/Models/ThemeConfig/Json/FilterConfigJson.ts @@ -16,6 +16,9 @@ export default interface FilterConfigJson { osmTags?: AndOrTagConfigJson | string, default?: boolean, fields?: { + /** + * If name is `search`, use "_first_comment~.*{search}.*" as osmTags + */ name: string, type?: string | "string" }[] diff --git a/Models/ThemeConfig/Json/LayerConfigJson.ts b/Models/ThemeConfig/Json/LayerConfigJson.ts index d70433da93..675c17f311 100644 --- a/Models/ThemeConfig/Json/LayerConfigJson.ts +++ b/Models/ThemeConfig/Json/LayerConfigJson.ts @@ -239,7 +239,7 @@ export interface LayerConfigJson { /** * The type of background picture */ - preferredBackground: "osmbasedmap" | "photo" | "historicphoto" | "map" | string | string [], + preferredBackground: "osmbasedmap" | "photo" | "historicphoto" | "map" | string | string[], /** * If specified, these layers will be shown to and the new point will be snapped towards it */ diff --git a/Models/ThemeConfig/LayerConfig.ts b/Models/ThemeConfig/LayerConfig.ts index e428dafea7..ce2e56f051 100644 --- a/Models/ThemeConfig/LayerConfig.ts +++ b/Models/ThemeConfig/LayerConfig.ts @@ -27,6 +27,7 @@ import FilterConfigJson from "./Json/FilterConfigJson"; import {And} from "../../Logic/Tags/And"; import {Overpass} from "../../Logic/Osm/Overpass"; import Constants from "../Constants"; +import undefinedError = Mocha.utils.undefinedError; export default class LayerConfig extends WithContextLoader { @@ -72,6 +73,7 @@ export default class LayerConfig extends WithContextLoader { official: boolean = true ) { context = context + "." + json.id; + const translationContext = "layers:"+json.id super(json, context) this.id = json.id; @@ -130,7 +132,7 @@ export default class LayerConfig extends WithContextLoader { this.allowSplit = json.allowSplit ?? false; - this.name = Translations.T(json.name, context + ".name"); + this.name = Translations.T(json.name, translationContext + ".name"); this.units = (json.units ?? []).map(((unitJson, i) => Unit.fromJson(unitJson, `${context}.unit[${i}]`))) if (json.description !== undefined) { @@ -141,7 +143,7 @@ export default class LayerConfig extends WithContextLoader { this.description = Translations.T( json.description, - context + ".description" + translationContext + ".description" ); @@ -202,23 +204,23 @@ export default class LayerConfig extends WithContextLoader { snapToLayers = pr.preciseInput.snapToLayer } - let preferredBackground: string[] + let preferredBackground: ("map" | "photo" | "osmbasedmap" | "historicphoto" | string)[] if (typeof pr.preciseInput.preferredBackground === "string") { preferredBackground = [pr.preciseInput.preferredBackground] } else { preferredBackground = pr.preciseInput.preferredBackground } preciseInput = { - preferredBackground: preferredBackground, + preferredBackground, snapToLayers, maxSnapDistance: pr.preciseInput.maxSnapDistance ?? 10 } } const config: PresetConfig = { - title: Translations.T(pr.title, `${context}.presets[${i}].title`), + title: Translations.T(pr.title, `${translationContext}.presets.${i}.title`), tags: pr.tags.map((t) => TagUtils.SimpleTag(t)), - description: Translations.T(pr.description, `${context}.presets[${i}].description`), + description: Translations.T(pr.description, `${translationContext}.presets.${i}.description`), preciseInput: preciseInput, exampleImages: pr.exampleImages } @@ -263,7 +265,7 @@ export default class LayerConfig extends WithContextLoader { this.filters = [] } else { this.filters = (json.filter ?? []).map((option, i) => { - return new FilterConfig(option, `${context}.filter-[${i}]`) + return new FilterConfig(option, `layers:${this.id}.filter.${i}`) }); } @@ -334,6 +336,8 @@ export default class LayerConfig extends WithContextLoader { neededLayer: string; }[], addedByDefault = false, canBeIncluded = true): BaseUIElement { const extraProps = [] + + extraProps.push("This layer is shown at zoomlevel **"+this.minzoom+"** and higher") if (canBeIncluded) { if (addedByDefault) { @@ -438,9 +442,6 @@ export default class LayerConfig extends WithContextLoader { new List(extraProps), ...usingLayer, - new Link("Go to the source code", - `https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/${this.id}/${this.id}.json`), - new Title("Basic tags for this layer", 2), "Elements must have the all of following tags to be shown on this layer:", new List(neededTags.map(t => t.asHumanString(true, false, {}))), diff --git a/Models/ThemeConfig/LayoutConfig.ts b/Models/ThemeConfig/LayoutConfig.ts index be970107aa..402f288929 100644 --- a/Models/ThemeConfig/LayoutConfig.ts +++ b/Models/ThemeConfig/LayoutConfig.ts @@ -67,7 +67,11 @@ export default class LayoutConfig { throw "The id of a theme should match [a-z0-9-_]*: " + json.id } } - context = (context ?? "") + "." + this.id; + if(context === undefined){ + context = this.id + }else{ + context = context + "." + this.id; + } this.maintainer = json.maintainer; this.credits = json.credits; this.version = json.version; @@ -99,10 +103,10 @@ export default class LayoutConfig { throw "Got undefined layers for " + json.id + " at " + context } } - this.title = new Translation(json.title, context + ".title"); - this.description = new Translation(json.description, context + ".description"); - this.shortDescription = json.shortDescription === undefined ? this.description.FirstSentence() : new Translation(json.shortDescription, context + ".shortdescription"); - this.descriptionTail = json.descriptionTail === undefined ? undefined : new Translation(json.descriptionTail, context + ".descriptionTail"); + this.title = new Translation(json.title, "themes:"+context + ".title"); + this.description = new Translation(json.description, "themes:"+context + ".description"); + this.shortDescription = json.shortDescription === undefined ? this.description.FirstSentence() : new Translation(json.shortDescription, "themes:"+context + ".shortdescription"); + this.descriptionTail = json.descriptionTail === undefined ? undefined : new Translation(json.descriptionTail, "themes:"+context + ".descriptionTail"); this.icon = json.icon; this.socialImage = json.socialImage ?? LayoutConfig.defaultSocialImage; if (this.socialImage === "") { @@ -125,7 +129,7 @@ export default class LayoutConfig { href: "https://mapcomplete.osm.be/{theme}.html?lat={lat}&lon={lon}&z={zoom}&language={language}", newTab: true, requirements: ["iframe","no-welcome-message"] - }, context) + }, context+".extraLink") this.clustering = { diff --git a/Models/ThemeConfig/PresetConfig.ts b/Models/ThemeConfig/PresetConfig.ts index 4522d90792..a9e68050c0 100644 --- a/Models/ThemeConfig/PresetConfig.ts +++ b/Models/ThemeConfig/PresetConfig.ts @@ -2,7 +2,7 @@ import {Translation} from "../../UI/i18n/Translation"; import {Tag} from "../../Logic/Tags/Tag"; export interface PreciseInput { - preferredBackground?: string[], + preferredBackground?: ("map" | "photo" | "osmbasedmap" | "historicphoto" | string)[], snapToLayers?: string[], maxSnapDistance?: number } diff --git a/Models/ThemeConfig/TagRenderingConfig.ts b/Models/ThemeConfig/TagRenderingConfig.ts index 967b0cd0e9..6af7592cd8 100644 --- a/Models/ThemeConfig/TagRenderingConfig.ts +++ b/Models/ThemeConfig/TagRenderingConfig.ts @@ -12,6 +12,7 @@ import Title from "../../UI/Base/Title"; import Link from "../../UI/Base/Link"; import List from "../../UI/Base/List"; import {QuestionableTagRenderingConfigJson} from "./Json/QuestionableTagRenderingConfigJson"; +import {FixedUiElement} from "../../UI/Base/FixedUiElement"; /*** * The parsed version of TagRenderingConfigJSON @@ -54,7 +55,6 @@ export default class TagRenderingConfig { if (json === undefined) { throw "Initing a TagRenderingConfig with undefined in " + context; } - if (json === "questions") { // Very special value this.render = null; @@ -70,9 +70,23 @@ export default class TagRenderingConfig { json = "" + json } + let translationKey = context; + if(json["id"] !== undefined){ + const layerId = context.split(".")[0] + if(json["source"]){ + let src = json["source"]+":" + if(json["source"] === "shared-questions"){ + src += "shared_questions." + } + translationKey = `${src}${json["id"] ?? ""}` + }else{ + translationKey = `layers:${layerId}.tagRenderings.${json["id"] ?? ""}` + } + } + if (typeof json === "string") { - this.render = Translations.T(json, context + ".render"); + this.render = Translations.T(json, translationKey + ".render"); this.multiAnswer = false; return; } @@ -86,8 +100,8 @@ export default class TagRenderingConfig { this.group = json.group ?? ""; this.labels = json.labels ?? [] - this.render = Translations.T(json.render, context + ".render"); - this.question = Translations.T(json.question, context + ".question"); + this.render = Translations.T(json.render, translationKey + ".render"); + this.question = Translations.T(json.question, translationKey + ".question"); this.condition = TagUtils.Tag(json.condition ?? {"and": []}, `${context}.condition`); if (json.freeform) { @@ -101,7 +115,7 @@ export default class TagRenderingConfig { const typeDescription = Translations.t.validation[type]?.description placeholder = Translations.T(json.freeform.key+" ("+type+")") if(typeDescription !== undefined){ - placeholder = placeholder.Fuse(typeDescription, type) + placeholder = placeholder.Subs({[type]: typeDescription}) } } @@ -155,7 +169,7 @@ export default class TagRenderingConfig { this.mappings = json.mappings.map((mapping, i) => { - const ctx = `${context}.mapping[${i}]` + const ctx = `${translationKey}.mappings.${i}` if (mapping.then === undefined) { throw `${ctx}: Invalid mapping: if without body` } @@ -520,12 +534,21 @@ export default class TagRenderingConfig { ) ) } + + let condition : BaseUIElement = undefined + if(this.condition !== undefined && !this.condition?.matchesProperties({})){ + condition = new Combine(["Only visible if", + new FixedUiElement( this.condition.asHumanString(false, false, {}) + ).SetClass("code") + , "is shown"]) + } return new Combine([ new Title(this.id, 3), this.question !== undefined ? "The question is **" + this.question.txt + "**" : "_This tagrendering has no question and is thus read-only_", new Combine(withRender), - mappings + mappings, + condition ]).SetClass("flex-col"); } } \ No newline at end of file diff --git a/UI/AllThemesGui.ts b/UI/AllThemesGui.ts index eb5e738f1d..cca64fd567 100644 --- a/UI/AllThemesGui.ts +++ b/UI/AllThemesGui.ts @@ -14,7 +14,7 @@ import {VariableUiElement} from "./Base/VariableUIElement"; import Svg from "../Svg"; export default class AllThemesGui { - constructor() { + setup() { try { new FixedUiElement("").AttachTo("centermessage") diff --git a/UI/Base/FixedUiElement.ts b/UI/Base/FixedUiElement.ts index 4600d26ff6..1b2c7c4d3c 100644 --- a/UI/Base/FixedUiElement.ts +++ b/UI/Base/FixedUiElement.ts @@ -13,6 +13,9 @@ export class FixedUiElement extends BaseUIElement { } AsMarkdown(): string { + if(this.HasClass("code")){ + return "`"+this.content+"`" + } return this.content; } diff --git a/UI/Base/Link.ts b/UI/Base/Link.ts index d0c40faa42..d336793126 100644 --- a/UI/Base/Link.ts +++ b/UI/Base/Link.ts @@ -16,6 +16,7 @@ export default class Link extends BaseUIElement { if (this._embeddedShow === undefined) { throw "Error: got a link where embeddedShow is undefined" } + this.onClick(() => {}) } diff --git a/UI/Base/LinkToWeblate.ts b/UI/Base/LinkToWeblate.ts new file mode 100644 index 0000000000..d088658aba --- /dev/null +++ b/UI/Base/LinkToWeblate.ts @@ -0,0 +1,39 @@ +import {VariableUiElement} from "./VariableUIElement"; +import Locale from "../i18n/Locale"; +import Link from "./Link"; +import Svg from "../../Svg"; + +export default class LinkToWeblate extends VariableUiElement { + constructor(context: string, availableTranslations: object) { + super( Locale.language.map(ln => { + if (Locale.showLinkToWeblate.data === false) { + return undefined; + } + if(availableTranslations["*"] !== undefined){ + return undefined + } + if(context === undefined || context.indexOf(":") < 0){ + return undefined + } + const icon = Svg.translate_svg() + .SetClass("rounded-full border border-gray-400 inline-block w-4 h-4 m-1 weblate-link self-center") + if(availableTranslations[ln] === undefined){ + icon.SetClass("bg-red-400") + } + return new Link(icon, + LinkToWeblate.hrefToWeblate(ln, context), true) + } ,[Locale.showLinkToWeblate])); + this.SetClass("enable-links hidden-on-mobile") + } + + public static hrefToWeblate(language: string, contextKey: string): string{ + if(contextKey === undefined || contextKey.indexOf(":") < 0){ + return undefined + } + const [category, ...rest] = contextKey.split(":") + const key = rest.join(":") + + const baseUrl = "https://hosted.weblate.org/translate/mapcomplete/" + return baseUrl + category + "/" + language + "/?offset=1&q=context%3A%3D%22" + key + "%22" + } +} \ No newline at end of file diff --git a/UI/Base/Table.ts b/UI/Base/Table.ts index a26f4a025a..9ffa4317ce 100644 --- a/UI/Base/Table.ts +++ b/UI/Base/Table.ts @@ -1,20 +1,26 @@ import BaseUIElement from "../BaseUIElement"; import {Utils} from "../../Utils"; import Translations from "../i18n/Translations"; +import {UIEventSource} from "../../Logic/UIEventSource"; export default class Table extends BaseUIElement { private readonly _header: BaseUIElement[]; private readonly _contents: BaseUIElement[][]; private readonly _contentStyle: string[][]; - + private readonly _sortable: boolean; + constructor(header: (BaseUIElement | string)[], contents: (BaseUIElement | string)[][], - contentStyle?: string[][]) { + options?: { + contentStyle?: string[][], + sortable?: false | boolean + }) { super(); - this._contentStyle = contentStyle ?? [["min-width: 9rem"]]; + this._contentStyle = options?.contentStyle ?? [["min-width: 9rem"]]; this._header = header?.map(Translations.W); this._contents = contents.map(row => row.map(Translations.W)); + this._sortable = options?.sortable ?? false } AsMarkdown(): string { @@ -30,7 +36,25 @@ export default class Table extends BaseUIElement { protected InnerConstructElement(): HTMLElement { const table = document.createElement("table") - const headerElems = Utils.NoNull((this._header ?? []).map(elems => elems.ConstructElement())) + /** + * Sortmode: i: sort column i ascending; + * if i is negative : sort column (-i - 1) descending + */ + const sortmode = new UIEventSource(undefined); + const self = this; + const headerElems = Utils.NoNull((this._header ?? []).map((elem, i) => { + if(self._sortable){ + elem.onClick(() => { + const current = sortmode.data + if(current == i){ + sortmode.setData(- 1 - i ) + }else{ + sortmode.setData(i) + } + }) + } + return elem.ConstructElement(); + })) if (headerElems.length > 0) { const thead = document.createElement("thead") @@ -73,6 +97,31 @@ export default class Table extends BaseUIElement { } table.appendChild(tr) } + + sortmode.addCallback(sortCol => { + if(sortCol === undefined){ + return + } + const descending = sortCol < 0 + const col = descending ? - sortCol - 1: sortCol; + let rows: HTMLTableRowElement[] = Array.from(table.rows) + rows.splice(0,1) // remove header row + rows = rows.sort((a, b) => { + const ac = a.cells[col]?.innerText?.toLowerCase() + const bc = b.cells[col]?.innerText?.toLowerCase() + if(ac === bc){ + return 0 + } + return( ac < bc !== descending) ? -1 : 1; + }) + for (let j = rows.length ; j > 1; j--) { + table.deleteRow(j) + } + for (const row of rows) { + table.appendChild(row) + } + }) + return table; } diff --git a/UI/BigComponents/CopyrightPanel.ts b/UI/BigComponents/CopyrightPanel.ts index 73475b6478..c1cadcf8b4 100644 --- a/UI/BigComponents/CopyrightPanel.ts +++ b/UI/BigComponents/CopyrightPanel.ts @@ -23,6 +23,7 @@ import Constants from "../../Models/Constants"; import ContributorCount from "../../Logic/ContributorCount"; import Img from "../Base/Img"; import {Translation} from "../i18n/Translation"; +import TranslatorsPanel from "./TranslatorsPanel"; export class OpenIdEditor extends VariableUiElement { constructor(state: { locationControl: UIEventSource }, iconStyle?: string, objectId?: string) { @@ -110,7 +111,8 @@ export default class CopyrightPanel extends Combine { featurePipeline: FeaturePipeline, currentBounds: UIEventSource, locationControl: UIEventSource, - osmConnection: OsmConnection + osmConnection: OsmConnection, + isTranslator: UIEventSource }) { const t = Translations.t.general.attribution @@ -131,25 +133,21 @@ export default class CopyrightPanel extends Combine { }), new OpenIdEditor(state, iconStyle), new OpenMapillary(state, iconStyle), - new OpenJosm(state, iconStyle) + new OpenJosm(state, iconStyle), + new TranslatorsPanel(state, iconStyle) + ] const iconAttributions = layoutToUse.usedImages.map(CopyrightPanel.IconAttribution) let maintainer: BaseUIElement = undefined if (layoutToUse.maintainer !== undefined && layoutToUse.maintainer !== "" && layoutToUse.maintainer.toLowerCase() !== "mapcomplete") { - maintainer = Translations.t.general.attribution.themeBy.Subs({author: layoutToUse.maintainer}) + maintainer = t.themeBy.Subs({author: layoutToUse.maintainer}) } const contributions = new ContributorCount(state).Contributors - super([ - Translations.t.general.attribution.attributionContent, - new FixedUiElement("MapComplete " + Constants.vNumber).SetClass("font-bold"), - maintainer, - new Combine(actionButtons).SetClass("block w-full"), - new FixedUiElement(layoutToUse.credits), - new VariableUiElement(contributions.map(contributions => { + const dataContributors = new VariableUiElement(contributions.map(contributions => { if (contributions === undefined) { return "" } @@ -170,20 +168,29 @@ export default class CopyrightPanel extends Combine { const contribs = links.join(", ") if (hiddenCount <= 0) { - return Translations.t.general.attribution.mapContributionsBy.Subs({ + return t.mapContributionsBy.Subs({ contributors: contribs }) } else { - return Translations.t.general.attribution.mapContributionsByAndHidden.Subs({ + return t.mapContributionsByAndHidden.Subs({ contributors: contribs, hiddenCount: hiddenCount }); } - })), - CopyrightPanel.CodeContributors(contributors, Translations.t.general.attribution.codeContributionsBy), - CopyrightPanel.CodeContributors(translators, Translations.t.general.attribution.translatedBy), + })) + + super([ + new Title(t.attributionTitle), + t.attributionContent, + maintainer, + new FixedUiElement(layoutToUse.credits), + dataContributors, + CopyrightPanel.CodeContributors(contributors, t.codeContributionsBy), + CopyrightPanel.CodeContributors(translators, t.translatedBy), + new FixedUiElement("MapComplete " + Constants.vNumber).SetClass("font-bold"), + new Combine(actionButtons).SetClass("block w-full"), new Title(t.iconAttribution.title, 3), ...iconAttributions ].map(e => e?.SetClass("mt-4"))); @@ -213,9 +220,9 @@ export default class CopyrightPanel extends Combine { private static IconAttribution(iconPath: string): BaseUIElement { if (iconPath.startsWith("http")) { - try{ + try { iconPath = "." + new URL(iconPath).pathname; - }catch(e){ + } catch (e) { console.warn(e) } } @@ -234,16 +241,16 @@ export default class CopyrightPanel extends Combine { new Img(iconPath).SetClass("w-12 min-h-12 mr-2 mb-2"), new Combine([ new FixedUiElement(license.authors.join("; ")).SetClass("font-bold"), - license.license, - new Combine([ ...sources.map(lnk => { - let sourceLinkContent = lnk; - try { - sourceLinkContent = new URL(lnk).hostname - } catch { - console.error("Not a valid URL:", lnk) - } - return new Link(sourceLinkContent, lnk, true).SetClass("mr-2 mb-2"); - })]).SetClass("flex flex-wrap") + license.license, + new Combine([...sources.map(lnk => { + let sourceLinkContent = lnk; + try { + sourceLinkContent = new URL(lnk).hostname + } catch { + console.error("Not a valid URL:", lnk) + } + return new Link(sourceLinkContent, lnk, true).SetClass("mr-2 mb-2"); + })]).SetClass("flex flex-wrap") ]).SetClass("flex flex-col").SetStyle("width: calc(100% - 50px - 0.5em); min-width: 12rem;") ]).SetClass("flex flex-wrap border-b border-gray-300 m-2 border-box") } diff --git a/UI/BigComponents/ExtraLinkButton.ts b/UI/BigComponents/ExtraLinkButton.ts index 102204e8de..4e4dbb0a20 100644 --- a/UI/BigComponents/ExtraLinkButton.ts +++ b/UI/BigComponents/ExtraLinkButton.ts @@ -62,7 +62,7 @@ export default class ExtraLinkButton extends UIElement { let text: Translation if (c.text === undefined) { - text = Translations.t.general.screenToSmall.Fuse(this.state.layoutToUse.title, "{theme}") + text = Translations.t.general.screenToSmall.Subs({theme: this.state.layoutToUse.title}) } else { text = c.text.Clone() } diff --git a/UI/BigComponents/FilterView.ts b/UI/BigComponents/FilterView.ts index 9c83a98895..e707211a09 100644 --- a/UI/BigComponents/FilterView.ts +++ b/UI/BigComponents/FilterView.ts @@ -101,9 +101,7 @@ export default class FilterView extends VariableUiElement { iconStyle ); - const name: Translation = Translations.WT( - filteredLayer.layerDef.name - ); + const name: Translation = filteredLayer.layerDef.name.Clone() const styledNameChecked = name.Clone().SetStyle("font-size:large").SetClass("ml-3"); diff --git a/UI/BigComponents/FullWelcomePaneWithTabs.ts b/UI/BigComponents/FullWelcomePaneWithTabs.ts index b9e149800f..7daa95088b 100644 --- a/UI/BigComponents/FullWelcomePaneWithTabs.ts +++ b/UI/BigComponents/FullWelcomePaneWithTabs.ts @@ -83,9 +83,7 @@ export default class FullWelcomePaneWithTabs extends ScrollableFullScreen { new Combine( [ Translations.t.general.openStreetMapIntro.SetClass("link-underline"), - Translations.t.general.attribution.attributionTitle, new CopyrightPanel(state) - ] ) } diff --git a/UI/BigComponents/Histogram.ts b/UI/BigComponents/Histogram.ts index d786fbf5da..ba1387dddf 100644 --- a/UI/BigComponents/Histogram.ts +++ b/UI/BigComponents/Histogram.ts @@ -128,8 +128,9 @@ export default class Histogram extends VariableUiElement { .SetStyle(`background: ${actualAssignColor(key)}; width: ${100 * counts.get(key) / max}%`) ]).SetClass("block w-full") - ]), - keys.map(_ => ["width: 20%"]) + ]),{ + contentStyle:keys.map(_ => ["width: 20%"]) + } ).SetClass("w-full zebra-table"); }, [sortMode])); } diff --git a/UI/BigComponents/MoreScreen.ts b/UI/BigComponents/MoreScreen.ts index 1d3820cbe7..4fa8d418a3 100644 --- a/UI/BigComponents/MoreScreen.ts +++ b/UI/BigComponents/MoreScreen.ts @@ -9,7 +9,7 @@ import BaseUIElement from "../BaseUIElement"; import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"; import {UIEventSource} from "../../Logic/UIEventSource"; import Loc from "../../Models/Loc"; -import UserDetails, {OsmConnection} from "../../Logic/Osm/OsmConnection"; +import {OsmConnection} from "../../Logic/Osm/OsmConnection"; import UserRelatedState from "../../Logic/State/UserRelatedState"; import Toggle from "../Input/Toggle"; import {Utils} from "../../Utils"; @@ -53,7 +53,8 @@ export default class MoreScreen extends Combine { icon: string, title: any, shortDescription: any, - definition?: any + definition?: any, + mustHaveLanguage?: boolean }, isCustom: boolean = false ): BaseUIElement { @@ -109,7 +110,7 @@ export default class MoreScreen extends Combine { return new SubtleButton(layout.icon, new Combine([ `
`, - new Translation(layout.title), + new Translation(layout.title, !isCustom && !layout.mustHaveLanguage ? "themes:"+layout.id+".title" : undefined), `
`, `
`, new Translation(layout.shortDescription)?.SetClass("subtle") ?? "", @@ -142,9 +143,10 @@ export default class MoreScreen extends Combine { icon: string, title: any, shortDescription: any, - definition?: any + definition?: any, + isOfficial: boolean } = JSON.parse(str) - + value.isOfficial = false return MoreScreen.createLinkButton(state, value, true) } catch (e) { console.debug("Could not parse unofficial theme information for " + id, "The json is: ", str, e) diff --git a/UI/BigComponents/ShareScreen.ts b/UI/BigComponents/ShareScreen.ts index 0f3bd5bae9..a550627792 100644 --- a/UI/BigComponents/ShareScreen.ts +++ b/UI/BigComponents/ShareScreen.ts @@ -12,6 +12,8 @@ import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"; import Loc from "../../Models/Loc"; import BaseLayer from "../../Models/BaseLayer"; import FilteredLayer from "../../Models/FilteredLayer"; +import {InputElement} from "../Input/InputElement"; +import CheckBoxes, {CheckBox} from "../Input/Checkboxes"; export default class ShareScreen extends Combine { @@ -19,7 +21,7 @@ export default class ShareScreen extends Combine { const layout = state?.layoutToUse; const tr = Translations.t.general.sharescreen; - const optionCheckboxes: BaseUIElement[] = [] + const optionCheckboxes: InputElement[] = [] const optionParts: (UIEventSource)[] = []; function check() { @@ -30,16 +32,12 @@ export default class ShareScreen extends Combine { return Svg.no_checkmark_svg().SetStyle("width: 1.5em; display: inline-block;"); } - const includeLocation = new Toggle( - new Combine([check(), tr.fsIncludeCurrentLocation.Clone()]), - new Combine([nocheck(), tr.fsIncludeCurrentLocation.Clone()]), - new UIEventSource(true) - ).ToggleOnClick() + const includeLocation = new CheckBox(tr.fsIncludeCurrentLocation, true) optionCheckboxes.push(includeLocation); const currentLocation = state.locationControl; - optionParts.push(includeLocation.isEnabled.map((includeL) => { + optionParts.push(includeLocation.GetValue().map((includeL) => { if (currentLocation === undefined) { return null; } @@ -66,13 +64,9 @@ export default class ShareScreen extends Combine { const currentBackground = new VariableUiElement(currentLayer.map(layer => { return tr.fsIncludeCurrentBackgroundMap.Subs({name: layer?.name ?? ""}); })); - const includeCurrentBackground = new Toggle( - new Combine([check(), currentBackground]), - new Combine([nocheck(), currentBackground]), - new UIEventSource(true) - ).ToggleOnClick() + const includeCurrentBackground = new CheckBox(currentBackground, true) optionCheckboxes.push(includeCurrentBackground); - optionParts.push(includeCurrentBackground.isEnabled.map((includeBG) => { + optionParts.push(includeCurrentBackground.GetValue().map((includeBG) => { if (includeBG) { return "background=" + currentLayer.data.id } else { @@ -81,14 +75,10 @@ export default class ShareScreen extends Combine { }, [currentLayer])); - const includeLayerChoices = new Toggle( - new Combine([check(), tr.fsIncludeCurrentLayers.Clone()]), - new Combine([nocheck(), tr.fsIncludeCurrentLayers.Clone()]), - new UIEventSource(true) - ).ToggleOnClick() + const includeLayerChoices = new CheckBox(tr.fsIncludeCurrentLayers, true) optionCheckboxes.push(includeLayerChoices); - optionParts.push(includeLayerChoices.isEnabled.map((includeLayerSelection) => { + optionParts.push(includeLayerChoices.GetValue().map((includeLayerSelection) => { if (includeLayerSelection) { return Utils.NoNull(state.filteredLayers.data.map(fLayerToParam)).join("&") } else { @@ -110,13 +100,9 @@ export default class ShareScreen extends Combine { for (const swtch of switches) { - const checkbox = new Toggle( - new Combine([check(), Translations.W(swtch.human.Clone())]), - new Combine([nocheck(), Translations.W(swtch.human.Clone())]), - new UIEventSource(!swtch.reverse) - ).ToggleOnClick(); + const checkbox =new CheckBox(Translations.W(swtch.human), !swtch.reverse) optionCheckboxes.push(checkbox); - optionParts.push(checkbox.isEnabled.map((isEn) => { + optionParts.push(checkbox.GetValue().map((isEn) => { if (isEn) { if (swtch.reverse) { return `${swtch.urlName}=true` diff --git a/UI/BigComponents/SimpleAddUI.ts b/UI/BigComponents/SimpleAddUI.ts index 87e8730efd..2e8371a0a9 100644 --- a/UI/BigComponents/SimpleAddUI.ts +++ b/UI/BigComponents/SimpleAddUI.ts @@ -117,7 +117,7 @@ export default class SimpleAddUI extends Toggle { selectedPreset.setData(undefined) } - const message = Translations.t.general.add.addNew.Subs({category: preset.name}); + const message = Translations.t.general.add.addNew.Subs({category: preset.name}, preset.name["context"]); return new ConfirmLocationOfPoint(state, filterViewIsOpened, preset, message, state.LastClickLocation.data, @@ -184,12 +184,13 @@ export default class SimpleAddUI extends Toggle { private static CreatePresetSelectButton(preset: PresetInfo) { + const title = Translations.t.general.add.addNew.Subs({ + category: preset.name + }, preset.name["context"]) return new SubtleButton( preset.icon(), new Combine([ - Translations.t.general.add.addNew.Subs({ - category: preset.name - }).SetClass("font-bold"), + title.SetClass("font-bold"), Translations.WT(preset.description)?.FirstSentence() ]).SetClass("flex flex-col") ) diff --git a/UI/BigComponents/TranslatorsPanel.ts b/UI/BigComponents/TranslatorsPanel.ts new file mode 100644 index 0000000000..a036a1d546 --- /dev/null +++ b/UI/BigComponents/TranslatorsPanel.ts @@ -0,0 +1,141 @@ +import Toggle from "../Input/Toggle"; +import Lazy from "../Base/Lazy"; +import {Utils} from "../../Utils"; +import Translations from "../i18n/Translations"; +import Combine from "../Base/Combine"; +import Locale from "../i18n/Locale"; +import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"; +import {Translation} from "../i18n/Translation"; +import {VariableUiElement} from "../Base/VariableUIElement"; +import Link from "../Base/Link"; +import LinkToWeblate from "../Base/LinkToWeblate"; +import Toggleable from "../Base/Toggleable"; +import Title from "../Base/Title"; +import {UIEventSource} from "../../Logic/UIEventSource"; +import {SubtleButton} from "../Base/SubtleButton"; +import Svg from "../../Svg"; + + +class TranslatorsPanelContent extends Combine { + constructor(layout: LayoutConfig, isTranslator: UIEventSource) { + const t = Translations.t.translations + + const {completeness, untranslated, total} = TranslatorsPanel.MissingTranslationsFor(layout) + + const seed = t.completeness + for (const ln of Array.from(completeness.keys())) { + if(ln === "*"){ + continue + } + if (seed.translations[ln] === undefined) { + seed.translations[ln] = seed.translations["en"] + } + } + + const completenessTr = {} + const completenessPercentage = {} + seed.SupportedLanguages().forEach(ln => { + completenessTr[ln] = ""+(completeness.get(ln) ?? 0) + completenessPercentage[ln] = ""+Math.round(100 * (completeness.get(ln) ?? 0) / total) + }) + + const missingTranslationsFor = (ln: string) => Utils.NoNull(untranslated.get(ln) ?? []) + .filter(ctx => ctx.indexOf(":") >= 0) + .map(ctx => ctx.replace(/note_import_[a-zA-Z0-9_]*/, "note_import")) + .map(context => new Link(context, LinkToWeblate.hrefToWeblate(ln, context), true)) + + + // "translationCompleteness": "Translations for {theme} in {language} are at {percentage}: {translated} out of {total}", + const translated = seed.Subs({total, theme: layout.title, + percentage: new Translation(completenessPercentage), + translated: new Translation(completenessTr) + }) + + super([ + new Title( + Translations.t.translations.activateButton, + ), + new Toggle(t.isTranslator.SetClass("thanks block"), undefined, isTranslator), + t.help, + translated, + /*Disable button:*/ + new SubtleButton(undefined, t.deactivate) + .onClick(() => { + Locale.showLinkToWeblate.setData(false) + }), + + new VariableUiElement(Locale.language.map(ln => { + + const missing = missingTranslationsFor(ln) + if (missing.length === 0) { + return undefined + } + return new Toggleable( + new Title(Translations.t.translations.missing.Subs({count: missing.length})), + new Combine(missing).SetClass("flex flex-col") + ) + })) + ]) + + } + +} + +export default class TranslatorsPanel extends Toggle { + + + constructor(state: { layoutToUse: LayoutConfig, isTranslator: UIEventSource }, iconStyle?: string) { + const t = Translations.t.translations + super( + new Lazy(() => new TranslatorsPanelContent(state.layoutToUse, state.isTranslator) + ).SetClass("flex flex-col"), + new SubtleButton(Svg.translate_ui().SetStyle(iconStyle), t.activateButton).onClick(() => Locale.showLinkToWeblate.setData(true)), + Locale.showLinkToWeblate + ) + this.SetClass("hidden-on-mobile") + + } + + + public static MissingTranslationsFor(layout: LayoutConfig) : {completeness: Map, untranslated: Map, total: number} { + let total = 0 + const completeness = new Map() + const untranslated = new Map() + Utils.WalkObject(layout, (o, path) => { + const translation = o; + if(translation.translations["*"] !== undefined){ + return + } + if(translation.context === undefined || translation.context.indexOf(":") < 0){ + // no source given - lets ignore + return + } + + for (const lang of translation.SupportedLanguages()) { + completeness.set(lang, 1 + (completeness.get(lang) ?? 0)) + } + layout.title.SupportedLanguages().forEach(ln => { + const trans = translation.translations + if (trans["*"] !== undefined) { + return; + } + if (trans[ln] === undefined) { + if (!untranslated.has(ln)) { + untranslated.set(ln, []) + } + untranslated.get(ln).push(translation.context) + } + }) + if(translation.translations["*"] === undefined){ + total++ + } + }, o => { + if (o === undefined || o === null) { + return false; + } + return o instanceof Translation; + }) + + return {completeness, untranslated, total} + } +} diff --git a/UI/DefaultGUI.ts b/UI/DefaultGUI.ts index 3d0e2cacdd..095040c634 100644 --- a/UI/DefaultGUI.ts +++ b/UI/DefaultGUI.ts @@ -33,27 +33,30 @@ import ExtraLinkButton from "./BigComponents/ExtraLinkButton"; * Adds a welcome pane, contorl buttons, ... etc to index.html */ export default class DefaultGUI { - private readonly _guiState: DefaultGuiState; + private readonly guiState: DefaultGuiState; private readonly state: FeaturePipelineState; constructor(state: FeaturePipelineState, guiState: DefaultGuiState) { this.state = state; - this._guiState = guiState; + this.guiState = guiState; - if (state.layoutToUse.customCss !== undefined) { - Utils.LoadCustomCss(state.layoutToUse.customCss); + } + + public setup(){ + if (this.state.layoutToUse.customCss !== undefined) { + Utils.LoadCustomCss(this.state.layoutToUse.customCss); } this.SetupUIElements(); this.SetupMap() - if (state.layoutToUse.customCss !== undefined && window.location.pathname.indexOf("index") >= 0) { - Utils.LoadCustomCss(state.layoutToUse.customCss) + if (this.state.layoutToUse.customCss !== undefined && window.location.pathname.indexOf("index") >= 0) { + Utils.LoadCustomCss(this.state.layoutToUse.customCss) } } - + public setupClickDialogOnMap(filterViewIsOpened: UIEventSource, state: FeaturePipelineState) { const hasPresets = state.layoutToUse.layers.some(layer => layer.presets.length > 0); @@ -125,7 +128,7 @@ export default class DefaultGUI { private SetupMap() { const state = this.state; - const guiState = this._guiState; + const guiState = this.guiState; // Attach the map state.mainMapObject.SetClass("w-full h-full") @@ -155,7 +158,7 @@ export default class DefaultGUI { private SetupUIElements() { const state = this.state; - const guiState = this._guiState; + const guiState = this.guiState; const self = this new Combine([ @@ -210,8 +213,8 @@ export default class DefaultGUI { } private InitWelcomeMessage(): BaseUIElement { - const isOpened = this._guiState.welcomeMessageIsOpened - const fullOptions = new FullWelcomePaneWithTabs(isOpened, this._guiState.welcomeMessageOpenedTab, this.state); + const isOpened = this.guiState.welcomeMessageIsOpened + const fullOptions = new FullWelcomePaneWithTabs(isOpened, this.guiState.welcomeMessageOpenedTab, this.state); // ?-Button on Desktop, opens panel with close-X. const help = new MapControlButton(Svg.help_svg()); diff --git a/UI/ImportFlow/AskMetadata.ts b/UI/ImportFlow/AskMetadata.ts index 203d44b3c7..9f7c16caf5 100644 --- a/UI/ImportFlow/AskMetadata.ts +++ b/UI/ImportFlow/AskMetadata.ts @@ -4,19 +4,8 @@ import {UIEventSource} from "../../Logic/UIEventSource"; import ValidatedTextField from "../Input/ValidatedTextField"; import {LocalStorageSource} from "../../Logic/Web/LocalStorageSource"; import Title from "../Base/Title"; -import {AllKnownLayouts} from "../../Customizations/AllKnownLayouts"; -import {DropDown} from "../Input/DropDown"; -import LayerConfig from "../../Models/ThemeConfig/LayerConfig"; -import BaseUIElement from "../BaseUIElement"; import {FixedUiElement} from "../Base/FixedUiElement"; -import {RadioButton} from "../Input/RadioButton"; -import {FixedInputElement} from "../Input/FixedInputElement"; -import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"; -import {InputElement} from "../Input/InputElement"; -import Img from "../Base/Img"; import {VariableUiElement} from "../Base/VariableUIElement"; -import {And} from "../../Logic/Tags/And"; -import Toggleable from "../Base/Toggleable"; export class AskMetadata extends Combine implements FlowStep<{ features: any[], @@ -93,7 +82,6 @@ export class AskMetadata extends Combine implements FlowStep<{ return false; } if ([ obj.features, obj.intro, obj.wikilink, obj.source].some(v => v === undefined)){ - console.log("Obj is", obj) return false; } diff --git a/UI/ImportFlow/ConflationChecker.ts b/UI/ImportFlow/ConflationChecker.ts index 192442043c..f0a3f17c96 100644 --- a/UI/ImportFlow/ConflationChecker.ts +++ b/UI/ImportFlow/ConflationChecker.ts @@ -35,7 +35,7 @@ import {ImportUtils} from "./ImportUtils"; export default class ConflationChecker extends Combine implements FlowStep<{ features: any[], theme: string }> { public readonly IsValid - public readonly Value + public readonly Value: UIEventSource<{ features: any[], theme: string }> constructor( state, @@ -249,7 +249,7 @@ export default class ConflationChecker extends Combine implements FlowStep<{ fea ]) - this.Value = paritionedImport.map(feats => ({features: feats?.noNearby, layer: params.layer})) + this.Value = paritionedImport.map(feats => ({theme: params.theme, features: feats?.noNearby, layer: params.layer})) this.IsValid = this.Value.map(v => v?.features !== undefined && v.features.length > 0) } diff --git a/UI/ImportFlow/CreateNotes.ts b/UI/ImportFlow/CreateNotes.ts index f364196f0f..1364d36751 100644 --- a/UI/ImportFlow/CreateNotes.ts +++ b/UI/ImportFlow/CreateNotes.ts @@ -30,10 +30,14 @@ export class CreateNotes extends Combine { const tags: string [] = [] for (const key in f.properties) { + if (f.properties[key] === null || f.properties[key] === undefined) { + console.warn("Null or undefined key for ", f.properties) + continue + } if (f.properties[key] === "") { continue } - tags.push(key + "=" + f.properties[key].replace(/=/, "\\=").replace(/;/g, "\\;").replace(/\n/g, "\\n")) + tags.push(key + "=" + (f.properties[key]+"").replace(/=/, "\\=").replace(/;/g, "\\;").replace(/\n/g, "\\n")) } const lat = f.geometry.coordinates[1] const lon = f.geometry.coordinates[0] diff --git a/UI/ImportFlow/ImportHelperGui.ts b/UI/ImportFlow/ImportHelperGui.ts index b577c6cfd5..8fb1c041b3 100644 --- a/UI/ImportFlow/ImportHelperGui.ts +++ b/UI/ImportFlow/ImportHelperGui.ts @@ -10,7 +10,6 @@ import {RequestFile} from "./RequestFile"; import {PreviewPanel} from "./PreviewPanel"; import ConflationChecker from "./ConflationChecker"; import {AskMetadata} from "./AskMetadata"; -import LayerConfig from "../../Models/ThemeConfig/LayerConfig"; import {ConfirmProcess} from "./ConfirmProcess"; import {CreateNotes} from "./CreateNotes"; import {FixedUiElement} from "../Base/FixedUiElement"; @@ -38,8 +37,8 @@ export default class ImportHelperGui extends LeftIndex { .then("Select theme", v => new SelectTheme(v)) .then("Compare with open notes", v => new CompareToAlreadyExistingNotes(state, v)) .then("Compare with existing data", v => new ConflationChecker(state, v)) - .then("License and community check", (v : {features: any[], theme: string}) => new ConfirmProcess(v)) - .then("Metadata", (v: { features: any[], layer: LayerConfig, theme: string }) => new AskMetadata(v)) + .then("License and community check", v => new ConfirmProcess(v)) + .then("Metadata", (v) => new AskMetadata(v)) .finish("Note creation", v => new CreateNotes(state, v)); const toc = new List( diff --git a/UI/ImportFlow/ImportViewerGui.ts b/UI/ImportFlow/ImportViewerGui.ts index f0af1f059d..2c427bd9c5 100644 --- a/UI/ImportFlow/ImportViewerGui.ts +++ b/UI/ImportFlow/ImportViewerGui.ts @@ -139,16 +139,59 @@ class MassAction extends Combine { } +class NoteTable extends Combine { + + constructor(noteStates: NoteState[], state?: UserRelatedState) { + const typicalComment = noteStates[0].props.comments[0].html + + const table = new Table( + ["id", "status", "last comment", "last modified by"], + noteStates.map(ns => { + const link = new Link( + "" + ns.props.id, + "https://openstreetmap.org/note/" + ns.props.id, true + ) + let last_comment = ""; + const last_comment_props = ns.props.comments[ns.props.comments.length - 1] + const before_last_comment = ns.props.comments[ns.props.comments.length - 2] + if (ns.props.comments.length > 1) { + last_comment = last_comment_props.text + if (last_comment === undefined && before_last_comment?.uid === last_comment_props.uid) { + last_comment = before_last_comment.text + } + } + const statusIcon = BatchView.icons[ns.status]().SetClass("h-4 w-4 shrink-0") + return [link, new Combine([statusIcon, ns.status]).SetClass("flex"), last_comment, + new Link(last_comment_props.user, "https://www.openstreetmap.org/user/" + last_comment_props.user, true) + ] + }), + {sortable: true} + ).SetClass("zebra-table link-underline"); + + + super([ + new Title("Mass apply an action on " + noteStates.length + " notes below"), + state !== undefined ? new MassAction(state, noteStates.map(ns => ns.props)).SetClass("block") : undefined, + table, + new Title("Example note", 4), + new FixedUiElement(typicalComment).SetClass("literal-code link-underline"), + + ]) + this.SetClass("flex flex-col") + } + +} + class BatchView extends Toggleable { - private static icons = { + public static icons = { open: Svg.compass_svg, has_comments: Svg.speech_bubble_svg, imported: Svg.addSmall_svg, already_mapped: Svg.checkmark_svg, - invalid: Svg.invalid_svg, - closed: Svg.close_svg, not_found: Svg.not_found_svg, + closed: Svg.close_svg, + invalid: Svg.invalid_svg, } constructor(noteStates: NoteState[], state?: UserRelatedState) { @@ -164,14 +207,44 @@ class BatchView extends Toggleable { statusHist.set(st, c + 1) } - const badges: (BaseUIElement)[] = [new FixedUiElement(dateStr).SetClass("literal-code rounded-full")] - statusHist.forEach((count, status) => { - const icon = BatchView.icons[status]().SetClass("h-6 m-1") - badges.push(new Combine([icon, count + " " + status]) - .SetClass("flex ml-1 mb-1 pl-1 pr-3 items-center rounded-full border border-black")) + const unresolvedTotal = (statusHist.get("open") ?? 0) + (statusHist.get("has_comments") ?? 0) + const badges: (BaseUIElement)[] = [ + new FixedUiElement(dateStr).SetClass("literal-code rounded-full"), + new FixedUiElement(noteStates.length + " total").SetClass("literal-code rounded-full ml-1 border-4 border-gray") + .onClick(() => filterOn.setData(undefined)), + unresolvedTotal === 0 ? + new Combine([Svg.party_svg().SetClass("h-6 m-1"), "All done!"]) + .SetClass("flex ml-1 mb-1 pl-1 pr-3 items-center rounded-full border border-black") : + new FixedUiElement(Math.round(100 - 100 * unresolvedTotal / noteStates.length) + "%").SetClass("literal-code rounded-full ml-1") + ] + + const filterOn = new UIEventSource(undefined) + Object.keys(BatchView.icons).forEach(status => { + const count = statusHist.get(status) + if (count === undefined) { + return undefined + } + + const normal = new Combine([BatchView.icons[status]().SetClass("h-6 m-1"), count + " " + status]) + .SetClass("flex ml-1 mb-1 pl-1 pr-3 items-center rounded-full border border-black") + const selected = new Combine([BatchView.icons[status]().SetClass("h-6 m-1"), count + " " + status]) + .SetClass("flex ml-1 mb-1 pl-1 pr-3 items-center rounded-full border-4 border-black animate-pulse") + + const toggle = new Toggle(selected, normal, filterOn.map(f => f === status, [], (selected, previous) => { + if (selected) { + return status; + } + if (previous === status) { + return undefined + } + return previous + })).ToggleOnClick() + + badges.push(toggle) }) - const typicalComment = noteStates[0].props.comments[0].html + + const fullTable = new NoteTable(noteStates, state); super( @@ -179,27 +252,12 @@ class BatchView extends Toggleable { new Title(theme + ": " + intro, 2), new Combine(badges).SetClass("flex flex-wrap"), ]), - new Combine([ - new Title("Example note", 4), - new FixedUiElement(typicalComment).SetClass("literal-code link-underline"), - new Title("Mass apply an action"), - state !== undefined ? new MassAction(state, noteStates.map(ns => ns.props)).SetClass("block") : undefined, - new Table( - ["id", "status", "last comment"], - noteStates.map(ns => { - const link = new Link( - "" + ns.props.id, - "https://openstreetmap.org/note/" + ns.props.id, true - ) - let last_comment = ""; - if (ns.props.comments.length > 1) { - last_comment = ns.props.comments[ns.props.comments.length - 1].text - } - const statusIcon = BatchView.icons[ns.status]().SetClass("h-4 w-4 shrink-0") - return [link, new Combine([statusIcon, ns.status]).SetClass("flex"), last_comment] - }) - ).SetClass("zebra-table link-underline") - ]).SetClass("flex flex-col"), + new VariableUiElement(filterOn.map(filter => { + if (filter === undefined) { + return fullTable + } + return new NoteTable(noteStates.filter(ns => ns.status === filter), state) + })), { closeOnClick: false }) diff --git a/UI/ImportFlow/RequestFile.ts b/UI/ImportFlow/RequestFile.ts index eaad85a5ac..e435758470 100644 --- a/UI/ImportFlow/RequestFile.ts +++ b/UI/ImportFlow/RequestFile.ts @@ -10,6 +10,8 @@ import FileSelectorButton from "../Input/FileSelectorButton"; import {FlowStep} from "./FlowStep"; import {parse} from "papaparse"; import {FixedUiElement} from "../Base/FixedUiElement"; +import {del} from "idb-keyval"; +import {TagUtils} from "../../Logic/Tags/TagUtils"; class FileSelector extends InputElementMap }> { constructor(label: BaseUIElement) { @@ -72,6 +74,17 @@ export class RequestFile extends Combine implements FlowStep<{features: any[]}> if (parsed.features.some(f => f.geometry.type != "Point")) { return {error: t.errPointsOnly} } + parsed.features.forEach(f => { + const props = f.properties + for (const key in props) { + if(props[key] === undefined || props[key] === null || props[key] === ""){ + delete props[key] + } + if(!TagUtils.isValidKey(key)){ + return {error: "Probably an invalid key: "+key} + } + } + }) return parsed; } catch (e) { diff --git a/UI/ImportFlow/SelectTheme.ts b/UI/ImportFlow/SelectTheme.ts index 45f0508c7a..1a84aee0f4 100644 --- a/UI/ImportFlow/SelectTheme.ts +++ b/UI/ImportFlow/SelectTheme.ts @@ -13,6 +13,9 @@ import {VariableUiElement} from "../Base/VariableUIElement"; import {FixedUiElement} from "../Base/FixedUiElement"; import Toggleable from "../Base/Toggleable"; import {BBox} from "../../Logic/BBox"; +import BaseUIElement from "../BaseUIElement"; +import PresetConfig from "../../Models/ThemeConfig/PresetConfig"; +import List from "../Base/List"; export default class SelectTheme extends Combine implements FlowStep<{ features: any[], @@ -29,7 +32,7 @@ export default class SelectTheme extends Combine implements FlowStep<{ }>; public readonly IsValid: UIEventSource; - constructor(params: ({ features: any[], layer: LayerConfig, bbox: BBox, })) { + constructor(params: ({ features: any[], layer: LayerConfig, bbox: BBox, })) { let options: InputElement[] = AllKnownLayouts.layoutsList .filter(th => th.layers.some(l => l.id === params.layer.id)) @@ -37,7 +40,7 @@ export default class SelectTheme extends Combine implements FlowStep<{ .map(th => new FixedInputElement( new Combine([ new Img(th.icon).SetClass("block h-12 w-12 br-4"), - new Title( th.title) + new Title(th.title) ]).SetClass("flex items-center"), th.id)) @@ -47,9 +50,8 @@ export default class SelectTheme extends Combine implements FlowStep<{ }) - const applicablePresets = themeRadios.GetValue().map(theme => { - if(theme === undefined){ + if (theme === undefined) { return [] } // we get the layer with the correct ID via the actual theme config, as the actual theme might have different presets due to overrides @@ -60,7 +62,7 @@ export default class SelectTheme extends Combine implements FlowStep<{ const nonMatchedElements = applicablePresets.map(presets => { - if(presets === undefined || presets.length === 0){ + if (presets === undefined || presets.length === 0) { return undefined } return params.features.filter(feat => !presets.some(preset => new And(preset.tags).matchesProperties(feat.properties))) @@ -71,27 +73,15 @@ export default class SelectTheme extends Combine implements FlowStep<{ "All of the following themes will show the import notes. However, the note on OpenStreetMap can link to only one single theme. Choose which theme that the created notes will link to", themeRadios, new VariableUiElement(applicablePresets.map(applicablePresets => { - if(themeRadios.GetValue().data === undefined){ + if (themeRadios.GetValue().data === undefined) { return undefined } - if(applicablePresets === undefined || applicablePresets.length === 0){ + if (applicablePresets === undefined || applicablePresets.length === 0) { return new FixedUiElement("This theme has no presets loaded. As a result, imports won't work here").SetClass("alert") } - },[themeRadios.GetValue()])), - new VariableUiElement(nonMatchedElements.map(unmatched => { - if(unmatched === undefined || unmatched.length === 0){ - return - } - return new Combine([new FixedUiElement(unmatched.length+" objects dont match any presets").SetClass("alert"), - ...applicablePresets.data.map(preset => preset.title.txt +" needs tags "+ preset.tags.map(t => t.asHumanString()).join(" & ")), - , - new Toggleable( new Title( "The following elements don't match any of the presets"), - new Combine( unmatched.map(feat => JSON.stringify(feat.properties))).SetClass("flex flex-col") - ) + }, [themeRadios.GetValue()])), - ]) .SetClass("flex flex-col") - - })) + new VariableUiElement(nonMatchedElements.map(unmatched => SelectTheme.nonMatchedElementsPanel(unmatched, applicablePresets.data), [applicablePresets])) ]); this.SetClass("flex flex-col") @@ -106,13 +96,13 @@ export default class SelectTheme extends Combine implements FlowStep<{ if (obj === undefined) { return false; } - if ([obj.theme, obj.features].some(v => v === undefined)){ + if ([obj.theme, obj.features].some(v => v === undefined)) { return false; } - if(applicablePresets.data === undefined || applicablePresets.data.length === 0){ + if (applicablePresets.data === undefined || applicablePresets.data.length === 0) { return false } - if((nonMatchedElements.data?.length??0) > 0){ + if ((nonMatchedElements.data?.length ?? 0) > 0) { return false; } @@ -121,5 +111,60 @@ export default class SelectTheme extends Combine implements FlowStep<{ }, [applicablePresets]) } + private static nonMatchedElementsPanel(unmatched: any[], applicablePresets: PresetConfig[]): BaseUIElement { + if (unmatched === undefined || unmatched.length === 0) { + return + } + + const applicablePresetsOverview = applicablePresets.map(preset => new Combine([ + preset.title.txt, "needs tags", + new FixedUiElement(preset.tags.map(t => t.asHumanString()).join(" & ")).SetClass("thanks") + ])) + + const unmatchedPanels: BaseUIElement[] = [] + for (const feat of unmatched) { + const parts: BaseUIElement[] = [] + parts.push(new Combine(Object.keys(feat.properties).map(k => + k+"="+feat.properties[k] + )).SetClass("flex flex-col")) + + for (const preset of applicablePresets) { + const tags = new And(preset.tags).asChange({}) + const missing = [] + for (const {k, v} of tags) { + if (preset[k] === undefined) { + missing.push( + `Expected ${k}=${v}, but it is completely missing` + ) + } else if (feat.properties[k] !== v) { + missing.push( + `Property with key ${k} does not have expected value ${v}; instead it is ${feat.properties}` + ) + } + } + + if (missing.length > 0) { + parts.push( + new Combine([ + new FixedUiElement(`Preset ${preset.title.txt} is not applicable:`), + new List(missing) + ]).SetClass("flex flex-col alert") + ) + } + + } + + unmatchedPanels.push(new Combine(parts).SetClass("flex flex-col")) + } + + return new Combine([ + new FixedUiElement(unmatched.length + " objects dont match any presets").SetClass("alert"), + ...applicablePresetsOverview, + new Toggleable(new Title("The following elements don't match any of the presets"), + new Combine(unmatchedPanels)) + ]).SetClass("flex flex-col") + + } + } \ No newline at end of file diff --git a/UI/Input/Checkboxes.ts b/UI/Input/Checkboxes.ts index affad21920..cf849081e7 100644 --- a/UI/Input/Checkboxes.ts +++ b/UI/Input/Checkboxes.ts @@ -2,6 +2,21 @@ import {InputElement} from "./InputElement"; import {UIEventSource} from "../../Logic/UIEventSource"; import {Utils} from "../../Utils"; import BaseUIElement from "../BaseUIElement"; +import InputElementMap from "./InputElementMap"; + +export class CheckBox extends InputElementMap { + constructor(el: BaseUIElement , defaultValue?: boolean) { + super( + new CheckBoxes([el]), + (x0, x1) => x0 === x1, + t => t.length > 0, + x => x ? [0] : [] + ); + if(defaultValue !== undefined){ + this.GetValue().setData(defaultValue) + } + } +} /** * Supports multi-input diff --git a/UI/Input/InputElementWrapper.ts b/UI/Input/InputElementWrapper.ts index a671a00270..9006956c52 100644 --- a/UI/Input/InputElementWrapper.ts +++ b/UI/Input/InputElementWrapper.ts @@ -17,11 +17,8 @@ export default class InputElementWrapper extends InputElement { mapping.set(key, inputElement) // Bit of a hack: the SubstitutedTranslation expects a special rendering, but those are formatted '{key()}' instead of '{key}', so we substitute it first - const newTranslations = {} - for (const lang in translation.translations) { - newTranslations[lang] = translation.translations[lang].replace("{" + key + "}", "{" + key + "()}") - } - this._renderElement = new SubstitutedTranslation(new Translation(newTranslations), tags, state, mapping) + translation = translation.OnEveryLanguage((txt) => txt.replace("{" + key + "}", "{" + key + "()}")) + this._renderElement = new SubstitutedTranslation(translation, tags, state, mapping) } GetValue(): UIEventSource { diff --git a/UI/LanguagePicker.ts b/UI/LanguagePicker.ts index 2945887c6d..3d1437e557 100644 --- a/UI/LanguagePicker.ts +++ b/UI/LanguagePicker.ts @@ -4,22 +4,33 @@ import BaseUIElement from "./BaseUIElement"; import * as native from "../assets/language_native.json" import * as language_translations from "../assets/language_translations.json" import {Translation} from "./i18n/Translation"; +import * as used_languages from "../assets/generated/used_languages.json" +import Lazy from "./Base/Lazy"; +import Toggle from "./Input/Toggle"; export default class LanguagePicker { public static CreateLanguagePicker( languages: string[], - label: string | BaseUIElement = "") { + label: string | BaseUIElement = "") : BaseUIElement{ if (languages === undefined || languages.length <= 1) { return undefined; } - return new DropDown(label, languages.map(lang => { + const allLanguages : string[] = used_languages.languages; + + const normalPicker = LanguagePicker.dropdownFor(languages, label); + const fullPicker = new Lazy(() => LanguagePicker.dropdownFor(allLanguages, label)) + return new Toggle(fullPicker, normalPicker, Locale.showLinkToWeblate) + } + + private static dropdownFor(languages: string[], label: string | BaseUIElement): BaseUIElement { + return new DropDown(label, languages.map(lang => { return {value: lang, shown: LanguagePicker.hybrid(lang) } } - ), Locale.language); + ), Locale.language) } private static hybrid(lang: string): Translation { diff --git a/UI/OpeningHours/OpeningHoursVisualization.ts b/UI/OpeningHours/OpeningHoursVisualization.ts index 41744a4897..b3e94c7ae5 100644 --- a/UI/OpeningHours/OpeningHoursVisualization.ts +++ b/UI/OpeningHours/OpeningHoursVisualization.ts @@ -168,7 +168,7 @@ export default class OpeningHoursVisualization extends Toggle { } return new Table(undefined, [[" ", header], ...weekdays], - [["width: 5%", `position: relative; height: ${headerHeight}`], ...weekdayStyles] + {contentStyle: [["width: 5%", `position: relative; height: ${headerHeight}`], ...weekdayStyles]} ).SetClass("w-full") .SetStyle("border-collapse: collapse; word-break; word-break: normal; word-wrap: normal") diff --git a/UI/Popup/AutoApplyButton.ts b/UI/Popup/AutoApplyButton.ts index 27c1d2a482..0956a56c53 100644 --- a/UI/Popup/AutoApplyButton.ts +++ b/UI/Popup/AutoApplyButton.ts @@ -156,22 +156,26 @@ class ApplyButton extends UIElement { export default class AutoApplyButton implements SpecialVisualization { public readonly docs: string; public readonly funcName: string = "auto_apply"; - public readonly args: { name: string; defaultValue?: string; doc: string }[] = [ + public readonly args: { name: string; defaultValue?: string; doc: string, required?: boolean }[] = [ { name: "target_layer", - doc: "The layer that the target features will reside in" + doc: "The layer that the target features will reside in", + required: true }, { name: "target_feature_ids", - doc: "The key, of which the value contains a list of ids" + doc: "The key, of which the value contains a list of ids", + required: true }, { name: "tag_rendering_id", - doc: "The ID of the tagRendering containing the autoAction. This tagrendering will be calculated. The embedded actions will be executed" + doc: "The ID of the tagRendering containing the autoAction. This tagrendering will be calculated. The embedded actions will be executed", + required: true }, { name: "text", - doc: "The text to show on the button" + doc: "The text to show on the button", + required: true }, { name: "icon", diff --git a/UI/Popup/FeatureInfoBox.ts b/UI/Popup/FeatureInfoBox.ts index 55f1a0b671..43c56778a8 100644 --- a/UI/Popup/FeatureInfoBox.ts +++ b/UI/Popup/FeatureInfoBox.ts @@ -64,8 +64,10 @@ export default class FeatureInfoBox extends ScrollableFullScreen { const title = new TagRenderingAnswer(tags, layerConfig.title ?? new TagRenderingConfig("POI"), state) .SetClass("break-words font-bold sm:p-0.5 md:p-1 sm:p-1.5 md:p-2 text-2xl"); const titleIcons = new Combine( - layerConfig.titleIcons.map(icon => new TagRenderingAnswer(tags, icon, state, - "block w-8 h-8 max-h-8 align-baseline box-content sm:p-0.5 w-10",) + layerConfig.titleIcons.map(icon => { + return new TagRenderingAnswer(tags, icon, state, + "block h-8 max-h-8 align-baseline box-content sm:p-0.5").SetClass("flex"); + } )) .SetClass("flex flex-row flex-wrap pt-0.5 sm:pt-1 items-center mr-2") diff --git a/UI/Popup/ImportButton.ts b/UI/Popup/ImportButton.ts index c8a50ba422..4108c4e24c 100644 --- a/UI/Popup/ImportButton.ts +++ b/UI/Popup/ImportButton.ts @@ -42,6 +42,7 @@ import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"; import {Changes} from "../../Logic/Osm/Changes"; import {ElementStorage} from "../../Logic/ElementStorage"; import Hash from "../../Logic/Web/Hash"; +import {PreciseInput} from "../../Models/ThemeConfig/PresetConfig"; /** * A helper class for the various import-flows. @@ -54,7 +55,7 @@ abstract class AbstractImportButton implements SpecialVisualizations { public readonly args: { name: string, defaultValue?: string, doc: string }[] private readonly showRemovedTags: boolean; - constructor(funcName: string, docsIntro: string, extraArgs: { name: string, doc: string, defaultValue?: string }[], showRemovedTags = true) { + constructor(funcName: string, docsIntro: string, extraArgs: { name: string, doc: string, defaultValue?: string, required?: boolean }[], showRemovedTags = true) { this.funcName = funcName this.showRemovedTags = showRemovedTags; @@ -73,11 +74,13 @@ ${Utils.special_visualizations_importRequirementDocs} this.args = [ { name: "targetLayer", - doc: "The id of the layer where this point should end up. This is not very strict, it will simply result in checking that this layer is shown preventing possible duplicate elements" + doc: "The id of the layer where this point should end up. This is not very strict, it will simply result in checking that this layer is shown preventing possible duplicate elements", + required: true }, { name: "tags", - doc: "The tags to add onto the new object - see specification above. If this is a key (a single word occuring in the properties of the object), the corresponding value is taken and expanded instead" + doc: "The tags to add onto the new object - see specification above. If this is a key (a single word occuring in the properties of the object), the corresponding value is taken and expanded instead", + required: true }, { name: "text", @@ -394,6 +397,43 @@ export class ImportWayButton extends AbstractImportButton implements AutoAction ) } + private static CreateAction(feature, + args: { max_snap_distance: string; snap_onto_layers: string; icon: string; text: string; tags: string; newTags: UIEventSource; targetLayer: string }, + state: FeaturePipelineState, + mergeConfigs: any[]) { + const coors = feature.geometry.coordinates + if ((feature.geometry.type === "Polygon") && coors.length > 1) { + const outer = coors[0] + const inner = [...coors] + inner.splice(0, 1) + return new CreateMultiPolygonWithPointReuseAction( + args.newTags.data, + outer, + inner, + state, + mergeConfigs, + "import" + ) + } else if (feature.geometry.type === "Polygon") { + const outer = coors[0] + return new CreateWayWithPointReuseAction( + args.newTags.data, + outer, + state, + mergeConfigs + ) + } else if (feature.geometry.type === "LineString") { + return new CreateWayWithPointReuseAction( + args.newTags.data, + coors, + state, + mergeConfigs + ) + } else { + throw "Unsupported type" + } + } + async applyActionOn(state: { layoutToUse: LayoutConfig; changes: Changes, allElements: ElementStorage }, originalFeatureTags: UIEventSource, argument: string[]): Promise { @@ -484,43 +524,6 @@ export class ImportWayButton extends AbstractImportButton implements AutoAction return mergeConfigs; } - - private static CreateAction(feature, - args: { max_snap_distance: string; snap_onto_layers: string; icon: string; text: string; tags: string; newTags: UIEventSource; targetLayer: string }, - state: FeaturePipelineState, - mergeConfigs: any[]) { - const coors = feature.geometry.coordinates - if ((feature.geometry.type === "Polygon" ) && coors.length > 1) { - const outer = coors[0] - const inner = [...coors] - inner.splice(0, 1) - return new CreateMultiPolygonWithPointReuseAction( - args.newTags.data, - outer, - inner, - state, - mergeConfigs, - "import" - ) - } else if(feature.geometry.type === "Polygon"){ - const outer = coors[0] - return new CreateWayWithPointReuseAction( - args.newTags.data, - outer, - state, - mergeConfigs - ) - }else if(feature.geometry.type === "LineString"){ - return new CreateWayWithPointReuseAction( - args.newTags.data, - coors, - state, - mergeConfigs - ) - }else{ - throw "Unsupported type" - } - } } export class ImportPointButton extends AbstractImportButton { @@ -528,18 +531,23 @@ export class ImportPointButton extends AbstractImportButton { constructor() { super("import_button", "This button will copy the point from an external dataset into OpenStreetMap", - [{ - name: "snap_onto_layers", - doc: "If a way of the given layer(s) is closeby, will snap the new point onto this way (similar as preset might snap). To show multiple layers to snap onto, use a `;`-seperated list" - }, + [ + { + name: "snap_onto_layers", + doc: "If a way of the given layer(s) is closeby, will snap the new point onto this way (similar as preset might snap). To show multiple layers to snap onto, use a `;`-seperated list" + }, { name: "max_snap_distance", doc: "The maximum distance that the imported point will be moved to snap onto a way in an already existing layer (in meters). This is previewed to the contributor, similar to the 'add new point'-action of MapComplete", defaultValue: "5" - }, { - name: "note_id", - doc: "If given, this key will be read. The corresponding note on OSM will be closed, stating 'imported'" - }], + }, + { + name: "note_id", + doc: "If given, this key will be read. The corresponding note on OSM will be closed, stating 'imported'" + }, + {name:"location_picker", + defaultValue: "photo", + doc: "Chooses the background for the precise location picker, options are 'map', 'photo' or 'osmbasedmap' or 'none' if the precise input picker should be disabled"}], false ) } @@ -581,7 +589,7 @@ export class ImportPointButton extends AbstractImportButton { newElementAction.newElementId )) Hash.hash.setData(newElementAction.newElementId) - + if (note_id !== undefined) { state.osmConnection.closeNote(note_id, "imported") originalFeatureTags.data["closed_at"] = new Date().toISOString() @@ -589,16 +597,24 @@ export class ImportPointButton extends AbstractImportButton { } } + let preciseInputOption = args["location_picker"] + let preciseInputSpec: PreciseInput = undefined + console.log("Precise input location is ", preciseInputOption) + if(preciseInputOption !== "none") { + preciseInputSpec = { + snapToLayers: args.snap_onto_layers?.split(";"), + maxSnapDistance: Number(args.max_snap_distance), + preferredBackground: args["location_picker"] ?? ["photo", "map"] + } + } + const presetInfo = { tags: args.newTags.data, icon: () => new Img(args.icon), layerToAddTo: state.filteredLayers.data.filter(l => l.layerDef.id === args.targetLayer)[0], name: args.text, title: Translations.WT(args.text), - preciseInput: { - snapToLayers: args.snap_onto_layers?.split(";"), - maxSnapDistance: Number(args.max_snap_distance) - }, + preciseInput: preciseInputSpec, // must be explicitely assigned, if 'undefined' won't work otherwise boundsFactor: 3 } diff --git a/UI/SpecialVisualizations.ts b/UI/SpecialVisualizations.ts index 68f9e75dc2..046bd28f60 100644 --- a/UI/SpecialVisualizations.ts +++ b/UI/SpecialVisualizations.ts @@ -52,7 +52,7 @@ export interface SpecialVisualization { constr: ((state: FeaturePipelineState, tagSource: UIEventSource, argument: string[], guistate: DefaultGuiState,) => BaseUIElement), docs: string, example?: string, - args: { name: string, defaultValue?: string, doc: string }[], + args: { name: string, defaultValue?: string, doc: string, required?: false | boolean }[], getLayerDependencies?: (argument: string[]) => string[] } @@ -102,6 +102,7 @@ class CloseNoteButton implements SpecialVisualization { { name: "text", doc: "Text to show on this button", + required: true }, { name: "icon", @@ -179,7 +180,7 @@ class CloseNoteButton implements SpecialVisualization { export default class SpecialVisualizations { - public static specialVisualizations = SpecialVisualizations.init() + public static specialVisualizations : SpecialVisualization[] = SpecialVisualizations.init() public static HelpMessage() { @@ -206,9 +207,28 @@ export default class SpecialVisualizations { )); return new Combine([ + new Combine([ + new Title("Special tag renderings", 1), + "In a tagrendering, some special values are substituted by an advanced UI-element. This allows advanced features and visualizations to be reused by custom themes or even to query third-party API's.", "General usage is `{func_name()}`, `{func_name(arg, someotherarg)}` or `{func_name(args):cssStyle}`. Note that you _do not_ need to use quotes around your arguments, the comma is enough to separate them. This also implies you cannot use a comma in your args", + new Title("Using expanded syntax",4), + `Instead of using \`{"render": {"en": "{some_special_visualisation(some_arg, some other really long message, more args)} , "nl": "{some_special_visualisation(some_arg, een boodschap in een andere taal, more args)}}, one can also write`, + new FixedUiElement(JSON.stringify({ + render: { + special:{ + type: "some_special_visualisation", + "argname": "some_arg", + "message":{ + en:"some other really long message", + nl: "een boodschap in een andere taal" + }, + "other_arg_name":"more args" + } + } + })).SetClass("code") + ]).SetClass("flex flex-col"), ...helpTexts ] ).SetClass("flex flex-col"); @@ -227,9 +247,9 @@ export default class SpecialVisualizations { funcName: "image_carousel", docs: "Creates an image carousel for the given sources. An attempt will be made to guess what source is used. Supported: Wikidata identifiers, Wikipedia pages, Wikimedia categories, IMGUR (with attribution, direct links)", args: [{ - name: "image key/prefix (multiple values allowed if comma-seperated)", + name: "image_key", defaultValue: AllImageProviders.defaultKeys.join(","), - doc: "The keys given to the images, e.g. if image is given, the first picture URL will be added as image, the second as image:0, the third as image:1, etc... " + doc: "The keys given to the images, e.g. if image is given, the first picture URL will be added as image, the second as image:0, the third as image:1, etc... Multiple values are allowed if ';'-separated " }], constr: (state, tags, args) => { let imagePrefixes: string[] = undefined; @@ -368,6 +388,7 @@ export default class SpecialVisualizations { { doc: "The side to show, either `left` or `right`", name: "side", + required: true } ], example: "`{sided_minimap(left)}`", @@ -461,12 +482,15 @@ export default class SpecialVisualizations { docs: "Downloads a JSON from the given URL, e.g. '{live(example.org/data.json, shorthand:x.y.z, other:a.b.c, shorthand)}' will download the given file, will create an object {shorthand: json[x][y][z], other: json[a][b][c] out of it and will return 'other' or 'json[a][b][c]. This is made to use in combination with tags, e.g. {live({url}, {url:format}, needed_value)}", example: "{live({url},{url:format},hour)} {live(https://data.mobility.brussels/bike/api/counts/?request=live&featureID=CB2105,hour:data.hour_cnt;day:data.day_cnt;year:data.year_cnt,hour)}", args: [{ - name: "Url", doc: "The URL to load" + name: "Url", + doc: "The URL to load", + required: true }, { name: "Shorthands", doc: "A list of shorthands, of the format 'shorthandname:path.path.path'. separated by ;" }, { - name: "path", doc: "The path (or shorthand) that should be returned" + name: "path", + doc: "The path (or shorthand) that should be returned" }], constr: (state, tagSource: UIEventSource, args) => { const url = args[0]; @@ -483,7 +507,8 @@ export default class SpecialVisualizations { args: [ { name: "key", - doc: "The key to be read and to generate a histogram from" + doc: "The key to be read and to generate a histogram from", + required: true }, { name: "title", @@ -588,7 +613,8 @@ export default class SpecialVisualizations { example: "{canonical(length)} will give 42 metre (in french)", args: [{ name: "key", - doc: "The key of the tag to give the canonical text for" + doc: "The key of the tag to give the canonical text for", + required: true }], constr: (state, tagSource, args) => { const key = args [0] @@ -618,16 +644,19 @@ export default class SpecialVisualizations { {name: "feature_ids", doc: "A JSON-serialized list of IDs of features to apply the tagging on"}, { name: "keys", - doc: "One key (or multiple keys, seperated by ';') of the attribute that should be copied onto the other features." + doc: "One key (or multiple keys, seperated by ';') of the attribute that should be copied onto the other features.", + required: true }, {name: "text", doc: "The text to show on the button"}, { name: "autoapply", - doc: "A boolean indicating wether this tagging should be applied automatically if the relevant tags on this object are changed. A visual element indicating the multi_apply is still shown" + doc: "A boolean indicating wether this tagging should be applied automatically if the relevant tags on this object are changed. A visual element indicating the multi_apply is still shown", + required: true }, { name: "overwrite", - doc: "If set to 'true', the tags on the other objects will always be overwritten. The default behaviour will be to only change the tags on other objects if they are either undefined or had the same value before the change" + doc: "If set to 'true', the tags on the other objects will always be overwritten. The default behaviour will be to only change the tags on other objects if they are either undefined or had the same value before the change", + required: true } ], example: "{multi_apply(_features_with_the_same_name_within_100m, name:etymology:wikidata;name:etymology, Apply etymology information on all nearby objects with the same name)}", @@ -813,7 +842,7 @@ export default class SpecialVisualizations { return new LoginToggle( new Combine([ - new Title("Add a comment"), + new Title(t.addAComment), textField, new Combine([ stateButtons.SetClass("sm:mr-2"), @@ -918,7 +947,7 @@ export default class SpecialVisualizations { ] specialVisualizations.push(new AutoApplyButton(specialVisualizations)) - + return specialVisualizations; } diff --git a/UI/SubstitutedTranslation.ts b/UI/SubstitutedTranslation.ts index 59d7ae50ba..856ff2482e 100644 --- a/UI/SubstitutedTranslation.ts +++ b/UI/SubstitutedTranslation.ts @@ -9,6 +9,7 @@ import Combine from "./Base/Combine"; import BaseUIElement from "./BaseUIElement"; import {DefaultGuiState} from "./DefaultGuiState"; import FeaturePipelineState from "../Logic/State/FeaturePipelineState"; +import LinkToWeblate from "./Base/LinkToWeblate"; export class SubstitutedTranslation extends VariableUiElement { @@ -34,6 +35,8 @@ export class SubstitutedTranslation extends VariableUiElement { ) }) + const linkToWeblate = translation !== undefined ? new LinkToWeblate(translation.context, translation.translations) : undefined; + super( Locale.language.map(language => { let txt = translation?.textFor(language); @@ -44,7 +47,7 @@ export class SubstitutedTranslation extends VariableUiElement { txt = txt.replace(new RegExp(`{${key}}`, "g"), `{${key}()}`) }) - return new Combine(SubstitutedTranslation.ExtractSpecialComponents(txt, extraMappings).map( + const allElements = SubstitutedTranslation.ExtractSpecialComponents(txt, extraMappings).map( proto => { if (proto.fixed !== undefined) { return new VariableUiElement(tagsSource.map(tags => Utils.SubstituteKeys(proto.fixed, tags))); @@ -56,8 +59,12 @@ export class SubstitutedTranslation extends VariableUiElement { console.error("SPECIALRENDERING FAILED for", tagsSource.data?.id, e) return new FixedUiElement(`Could not generate special rendering for ${viz.func.funcName}(${viz.args.join(", ")}) ${e}`).SetStyle("alert") } - } - )) + }); + allElements.push(linkToWeblate) + + return new Combine( + allElements + ) }) ) diff --git a/UI/Wikipedia/WikidataPreviewBox.ts b/UI/Wikipedia/WikidataPreviewBox.ts index 7a94c4e02a..a5f125e5cc 100644 --- a/UI/Wikipedia/WikidataPreviewBox.ts +++ b/UI/Wikipedia/WikidataPreviewBox.ts @@ -39,16 +39,12 @@ export default class WikidataPreviewBox extends VariableUiElement { { property: "P569", requires: WikidataPreviewBox.isHuman, - display: new Translation({ - "*": "Born: {value}" - }) + display: Translations.t.general.wikipedia.previewbox.born }, { property: "P570", requires: WikidataPreviewBox.isHuman, - display: new Translation({ - "*": "Died: {value}" - }) + display:Translations.t.general.wikipedia.previewbox.died } ] diff --git a/UI/i18n/Locale.ts b/UI/i18n/Locale.ts index 7c71fcbe12..9fda1d07b1 100644 --- a/UI/i18n/Locale.ts +++ b/UI/i18n/Locale.ts @@ -6,8 +6,9 @@ import {QueryParameters} from "../../Logic/Web/QueryParameters"; export default class Locale { + public static showLinkToWeblate: UIEventSource = new UIEventSource(false); public static language: UIEventSource = Locale.setup(); - + private static setup() { const source = LocalStorageSource.Get('language', "en"); if (!Utils.runningFromConsole) { @@ -15,11 +16,17 @@ export default class Locale { window.setLanguage = function (language: string) { source.setData(language) } - source.syncWith( - QueryParameters.GetQueryParameter("language", undefined, "The language to display mapcomplete in. Will be ignored in case a logged-in-user did set their language before. If the specified language does not exist, it will default to the first language in the theme."), - true - ) } + source.syncWith( + QueryParameters.GetQueryParameter("language", undefined, "The language to display mapcomplete in. Will be ignored in case a logged-in-user did set their language before. If the specified language does not exist, it will default to the first language in the theme."), + true + ) + QueryParameters.GetBooleanQueryParameter("fs-translation-mode",false,"If set, will show a translation button next to every string.") + .addCallbackAndRunD(tr => { + Locale.showLinkToWeblate.setData(Locale.showLinkToWeblate.data || tr); + }) + + return source; } } diff --git a/UI/i18n/Translation.ts b/UI/i18n/Translation.ts index 7c70277094..e9c8157081 100644 --- a/UI/i18n/Translation.ts +++ b/UI/i18n/Translation.ts @@ -1,12 +1,17 @@ import Locale from "./Locale"; import {Utils} from "../../Utils"; import BaseUIElement from "../BaseUIElement"; +import Link from "../Base/Link"; +import Svg from "../../Svg"; +import {VariableUiElement} from "../Base/VariableUIElement"; +import LinkToWeblate from "../Base/LinkToWeblate"; export class Translation extends BaseUIElement { public static forcedLanguage = undefined; public readonly translations: object + context?: string; constructor(translations: object, context?: string) { super() @@ -14,6 +19,11 @@ export class Translation extends BaseUIElement { console.error("Translation without content at "+context) throw `Translation without content (${context})` } + this.context = translations["_context"] ?? context; + if(translations["_context"] !== undefined){ + translations = {...translations} + delete translations["_context"] + } if (typeof translations === "string") { translations = {"*": translations}; } @@ -22,6 +32,9 @@ export class Translation extends BaseUIElement { if (!translations.hasOwnProperty(translationsKey)) { continue } + if(translationsKey === "_context"){ + continue + } count++; if (typeof (translations[translationsKey]) != "string") { console.error("Non-string object in translation: ", translations[translationsKey]) @@ -101,13 +114,34 @@ export class Translation extends BaseUIElement { InnerConstructElement(): HTMLElement { const el = document.createElement("span") const self = this + + Locale.language.addCallbackAndRun(_ => { if (self.isDestroyed) { return true } el.innerHTML = this.txt }) - return el; + + if (self.translations["*"] !== undefined || self.context === undefined || self.context?.indexOf(":") < 0) { + return el; + } + + const linkToWeblate = new LinkToWeblate(self.context, self.translations) + + const wrapper = document.createElement("span") + wrapper.appendChild(el) + Locale.showLinkToWeblate.addCallbackAndRun(doShow => { + + if (!doShow) { + return; + } + wrapper.appendChild(linkToWeblate.ConstructElement()) + return true; + }) + + + return wrapper ; } public SupportedLanguages(): string[] { @@ -131,11 +165,25 @@ export class Translation extends BaseUIElement { return this.SupportedLanguages().map(lng => this.translations[lng]); } - public Subs(text: any): Translation { - return this.OnEveryLanguage((template, lang) => Utils.SubstituteKeys(template, text, lang)) + /** + * Substitutes text in a translation. + * If a translation is passed, it'll be fused + * + * // Should replace simple keys + * new Translation({"en": "Some text {key}"}).Subs({key: "xyz"}).textFor("en") // => "Some text xyz" + * + * // Should fuse translations + * const subpart = new Translation({"en": "subpart","nl":"onderdeel"}) + * const tr = new Translation({"en": "Full sentence with {part}", nl: "Volledige zin met {part}"}) + * const subbed = tr.Subs({part: subpart}) + * subbed.textFor("en") // => "Full sentence with subpart" + * subbed.textFor("nl") // => "Volledige zin met onderdeel" + */ + public Subs(text: any, context?: string): Translation { + return this.OnEveryLanguage((template, lang) => Utils.SubstituteKeys(template, text, lang), context) } - public OnEveryLanguage(f: (s: string, language: string) => string): Translation { + public OnEveryLanguage(f: (s: string, language: string) => string, context?: string): Translation { const newTranslations = {}; for (const lang in this.translations) { if (!this.translations.hasOwnProperty(lang)) { @@ -143,37 +191,10 @@ export class Translation extends BaseUIElement { } newTranslations[lang] = f(this.translations[lang], lang); } - return new Translation(newTranslations); + return new Translation(newTranslations, context ?? this.context); } - - /** - * - * Given a translation such as `{en: "How much of bicycle_types are rented here}` (which is this translation) - * and a translation object `{ en: "electrical bikes" }`, plus the translation specification `bicycle_types`, will return - * a new translation: - * `{en: "How much electrical bikes are rented here?"}` - * - * @param translationObject - * @param stringToReplace - * @constructor - */ - public Fuse(translationObject: Translation, stringToReplace: string): Translation{ - const translations = this.translations - const newTranslations = {} - for (const lang in translations) { - const target = translationObject.textFor(lang) - if(target === undefined){ - continue - } - if(typeof target !== "string"){ - throw "Invalid object in Translation.fuse: translationObject['"+lang+"'] is not a string, it is: "+JSON.stringify(target) - } - newTranslations[lang] = this.translations[lang].replaceAll(stringToReplace, target) - } - return new Translation(newTranslations) - } - + /** * Replaces the given string with the given text in the language. * Other substitutions are left in place @@ -190,7 +211,7 @@ export class Translation extends BaseUIElement { } public Clone() { - return new Translation(this.translations) + return new Translation(this.translations, this.context) } FirstSentence() { @@ -256,4 +277,6 @@ export class Translation extends BaseUIElement { AsMarkdown(): string { return this.txt } + + } \ No newline at end of file diff --git a/UI/i18n/Translations.ts b/UI/i18n/Translations.ts index 4f23c89082..482cc7eeb4 100644 --- a/UI/i18n/Translations.ts +++ b/UI/i18n/Translations.ts @@ -107,7 +107,7 @@ export default class Translations { return false } // is a weird key found? - if(Object.keys(transl).some(key => !this.knownLanguages.has(key))){ + if(Object.keys(transl).some(key => key !== '_context' && !this.knownLanguages.has(key))){ return false } diff --git a/Utils.ts b/Utils.ts index 43f891c0ea..7ee06e1744 100644 --- a/Utils.ts +++ b/Utils.ts @@ -184,6 +184,14 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be return str.substr(0, l - 3) + "..."; } + public static FixedLength(str: string, l: number) { + str = Utils.EllipsesAfter(str, l) + while (str.length < l) { + str = " " + str + } + return str; + } + public static Dedup(arr: string[]): string[] { if (arr === undefined) { return undefined; @@ -212,6 +220,28 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be return newArr; } + /** + * In the given list, all values which are lists will be merged with the values, e.g. + * + * Utils.Flatten([ [1,2], 3, [4, [5 ,6]] ]) // => [1, 2, 3, 4, [5, 6]] + */ + public static Flatten(list: (T | T[])[]): T[] { + const result = [] + for (const value of list) { + if (Array.isArray(value)) { + result.push(...value) + } else { + result.push(value) + } + } + return result; + } + + /** + * Utils.Identical([1,2], [1,2]) // => true + * Utils.Identical([1,2,3], [1,2,4}]) // => false + * Utils.Identical([1,2], [1,2,3]) // => false + */ public static Identical(t1: T[], t2: T[], eq?: (t: T, t0: T) => boolean): boolean { if (t1.length !== t2.length) { return false @@ -225,6 +255,9 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be return true; } + /** + * Utils.MergeTags({k0:"v0","common":"0"},{k1:"v1", common: "1"}) // => {k0: "v0", k1:"v1", common: "1"} + */ public static MergeTags(a: any, b: any) { const t = {}; for (const k in a) { @@ -407,7 +440,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be * * If a list is encountered, this is tranparently walked recursively on every object. * - * The leaf objects are replaced by the function + * The leaf objects are replaced in the object itself by the specified function */ public static WalkPath(path: string[], object: any, replaceLeaf: ((leaf: any, travelledPath: string[]) => any), travelledPath: string[] = []) { const head = path[0] @@ -482,37 +515,75 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be } /** - * Apply a function on every leaf of the JSON; used to rewrite parts of the JSON + * Apply a function on every leaf of the JSON; used to rewrite parts of the JSON. + * Returns a modified copy of the original object. + * + * Hangs if the object contains a loop */ - static WalkJson(json: any, f: (v: number | string | boolean | undefined) => any, isLeaf: (object) => boolean = undefined) { + static WalkJson(json: any, f: (v: object | number | string | boolean | undefined, path: string[]) => any, isLeaf: (object) => boolean = undefined, path: string[] = []) { if (json === undefined) { - return f(undefined) + return f(undefined, path) } const jtp = typeof json if (isLeaf !== undefined) { if (jtp === "object") { if (isLeaf(json)) { - return f(json) + return f(json, path) } } else { return json } } else if (jtp === "boolean" || jtp === "string" || jtp === "number") { - return f(json) + return f(json, path) } if (Array.isArray(json)) { - return json.map(sub => { - return Utils.WalkJson(sub, f, isLeaf); + return json.map((sub,i) => { + return Utils.WalkJson(sub, f, isLeaf, [...path,""+i]); }) } const cp = {...json} for (const key in json) { - cp[key] = Utils.WalkJson(json[key], f, isLeaf) + cp[key] = Utils.WalkJson(json[key], f, isLeaf, [...path, key]) } return cp } + /** + * Walks an object recursively, will execute the 'collect'-callback on every leaf. + * + * Will hang on objects with loops + */ + static WalkObject(json: any, collect: (v: number | string | boolean | undefined, path: string[]) => any, isLeaf: (object) => boolean = undefined, path = []): void { + if (json === undefined) { + return; + } + const jtp = typeof json + if (isLeaf !== undefined) { + if (jtp !== "object") { + return + } + + if (isLeaf(json)) { + return collect(json, path) + } + } else if (jtp === "boolean" || jtp === "string" || jtp === "number") { + collect(json, path) + return + } + if (Array.isArray(json)) { + json.map((sub, i) => { + return Utils.WalkObject(sub, collect, isLeaf, [...path, i]); + }) + return + } + + for (const key in json) { + Utils.WalkObject(json[key], collect, isLeaf, [...path, key]) + } + } + + static getOrSetDefault(dict: Map, k: K, v: () => V) { let found = dict.get(k); if (found !== undefined) { @@ -794,6 +865,12 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be return new Date(str) } + public static sortedByLevenshteinDistance(reference: string, ts: T[], getName: (t: T) => string): T[] { + const withDistance: [T, number][] = ts.map(t => [t, Utils.levenshteinDistance(getName(t), reference)]) + withDistance.sort(([_, a], [__, b]) => a - b) + return withDistance.map(n => n[0]) + } + public static levenshteinDistance(str1: string, str2: string) { const track = Array(str2.length + 1).fill(null).map(() => Array(str1.length + 1).fill(null)); @@ -827,43 +904,41 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be return o } - private static colorDiff(c0: { r: number, g: number, b: number }, c1: { r: number, g: number, b: number }) { - return Math.abs(c0.r - c1.r) + Math.abs(c0.g - c1.g) + Math.abs(c0.b - c1.b); - } - /** * Utils.colorAsHex({r: 255, g: 128, b: 0}) // => "#ff8000" * Utils.colorAsHex(undefined) // => undefined */ - public static colorAsHex(c:{ r: number, g: number, b: number } ){ - if(c === undefined){ + public static colorAsHex(c: { r: number, g: number, b: number }) { + if (c === undefined) { return undefined } + function componentToHex(n) { let hex = n.toString(16); return hex.length == 1 ? "0" + hex : hex; } + return "#" + componentToHex(c.r) + componentToHex(c.g) + componentToHex(c.b); } - + /** - * + * * Utils.color("#ff8000") // => {r: 255, g:128, b: 0} * Utils.color(" rgba (12,34,56) ") // => {r: 12, g:34, b: 56} * Utils.color(" rgba (12,34,56,0.5) ") // => {r: 12, g:34, b: 56} * Utils.color(undefined) // => undefined */ public static color(hex: string): { r: number, g: number, b: number } { - if(hex === undefined){ + if (hex === undefined) { return undefined } hex = hex.replace(/[ \t]/g, "") if (hex.startsWith("rgba(")) { - const match = hex.match(/rgba\(([0-9.]+),([0-9.]+),([0-9.]+)(,[0-9.]*)?\)/) - if(match == undefined){ + const match = hex.match(/rgba\(([0-9.]+),([0-9.]+),([0-9.]+)(,[0-9.]*)?\)/) + if (match == undefined) { return undefined } - return {r: Number(match[1]), g: Number(match[2]), b:Number( match[3])} + return {r: Number(match[1]), g: Number(match[2]), b: Number(match[3])} } if (!hex.startsWith("#")) { @@ -883,9 +958,9 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be b: parseInt(hex.substr(5, 2), 16), } } - - public static asDict(tags: {key: string, value: string | number}[]) : Map{ - const d= new Map() + + public static asDict(tags: { key: string, value: string | number }[]): Map { + const d = new Map() for (const tag of tags) { d.set(tag.key, tag.value) @@ -893,5 +968,9 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be return d } + + private static colorDiff(c0: { r: number, g: number, b: number }, c1: { r: number, g: number, b: number }) { + return Math.abs(c0.r - c1.r) + Math.abs(c0.g - c1.g) + Math.abs(c0.b - c1.b); + } } diff --git a/all_themes_index.ts b/all_themes_index.ts index 12abde8c54..058a2c3e58 100644 --- a/all_themes_index.ts +++ b/all_themes_index.ts @@ -19,4 +19,4 @@ if (layout !== "") { Utils.DisableLongPresses() document.getElementById("decoration-desktop").remove(); -new AllThemesGui(); \ No newline at end of file +new AllThemesGui().setup(); \ No newline at end of file diff --git a/assets/contributors.json b/assets/contributors.json index 1fdb6676cf..4990cc0670 100644 --- a/assets/contributors.json +++ b/assets/contributors.json @@ -1 +1 @@ -{"contributors":[{"commits":3432,"contributor":"Pieter Vander Vennet"},{"commits":86,"contributor":"Robin van der Linde"},{"commits":39,"contributor":"Tobias"},{"commits":33,"contributor":"Christian Neumann"},{"commits":31,"contributor":"Win Olario"},{"commits":31,"contributor":"Pieter Fiers"},{"commits":26,"contributor":"karelleketers"},{"commits":24,"contributor":"Ward"},{"commits":20,"contributor":"Joost"},{"commits":19,"contributor":"Sebastian Kürten"},{"commits":18,"contributor":"Hosted Weblate"},{"commits":18,"contributor":"riQQ"},{"commits":18,"contributor":"Arno Deceuninck"},{"commits":17,"contributor":"pgm-chardelv1"},{"commits":15,"contributor":"ToastHawaii"},{"commits":13,"contributor":"Nicole"},{"commits":12,"contributor":"Tobias Jordans"},{"commits":12,"contributor":"Bavo Vanderghote"},{"commits":10,"contributor":"LiamSimons"},{"commits":8,"contributor":"dependabot[bot]"},{"commits":8,"contributor":"Midgard"},{"commits":7,"contributor":"RobJN"},{"commits":7,"contributor":"Mateusz Konieczny"},{"commits":7,"contributor":"Flo Edelmann"},{"commits":7,"contributor":"Binnette"},{"commits":7,"contributor":"yopaseopor"},{"commits":6,"contributor":"pelderson"},{"commits":5,"contributor":"David Haberthür"},{"commits":4,"contributor":"Ward Beyens"},{"commits":3,"contributor":"Weblate (bot)"},{"commits":3,"contributor":"Léo Villeveygoux"},{"commits":2,"contributor":"Codain"},{"commits":2,"contributor":"arrival-spring"},{"commits":2,"contributor":"Strubbl"},{"commits":2,"contributor":"RayBB"},{"commits":2,"contributor":"Charlotte Delvaux"},{"commits":2,"contributor":"Supaplex"},{"commits":2,"contributor":"pbarban"},{"commits":2,"contributor":"graveelius"},{"commits":2,"contributor":"Stanislas Gueniffey"},{"commits":1,"contributor":"Štefan Baebler"},{"commits":1,"contributor":"Jiří Podhorecký"},{"commits":1,"contributor":"Mark Rogerson"},{"commits":1,"contributor":"nicole_s"},{"commits":1,"contributor":"SC"},{"commits":1,"contributor":"Raphael Das Gupta"},{"commits":1,"contributor":"Nikolay Korotkiy"},{"commits":1,"contributor":"Seppe Santens"},{"commits":1,"contributor":"root"},{"commits":1,"contributor":"Allan Nordhøy"},{"commits":1,"contributor":"快乐的老鼠宝宝"},{"commits":1,"contributor":"Sebastian"},{"commits":1,"contributor":"Hiroshi Miura"},{"commits":1,"contributor":"riiga"},{"commits":1,"contributor":"Vinicius"},{"commits":1,"contributor":"Alexey Shabanov"},{"commits":1,"contributor":"Polgár Sándor"},{"commits":1,"contributor":"SiegbjornSitumeang"},{"commits":1,"contributor":"Marco"},{"commits":1,"contributor":"mozita"},{"commits":1,"contributor":"Schouppe Joost"},{"commits":1,"contributor":"Thibault Molleman"},{"commits":1,"contributor":"Noémie"},{"commits":1,"contributor":"Tomas Fiers"},{"commits":1,"contributor":"tbowdecl97"}]} \ No newline at end of file +{"contributors":[{"commits":3435,"contributor":"Pieter Vander Vennet"},{"commits":86,"contributor":"Robin van der Linde"},{"commits":39,"contributor":"Tobias"},{"commits":33,"contributor":"Christian Neumann"},{"commits":31,"contributor":"Win Olario"},{"commits":31,"contributor":"Pieter Fiers"},{"commits":26,"contributor":"karelleketers"},{"commits":24,"contributor":"Ward"},{"commits":20,"contributor":"Joost"},{"commits":19,"contributor":"Sebastian Kürten"},{"commits":18,"contributor":"Hosted Weblate"},{"commits":18,"contributor":"riQQ"},{"commits":18,"contributor":"Arno Deceuninck"},{"commits":17,"contributor":"pgm-chardelv1"},{"commits":15,"contributor":"ToastHawaii"},{"commits":13,"contributor":"Nicole"},{"commits":12,"contributor":"Tobias Jordans"},{"commits":12,"contributor":"Bavo Vanderghote"},{"commits":10,"contributor":"LiamSimons"},{"commits":8,"contributor":"dependabot[bot]"},{"commits":8,"contributor":"Midgard"},{"commits":7,"contributor":"RobJN"},{"commits":7,"contributor":"Mateusz Konieczny"},{"commits":7,"contributor":"Flo Edelmann"},{"commits":7,"contributor":"Binnette"},{"commits":7,"contributor":"yopaseopor"},{"commits":6,"contributor":"pelderson"},{"commits":5,"contributor":"David Haberthür"},{"commits":4,"contributor":"Ward Beyens"},{"commits":3,"contributor":"Weblate (bot)"},{"commits":3,"contributor":"Léo Villeveygoux"},{"commits":2,"contributor":"Codain"},{"commits":2,"contributor":"arrival-spring"},{"commits":2,"contributor":"Strubbl"},{"commits":2,"contributor":"RayBB"},{"commits":2,"contributor":"Charlotte Delvaux"},{"commits":2,"contributor":"Supaplex"},{"commits":2,"contributor":"pbarban"},{"commits":2,"contributor":"graveelius"},{"commits":2,"contributor":"Stanislas Gueniffey"},{"commits":1,"contributor":"Štefan Baebler"},{"commits":1,"contributor":"Jiří Podhorecký"},{"commits":1,"contributor":"Mark Rogerson"},{"commits":1,"contributor":"nicole_s"},{"commits":1,"contributor":"SC"},{"commits":1,"contributor":"Raphael Das Gupta"},{"commits":1,"contributor":"Nikolay Korotkiy"},{"commits":1,"contributor":"Seppe Santens"},{"commits":1,"contributor":"root"},{"commits":1,"contributor":"Allan Nordhøy"},{"commits":1,"contributor":"快乐的老鼠宝宝"},{"commits":1,"contributor":"Sebastian"},{"commits":1,"contributor":"Hiroshi Miura"},{"commits":1,"contributor":"riiga"},{"commits":1,"contributor":"Vinicius"},{"commits":1,"contributor":"Alexey Shabanov"},{"commits":1,"contributor":"Polgár Sándor"},{"commits":1,"contributor":"SiegbjornSitumeang"},{"commits":1,"contributor":"Marco"},{"commits":1,"contributor":"mozita"},{"commits":1,"contributor":"Schouppe Joost"},{"commits":1,"contributor":"Thibault Molleman"},{"commits":1,"contributor":"Noémie"},{"commits":1,"contributor":"Tomas Fiers"},{"commits":1,"contributor":"tbowdecl97"}]} \ No newline at end of file diff --git a/assets/layers/bike_shop/bike_shop.json b/assets/layers/bike_shop/bike_shop.json index f3758c298a..ed209dbdc0 100644 --- a/assets/layers/bike_shop/bike_shop.json +++ b/assets/layers/bike_shop/bike_shop.json @@ -298,18 +298,13 @@ }, "id": "bike_shop-email" }, - { - "render": "{opening_hours_table(opening_hours)}", - "question": "When is this shop opened?", - "freeform": { - "key": "opening_hours", - "type": "opening_hours" - }, - "id": "bike_shop-opening_hours" - }, + "opening_hours", "description", { - "render": "Enkel voor {access}", + "render": { + "en": "Only accessible to {access}", + "nl": "Enkel voor {access}" + }, "freeform": { "key": "access" }, diff --git a/assets/layers/note/note.json b/assets/layers/note/note.json index 27e3c12449..e3fa7cbcce 100644 --- a/assets/layers/note/note.json +++ b/assets/layers/note/note.json @@ -90,7 +90,7 @@ "iconBadges": [ { "if": "_total_comments>1", - "then": "speech_bubble" + "then": "circle:white;speech_bubble" }, { "if": "_is_import_note~*", diff --git a/assets/layers/playground/playground.json b/assets/layers/playground/playground.json index e707ea531e..2929fc142a 100644 --- a/assets/layers/playground/playground.json +++ b/assets/layers/playground/playground.json @@ -346,6 +346,7 @@ } ] }, + "website", { "question": { "nl": "Wie kan men emailen indien er problemen zijn met de speeltuin?", diff --git a/assets/layers/shops/shops.json b/assets/layers/shops/shops.json index 69df31c5a0..401fd0c01e 100644 --- a/assets/layers/shops/shops.json +++ b/assets/layers/shops/shops.json @@ -408,5 +408,41 @@ "render": "8" } } + ], + "filter": [ + { + "id": "shop-type", + "options": [ + { + "fields": [ + { + "name": "search", + "type": "string" + } + ], + "osmTags": "shop~^.*{search}.*$", + "question": { + "en": "Only show shops selling {search}" + } + } + ] + }, + { + "id": "shop-name", + "options": [ + { + "fields": [ + { + "name": "search", + "type": "string" + } + ], + "osmTags": "name~^.*{search}.*$", + "question": { + "en": "Only show shops with name {search}" + } + } + ] + } ] } \ No newline at end of file diff --git a/assets/svg/license_info.json b/assets/svg/license_info.json index c886034d32..530adea9ad 100644 --- a/assets/svg/license_info.json +++ b/assets/svg/license_info.json @@ -915,6 +915,16 @@ "https://www.OpenStreetMap.org" ] }, + { + "path": "party.svg", + "license": "CC-BY 4.0", + "authors": [ + "Twemoji" + ], + "sources": [ + "https://github.com/twitter/twemoji" + ] + }, { "path": "payment_card.svg", "license": "CC0", diff --git a/assets/svg/party.svg b/assets/svg/party.svg new file mode 100644 index 0000000000..a4b8305af6 --- /dev/null +++ b/assets/svg/party.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/themes/climbing/climbing.json b/assets/themes/climbing/climbing.json index f48ce9bfa5..9607011536 100644 --- a/assets/themes/climbing/climbing.json +++ b/assets/themes/climbing/climbing.json @@ -143,10 +143,6 @@ }, "id": "climbing_club-name" }, - { - "id": "minimap", - "render": "{minimap(18): height: 5rem; overflow: hidden; border-radius:3rem; }" - }, "website", "email", "phone", @@ -287,11 +283,6 @@ }, "tagRenderings": [ "images", - "questions", - { - "id": "minimap", - "render": "{minimap(18): height: 5rem; overflow: hidden; border-radius:3rem; }" - }, { "render": { "en": "{name}", @@ -320,8 +311,7 @@ "website", "phone", "email", - "opening_hours", - "reviews" + "opening_hours" ], "mapRendering": [ { @@ -397,11 +387,6 @@ }, "tagRenderings": [ "images", - "questions", - { - "id": "minimap", - "render": "{minimap(18): height: 5rem; overflow: hidden; border-radius:3rem; }" - }, { "render": { "en": "{name}", @@ -555,8 +540,7 @@ "key": "_embedding_features_with_rock:rock" }, "id": "Rock type" - }, - "reviews" + } ], "presets": [ { @@ -704,7 +688,6 @@ }, "tagRenderings": [ "images", - "questions", { "id": "minimap", "render": "{minimap(18, id, _contained_climbing_route_ids): height: 9rem; overflow: hidden; border-radius:3rem; }" @@ -846,8 +829,7 @@ ] }, "id": "Rock type (crag/rock/cliff only)" - }, - "reviews" + } ], "presets": [ { @@ -955,10 +937,6 @@ "it": "Un’opportunità di arrampicata?" }, "tagRenderings": [ - { - "id": "minimap", - "render": "{minimap(18): height: 5rem; overflow: hidden; border-radius:3rem; }" - }, { "id": "climbing-opportunity-name", "render": { @@ -1053,26 +1031,51 @@ } ], "overrideAll": { - "titleIcons": [ + "+titleIcons": [ { - "render": "
{climbing:length}m
", - "freeform": { - "key": "climbing:length" - } + "render": "
{climbing:length}m
", + "condition": "climbing:length~*" }, { - "render": "
{climbing:bolted}
", - "freeform": { - "key": "climbing:bolted" - }, "mappings": [ + { + "if": "climbing:bolts~*", + "then": "
{climbing:bolts}
" + }, { "if": "climbing:bolted=yes", "then": "" } ] }, - "defaults" + { + "mappings": [ + { + "if": "climbing:grade:french~3.*", + "then": "
{climbing:grade:french}
" + }, + { + "if": "climbing:grade:french~4.*", + "then": "
{climbing:grade:french}
" + }, + { + "if": "climbing:grade:french~5.*", + "then": "
{climbing:grade:french}
" + }, + { + "if": "climbing:grade:french~6.*", + "then": "
{climbing:grade:french}
" + }, + { + "if": "climbing:grade:french~7.*", + "then": "
{climbing:grade:french}
" + }, + { + "if": "climbing:grade:french~*", + "then": "
{climbing:grade:french}
" + } + ] + } ], "+calculatedTags": [ "_embedding_feature_properties=feat.overlapWith('climbing').map(f => f.feat.properties).filter(p => p !== undefined).map(p => {return{access: p.access, id: p.id, name: p.name, climbing: p.climbing, 'access:description': p['access:description']}})", @@ -1690,7 +1693,9 @@ "hideInAnswer": true } ] - } + }, + "questions", + "reviews" ] } } \ No newline at end of file diff --git a/assets/themes/etymology.json b/assets/themes/etymology/etymology.json similarity index 100% rename from assets/themes/etymology.json rename to assets/themes/etymology/etymology.json diff --git a/assets/themes/grb_import/grb.json b/assets/themes/grb_import/grb.json index 4eb84c7175..699a3e9c7c 100644 --- a/assets/themes/grb_import/grb.json +++ b/assets/themes/grb_import/grb.json @@ -374,7 +374,13 @@ "tagRenderings+": [ { "id": "render_embedded", - "render": "Dit CRAB-adres ligt in OSM-gebouw {_embedding_id}" + "render": "Dit CRAB-adres ligt in OSM-gebouw {_embedding_id}", + "mappings": [{ + "if": "_embedding_id=", + "then": { + "nl": "Geen omliggend OSM-gebouw gevonden" + } + }] }, { "id": "embedded_address", @@ -409,17 +415,30 @@ }, { "id": "import-button", - "render": "{import_button(address, addr:street=$STRAATNM; addr:housenumber=$_HNRLABEL,Voeg dit adres als een nieuw adrespunt toe,,osm-buildings,5)}", + "render": { + "special": { + "type": "import_button", + "targetLayer": "address", + "tags": "addr:street=$STRAATNM; addr:housenumber=$_HNRLABEL", + "text": { + "nl": "Voeg dit adres als een nieuw adrespunt toe" + }, + "snap_onto_layers": "osm-buildings" + } + }, + "mappings": [ + { + "if": "_embedding_id=", + "then": { + "nl": "Geen omliggend OSM-gebouw gevonden. Een omliggend gebouw is nodig om dit punt als adres punt toe te voegen.
Importeer eerst de gebouwen. Vernieuw dan de pagina om losse adressen toe te voegen
" + } + } + ], "condition": { - "and": [ - "_embedding_id!=", - { "or": [ "_embedding_street!:={STRAATNM}", "_embedding_nr!:={_HNRLABEL}" ] - } - ] } } ] diff --git a/assets/themes/mapcomplete-changes/mapcomplete-changes.json b/assets/themes/mapcomplete-changes/mapcomplete-changes.json index 478d968efe..da73732b30 100644 --- a/assets/themes/mapcomplete-changes/mapcomplete-changes.json +++ b/assets/themes/mapcomplete-changes/mapcomplete-changes.json @@ -1,8 +1,7 @@ { "id": "mapcomplete-changes", "title": { - "en": "Changes made with MapComplete", - "nl": "Wijzigingen gemaakt met MapComplete" + "en": "Changes made with MapComplete" }, "shortDescription": { "en": "Shows changes made by MapComplete" diff --git a/assets/themes/toerisme_vlaanderen/license_info.json b/assets/themes/toerisme_vlaanderen/license_info.json index 0013ceba58..feefa82985 100644 --- a/assets/themes/toerisme_vlaanderen/license_info.json +++ b/assets/themes/toerisme_vlaanderen/license_info.json @@ -144,6 +144,72 @@ "https://mapcomplete.osm.be/toerisme_vlaanderen" ] }, + { + "path": "pin je punt1.jpg", + "license": "CC0", + "authors": [ + "Toerisme Vlaanderen" + ], + "sources": [ + "https://toerismevlaanderen.be/pinjepunt", + "https://mapcomplete.osm.be/toerisme_vlaanderenn" + ] + }, + { + "path": "pin je punt2.jpg", + "license": "CC0", + "authors": [ + "Toerisme Vlaanderen" + ], + "sources": [ + "https://toerismevlaanderen.be/pinjepunt", + "https://mapcomplete.osm.be/toerisme_vlaanderenn" + ] + }, + { + "path": "pin je punt3.jpg", + "license": "CC0", + "authors": [ + "Toerisme Vlaanderen" + ], + "sources": [ + "https://toerismevlaanderen.be/pinjepunt", + "https://mapcomplete.osm.be/toerisme_vlaanderenn" + ] + }, + { + "path": "pin je punt4.jpg", + "license": "CC0", + "authors": [ + "Toerisme Vlaanderen" + ], + "sources": [ + "https://toerismevlaanderen.be/pinjepunt", + "https://mapcomplete.osm.be/toerisme_vlaanderenn" + ] + }, + { + "path": "pin je punt5.jpg", + "license": "CC0", + "authors": [ + "Toerisme Vlaanderen" + ], + "sources": [ + "https://toerismevlaanderen.be/pinjepunt", + "https://mapcomplete.osm.be/toerisme_vlaanderenn" + ] + }, + { + "path": "pin je punt6.jpg", + "license": "CC0", + "authors": [ + "Toerisme Vlaanderen" + ], + "sources": [ + "https://toerismevlaanderen.be/pinjepunt", + "https://mapcomplete.osm.be/toerisme_vlaanderenn" + ] + }, { "path": "playground.svg", "license": "CC0", diff --git a/assets/themes/toerisme_vlaanderen/toerisme_vlaanderen.json b/assets/themes/toerisme_vlaanderen/toerisme_vlaanderen.json index 24f0208611..fa0f7383fb 100644 --- a/assets/themes/toerisme_vlaanderen/toerisme_vlaanderen.json +++ b/assets/themes/toerisme_vlaanderen/toerisme_vlaanderen.json @@ -50,7 +50,7 @@ ] } }, - "=filter": null, + "filter": null, "=mapRendering": [ { "location": [ @@ -242,7 +242,8 @@ ] }, "hideTagRenderingsWithLabels": [ - "extra" + "extra", + "website" ] } ], diff --git a/assets/themes/uk_addresses/uk_addresses.json b/assets/themes/uk_addresses/uk_addresses.json index 75a10030c4..80bccb856b 100644 --- a/assets/themes/uk_addresses/uk_addresses.json +++ b/assets/themes/uk_addresses/uk_addresses.json @@ -123,7 +123,16 @@ }, { "id": "uk_addresses_import_button", - "render": "{import_button(address,urpn_count=$urpn_count;ref:GB:uprn=$ref:GB:uprn$, Add this address, ./assets/themes/uk_addresses/housenumber_add.svg)}" + "render": { + "special": { + "type": "import_button", + "targetLayer": "address", + "tags": "urpn_count=$urpn_count;ref:GB:uprn=$ref:GB:uprn$", + "text": "Add this address", + "icon": "./assets/themes/uk_addresses/housenumber_add.svg", + "location_picker": "none" + } + } } ], "calculatedTags": [ diff --git a/assets/translators.json b/assets/translators.json index ad1f987e45..b7e86ca859 100644 --- a/assets/translators.json +++ b/assets/translators.json @@ -1 +1 @@ -{"contributors":[{"commits":60,"contributor":"danieldegroot2"},{"commits":53,"contributor":"Pieter Vander Vennet"},{"commits":43,"contributor":"kjon"},{"commits":29,"contributor":"Artem"},{"commits":25,"contributor":"Babos Gábor"},{"commits":22,"contributor":"Supaplex"},{"commits":22,"contributor":"Marco"},{"commits":22,"contributor":"Allan Nordhøy"},{"commits":21,"contributor":"Anonymous"},{"commits":15,"contributor":"WaldiS"},{"commits":14,"contributor":"Reza Almanda"},{"commits":14,"contributor":"J. Lavoie"},{"commits":13,"contributor":"SC"},{"commits":10,"contributor":"Joost"},{"commits":10,"contributor":"Robin van der Linde"},{"commits":9,"contributor":"Jacque Fresco"},{"commits":8,"contributor":"LeJun"},{"commits":8,"contributor":"Irina"},{"commits":6,"contributor":"Štefan Baebler"},{"commits":6,"contributor":"seppesantens"},{"commits":6,"contributor":"Nikolay Korotkiy"},{"commits":6,"contributor":"William Weber Berrutti"},{"commits":6,"contributor":"lvgx"},{"commits":5,"contributor":"Romain de Bossoreille"},{"commits":5,"contributor":"Piotr"},{"commits":5,"contributor":"Vinicius"},{"commits":5,"contributor":"Alexey Shabanov"},{"commits":4,"contributor":"Jeff Huang"},{"commits":4,"contributor":"Adolfo Jayme Barrientos"},{"commits":4,"contributor":"Polgár Sándor"},{"commits":4,"contributor":"David Haberthür"},{"commits":4,"contributor":"phlostically"},{"commits":4,"contributor":"Jan Zabel"},{"commits":4,"contributor":"Fabio Bettani"},{"commits":3,"contributor":"Sasha"},{"commits":3,"contributor":"Jose Luis Infante"},{"commits":3,"contributor":"Francois"},{"commits":3,"contributor":"Eduardo Addad de Oliveira"},{"commits":3,"contributor":"Wiktor Przybylski"},{"commits":3,"contributor":"Erik Palm"},{"commits":3,"contributor":"vankos"},{"commits":3,"contributor":"JCGF-OSM"},{"commits":3,"contributor":"Hiroshi Miura"},{"commits":3,"contributor":"SiegbjornSitumeang"},{"commits":2,"contributor":"MeblIkea"},{"commits":2,"contributor":"快乐的老鼠宝宝"},{"commits":2,"contributor":"わたなべけんご"},{"commits":2,"contributor":"Mateusz Konieczny"},{"commits":2,"contributor":"Kristoffer Grundström"},{"commits":2,"contributor":"el_libre como el chaval"},{"commits":2,"contributor":"Sebastian Kürten"},{"commits":2,"contributor":"Damian Tokarski"},{"commits":2,"contributor":"mic140"},{"commits":2,"contributor":"Heiko"},{"commits":2,"contributor":"Leo Alcaraz"},{"commits":1,"contributor":"Falk Rund"},{"commits":1,"contributor":"pdassori"},{"commits":1,"contributor":"sparky-oxford"},{"commits":1,"contributor":"jcn706"},{"commits":1,"contributor":"whatismoss"},{"commits":1,"contributor":"LePirlouit"},{"commits":1,"contributor":"SoftwareByRedline"},{"commits":1,"contributor":"plic ploc"},{"commits":1,"contributor":"Janina Ellinghaus"},{"commits":1,"contributor":"ssantos"},{"commits":1,"contributor":"Andre Fajar N"},{"commits":1,"contributor":"Ahen Purwakarta"},{"commits":1,"contributor":"Luna Jernberg"},{"commits":1,"contributor":"Rodrigo Tavares"},{"commits":1,"contributor":"liimee"},{"commits":1,"contributor":"Michał Targoński"},{"commits":1,"contributor":"Sean Young"},{"commits":1,"contributor":"Damian Pułka"},{"commits":1,"contributor":"Iváns"},{"commits":1,"contributor":"Eric Armijo"},{"commits":1,"contributor":"Beardhatcode"},{"commits":1,"contributor":"riiga"},{"commits":1,"contributor":"Carlos Ramos Carreño"}]} \ No newline at end of file +{"contributors":[{"commits":60,"contributor":"danieldegroot2"},{"commits":47,"contributor":"Pieter Vander Vennet"},{"commits":43,"contributor":"kjon"},{"commits":29,"contributor":"Artem"},{"commits":25,"contributor":"Babos Gábor"},{"commits":22,"contributor":"Supaplex"},{"commits":22,"contributor":"Marco"},{"commits":22,"contributor":"Allan Nordhøy"},{"commits":21,"contributor":"Anonymous"},{"commits":15,"contributor":"WaldiS"},{"commits":14,"contributor":"Reza Almanda"},{"commits":14,"contributor":"J. Lavoie"},{"commits":13,"contributor":"SC"},{"commits":10,"contributor":"Robin van der Linde"},{"commits":9,"contributor":"Jacque Fresco"},{"commits":8,"contributor":"Joost"},{"commits":8,"contributor":"LeJun"},{"commits":8,"contributor":"Irina"},{"commits":6,"contributor":"Štefan Baebler"},{"commits":6,"contributor":"seppesantens"},{"commits":6,"contributor":"Nikolay Korotkiy"},{"commits":6,"contributor":"William Weber Berrutti"},{"commits":6,"contributor":"lvgx"},{"commits":5,"contributor":"Romain de Bossoreille"},{"commits":5,"contributor":"Piotr"},{"commits":5,"contributor":"Vinicius"},{"commits":5,"contributor":"Alexey Shabanov"},{"commits":4,"contributor":"Jeff Huang"},{"commits":4,"contributor":"Adolfo Jayme Barrientos"},{"commits":4,"contributor":"Polgár Sándor"},{"commits":4,"contributor":"David Haberthür"},{"commits":4,"contributor":"phlostically"},{"commits":4,"contributor":"Jan Zabel"},{"commits":4,"contributor":"Fabio Bettani"},{"commits":3,"contributor":"Sasha"},{"commits":3,"contributor":"Jose Luis Infante"},{"commits":3,"contributor":"Francois"},{"commits":3,"contributor":"Eduardo Addad de Oliveira"},{"commits":3,"contributor":"Wiktor Przybylski"},{"commits":3,"contributor":"Erik Palm"},{"commits":3,"contributor":"vankos"},{"commits":3,"contributor":"JCGF-OSM"},{"commits":3,"contributor":"Hiroshi Miura"},{"commits":3,"contributor":"SiegbjornSitumeang"},{"commits":2,"contributor":"MeblIkea"},{"commits":2,"contributor":"快乐的老鼠宝宝"},{"commits":2,"contributor":"わたなべけんご"},{"commits":2,"contributor":"Mateusz Konieczny"},{"commits":2,"contributor":"Kristoffer Grundström"},{"commits":2,"contributor":"el_libre como el chaval"},{"commits":2,"contributor":"Sebastian Kürten"},{"commits":2,"contributor":"Damian Tokarski"},{"commits":2,"contributor":"mic140"},{"commits":2,"contributor":"Heiko"},{"commits":2,"contributor":"Leo Alcaraz"},{"commits":1,"contributor":"Falk Rund"},{"commits":1,"contributor":"pdassori"},{"commits":1,"contributor":"sparky-oxford"},{"commits":1,"contributor":"jcn706"},{"commits":1,"contributor":"whatismoss"},{"commits":1,"contributor":"LePirlouit"},{"commits":1,"contributor":"SoftwareByRedline"},{"commits":1,"contributor":"plic ploc"},{"commits":1,"contributor":"Janina Ellinghaus"},{"commits":1,"contributor":"ssantos"},{"commits":1,"contributor":"Andre Fajar N"},{"commits":1,"contributor":"Ahen Purwakarta"},{"commits":1,"contributor":"Luna Jernberg"},{"commits":1,"contributor":"Rodrigo Tavares"},{"commits":1,"contributor":"liimee"},{"commits":1,"contributor":"Michał Targoński"},{"commits":1,"contributor":"Sean Young"},{"commits":1,"contributor":"Damian Pułka"},{"commits":1,"contributor":"Iváns"},{"commits":1,"contributor":"Eric Armijo"},{"commits":1,"contributor":"Beardhatcode"},{"commits":1,"contributor":"riiga"},{"commits":1,"contributor":"Carlos Ramos Carreño"}]} \ No newline at end of file diff --git a/css/index-tailwind-output.css b/css/index-tailwind-output.css index d44c18b2d4..a41659488f 100644 --- a/css/index-tailwind-output.css +++ b/css/index-tailwind-output.css @@ -706,6 +706,7 @@ video { } .sticky { + position: -webkit-sticky; position: sticky; } @@ -1039,6 +1040,10 @@ video { height: 50%; } +.h-4 { + height: 1rem; +} + .h-screen { height: 100vh; } @@ -1059,10 +1064,6 @@ video { height: 4rem; } -.h-4 { - height: 1rem; -} - .h-0 { height: 0px; } @@ -1131,6 +1132,10 @@ video { width: 0px; } +.w-4 { + width: 1rem; +} + .w-screen { width: 100vw; } @@ -1139,10 +1144,6 @@ video { width: 2.75rem; } -.w-4 { - width: 1rem; -} - .w-16 { width: 4rem; } @@ -1411,6 +1412,11 @@ video { border-color: rgba(0, 0, 0, var(--tw-border-opacity)); } +.border-gray-400 { + --tw-border-opacity: 1; + border-color: rgba(156, 163, 175, var(--tw-border-opacity)); +} + .border-gray-300 { --tw-border-opacity: 1; border-color: rgba(209, 213, 219, var(--tw-border-opacity)); @@ -1421,11 +1427,6 @@ video { border-color: rgba(252, 165, 165, var(--tw-border-opacity)); } -.border-gray-400 { - --tw-border-opacity: 1; - border-color: rgba(156, 163, 175, var(--tw-border-opacity)); -} - .border-gray-200 { --tw-border-opacity: 1; border-color: rgba(229, 231, 235, var(--tw-border-opacity)); @@ -1440,6 +1441,11 @@ video { background-color: rgba(255, 255, 255, var(--tw-bg-opacity)); } +.bg-red-400 { + --tw-bg-opacity: 1; + background-color: rgba(248, 113, 113, var(--tw-bg-opacity)); +} + .bg-gray-400 { --tw-bg-opacity: 1; background-color: rgba(156, 163, 175, var(--tw-bg-opacity)); @@ -1504,10 +1510,6 @@ video { padding: 0.125rem; } -.p-8 { - padding: 2rem; -} - .px-0 { padding-left: 0px; padding-right: 0px; @@ -1911,6 +1913,10 @@ svg, img { display: none; } +.weblate-link { + /* Weblate-links are the little translation icon next to translatable sentences. Due to their special nature, they are exempt from some rules */ +} + .mapcontrol svg path { fill: var(--subtle-detail-color-contrast) !important; } diff --git a/index.css b/index.css index 921261d458..77c7b01600 100644 --- a/index.css +++ b/index.css @@ -151,6 +151,10 @@ svg, img { display: none; } +.weblate-link { + /* Weblate-links are the little translation icon next to translatable sentences. Due to their special nature, they are exempt from some rules */ +} + .mapcontrol svg path { fill: var(--subtle-detail-color-contrast) !important; } diff --git a/index.ts b/index.ts index 58a0e54b79..355eb5e930 100644 --- a/index.ts +++ b/index.ts @@ -26,7 +26,7 @@ class Init { if (layoutToUse === undefined) { // No layout found - new AllThemesGui() + new AllThemesGui().setup() return; } @@ -36,9 +36,7 @@ class Init { // This 'leaks' the global state via the window object, useful for debugging // @ts-ignore window.mapcomplete_state = State.state; - new DefaultGUI(State.state, guiState) - - + new DefaultGUI(State.state, guiState).setup() } } diff --git a/langs/en.json b/langs/en.json index 2af8321ffc..422169ff85 100644 --- a/langs/en.json +++ b/langs/en.json @@ -246,6 +246,10 @@ "loading": "Loading Wikipedia...", "noResults": "Nothing found for {search}", "noWikipediaPage": "This Wikidata item has no corresponding Wikipedia page yet.", + "previewbox": { + "born": "Born: {value}", + "died": "Died: {value}" + }, "searchWikidata": "Search on Wikidata", "wikipediaboxTitle": "Wikipedia" } @@ -359,6 +363,7 @@ "autoApply": "When changing the attributes {attr_names}, these attributes will automatically be changed on {count} other objects too" }, "notes": { + "addAComment": "Add a comment", "addComment": "Add comment", "addCommentAndClose": "Add comment and close", "addCommentPlaceholder": "Add a comment...", @@ -525,6 +530,15 @@ "split": "Split", "splitTitle": "Choose on the map where to split this road" }, + "translations": { + "activateButton": "Help to translate MapComplete", + "completeness": "Translations for {theme} in {language} are at {percentage}%: {translated} strings out of {total} are translated", + "deactivate": "Disable translation buttons", + "help": "Click the 'translate'-icon next to a string to enter or update a piece of text. You need a Weblate-account for this. Create one with your OSM-username to automatically unlock translation mode.", + "isTranslator": "Translation mode is active as your username matches the name of a previous translator", + "missing": "{count} untranslated strings", + "notImmediate": "Translations are not updated directly. This typically takes a few days" + }, "validation": { "color": { "description": "A color or hexcode" diff --git a/langs/layers/en.json b/langs/layers/en.json index 6fd10dbccf..3a225cadb6 100644 --- a/langs/layers/en.json +++ b/langs/layers/en.json @@ -1062,6 +1062,9 @@ }, "question": "Are there tools here to repair your own bike?" }, + "bike_shop-access": { + "render": "Only accessible to {access}" + }, "bike_shop-email": { "question": "What is the email address of {name}?" }, @@ -4409,6 +4412,22 @@ } }, "description": "A shop", + "filter": { + "0": { + "options": { + "0": { + "question": "Only show shops selling {search}" + } + } + }, + "1": { + "options": { + "0": { + "question": "Only show shops with name {search}" + } + } + } + }, "name": "Shop", "presets": { "0": { diff --git a/langs/layers/nl.json b/langs/layers/nl.json index 9399e05146..2891ca55c8 100644 --- a/langs/layers/nl.json +++ b/langs/layers/nl.json @@ -1062,6 +1062,9 @@ }, "question": "Biedt deze winkel gereedschap aan om je fiets zelf te herstellen?" }, + "bike_shop-access": { + "render": "Enkel voor {access}" + }, "bike_shop-email": { "question": "Wat is het email-adres van {name}?" }, diff --git a/langs/themes/nl.json b/langs/themes/nl.json index 6d0cbe4236..e793889d5e 100644 --- a/langs/themes/nl.json +++ b/langs/themes/nl.json @@ -860,9 +860,6 @@ "hailhydrant": { "title": "Brandkranen, brandblussers, brandweerposten en ambulanceposten" }, - "mapcomplete-changes": { - "title": "Wijzigingen gemaakt met MapComplete" - }, "maps": { "description": "Op deze kaart kan je alle kaarten zien die OpenStreetMap kent.

Ontbreekt er een kaart, dan kan je die kaart hier ook gemakelijk aan deze kaart toevoegen.", "shortDescription": "Een kaart met alle kaarten die OpenStreetMap kent", diff --git a/package-lock.json b/package-lock.json index 48e04ca737..34bf3624d1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,7 +26,7 @@ "@types/wikidata-sdk": "^6.1.0", "@types/xml2js": "^0.4.9", "country-language": "^0.1.7", - "doctest-ts-improved": "^0.8.4", + "doctest-ts-improved": "^0.8.6", "email-validator": "^2.0.4", "escape-html": "^1.0.3", "geojson2svg": "^1.3.1", @@ -6024,14 +6024,15 @@ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" }, "node_modules/doctest-ts-improved": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/doctest-ts-improved/-/doctest-ts-improved-0.8.4.tgz", - "integrity": "sha512-CMVSnyDB00sLkTqHIZ20Z/kHD2XczNHwWkD4UC4retGaSfuP8XG4cnAGwkr8qoQq3mjc3w8O4w3OTWrC4HC2vA==", + "version": "0.8.6", + "resolved": "https://registry.npmjs.org/doctest-ts-improved/-/doctest-ts-improved-0.8.6.tgz", + "integrity": "sha512-J7fXMJ29ve6DUsUHKEO5bOwGmYjhNZd88L7NMVDKIiLIiUCJ9zkR2k7IZOGjMC0RXw/q788REawcMUgIj+7Muw==", "dependencies": { "@types/chai": "^4.3.0", "chai": "^4.3.6", "global": "^4.3.2", "mocha": "^9.2.2", + "process-yargs-parser": "^2.1.0", "typescript": "^4.6.2" }, "bin": { @@ -12326,6 +12327,11 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, + "node_modules/process-yargs-parser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/process-yargs-parser/-/process-yargs-parser-2.1.0.tgz", + "integrity": "sha512-tzMsZn3lKksICtEhICR/k+Qv1UmQNVtzm0FaL10OiGJtw0ixgw0woNefcREDc6ZjqXOKBSruRagyULuwZ4FK4Q==" + }, "node_modules/prompt-sync": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/prompt-sync/-/prompt-sync-4.2.0.tgz", @@ -21413,14 +21419,15 @@ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" }, "doctest-ts-improved": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/doctest-ts-improved/-/doctest-ts-improved-0.8.4.tgz", - "integrity": "sha512-CMVSnyDB00sLkTqHIZ20Z/kHD2XczNHwWkD4UC4retGaSfuP8XG4cnAGwkr8qoQq3mjc3w8O4w3OTWrC4HC2vA==", + "version": "0.8.6", + "resolved": "https://registry.npmjs.org/doctest-ts-improved/-/doctest-ts-improved-0.8.6.tgz", + "integrity": "sha512-J7fXMJ29ve6DUsUHKEO5bOwGmYjhNZd88L7NMVDKIiLIiUCJ9zkR2k7IZOGjMC0RXw/q788REawcMUgIj+7Muw==", "requires": { "@types/chai": "^4.3.0", "chai": "^4.3.6", "global": "^4.3.2", "mocha": "^9.2.2", + "process-yargs-parser": "^2.1.0", "typescript": "^4.6.2" }, "dependencies": { @@ -26306,6 +26313,11 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, + "process-yargs-parser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/process-yargs-parser/-/process-yargs-parser-2.1.0.tgz", + "integrity": "sha512-tzMsZn3lKksICtEhICR/k+Qv1UmQNVtzm0FaL10OiGJtw0ixgw0woNefcREDc6ZjqXOKBSruRagyULuwZ4FK4Q==" + }, "prompt-sync": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/prompt-sync/-/prompt-sync-4.2.0.tgz", diff --git a/package.json b/package.json index d1a39a6e8d..8a84395bcf 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,8 @@ "strttest": "export NODE_OPTIONS=--max_old_space_size=8364 && parcel serve test.html", "watch:css": "tailwindcss -i index.css -o css/index-tailwind-output.css --watch", "generate:css": "tailwindcss -i index.css -o css/index-tailwind-output.css", - "generate:doctests": "doctest-ts-improved .", - "test:run-only": "mocha --require ts-node/register --require tests/testhooks.ts \"./**/*.doctest.ts\" \"tests/*\" \"tests/**/*.ts\"", + "generate:doctests": "doctest-ts-improved . --ignore .*.spec.ts --ignore .*ConfigJson.ts", + "test:run-only": "mocha --require ts-node/register --require test/testhooks.ts \"./**/*.doctest.ts\" \"test/*\" \"test/**/*.ts\"", "test": "(npm run generate:doctests 2>&1 | grep -v \"No doctests found in\") && npm run test:run-only && npm run clean:tests", "init": "npm ci && npm run generate && npm run generate:editor-layer-index && npm run generate:layouts && npm run clean", "add-weblate-upstream": "git remote add weblate-layers https://hosted.weblate.org/git/mapcomplete/layer-translations/ ; git remote add weblate-core https://hosted.weblate.org/git/mapcomplete/layer-core/; git remote add weblate-themes https://hosted.weblate.org/git/mapcomplete/layer-themes/; git remote add weblate-github git@github.com:weblate/MapComplete.git", @@ -44,7 +44,7 @@ "gittag": "ts-node scripts/printVersion.ts | bash", "lint": "tslint --project . -c tslint.json '**.ts' ", "clean:tests": "(find . -type f -name \"*.doctest.ts\" | xargs rm)", - "clean": "rm -rf .cache/ && (find *.html | grep -v \"\\(404\\|index\\|land\\|test\\|preferences\\|customGenerator\\|professional\\|automaton\\|import_helper\\|import_viewer\\|theme\\).html\" | xargs rm) && (ls | grep \"^index_[a-zA-Z_]\\+\\.ts$\" | xargs rm) && (ls | grep \".*.webmanifest$\" | xargs rm)", + "clean": "rm -rf .cache/ && (find *.html | grep -v \"\\(404\\|index\\|land\\|test\\|preferences\\|customGenerator\\|professional\\|automaton\\|import_helper\\|import_viewer\\|theme\\).html\" | xargs rm) && (ls | grep \"^index_[a-zA-Z_-]\\+\\.ts$\" | xargs rm) && (ls | grep \".*.webmanifest$\" | xargs rm)", "generate:dependency-graph": "node_modules/.bin/depcruise --exclude \"^node_modules\" --output-type dot Logic/State/MapState.ts > dependencies.dot && dot dependencies.dot -T svg -o dependencies.svg && rm dependencies.dot", "script": "ts-node" }, @@ -72,7 +72,7 @@ "@types/wikidata-sdk": "^6.1.0", "@types/xml2js": "^0.4.9", "country-language": "^0.1.7", - "doctest-ts-improved": "^0.8.4", + "doctest-ts-improved": "^0.8.6", "email-validator": "^2.0.4", "escape-html": "^1.0.3", "geojson2svg": "^1.3.1", diff --git a/scripts/generateDocs.ts b/scripts/generateDocs.ts index 4d43d5c027..de9a995c96 100644 --- a/scripts/generateDocs.ts +++ b/scripts/generateDocs.ts @@ -1,7 +1,7 @@ import Combine from "../UI/Base/Combine"; import BaseUIElement from "../UI/BaseUIElement"; import Translations from "../UI/i18n/Translations"; -import {existsSync, writeFileSync} from "fs"; +import {existsSync, mkdir, mkdirSync, writeFileSync} from "fs"; import {AllKnownLayouts} from "../Customizations/AllKnownLayouts"; import TableOfContents from "../UI/Base/TableOfContents"; import SimpleMetaTaggers, {SimpleMetaTagger} from "../Logic/SimpleMetaTagger"; @@ -18,7 +18,9 @@ import ScriptUtils from "./ScriptUtils"; import List from "../UI/Base/List"; import SharedTagRenderings from "../Customizations/SharedTagRenderings"; -function WriteFile(filename, html: BaseUIElement, autogenSource: string[]): void { +function WriteFile(filename, html: BaseUIElement, autogenSource: string[], options?: { + noTableOfContents: boolean +}): void { for (const source of autogenSource) { @@ -30,7 +32,7 @@ function WriteFile(filename, html: BaseUIElement, autogenSource: string[]): void } } - if (html instanceof Combine) { + if (html instanceof Combine && !(options?.noTableOfContents)) { const toc = new TableOfContents(html); const els = html.getElements(); html = new Combine( @@ -51,9 +53,16 @@ function WriteFile(filename, html: BaseUIElement, autogenSource: string[]): void } console.log("Starting documentation generation...") -AllKnownLayouts.GenOverviewsForSingleLayer((layer, element) => { +AllKnownLayouts.GenOverviewsForSingleLayer((layer, element, inlineSource) => { console.log("Exporting ", layer.id) - WriteFile("./Docs/Layers/" + layer.id + ".md", element, [`assets/layers/${layer.id}/${layer.id}.json`]) + if(!existsSync("./Docs/Layers")){ + mkdirSync("./Docs/Layers") + } + let source: string = `assets/layers/${layer.id}/${layer.id}.json` + if(inlineSource !== undefined){ + source = `assets/themes/${inlineSource}/${inlineSource}.json` + } + WriteFile("./Docs/Layers/" + layer.id + ".md", element, [source], {noTableOfContents: true}) }) WriteFile("./Docs/SpecialRenderings.md", SpecialVisualizations.HelpMessage(), ["UI/SpecialVisualizations.ts"]) diff --git a/scripts/generateLayerOverview.ts b/scripts/generateLayerOverview.ts index 5c8b4836b0..d9faf2d9ab 100644 --- a/scripts/generateLayerOverview.ts +++ b/scripts/generateLayerOverview.ts @@ -19,7 +19,7 @@ import {DesugaringContext} from "../Models/ThemeConfig/Conversion/Conversion"; class LayerOverviewUtils { - writeSmallOverview(themes: { id: string, title: any, shortDescription: any, icon: string, hideFromOverview: boolean }[]) { + writeSmallOverview(themes: { id: string, title: any, shortDescription: any, icon: string, hideFromOverview: boolean, mustHaveLanguage: boolean }[]) { const perId = new Map(); for (const theme of themes) { const data = { @@ -27,7 +27,8 @@ class LayerOverviewUtils { title: theme.title, shortDescription: theme.shortDescription, icon: theme.icon, - hideFromOverview: theme.hideFromOverview + hideFromOverview: theme.hideFromOverview, + mustHaveLanguage: theme.mustHaveLanguage } perId.set(theme.id, data); } @@ -73,6 +74,7 @@ class LayerOverviewUtils { continue } questions[key].id = key; + questions[key]["source"] = "shared-questions" dict.set(key, questions[key]) } for (const key in icons["default"]) { @@ -218,7 +220,8 @@ class LayerOverviewUtils { return { ...t, hideFromOverview: t.hideFromOverview ?? false, - shortDescription: t.shortDescription ?? new Translation(t.description).FirstSentence().translations + shortDescription: t.shortDescription ?? new Translation(t.description).FirstSentence().translations, + mustHaveLanguage: t.mustHaveLanguage?.length > 0 } })); return fixed; diff --git a/scripts/generateTranslations.ts b/scripts/generateTranslations.ts index 259563bb90..71dae3c505 100644 --- a/scripts/generateTranslations.ts +++ b/scripts/generateTranslations.ts @@ -2,6 +2,8 @@ import * as fs from "fs"; import {readFileSync, writeFileSync} from "fs"; import {Utils} from "../Utils"; import ScriptUtils from "./ScriptUtils"; +import {AllKnownLayouts} from "../Customizations/AllKnownLayouts"; +import TranslatorsPanel from "../UI/BigComponents/TranslatorsPanel"; const knownLanguages = ["en", "nl", "de", "fr", "es", "gl", "ca"]; @@ -244,11 +246,11 @@ function isTranslation(tr: any): boolean { } /** - * Converts a translation object into something that can be added to the 'generated translations' - * @param obj - * @param depth + * Converts a translation object into something that can be added to the 'generated translations'. + * + * To debug the 'compiledTranslations', add a languageWhiteList to only generate a single language */ -function transformTranslation(obj: any, depth = 1) { +function transformTranslation(obj: any, path: string[] = [], languageWhitelist : string[] = undefined) { if (isTranslation(obj)) { return `new Translation( ${JSON.stringify(obj)} )` @@ -259,15 +261,24 @@ function transformTranslation(obj: any, depth = 1) { if (key === "#") { continue; } + if (key.match("^[a-zA-Z0-9_]*$") === null) { throw "Invalid character in key: " + key } - const value = obj[key] + let value = obj[key] if (isTranslation(value)) { - values += (Utils.Times((_) => " ", depth)) + "get " + key + "() { return new Translation(" + JSON.stringify(value) + ") }" + ",\n" + if(languageWhitelist !== undefined){ + const nv = {} + for (const ln of languageWhitelist) { + nv[ln] = value[ln] + } + value = nv; + } + values += `${Utils.Times((_) => " ", path.length + 1)}get ${key}() { return new Translation(${JSON.stringify(value)}, "core:${path.join(".")}.${key}") }, +` } else { - values += (Utils.Times((_) => " ", depth)) + key + ": " + transformTranslation(value, depth + 1) + ",\n" + values += (Utils.Times((_) => " ", path.length + 1)) + key + ": " + transformTranslation(value, [...path, key], languageWhitelist) + ",\n" } } return `{${values}}`; @@ -305,11 +316,11 @@ function formatFile(path) { */ function genTranslations() { const translations = JSON.parse(fs.readFileSync("./assets/generated/translations.json", "utf-8")) - const transformed = transformTranslation(translations); + const transformed = transformTranslation(translations); let module = `import {Translation} from "../../UI/i18n/Translation"\n\nexport default class CompiledTranslations {\n\n`; module += " public static t = " + transformed; - module += "}" + module += "\n }" fs.writeFileSync("./assets/generated/CompiledTranslations.ts", module); @@ -525,7 +536,7 @@ const l1 = generateTranslationsObjectFrom(ScriptUtils.getLayerFiles(), "layers") const l2 = generateTranslationsObjectFrom(ScriptUtils.getThemeFiles().filter(th => th.parsed.mustHaveLanguage === undefined), "themes") const l3 = generateTranslationsObjectFrom([{path: questionsPath, parsed: questionsParsed}], "shared-questions") -const usedLanguages = Utils.Dedup(l1.concat(l2).concat(l3)).filter(v => v !== "*") +const usedLanguages: string[] = Utils.Dedup(l1.concat(l2).concat(l3)).filter(v => v !== "*") usedLanguages.sort() fs.writeFileSync("./assets/generated/used_languages.json", JSON.stringify({languages: usedLanguages})) @@ -541,8 +552,9 @@ for (const path of allTranslationFiles) { } -// SOme validation +// Some validation TranslationPart.fromDirectory("./langs").validateStrict("./langs") TranslationPart.fromDirectory("./langs/layers").validateStrict("layers") TranslationPart.fromDirectory("./langs/themes").validateStrict("themes") TranslationPart.fromDirectory("./langs/shared-questions").validateStrict("shared-questions") + diff --git a/scripts/translationStatistics.ts b/scripts/translationStatistics.ts new file mode 100644 index 0000000000..12a81b9381 --- /dev/null +++ b/scripts/translationStatistics.ts @@ -0,0 +1,44 @@ +import {Utils} from "../Utils"; +import {AllKnownLayouts} from "../Customizations/AllKnownLayouts"; +import TranslatorsPanel from "../UI/BigComponents/TranslatorsPanel"; +import * as languages from "../assets/generated/used_languages.json" +{ + const usedLanguages = languages.languages + + // Some statistics + console.log(Utils.FixedLength("", 12) + " " + usedLanguages.map(l => Utils.FixedLength(l, 6)).join("")) + const all = new Map() + + usedLanguages.forEach(ln => all.set(ln, [])) + + for (const layoutId of Array.from(AllKnownLayouts.allKnownLayouts.keys())) { + const layout = AllKnownLayouts.allKnownLayouts.get(layoutId) + if(layout.hideFromOverview){ + continue + } + const {completeness, total} = TranslatorsPanel.MissingTranslationsFor(layout) + process.stdout.write(Utils.FixedLength(layout.id, 12) + " ") + for (const language of usedLanguages) { + const compl = completeness.get(language) + all.get(language).push((compl ?? 0) / total) + if (compl === undefined) { + process.stdout.write(" ") + continue + } + const percentage = Math.round(100 * compl / total) + process.stdout.write(Utils.FixedLength(percentage + "%", 6)) + } + process.stdout.write("\n") + } + + process.stdout.write(Utils.FixedLength("average", 12) + " ") + for (const language of usedLanguages) { + const ratios = all.get(language) + let sum = 0 + ratios.forEach(x => sum += x) + const percentage = Math.round(100 * (sum / ratios.length)) + process.stdout.write(Utils.FixedLength(percentage + "%", 6)) + } + process.stdout.write("\n") + console.log(Utils.FixedLength("", 12) + " " + usedLanguages.map(l => Utils.FixedLength(l, 6)).join("")) +} \ No newline at end of file diff --git a/test.ts b/test.ts index fdd7f691e8..9a6b02f972 100644 --- a/test.ts +++ b/test.ts @@ -13,8 +13,7 @@ new Combine( try { inp = ValidatedTextField.ForType(key).ConstructInputElement({ feedback, - country: () => "be", - + country: () => "be" }); } catch (e) { console.error(e) @@ -29,5 +28,4 @@ new Combine( ]); } ) -).AttachTo("maindiv") - +).AttachTo("maindiv") \ No newline at end of file diff --git a/tests/Chai.spec.ts b/test/Chai.spec.ts similarity index 87% rename from tests/Chai.spec.ts rename to test/Chai.spec.ts index cc11fcb7f1..b7a2f54db9 100644 --- a/tests/Chai.spec.ts +++ b/test/Chai.spec.ts @@ -4,7 +4,7 @@ import {Utils} from "../Utils"; describe("TestSuite", () => { - describe("function onder test", () => { + describe("function under test", () => { it("should work", () => { expect("abc").eq("abc") }) diff --git a/tests/CodeQuality.spec.ts b/test/CodeQuality.spec.ts similarity index 94% rename from tests/CodeQuality.spec.ts rename to test/CodeQuality.spec.ts index a3db97b4e4..33fffcb54f 100644 --- a/tests/CodeQuality.spec.ts +++ b/test/CodeQuality.spec.ts @@ -24,7 +24,7 @@ function detectInCode(forbidden: string, reason: string) { throw stderr } - const found = stdout.split("\n").filter(s => s !== "").filter(s => !s.startsWith("./tests/") && !s.startsWith("./testLegacy/")); + const found = stdout.split("\n").filter(s => s !== "").filter(s => !s.startsWith("./test/")); if (found.length > 0) { throw `Found a '${forbidden}' at \n ${found.join("\n ")}.\n ${reason}` } diff --git a/tests/Logic/Actors/Actors.spec.ts b/test/Logic/Actors/Actors.spec.ts similarity index 100% rename from tests/Logic/Actors/Actors.spec.ts rename to test/Logic/Actors/Actors.spec.ts diff --git a/tests/Logic/Actors/CreateMultiPolygonWithPointReuseAction.spec.ts b/test/Logic/Actors/CreateMultiPolygonWithPointReuseAction.spec.ts similarity index 100% rename from tests/Logic/Actors/CreateMultiPolygonWithPointReuseAction.spec.ts rename to test/Logic/Actors/CreateMultiPolygonWithPointReuseAction.spec.ts diff --git a/tests/Logic/FeatureSource/TileFreshnessCalculator.spec.ts b/test/Logic/FeatureSource/TileFreshnessCalculator.spec.ts similarity index 100% rename from tests/Logic/FeatureSource/TileFreshnessCalculator.spec.ts rename to test/Logic/FeatureSource/TileFreshnessCalculator.spec.ts diff --git a/tests/Logic/GeoOperations.spec.ts b/test/Logic/GeoOperations.spec.ts similarity index 100% rename from tests/Logic/GeoOperations.spec.ts rename to test/Logic/GeoOperations.spec.ts diff --git a/tests/Logic/ImageProviders/ImageProviders.spec.ts b/test/Logic/ImageProviders/ImageProviders.spec.ts similarity index 100% rename from tests/Logic/ImageProviders/ImageProviders.spec.ts rename to test/Logic/ImageProviders/ImageProviders.spec.ts diff --git a/tests/Logic/OSM/Actions/RelationSplitHandler.spec.ts b/test/Logic/OSM/Actions/RelationSplitHandler.spec.ts similarity index 100% rename from tests/Logic/OSM/Actions/RelationSplitHandler.spec.ts rename to test/Logic/OSM/Actions/RelationSplitHandler.spec.ts diff --git a/tests/Logic/OSM/Actions/ReplaceGeometryAction.spec.ts b/test/Logic/OSM/Actions/ReplaceGeometryAction.spec.ts similarity index 100% rename from tests/Logic/OSM/Actions/ReplaceGeometryAction.spec.ts rename to test/Logic/OSM/Actions/ReplaceGeometryAction.spec.ts diff --git a/tests/Logic/OSM/Actions/SplitAction.spec.ts b/test/Logic/OSM/Actions/SplitAction.spec.ts similarity index 100% rename from tests/Logic/OSM/Actions/SplitAction.spec.ts rename to test/Logic/OSM/Actions/SplitAction.spec.ts diff --git a/tests/Logic/OSM/Changes.spec.ts b/test/Logic/OSM/Changes.spec.ts similarity index 100% rename from tests/Logic/OSM/Changes.spec.ts rename to test/Logic/OSM/Changes.spec.ts diff --git a/tests/Logic/OSM/ChangesetHandler.spec.ts b/test/Logic/OSM/ChangesetHandler.spec.ts similarity index 100% rename from tests/Logic/OSM/ChangesetHandler.spec.ts rename to test/Logic/OSM/ChangesetHandler.spec.ts diff --git a/tests/Logic/OSM/OsmObject.spec.ts b/test/Logic/OSM/OsmObject.spec.ts similarity index 100% rename from tests/Logic/OSM/OsmObject.spec.ts rename to test/Logic/OSM/OsmObject.spec.ts diff --git a/tests/Logic/Tags/LazyMatching.spec.ts b/test/Logic/Tags/LazyMatching.spec.ts similarity index 100% rename from tests/Logic/Tags/LazyMatching.spec.ts rename to test/Logic/Tags/LazyMatching.spec.ts diff --git a/tests/Logic/Tags/OptimzeTags.spec.ts b/test/Logic/Tags/OptimzeTags.spec.ts similarity index 100% rename from tests/Logic/Tags/OptimzeTags.spec.ts rename to test/Logic/Tags/OptimzeTags.spec.ts diff --git a/tests/Logic/Tags/TagUtils.spec.ts b/test/Logic/Tags/TagUtils.spec.ts similarity index 100% rename from tests/Logic/Tags/TagUtils.spec.ts rename to test/Logic/Tags/TagUtils.spec.ts diff --git a/tests/Logic/Web/Wikidata.spec.ts b/test/Logic/Web/Wikidata.spec.ts similarity index 100% rename from tests/Logic/Web/Wikidata.spec.ts rename to test/Logic/Web/Wikidata.spec.ts diff --git a/tests/Models/ThemeConfig/Conversion/CreateNoteImportLayer.spec.ts b/test/Models/ThemeConfig/Conversion/CreateNoteImportLayer.spec.ts similarity index 100% rename from tests/Models/ThemeConfig/Conversion/CreateNoteImportLayer.spec.ts rename to test/Models/ThemeConfig/Conversion/CreateNoteImportLayer.spec.ts diff --git a/tests/Models/ThemeConfig/Conversion/FixLegacyTheme.spec.ts b/test/Models/ThemeConfig/Conversion/FixLegacyTheme.spec.ts similarity index 100% rename from tests/Models/ThemeConfig/Conversion/FixLegacyTheme.spec.ts rename to test/Models/ThemeConfig/Conversion/FixLegacyTheme.spec.ts diff --git a/tests/Models/ThemeConfig/Conversion/PrepareLayer.spec.ts b/test/Models/ThemeConfig/Conversion/PrepareLayer.spec.ts similarity index 74% rename from tests/Models/ThemeConfig/Conversion/PrepareLayer.spec.ts rename to test/Models/ThemeConfig/Conversion/PrepareLayer.spec.ts index d85a542e02..d395401bef 100644 --- a/tests/Models/ThemeConfig/Conversion/PrepareLayer.spec.ts +++ b/test/Models/ThemeConfig/Conversion/PrepareLayer.spec.ts @@ -3,14 +3,15 @@ import {expect} from 'chai' import {LayerConfigJson} from "../../../../Models/ThemeConfig/Json/LayerConfigJson"; import {TagRenderingConfigJson} from "../../../../Models/ThemeConfig/Json/TagRenderingConfigJson"; import LineRenderingConfigJson from "../../../../Models/ThemeConfig/Json/LineRenderingConfigJson"; -import {ExpandRewrite, PrepareLayer} from "../../../../Models/ThemeConfig/Conversion/PrepareLayer"; +import {ExpandRewrite, PrepareLayer, RewriteSpecial} from "../../../../Models/ThemeConfig/Conversion/PrepareLayer"; +import { + QuestionableTagRenderingConfigJson +} from "../../../../Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson"; import RewritableConfigJson from "../../../../Models/ThemeConfig/Json/RewritableConfigJson"; + describe("ExpandRewrite", () => { - it("should do simple substitution", () => { - - }) it("should not allow overlapping keys", () => { const spec = >{ rewrite: { @@ -104,3 +105,26 @@ describe("PrepareLayer", () => { }) }) +describe('RewriteSpecial', function () { + it("should rewrite the UK import button", () => { + const tr = { + "id": "uk_addresses_import_button", + "render": { + "special": { + "type": "import_button", + "targetLayer": "address", + "tags": "urpn_count=$urpn_count;ref:GB:uprn=$ref:GB:uprn$", + "text": "Add this address", + "icon": "./assets/themes/uk_addresses/housenumber_add.svg", + "location_picker": "none" + } + } + } + const r = new RewriteSpecial().convert(tr, "test").result + expect(r).to.deep.eq({ + "id": "uk_addresses_import_button", + "render": {'*': "{import_button(address,urpn_count=$urpn_count;ref:GB:uprn=$ref:GB:uprn$,Add this address,./assets/themes/uk_addresses/housenumber_add.svg,,,,none)}"} + }) + }) +}); + diff --git a/tests/Models/ThemeConfig/Conversion/PrepareTheme.spec.ts b/test/Models/ThemeConfig/Conversion/PrepareTheme.spec.ts similarity index 65% rename from tests/Models/ThemeConfig/Conversion/PrepareTheme.spec.ts rename to test/Models/ThemeConfig/Conversion/PrepareTheme.spec.ts index 6b60434911..b18863ce79 100644 --- a/tests/Models/ThemeConfig/Conversion/PrepareTheme.spec.ts +++ b/test/Models/ThemeConfig/Conversion/PrepareTheme.spec.ts @@ -9,6 +9,7 @@ import * as bookcaseLayer from "../../../../assets/generated/layers/public_bookc import LayerConfig from "../../../../Models/ThemeConfig/LayerConfig"; import {ExtractImages} from "../../../../Models/ThemeConfig/Conversion/FixImages"; import * as cyclofix from "../../../../assets/generated/themes/cyclofix.json" +import {Tag} from "../../../../Logic/Tags/Tag"; const themeConfigJson: LayoutConfigJson = { @@ -37,8 +38,24 @@ const themeConfigJson: LayoutConfigJson = { } describe("PrepareTheme", () => { + + it("should substitute layers", () => { + + const sharedLayers = new Map() + sharedLayers.set("public_bookcase", bookcaseLayer["default"]) + const theme ={...themeConfigJson, layers: ["public_bookcase"]} + const prepareStep = new PrepareTheme({ + tagRenderings: new Map(), + sharedLayers: sharedLayers + }) + let themeConfigJsonPrepared = prepareStep.convert(theme, "test").result + const themeConfig = new LayoutConfig(themeConfigJsonPrepared); + const layerUnderTest = themeConfig.layers.find(l => l.id === "public_bookcase") + expect(layerUnderTest.source.osmTags).deep.eq(new Tag("amenity","public_bookcase")) + + }) - it("should apply overrideAll", () => { + it("should apply override", () => { const sharedLayers = new Map() sharedLayers.set("public_bookcase", bookcaseLayer["default"]) @@ -51,6 +68,20 @@ describe("PrepareTheme", () => { expect(layerUnderTest.source.geojsonSource).eq("xyz") }) + + + it("should apply override", () => { + + const sharedLayers = new Map() + sharedLayers.set("public_bookcase", bookcaseLayer["default"]) + let themeConfigJsonPrepared = new PrepareTheme({ + tagRenderings: new Map(), + sharedLayers: sharedLayers + }).convert({...themeConfigJson, overrideAll: {source: {geoJson: "https://example.com/data.geojson"}}}, "test").result + const themeConfig = new LayoutConfig(themeConfigJsonPrepared); + const layerUnderTest = themeConfig.layers.find(l => l.id === "public_bookcase") + expect(layerUnderTest.source.geojsonSource).eq("https://example.com/data.geojson") + }) }) diff --git a/tests/Models/ThemeConfig/TagRenderingConfig.spec.ts b/test/Models/ThemeConfig/TagRenderingConfig.spec.ts similarity index 100% rename from tests/Models/ThemeConfig/TagRenderingConfig.spec.ts rename to test/Models/ThemeConfig/TagRenderingConfig.spec.ts diff --git a/tests/Models/Units.spec.ts b/test/Models/Units.spec.ts similarity index 100% rename from tests/Models/Units.spec.ts rename to test/Models/Units.spec.ts diff --git a/test/UI/SpecialVisualisations.spec.ts b/test/UI/SpecialVisualisations.spec.ts new file mode 100644 index 0000000000..b683393098 --- /dev/null +++ b/test/UI/SpecialVisualisations.spec.ts @@ -0,0 +1,19 @@ +import {describe} from 'mocha' +import SpecialVisualizations from "../../UI/SpecialVisualizations"; +import {expect} from "chai"; + +describe("SpecialVisualisations", () => { + + describe("predifined special visualisations", () => { + it("should not have an argument called 'type'", () => { + const specials = SpecialVisualizations.specialVisualizations + for (const special of specials) { + expect(special.funcName).not.eq('type', "A special visualisation is not allowed to be named 'type', as this will conflict with the 'special'-blocks") + for (const arg of special.args) { + expect(arg.name).not.eq('type', "An argument is not allowed to be called 'type', as this will conflict with the 'special'-blocks") + } + + } + }) + }) +}) \ No newline at end of file diff --git a/tests/UI/ValidatedTextFieldTranslations.ts b/test/UI/ValidatedTextFieldTranslations.ts similarity index 100% rename from tests/UI/ValidatedTextFieldTranslations.ts rename to test/UI/ValidatedTextFieldTranslations.ts diff --git a/tests/Utils.MinifyJson.spec.ts b/test/Utils.MinifyJson.spec.ts similarity index 100% rename from tests/Utils.MinifyJson.spec.ts rename to test/Utils.MinifyJson.spec.ts diff --git a/test/scripts/GenerateCache.spec.ts b/test/scripts/GenerateCache.spec.ts new file mode 100644 index 0000000000..e5be78431b --- /dev/null +++ b/test/scripts/GenerateCache.spec.ts @@ -0,0 +1,52 @@ +import {describe} from 'mocha' +import {expect} from 'chai' +import {Utils} from "../../Utils"; +import {existsSync, mkdirSync, readFileSync, rmdirSync, unlinkSync} from "fs"; +import ScriptUtils from "../../scripts/ScriptUtils"; +import {main} from "../../scripts/generateCache"; + + +function initDownloads(query: string){ + + + const d = {"version":0.6,"generator":"Overpass API 0.7.57 93a4d346","osm3s":{"timestamp_osm_base":"2022-02-13T23:54:06Z","copyright":"The data included in this document is from www.openstreetmap.org. The data is made available under ODbL."},"elements":[{"type":"node","id":518224450,"lat":51.1548065,"lon":3.1880118,"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"street_side"}},{"type":"node","id":665418924,"lat":51.1575547,"lon":3.20522,"tags":{"amenity":"parking"}},{"type":"node","id":1168727903,"lat":51.1299141,"lon":3.1776123,"tags":{"amenity":"drinking_water","mapillary":"https://www.mapillary.com/app/?lat=51.129853685131906&lng=3.177603984688602&z=17&pKey=SEyKzIMUeKssni1ZLVe-9A&focus=photo&dateTo=2017-04-02&dateFrom=2017-04-01&x=0.5168826751181941&y=0.6114877557873634&zoom=0"}},{"type":"node","id":1168728245,"lat":51.1290938,"lon":3.1767502,"tags":{"amenity":"drinking_water","mapillary":"https://www.mapillary.com/app/?lat=51.129104406662464&lng=3.176675795895676&z=17&pKey=vSP3D_hWv3XCBtH75GnYUQ&focus=photo&dateTo=2017-04-02&dateFrom=2017-04-01"}},{"type":"node","id":1725842653,"lat":51.153364,"lon":3.2352655,"tags":{"amenity":"bench"}},{"type":"node","id":1744641290,"lat":51.1389321,"lon":3.2385407,"tags":{"amenity":"bench","backrest":"yes","material":"wood"}},{"type":"node","id":1746891135,"lat":51.1598841,"lon":3.2361425,"tags":{"amenity":"bench"}},{"type":"node","id":1810326078,"lat":51.1550855,"lon":3.2349358,"tags":{"amenity":"bench"}},{"type":"node","id":1810326092,"lat":51.1552302,"lon":3.234968,"tags":{"amenity":"bench"}},{"type":"node","id":2325437742,"lat":51.1770052,"lon":3.1967794,"tags":{"board_type":"board","information":"board","name":"Tillegembos","tourism":"information"}},{"type":"node","id":2325437743,"lat":51.1787363,"lon":3.1949036,"tags":{"board_type":"board","information":"board","name":"Tillegembos","tourism":"information"}},{"type":"node","id":2325437813,"lat":51.1733102,"lon":3.1895672,"tags":{"amenity":"bench","backrest":"yes","material":"wood"}},{"type":"node","id":2325437839,"lat":51.1763436,"lon":3.1984985,"tags":{"amenity":"bench","backrest":"yes","material":"wood"}},{"type":"node","id":2325437848,"lat":51.1770966,"lon":3.1963507,"tags":{"amenity":"bench","backrest":"yes","material":"wood"}},{"type":"node","id":2325437862,"lat":51.1773439,"lon":3.1948779,"tags":{"amenity":"bench","backrest":"yes","material":"wood"}},{"type":"node","id":2325437867,"lat":51.1775994,"lon":3.1888088,"tags":{"amenity":"bench","backrest":"yes","material":"wood"}},{"type":"node","id":2325437873,"lat":51.1778384,"lon":3.1913802,"tags":{"amenity":"bench","backrest":"yes","material":"wood"}},{"type":"node","id":2732486257,"lat":51.129741,"lon":3.1907419,"tags":{"board_type":"nature","information":"board","name":"Doeveren","tourism":"information"}},{"type":"node","id":3774054068,"lat":51.1586662,"lon":3.2271102,"tags":{"amenity":"bench"}},{"type":"node","id":4769106605,"lat":51.138264,"lon":3.1798655,"tags":{"backrest":"yes","leisure":"picnic_table"}},{"type":"node","id":4912238707,"lat":51.1448634,"lon":3.2455986,"tags":{"access":"yes","amenity":"parking","fee":"no","name":"Oostkamp","parking":"Carpool"}},{"type":"node","id":5637212235,"lat":51.1305439,"lon":3.1866873,"tags":{"board_type":"nature","image":"https://i.imgur.com/HehOQL9.jpg","information":"board","name":"Welkom Doeveren","tourism":"information"}},{"type":"node","id":5637224573,"lat":51.1281084,"lon":3.1881726,"tags":{"board_type":"nature","information":"board","name":"Welkom Doeveren","tourism":"information"}},{"type":"node","id":5637230107,"lat":51.1280884,"lon":3.1889798,"tags":{"information":"board","tourism":"information"}},{"type":"node","id":5637743026,"lat":51.1295973,"lon":3.1751122,"tags":{"information":"board","name":"Doeveren Wandelroute","tourism":"information"}},{"type":"node","id":5716130103,"lat":51.1767183,"lon":3.1947867,"tags":{"amenity":"bench","backrest":"yes"}},{"type":"node","id":5745783208,"lat":51.1782581,"lon":3.2410111,"tags":{"amenity":"bench"}},{"type":"node","id":5745807545,"lat":51.1784037,"lon":3.2369439,"tags":{"amenity":"bench"}},{"type":"node","id":5745807551,"lat":51.1783278,"lon":3.236678,"tags":{"amenity":"bench"}},{"type":"node","id":6535241426,"lat":51.1693142,"lon":3.1673093,"tags":{"amenity":"bench"}},{"type":"node","id":6535241427,"lat":51.169265,"lon":3.1673159,"tags":{"amenity":"bench"}},{"type":"node","id":6535241428,"lat":51.1692199,"lon":3.1673224,"tags":{"amenity":"bench"}},{"type":"node","id":6535241430,"lat":51.1685726,"lon":3.1678225,"tags":{"bench":"yes","leisure":"picnic_table","material":"wood"}},{"type":"node","id":6536026827,"lat":51.1703142,"lon":3.1691109,"tags":{"leisure":"picnic_table"}},{"type":"node","id":6536026828,"lat":51.1702795,"lon":3.1691552,"tags":{"leisure":"picnic_table"}},{"type":"node","id":6712112244,"lat":51.1595064,"lon":3.2021482,"tags":{"leisure":"picnic_table"}},{"type":"node","id":7304050040,"lat":51.1560908,"lon":3.1748919,"tags":{"amenity":"bench"}},{"type":"node","id":7304050041,"lat":51.1560141,"lon":3.1749533,"tags":{"amenity":"bench"}},{"type":"node","id":7304050042,"lat":51.156032,"lon":3.1749379,"tags":{"amenity":"bench"}},{"type":"node","id":7439979218,"lat":51.1780402,"lon":3.2178666,"tags":{"amenity":"bench","backrest":"yes"}},{"type":"node","id":7439979219,"lat":51.1780508,"lon":3.2179033,"tags":{"amenity":"bench","backrest":"yes"}},{"type":"node","id":7529262982,"lat":51.1585566,"lon":3.1715528,"tags":{"board_type":"map","information":"board","tourism":"information"}},{"type":"node","id":7529262984,"lat":51.1585786,"lon":3.1715385,"tags":{"leisure":"picnic_table"}},{"type":"node","id":7554879668,"lat":51.1573713,"lon":3.2043731,"tags":{"access":"yes","amenity":"toilets","fee":"no","toilets:disposal":"flush","unisex":"yes","wheelchair":"yes"}},{"type":"node","id":7554879669,"lat":51.1594855,"lon":3.2021507,"tags":{"leisure":"picnic_table"}},{"type":"node","id":7556988723,"lat":51.1330234,"lon":3.1839944,"tags":{"amenity":"bench","material":"wood"}},{"type":"node","id":7575825326,"lat":51.1386553,"lon":3.1797358,"tags":{"amenity":"bench"}},{"type":"node","id":7575825327,"lat":51.1382456,"lon":3.1797422,"tags":{"information":"board","tourism":"information"}},{"type":"node","id":8109498958,"lat":51.1332267,"lon":3.2341272,"tags":{"amenity":"bench","backrest":"yes"}},{"type":"node","id":8109498959,"lat":51.1335011,"lon":3.2343954,"tags":{"leisure":"picnic_table"}},{"type":"node","id":8198894646,"lat":51.125688,"lon":3.1856217,"tags":{"image":"https://i.imgur.com/O5kX20u.jpg","information":"board","tourism":"information"}},{"type":"node","id":8199012519,"lat":51.1262245,"lon":3.1802429,"tags":{"image":"https://i.imgur.com/tomw9p5.jpg","information":"board","tourism":"information"}},{"type":"node","id":8199244816,"lat":51.1252874,"lon":3.1837622,"tags":{"amenity":"bench"}},{"type":"node","id":8199301617,"lat":51.1256827,"lon":3.1853543,"tags":{"amenity":"bench","backrest":"no"}},{"type":"node","id":8255488518,"lat":51.1406698,"lon":3.235178,"tags":{"amenity":"bench","backrest":"yes"}},{"type":"node","id":9316104741,"lat":51.1330984,"lon":3.2335257,"tags":{"information":"board","tourism":"information"}},{"type":"node","id":9442532340,"lat":51.1763651,"lon":3.1947952,"tags":{"amenity":"bench","backrest":"yes","image":"https://i.imgur.com/eZ0Loii.jpg"}},{"type":"way","id":15242261,"nodes":[150996092,150996093,6754312552,6754312553,6754312550,6754312551,150996094,150996095,150996097,150996098,6754312560,6754312559,6754312558,150996099,6754312557,150996100,6754312555,6754312556,150996101,6754312554,150996092],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":16514228,"nodes":[170464837,170464839,170464840,170464841,170464837],"tags":{"access":"yes","amenity":"parking","fee":"no","maxstay":"4 hours","parking":"surface"}},{"type":"way","id":76706071,"nodes":[903903386,1038557094,1038557233,1038557143,1038557075,903903387,1038557195,903903388,903903390,903904576,903903386],"tags":{"access":"permissive","amenity":"parking"}},{"type":"way","id":89601157,"nodes":[1038557083,1038557078,1038557104,1038557072,1038557108,1038557230,1038557227,1038557102,1038557137,1038575040,1038557191,1038557014,6960473080,1038557035,1038557012,1038557083],"tags":{"amenity":"parking"}},{"type":"way","id":89604999,"nodes":[1038583404,1038583491,1038583375,1038583483,1038583479,1038583398,1038583459,1038583456,1038583446,1038583441,1038583425,1038583501,1038583451,1038583463,1038583476,1038583404],"tags":{"access":"yes","amenity":"parking","capacity":"57","carpool":"yes","description":"carpoolparking","fee":"no","name":"Loppem","parking":"surface"}},{"type":"way","id":92035679,"nodes":[1069177920,6853179264,1069177925,1069177919,6853179269,6853179268,6853179267,6853179215,6853179213,6853179214,1069178133,1069177984,6853179230,6853179228,6853179229,6853179224,6853179225,6853179227,6853179226,6853179216,6853179220,6853179219,6853179218,6853179217,6853179223,6853179221,6853179222,1069177967,1069177852,6853179211,6853179212,6853179210,6853179327,6853179208,6853179209,6853179203,1069177976,6853179207,6853179206,6853179205,6853179204,6853179202,1069177849,6852012579,6852012578,6852012580,6852012577,6852012581,6852012582,6852012583,1069177845,1759437085,1519342743,1519342742,1069178166,1069177853,1069177915,6853179235,6853179234,6853179236,1069177933,6853179237,6853179238,1069178021,6853179246,6853179244,6853179245,6853179240,6853179243,6853179241,6853179242,6853179239,6853179248,6853179249,6853179250,6853179247,1069177873,6853179262,6853179263,6853179260,6853179261,6853179256,6853179259,6853179257,6853179258,1069177920],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":101248451,"nodes":[1168728158,1168728325,1168728159,5637669355,1168728109,1168728158],"tags":{"access":"private","amenity":"parking","name":"Parking Merkenveld"}},{"type":"way","id":101248462,"nodes":[1168727876,1168728288,1168728412,1168728208,1168727876],"tags":{"amenity":"toilets","building":"yes","source:geometry:date":"2019-03-14","source:geometry:ref":"Gbg/6588148"}},{"type":"way","id":131622387,"nodes":[1448421093,1448421099,1448421091,1448421081,1448421093],"tags":{"amenity":"parking","name":"Tudor - Zeeweg","parking":"surface"}},{"type":"way","id":145691934,"nodes":[1590642859,1590642860,1590642858,1590642849,1590642859],"tags":{"amenity":"parking"}},{"type":"way","id":145691937,"nodes":[1590642829,1590642828,1590642830,1590642832,1590642829],"tags":{"amenity":"parking"}},{"type":"way","id":158901716,"nodes":[1710245713,1710245718,1710245707,1710245705,1710245703,1710245715,1710245711,1710245709,1710245701,1710245713],"tags":{"access":"yes","amenity":"parking","capacity":"14","fee":"no","parking":"surface"}},{"type":"way","id":158904558,"nodes":[1710262742,1710262745,1710262735,1710262733,1710262732,1710262743,1710262741,1710262739,1710262744,1710262737,1710262736,1710262731,1710262738,1710262742],"tags":{"access":"yes","alt_name":"Schoolparking","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":158906028,"nodes":[1710276259,1710276251,1810330766,1710276255,1710276261,1710276240,1710276232,1710276257,1710276243,1710276253,1810347217,1710276242,1710276259],"tags":{"access":"yes","amenity":"parking","fee":"no","name":"Parking Sportcentrum De Valkaart","parking":"surface"}},{"type":"way","id":160825858,"nodes":[1728421375,1728421374,1728421379,1728421377,1728421376,1728421378,1728421375],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":162602213,"nodes":[1920143232,7393009684,7393048385,1744641293,1523513488,1744641292,1920143232],"tags":{"amenity":"parking","capacity":"15"}},{"type":"way","id":165489167,"nodes":[4912197370,4912197365,4912197373,4912197364,4912197372,1770289505,4912197362,4912197371,4912197374,4912197363,4912197368,4912197366,4912197369,4912197367,4912197370],"tags":{"access":"yes","amenity":"parking","fee":"no","name":"Bad Neuheimplein","parking":"surface"}},{"type":"way","id":168291852,"nodes":[1795793399,4979389763,1795793409,1795793395,1795793393,1795793397,1795793407,1795793406,1795793408,1795793405,1795793399],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":169875513,"nodes":[1810345951,1810345955,1810345947,1810345944,1810345951],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":170015605,"nodes":[1811673425,1811673421,1811673418,1811673423,1811673425],"tags":{"access":"private","amenity":"parking","name":"gheeraert E40","operator":"Gheeraert"}},{"type":"way","id":170018487,"nodes":[1811699779,1811699778,1811699776,1811699777,1811699779],"tags":{"access":"private","amenity":"parking","name":"Gheeraert vooraan"}},{"type":"way","id":170559194,"nodes":[1817319304,1817319302,1817319297,1817319301,1817319304],"tags":{"access":"private","amenity":"parking","name":"Gheeraert laadkade"}},{"type":"way","id":170559195,"nodes":[1817319299,1817319303,1817319300,1817319292,1817319299],"tags":{"access":"private","amenity":"parking","name":"Gheeraert spoorweg trailers"}},{"type":"way","id":170559196,"nodes":[1817319293,1817319289,1817319291,1817319296,1817319293],"tags":{"access":"private","amenity":"parking","name":"Gheeraert spoorweg trucks"}},{"type":"way","id":170559197,"nodes":[1817319294,1817319298,1817319295,1817319290,1817319294],"tags":{"access":"private","amenity":"parking","name":"Gheeraert zijkant"}},{"type":"way","id":170559292,"nodes":[1817320496,1817320494,1817320493,1817320495,1817320496],"tags":{"access":"private","amenity":"parking","name":"Gheeraert vooraan gebouw"}},{"type":"way","id":170559832,"nodes":[1817324515,1817324509,1817324491,6397031888,4044172008,4044172003,4044171997,4044171962,4044171957,4044171976,1817324489,1817324488,3550860268,1817324505,3550860269,1817324513,1817324515],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":223674368,"nodes":[2325437844,8191691971,8191691973,8191691972,2325437840,8191691970,414025563,2325437844],"tags":{"amenity":"parking","name":"Tillegembos","parking":"surface"}},{"type":"way","id":237214948,"nodes":[2451574741,2451574742,2451574744,1015583939,2451574741],"tags":{"access":"private","amenity":"parking"}},{"type":"way","id":237214949,"nodes":[2451574748,2451574746,2451574747,2451574749,2451574748],"tags":{"access":"private","amenity":"parking"}},{"type":"way","id":237214950,"nodes":[2451569392,1015567837,2451574745,2451574743,2451578121,2451569392],"tags":{"access":"private","amenity":"parking"}},{"type":"way","id":325909586,"nodes":[3325315243,111759500,3325315247,3325315232,3325315230,3325315226,1169056712,3325315243],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":326834162,"nodes":[3335137807,3335137692,3335137795,9163493632,3335137802,3335137812,9163486855,9163486856,3335137823,3335137807],"tags":{"access":"customers","amenity":"parking","operator":"Best Western Weinebrugge","parking":"surface"}},{"type":"way","id":327849054,"nodes":[3346575929,3346575873,3346575876,3346575843,3346575845,3346575891,3346575901,3346575923,3346575928,3346575950,3346575929],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":327849055,"nodes":[3346575945,3346575946,3346575943,3346575933,3346575925,3346575917,3346575903,3346575908,3346575889,3346575886,3346575945],"tags":{"access":"customers","amenity":"parking","parking":"surface"}},{"type":"way","id":327849056,"nodes":[3346575865,3346575853,3346575855,3346575846,3346575840,3346575858,3346575865],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":374677860,"nodes":[3780611504,3780611502,3780611500,3780611503,3780611504],"tags":{"amenity":"parking"}},{"type":"way","id":374677861,"nodes":[3780611495,3780611493,3780611492,3780611494,3780611495],"tags":{"amenity":"parking"}},{"type":"way","id":374677862,"nodes":[3780611498,3780611497,3780611496,3780611499,3780611501,3780611498],"tags":{"amenity":"parking"}},{"type":"way","id":389912371,"nodes":[3930713440,3930713451,3930713447,3930713437,3930713440],"tags":{"amenity":"parking"}},{"type":"way","id":389912372,"nodes":[3930713454,3930713442,3930713435,3930713429,5826811614,3930713426,3930713430,6982605752,6982605754,3930713438,6982605769,6982605766,6982605767,6982605762,6982605764,3930713446,3930713454],"tags":{"access":"customers","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":401995684,"nodes":[4044171963,4044171954,4044171924,4044171936,4044171941,4044171963],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":500067820,"nodes":[4912203166,4912203165,4912203164,4912203163,4912203162,4912203161,4912203160,4912203166],"tags":{"access":"yes","amenity":"parking","parking":"surface"}},{"type":"way","id":500067821,"nodes":[4912203170,4912203169,4912203168,4912203167,4912203170],"tags":{"access":"yes","amenity":"parking","parking":"surface"}},{"type":"way","id":500067822,"nodes":[4912203174,4912203173,4912203172,4912203171,4912203174],"tags":{"access":"yes","amenity":"parking","parking":"surface"}},{"type":"way","id":500067823,"nodes":[4912203179,4912203178,4912203177,4912203176,4912203179],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":500069613,"nodes":[4912214695,4912214685,4912214694,4912214693,4912214692,4912214680,4912214695],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":500071452,"nodes":[4912225068,4912225062,4912225063,4912225053,4912225064,4912214694,4912214685,4912225068],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":500071455,"nodes":[4912225070,4912214681,4912214686,4912225052,4912225051,4912225067,4912225062,4912225068,4912225070],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":500071458,"nodes":[4912214695,4912214680,4912225069,4912225050,1525460846,4912214681,4912225070,4912214695],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":533276307,"nodes":[5173881316,5173881317,5173881318,7054196467,5173881316],"tags":{"amenity":"parking"}},{"type":"way","id":533276308,"nodes":[5173881320,5173881621,5173881622,5173881623,5173881320],"tags":{"amenity":"parking"}},{"type":"way","id":533276309,"nodes":[5173881624,5173881625,5173881626,5173881627,5173881624],"tags":{"amenity":"parking"}},{"type":"way","id":579848581,"nodes":[4043782112,5825400688,5552466020,6997096756,6997096759,6997096758,5552466018,5552466013,5552466014,6997076567,4043782112],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":584455569,"nodes":[5586765933,5586765934,5586765935,5586765936,5586765933],"tags":{"amenity":"parking"}},{"type":"way","id":585977870,"nodes":[5587844460,5599314384,5599314385,1659850846,6870850178,5587844462,5587844461,6870863414,5587844460],"tags":{"amenity":"parking"}},{"type":"way","id":587014342,"nodes":[5607796820,5607798725,5607798721,5607798722,5607796819,5607798723,5607796820],"tags":{"access":"permissive","amenity":"parking","park_ride":"no","parking":"surface","surface":"paved"}},{"type":"way","id":590167103,"nodes":[5635001277,5635001274,5635001275,5635001276,5635001277],"tags":{"amenity":"parking"}},{"type":"way","id":590167113,"nodes":[5635001312,5635001306,7767137237,7767137235,7767137236,7767137234,5635001312],"tags":{"amenity":"parking"}},{"type":"way","id":590167134,"nodes":[5635001374,5635001373,5635001372,5635001371,5635001374],"tags":{"amenity":"parking"}},{"type":"way","id":590167135,"nodes":[5635001378,5635001377,5635001376,5635001375,5635001378],"tags":{"amenity":"parking"}},{"type":"way","id":590167136,"nodes":[5635001382,5635001381,5635001380,5635001379,5635001382],"tags":{"amenity":"parking"}},{"type":"way","id":590167137,"nodes":[5635001386,5882873336,5882873337,5882873338,5882873335,6593340582,6593340583,5882873334,6593340584,5635001385,5635001384,5635001383,5635001386],"tags":{"amenity":"parking"}},{"type":"way","id":590167147,"nodes":[5635001417,5635001414,5635001415,5635001416,5635001417],"tags":{"amenity":"parking"}},{"type":"way","id":601406079,"nodes":[5716136617,5716136618,5716136619,5716136620,5716136617],"tags":{"amenity":"parking"}},{"type":"way","id":632813009,"nodes":[5974489618,1810326044,1810326087,5974489617,5972179348,5972179347,5972179346,5972179345,5972179344,5972179343,5972179331,5974489616,5974489615,5974489614,5974489618],"tags":{"amenity":"parking","name":"Gemeenteplein","parking":"surface"}},{"type":"way","id":668043297,"nodes":[6255587424,6255587425,6255587426,6255587427,6255587424],"tags":{"access":"private","amenity":"parking"}},{"type":"way","id":670104236,"nodes":[6275462768,6275462769,6275462770,6275462771,6275462768],"tags":{"amenity":"parking"}},{"type":"way","id":670104238,"nodes":[6275462772,6275462989,6275462773,6275462774,6275462775,6275462772],"tags":{"amenity":"parking"}},{"type":"way","id":670104239,"nodes":[6275462776,6275462777,6275462778,6275462779,6275462776],"tags":{"amenity":"parking"}},{"type":"way","id":670104241,"nodes":[6275462780,6275462781,6275462782,6275462783,6275462780],"tags":{"amenity":"parking"}},{"type":"way","id":670104242,"nodes":[6275462784,6275462985,6275462988,6275462986,6275462987,6275462784],"tags":{"amenity":"parking"}},{"type":"way","id":671840055,"nodes":[6291339827,6291339828,6291339816,6291339815,6291339822,6291339821,6291339829,6291339830,6291339827],"tags":{"amenity":"parking"}},{"type":"way","id":695825223,"nodes":[1519476746,6533893620,6533893621,6533893622,1519476797,1519476620,1519476746],"tags":{"access":"yes","amenity":"parking"}},{"type":"way","id":695825224,"nodes":[1519476744,6533893624,6533893625,6533893626,1519476698,1519476635,1519476744],"tags":{"access":"yes","amenity":"parking"}},{"type":"way","id":696040917,"nodes":[6536026850,6536026851,6536026852,6536026853,6536026850],"tags":{"amenity":"parking","name":"Kasteel Tudor"}},{"type":"way","id":696043218,"nodes":[6536038234,6536038235,6536038236,6536038237,6536038234],"tags":{"access":"customers","amenity":"parking"}},{"type":"way","id":700675991,"nodes":[6579962064,6579962065,6579962066,6579962068,6579962067,6579962064],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":705278707,"nodes":[6625037999,6625038000,6625038001,6625038002,6625038003,6004375826,6625038005,6625038006,6625037999],"tags":{"amenity":"parking"}},{"type":"way","id":719482833,"nodes":[6754312544,6754312543,6754312542,6754312541,6754312544],"tags":{"access":"yes","amenity":"parking","capacity":"5"}},{"type":"way","id":719482834,"nodes":[6754312565,6754312564,6754312563,6754312562,6754312565],"tags":{"access":"yes","amenity":"parking","capacity":"12"}},{"type":"way","id":737054013,"nodes":[5826811496,5826811497,5826811494,5826811495,5826811496],"tags":{"amenity":"parking"}},{"type":"way","id":737054014,"nodes":[5826810676,5826810673,5826810674,5826810675,5826810676],"tags":{"amenity":"parking"}},{"type":"way","id":737054015,"nodes":[5826810681,5826810678,5826810679,5826810680,5826810681],"tags":{"amenity":"parking"}},{"type":"way","id":737093410,"nodes":[5826811559,5826811536,5826811535,5826811561,5826811560,5826811559],"tags":{"access":"yes","amenity":"parking","capacity":"4","fee":"no","parking":"surface"}},{"type":"way","id":737093411,"nodes":[5826811551,5826811547,5826811548,5826811549,5826811550,5826811551],"tags":{"access":"yes","amenity":"parking","capacity":"4","fee":"no","parking":"surface"}},{"type":"way","id":739652949,"nodes":[6925536542,6925536541,6925536540,6925536539,6925536542],"tags":{"amenity":"parking","capacity":"6","parking":"surface"}},{"type":"way","id":741675236,"nodes":[6943148207,6943148206,6943148205,6943148204,1637742821,6943148203,6943148202,6943148201,6943148200,6943148199,6943148198,6943148197,6943148207],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":742295526,"nodes":[6949357909,6949357908,6949357907,6949357906,6949357909],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":742295527,"nodes":[6949357913,6949357912,6949357911,6949357910,6949357913],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":742295528,"nodes":[6949357917,6949357916,6949357915,6949357914,6949357917],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":742295529,"nodes":[6949357921,6949357920,6949357919,6949357918,6949357921],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":746170866,"nodes":[6982906547,6982906546,6982906545,6982906544,6982906543,6982906542,6982906547],"tags":{"access":"customers","amenity":"parking"}},{"type":"way","id":747880657,"nodes":[3325315397,6997076566,6997076565,6997076563,6997076562,6997076564,3325315395,3325315397],"tags":{"access":"customers","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":763977465,"nodes":[7137343680,7137343681,7137343682,7137343683,7137343680],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":763977466,"nodes":[7137343684,7137383185,7137383186,7137383187,7137343684],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":803821090,"nodes":[7519058290,7519058289,7519058288,7519058287,7519058290],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":803821091,"nodes":[7519058294,7519058293,7519058292,7519058291,7519058294],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":803821092,"nodes":[7519058298,7519058297,7519058296,7519058295,7519058298],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":803821093,"nodes":[7519058302,7519058301,7519058300,7519058299,7519058302],"tags":{"access":"private","amenity":"parking","capacity":"6","parking":"surface"}},{"type":"way","id":804963962,"nodes":[7529417225,7529417226,7529417227,7529417228,7529417229,7529417230,7529417232,7529417225],"tags":{"access":"customers","amenity":"parking","fee":"no","operator":"’t Kiekekot","parking":"surface","surface":"unpaved"}},{"type":"way","id":806875503,"nodes":[4042671969,7545532512,7545532514,7545532513,3359977305,4042671969],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":806963547,"nodes":[7546193222,7546193221,7546193220,7546193219,7546193222],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":865357121,"nodes":[8065883228,8065883227,8065883226,8065883225,8065883228],"tags":{"amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":865357122,"nodes":[8065883233,8065883230,8065883229,8065883232,8065883233],"tags":{"amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":879281221,"nodes":[8179735269,8179735268,8179735267,8179735266,8179735265,8179735264,8179735224,8179735269],"tags":{"access":"customers","amenity":"parking","parking":"surface"}},{"type":"way","id":881770201,"nodes":[8200275847,8200275848,8200275844,8200275853,8200275849,8200275847],"tags":{"amenity":"parking","parking":"surface","surface":"grass"}},{"type":"way","id":978360549,"nodes":[5761770202,5761770204,9052878229,9052878228,5761770202],"tags":{"amenity":"parking"}},{"type":"way","id":1009692722,"nodes":[9316118540,9316118536,9316118531,9316118535,9316118534,9316118533,9316118530,9316118532,3311835478,9316118540],"tags":{"amenity":"parking","parking":"street_side"}},{"type":"relation","id":8188853,"members":[{"type":"way","ref":577572397,"role":"outer"},{"type":"way","ref":577572399,"role":"outer"}],"tags":{"access":"guided","curator":"Luc Maene;Geert De Clercq","email":"lucmaene@hotmail.com;geert.de.clercq1@pandora.be","landuse":"meadow","leisure":"nature_reserve","name":"De Wulgenbroeken","natural":"wetland","operator":"Natuurpunt Brugge","type":"multipolygon","website":"https://natuurpuntbrugge.be/wulgenbroeken/","wetland":"wet_meadow","wikidata":"Q60061498","wikipedia":"nl:Wulgenbroeken"}},{"type":"relation","id":11163488,"members":[{"type":"way","ref":810604915,"role":"outer"},{"type":"way","ref":989393316,"role":"outer"},{"type":"way","ref":389026405,"role":"inner"},{"type":"way","ref":810607458,"role":"outer"}],"tags":{"access":"yes","curator":"Kris Lesage","description":"Wat Doeveren zo uniek maakt, zijn zijn kleine heidegebiedjes met soorten die erg verschillen van de Kempense heide. Doeveren en omstreken was vroeger één groot heidegebied, maar bestaat nu grotendeels uit bossen.","dog":"leashed","email":"doeveren@natuurpuntzedelgem.be","image":"https://i.imgur.com/NEAsQZG.jpg","image:0":"https://i.imgur.com/Dq71hyQ.jpg","image:1":"https://i.imgur.com/mAIiT4f.jpg","image:2":"https://i.imgur.com/dELZU97.jpg","image:3":"https://i.imgur.com/Bso57JC.jpg","image:4":"https://i.imgur.com/9DtcfXo.jpg","image:5":"https://i.imgur.com/0R6eBfk.jpg","image:6":"https://i.imgur.com/b0JpvbR.jpg","leisure":"nature_reserve","name":"Doeveren","operator":"Natuurpunt Zedelgem","phone":"+32 486 25 25 30","type":"multipolygon","website":"https://www.natuurpuntzedelgem.be/gebieden/doeveren/","wikidata":"Q56395754","wikipedia":"nl:Doeveren (natuurgebied)"}},{"type":"relation","id":11790117,"members":[{"type":"way","ref":863373849,"role":"outer"},{"type":"way","ref":777280458,"role":"outer"}],"tags":{"access":"no","description:0":"In gebruik als waterbuffering","leisure":"nature_reserve","name":"Kerkebeek","operator":"Natuurpunt Brugge","type":"multipolygon"}},{"type":"node","id":518224450,"lat":51.1548065,"lon":3.1880118,"timestamp":"2021-08-14T21:49:28Z","version":5,"changeset":109683837,"user":"effem","uid":16437,"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"street_side"}},{"type":"node","id":665418924,"lat":51.1575547,"lon":3.20522,"timestamp":"2012-05-12T20:13:39Z","version":2,"changeset":11580224,"user":"martino260","uid":655442,"tags":{"amenity":"parking"}},{"type":"node","id":1168727903,"lat":51.1299141,"lon":3.1776123,"timestamp":"2017-04-03T08:34:05Z","version":2,"changeset":47403889,"user":"philippec","uid":76884,"tags":{"amenity":"drinking_water","mapillary":"https://www.mapillary.com/app/?lat=51.129853685131906&lng=3.177603984688602&z=17&pKey=SEyKzIMUeKssni1ZLVe-9A&focus=photo&dateTo=2017-04-02&dateFrom=2017-04-01&x=0.5168826751181941&y=0.6114877557873634&zoom=0"}},{"type":"node","id":1168728245,"lat":51.1290938,"lon":3.1767502,"timestamp":"2019-10-07T11:06:57Z","version":3,"changeset":75370316,"user":"Hopperpop","uid":3664604,"tags":{"amenity":"drinking_water","mapillary":"https://www.mapillary.com/app/?lat=51.129104406662464&lng=3.176675795895676&z=17&pKey=vSP3D_hWv3XCBtH75GnYUQ&focus=photo&dateTo=2017-04-02&dateFrom=2017-04-01"}},{"type":"node","id":1725842653,"lat":51.153364,"lon":3.2352655,"timestamp":"2012-07-02T17:33:00Z","version":2,"changeset":12090625,"user":"martino260","uid":655442,"tags":{"amenity":"bench"}},{"type":"node","id":1744641290,"lat":51.1389321,"lon":3.2385407,"timestamp":"2012-09-18T13:29:52Z","version":3,"changeset":13156159,"user":"martino260","uid":655442,"tags":{"amenity":"bench","backrest":"yes","material":"wood"}},{"type":"node","id":1746891135,"lat":51.1598841,"lon":3.2361425,"timestamp":"2012-05-09T18:22:11Z","version":1,"changeset":11551825,"user":"martino260","uid":655442,"tags":{"amenity":"bench"}},{"type":"node","id":1810326078,"lat":51.1550855,"lon":3.2349358,"timestamp":"2012-07-02T19:50:15Z","version":1,"changeset":12093439,"user":"martino260","uid":655442,"tags":{"amenity":"bench"}},{"type":"node","id":1810326092,"lat":51.1552302,"lon":3.234968,"timestamp":"2012-07-02T19:50:16Z","version":1,"changeset":12093439,"user":"martino260","uid":655442,"tags":{"amenity":"bench"}},{"type":"node","id":2325437742,"lat":51.1770052,"lon":3.1967794,"timestamp":"2013-05-30T12:19:08Z","version":1,"changeset":16350909,"user":"peeweeke","uid":494726,"tags":{"board_type":"board","information":"board","name":"Tillegembos","tourism":"information"}},{"type":"node","id":2325437743,"lat":51.1787363,"lon":3.1949036,"timestamp":"2013-05-30T12:19:08Z","version":1,"changeset":16350909,"user":"peeweeke","uid":494726,"tags":{"board_type":"board","information":"board","name":"Tillegembos","tourism":"information"}},{"type":"node","id":2325437813,"lat":51.1733102,"lon":3.1895672,"timestamp":"2013-05-30T12:19:09Z","version":1,"changeset":16350909,"user":"peeweeke","uid":494726,"tags":{"amenity":"bench","backrest":"yes","material":"wood"}},{"type":"node","id":2325437839,"lat":51.1763436,"lon":3.1984985,"timestamp":"2013-05-30T12:19:10Z","version":1,"changeset":16350909,"user":"peeweeke","uid":494726,"tags":{"amenity":"bench","backrest":"yes","material":"wood"}},{"type":"node","id":2325437848,"lat":51.1770966,"lon":3.1963507,"timestamp":"2013-05-30T12:19:10Z","version":1,"changeset":16350909,"user":"peeweeke","uid":494726,"tags":{"amenity":"bench","backrest":"yes","material":"wood"}},{"type":"node","id":2325437862,"lat":51.1773439,"lon":3.1948779,"timestamp":"2013-05-30T12:19:10Z","version":1,"changeset":16350909,"user":"peeweeke","uid":494726,"tags":{"amenity":"bench","backrest":"yes","material":"wood"}},{"type":"node","id":2325437867,"lat":51.1775994,"lon":3.1888088,"timestamp":"2013-05-30T12:19:11Z","version":1,"changeset":16350909,"user":"peeweeke","uid":494726,"tags":{"amenity":"bench","backrest":"yes","material":"wood"}},{"type":"node","id":2325437873,"lat":51.1778384,"lon":3.1913802,"timestamp":"2013-05-30T12:19:11Z","version":1,"changeset":16350909,"user":"peeweeke","uid":494726,"tags":{"amenity":"bench","backrest":"yes","material":"wood"}},{"type":"node","id":2732486257,"lat":51.129741,"lon":3.1907419,"timestamp":"2014-03-21T21:15:28Z","version":1,"changeset":21234491,"user":"meannder","uid":149496,"tags":{"board_type":"nature","information":"board","name":"Doeveren","tourism":"information"}},{"type":"node","id":3774054068,"lat":51.1586662,"lon":3.2271102,"timestamp":"2015-10-05T20:34:04Z","version":1,"changeset":34456387,"user":"TripleBee","uid":497177,"tags":{"amenity":"bench"}},{"type":"node","id":4769106605,"lat":51.138264,"lon":3.1798655,"timestamp":"2020-05-31T19:49:45Z","version":3,"changeset":86019474,"user":"Hopperpop","uid":3664604,"tags":{"backrest":"yes","leisure":"picnic_table"}},{"type":"node","id":4912238707,"lat":51.1448634,"lon":3.2455986,"timestamp":"2017-06-13T08:12:04Z","version":1,"changeset":49491753,"user":"Jakka","uid":2403313,"tags":{"access":"yes","amenity":"parking","fee":"no","name":"Oostkamp","parking":"Carpool"}},{"type":"node","id":5637212235,"lat":51.1305439,"lon":3.1866873,"timestamp":"2021-11-22T11:54:45Z","version":4,"changeset":114095475,"user":"L'imaginaire","uid":654234,"tags":{"board_type":"nature","image":"https://i.imgur.com/HehOQL9.jpg","information":"board","name":"Welkom Doeveren","tourism":"information"}},{"type":"node","id":5637224573,"lat":51.1281084,"lon":3.1881726,"timestamp":"2020-06-01T22:39:30Z","version":2,"changeset":86065716,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"board_type":"nature","information":"board","name":"Welkom Doeveren","tourism":"information"}},{"type":"node","id":5637230107,"lat":51.1280884,"lon":3.1889798,"timestamp":"2018-05-23T11:55:01Z","version":1,"changeset":59208628,"user":"Jakka","uid":2403313,"tags":{"information":"board","tourism":"information"}},{"type":"node","id":5637743026,"lat":51.1295973,"lon":3.1751122,"timestamp":"2021-10-08T08:53:14Z","version":2,"changeset":112251989,"user":"DieterWesttoer","uid":13062237,"tags":{"information":"board","name":"Doeveren Wandelroute","tourism":"information"}},{"type":"node","id":5716130103,"lat":51.1767183,"lon":3.1947867,"timestamp":"2018-06-24T22:04:21Z","version":1,"changeset":60130942,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"amenity":"bench","backrest":"yes"}},{"type":"node","id":5745783208,"lat":51.1782581,"lon":3.2410111,"timestamp":"2018-07-07T18:42:23Z","version":1,"changeset":60494990,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"amenity":"bench"}},{"type":"node","id":5745807545,"lat":51.1784037,"lon":3.2369439,"timestamp":"2018-07-07T18:58:25Z","version":1,"changeset":60495307,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"amenity":"bench"}},{"type":"node","id":5745807551,"lat":51.1783278,"lon":3.236678,"timestamp":"2018-07-07T18:58:25Z","version":1,"changeset":60495307,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"amenity":"bench"}},{"type":"node","id":6535241426,"lat":51.1693142,"lon":3.1673093,"timestamp":"2019-06-09T13:50:19Z","version":1,"changeset":71071874,"user":"Hopperpop","uid":3664604,"tags":{"amenity":"bench"}},{"type":"node","id":6535241427,"lat":51.169265,"lon":3.1673159,"timestamp":"2019-06-09T13:50:19Z","version":1,"changeset":71071874,"user":"Hopperpop","uid":3664604,"tags":{"amenity":"bench"}},{"type":"node","id":6535241428,"lat":51.1692199,"lon":3.1673224,"timestamp":"2019-06-09T13:50:19Z","version":1,"changeset":71071874,"user":"Hopperpop","uid":3664604,"tags":{"amenity":"bench"}},{"type":"node","id":6535241430,"lat":51.1685726,"lon":3.1678225,"timestamp":"2019-06-09T13:50:19Z","version":1,"changeset":71071874,"user":"Hopperpop","uid":3664604,"tags":{"bench":"yes","leisure":"picnic_table","material":"wood"}},{"type":"node","id":6536026827,"lat":51.1703142,"lon":3.1691109,"timestamp":"2019-06-09T22:54:45Z","version":1,"changeset":71082671,"user":"Hopperpop","uid":3664604,"tags":{"leisure":"picnic_table"}},{"type":"node","id":6536026828,"lat":51.1702795,"lon":3.1691552,"timestamp":"2019-06-09T22:54:45Z","version":1,"changeset":71082671,"user":"Hopperpop","uid":3664604,"tags":{"leisure":"picnic_table"}},{"type":"node","id":6712112244,"lat":51.1595064,"lon":3.2021482,"timestamp":"2020-05-24T21:35:50Z","version":2,"changeset":85695537,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"leisure":"picnic_table"}},{"type":"node","id":7304050040,"lat":51.1560908,"lon":3.1748919,"timestamp":"2020-03-17T19:11:00Z","version":1,"changeset":82315744,"user":"Hopperpop","uid":3664604,"tags":{"amenity":"bench"}},{"type":"node","id":7304050041,"lat":51.1560141,"lon":3.1749533,"timestamp":"2020-03-17T19:11:00Z","version":1,"changeset":82315744,"user":"Hopperpop","uid":3664604,"tags":{"amenity":"bench"}},{"type":"node","id":7304050042,"lat":51.156032,"lon":3.1749379,"timestamp":"2020-03-17T19:11:00Z","version":1,"changeset":82315744,"user":"Hopperpop","uid":3664604,"tags":{"amenity":"bench"}},{"type":"node","id":7439979218,"lat":51.1780402,"lon":3.2178666,"timestamp":"2020-04-24T00:56:14Z","version":1,"changeset":84027933,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"amenity":"bench","backrest":"yes"}},{"type":"node","id":7439979219,"lat":51.1780508,"lon":3.2179033,"timestamp":"2020-04-24T00:56:14Z","version":1,"changeset":84027933,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"amenity":"bench","backrest":"yes"}},{"type":"node","id":7529262982,"lat":51.1585566,"lon":3.1715528,"timestamp":"2020-05-17T16:12:04Z","version":1,"changeset":85340264,"user":"Hopperpop","uid":3664604,"tags":{"board_type":"map","information":"board","tourism":"information"}},{"type":"node","id":7529262984,"lat":51.1585786,"lon":3.1715385,"timestamp":"2020-05-17T16:12:04Z","version":1,"changeset":85340264,"user":"Hopperpop","uid":3664604,"tags":{"leisure":"picnic_table"}},{"type":"node","id":7554879668,"lat":51.1573713,"lon":3.2043731,"timestamp":"2020-05-24T21:35:50Z","version":1,"changeset":85695537,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"access":"yes","amenity":"toilets","fee":"no","toilets:disposal":"flush","unisex":"yes","wheelchair":"yes"}},{"type":"node","id":7554879669,"lat":51.1594855,"lon":3.2021507,"timestamp":"2020-05-24T21:35:50Z","version":1,"changeset":85695537,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"leisure":"picnic_table"}},{"type":"node","id":7556988723,"lat":51.1330234,"lon":3.1839944,"timestamp":"2020-05-25T19:19:56Z","version":1,"changeset":85730259,"user":"Hopperpop","uid":3664604,"tags":{"amenity":"bench","material":"wood"}},{"type":"node","id":7575825326,"lat":51.1386553,"lon":3.1797358,"timestamp":"2020-05-31T19:49:45Z","version":1,"changeset":86019474,"user":"Hopperpop","uid":3664604,"tags":{"amenity":"bench"}},{"type":"node","id":7575825327,"lat":51.1382456,"lon":3.1797422,"timestamp":"2020-05-31T19:49:45Z","version":1,"changeset":86019474,"user":"Hopperpop","uid":3664604,"tags":{"information":"board","tourism":"information"}},{"type":"node","id":8109498958,"lat":51.1332267,"lon":3.2341272,"timestamp":"2020-11-11T20:42:45Z","version":1,"changeset":93951029,"user":"L'imaginaire","uid":654234,"tags":{"amenity":"bench","backrest":"yes"}},{"type":"node","id":8109498959,"lat":51.1335011,"lon":3.2343954,"timestamp":"2020-11-11T20:42:45Z","version":1,"changeset":93951029,"user":"L'imaginaire","uid":654234,"tags":{"leisure":"picnic_table"}},{"type":"node","id":8198894646,"lat":51.125688,"lon":3.1856217,"timestamp":"2020-12-06T23:39:34Z","version":3,"changeset":95384686,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"image":"https://i.imgur.com/O5kX20u.jpg","information":"board","tourism":"information"}},{"type":"node","id":8199012519,"lat":51.1262245,"lon":3.1802429,"timestamp":"2020-12-07T00:12:14Z","version":3,"changeset":95385124,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"image":"https://i.imgur.com/tomw9p5.jpg","information":"board","tourism":"information"}},{"type":"node","id":8199244816,"lat":51.1252874,"lon":3.1837622,"timestamp":"2020-12-06T17:14:52Z","version":1,"changeset":95374174,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"amenity":"bench"}},{"type":"node","id":8199301617,"lat":51.1256827,"lon":3.1853543,"timestamp":"2020-12-06T17:14:52Z","version":1,"changeset":95374174,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"amenity":"bench","backrest":"no"}},{"type":"node","id":8255488518,"lat":51.1406698,"lon":3.235178,"timestamp":"2020-12-23T18:20:35Z","version":1,"changeset":96342158,"user":"L'imaginaire","uid":654234,"tags":{"amenity":"bench","backrest":"yes"}},{"type":"node","id":9316104741,"lat":51.1330984,"lon":3.2335257,"timestamp":"2021-12-06T18:31:00Z","version":1,"changeset":114629890,"user":"L'imaginaire","uid":654234,"tags":{"information":"board","tourism":"information"}},{"type":"node","id":9442532340,"lat":51.1763651,"lon":3.1947952,"timestamp":"2022-01-23T16:26:28Z","version":2,"changeset":116506336,"user":"L'imaginaire","uid":654234,"tags":{"amenity":"bench","backrest":"yes","image":"https://i.imgur.com/eZ0Loii.jpg"}},{"type":"way","id":15242261,"timestamp":"2020-04-05T07:08:45Z","version":8,"changeset":83089516,"user":"Hopperpop","uid":3664604,"nodes":[150996092,150996093,6754312552,6754312553,6754312550,6754312551,150996094,150996095,150996097,150996098,6754312560,6754312559,6754312558,150996099,6754312557,150996100,6754312555,6754312556,150996101,6754312554,150996092],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":16514228,"timestamp":"2017-06-13T07:14:23Z","version":9,"changeset":49490318,"user":"Jakka","uid":2403313,"nodes":[170464837,170464839,170464840,170464841,170464837],"tags":{"access":"yes","amenity":"parking","fee":"no","maxstay":"4 hours","parking":"surface"}},{"type":"way","id":76706071,"timestamp":"2017-06-17T07:51:31Z","version":4,"changeset":49608752,"user":"rowers2","uid":2445224,"nodes":[903903386,1038557094,1038557233,1038557143,1038557075,903903387,1038557195,903903388,903903390,903904576,903903386],"tags":{"access":"permissive","amenity":"parking"}},{"type":"way","id":89601157,"timestamp":"2019-11-09T18:40:50Z","version":3,"changeset":76851428,"user":"Hopperpop","uid":3664604,"nodes":[1038557083,1038557078,1038557104,1038557072,1038557108,1038557230,1038557227,1038557102,1038557137,1038575040,1038557191,1038557014,6960473080,1038557035,1038557012,1038557083],"tags":{"amenity":"parking"}},{"type":"way","id":89604999,"timestamp":"2020-01-16T22:01:28Z","version":5,"changeset":79667667,"user":"Hopperpop","uid":3664604,"nodes":[1038583404,1038583491,1038583375,1038583483,1038583479,1038583398,1038583459,1038583456,1038583446,1038583441,1038583425,1038583501,1038583451,1038583463,1038583476,1038583404],"tags":{"access":"yes","amenity":"parking","capacity":"57","carpool":"yes","description":"carpoolparking","fee":"no","name":"Loppem","parking":"surface"}},{"type":"way","id":92035679,"timestamp":"2019-10-05T08:05:33Z","version":7,"changeset":75311122,"user":"skyman81","uid":955688,"nodes":[1069177920,6853179264,1069177925,1069177919,6853179269,6853179268,6853179267,6853179215,6853179213,6853179214,1069178133,1069177984,6853179230,6853179228,6853179229,6853179224,6853179225,6853179227,6853179226,6853179216,6853179220,6853179219,6853179218,6853179217,6853179223,6853179221,6853179222,1069177967,1069177852,6853179211,6853179212,6853179210,6853179327,6853179208,6853179209,6853179203,1069177976,6853179207,6853179206,6853179205,6853179204,6853179202,1069177849,6852012579,6852012578,6852012580,6852012577,6852012581,6852012582,6852012583,1069177845,1759437085,1519342743,1519342742,1069178166,1069177853,1069177915,6853179235,6853179234,6853179236,1069177933,6853179237,6853179238,1069178021,6853179246,6853179244,6853179245,6853179240,6853179243,6853179241,6853179242,6853179239,6853179248,6853179249,6853179250,6853179247,1069177873,6853179262,6853179263,6853179260,6853179261,6853179256,6853179259,6853179257,6853179258,1069177920],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":101248451,"timestamp":"2018-05-23T14:18:27Z","version":2,"changeset":59213416,"user":"Jakka","uid":2403313,"nodes":[1168728158,1168728325,1168728159,5637669355,1168728109,1168728158],"tags":{"access":"private","amenity":"parking","name":"Parking Merkenveld"}},{"type":"way","id":101248462,"timestamp":"2020-05-25T13:53:02Z","version":3,"changeset":85720081,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[1168727876,1168728288,1168728412,1168728208,1168727876],"tags":{"amenity":"toilets","building":"yes","source:geometry:date":"2019-03-14","source:geometry:ref":"Gbg/6588148"}},{"type":"way","id":131622387,"timestamp":"2015-01-09T12:06:51Z","version":2,"changeset":28017707,"user":"TripleBee","uid":497177,"nodes":[1448421093,1448421099,1448421091,1448421081,1448421093],"tags":{"amenity":"parking","name":"Tudor - Zeeweg","parking":"surface"}},{"type":"way","id":145691934,"timestamp":"2012-01-15T12:43:37Z","version":1,"changeset":10397429,"user":"Sanderd17","uid":253266,"nodes":[1590642859,1590642860,1590642858,1590642849,1590642859],"tags":{"amenity":"parking"}},{"type":"way","id":145691937,"timestamp":"2012-01-15T12:43:37Z","version":1,"changeset":10397429,"user":"Sanderd17","uid":253266,"nodes":[1590642829,1590642828,1590642830,1590642832,1590642829],"tags":{"amenity":"parking"}},{"type":"way","id":158901716,"timestamp":"2017-06-13T07:12:20Z","version":2,"changeset":49490264,"user":"Jakka","uid":2403313,"nodes":[1710245713,1710245718,1710245707,1710245705,1710245703,1710245715,1710245711,1710245709,1710245701,1710245713],"tags":{"access":"yes","amenity":"parking","capacity":"14","fee":"no","parking":"surface"}},{"type":"way","id":158904558,"timestamp":"2020-12-22T22:39:41Z","version":4,"changeset":96283379,"user":"M!dgard","uid":763799,"nodes":[1710262742,1710262745,1710262735,1710262733,1710262732,1710262743,1710262741,1710262739,1710262744,1710262737,1710262736,1710262731,1710262738,1710262742],"tags":{"access":"yes","alt_name":"Schoolparking","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":158906028,"timestamp":"2017-06-13T07:27:19Z","version":5,"changeset":49490646,"user":"Jakka","uid":2403313,"nodes":[1710276259,1710276251,1810330766,1710276255,1710276261,1710276240,1710276232,1710276257,1710276243,1710276253,1810347217,1710276242,1710276259],"tags":{"access":"yes","amenity":"parking","fee":"no","name":"Parking Sportcentrum De Valkaart","parking":"surface"}},{"type":"way","id":160825858,"timestamp":"2012-04-23T20:35:52Z","version":1,"changeset":11399632,"user":"martino260","uid":655442,"nodes":[1728421375,1728421374,1728421379,1728421377,1728421376,1728421378,1728421375],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":162602213,"timestamp":"2020-04-11T18:12:16Z","version":8,"changeset":83407731,"user":"JanFi","uid":672253,"nodes":[1920143232,7393009684,7393048385,1744641293,1523513488,1744641292,1920143232],"tags":{"amenity":"parking","capacity":"15"}},{"type":"way","id":165489167,"timestamp":"2020-10-12T19:06:29Z","version":3,"changeset":92371840,"user":"L'imaginaire","uid":654234,"nodes":[4912197370,4912197365,4912197373,4912197364,4912197372,1770289505,4912197362,4912197371,4912197374,4912197363,4912197368,4912197366,4912197369,4912197367,4912197370],"tags":{"access":"yes","amenity":"parking","fee":"no","name":"Bad Neuheimplein","parking":"surface"}},{"type":"way","id":168291852,"timestamp":"2017-07-19T11:17:33Z","version":3,"changeset":50402298,"user":"martino260","uid":655442,"nodes":[1795793399,4979389763,1795793409,1795793395,1795793393,1795793397,1795793407,1795793406,1795793408,1795793405,1795793399],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":169875513,"timestamp":"2017-06-13T07:26:09Z","version":2,"changeset":49490613,"user":"Jakka","uid":2403313,"nodes":[1810345951,1810345955,1810345947,1810345944,1810345951],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":170015605,"timestamp":"2017-06-17T07:51:33Z","version":4,"changeset":49608752,"user":"rowers2","uid":2445224,"nodes":[1811673425,1811673421,1811673418,1811673423,1811673425],"tags":{"access":"private","amenity":"parking","name":"gheeraert E40","operator":"Gheeraert"}},{"type":"way","id":170018487,"timestamp":"2017-06-17T07:51:33Z","version":3,"changeset":49608752,"user":"rowers2","uid":2445224,"nodes":[1811699779,1811699778,1811699776,1811699777,1811699779],"tags":{"access":"private","amenity":"parking","name":"Gheeraert vooraan"}},{"type":"way","id":170559194,"timestamp":"2017-06-17T07:51:33Z","version":2,"changeset":49608752,"user":"rowers2","uid":2445224,"nodes":[1817319304,1817319302,1817319297,1817319301,1817319304],"tags":{"access":"private","amenity":"parking","name":"Gheeraert laadkade"}},{"type":"way","id":170559195,"timestamp":"2017-06-17T07:51:33Z","version":2,"changeset":49608752,"user":"rowers2","uid":2445224,"nodes":[1817319299,1817319303,1817319300,1817319292,1817319299],"tags":{"access":"private","amenity":"parking","name":"Gheeraert spoorweg trailers"}},{"type":"way","id":170559196,"timestamp":"2017-06-17T07:51:33Z","version":2,"changeset":49608752,"user":"rowers2","uid":2445224,"nodes":[1817319293,1817319289,1817319291,1817319296,1817319293],"tags":{"access":"private","amenity":"parking","name":"Gheeraert spoorweg trucks"}},{"type":"way","id":170559197,"timestamp":"2017-06-17T07:51:33Z","version":2,"changeset":49608752,"user":"rowers2","uid":2445224,"nodes":[1817319294,1817319298,1817319295,1817319290,1817319294],"tags":{"access":"private","amenity":"parking","name":"Gheeraert zijkant"}},{"type":"way","id":170559292,"timestamp":"2017-06-17T07:51:33Z","version":2,"changeset":49608752,"user":"rowers2","uid":2445224,"nodes":[1817320496,1817320494,1817320493,1817320495,1817320496],"tags":{"access":"private","amenity":"parking","name":"Gheeraert vooraan gebouw"}},{"type":"way","id":170559832,"timestamp":"2020-10-07T10:51:41Z","version":6,"changeset":92105788,"user":"effem","uid":16437,"nodes":[1817324515,1817324509,1817324491,6397031888,4044172008,4044172003,4044171997,4044171962,4044171957,4044171976,1817324489,1817324488,3550860268,1817324505,3550860269,1817324513,1817324515],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":223674368,"timestamp":"2020-12-03T18:47:28Z","version":3,"changeset":95244226,"user":"L'imaginaire","uid":654234,"nodes":[2325437844,8191691971,8191691973,8191691972,2325437840,8191691970,414025563,2325437844],"tags":{"amenity":"parking","name":"Tillegembos","parking":"surface"}},{"type":"way","id":237214948,"timestamp":"2017-06-17T07:51:35Z","version":2,"changeset":49608752,"user":"rowers2","uid":2445224,"nodes":[2451574741,2451574742,2451574744,1015583939,2451574741],"tags":{"access":"private","amenity":"parking"}},{"type":"way","id":237214949,"timestamp":"2017-06-17T07:51:35Z","version":2,"changeset":49608752,"user":"rowers2","uid":2445224,"nodes":[2451574748,2451574746,2451574747,2451574749,2451574748],"tags":{"access":"private","amenity":"parking"}},{"type":"way","id":237214950,"timestamp":"2017-06-17T07:51:35Z","version":3,"changeset":49608752,"user":"rowers2","uid":2445224,"nodes":[2451569392,1015567837,2451574745,2451574743,2451578121,2451569392],"tags":{"access":"private","amenity":"parking"}},{"type":"way","id":325909586,"timestamp":"2016-01-05T18:51:49Z","version":2,"changeset":36387330,"user":"JanFi","uid":672253,"nodes":[3325315243,111759500,3325315247,3325315232,3325315230,3325315226,1169056712,3325315243],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":326834162,"timestamp":"2021-10-10T21:49:11Z","version":4,"changeset":112350014,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[3335137807,3335137692,3335137795,9163493632,3335137802,3335137812,9163486855,9163486856,3335137823,3335137807],"tags":{"access":"customers","amenity":"parking","operator":"Best Western Weinebrugge","parking":"surface"}},{"type":"way","id":327849054,"timestamp":"2015-02-12T20:26:22Z","version":1,"changeset":28807613,"user":"escada","uid":436365,"nodes":[3346575929,3346575873,3346575876,3346575843,3346575845,3346575891,3346575901,3346575923,3346575928,3346575950,3346575929],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":327849055,"timestamp":"2016-10-08T21:24:46Z","version":2,"changeset":42742859,"user":"maggot27","uid":118021,"nodes":[3346575945,3346575946,3346575943,3346575933,3346575925,3346575917,3346575903,3346575908,3346575889,3346575886,3346575945],"tags":{"access":"customers","amenity":"parking","parking":"surface"}},{"type":"way","id":327849056,"timestamp":"2015-02-12T20:26:22Z","version":1,"changeset":28807613,"user":"escada","uid":436365,"nodes":[3346575865,3346575853,3346575855,3346575846,3346575840,3346575858,3346575865],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":374677860,"timestamp":"2015-10-10T09:08:20Z","version":1,"changeset":34545536,"user":"Jakka","uid":2403313,"nodes":[3780611504,3780611502,3780611500,3780611503,3780611504],"tags":{"amenity":"parking"}},{"type":"way","id":374677861,"timestamp":"2015-10-10T09:08:20Z","version":1,"changeset":34545536,"user":"Jakka","uid":2403313,"nodes":[3780611495,3780611493,3780611492,3780611494,3780611495],"tags":{"amenity":"parking"}},{"type":"way","id":374677862,"timestamp":"2015-10-10T09:08:20Z","version":1,"changeset":34545536,"user":"Jakka","uid":2403313,"nodes":[3780611498,3780611497,3780611496,3780611499,3780611501,3780611498],"tags":{"amenity":"parking"}},{"type":"way","id":389912371,"timestamp":"2016-01-06T16:51:45Z","version":1,"changeset":36407948,"user":"Spectrokid","uid":19775,"nodes":[3930713440,3930713451,3930713447,3930713437,3930713440],"tags":{"amenity":"parking"}},{"type":"way","id":389912372,"timestamp":"2019-11-16T13:17:09Z","version":4,"changeset":77164376,"user":"Hopperpop","uid":3664604,"nodes":[3930713454,3930713442,3930713435,3930713429,5826811614,3930713426,3930713430,6982605752,6982605754,3930713438,6982605769,6982605766,6982605767,6982605762,6982605764,3930713446,3930713454],"tags":{"access":"customers","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":401995684,"timestamp":"2020-10-07T10:52:00Z","version":3,"changeset":92105972,"user":"effem","uid":16437,"nodes":[4044171963,4044171954,4044171924,4044171936,4044171941,4044171963],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":500067820,"timestamp":"2017-06-13T07:49:12Z","version":1,"changeset":49491219,"user":"Jakka","uid":2403313,"nodes":[4912203166,4912203165,4912203164,4912203163,4912203162,4912203161,4912203160,4912203166],"tags":{"access":"yes","amenity":"parking","parking":"surface"}},{"type":"way","id":500067821,"timestamp":"2017-06-13T07:49:12Z","version":1,"changeset":49491219,"user":"Jakka","uid":2403313,"nodes":[4912203170,4912203169,4912203168,4912203167,4912203170],"tags":{"access":"yes","amenity":"parking","parking":"surface"}},{"type":"way","id":500067822,"timestamp":"2017-06-13T07:49:12Z","version":1,"changeset":49491219,"user":"Jakka","uid":2403313,"nodes":[4912203174,4912203173,4912203172,4912203171,4912203174],"tags":{"access":"yes","amenity":"parking","parking":"surface"}},{"type":"way","id":500067823,"timestamp":"2017-06-13T07:49:12Z","version":1,"changeset":49491219,"user":"Jakka","uid":2403313,"nodes":[4912203179,4912203178,4912203177,4912203176,4912203179],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":500069613,"timestamp":"2018-10-11T09:30:48Z","version":2,"changeset":63409550,"user":"Jakka","uid":2403313,"nodes":[4912214695,4912214685,4912214694,4912214693,4912214692,4912214680,4912214695],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":500071452,"timestamp":"2018-10-11T09:30:48Z","version":2,"changeset":63409550,"user":"Jakka","uid":2403313,"nodes":[4912225068,4912225062,4912225063,4912225053,4912225064,4912214694,4912214685,4912225068],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":500071455,"timestamp":"2018-10-11T09:30:48Z","version":2,"changeset":63409550,"user":"Jakka","uid":2403313,"nodes":[4912225070,4912214681,4912214686,4912225052,4912225051,4912225067,4912225062,4912225068,4912225070],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":500071458,"timestamp":"2018-10-11T09:30:48Z","version":2,"changeset":63409550,"user":"Jakka","uid":2403313,"nodes":[4912214695,4912214680,4912225069,4912225050,1525460846,4912214681,4912225070,4912214695],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":533276307,"timestamp":"2019-12-13T10:02:12Z","version":2,"changeset":78364882,"user":"skyman81","uid":955688,"nodes":[5173881316,5173881317,5173881318,7054196467,5173881316],"tags":{"amenity":"parking"}},{"type":"way","id":533276308,"timestamp":"2017-10-17T23:36:18Z","version":1,"changeset":53027174,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[5173881320,5173881621,5173881622,5173881623,5173881320],"tags":{"amenity":"parking"}},{"type":"way","id":533276309,"timestamp":"2017-10-17T23:36:18Z","version":1,"changeset":53027174,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[5173881624,5173881625,5173881626,5173881627,5173881624],"tags":{"amenity":"parking"}},{"type":"way","id":579848581,"timestamp":"2020-04-05T07:08:57Z","version":6,"changeset":83089516,"user":"Hopperpop","uid":3664604,"nodes":[4043782112,5825400688,5552466020,6997096756,6997096759,6997096758,5552466018,5552466013,5552466014,6997076567,4043782112],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":584455569,"timestamp":"2019-10-31T19:49:18Z","version":2,"changeset":76465627,"user":"Hopperpop","uid":3664604,"nodes":[5586765933,5586765934,5586765935,5586765936,5586765933],"tags":{"amenity":"parking"}},{"type":"way","id":585977870,"timestamp":"2019-10-11T13:28:22Z","version":2,"changeset":75566739,"user":"Hopperpop","uid":3664604,"nodes":[5587844460,5599314384,5599314385,1659850846,6870850178,5587844462,5587844461,6870863414,5587844460],"tags":{"amenity":"parking"}},{"type":"way","id":587014342,"timestamp":"2018-05-09T19:13:29Z","version":1,"changeset":58829130,"user":"Sille Van Landschoot","uid":4852501,"nodes":[5607796820,5607798725,5607798721,5607798722,5607796819,5607798723,5607796820],"tags":{"access":"permissive","amenity":"parking","park_ride":"no","parking":"surface","surface":"paved"}},{"type":"way","id":590167103,"timestamp":"2018-05-22T12:37:36Z","version":1,"changeset":59179114,"user":"ForstEK","uid":1737608,"nodes":[5635001277,5635001274,5635001275,5635001276,5635001277],"tags":{"amenity":"parking"}},{"type":"way","id":590167113,"timestamp":"2020-07-29T17:45:20Z","version":2,"changeset":88691835,"user":"JanFi","uid":672253,"nodes":[5635001312,5635001306,7767137237,7767137235,7767137236,7767137234,5635001312],"tags":{"amenity":"parking"}},{"type":"way","id":590167134,"timestamp":"2018-05-22T12:37:37Z","version":1,"changeset":59179114,"user":"ForstEK","uid":1737608,"nodes":[5635001374,5635001373,5635001372,5635001371,5635001374],"tags":{"amenity":"parking"}},{"type":"way","id":590167135,"timestamp":"2018-05-22T12:37:37Z","version":1,"changeset":59179114,"user":"ForstEK","uid":1737608,"nodes":[5635001378,5635001377,5635001376,5635001375,5635001378],"tags":{"amenity":"parking"}},{"type":"way","id":590167136,"timestamp":"2018-05-22T12:37:37Z","version":1,"changeset":59179114,"user":"ForstEK","uid":1737608,"nodes":[5635001382,5635001381,5635001380,5635001379,5635001382],"tags":{"amenity":"parking"}},{"type":"way","id":590167137,"timestamp":"2019-07-06T15:58:19Z","version":3,"changeset":71962591,"user":"gjosch","uid":1776978,"nodes":[5635001386,5882873336,5882873337,5882873338,5882873335,6593340582,6593340583,5882873334,6593340584,5635001385,5635001384,5635001383,5635001386],"tags":{"amenity":"parking"}},{"type":"way","id":590167147,"timestamp":"2018-05-22T12:37:38Z","version":1,"changeset":59179114,"user":"ForstEK","uid":1737608,"nodes":[5635001417,5635001414,5635001415,5635001416,5635001417],"tags":{"amenity":"parking"}},{"type":"way","id":601406079,"timestamp":"2018-06-24T22:15:06Z","version":1,"changeset":60131072,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[5716136617,5716136618,5716136619,5716136620,5716136617],"tags":{"amenity":"parking"}},{"type":"way","id":632813009,"timestamp":"2018-10-11T09:24:42Z","version":1,"changeset":63409297,"user":"Jakka","uid":2403313,"nodes":[5974489618,1810326044,1810326087,5974489617,5972179348,5972179347,5972179346,5972179345,5972179344,5972179343,5972179331,5974489616,5974489615,5974489614,5974489618],"tags":{"amenity":"parking","name":"Gemeenteplein","parking":"surface"}},{"type":"way","id":668043297,"timestamp":"2019-04-10T18:34:27Z","version":2,"changeset":69093378,"user":"RudolpheDeer","uid":9408828,"nodes":[6255587424,6255587425,6255587426,6255587427,6255587424],"tags":{"access":"private","amenity":"parking"}},{"type":"way","id":670104236,"timestamp":"2019-02-13T00:05:02Z","version":1,"changeset":67147239,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[6275462768,6275462769,6275462770,6275462771,6275462768],"tags":{"amenity":"parking"}},{"type":"way","id":670104238,"timestamp":"2019-02-13T00:05:02Z","version":1,"changeset":67147239,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[6275462772,6275462989,6275462773,6275462774,6275462775,6275462772],"tags":{"amenity":"parking"}},{"type":"way","id":670104239,"timestamp":"2019-02-13T00:05:02Z","version":1,"changeset":67147239,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[6275462776,6275462777,6275462778,6275462779,6275462776],"tags":{"amenity":"parking"}},{"type":"way","id":670104241,"timestamp":"2019-02-13T00:05:02Z","version":1,"changeset":67147239,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[6275462780,6275462781,6275462782,6275462783,6275462780],"tags":{"amenity":"parking"}},{"type":"way","id":670104242,"timestamp":"2019-02-13T00:05:02Z","version":1,"changeset":67147239,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[6275462784,6275462985,6275462988,6275462986,6275462987,6275462784],"tags":{"amenity":"parking"}},{"type":"way","id":671840055,"timestamp":"2019-02-20T15:15:45Z","version":1,"changeset":67395313,"user":"Tim Couwelier","uid":7246683,"nodes":[6291339827,6291339828,6291339816,6291339815,6291339822,6291339821,6291339829,6291339830,6291339827],"tags":{"amenity":"parking"}},{"type":"way","id":695825223,"timestamp":"2019-06-08T15:19:24Z","version":1,"changeset":71053301,"user":"Hopperpop","uid":3664604,"nodes":[1519476746,6533893620,6533893621,6533893622,1519476797,1519476620,1519476746],"tags":{"access":"yes","amenity":"parking"}},{"type":"way","id":695825224,"timestamp":"2019-06-08T15:19:24Z","version":1,"changeset":71053301,"user":"Hopperpop","uid":3664604,"nodes":[1519476744,6533893624,6533893625,6533893626,1519476698,1519476635,1519476744],"tags":{"access":"yes","amenity":"parking"}},{"type":"way","id":696040917,"timestamp":"2019-06-09T23:24:59Z","version":2,"changeset":71082992,"user":"Hopperpop","uid":3664604,"nodes":[6536026850,6536026851,6536026852,6536026853,6536026850],"tags":{"amenity":"parking","name":"Kasteel Tudor"}},{"type":"way","id":696043218,"timestamp":"2019-06-09T23:24:59Z","version":1,"changeset":71082992,"user":"Hopperpop","uid":3664604,"nodes":[6536038234,6536038235,6536038236,6536038237,6536038234],"tags":{"access":"customers","amenity":"parking"}},{"type":"way","id":700675991,"timestamp":"2020-12-18T10:48:20Z","version":2,"changeset":96062619,"user":"Hopperpop","uid":3664604,"nodes":[6579962064,6579962065,6579962066,6579962068,6579962067,6579962064],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":705278707,"timestamp":"2020-09-30T20:36:55Z","version":2,"changeset":91787895,"user":"L'imaginaire","uid":654234,"nodes":[6625037999,6625038000,6625038001,6625038002,6625038003,6004375826,6625038005,6625038006,6625037999],"tags":{"amenity":"parking"}},{"type":"way","id":719482833,"timestamp":"2019-08-28T21:18:49Z","version":1,"changeset":73857967,"user":"Hopperpop","uid":3664604,"nodes":[6754312544,6754312543,6754312542,6754312541,6754312544],"tags":{"access":"yes","amenity":"parking","capacity":"5"}},{"type":"way","id":719482834,"timestamp":"2019-08-28T21:18:49Z","version":1,"changeset":73857967,"user":"Hopperpop","uid":3664604,"nodes":[6754312565,6754312564,6754312563,6754312562,6754312565],"tags":{"access":"yes","amenity":"parking","capacity":"12"}},{"type":"way","id":737054013,"timestamp":"2019-10-20T15:39:32Z","version":1,"changeset":75957554,"user":"Hopperpop","uid":3664604,"nodes":[5826811496,5826811497,5826811494,5826811495,5826811496],"tags":{"amenity":"parking"}},{"type":"way","id":737054014,"timestamp":"2019-10-20T15:39:32Z","version":1,"changeset":75957554,"user":"Hopperpop","uid":3664604,"nodes":[5826810676,5826810673,5826810674,5826810675,5826810676],"tags":{"amenity":"parking"}},{"type":"way","id":737054015,"timestamp":"2019-10-20T15:39:32Z","version":1,"changeset":75957554,"user":"Hopperpop","uid":3664604,"nodes":[5826810681,5826810678,5826810679,5826810680,5826810681],"tags":{"amenity":"parking"}},{"type":"way","id":737093410,"timestamp":"2021-08-14T21:52:07Z","version":2,"changeset":109683899,"user":"effem","uid":16437,"nodes":[5826811559,5826811536,5826811535,5826811561,5826811560,5826811559],"tags":{"access":"yes","amenity":"parking","capacity":"4","fee":"no","parking":"surface"}},{"type":"way","id":737093411,"timestamp":"2021-08-14T21:52:03Z","version":2,"changeset":109683899,"user":"effem","uid":16437,"nodes":[5826811551,5826811547,5826811548,5826811549,5826811550,5826811551],"tags":{"access":"yes","amenity":"parking","capacity":"4","fee":"no","parking":"surface"}},{"type":"way","id":739652949,"timestamp":"2019-10-28T20:18:16Z","version":1,"changeset":76314556,"user":"Hopperpop","uid":3664604,"nodes":[6925536542,6925536541,6925536540,6925536539,6925536542],"tags":{"amenity":"parking","capacity":"6","parking":"surface"}},{"type":"way","id":741675236,"timestamp":"2020-12-17T22:07:55Z","version":4,"changeset":96029554,"user":"Hopperpop","uid":3664604,"nodes":[6943148207,6943148206,6943148205,6943148204,1637742821,6943148203,6943148202,6943148201,6943148200,6943148199,6943148198,6943148197,6943148207],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":742295526,"timestamp":"2019-11-05T19:27:15Z","version":1,"changeset":76664875,"user":"Hopperpop","uid":3664604,"nodes":[6949357909,6949357908,6949357907,6949357906,6949357909],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":742295527,"timestamp":"2019-11-05T19:27:15Z","version":1,"changeset":76664875,"user":"Hopperpop","uid":3664604,"nodes":[6949357913,6949357912,6949357911,6949357910,6949357913],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":742295528,"timestamp":"2019-11-05T19:27:15Z","version":1,"changeset":76664875,"user":"Hopperpop","uid":3664604,"nodes":[6949357917,6949357916,6949357915,6949357914,6949357917],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":742295529,"timestamp":"2019-11-05T19:27:15Z","version":1,"changeset":76664875,"user":"Hopperpop","uid":3664604,"nodes":[6949357921,6949357920,6949357919,6949357918,6949357921],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":746170866,"timestamp":"2019-11-16T15:27:02Z","version":1,"changeset":77167609,"user":"Hopperpop","uid":3664604,"nodes":[6982906547,6982906546,6982906545,6982906544,6982906543,6982906542,6982906547],"tags":{"access":"customers","amenity":"parking"}},{"type":"way","id":747880657,"timestamp":"2021-09-19T12:40:45Z","version":2,"changeset":111407274,"user":"Hopperpop","uid":3664604,"nodes":[3325315397,6997076566,6997076565,6997076563,6997076562,6997076564,3325315395,3325315397],"tags":{"access":"customers","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":763977465,"timestamp":"2020-12-17T21:59:46Z","version":2,"changeset":96029554,"user":"Hopperpop","uid":3664604,"nodes":[7137343680,7137343681,7137343682,7137343683,7137343680],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":763977466,"timestamp":"2020-12-17T21:59:40Z","version":2,"changeset":96029554,"user":"Hopperpop","uid":3664604,"nodes":[7137343684,7137383185,7137383186,7137383187,7137343684],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":803821090,"timestamp":"2020-05-14T17:37:10Z","version":1,"changeset":85215781,"user":"Hopperpop","uid":3664604,"nodes":[7519058290,7519058289,7519058288,7519058287,7519058290],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":803821091,"timestamp":"2020-05-14T17:37:10Z","version":1,"changeset":85215781,"user":"Hopperpop","uid":3664604,"nodes":[7519058294,7519058293,7519058292,7519058291,7519058294],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":803821092,"timestamp":"2020-05-14T17:37:10Z","version":1,"changeset":85215781,"user":"Hopperpop","uid":3664604,"nodes":[7519058298,7519058297,7519058296,7519058295,7519058298],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":803821093,"timestamp":"2020-05-14T17:37:10Z","version":1,"changeset":85215781,"user":"Hopperpop","uid":3664604,"nodes":[7519058302,7519058301,7519058300,7519058299,7519058302],"tags":{"access":"private","amenity":"parking","capacity":"6","parking":"surface"}},{"type":"way","id":804963962,"timestamp":"2020-05-17T17:09:31Z","version":1,"changeset":85342199,"user":"Hopperpop","uid":3664604,"nodes":[7529417225,7529417226,7529417227,7529417228,7529417229,7529417230,7529417232,7529417225],"tags":{"access":"customers","amenity":"parking","fee":"no","operator":"’t Kiekekot","parking":"surface","surface":"unpaved"}},{"type":"way","id":806875503,"timestamp":"2020-05-21T15:48:37Z","version":1,"changeset":85563652,"user":"Hopperpop","uid":3664604,"nodes":[4042671969,7545532512,7545532514,7545532513,3359977305,4042671969],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":806963547,"timestamp":"2020-05-21T21:16:34Z","version":1,"changeset":85574048,"user":"Hopperpop","uid":3664604,"nodes":[7546193222,7546193221,7546193220,7546193219,7546193222],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":865357121,"timestamp":"2020-10-30T14:45:23Z","version":1,"changeset":93296961,"user":"L'imaginaire","uid":654234,"nodes":[8065883228,8065883227,8065883226,8065883225,8065883228],"tags":{"amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":865357122,"timestamp":"2020-10-30T14:45:23Z","version":1,"changeset":93296961,"user":"L'imaginaire","uid":654234,"nodes":[8065883233,8065883230,8065883229,8065883232,8065883233],"tags":{"amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":879281221,"timestamp":"2020-11-30T14:18:18Z","version":1,"changeset":95050429,"user":"M!dgard","uid":763799,"nodes":[8179735269,8179735268,8179735267,8179735266,8179735265,8179735264,8179735224,8179735269],"tags":{"access":"customers","amenity":"parking","parking":"surface"}},{"type":"way","id":881770201,"timestamp":"2020-12-07T00:46:56Z","version":1,"changeset":95385582,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[8200275847,8200275848,8200275844,8200275853,8200275849,8200275847],"tags":{"amenity":"parking","parking":"surface","surface":"grass"}},{"type":"way","id":978360549,"timestamp":"2021-09-01T08:53:08Z","version":1,"changeset":110553113,"user":"JanFi","uid":672253,"nodes":[5761770202,5761770204,9052878229,9052878228,5761770202],"tags":{"amenity":"parking"}},{"type":"way","id":1009692722,"timestamp":"2021-12-06T18:34:20Z","version":1,"changeset":114629990,"user":"L'imaginaire","uid":654234,"nodes":[9316118540,9316118536,9316118531,9316118535,9316118534,9316118533,9316118530,9316118532,3311835478,9316118540],"tags":{"amenity":"parking","parking":"street_side"}},{"type":"relation","id":8188853,"timestamp":"2020-07-05T12:38:48Z","version":13,"changeset":87554177,"user":"Pieter Vander Vennet","uid":3818858,"members":[{"type":"way","ref":577572397,"role":"outer"},{"type":"way","ref":577572399,"role":"outer"}],"tags":{"access":"guided","curator":"Luc Maene;Geert De Clercq","email":"lucmaene@hotmail.com;geert.de.clercq1@pandora.be","landuse":"meadow","leisure":"nature_reserve","name":"De Wulgenbroeken","natural":"wetland","operator":"Natuurpunt Brugge","type":"multipolygon","website":"https://natuurpuntbrugge.be/wulgenbroeken/","wetland":"wet_meadow","wikidata":"Q60061498","wikipedia":"nl:Wulgenbroeken"}},{"type":"relation","id":11163488,"timestamp":"2021-10-04T14:09:47Z","version":15,"changeset":112079863,"user":"DieterWesttoer","uid":13062237,"members":[{"type":"way","ref":810604915,"role":"outer"},{"type":"way","ref":989393316,"role":"outer"},{"type":"way","ref":389026405,"role":"inner"},{"type":"way","ref":810607458,"role":"outer"}],"tags":{"access":"yes","curator":"Kris Lesage","description":"Wat Doeveren zo uniek maakt, zijn zijn kleine heidegebiedjes met soorten die erg verschillen van de Kempense heide. Doeveren en omstreken was vroeger één groot heidegebied, maar bestaat nu grotendeels uit bossen.","dog":"leashed","email":"doeveren@natuurpuntzedelgem.be","image":"https://i.imgur.com/NEAsQZG.jpg","image:0":"https://i.imgur.com/Dq71hyQ.jpg","image:1":"https://i.imgur.com/mAIiT4f.jpg","image:2":"https://i.imgur.com/dELZU97.jpg","image:3":"https://i.imgur.com/Bso57JC.jpg","image:4":"https://i.imgur.com/9DtcfXo.jpg","image:5":"https://i.imgur.com/0R6eBfk.jpg","image:6":"https://i.imgur.com/b0JpvbR.jpg","leisure":"nature_reserve","name":"Doeveren","operator":"Natuurpunt Zedelgem","phone":"+32 486 25 25 30","type":"multipolygon","website":"https://www.natuurpuntzedelgem.be/gebieden/doeveren/","wikidata":"Q56395754","wikipedia":"nl:Doeveren (natuurgebied)"}},{"type":"relation","id":11790117,"timestamp":"2020-10-24T19:11:01Z","version":1,"changeset":92997462,"user":"Pieter Vander Vennet","uid":3818858,"members":[{"type":"way","ref":863373849,"role":"outer"},{"type":"way","ref":777280458,"role":"outer"}],"tags":{"access":"no","description:0":"In gebruik als waterbuffering","leisure":"nature_reserve","name":"Kerkebeek","operator":"Natuurpunt Brugge","type":"multipolygon"}},{"type":"node","id":1038638696,"lat":51.1197075,"lon":3.1827007},{"type":"node","id":7578975029,"lat":51.1199041,"lon":3.1828945},{"type":"node","id":7578975030,"lat":51.1201514,"lon":3.1831942},{"type":"node","id":1038638743,"lat":51.1202445,"lon":3.1894878},{"type":"node","id":7578975002,"lat":51.1202598,"lon":3.1897155},{"type":"node","id":7578975007,"lat":51.1199771,"lon":3.1863015},{"type":"node","id":7578975008,"lat":51.1199523,"lon":3.1863031},{"type":"node","id":7578975009,"lat":51.1199279,"lon":3.1859524},{"type":"node","id":1168728109,"lat":51.1275839,"lon":3.1765505},{"type":"node","id":1168728158,"lat":51.1278835,"lon":3.1763986},{"type":"node","id":1168728159,"lat":51.1276298,"lon":3.1767808},{"type":"node","id":5637669355,"lat":51.1276039,"lon":3.1766509},{"type":"node","id":1038638723,"lat":51.1272818,"lon":3.184601},{"type":"node","id":7554434438,"lat":51.1225298,"lon":3.1847624},{"type":"node","id":7578865273,"lat":51.122084,"lon":3.1846859},{"type":"node","id":7578975032,"lat":51.1215762,"lon":3.1842866},{"type":"node","id":1168727876,"lat":51.1290569,"lon":3.1766033},{"type":"node","id":1168728208,"lat":51.1289763,"lon":3.1767696},{"type":"node","id":1168728288,"lat":51.1291195,"lon":3.1766799},{"type":"node","id":1168728325,"lat":51.1279295,"lon":3.1766288},{"type":"node","id":1168728412,"lat":51.1290389,"lon":3.1768463},{"type":"node","id":1038638712,"lat":51.1282367,"lon":3.1840296},{"type":"node","id":1168727824,"lat":51.1312478,"lon":3.182233},{"type":"node","id":3922375256,"lat":51.1301155,"lon":3.1848042},{"type":"node","id":3922380071,"lat":51.1304048,"lon":3.1838954},{"type":"node","id":3922380081,"lat":51.1305694,"lon":3.1845093},{"type":"node","id":3922380086,"lat":51.1306445,"lon":3.1848152},{"type":"node","id":3922380092,"lat":51.1307378,"lon":3.1849591},{"type":"node","id":7577430793,"lat":51.1289492,"lon":3.1836032},{"type":"node","id":7578975024,"lat":51.1299598,"lon":3.1841704},{"type":"node","id":7578975028,"lat":51.1322547,"lon":3.1833542},{"type":"node","id":7578975049,"lat":51.1313772,"lon":3.1838431},{"type":"node","id":9167054153,"lat":51.1310258,"lon":3.1823668},{"type":"node","id":9167054154,"lat":51.13145,"lon":3.1841492},{"type":"node","id":9167054156,"lat":51.1316731,"lon":3.1850331},{"type":"node","id":9274761589,"lat":51.1297088,"lon":3.1831312},{"type":"node","id":9274761596,"lat":51.1296735,"lon":3.1831518},{"type":"node","id":929120698,"lat":51.1276376,"lon":3.1903134},{"type":"node","id":1038638592,"lat":51.1264889,"lon":3.19027},{"type":"node","id":1038638661,"lat":51.1258582,"lon":3.1854626},{"type":"node","id":1038638721,"lat":51.125636,"lon":3.1855855},{"type":"node","id":1038638753,"lat":51.123845,"lon":3.1880289},{"type":"node","id":3921878998,"lat":51.1255719,"lon":3.1902463},{"type":"node","id":3921879004,"lat":51.1275463,"lon":3.188843},{"type":"node","id":3921879011,"lat":51.1271626,"lon":3.1872368},{"type":"node","id":3921879019,"lat":51.1277666,"lon":3.1868505},{"type":"node","id":7554434436,"lat":51.1252645,"lon":3.1852941},{"type":"node","id":7578865274,"lat":51.1230564,"lon":3.187978},{"type":"node","id":7578865275,"lat":51.1226417,"lon":3.188075},{"type":"node","id":7578904489,"lat":51.1247504,"lon":3.1900249},{"type":"node","id":7578974988,"lat":51.1223221,"lon":3.1906513},{"type":"node","id":7578974989,"lat":51.1224255,"lon":3.1905646},{"type":"node","id":7578974990,"lat":51.1224672,"lon":3.1905195},{"type":"node","id":7578974991,"lat":51.1228709,"lon":3.1901867},{"type":"node","id":7578974992,"lat":51.1229568,"lon":3.1901459},{"type":"node","id":7578974995,"lat":51.123814,"lon":3.1899138},{"type":"node","id":7578974996,"lat":51.1239199,"lon":3.189925},{"type":"node","id":7578974997,"lat":51.1244111,"lon":3.1899686},{"type":"node","id":7578974998,"lat":51.1248503,"lon":3.190215},{"type":"node","id":7578974999,"lat":51.1247917,"lon":3.1900516},{"type":"node","id":7578975000,"lat":51.1248293,"lon":3.1900978},{"type":"node","id":7578975001,"lat":51.1248444,"lon":3.1901483},{"type":"node","id":7578975035,"lat":51.1250798,"lon":3.1851611},{"type":"node","id":7578975045,"lat":51.1278881,"lon":3.1882941},{"type":"node","id":9199177059,"lat":51.1256647,"lon":3.1855696},{"type":"node","id":7578987409,"lat":51.1232707,"lon":3.1920382},{"type":"node","id":7578987413,"lat":51.1260416,"lon":3.1973652},{"type":"node","id":7578987414,"lat":51.1263443,"lon":3.1973775},{"type":"node","id":7578987416,"lat":51.1278708,"lon":3.1974134},{"type":"node","id":7578987417,"lat":51.126749,"lon":3.197258},{"type":"node","id":1675648152,"lat":51.1281877,"lon":3.1903323},{"type":"node","id":2732486274,"lat":51.1302553,"lon":3.1886305},{"type":"node","id":3921879018,"lat":51.1280809,"lon":3.188102},{"type":"node","id":3922380061,"lat":51.1301929,"lon":3.1895402},{"type":"node","id":3922380083,"lat":51.1305788,"lon":3.1884337},{"type":"node","id":3922380095,"lat":51.130784,"lon":3.1852632},{"type":"node","id":7578865281,"lat":51.1283938,"lon":3.1903716},{"type":"node","id":7578865283,"lat":51.1288414,"lon":3.1904911},{"type":"node","id":7578960079,"lat":51.1303025,"lon":3.1855669},{"type":"node","id":7578975012,"lat":51.1294792,"lon":3.1906231},{"type":"node","id":7578975015,"lat":51.1297374,"lon":3.1907018},{"type":"node","id":7578975016,"lat":51.1300451,"lon":3.1907679},{"type":"node","id":7578975018,"lat":51.1305785,"lon":3.186668},{"type":"node","id":7578975019,"lat":51.130956,"lon":3.1881852},{"type":"node","id":7578975021,"lat":51.1303082,"lon":3.1855908},{"type":"node","id":7578975026,"lat":51.1310167,"lon":3.1861981},{"type":"node","id":7578975027,"lat":51.1318642,"lon":3.1857905},{"type":"node","id":7578975040,"lat":51.1280348,"lon":3.1889503},{"type":"node","id":7578975044,"lat":51.1279308,"lon":3.1875031},{"type":"node","id":7578975046,"lat":51.1279329,"lon":3.1881992},{"type":"node","id":9167054157,"lat":51.1308023,"lon":3.1852517},{"type":"node","id":9274761591,"lat":51.1310994,"lon":3.1862668},{"type":"node","id":9274761592,"lat":51.1310643,"lon":3.1862655},{"type":"node","id":9274761593,"lat":51.1310386,"lon":3.1862393},{"type":"node","id":7578987418,"lat":51.128003,"lon":3.1959031},{"type":"node","id":7578987419,"lat":51.1282167,"lon":3.193723},{"type":"node","id":5745833239,"lat":51.1258572,"lon":3.1996713},{"type":"node","id":5745833240,"lat":51.1257519,"lon":3.1995939},{"type":"node","id":5745833241,"lat":51.1253365,"lon":3.1991234},{"type":"node","id":7578987410,"lat":51.1243814,"lon":3.1988516},{"type":"node","id":7578987411,"lat":51.1243992,"lon":3.1989686},{"type":"node","id":7578987412,"lat":51.1259883,"lon":3.1997074},{"type":"node","id":7578987415,"lat":51.1260745,"lon":3.1997142},{"type":"node","id":1590642829,"lat":51.1333867,"lon":3.2308055},{"type":"node","id":1590642832,"lat":51.1334371,"lon":3.2308262},{"type":"node","id":1590642849,"lat":51.1336392,"lon":3.2305316},{"type":"node","id":1590642858,"lat":51.133659,"lon":3.2303991},{"type":"node","id":1590642859,"lat":51.1336899,"lon":3.2305508},{"type":"node","id":1590642860,"lat":51.1337096,"lon":3.2304183},{"type":"node","id":1590642828,"lat":51.1333653,"lon":3.2309374},{"type":"node","id":1590642830,"lat":51.1334157,"lon":3.2309581},{"type":"node","id":3311835478,"lat":51.133195,"lon":3.2334351},{"type":"node","id":9316118530,"lat":51.1331607,"lon":3.2333604},{"type":"node","id":9316118531,"lat":51.1330927,"lon":3.2334241},{"type":"node","id":9316118532,"lat":51.1331767,"lon":3.233347},{"type":"node","id":9316118533,"lat":51.133147,"lon":3.2333808},{"type":"node","id":9316118534,"lat":51.1331302,"lon":3.2334006},{"type":"node","id":9316118535,"lat":51.1331127,"lon":3.2334144},{"type":"node","id":9316118536,"lat":51.1330784,"lon":3.2334281},{"type":"node","id":9316118540,"lat":51.1330946,"lon":3.2335103},{"type":"node","id":6579962064,"lat":51.1367061,"lon":3.1640546},{"type":"node","id":6579962065,"lat":51.1361156,"lon":3.1646435},{"type":"node","id":6579962066,"lat":51.1357413,"lon":3.1637334},{"type":"node","id":6579962067,"lat":51.1359511,"lon":3.1637408},{"type":"node","id":6579962068,"lat":51.1359389,"lon":3.1638093},{"type":"node","id":7546193219,"lat":51.1456739,"lon":3.1637073},{"type":"node","id":7546193220,"lat":51.1455706,"lon":3.1643444},{"type":"node","id":7546193221,"lat":51.1456623,"lon":3.1643821},{"type":"node","id":7546193222,"lat":51.1457656,"lon":3.1637451},{"type":"node","id":3359977305,"lat":51.1464982,"lon":3.1689911},{"type":"node","id":4042671969,"lat":51.1461398,"lon":3.169233},{"type":"node","id":7545532512,"lat":51.1463103,"lon":3.169498},{"type":"node","id":7545532513,"lat":51.1466008,"lon":3.1695349},{"type":"node","id":7545532514,"lat":51.1464331,"lon":3.16962},{"type":"node","id":8200275848,"lat":51.1409105,"lon":3.1800288},{"type":"node","id":8200275844,"lat":51.1416967,"lon":3.1797728},{"type":"node","id":8200275847,"lat":51.1411211,"lon":3.1805153},{"type":"node","id":8200275849,"lat":51.1417397,"lon":3.1802115},{"type":"node","id":8200275853,"lat":51.1417351,"lon":3.1801651},{"type":"node","id":111759500,"lat":51.1483444,"lon":3.1886487},{"type":"node","id":1169056712,"lat":51.1482974,"lon":3.1884805},{"type":"node","id":3325315226,"lat":51.147926,"lon":3.1887015},{"type":"node","id":3325315230,"lat":51.1479856,"lon":3.1889124},{"type":"node","id":3325315232,"lat":51.1480454,"lon":3.1891027},{"type":"node","id":3325315243,"lat":51.1483285,"lon":3.1885919},{"type":"node","id":3325315247,"lat":51.1484007,"lon":3.1888131},{"type":"node","id":5826810673,"lat":51.1512507,"lon":3.1914885},{"type":"node","id":5826810674,"lat":51.15126,"lon":3.1914533},{"type":"node","id":5826810675,"lat":51.1510883,"lon":3.1912776},{"type":"node","id":5826810676,"lat":51.151057,"lon":3.1912906},{"type":"node","id":5826810678,"lat":51.1509897,"lon":3.1911759},{"type":"node","id":5826810679,"lat":51.1510025,"lon":3.1911334},{"type":"node","id":5826810680,"lat":51.1509352,"lon":3.1908874},{"type":"node","id":5826810681,"lat":51.1509074,"lon":3.1908689},{"type":"node","id":5826811494,"lat":51.1512125,"lon":3.1911315},{"type":"node","id":5826811495,"lat":51.1512055,"lon":3.191187},{"type":"node","id":5826811496,"lat":51.151296,"lon":3.1914182},{"type":"node","id":5826811497,"lat":51.1513261,"lon":3.1914182},{"type":"node","id":5826811535,"lat":51.1517839,"lon":3.1959375},{"type":"node","id":5826811536,"lat":51.1518581,"lon":3.1959708},{"type":"node","id":5826811547,"lat":51.1515913,"lon":3.196115},{"type":"node","id":5826811548,"lat":51.1516307,"lon":3.1961465},{"type":"node","id":5826811549,"lat":51.1516435,"lon":3.1961076},{"type":"node","id":5826811550,"lat":51.1516087,"lon":3.1959541},{"type":"node","id":5826811551,"lat":51.1515437,"lon":3.1959024},{"type":"node","id":5826811559,"lat":51.1517896,"lon":3.1957717},{"type":"node","id":5826811560,"lat":51.1517417,"lon":3.1957528},{"type":"node","id":5826811561,"lat":51.1517365,"lon":3.1957872},{"type":"node","id":3325315395,"lat":51.1544187,"lon":3.1856685},{"type":"node","id":3325315397,"lat":51.1545358,"lon":3.1860117},{"type":"node","id":3930713426,"lat":51.1571474,"lon":3.1889324},{"type":"node","id":3930713429,"lat":51.1573669,"lon":3.1883265},{"type":"node","id":3930713430,"lat":51.1573202,"lon":3.1890776},{"type":"node","id":3930713435,"lat":51.1574561,"lon":3.1883916},{"type":"node","id":3930713437,"lat":51.1574971,"lon":3.1893349},{"type":"node","id":3930713438,"lat":51.1574907,"lon":3.1884223},{"type":"node","id":3930713440,"lat":51.1575693,"lon":3.1890951},{"type":"node","id":3930713442,"lat":51.1575932,"lon":3.1879961},{"type":"node","id":3930713446,"lat":51.1577118,"lon":3.1885611},{"type":"node","id":3930713447,"lat":51.157698,"lon":3.1894886},{"type":"node","id":3930713451,"lat":51.1577702,"lon":3.1892488},{"type":"node","id":3930713454,"lat":51.1577969,"lon":3.1882567},{"type":"node","id":4043782112,"lat":51.1549447,"lon":3.1864571},{"type":"node","id":5552466013,"lat":51.1545783,"lon":3.1874672},{"type":"node","id":5552466014,"lat":51.1543143,"lon":3.1873045},{"type":"node","id":5552466018,"lat":51.1545999,"lon":3.1873846},{"type":"node","id":5552466020,"lat":51.1548079,"lon":3.1868846},{"type":"node","id":5825400688,"lat":51.1549303,"lon":3.1867969},{"type":"node","id":5826811614,"lat":51.1572659,"lon":3.1885288},{"type":"node","id":6949357906,"lat":51.1572911,"lon":3.1915323},{"type":"node","id":6949357909,"lat":51.1573109,"lon":3.1914572},{"type":"node","id":6949357910,"lat":51.1574373,"lon":3.1913744},{"type":"node","id":6949357911,"lat":51.1574179,"lon":3.1914502},{"type":"node","id":6949357912,"lat":51.1575109,"lon":3.1915112},{"type":"node","id":6949357913,"lat":51.1575304,"lon":3.1914354},{"type":"node","id":6949357914,"lat":51.1574638,"lon":3.1912712},{"type":"node","id":6949357915,"lat":51.1574444,"lon":3.1913473},{"type":"node","id":6949357916,"lat":51.1575599,"lon":3.191423},{"type":"node","id":6949357917,"lat":51.1575803,"lon":3.1913473},{"type":"node","id":6949357918,"lat":51.157501,"lon":3.1911303},{"type":"node","id":6949357919,"lat":51.1574808,"lon":3.1912058},{"type":"node","id":6949357920,"lat":51.1577374,"lon":3.1913724},{"type":"node","id":6949357921,"lat":51.1577563,"lon":3.1912987},{"type":"node","id":6982605752,"lat":51.1574664,"lon":3.1885975},{"type":"node","id":6982605754,"lat":51.1574428,"lon":3.1885793},{"type":"node","id":6982605762,"lat":51.1576066,"lon":3.1884793},{"type":"node","id":6982605764,"lat":51.1576853,"lon":3.18854},{"type":"node","id":6982605766,"lat":51.1575125,"lon":3.1884502},{"type":"node","id":6982605767,"lat":51.1575959,"lon":3.1885145},{"type":"node","id":6982605769,"lat":51.1575152,"lon":3.1884412},{"type":"node","id":6982906542,"lat":51.1591649,"lon":3.1904238},{"type":"node","id":6982906543,"lat":51.1592937,"lon":3.1905221},{"type":"node","id":6982906544,"lat":51.1593438,"lon":3.1903659},{"type":"node","id":6982906545,"lat":51.1593158,"lon":3.1903453},{"type":"node","id":6982906546,"lat":51.1593351,"lon":3.1902852},{"type":"node","id":6982906547,"lat":51.1592385,"lon":3.1902052},{"type":"node","id":6997076562,"lat":51.1546633,"lon":3.1858333},{"type":"node","id":6997076563,"lat":51.1546293,"lon":3.1858642},{"type":"node","id":6997076564,"lat":51.154594,"lon":3.1856715},{"type":"node","id":6997076565,"lat":51.1546727,"lon":3.1859889},{"type":"node","id":6997076566,"lat":51.1545545,"lon":3.1860687},{"type":"node","id":6997076567,"lat":51.1543063,"lon":3.1869337},{"type":"node","id":6997096756,"lat":51.1547387,"lon":3.1868376},{"type":"node","id":6997096758,"lat":51.1546899,"lon":3.1870707},{"type":"node","id":6997096759,"lat":51.1546751,"lon":3.1870601},{"type":"node","id":7137343680,"lat":51.1558646,"lon":3.1876808},{"type":"node","id":7137343681,"lat":51.1558466,"lon":3.1877456},{"type":"node","id":7137343682,"lat":51.1555824,"lon":3.187559},{"type":"node","id":7137343683,"lat":51.1556004,"lon":3.1874941},{"type":"node","id":7137343684,"lat":51.1555549,"lon":3.1874612},{"type":"node","id":7137383185,"lat":51.1555369,"lon":3.1875268},{"type":"node","id":7137383186,"lat":51.1553925,"lon":3.1874261},{"type":"node","id":7137383187,"lat":51.1554105,"lon":3.1873604},{"type":"node","id":7519058287,"lat":51.1555296,"lon":3.1858152},{"type":"node","id":7519058288,"lat":51.1555027,"lon":3.1858752},{"type":"node","id":7519058289,"lat":51.1556329,"lon":3.1860234},{"type":"node","id":7519058290,"lat":51.1556597,"lon":3.1859634},{"type":"node","id":7519058291,"lat":51.1557039,"lon":3.1860155},{"type":"node","id":7519058292,"lat":51.1556789,"lon":3.1860736},{"type":"node","id":7519058293,"lat":51.1558105,"lon":3.1862177},{"type":"node","id":7519058294,"lat":51.1558355,"lon":3.1861597},{"type":"node","id":7519058295,"lat":51.1557209,"lon":3.185828},{"type":"node","id":7519058296,"lat":51.1556932,"lon":3.1858902},{"type":"node","id":7519058297,"lat":51.1558686,"lon":3.1860888},{"type":"node","id":7519058298,"lat":51.1558963,"lon":3.1860265},{"type":"node","id":7519058299,"lat":51.1555421,"lon":3.1856365},{"type":"node","id":7519058300,"lat":51.1555168,"lon":3.1856923},{"type":"node","id":7519058301,"lat":51.1556479,"lon":3.1858437},{"type":"node","id":7519058302,"lat":51.1556732,"lon":3.1857879},{"type":"node","id":150996092,"lat":51.1554945,"lon":3.1954639},{"type":"node","id":150996093,"lat":51.155531,"lon":3.1953168},{"type":"node","id":150996094,"lat":51.1554912,"lon":3.1943936},{"type":"node","id":150996095,"lat":51.155456,"lon":3.1942488},{"type":"node","id":150996097,"lat":51.155432,"lon":3.1942095},{"type":"node","id":150996098,"lat":51.155397,"lon":3.1941906},{"type":"node","id":150996099,"lat":51.1552938,"lon":3.1945134},{"type":"node","id":150996100,"lat":51.1552701,"lon":3.1949002},{"type":"node","id":150996101,"lat":51.1553901,"lon":3.1953415},{"type":"node","id":1015567837,"lat":51.1603457,"lon":3.1926746},{"type":"node","id":1015583939,"lat":51.1598982,"lon":3.1934595},{"type":"node","id":1659850846,"lat":51.1562462,"lon":3.1925019},{"type":"node","id":1811699776,"lat":51.1604859,"lon":3.1920734},{"type":"node","id":1811699777,"lat":51.1605587,"lon":3.1917984},{"type":"node","id":1817319289,"lat":51.1599853,"lon":3.1935159},{"type":"node","id":1817319290,"lat":51.1600476,"lon":3.1933385},{"type":"node","id":1817319291,"lat":51.1600745,"lon":3.1934309},{"type":"node","id":1817319292,"lat":51.1602073,"lon":3.1941751},{"type":"node","id":1817319293,"lat":51.160208,"lon":3.1941098},{"type":"node","id":1817319294,"lat":51.1602178,"lon":3.1935425},{"type":"node","id":1817319295,"lat":51.1602385,"lon":3.19297},{"type":"node","id":1817319296,"lat":51.1602972,"lon":3.1940248},{"type":"node","id":1817319297,"lat":51.1603313,"lon":3.193809},{"type":"node","id":1817319298,"lat":51.1603427,"lon":3.1930326},{"type":"node","id":1817319299,"lat":51.1603716,"lon":3.1940192},{"type":"node","id":1817319300,"lat":51.1603777,"lon":3.1946319},{"type":"node","id":1817319301,"lat":51.1604665,"lon":3.193304},{"type":"node","id":1817319302,"lat":51.1604758,"lon":3.1939077},{"type":"node","id":1817319303,"lat":51.1605421,"lon":3.194476},{"type":"node","id":1817319304,"lat":51.1606037,"lon":3.1933895},{"type":"node","id":1817320493,"lat":51.1604248,"lon":3.1927398},{"type":"node","id":1817320494,"lat":51.1604851,"lon":3.192495},{"type":"node","id":2451569392,"lat":51.1598651,"lon":3.1919974},{"type":"node","id":2451574741,"lat":51.1594995,"lon":3.1924908},{"type":"node","id":2451574742,"lat":51.1596217,"lon":3.1923259},{"type":"node","id":2451574743,"lat":51.1597161,"lon":3.1922023},{"type":"node","id":2451574744,"lat":51.1600391,"lon":3.1932123},{"type":"node","id":2451574745,"lat":51.1601904,"lon":3.192947},{"type":"node","id":2451574746,"lat":51.1603862,"lon":3.1925461},{"type":"node","id":2451574747,"lat":51.1604272,"lon":3.19257},{"type":"node","id":2451574748,"lat":51.1604837,"lon":3.1921535},{"type":"node","id":2451574749,"lat":51.1605266,"lon":3.1921769},{"type":"node","id":2451578121,"lat":51.159758,"lon":3.1921448},{"type":"node","id":5587844460,"lat":51.1562664,"lon":3.1919544},{"type":"node","id":5587844461,"lat":51.15612,"lon":3.1920681},{"type":"node","id":5587844462,"lat":51.1561808,"lon":3.1922614},{"type":"node","id":5599314384,"lat":51.1563882,"lon":3.1923707},{"type":"node","id":5599314385,"lat":51.1563587,"lon":3.1924465},{"type":"node","id":6754312541,"lat":51.154716,"lon":3.1952084},{"type":"node","id":6754312542,"lat":51.1547723,"lon":3.1953372},{"type":"node","id":6754312543,"lat":51.1548078,"lon":3.1952983},{"type":"node","id":6754312544,"lat":51.1547519,"lon":3.1951702},{"type":"node","id":6754312550,"lat":51.1555879,"lon":3.1950341},{"type":"node","id":6754312551,"lat":51.1556025,"lon":3.194956},{"type":"node","id":6754312552,"lat":51.1555664,"lon":3.1952408},{"type":"node","id":6754312553,"lat":51.1556188,"lon":3.1951751},{"type":"node","id":6754312554,"lat":51.1554565,"lon":3.195427},{"type":"node","id":6754312555,"lat":51.1552894,"lon":3.1950649},{"type":"node","id":6754312556,"lat":51.1553277,"lon":3.1951991},{"type":"node","id":6754312557,"lat":51.1552774,"lon":3.1947027},{"type":"node","id":6754312558,"lat":51.1553131,"lon":3.1943816},{"type":"node","id":6754312559,"lat":51.1553397,"lon":3.1942577},{"type":"node","id":6754312560,"lat":51.1553697,"lon":3.1942084},{"type":"node","id":6754312562,"lat":51.1548064,"lon":3.1954209},{"type":"node","id":6754312563,"lat":51.1548266,"lon":3.1954893},{"type":"node","id":6754312564,"lat":51.1550417,"lon":3.1953175},{"type":"node","id":6754312565,"lat":51.1550193,"lon":3.1952538},{"type":"node","id":6870850178,"lat":51.1561935,"lon":3.1923019},{"type":"node","id":6870863414,"lat":51.1562489,"lon":3.1919675},{"type":"node","id":6949357907,"lat":51.1575239,"lon":3.1916859},{"type":"node","id":6949357908,"lat":51.1575439,"lon":3.1916101},{"type":"node","id":1448421081,"lat":51.167491,"lon":3.1713256},{"type":"node","id":1448421091,"lat":51.1677042,"lon":3.1714548},{"type":"node","id":1448421093,"lat":51.1677455,"lon":3.1702529},{"type":"node","id":1448421099,"lat":51.1679647,"lon":3.1703977},{"type":"node","id":6536026850,"lat":51.1711159,"lon":3.1669401},{"type":"node","id":6536026851,"lat":51.1712692,"lon":3.167296},{"type":"node","id":6536026852,"lat":51.1711296,"lon":3.1674712},{"type":"node","id":6536026853,"lat":51.1709602,"lon":3.1671189},{"type":"node","id":6536038234,"lat":51.1711913,"lon":3.165543},{"type":"node","id":6536038235,"lat":51.1711301,"lon":3.1656263},{"type":"node","id":6536038236,"lat":51.1712318,"lon":3.1658161},{"type":"node","id":6536038237,"lat":51.171293,"lon":3.1657327},{"type":"node","id":1038583451,"lat":51.1625071,"lon":3.191602},{"type":"node","id":4044171936,"lat":51.1609177,"lon":3.1911926},{"type":"node","id":4044171941,"lat":51.1609801,"lon":3.191229},{"type":"node","id":4044171963,"lat":51.1611962,"lon":3.1913534},{"type":"node","id":903903386,"lat":51.1618084,"lon":3.1932127},{"type":"node","id":903903387,"lat":51.1623536,"lon":3.1936011},{"type":"node","id":903903388,"lat":51.1624429,"lon":3.1931156},{"type":"node","id":903903390,"lat":51.1618641,"lon":3.1930197},{"type":"node","id":903904576,"lat":51.1618211,"lon":3.1931711},{"type":"node","id":1038557012,"lat":51.16155,"lon":3.1931121},{"type":"node","id":1038557014,"lat":51.1613774,"lon":3.1930711},{"type":"node","id":1038557035,"lat":51.1615349,"lon":3.1931712},{"type":"node","id":1038557072,"lat":51.1616138,"lon":3.1927483},{"type":"node","id":1038557075,"lat":51.162286,"lon":3.1935989},{"type":"node","id":1038557078,"lat":51.1616517,"lon":3.1928439},{"type":"node","id":1038557083,"lat":51.1616055,"lon":3.1930249},{"type":"node","id":1038557094,"lat":51.1618993,"lon":3.193299},{"type":"node","id":1038557102,"lat":51.1613235,"lon":3.1927138},{"type":"node","id":1038557104,"lat":51.1615987,"lon":3.1928077},{"type":"node","id":1038557108,"lat":51.1615113,"lon":3.1926816},{"type":"node","id":1038557137,"lat":51.1608873,"lon":3.1924416},{"type":"node","id":1038557143,"lat":51.1622248,"lon":3.193662},{"type":"node","id":1038557191,"lat":51.1608171,"lon":3.1926951},{"type":"node","id":1038557195,"lat":51.162409,"lon":3.1933428},{"type":"node","id":1038557227,"lat":51.1613767,"lon":3.1925113},{"type":"node","id":1038557230,"lat":51.1615281,"lon":3.1926132},{"type":"node","id":1038557233,"lat":51.1619765,"lon":3.1933723},{"type":"node","id":1038575040,"lat":51.1608523,"lon":3.1925679},{"type":"node","id":1038583375,"lat":51.1625113,"lon":3.1926776},{"type":"node","id":1038583398,"lat":51.1624305,"lon":3.1925743},{"type":"node","id":1038583404,"lat":51.1627055,"lon":3.191826},{"type":"node","id":1038583425,"lat":51.1624272,"lon":3.1916637},{"type":"node","id":1038583441,"lat":51.1621479,"lon":3.1921546},{"type":"node","id":1038583446,"lat":51.1622018,"lon":3.1921814},{"type":"node","id":1038583456,"lat":51.162174,"lon":3.1922806},{"type":"node","id":1038583459,"lat":51.162259,"lon":3.1924885},{"type":"node","id":1038583463,"lat":51.162661,"lon":3.1917442},{"type":"node","id":1038583476,"lat":51.1626425,"lon":3.1918448},{"type":"node","id":1038583479,"lat":51.1624196,"lon":3.1926561},{"type":"node","id":1038583483,"lat":51.1625037,"lon":3.1927232},{"type":"node","id":1038583491,"lat":51.1625701,"lon":3.1926387},{"type":"node","id":1038583501,"lat":51.1624928,"lon":3.1917013},{"type":"node","id":1811673418,"lat":51.1618484,"lon":3.1950253},{"type":"node","id":1811673421,"lat":51.1619875,"lon":3.1951427},{"type":"node","id":1811673423,"lat":51.162144,"lon":3.193835},{"type":"node","id":1811673425,"lat":51.1622452,"lon":3.1939149},{"type":"node","id":1811699778,"lat":51.1608187,"lon":3.1922973},{"type":"node","id":1811699779,"lat":51.1608915,"lon":3.1920223},{"type":"node","id":1817320495,"lat":51.1607269,"lon":3.192929},{"type":"node","id":1817320496,"lat":51.1607872,"lon":3.1926841},{"type":"node","id":1817324488,"lat":51.1615575,"lon":3.1921423},{"type":"node","id":1817324489,"lat":51.1612682,"lon":3.1920196},{"type":"node","id":1817324491,"lat":51.1617501,"lon":3.1918468},{"type":"node","id":1817324505,"lat":51.1618272,"lon":3.1921231},{"type":"node","id":1817324509,"lat":51.1618658,"lon":3.191793},{"type":"node","id":1817324513,"lat":51.1619814,"lon":3.1920002},{"type":"node","id":1817324515,"lat":51.161985,"lon":3.191793},{"type":"node","id":3550860268,"lat":51.1617349,"lon":3.1921922},{"type":"node","id":3550860269,"lat":51.1619403,"lon":3.1920686},{"type":"node","id":4044171924,"lat":51.1608199,"lon":3.1916126},{"type":"node","id":4044171954,"lat":51.1610853,"lon":3.191781},{"type":"node","id":4044171957,"lat":51.1611433,"lon":3.1918701},{"type":"node","id":4044171962,"lat":51.1611926,"lon":3.1916807},{"type":"node","id":4044171976,"lat":51.1612826,"lon":3.1919582},{"type":"node","id":4044171997,"lat":51.1613568,"lon":3.1917787},{"type":"node","id":4044172003,"lat":51.1613248,"lon":3.1919027},{"type":"node","id":4044172008,"lat":51.1614345,"lon":3.1919767},{"type":"node","id":6397031888,"lat":51.1615029,"lon":3.1919851},{"type":"node","id":6960473080,"lat":51.1614227,"lon":3.1931004},{"type":"node","id":3335137692,"lat":51.1698302,"lon":3.1965654},{"type":"node","id":3335137795,"lat":51.1698788,"lon":3.1970728},{"type":"node","id":3335137802,"lat":51.1700082,"lon":3.1971734},{"type":"node","id":3335137807,"lat":51.1701139,"lon":3.1965001},{"type":"node","id":3335137812,"lat":51.1703247,"lon":3.197352},{"type":"node","id":3335137823,"lat":51.1703133,"lon":3.1966232},{"type":"node","id":6255587427,"lat":51.1694775,"lon":3.1980047},{"type":"node","id":9163486855,"lat":51.1703854,"lon":3.1970901},{"type":"node","id":9163486856,"lat":51.1702114,"lon":3.1969688},{"type":"node","id":9163493632,"lat":51.1699473,"lon":3.197063},{"type":"node","id":414025563,"lat":51.1768198,"lon":3.1839265},{"type":"node","id":2325437840,"lat":51.1765747,"lon":3.1839745},{"type":"node","id":2325437844,"lat":51.1768286,"lon":3.1825946},{"type":"node","id":8191691970,"lat":51.1767611,"lon":3.1839766},{"type":"node","id":8191691971,"lat":51.1767812,"lon":3.1826167},{"type":"node","id":8191691972,"lat":51.1765804,"lon":3.1826583},{"type":"node","id":8191691973,"lat":51.1766324,"lon":3.182616},{"type":"node","id":5716136617,"lat":51.1773127,"lon":3.1969033},{"type":"node","id":5716136618,"lat":51.1771859,"lon":3.1969078},{"type":"node","id":5716136619,"lat":51.177203,"lon":3.1981369},{"type":"node","id":5716136620,"lat":51.1773298,"lon":3.1981324},{"type":"node","id":6004375826,"lat":51.1786839,"lon":3.1952389},{"type":"node","id":6625037999,"lat":51.1788016,"lon":3.1950645},{"type":"node","id":6625038000,"lat":51.1789916,"lon":3.1966631},{"type":"node","id":6625038001,"lat":51.1789003,"lon":3.1966838},{"type":"node","id":6625038002,"lat":51.1788554,"lon":3.1963547},{"type":"node","id":6625038003,"lat":51.1788165,"lon":3.1963622},{"type":"node","id":6625038005,"lat":51.1785124,"lon":3.1952362},{"type":"node","id":6625038006,"lat":51.1784779,"lon":3.1950618},{"type":"node","id":6925536539,"lat":51.1522475,"lon":3.1985416},{"type":"node","id":6925536540,"lat":51.1522635,"lon":3.1986187},{"type":"node","id":6925536541,"lat":51.1523922,"lon":3.1985517},{"type":"node","id":6925536542,"lat":51.1523766,"lon":3.1984746},{"type":"node","id":1637742821,"lat":51.158524,"lon":3.199021},{"type":"node","id":5586765933,"lat":51.1566667,"lon":3.2008881},{"type":"node","id":5586765934,"lat":51.1564286,"lon":3.2012575},{"type":"node","id":5586765935,"lat":51.1562496,"lon":3.2008579},{"type":"node","id":5586765936,"lat":51.1564982,"lon":3.200522},{"type":"node","id":6943148197,"lat":51.1581916,"lon":3.1989071},{"type":"node","id":6943148198,"lat":51.1582377,"lon":3.1989899},{"type":"node","id":6943148199,"lat":51.1581859,"lon":3.1990728},{"type":"node","id":6943148200,"lat":51.1583257,"lon":3.199295},{"type":"node","id":6943148201,"lat":51.1583563,"lon":3.199246},{"type":"node","id":6943148202,"lat":51.1583988,"lon":3.1993135},{"type":"node","id":6943148203,"lat":51.1585529,"lon":3.1990669},{"type":"node","id":6943148204,"lat":51.1586554,"lon":3.1988109},{"type":"node","id":6943148205,"lat":51.1585617,"lon":3.1986619},{"type":"node","id":6943148206,"lat":51.1586782,"lon":3.1984755},{"type":"node","id":6943148207,"lat":51.1585692,"lon":3.1982996},{"type":"node","id":8065883225,"lat":51.1366029,"lon":3.233506},{"type":"node","id":8065883226,"lat":51.1364627,"lon":3.2335338},{"type":"node","id":8065883227,"lat":51.1363922,"lon":3.2326314},{"type":"node","id":8065883228,"lat":51.1365324,"lon":3.2326036},{"type":"node","id":8065883229,"lat":51.1374344,"lon":3.2333338},{"type":"node","id":8065883230,"lat":51.1373632,"lon":3.2324534},{"type":"node","id":8065883232,"lat":51.1375819,"lon":3.2333035},{"type":"node","id":8065883233,"lat":51.1375107,"lon":3.232423},{"type":"node","id":1795793393,"lat":51.1475704,"lon":3.233832},{"type":"node","id":3346575840,"lat":51.146485,"lon":3.2349284},{"type":"node","id":3346575846,"lat":51.1465127,"lon":3.2355341},{"type":"node","id":3346575853,"lat":51.1466617,"lon":3.2349708},{"type":"node","id":3346575855,"lat":51.1466787,"lon":3.2355171},{"type":"node","id":3346575858,"lat":51.1466968,"lon":3.2342532},{"type":"node","id":3346575865,"lat":51.1468756,"lon":3.2344143},{"type":"node","id":3346575873,"lat":51.1469706,"lon":3.2366779},{"type":"node","id":3346575929,"lat":51.1474307,"lon":3.2366434},{"type":"node","id":1523513488,"lat":51.1398248,"lon":3.2392608},{"type":"node","id":1744641292,"lat":51.1395814,"lon":3.2390365},{"type":"node","id":1744641293,"lat":51.1397822,"lon":3.2393867},{"type":"node","id":1920143232,"lat":51.1394724,"lon":3.2390121},{"type":"node","id":7393009684,"lat":51.1394307,"lon":3.2390001},{"type":"node","id":7393048385,"lat":51.1394135,"lon":3.2390524},{"type":"node","id":3346575843,"lat":51.1465041,"lon":3.2376453},{"type":"node","id":3346575845,"lat":51.146508,"lon":3.2378517},{"type":"node","id":3346575876,"lat":51.1470052,"lon":3.237604},{"type":"node","id":3346575886,"lat":51.147098,"lon":3.2412975},{"type":"node","id":3346575889,"lat":51.1471585,"lon":3.2428761},{"type":"node","id":3346575891,"lat":51.1471715,"lon":3.2377865},{"type":"node","id":3346575901,"lat":51.1472492,"lon":3.2398591},{"type":"node","id":3346575903,"lat":51.1472654,"lon":3.242623},{"type":"node","id":3346575908,"lat":51.1472751,"lon":3.2428571},{"type":"node","id":3346575917,"lat":51.1473518,"lon":3.2426093},{"type":"node","id":3346575923,"lat":51.1473906,"lon":3.2398205},{"type":"node","id":3346575925,"lat":51.147408,"lon":3.2424474},{"type":"node","id":3346575928,"lat":51.1474263,"lon":3.24062},{"type":"node","id":3346575933,"lat":51.1474728,"lon":3.2421565},{"type":"node","id":3346575943,"lat":51.1475354,"lon":3.2418174},{"type":"node","id":3346575945,"lat":51.1475494,"lon":3.2412786},{"type":"node","id":3346575946,"lat":51.1475667,"lon":3.2415454},{"type":"node","id":6291339815,"lat":51.1434669,"lon":3.2496811},{"type":"node","id":6291339816,"lat":51.1434103,"lon":3.2497287},{"type":"node","id":6291339821,"lat":51.1435685,"lon":3.2496576},{"type":"node","id":6291339822,"lat":51.1434825,"lon":3.2497283},{"type":"node","id":6291339827,"lat":51.1437401,"lon":3.2490327},{"type":"node","id":6291339828,"lat":51.1433037,"lon":3.2494123},{"type":"node","id":6291339829,"lat":51.1436099,"lon":3.2497855},{"type":"node","id":6291339830,"lat":51.1439041,"lon":3.249535},{"type":"node","id":170464837,"lat":51.1533286,"lon":3.236239},{"type":"node","id":170464839,"lat":51.1532379,"lon":3.2364578},{"type":"node","id":1710262731,"lat":51.1513274,"lon":3.2373199},{"type":"node","id":1710262732,"lat":51.1508759,"lon":3.2370371},{"type":"node","id":1710262733,"lat":51.1509316,"lon":3.2370599},{"type":"node","id":1710262735,"lat":51.1510166,"lon":3.2370123},{"type":"node","id":1710262738,"lat":51.1512751,"lon":3.2372984},{"type":"node","id":1710262742,"lat":51.1513127,"lon":3.237065},{"type":"node","id":1710262743,"lat":51.1508201,"lon":3.2373832},{"type":"node","id":1710262745,"lat":51.151027,"lon":3.2369479},{"type":"node","id":1795793395,"lat":51.1476158,"lon":3.2338163},{"type":"node","id":1795793397,"lat":51.1475842,"lon":3.2344427},{"type":"node","id":1795793399,"lat":51.1477641,"lon":3.233033},{"type":"node","id":1795793405,"lat":51.1477717,"lon":3.2338665},{"type":"node","id":1795793406,"lat":51.1480775,"lon":3.2344787},{"type":"node","id":1795793407,"lat":51.1478893,"lon":3.2344203},{"type":"node","id":1795793408,"lat":51.1481719,"lon":3.2342485},{"type":"node","id":1795793409,"lat":51.147607,"lon":3.2330256},{"type":"node","id":4979389763,"lat":51.1476223,"lon":3.2330288},{"type":"node","id":8179735224,"lat":51.156047,"lon":3.2252534},{"type":"node","id":8179735264,"lat":51.1560464,"lon":3.2252785},{"type":"node","id":8179735265,"lat":51.1558544,"lon":3.2252597},{"type":"node","id":8179735266,"lat":51.1556789,"lon":3.2252522},{"type":"node","id":8179735267,"lat":51.1555253,"lon":3.2252547},{"type":"node","id":8179735268,"lat":51.1555747,"lon":3.2250024},{"type":"node","id":8179735269,"lat":51.1560527,"lon":3.2250198},{"type":"node","id":1525460846,"lat":51.1550489,"lon":3.2347709},{"type":"node","id":1810326044,"lat":51.1547625,"lon":3.2355098},{"type":"node","id":1810326087,"lat":51.1547809,"lon":3.2353708},{"type":"node","id":4912203160,"lat":51.1554941,"lon":3.2364781},{"type":"node","id":4912203161,"lat":51.1554192,"lon":3.2369649},{"type":"node","id":4912203162,"lat":51.1554175,"lon":3.2371071},{"type":"node","id":4912203163,"lat":51.1554301,"lon":3.2372063},{"type":"node","id":4912203164,"lat":51.1553847,"lon":3.2372197},{"type":"node","id":4912203165,"lat":51.1553763,"lon":3.2369502},{"type":"node","id":4912203166,"lat":51.1554512,"lon":3.236462},{"type":"node","id":4912203167,"lat":51.1555218,"lon":3.2366455},{"type":"node","id":4912203168,"lat":51.1554742,"lon":3.2369592},{"type":"node","id":4912203169,"lat":51.155516,"lon":3.2369752},{"type":"node","id":4912203170,"lat":51.1555635,"lon":3.2366616},{"type":"node","id":4912203171,"lat":51.1556125,"lon":3.2360775},{"type":"node","id":4912203172,"lat":51.155547,"lon":3.2364923},{"type":"node","id":4912203173,"lat":51.1555893,"lon":3.2365092},{"type":"node","id":4912203174,"lat":51.1556547,"lon":3.2360945},{"type":"node","id":4912203176,"lat":51.1554841,"lon":3.2362949},{"type":"node","id":4912203177,"lat":51.1553752,"lon":3.2362591},{"type":"node","id":4912203178,"lat":51.1553968,"lon":3.2360924},{"type":"node","id":4912203179,"lat":51.1555056,"lon":3.2361281},{"type":"node","id":4912214680,"lat":51.1553544,"lon":3.2348128},{"type":"node","id":4912214681,"lat":51.1550186,"lon":3.2346814},{"type":"node","id":4912214685,"lat":51.1554486,"lon":3.2338965},{"type":"node","id":4912214686,"lat":51.1550098,"lon":3.2346405},{"type":"node","id":4912214692,"lat":51.155386,"lon":3.2347722},{"type":"node","id":4912214693,"lat":51.1555155,"lon":3.2338415},{"type":"node","id":4912214694,"lat":51.1554587,"lon":3.2338214},{"type":"node","id":4912214695,"lat":51.1553292,"lon":3.2347521},{"type":"node","id":4912225050,"lat":51.1553136,"lon":3.234866},{"type":"node","id":4912225051,"lat":51.1551036,"lon":3.2337751},{"type":"node","id":4912225052,"lat":51.1549825,"lon":3.2346307},{"type":"node","id":4912225053,"lat":51.1551894,"lon":3.2336789},{"type":"node","id":4912225062,"lat":51.1551528,"lon":3.233747},{"type":"node","id":4912225063,"lat":51.1551831,"lon":3.2337249},{"type":"node","id":4912225064,"lat":51.1554653,"lon":3.2337755},{"type":"node","id":4912225067,"lat":51.1551309,"lon":3.2337849},{"type":"node","id":4912225068,"lat":51.1551727,"lon":3.2337999},{"type":"node","id":4912225069,"lat":51.1553182,"lon":3.2348322},{"type":"node","id":4912225070,"lat":51.1550516,"lon":3.2346556},{"type":"node","id":5972179331,"lat":51.154488,"lon":3.2350802},{"type":"node","id":5972179343,"lat":51.1545781,"lon":3.2351138},{"type":"node","id":5972179344,"lat":51.1546444,"lon":3.2351409},{"type":"node","id":5972179345,"lat":51.1546431,"lon":3.2351485},{"type":"node","id":5972179346,"lat":51.1547126,"lon":3.2351739},{"type":"node","id":5972179347,"lat":51.154714,"lon":3.2351659},{"type":"node","id":5972179348,"lat":51.1547795,"lon":3.235188},{"type":"node","id":5974489614,"lat":51.1546386,"lon":3.2355125},{"type":"node","id":5974489615,"lat":51.1544914,"lon":3.2353516},{"type":"node","id":5974489616,"lat":51.1544813,"lon":3.2351384},{"type":"node","id":5974489617,"lat":51.1548024,"lon":3.2352003},{"type":"node","id":5974489618,"lat":51.154732,"lon":3.2356091},{"type":"node","id":7529417225,"lat":51.159095,"lon":3.2366844},{"type":"node","id":7529417226,"lat":51.1589926,"lon":3.2372825},{"type":"node","id":7529417227,"lat":51.1588687,"lon":3.2372286},{"type":"node","id":7529417228,"lat":51.1589264,"lon":3.2368918},{"type":"node","id":7529417229,"lat":51.1588879,"lon":3.236875},{"type":"node","id":7529417230,"lat":51.1589326,"lon":3.2366138},{"type":"node","id":7529417232,"lat":51.159019,"lon":3.2366513},{"type":"node","id":170464840,"lat":51.1531619,"lon":3.2376814},{"type":"node","id":170464841,"lat":51.1532306,"lon":3.2376888},{"type":"node","id":1710245701,"lat":51.1528676,"lon":3.2390068},{"type":"node","id":1710245703,"lat":51.1527703,"lon":3.239403},{"type":"node","id":1710245705,"lat":51.1527888,"lon":3.2390966},{"type":"node","id":1710245707,"lat":51.1526357,"lon":3.2390543},{"type":"node","id":1710245709,"lat":51.1528763,"lon":3.2390382},{"type":"node","id":1710245711,"lat":51.1528928,"lon":3.2390631},{"type":"node","id":1710245713,"lat":51.1528729,"lon":3.2389738},{"type":"node","id":1710245715,"lat":51.1528645,"lon":3.2394083},{"type":"node","id":1710245718,"lat":51.1526407,"lon":3.2389524},{"type":"node","id":1710262736,"lat":51.1512857,"lon":3.2375783},{"type":"node","id":1710262737,"lat":51.151234,"lon":3.2375571},{"type":"node","id":1710262739,"lat":51.151183,"lon":3.2375939},{"type":"node","id":1710262741,"lat":51.1511924,"lon":3.2375358},{"type":"node","id":1710262744,"lat":51.1512252,"lon":3.2376112},{"type":"node","id":3346575950,"lat":51.1475926,"lon":3.2406028},{"type":"node","id":1728421374,"lat":51.1554436,"lon":3.2438233},{"type":"node","id":1728421375,"lat":51.15594,"lon":3.2438649},{"type":"node","id":1728421377,"lat":51.15559,"lon":3.2439695},{"type":"node","id":1728421379,"lat":51.1554335,"lon":3.243944},{"type":"node","id":1770289505,"lat":51.1565437,"lon":3.2437924},{"type":"node","id":4912197362,"lat":51.1565535,"lon":3.2438327},{"type":"node","id":4912197363,"lat":51.1562818,"lon":3.2438374},{"type":"node","id":4912197364,"lat":51.1565321,"lon":3.2435757},{"type":"node","id":4912197365,"lat":51.1565279,"lon":3.2433181},{"type":"node","id":4912197366,"lat":51.1562804,"lon":3.2435833},{"type":"node","id":4912197367,"lat":51.1562798,"lon":3.2431702},{"type":"node","id":4912197368,"lat":51.1562813,"lon":3.2437497},{"type":"node","id":4912197369,"lat":51.1562802,"lon":3.243488},{"type":"node","id":4912197370,"lat":51.1565257,"lon":3.2431702},{"type":"node","id":4912197371,"lat":51.1565542,"lon":3.2439044},{"type":"node","id":4912197372,"lat":51.1565308,"lon":3.2437482},{"type":"node","id":4912197373,"lat":51.1565294,"lon":3.2434893},{"type":"node","id":4912197374,"lat":51.1562835,"lon":3.2439005},{"type":"node","id":1710276232,"lat":51.1572435,"lon":3.2451269},{"type":"node","id":1710276240,"lat":51.156984,"lon":3.2453481},{"type":"node","id":1710276242,"lat":51.1567167,"lon":3.2452913},{"type":"node","id":1710276243,"lat":51.1570484,"lon":3.2451},{"type":"node","id":1710276251,"lat":51.1562241,"lon":3.2457572},{"type":"node","id":1710276253,"lat":51.156868,"lon":3.2451689},{"type":"node","id":1710276255,"lat":51.1563873,"lon":3.2456553},{"type":"node","id":1710276257,"lat":51.1572402,"lon":3.2450303},{"type":"node","id":1710276259,"lat":51.1561703,"lon":3.2454299},{"type":"node","id":1710276261,"lat":51.1564411,"lon":3.2457304},{"type":"node","id":1728421376,"lat":51.1555858,"lon":3.2441572},{"type":"node","id":1728421378,"lat":51.1559348,"lon":3.2441264},{"type":"node","id":1810330766,"lat":51.1562599,"lon":3.2457349},{"type":"node","id":1810345944,"lat":51.1572859,"lon":3.2458614},{"type":"node","id":1810345947,"lat":51.1568366,"lon":3.2461909},{"type":"node","id":1810345951,"lat":51.1572074,"lon":3.2455895},{"type":"node","id":1810345955,"lat":51.1567582,"lon":3.245919},{"type":"node","id":1810347217,"lat":51.1568783,"lon":3.2452387},{"type":"node","id":6255587424,"lat":51.1699788,"lon":3.1988617},{"type":"node","id":6255587425,"lat":51.1695322,"lon":3.1995447},{"type":"node","id":6255587426,"lat":51.1690026,"lon":3.1986489},{"type":"node","id":5173881316,"lat":51.1728811,"lon":3.210692},{"type":"node","id":5173881317,"lat":51.1728829,"lon":3.21077},{"type":"node","id":5173881318,"lat":51.1726197,"lon":3.2107914},{"type":"node","id":5173881320,"lat":51.1728794,"lon":3.2108575},{"type":"node","id":5173881621,"lat":51.1728791,"lon":3.2109364},{"type":"node","id":5173881622,"lat":51.1727133,"lon":3.2109488},{"type":"node","id":5173881623,"lat":51.1727117,"lon":3.2108703},{"type":"node","id":5173881624,"lat":51.1728613,"lon":3.211069},{"type":"node","id":5173881625,"lat":51.1728601,"lon":3.2111406},{"type":"node","id":5173881626,"lat":51.1727019,"lon":3.2111316},{"type":"node","id":5173881627,"lat":51.1727041,"lon":3.2110597},{"type":"node","id":6275462772,"lat":51.1733576,"lon":3.2110928},{"type":"node","id":6275462773,"lat":51.1733528,"lon":3.2112295},{"type":"node","id":6275462774,"lat":51.1735278,"lon":3.2112449},{"type":"node","id":6275462775,"lat":51.1735325,"lon":3.2111082},{"type":"node","id":6275462776,"lat":51.1736659,"lon":3.2112568},{"type":"node","id":6275462777,"lat":51.1736113,"lon":3.2112529},{"type":"node","id":6275462784,"lat":51.1735598,"lon":3.2109277},{"type":"node","id":6275462985,"lat":51.1734626,"lon":3.2109229},{"type":"node","id":6275462986,"lat":51.1734599,"lon":3.2110592},{"type":"node","id":6275462987,"lat":51.1735572,"lon":3.211064},{"type":"node","id":6275462988,"lat":51.1734613,"lon":3.2109904},{"type":"node","id":6275462989,"lat":51.173357,"lon":3.2111476},{"type":"node","id":7054196467,"lat":51.1726209,"lon":3.2107131},{"type":"node","id":8042845810,"lat":51.1737696,"lon":3.206708},{"type":"node","id":8042845811,"lat":51.1734466,"lon":3.2056148},{"type":"node","id":5952389321,"lat":51.1668901,"lon":3.2166736},{"type":"node","id":5952389322,"lat":51.1664592,"lon":3.2166337},{"type":"node","id":5952389323,"lat":51.1659941,"lon":3.2166018},{"type":"node","id":5172938444,"lat":51.1667283,"lon":3.2192609},{"type":"node","id":5536609426,"lat":51.1664884,"lon":3.2184803},{"type":"node","id":5536620510,"lat":51.1668363,"lon":3.2197448},{"type":"node","id":5536620511,"lat":51.1671911,"lon":3.2210959},{"type":"node","id":5952389320,"lat":51.1665059,"lon":3.2183884},{"type":"node","id":5536620506,"lat":51.1675299,"lon":3.2170283},{"type":"node","id":5536620507,"lat":51.1672585,"lon":3.2168071},{"type":"node","id":6275462778,"lat":51.1736042,"lon":3.2115044},{"type":"node","id":6275462779,"lat":51.1736588,"lon":3.2115083},{"type":"node","id":6275462780,"lat":51.1735687,"lon":3.2112964},{"type":"node","id":6275462781,"lat":51.1735211,"lon":3.2112937},{"type":"node","id":6275462782,"lat":51.1735156,"lon":3.2115423},{"type":"node","id":6275462783,"lat":51.1735632,"lon":3.211545},{"type":"node","id":5536620505,"lat":51.1683944,"lon":3.2180288},{"type":"node","id":5536620512,"lat":51.1673641,"lon":3.2217199},{"type":"node","id":5536620513,"lat":51.1675007,"lon":3.2221772},{"type":"node","id":5536620514,"lat":51.1679104,"lon":3.2236675},{"type":"node","id":5536620516,"lat":51.1679955,"lon":3.224005},{"type":"node","id":5536620824,"lat":51.1700823,"lon":3.2236258},{"type":"node","id":5536620826,"lat":51.171324,"lon":3.2230929},{"type":"node","id":5536620827,"lat":51.1717731,"lon":3.2213846},{"type":"node","id":5536620828,"lat":51.170726,"lon":3.2202369},{"type":"node","id":5536620829,"lat":51.1706206,"lon":3.2201178},{"type":"node","id":5536620830,"lat":51.170049,"lon":3.2215441},{"type":"node","id":5536620831,"lat":51.1699442,"lon":3.2215294},{"type":"node","id":5536620832,"lat":51.1683757,"lon":3.2194636},{"type":"node","id":6067483781,"lat":51.1675243,"lon":3.222207},{"type":"node","id":6067483782,"lat":51.1713888,"lon":3.2231705},{"type":"node","id":7794736251,"lat":51.1688401,"lon":3.2184325},{"type":"node","id":1069177852,"lat":51.1789546,"lon":3.2021791},{"type":"node","id":1069177853,"lat":51.1801636,"lon":3.2031369},{"type":"node","id":1069177873,"lat":51.1791663,"lon":3.2034541},{"type":"node","id":1069177915,"lat":51.1799187,"lon":3.2029579},{"type":"node","id":1069177919,"lat":51.1786053,"lon":3.2030903},{"type":"node","id":1069177920,"lat":51.1790417,"lon":3.2033998},{"type":"node","id":1069177925,"lat":51.1788415,"lon":3.2032442},{"type":"node","id":1069177933,"lat":51.1798479,"lon":3.2029364},{"type":"node","id":1069177967,"lat":51.178467,"lon":3.2025563},{"type":"node","id":1069177976,"lat":51.1791427,"lon":3.2026954},{"type":"node","id":1069177984,"lat":51.1783718,"lon":3.2028231},{"type":"node","id":1069178021,"lat":51.1793534,"lon":3.2033094},{"type":"node","id":1069178133,"lat":51.1784113,"lon":3.2028156},{"type":"node","id":6853179202,"lat":51.1792037,"lon":3.2026994},{"type":"node","id":6853179203,"lat":51.1790601,"lon":3.2026755},{"type":"node","id":6853179204,"lat":51.1791861,"lon":3.2027108},{"type":"node","id":6853179205,"lat":51.1791741,"lon":3.2027122},{"type":"node","id":6853179206,"lat":51.1791634,"lon":3.2027102},{"type":"node","id":6853179207,"lat":51.1791526,"lon":3.2027048},{"type":"node","id":6853179208,"lat":51.1790128,"lon":3.202488},{"type":"node","id":6853179209,"lat":51.1790434,"lon":3.2026225},{"type":"node","id":6853179210,"lat":51.1789811,"lon":3.2023837},{"type":"node","id":6853179211,"lat":51.1789744,"lon":3.2022415},{"type":"node","id":6853179212,"lat":51.1789438,"lon":3.2022643},{"type":"node","id":6853179213,"lat":51.1784216,"lon":3.2028567},{"type":"node","id":6853179214,"lat":51.1784157,"lon":3.2028375},{"type":"node","id":6853179215,"lat":51.1784506,"lon":3.2029294},{"type":"node","id":6853179216,"lat":51.1783884,"lon":3.2026704},{"type":"node","id":6853179217,"lat":51.178422,"lon":3.2026034},{"type":"node","id":6853179218,"lat":51.1784117,"lon":3.2026185},{"type":"node","id":6853179219,"lat":51.1784021,"lon":3.2026354},{"type":"node","id":6853179220,"lat":51.1783957,"lon":3.2026505},{"type":"node","id":6853179221,"lat":51.178443,"lon":3.2025785},{"type":"node","id":6853179222,"lat":51.1784546,"lon":3.202567},{"type":"node","id":6853179223,"lat":51.1784321,"lon":3.2025906},{"type":"node","id":6853179224,"lat":51.1783719,"lon":3.2027464},{"type":"node","id":6853179225,"lat":51.1783749,"lon":3.2027238},{"type":"node","id":6853179226,"lat":51.1783827,"lon":3.2026894},{"type":"node","id":6853179227,"lat":51.1783784,"lon":3.2027066},{"type":"node","id":6853179228,"lat":51.1783697,"lon":3.2027864},{"type":"node","id":6853179229,"lat":51.1783704,"lon":3.2027651},{"type":"node","id":6853179230,"lat":51.1783703,"lon":3.2028048},{"type":"node","id":6853179234,"lat":51.1798837,"lon":3.2029379},{"type":"node","id":6853179235,"lat":51.1798988,"lon":3.2029445},{"type":"node","id":6853179236,"lat":51.1798661,"lon":3.2029354},{"type":"node","id":6853179237,"lat":51.1798345,"lon":3.2029407},{"type":"node","id":6853179238,"lat":51.1798207,"lon":3.2029479},{"type":"node","id":6853179239,"lat":51.1792634,"lon":3.2033377},{"type":"node","id":6853179240,"lat":51.1793019,"lon":3.2033359},{"type":"node","id":6853179241,"lat":51.1792828,"lon":3.20334},{"type":"node","id":6853179242,"lat":51.1792732,"lon":3.2033393},{"type":"node","id":6853179243,"lat":51.1792921,"lon":3.2033388},{"type":"node","id":6853179244,"lat":51.1793279,"lon":3.2033257},{"type":"node","id":6853179245,"lat":51.1793153,"lon":3.2033313},{"type":"node","id":6853179246,"lat":51.1793413,"lon":3.2033182},{"type":"node","id":6853179247,"lat":51.1792384,"lon":3.2033981},{"type":"node","id":6853179248,"lat":51.1792572,"lon":3.2033605},{"type":"node","id":6853179249,"lat":51.1792512,"lon":3.2033774},{"type":"node","id":6853179250,"lat":51.1792456,"lon":3.2033888},{"type":"node","id":6853179256,"lat":51.1790996,"lon":3.2034514},{"type":"node","id":6853179257,"lat":51.1790731,"lon":3.2034317},{"type":"node","id":6853179258,"lat":51.1790581,"lon":3.2034168},{"type":"node","id":6853179259,"lat":51.1790862,"lon":3.2034422},{"type":"node","id":6853179260,"lat":51.179133,"lon":3.2034648},{"type":"node","id":6853179261,"lat":51.1791191,"lon":3.203461},{"type":"node","id":6853179262,"lat":51.1791546,"lon":3.2034608},{"type":"node","id":6853179263,"lat":51.1791443,"lon":3.2034639},{"type":"node","id":6853179264,"lat":51.1789437,"lon":3.2033089},{"type":"node","id":6853179267,"lat":51.1785146,"lon":3.2030128},{"type":"node","id":6853179268,"lat":51.1785517,"lon":3.2030489},{"type":"node","id":6853179269,"lat":51.1785863,"lon":3.2030773},{"type":"node","id":6853179327,"lat":51.1789936,"lon":3.2024248},{"type":"node","id":7252820961,"lat":51.175521,"lon":3.2045972},{"type":"node","id":7252863798,"lat":51.1754304,"lon":3.2044959},{"type":"node","id":8042845806,"lat":51.1753353,"lon":3.2041851},{"type":"node","id":8042845807,"lat":51.175363,"lon":3.2043314},{"type":"node","id":8042845812,"lat":51.1752711,"lon":3.2040127},{"type":"node","id":4036885076,"lat":51.1740632,"lon":3.2050437},{"type":"node","id":4036899624,"lat":51.1767493,"lon":3.2082945},{"type":"node","id":5607796819,"lat":51.1782483,"lon":3.2091883},{"type":"node","id":5607796820,"lat":51.1785128,"lon":3.2086016},{"type":"node","id":5607798721,"lat":51.1786474,"lon":3.2090453},{"type":"node","id":5607798722,"lat":51.1782874,"lon":3.2093115},{"type":"node","id":5607798723,"lat":51.178141,"lon":3.2088491},{"type":"node","id":5607798725,"lat":51.1785713,"lon":3.2087945},{"type":"node","id":5728443539,"lat":51.1753294,"lon":3.2097039},{"type":"node","id":5728443540,"lat":51.1752216,"lon":3.2089278},{"type":"node","id":6275462768,"lat":51.174424,"lon":3.2105467},{"type":"node","id":6275462769,"lat":51.1743524,"lon":3.2105548},{"type":"node","id":6275462770,"lat":51.1743644,"lon":3.2108257},{"type":"node","id":6275462771,"lat":51.1744361,"lon":3.2108176},{"type":"node","id":7252820962,"lat":51.1756015,"lon":3.204854},{"type":"node","id":7252820963,"lat":51.1755802,"lon":3.204928},{"type":"node","id":7252820964,"lat":51.1755132,"lon":3.2049422},{"type":"node","id":7252820965,"lat":51.1754719,"lon":3.2050156},{"type":"node","id":7252820966,"lat":51.1754575,"lon":3.2051212},{"type":"node","id":7252820967,"lat":51.1755143,"lon":3.2052892},{"type":"node","id":7252820968,"lat":51.1755533,"lon":3.2055086},{"type":"node","id":7252820969,"lat":51.1755563,"lon":3.2060065},{"type":"node","id":7252820970,"lat":51.175491,"lon":3.2064409},{"type":"node","id":7252820971,"lat":51.1753674,"lon":3.2068348},{"type":"node","id":7252820972,"lat":51.1751944,"lon":3.2070531},{"type":"node","id":7252820973,"lat":51.1751195,"lon":3.2071478},{"type":"node","id":7252820974,"lat":51.1750834,"lon":3.2072467},{"type":"node","id":7252820975,"lat":51.1750963,"lon":3.2073579},{"type":"node","id":7252820976,"lat":51.1751376,"lon":3.2074032},{"type":"node","id":7252820977,"lat":51.175215,"lon":3.2073826},{"type":"node","id":7252820978,"lat":51.1752848,"lon":3.2073785},{"type":"node","id":7252820979,"lat":51.1754252,"lon":3.2073858},{"type":"node","id":7252820980,"lat":51.1754615,"lon":3.2074926},{"type":"node","id":7252820981,"lat":51.1754259,"lon":3.20756},{"type":"node","id":7252820982,"lat":51.17537,"lon":3.2076668},{"type":"node","id":7252820983,"lat":51.1753304,"lon":3.2078901},{"type":"node","id":7252820984,"lat":51.1753152,"lon":3.2079319},{"type":"node","id":7252874885,"lat":51.1754423,"lon":3.2080951},{"type":"node","id":7252874886,"lat":51.1754991,"lon":3.2083134},{"type":"node","id":7252874887,"lat":51.1755307,"lon":3.2084864},{"type":"node","id":7252874888,"lat":51.1755729,"lon":3.2087064},{"type":"node","id":7252874889,"lat":51.1753248,"lon":3.2088635},{"type":"node","id":7252874890,"lat":51.1752645,"lon":3.2092365},{"type":"node","id":7252874891,"lat":51.1747746,"lon":3.2093558},{"type":"node","id":8042845789,"lat":51.1748587,"lon":3.209526},{"type":"node","id":8042845790,"lat":51.1749489,"lon":3.2096774},{"type":"node","id":8042845791,"lat":51.1750595,"lon":3.2097458},{"type":"node","id":8042845792,"lat":51.1753557,"lon":3.2077924},{"type":"node","id":8042845793,"lat":51.1754621,"lon":3.2074425},{"type":"node","id":8042845794,"lat":51.1754531,"lon":3.2074092},{"type":"node","id":8042845795,"lat":51.1754729,"lon":3.2051839},{"type":"node","id":8042845796,"lat":51.1754907,"lon":3.2052089},{"type":"node","id":8042845797,"lat":51.1755084,"lon":3.2052355},{"type":"node","id":8042845798,"lat":51.1755235,"lon":3.2053482},{"type":"node","id":8042845799,"lat":51.1755387,"lon":3.2053805},{"type":"node","id":8042845800,"lat":51.1755584,"lon":3.2057251},{"type":"node","id":8042845801,"lat":51.1755536,"lon":3.205762},{"type":"node","id":8042845802,"lat":51.1755492,"lon":3.2061312},{"type":"node","id":8042845803,"lat":51.1755305,"lon":3.2062755},{"type":"node","id":8042845804,"lat":51.1754335,"lon":3.2066603},{"type":"node","id":8042845805,"lat":51.1755929,"lon":3.2047843},{"type":"node","id":8042845808,"lat":51.1746278,"lon":3.2090183},{"type":"node","id":8042845809,"lat":51.1740796,"lon":3.2076268},{"type":"node","id":8042845844,"lat":51.1768218,"lon":3.20861},{"type":"node","id":8042845845,"lat":51.1767935,"lon":3.2085031},{"type":"node","id":8042845846,"lat":51.1769413,"lon":3.2089936},{"type":"node","id":8042845847,"lat":51.1757541,"lon":3.2096988},{"type":"node","id":8042845848,"lat":51.1757421,"lon":3.2096812},{"type":"node","id":8042845849,"lat":51.1757312,"lon":3.2096924},{"type":"node","id":8042845850,"lat":51.1757202,"lon":3.2096478},{"type":"node","id":8042845851,"lat":51.1756902,"lon":3.2096207},{"type":"node","id":8042845852,"lat":51.1756712,"lon":3.2096143},{"type":"node","id":8042845853,"lat":51.1756602,"lon":3.2095745},{"type":"node","id":8042845854,"lat":51.1756552,"lon":3.2095537},{"type":"node","id":8042845855,"lat":51.1756657,"lon":3.2095174},{"type":"node","id":8042845856,"lat":51.175658,"lon":3.20908},{"type":"node","id":8042845857,"lat":51.1756525,"lon":3.2093366},{"type":"node","id":8042845858,"lat":51.1756466,"lon":3.2088282},{"type":"node","id":8042845859,"lat":51.1756582,"lon":3.2089151},{"type":"node","id":8042845860,"lat":51.1765521,"lon":3.20839},{"type":"node","id":1069177845,"lat":51.1809357,"lon":3.2035366},{"type":"node","id":1069177849,"lat":51.1803975,"lon":3.2017749},{"type":"node","id":1069178166,"lat":51.1804195,"lon":3.2033098},{"type":"node","id":1519342742,"lat":51.1805239,"lon":3.2032684},{"type":"node","id":1519342743,"lat":51.18064,"lon":3.2036951},{"type":"node","id":1759437085,"lat":51.1806986,"lon":3.2036647},{"type":"node","id":6852012577,"lat":51.1804541,"lon":3.2017867},{"type":"node","id":6852012578,"lat":51.1804124,"lon":3.2018177},{"type":"node","id":6852012579,"lat":51.1804106,"lon":3.2018165},{"type":"node","id":6852012580,"lat":51.1804143,"lon":3.2018177},{"type":"node","id":6852012581,"lat":51.1808363,"lon":3.2030295},{"type":"node","id":6852012582,"lat":51.1807955,"lon":3.2030595},{"type":"node","id":6852012583,"lat":51.180798,"lon":3.2030712},{"type":"node","id":1519476620,"lat":51.1786696,"lon":3.2199463},{"type":"node","id":1519476635,"lat":51.179306,"lon":3.2193119},{"type":"node","id":1519476698,"lat":51.1795485,"lon":3.2192221},{"type":"node","id":1519476744,"lat":51.1791125,"lon":3.2194529},{"type":"node","id":1519476746,"lat":51.178483,"lon":3.2203218},{"type":"node","id":1519476797,"lat":51.1788731,"lon":3.2196593},{"type":"node","id":3780611492,"lat":51.1761568,"lon":3.2238485},{"type":"node","id":3780611493,"lat":51.1762213,"lon":3.223901},{"type":"node","id":3780611494,"lat":51.1762626,"lon":3.2237172},{"type":"node","id":3780611495,"lat":51.1763208,"lon":3.2237628},{"type":"node","id":3780611496,"lat":51.1763248,"lon":3.2236414},{"type":"node","id":3780611497,"lat":51.1763881,"lon":3.2236926},{"type":"node","id":3780611498,"lat":51.1764876,"lon":3.2235544},{"type":"node","id":3780611499,"lat":51.1766551,"lon":3.2232337},{"type":"node","id":3780611500,"lat":51.176687,"lon":3.2231945},{"type":"node","id":3780611501,"lat":51.1767105,"lon":3.2232776},{"type":"node","id":3780611502,"lat":51.176751,"lon":3.2232465},{"type":"node","id":3780611503,"lat":51.1767812,"lon":3.2230729},{"type":"node","id":3780611504,"lat":51.1768505,"lon":3.2231083},{"type":"node","id":6533893620,"lat":51.178521,"lon":3.2203687},{"type":"node","id":6533893621,"lat":51.1786845,"lon":3.220025},{"type":"node","id":6533893622,"lat":51.1789011,"lon":3.2197183},{"type":"node","id":6533893624,"lat":51.1791343,"lon":3.2195235},{"type":"node","id":6533893625,"lat":51.1793269,"lon":3.2193854},{"type":"node","id":6533893626,"lat":51.1795596,"lon":3.219299},{"type":"node","id":5536620518,"lat":51.1683264,"lon":3.224863},{"type":"node","id":5536620519,"lat":51.1684352,"lon":3.2251117},{"type":"node","id":5536620520,"lat":51.1685675,"lon":3.2254022},{"type":"node","id":5536620821,"lat":51.1687379,"lon":3.2258223},{"type":"node","id":5536620822,"lat":51.1693682,"lon":3.2250177},{"type":"node","id":5536620823,"lat":51.1693734,"lon":3.225049},{"type":"node","id":5536620825,"lat":51.1707605,"lon":3.2244639},{"type":"node","id":5536620837,"lat":51.1697793,"lon":3.2260181},{"type":"node","id":5536620838,"lat":51.1699712,"lon":3.2262338},{"type":"node","id":5536620839,"lat":51.1701247,"lon":3.2263242},{"type":"node","id":5536620840,"lat":51.1704719,"lon":3.2266478},{"type":"node","id":5536620841,"lat":51.1701028,"lon":3.2281081},{"type":"node","id":5536620842,"lat":51.1698158,"lon":3.2276446},{"type":"node","id":5536620843,"lat":51.1696441,"lon":3.2273837},{"type":"node","id":5536620844,"lat":51.1695154,"lon":3.2272009},{"type":"node","id":5536620845,"lat":51.169536,"lon":3.2271664},{"type":"node","id":5536620846,"lat":51.1694515,"lon":3.2270181},{"type":"node","id":5635001306,"lat":51.1737078,"lon":3.2354437},{"type":"node","id":5635001371,"lat":51.1722128,"lon":3.2340273},{"type":"node","id":5635001372,"lat":51.1723921,"lon":3.2343394},{"type":"node","id":5635001373,"lat":51.1724213,"lon":3.2342967},{"type":"node","id":5635001374,"lat":51.1722421,"lon":3.2339846},{"type":"node","id":5635001375,"lat":51.1728995,"lon":3.2339319},{"type":"node","id":5635001376,"lat":51.1729253,"lon":3.2339922},{"type":"node","id":5635001377,"lat":51.1723583,"lon":3.2340816},{"type":"node","id":5635001378,"lat":51.1723268,"lon":3.2340173},{"type":"node","id":5635001379,"lat":51.172885,"lon":3.2337993},{"type":"node","id":5635001380,"lat":51.1728611,"lon":3.2338706},{"type":"node","id":5635001381,"lat":51.1723325,"lon":3.2339419},{"type":"node","id":5635001382,"lat":51.1723464,"lon":3.2338696},{"type":"node","id":5882873334,"lat":51.1736186,"lon":3.2330966},{"type":"node","id":5882873335,"lat":51.1735451,"lon":3.2327633},{"type":"node","id":5882873336,"lat":51.1737001,"lon":3.2327438},{"type":"node","id":5882873337,"lat":51.1736796,"lon":3.2318764},{"type":"node","id":5882873338,"lat":51.1735265,"lon":3.2318782},{"type":"node","id":6593340582,"lat":51.1727872,"lon":3.2328745},{"type":"node","id":6593340583,"lat":51.1728013,"lon":3.2332051},{"type":"node","id":6593340584,"lat":51.1736743,"lon":3.2331435},{"type":"node","id":7767137235,"lat":51.1735198,"lon":3.2355568},{"type":"node","id":7767137236,"lat":51.1735366,"lon":3.2355246},{"type":"node","id":7767137237,"lat":51.1735198,"lon":3.2356399},{"type":"node","id":5635001274,"lat":51.1751425,"lon":3.2346144},{"type":"node","id":5635001275,"lat":51.1751696,"lon":3.2347601},{"type":"node","id":5635001276,"lat":51.1750553,"lon":3.2348141},{"type":"node","id":5635001277,"lat":51.1750282,"lon":3.2346684},{"type":"node","id":5635001312,"lat":51.174002,"lon":3.2349367},{"type":"node","id":5635001383,"lat":51.1740709,"lon":3.233056},{"type":"node","id":5635001384,"lat":51.1740249,"lon":3.2330598},{"type":"node","id":5635001385,"lat":51.1740265,"lon":3.2331313},{"type":"node","id":5635001386,"lat":51.1740597,"lon":3.2327202},{"type":"node","id":5635001414,"lat":51.174281,"lon":3.2336147},{"type":"node","id":5635001415,"lat":51.174081,"lon":3.2338914},{"type":"node","id":5635001416,"lat":51.1740489,"lon":3.2338323},{"type":"node","id":5635001417,"lat":51.1742489,"lon":3.2335556},{"type":"node","id":5761770202,"lat":51.1783111,"lon":3.2342484},{"type":"node","id":5761770204,"lat":51.1782819,"lon":3.2339616},{"type":"node","id":7767137234,"lat":51.1739713,"lon":3.2348766},{"type":"node","id":9052878228,"lat":51.1781206,"lon":3.234323},{"type":"node","id":9052878229,"lat":51.1781054,"lon":3.2339448},{"type":"way","id":810604915,"nodes":[1168727824,9167054153,9274761589,9274761596,7577430793,1038638712,1038638723,1038638661,9199177059,1038638721,7554434436,7578975035,7554434438,7578865273,7578975032,7578975030,7578975029,1038638696,7578975009,7578975008,7578975007,1038638743,7578975002,7578974988,7578974989,7578974990,7578974991,7578974992,7578865275,7578865274,1038638753,7578974995,7578974996,7578974997,7578904489,7578974999,7578975000,7578975001,7578974998,3921878998,1038638592,929120698,1675648152,7578865281,7578865283,7578975012,7578975015,7578975016,3922380061,2732486274,3922380083,7578975019,7578975018,7578975021,7578960079,3922375256,7578975024,3922380071]},{"type":"way","id":989393316,"nodes":[3922380071,3922380081,3922380086,3922380092,3922380095,9167054157,7578975026,9274761593,9274761592,9274761591,7578975027,9167054156,9167054154,7578975049,7578975028,1168727824]},{"type":"way","id":389026405,"nodes":[3921879019,7578975044,3921879018,7578975046,7578975045,7578975040,3921879004,3921879011,3921879019]},{"type":"way","id":810607458,"nodes":[7578987409,7578987410,7578987411,5745833241,5745833240,5745833239,7578987412,7578987415,7578987413,7578987414,7578987417,7578987416,7578987418,7578987419,7578987409]},{"type":"way","id":777280458,"nodes":[8042845812,8042845806,8042845807,7252863798,7252820961,8042845805,7252820962,7252820963,7252820964,7252820965,7252820966,8042845795,8042845796,8042845797,7252820967,8042845798,8042845799,7252820968,8042845800,8042845801,7252820969,8042845802,8042845803,7252820970,8042845804,7252820971,7252820972,7252820973,7252820974,7252820975,7252820976,7252820977,7252820978,7252820979,8042845794,8042845793,7252820980,7252820981,7252820982,8042845792,7252820983,7252820984,7252874885,7252874886,7252874887,7252874888,7252874889,5728443540,7252874890,5728443539,8042845791,8042845790,8042845789,7252874891,8042845808,8042845809,8042845810,8042845811,4036885076,8042845812]},{"type":"way","id":577572397,"nodes":[5536620518,5536620519,5536620520,5536620821,5536620822,5536620823,5536620824,5536620825,5536620826,6067483782,5536620827,5536620828,5536620829,5536620830,5536620831,5536620832,7794736251,5536620505,5536620506,5536620507,5952389321,5952389322,5952389323,5536609426,5952389320,5172938444,5536620510,5536620511,5536620512,5536620513,6067483781,5536620514,5536620516,5536620518]},{"type":"way","id":863373849,"nodes":[4036899624,8042845845,8042845844,8042845846,8042845847,8042845848,8042845849,8042845850,8042845851,8042845852,8042845853,8042845854,8042845855,8042845857,8042845856,8042845859,8042845858,8042845860,4036899624]},{"type":"way","id":577572399,"nodes":[5536620837,5536620838,5536620839,5536620840,5536620841,5536620842,5536620843,5536620844,5536620845,5536620846,5536620837]}]}; + + Utils.injectJsonDownloadForTests( + "https://overpass-api.de/api/interpreter?data=%5Bout%3Ajson%5D%5Btimeout%3A60%5D%5Bbbox%3A51.124212757826875%2C3.1640625%2C51.17934297928927%2C3.251953125%5D%3B"+query , d + ) + + Utils.injectJsonDownloadForTests( + "https://overpass-api.de/api/interpreter?data=%5Bout%3Ajson%5D%5Btimeout%3A60%5D%5Bbbox%3A51.124212757826875%2C3.251953125%2C51.17934297928927%2C3.33984375%5D%3B"+query , + {"version":0.6,"generator":"Overpass API 0.7.57 93a4d346","osm3s":{"timestamp_osm_base":"2022-02-14T00:02:14Z","copyright":"The data included in this document is from www.openstreetmap.org. The data is made available under ODbL."},"elements":[{"type":"node","id":668981602,"lat":51.1588243,"lon":3.2558654,"tags":{"amenity":"bench"}},{"type":"node","id":668981622,"lat":51.1565636,"lon":3.2549888,"tags":{"leisure":"bird_hide","operator":"Natuurpunt Vallei van de Zuidleie","shelter":"no"}},{"type":"node","id":1580339675,"lat":51.1395949,"lon":3.3332507,"tags":{"amenity":"parking"}},{"type":"node","id":1764571836,"lat":51.1701118,"lon":3.3363371,"tags":{"amenity":"parking"}},{"type":"node","id":2121652779,"lat":51.1268536,"lon":3.3239607,"tags":{"amenity":"parking"}},{"type":"node","id":2386053906,"lat":51.162161,"lon":3.263065,"tags":{"amenity":"toilets"}},{"type":"node","id":2978180520,"lat":51.1329149,"lon":3.3362322,"tags":{"amenity":"bench"}},{"type":"node","id":2978183271,"lat":51.1324243,"lon":3.3373735,"tags":{"amenity":"bench"}},{"type":"node","id":2978184471,"lat":51.1436385,"lon":3.2916539,"tags":{"amenity":"bench","backrest":"yes","check_date":"2021-02-26"}},{"type":"node","id":3925976407,"lat":51.1787486,"lon":3.2831866,"tags":{"leisure":"picnic_table"}},{"type":"node","id":5158056232,"lat":51.1592067,"lon":3.2567111,"tags":{"leisure":"bird_hide","operator":"Natuurpunt Vallei van de Zuidleie","shelter":"no"}},{"type":"node","id":5718776382,"lat":51.1609023,"lon":3.2582509,"tags":{"check_date":"2021-02-26","covered":"no","leisure":"picnic_table"}},{"type":"node","id":5718776383,"lat":51.1609488,"lon":3.2581877,"tags":{"check_date":"2021-02-26","covered":"no","leisure":"picnic_table"}},{"type":"node","id":5745727100,"lat":51.1594639,"lon":3.2604304,"tags":{"amenity":"bench"}},{"type":"node","id":5745739587,"lat":51.1580397,"lon":3.263101,"tags":{"check_date":"2021-02-26","leisure":"picnic_table"}},{"type":"node","id":5745739588,"lat":51.1580631,"lon":3.2630345,"tags":{"check_date":"2021-02-26","leisure":"picnic_table"}},{"type":"node","id":5961596093,"lat":51.1588103,"lon":3.2633933,"tags":{"leisure":"picnic_table"}},{"type":"node","id":5964032193,"lat":51.1514821,"lon":3.2723766,"tags":{"leisure":"picnic_table"}},{"type":"node","id":6034563379,"lat":51.1421689,"lon":3.3022271,"tags":{"leisure":"picnic_table"}},{"type":"node","id":6034564191,"lat":51.1722186,"lon":3.2823584,"tags":{"leisure":"picnic_table"}},{"type":"node","id":6034565298,"lat":51.1722796,"lon":3.282329,"tags":{"leisure":"picnic_table"}},{"type":"node","id":6145151111,"lat":51.1690435,"lon":3.3388676,"tags":{"amenity":"bench"}},{"type":"node","id":6145151112,"lat":51.1690023,"lon":3.3388636,"tags":{"amenity":"bench"}},{"type":"node","id":6216549651,"lat":51.1292813,"lon":3.332369,"tags":{"amenity":"bench"}},{"type":"node","id":6216549652,"lat":51.1292768,"lon":3.3324259,"tags":{"amenity":"bench"}},{"type":"node","id":7204447030,"lat":51.1791769,"lon":3.283116,"tags":{"board_type":"nature","information":"board","mapillary":"0BHVgU1XCyTMM9cjvidUqk","name":"De Assebroekse Meersen","tourism":"information"}},{"type":"node","id":7468175778,"lat":51.1344104,"lon":3.3348246,"tags":{"leisure":"picnic_table"}},{"type":"node","id":7602473480,"lat":51.1503874,"lon":3.2836867,"tags":{"leisure":"picnic_table"}},{"type":"node","id":7602473482,"lat":51.150244,"lon":3.2842925,"tags":{"board_type":"wildlife","information":"board","name":"Waterbeestjes","operator":"Natuurpunt Vallei van de Zuidleie","tourism":"information"}},{"type":"node","id":7602699080,"lat":51.1367031,"lon":3.3320712,"tags":{"amenity":"bench","backrest":"yes","material":"metal"}},{"type":"node","id":7680940369,"lat":51.1380074,"lon":3.3369928,"tags":{"amenity":"bench"}},{"type":"node","id":7726850522,"lat":51.1418585,"lon":3.3064234,"tags":{"image:0":"https://i.imgur.com/Bh6UjYy.jpg","information":"board","tourism":"information"}},{"type":"node","id":7727071212,"lat":51.1501173,"lon":3.2845352,"tags":{"board_type":"wildlife","image:0":"https://i.imgur.com/mFEQJWd.jpg","information":"board","name":"Vleermuizen","operator":"Natuurpunt Vallei van de Zuidleie","tourism":"information"}},{"type":"node","id":9122376662,"lat":51.1720505,"lon":3.3308524,"tags":{"amenity":"bench"}},{"type":"node","id":9425818876,"lat":51.1325315,"lon":3.3371616,"tags":{"leisure":"picnic_table","mapillary":"101961548889238"}},{"type":"way","id":149408639,"nodes":[1623924235,1623924236,1623924238,1864750831,1623924241,1623924235],"tags":{"amenity":"parking"}},{"type":"way","id":149553206,"nodes":[1625199938,1625199951,8377691836,8378081366,8378081429,8378081386,1625199950,6414383775,1625199827,1625199938],"tags":{"amenity":"parking"}},{"type":"way","id":184402308,"nodes":[1948836195,1948836194,1948836193,1948836189,1948836192,1948836195],"tags":{"building":"yes","leisure":"bird_hide","operator":"Natuurpunt Vallei van de Zuidleie","shelter":"yes","wheelchair":"yes"}},{"type":"way","id":184402309,"nodes":[1948836029,1948836038,1948836032,1948836025,1948836023,1948836029],"tags":{"building":"yes","leisure":"bird_hide","operator":"Natuurpunt Vallei van de Zuidleie","shelter":"yes","source:geometry:date":"2011-11-07","source:geometry:ref":"Gbg/3489204"}},{"type":"way","id":184402331,"nodes":[1948836104,1948836072,1948836068,1948836093,1948836104],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":236979353,"nodes":[2449323191,7962681624,7962681623,7962681621,7962681622,2449323193,7962681620,7962681619,8360787098,4350143592,6794421028,6794421027,6794421041,7962681614,2123461969,2449323198,7962681615,7962681616,6794421042,2449323191],"tags":{"amenity":"parking"}},{"type":"way","id":251590503,"nodes":[2577910543,2577910530,2577910542,2577910520,6418533335,2577910526,2577910545,2577910543],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":313090489,"nodes":[3190107423,3190107435,3190107442,3190107439,3190107432,3190107428,3190107424,3190107400,3190107393,3190107377,3190107371,3190107374,3190107408,3190107407,3190107415,3190107416,3190107420,3190107423],"tags":{"amenity":"parking"}},{"type":"way","id":314531418,"nodes":[7468171455,7468171451,7727393212,7727393211,7727393210,7727393208,7727393209,8781449489,7727393207,7727393206,7727393205,7727393204,7727393203,7727393202,7727393201,7727393200,7390697550,7390697534,7727393199,7727393198,7727393197,7390697549,7727393196,7727393195,7727393194,7727393193,7727393192,7727393191,7727393190,7727393189,7727393188,7727393187,7727393186,7727393185,7727339384,7727339383,7727339382,1553169911,1553169836,1493821433,1493821422,3185248088,7727339364,7727339365,7727339366,7727339367,7727339368,7727339369,7727339370,7727339371,7727339372,7727339373,7727339374,7727339375,7727339376,7727339377,3185248049,3185248048,3185248042,3185248040,7727339378,7727339379,7727339380,7727339381,7468171438,7468171442,7468171430,7468171432,7468171446,7468171404,7468171405,7468171422,7468171426,7468171433,7468171423,7468171428,7468171431,7468171429,7468171406,7468171407,7468171444,7468171408,7468171409,7468171410,7468171411,7468171412,7468171413,7190927792,7190927791,7190927793,7190927787,7190927788,7190927789,7190927790,7190927786,7602692242,7190927785,7190873584,7468171450,7190873582,7190873576,7190873578,7190873577,7468171455],"tags":{"access":"yes","dog":"leashed","dogs":"leashed","image":"https://i.imgur.com/cOfwWTj.jpg","image:0":"https://i.imgur.com/RliQdyi.jpg","image:1":"https://i.imgur.com/IeKHahz.jpg","image:2":"https://i.imgur.com/1K0IORH.jpg","image:3":"https://i.imgur.com/jojP09s.jpg","image:4":"https://i.imgur.com/DK6kT51.jpg","image:5":"https://i.imgur.com/RizbGM1.jpg","image:6":"https://i.imgur.com/hyoY6Cl.jpg","image:7":"https://i.imgur.com/xDd7Wrq.jpg","leisure":"nature_reserve","name":"Miseriebocht","operator":"Natuurpunt Beernem","website":"https://www.natuurpunt.be/natuurgebied/miseriebocht","wikidata":"Q97060915"}},{"type":"way","id":366318480,"nodes":[3702926557,3702926558,3702926559,3702926560,3702926557],"tags":{"amenity":"parking"}},{"type":"way","id":366318481,"nodes":[3702878648,3702926561,3702926562,3702926563,3702926564,3702926565,3702926566,3702926567,3702878648],"tags":{"amenity":"parking"}},{"type":"way","id":366318482,"nodes":[3702926568,8292789053,8292789054,3702878654,3702926568],"tags":{"amenity":"parking"}},{"type":"way","id":366320440,"nodes":[3702956173,3702956174,3702956175,3702956176,3702956173],"tags":{"amenity":"parking","name":"Kleine Beer"}},{"type":"way","id":366321706,"nodes":[3702969714,3702969715,3702969716,3702969717,3702969714],"tags":{"amenity":"parking"}},{"type":"way","id":480267681,"nodes":[4732689641,4732689640,4732689639,4732689638,4732689637,4732689636,4732689635,4732689634,4732689633,4732689632,4732689631,4732689630,4732689629,4732689628,4732689627,4732689626,8294875888,4732689641],"tags":{"amenity":"parking"}},{"type":"way","id":554341620,"nodes":[5349884603,5349884602,5349884601,5349884600,5349884603],"tags":{"amenity":"parking"}},{"type":"way","id":554341621,"nodes":[5349884607,5349884606,5349884605,5349884604,5349884607],"tags":{"amenity":"parking"}},{"type":"way","id":561902092,"nodes":[5417516023,5417515520,5417516021,5417516022,5417516023],"tags":{"building":"yes","image":"https://i.imgur.com/WmViSbL.jpg","leisure":"bird_hide","operator":"Natuurpunt Vallei van de Zuidleie","shelter":"yes","wheelchair":"no"}},{"type":"way","id":605915064,"nodes":[5745739924,5745739925,5745739926,5745739927,5745739924],"tags":{"amenity":"parking","surface":"fine2"}},{"type":"way","id":650285088,"nodes":[3645188881,6100803131,6100803130,6100803129,6100803124,6100803125,6100803128,6100803127,6100803126,3645188881],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":655944574,"nodes":[6145151107,6145151108,6145151109,6145151115,6145151114,6145151110,6145151107],"tags":{"amenity":"parking"}},{"type":"way","id":664171069,"nodes":[6216549610,6216549611,6216549612,6216549613,1413470849,1413470848,6216549605,6216549604,6216549610],"tags":{"amenity":"parking"}},{"type":"way","id":664171076,"nodes":[6216549656,6216549655,8307316294,6216549661,6216549657,6216549658,6216549659,6216549660,6216549656],"tags":{"amenity":"parking","capacity":"50"}},{"type":"way","id":665330334,"nodes":[6227395993,6227395991,6227395992,6227395997,6227395993],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface","surface":"asphalt"}},{"type":"way","id":684598363,"nodes":[3227068565,6416001161,6414352054,6414352055,7274233390,7274233391,7274233397,7274233395,7274233396,6414352053,3227068568,3227068565],"tags":{"amenity":"parking","fee":"no"}},{"type":"way","id":684599810,"nodes":[1317838331,8279842668,1384096112,1317838328,6414374315,3227068446,6414374316,6414374317,6414374318,3227068456,6414374319,6414374320,6414374321,1317838317,1317838331],"tags":{"access":"no","amenity":"parking","operator":"Politie"}},{"type":"way","id":761474468,"nodes":[7114502201,7114502203,7114502200,7114502202,3170562439,3170562437,3170562431,7114502240,7114502211,7114502212,7114502214,7114502215,7114502228,7114502234,7114502235,7114502236,7114502237,7114502238,7114502239,7114502233,7114502232,7114502231,7114502229,7114502230,7114502227,7114502226,7114502225,7114502216,7114502217,7114502224,3170562392,7114502218,3170562394,7114502219,7114502220,7114502221,7114502222,7114502223,3170562395,3170562396,3170562397,3170562402,3170562410,7114502209,7114502208,7114502207,7114502205,7114502206,3170562436,1475188519,1475188516,6627605025,8294886142,7114502201],"tags":{"image":"http://valleivandezuidleie.be/wp-content/uploads/2011/12/2011-03-24_G12_088_1_1.JPG","leisure":"nature_reserve","name":"Merlebeek-Meerberg","natural":"wetland","operator":"Natuurpunt Vallei van de Zuidleie","start_date":"2011","website":"http://valleivandezuidleie.be/info-over-de-vallei-van-de-zuidleie/merlebeek/","wetland":"wet_meadow"}},{"type":"way","id":813859435,"nodes":[7602479690,7459257985,7602479691,7459154784,7459154782,7602479692,5482441357,7602479693,7602479694,7602479695,7602479696,7602479690],"tags":{"access":"yes","image:0":"https://i.imgur.com/nb9nawa.jpg","landuse":"grass","leisure":"nature_reserve","name:signed":"no","natural":"grass","operator":"Natuurpunt Vallei van de Zuidleie"}},{"type":"way","id":826103452,"nodes":[7713176912,7713176911,7713176910,7713176909,7713176912],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":893176022,"nodes":[1927235214,8301349336,8301349335,8301349337,1927235214],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":895943476,"nodes":[8328251887,8328251886,8328251885,8328251884,8328251887],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":895943477,"nodes":[8328251891,8328251890,8328251889,8328251888,8328251891],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":895943478,"nodes":[8328251895,8328251894,8328251893,8328251892,8328251895],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":895943479,"nodes":[8328251897,8328251896,8328251901,8328251900,8328251897],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":895943480,"nodes":[8328251898,8328251899,8328251903,8328251902,8328251898],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":895943481,"nodes":[8328251907,8328251906,8328251905,8328251904,8328251907],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":895943482,"nodes":[8328251911,8328251910,8328251909,8328251908,8328251911],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":901952767,"nodes":[8378097127,8378097126,8378097125,8378097124,8378097127],"tags":{"amenity":"parking","parking":"street_side"}},{"type":"way","id":901952768,"nodes":[8378097134,8378097133,8378097132,8378097131,8378097130,8378097129,8378097128,8378097134],"tags":{"amenity":"parking","parking":"street_side"}},{"type":"way","id":947325182,"nodes":[8497007549,8768981525,8768981522,8768981524,8768981521,8768981523,8768981520,8768981519,6206789709,8768981533,8497007549],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":966827815,"nodes":[8945026757,8945026756,8945026755,8945026754,8945026757],"tags":{"access":"customers","amenity":"parking","parking":"surface"}},{"type":"relation","id":2589413,"members":[{"type":"way","ref":663050030,"role":"outer"},{"type":"way","ref":184402334,"role":"outer"},{"type":"way","ref":184402332,"role":"outer"},{"type":"way","ref":184402325,"role":"outer"},{"type":"way","ref":184402326,"role":"outer"},{"type":"way","ref":314899865,"role":"outer"},{"type":"way","ref":314956402,"role":"outer"}],"tags":{"access":"yes","image":"https://i.imgur.com/Yu4qHh5.jpg","leisure":"nature_reserve","name":"Warandeputten","operator":"Natuurpunt Vallei van de Zuidleie","type":"multipolygon","wikipedia":"nl:Warandeputten"}},{"type":"relation","id":8782624,"members":[{"type":"way","ref":315041273,"role":"outer"},{"type":"way","ref":631377343,"role":"outer"},{"type":"way","ref":631371237,"role":"outer"},{"type":"way","ref":631371236,"role":"outer"},{"type":"way","ref":631371234,"role":"outer"},{"type":"way","ref":631377344,"role":"outer"},{"type":"way","ref":631371232,"role":"outer"},{"type":"way","ref":631371231,"role":"outer"},{"type":"way","ref":315041263,"role":"outer"},{"type":"way","ref":631371228,"role":"outer"},{"type":"way","ref":631377341,"role":"outer"},{"type":"way","ref":315041261,"role":"outer"},{"type":"way","ref":631371223,"role":"outer"}],"tags":{"access":"yes","image:0":"https://i.imgur.com/VuzX5jW.jpg","image:1":"https://i.imgur.com/tPppmJG.jpg","image:2":"https://i.imgur.com/ecY3RER.jpg","image:3":"https://i.imgur.com/lr4FK6j.jpg","image:5":"https://i.imgur.com/uufEeE6.jpg","leisure":"nature_reserve","name":"Leiemeersen Noord","operator":"Natuurpunt Vallei van de Zuidleie","type":"multipolygon","website":"http://valleivandezuidleie.be/info-over-de-vallei-van-de-zuidleie/leiemeersen-noord/"}},{"type":"relation","id":8890076,"members":[{"type":"way","ref":640979982,"role":"outer"},{"type":"way","ref":640979978,"role":"outer"}],"tags":{"access":"yes","image:0":"https://i.imgur.com/SAAaKBH.jpg","image:1":"https://i.imgur.com/DGK9iBN.jpg","image:2":"https://i.imgur.com/bte1KJx.jpg","image:3":"https://i.imgur.com/f75Gxnx.jpg","leisure":"nature_reserve","name":"Gevaerts Noord","operator":"Natuurpunt Vallei van de Zuidleie","type":"multipolygon"}},{"type":"relation","id":9118029,"members":[{"type":"way","ref":606165130,"role":"outer"},{"type":"way","ref":655652319,"role":"outer"},{"type":"way","ref":655652321,"role":"outer"}],"tags":{"access":"no","image:0":"https://i.imgur.com/eBufo0v.jpg","image:1":"https://i.imgur.com/kBej2Nk.jpg","image:2":"https://i.imgur.com/QKoyIRl.jpg","leisure":"nature_reserve","name":"De Leiemeersen","note":"Door de hoge kwetsbaarheid van het gebied zijn De Leiemeersen enkel te bezoeken onder begeleiding van een gids","note:mapping":"NIET VOOR BEGINNENDE MAPPERS! Dit gebied is met relaties als multipolygonen gemapt (zo'n 50 stuks). Als je niet weet hoe dit werkt, vraag hulp.","note_1":"wetland=marsh is het veenmoerasgebied","operator":"Natuurpunt Vallei van de Zuidleie","type":"multipolygon","website":"http://valleivandezuidleie.be/info-over-de-vallei-van-de-zuidleie/leiemeersen/"}},{"type":"node","id":668981602,"lat":51.1588243,"lon":3.2558654,"timestamp":"2012-07-06T17:58:39Z","version":2,"changeset":12133044,"user":"martino260","uid":655442,"tags":{"amenity":"bench"}},{"type":"node","id":668981622,"lat":51.1565636,"lon":3.2549888,"timestamp":"2020-03-23T23:54:26Z","version":4,"changeset":82544029,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"leisure":"bird_hide","operator":"Natuurpunt Vallei van de Zuidleie","shelter":"no"}},{"type":"node","id":1580339675,"lat":51.1395949,"lon":3.3332507,"timestamp":"2012-01-07T00:44:42Z","version":1,"changeset":10317754,"user":"popaultje","uid":519184,"tags":{"amenity":"parking"}},{"type":"node","id":1764571836,"lat":51.1701118,"lon":3.3363371,"timestamp":"2012-05-24T21:06:50Z","version":1,"changeset":11693640,"user":"popaultje","uid":519184,"tags":{"amenity":"parking"}},{"type":"node","id":2121652779,"lat":51.1268536,"lon":3.3239607,"timestamp":"2013-01-20T20:12:50Z","version":1,"changeset":14725799,"user":"tomvdb","uid":437764,"tags":{"amenity":"parking"}},{"type":"node","id":2386053906,"lat":51.162161,"lon":3.263065,"timestamp":"2018-01-19T21:31:30Z","version":2,"changeset":55589374,"user":"L'imaginaire","uid":654234,"tags":{"amenity":"toilets"}},{"type":"node","id":2978180520,"lat":51.1329149,"lon":3.3362322,"timestamp":"2014-07-24T21:29:38Z","version":1,"changeset":24338416,"user":"pieterjanheyse","uid":254767,"tags":{"amenity":"bench"}},{"type":"node","id":2978183271,"lat":51.1324243,"lon":3.3373735,"timestamp":"2019-09-14T05:02:25Z","version":2,"changeset":74462201,"user":"JanFi","uid":672253,"tags":{"amenity":"bench"}},{"type":"node","id":2978184471,"lat":51.1436385,"lon":3.2916539,"timestamp":"2021-02-26T10:22:54Z","version":3,"changeset":100041319,"user":"s8evq","uid":3710738,"tags":{"amenity":"bench","backrest":"yes","check_date":"2021-02-26"}},{"type":"node","id":3925976407,"lat":51.1787486,"lon":3.2831866,"timestamp":"2019-08-12T19:48:31Z","version":2,"changeset":73281516,"user":"s8evq","uid":3710738,"tags":{"leisure":"picnic_table"}},{"type":"node","id":5158056232,"lat":51.1592067,"lon":3.2567111,"timestamp":"2021-04-17T16:21:52Z","version":5,"changeset":103110072,"user":"L'imaginaire","uid":654234,"tags":{"leisure":"bird_hide","operator":"Natuurpunt Vallei van de Zuidleie","shelter":"no"}},{"type":"node","id":5718776382,"lat":51.1609023,"lon":3.2582509,"timestamp":"2021-10-18T10:27:50Z","version":3,"changeset":112646117,"user":"s8evq","uid":3710738,"tags":{"check_date":"2021-02-26","covered":"no","leisure":"picnic_table"}},{"type":"node","id":5718776383,"lat":51.1609488,"lon":3.2581877,"timestamp":"2021-10-18T10:27:50Z","version":3,"changeset":112646117,"user":"s8evq","uid":3710738,"tags":{"check_date":"2021-02-26","covered":"no","leisure":"picnic_table"}},{"type":"node","id":5745727100,"lat":51.1594639,"lon":3.2604304,"timestamp":"2018-07-07T18:00:29Z","version":1,"changeset":60494261,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"amenity":"bench"}},{"type":"node","id":5745739587,"lat":51.1580397,"lon":3.263101,"timestamp":"2021-02-26T10:07:56Z","version":2,"changeset":100039706,"user":"s8evq","uid":3710738,"tags":{"check_date":"2021-02-26","leisure":"picnic_table"}},{"type":"node","id":5745739588,"lat":51.1580631,"lon":3.2630345,"timestamp":"2021-02-26T10:07:41Z","version":2,"changeset":100039706,"user":"s8evq","uid":3710738,"tags":{"check_date":"2021-02-26","leisure":"picnic_table"}},{"type":"node","id":5961596093,"lat":51.1588103,"lon":3.2633933,"timestamp":"2018-10-06T14:41:12Z","version":1,"changeset":63258667,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"leisure":"picnic_table"}},{"type":"node","id":5964032193,"lat":51.1514821,"lon":3.2723766,"timestamp":"2018-10-07T12:15:53Z","version":1,"changeset":63277533,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"leisure":"picnic_table"}},{"type":"node","id":6034563379,"lat":51.1421689,"lon":3.3022271,"timestamp":"2020-02-11T20:10:26Z","version":2,"changeset":80868434,"user":"s8evq","uid":3710738,"tags":{"leisure":"picnic_table"}},{"type":"node","id":6034564191,"lat":51.1722186,"lon":3.2823584,"timestamp":"2018-11-04T20:27:50Z","version":2,"changeset":64177431,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"leisure":"picnic_table"}},{"type":"node","id":6034565298,"lat":51.1722796,"lon":3.282329,"timestamp":"2018-11-04T20:27:50Z","version":2,"changeset":64177431,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"leisure":"picnic_table"}},{"type":"node","id":6145151111,"lat":51.1690435,"lon":3.3388676,"timestamp":"2018-12-18T13:13:36Z","version":1,"changeset":65580728,"user":"Siel Nollet","uid":3292414,"tags":{"amenity":"bench"}},{"type":"node","id":6145151112,"lat":51.1690023,"lon":3.3388636,"timestamp":"2018-12-18T13:13:36Z","version":1,"changeset":65580728,"user":"Siel Nollet","uid":3292414,"tags":{"amenity":"bench"}},{"type":"node","id":6216549651,"lat":51.1292813,"lon":3.332369,"timestamp":"2019-01-17T16:29:02Z","version":1,"changeset":66400781,"user":"Nilsnn","uid":4652000,"tags":{"amenity":"bench"}},{"type":"node","id":6216549652,"lat":51.1292768,"lon":3.3324259,"timestamp":"2019-01-17T16:29:03Z","version":1,"changeset":66400781,"user":"Nilsnn","uid":4652000,"tags":{"amenity":"bench"}},{"type":"node","id":7204447030,"lat":51.1791769,"lon":3.283116,"timestamp":"2021-01-01T12:18:32Z","version":3,"changeset":96768203,"user":"L'imaginaire","uid":654234,"tags":{"board_type":"nature","information":"board","mapillary":"0BHVgU1XCyTMM9cjvidUqk","name":"De Assebroekse Meersen","tourism":"information"}},{"type":"node","id":7468175778,"lat":51.1344104,"lon":3.3348246,"timestamp":"2020-04-30T19:07:49Z","version":1,"changeset":84433940,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"leisure":"picnic_table"}},{"type":"node","id":7602473480,"lat":51.1503874,"lon":3.2836867,"timestamp":"2020-06-08T10:39:07Z","version":1,"changeset":86349440,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"leisure":"picnic_table"}},{"type":"node","id":7602473482,"lat":51.150244,"lon":3.2842925,"timestamp":"2021-02-26T10:18:19Z","version":4,"changeset":100040859,"user":"s8evq","uid":3710738,"tags":{"board_type":"wildlife","information":"board","name":"Waterbeestjes","operator":"Natuurpunt Vallei van de Zuidleie","tourism":"information"}},{"type":"node","id":7602699080,"lat":51.1367031,"lon":3.3320712,"timestamp":"2020-06-08T12:08:11Z","version":1,"changeset":86353903,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"amenity":"bench","backrest":"yes","material":"metal"}},{"type":"node","id":7680940369,"lat":51.1380074,"lon":3.3369928,"timestamp":"2020-07-03T17:54:31Z","version":1,"changeset":87513827,"user":"L'imaginaire","uid":654234,"tags":{"amenity":"bench"}},{"type":"node","id":7726850522,"lat":51.1418585,"lon":3.3064234,"timestamp":"2020-07-18T15:57:43Z","version":1,"changeset":88179934,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"image:0":"https://i.imgur.com/Bh6UjYy.jpg","information":"board","tourism":"information"}},{"type":"node","id":7727071212,"lat":51.1501173,"lon":3.2845352,"timestamp":"2021-02-26T10:17:39Z","version":2,"changeset":100040859,"user":"s8evq","uid":3710738,"tags":{"board_type":"wildlife","image:0":"https://i.imgur.com/mFEQJWd.jpg","information":"board","name":"Vleermuizen","operator":"Natuurpunt Vallei van de Zuidleie","tourism":"information"}},{"type":"node","id":9122376662,"lat":51.1720505,"lon":3.3308524,"timestamp":"2021-09-25T13:32:42Z","version":1,"changeset":111688164,"user":"TeamP8","uid":718373,"tags":{"amenity":"bench"}},{"type":"node","id":9425818876,"lat":51.1325315,"lon":3.3371616,"timestamp":"2022-01-28T20:13:29Z","version":3,"changeset":116721474,"user":"L'imaginaire","uid":654234,"tags":{"leisure":"picnic_table","mapillary":"101961548889238"}},{"type":"way","id":149408639,"timestamp":"2012-08-15T19:09:59Z","version":4,"changeset":12742790,"user":"tomvdb","uid":437764,"nodes":[1623924235,1623924236,1623924238,1864750831,1623924241,1623924235],"tags":{"amenity":"parking"}},{"type":"way","id":149553206,"timestamp":"2021-01-30T12:11:53Z","version":4,"changeset":98411765,"user":"L'imaginaire","uid":654234,"nodes":[1625199938,1625199951,8377691836,8378081366,8378081429,8378081386,1625199950,6414383775,1625199827,1625199938],"tags":{"amenity":"parking"}},{"type":"way","id":184402308,"timestamp":"2020-03-23T23:54:26Z","version":6,"changeset":82544029,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[1948836195,1948836194,1948836193,1948836189,1948836192,1948836195],"tags":{"building":"yes","leisure":"bird_hide","operator":"Natuurpunt Vallei van de Zuidleie","shelter":"yes","wheelchair":"yes"}},{"type":"way","id":184402309,"timestamp":"2021-12-20T11:33:54Z","version":8,"changeset":115161990,"user":"s8evq","uid":3710738,"nodes":[1948836029,1948836038,1948836032,1948836025,1948836023,1948836029],"tags":{"building":"yes","leisure":"bird_hide","operator":"Natuurpunt Vallei van de Zuidleie","shelter":"yes","source:geometry:date":"2011-11-07","source:geometry:ref":"Gbg/3489204"}},{"type":"way","id":184402331,"timestamp":"2021-02-26T10:03:17Z","version":4,"changeset":100039746,"user":"s8evq","uid":3710738,"nodes":[1948836104,1948836072,1948836068,1948836093,1948836104],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":236979353,"timestamp":"2021-01-25T12:38:22Z","version":4,"changeset":98122705,"user":"JosV","uid":170722,"nodes":[2449323191,7962681624,7962681623,7962681621,7962681622,2449323193,7962681620,7962681619,8360787098,4350143592,6794421028,6794421027,6794421041,7962681614,2123461969,2449323198,7962681615,7962681616,6794421042,2449323191],"tags":{"amenity":"parking"}},{"type":"way","id":251590503,"timestamp":"2019-04-20T22:04:54Z","version":2,"changeset":69412561,"user":"L'imaginaire","uid":654234,"nodes":[2577910543,2577910530,2577910542,2577910520,6418533335,2577910526,2577910545,2577910543],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":313090489,"timestamp":"2014-11-16T14:59:12Z","version":1,"changeset":26823403,"user":"JanFi","uid":672253,"nodes":[3190107423,3190107435,3190107442,3190107439,3190107432,3190107428,3190107424,3190107400,3190107393,3190107377,3190107371,3190107374,3190107408,3190107407,3190107415,3190107416,3190107420,3190107423],"tags":{"amenity":"parking"}},{"type":"way","id":314531418,"timestamp":"2021-05-30T17:02:49Z","version":21,"changeset":105576255,"user":"s8evq","uid":3710738,"nodes":[7468171455,7468171451,7727393212,7727393211,7727393210,7727393208,7727393209,8781449489,7727393207,7727393206,7727393205,7727393204,7727393203,7727393202,7727393201,7727393200,7390697550,7390697534,7727393199,7727393198,7727393197,7390697549,7727393196,7727393195,7727393194,7727393193,7727393192,7727393191,7727393190,7727393189,7727393188,7727393187,7727393186,7727393185,7727339384,7727339383,7727339382,1553169911,1553169836,1493821433,1493821422,3185248088,7727339364,7727339365,7727339366,7727339367,7727339368,7727339369,7727339370,7727339371,7727339372,7727339373,7727339374,7727339375,7727339376,7727339377,3185248049,3185248048,3185248042,3185248040,7727339378,7727339379,7727339380,7727339381,7468171438,7468171442,7468171430,7468171432,7468171446,7468171404,7468171405,7468171422,7468171426,7468171433,7468171423,7468171428,7468171431,7468171429,7468171406,7468171407,7468171444,7468171408,7468171409,7468171410,7468171411,7468171412,7468171413,7190927792,7190927791,7190927793,7190927787,7190927788,7190927789,7190927790,7190927786,7602692242,7190927785,7190873584,7468171450,7190873582,7190873576,7190873578,7190873577,7468171455],"tags":{"access":"yes","dog":"leashed","dogs":"leashed","image":"https://i.imgur.com/cOfwWTj.jpg","image:0":"https://i.imgur.com/RliQdyi.jpg","image:1":"https://i.imgur.com/IeKHahz.jpg","image:2":"https://i.imgur.com/1K0IORH.jpg","image:3":"https://i.imgur.com/jojP09s.jpg","image:4":"https://i.imgur.com/DK6kT51.jpg","image:5":"https://i.imgur.com/RizbGM1.jpg","image:6":"https://i.imgur.com/hyoY6Cl.jpg","image:7":"https://i.imgur.com/xDd7Wrq.jpg","leisure":"nature_reserve","name":"Miseriebocht","operator":"Natuurpunt Beernem","website":"https://www.natuurpunt.be/natuurgebied/miseriebocht","wikidata":"Q97060915"}},{"type":"way","id":366318480,"timestamp":"2015-08-18T13:50:59Z","version":1,"changeset":33415758,"user":"xras3r","uid":323672,"nodes":[3702926557,3702926558,3702926559,3702926560,3702926557],"tags":{"amenity":"parking"}},{"type":"way","id":366318481,"timestamp":"2015-08-18T13:50:59Z","version":1,"changeset":33415758,"user":"xras3r","uid":323672,"nodes":[3702878648,3702926561,3702926562,3702926563,3702926564,3702926565,3702926566,3702926567,3702878648],"tags":{"amenity":"parking"}},{"type":"way","id":366318482,"timestamp":"2021-01-05T09:04:32Z","version":2,"changeset":96964072,"user":"JosV","uid":170722,"nodes":[3702926568,8292789053,8292789054,3702878654,3702926568],"tags":{"amenity":"parking"}},{"type":"way","id":366320440,"timestamp":"2015-08-18T14:02:00Z","version":1,"changeset":33415981,"user":"xras3r","uid":323672,"nodes":[3702956173,3702956174,3702956175,3702956176,3702956173],"tags":{"amenity":"parking","name":"Kleine Beer"}},{"type":"way","id":366321706,"timestamp":"2015-08-18T14:15:30Z","version":1,"changeset":33416303,"user":"xras3r","uid":323672,"nodes":[3702969714,3702969715,3702969716,3702969717,3702969714],"tags":{"amenity":"parking"}},{"type":"way","id":480267681,"timestamp":"2021-01-05T21:32:23Z","version":2,"changeset":97006454,"user":"JosV","uid":170722,"nodes":[4732689641,4732689640,4732689639,4732689638,4732689637,4732689636,4732689635,4732689634,4732689633,4732689632,4732689631,4732689630,4732689629,4732689628,4732689627,4732689626,8294875888,4732689641],"tags":{"amenity":"parking"}},{"type":"way","id":554341620,"timestamp":"2018-01-19T21:31:30Z","version":1,"changeset":55589374,"user":"L'imaginaire","uid":654234,"nodes":[5349884603,5349884602,5349884601,5349884600,5349884603],"tags":{"amenity":"parking"}},{"type":"way","id":554341621,"timestamp":"2018-01-19T21:31:30Z","version":1,"changeset":55589374,"user":"L'imaginaire","uid":654234,"nodes":[5349884607,5349884606,5349884605,5349884604,5349884607],"tags":{"amenity":"parking"}},{"type":"way","id":561902092,"timestamp":"2021-01-17T14:52:46Z","version":6,"changeset":97640804,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[5417516023,5417515520,5417516021,5417516022,5417516023],"tags":{"building":"yes","image":"https://i.imgur.com/WmViSbL.jpg","leisure":"bird_hide","operator":"Natuurpunt Vallei van de Zuidleie","shelter":"yes","wheelchair":"no"}},{"type":"way","id":605915064,"timestamp":"2018-07-07T18:07:31Z","version":1,"changeset":60494380,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[5745739924,5745739925,5745739926,5745739927,5745739924],"tags":{"amenity":"parking","surface":"fine2"}},{"type":"way","id":650285088,"timestamp":"2021-01-29T09:37:56Z","version":2,"changeset":98352073,"user":"JosV","uid":170722,"nodes":[3645188881,6100803131,6100803130,6100803129,6100803124,6100803125,6100803128,6100803127,6100803126,3645188881],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":655944574,"timestamp":"2020-02-23T22:05:54Z","version":2,"changeset":81377451,"user":"L'imaginaire","uid":654234,"nodes":[6145151107,6145151108,6145151109,6145151115,6145151114,6145151110,6145151107],"tags":{"amenity":"parking"}},{"type":"way","id":664171069,"timestamp":"2019-01-17T16:29:08Z","version":1,"changeset":66400781,"user":"Nilsnn","uid":4652000,"nodes":[6216549610,6216549611,6216549612,6216549613,1413470849,1413470848,6216549605,6216549604,6216549610],"tags":{"amenity":"parking"}},{"type":"way","id":664171076,"timestamp":"2021-01-09T21:56:37Z","version":3,"changeset":97230316,"user":"JosV","uid":170722,"nodes":[6216549656,6216549655,8307316294,6216549661,6216549657,6216549658,6216549659,6216549660,6216549656],"tags":{"amenity":"parking","capacity":"50"}},{"type":"way","id":665330334,"timestamp":"2019-01-22T14:20:51Z","version":1,"changeset":66539354,"user":"Nilsnn","uid":4652000,"nodes":[6227395993,6227395991,6227395992,6227395997,6227395993],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface","surface":"asphalt"}},{"type":"way","id":684598363,"timestamp":"2020-03-07T14:21:22Z","version":3,"changeset":81900556,"user":"L'imaginaire","uid":654234,"nodes":[3227068565,6416001161,6414352054,6414352055,7274233390,7274233391,7274233397,7274233395,7274233396,6414352053,3227068568,3227068565],"tags":{"amenity":"parking","fee":"no"}},{"type":"way","id":684599810,"timestamp":"2020-12-31T20:58:28Z","version":3,"changeset":96751036,"user":"JosV","uid":170722,"nodes":[1317838331,8279842668,1384096112,1317838328,6414374315,3227068446,6414374316,6414374317,6414374318,3227068456,6414374319,6414374320,6414374321,1317838317,1317838331],"tags":{"access":"no","amenity":"parking","operator":"Politie"}},{"type":"way","id":761474468,"timestamp":"2021-01-05T21:32:23Z","version":3,"changeset":97006454,"user":"JosV","uid":170722,"nodes":[7114502201,7114502203,7114502200,7114502202,3170562439,3170562437,3170562431,7114502240,7114502211,7114502212,7114502214,7114502215,7114502228,7114502234,7114502235,7114502236,7114502237,7114502238,7114502239,7114502233,7114502232,7114502231,7114502229,7114502230,7114502227,7114502226,7114502225,7114502216,7114502217,7114502224,3170562392,7114502218,3170562394,7114502219,7114502220,7114502221,7114502222,7114502223,3170562395,3170562396,3170562397,3170562402,3170562410,7114502209,7114502208,7114502207,7114502205,7114502206,3170562436,1475188519,1475188516,6627605025,8294886142,7114502201],"tags":{"image":"http://valleivandezuidleie.be/wp-content/uploads/2011/12/2011-03-24_G12_088_1_1.JPG","leisure":"nature_reserve","name":"Merlebeek-Meerberg","natural":"wetland","operator":"Natuurpunt Vallei van de Zuidleie","start_date":"2011","website":"http://valleivandezuidleie.be/info-over-de-vallei-van-de-zuidleie/merlebeek/","wetland":"wet_meadow"}},{"type":"way","id":813859435,"timestamp":"2021-02-26T10:18:26Z","version":3,"changeset":100040879,"user":"s8evq","uid":3710738,"nodes":[7602479690,7459257985,7602479691,7459154784,7459154782,7602479692,5482441357,7602479693,7602479694,7602479695,7602479696,7602479690],"tags":{"access":"yes","image:0":"https://i.imgur.com/nb9nawa.jpg","landuse":"grass","leisure":"nature_reserve","name:signed":"no","natural":"grass","operator":"Natuurpunt Vallei van de Zuidleie"}},{"type":"way","id":826103452,"timestamp":"2020-07-14T09:05:14Z","version":1,"changeset":87965884,"user":"L'imaginaire","uid":654234,"nodes":[7713176912,7713176911,7713176910,7713176909,7713176912],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":893176022,"timestamp":"2021-01-07T23:02:07Z","version":1,"changeset":97133621,"user":"JosV","uid":170722,"nodes":[1927235214,8301349336,8301349335,8301349337,1927235214],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":895943476,"timestamp":"2021-01-16T17:56:50Z","version":1,"changeset":97614669,"user":"JosV","uid":170722,"nodes":[8328251887,8328251886,8328251885,8328251884,8328251887],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":895943477,"timestamp":"2021-01-16T17:56:50Z","version":1,"changeset":97614669,"user":"JosV","uid":170722,"nodes":[8328251891,8328251890,8328251889,8328251888,8328251891],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":895943478,"timestamp":"2021-01-16T17:56:50Z","version":1,"changeset":97614669,"user":"JosV","uid":170722,"nodes":[8328251895,8328251894,8328251893,8328251892,8328251895],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":895943479,"timestamp":"2021-01-16T17:56:50Z","version":1,"changeset":97614669,"user":"JosV","uid":170722,"nodes":[8328251897,8328251896,8328251901,8328251900,8328251897],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":895943480,"timestamp":"2021-01-16T17:56:50Z","version":1,"changeset":97614669,"user":"JosV","uid":170722,"nodes":[8328251898,8328251899,8328251903,8328251902,8328251898],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":895943481,"timestamp":"2021-01-16T17:56:50Z","version":1,"changeset":97614669,"user":"JosV","uid":170722,"nodes":[8328251907,8328251906,8328251905,8328251904,8328251907],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":895943482,"timestamp":"2021-01-16T17:56:50Z","version":1,"changeset":97614669,"user":"JosV","uid":170722,"nodes":[8328251911,8328251910,8328251909,8328251908,8328251911],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":901952767,"timestamp":"2021-01-30T12:19:15Z","version":1,"changeset":98412028,"user":"L'imaginaire","uid":654234,"nodes":[8378097127,8378097126,8378097125,8378097124,8378097127],"tags":{"amenity":"parking","parking":"street_side"}},{"type":"way","id":901952768,"timestamp":"2021-01-30T12:19:15Z","version":1,"changeset":98412028,"user":"L'imaginaire","uid":654234,"nodes":[8378097134,8378097133,8378097132,8378097131,8378097130,8378097129,8378097128,8378097134],"tags":{"amenity":"parking","parking":"street_side"}},{"type":"way","id":947325182,"timestamp":"2021-05-26T15:16:06Z","version":1,"changeset":105366812,"user":"L'imaginaire","uid":654234,"nodes":[8497007549,8768981525,8768981522,8768981524,8768981521,8768981523,8768981520,8768981519,6206789709,8768981533,8497007549],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":966827815,"timestamp":"2021-07-23T20:01:09Z","version":1,"changeset":108511361,"user":"L'imaginaire","uid":654234,"nodes":[8945026757,8945026756,8945026755,8945026754,8945026757],"tags":{"access":"customers","amenity":"parking","parking":"surface"}},{"type":"relation","id":2589413,"timestamp":"2021-03-06T15:13:01Z","version":7,"changeset":100540347,"user":"Pieter Vander Vennet","uid":3818858,"members":[{"type":"way","ref":663050030,"role":"outer"},{"type":"way","ref":184402334,"role":"outer"},{"type":"way","ref":184402332,"role":"outer"},{"type":"way","ref":184402325,"role":"outer"},{"type":"way","ref":184402326,"role":"outer"},{"type":"way","ref":314899865,"role":"outer"},{"type":"way","ref":314956402,"role":"outer"}],"tags":{"access":"yes","image":"https://i.imgur.com/Yu4qHh5.jpg","leisure":"nature_reserve","name":"Warandeputten","operator":"Natuurpunt Vallei van de Zuidleie","type":"multipolygon","wikipedia":"nl:Warandeputten"}},{"type":"relation","id":8782624,"timestamp":"2021-03-08T13:15:15Z","version":14,"changeset":100640534,"user":"M!dgard","uid":763799,"members":[{"type":"way","ref":315041273,"role":"outer"},{"type":"way","ref":631377343,"role":"outer"},{"type":"way","ref":631371237,"role":"outer"},{"type":"way","ref":631371236,"role":"outer"},{"type":"way","ref":631371234,"role":"outer"},{"type":"way","ref":631377344,"role":"outer"},{"type":"way","ref":631371232,"role":"outer"},{"type":"way","ref":631371231,"role":"outer"},{"type":"way","ref":315041263,"role":"outer"},{"type":"way","ref":631371228,"role":"outer"},{"type":"way","ref":631377341,"role":"outer"},{"type":"way","ref":315041261,"role":"outer"},{"type":"way","ref":631371223,"role":"outer"}],"tags":{"access":"yes","image:0":"https://i.imgur.com/VuzX5jW.jpg","image:1":"https://i.imgur.com/tPppmJG.jpg","image:2":"https://i.imgur.com/ecY3RER.jpg","image:3":"https://i.imgur.com/lr4FK6j.jpg","image:5":"https://i.imgur.com/uufEeE6.jpg","leisure":"nature_reserve","name":"Leiemeersen Noord","operator":"Natuurpunt Vallei van de Zuidleie","type":"multipolygon","website":"http://valleivandezuidleie.be/info-over-de-vallei-van-de-zuidleie/leiemeersen-noord/"}},{"type":"relation","id":8890076,"timestamp":"2020-07-18T15:56:50Z","version":6,"changeset":88179905,"user":"Pieter Vander Vennet","uid":3818858,"members":[{"type":"way","ref":640979982,"role":"outer"},{"type":"way","ref":640979978,"role":"outer"}],"tags":{"access":"yes","image:0":"https://i.imgur.com/SAAaKBH.jpg","image:1":"https://i.imgur.com/DGK9iBN.jpg","image:2":"https://i.imgur.com/bte1KJx.jpg","image:3":"https://i.imgur.com/f75Gxnx.jpg","leisure":"nature_reserve","name":"Gevaerts Noord","operator":"Natuurpunt Vallei van de Zuidleie","type":"multipolygon"}},{"type":"relation","id":9118029,"timestamp":"2020-07-11T12:04:16Z","version":4,"changeset":87852045,"user":"Pieter Vander Vennet","uid":3818858,"members":[{"type":"way","ref":606165130,"role":"outer"},{"type":"way","ref":655652319,"role":"outer"},{"type":"way","ref":655652321,"role":"outer"}],"tags":{"access":"no","image:0":"https://i.imgur.com/eBufo0v.jpg","image:1":"https://i.imgur.com/kBej2Nk.jpg","image:2":"https://i.imgur.com/QKoyIRl.jpg","leisure":"nature_reserve","name":"De Leiemeersen","note":"Door de hoge kwetsbaarheid van het gebied zijn De Leiemeersen enkel te bezoeken onder begeleiding van een gids","note:mapping":"NIET VOOR BEGINNENDE MAPPERS! Dit gebied is met relaties als multipolygonen gemapt (zo'n 50 stuks). Als je niet weet hoe dit werkt, vraag hulp.","note_1":"wetland=marsh is het veenmoerasgebied","operator":"Natuurpunt Vallei van de Zuidleie","type":"multipolygon","website":"http://valleivandezuidleie.be/info-over-de-vallei-van-de-zuidleie/leiemeersen/"}},{"type":"node","id":7114502229,"lat":51.1340508,"lon":3.2949303},{"type":"node","id":7114502231,"lat":51.1340428,"lon":3.2959613},{"type":"node","id":7114502232,"lat":51.134096,"lon":3.2971973},{"type":"node","id":1927235214,"lat":51.1267391,"lon":3.3222921},{"type":"node","id":8301349336,"lat":51.1266966,"lon":3.3223356},{"type":"node","id":1413470848,"lat":51.1276558,"lon":3.3278194},{"type":"node","id":1413470849,"lat":51.1276852,"lon":3.3274627},{"type":"node","id":6216549605,"lat":51.1276578,"lon":3.3279376},{"type":"node","id":6216549611,"lat":51.1277354,"lon":3.3273608},{"type":"node","id":6216549612,"lat":51.1277281,"lon":3.3274215},{"type":"node","id":6216549613,"lat":51.1277062,"lon":3.3274249},{"type":"node","id":8301349335,"lat":51.1269096,"lon":3.3228882},{"type":"node","id":8301349337,"lat":51.126955,"lon":3.3228466},{"type":"node","id":8328251884,"lat":51.1278701,"lon":3.3253392},{"type":"node","id":8328251885,"lat":51.127857,"lon":3.3254078},{"type":"node","id":8328251888,"lat":51.1278797,"lon":3.325168},{"type":"node","id":8328251889,"lat":51.1278665,"lon":3.3252369},{"type":"node","id":8328251892,"lat":51.1271569,"lon":3.3248958},{"type":"node","id":8328251893,"lat":51.1272208,"lon":3.3252329},{"type":"node","id":8328251894,"lat":51.1272677,"lon":3.3252111},{"type":"node","id":8328251895,"lat":51.1272033,"lon":3.3248728},{"type":"node","id":8328251896,"lat":51.1271015,"lon":3.3257575},{"type":"node","id":8328251897,"lat":51.1270872,"lon":3.3256877},{"type":"node","id":8328251898,"lat":51.1271271,"lon":3.325744},{"type":"node","id":8328251899,"lat":51.1271128,"lon":3.3256743},{"type":"node","id":8328251900,"lat":51.1270462,"lon":3.3257067},{"type":"node","id":8328251901,"lat":51.1270609,"lon":3.3257756},{"type":"node","id":8328251902,"lat":51.1272095,"lon":3.3257043},{"type":"node","id":8328251903,"lat":51.1271957,"lon":3.3256351},{"type":"node","id":8328251904,"lat":51.1269631,"lon":3.3253915},{"type":"node","id":8328251905,"lat":51.1269756,"lon":3.3254617},{"type":"node","id":8328251906,"lat":51.1271678,"lon":3.3253747},{"type":"node","id":8328251907,"lat":51.1271557,"lon":3.3253045},{"type":"node","id":8328251908,"lat":51.1270115,"lon":3.3255467},{"type":"node","id":8328251909,"lat":51.1270235,"lon":3.3256138},{"type":"node","id":8328251910,"lat":51.1271099,"lon":3.3255749},{"type":"node","id":8328251911,"lat":51.1270975,"lon":3.3255072},{"type":"node","id":2449323191,"lat":51.1340437,"lon":3.3216558},{"type":"node","id":2449323193,"lat":51.134285,"lon":3.3221086},{"type":"node","id":2449323198,"lat":51.1334724,"lon":3.3223472},{"type":"node","id":4350143592,"lat":51.1344661,"lon":3.3226292},{"type":"node","id":4732689626,"lat":51.1301038,"lon":3.3223672},{"type":"node","id":4732689627,"lat":51.1301351,"lon":3.3223533},{"type":"node","id":4732689628,"lat":51.130161,"lon":3.3224805},{"type":"node","id":4732689629,"lat":51.1301379,"lon":3.3224524},{"type":"node","id":4732689630,"lat":51.130151,"lon":3.3225204},{"type":"node","id":4732689631,"lat":51.1301375,"lon":3.3225274},{"type":"node","id":4732689632,"lat":51.1301505,"lon":3.322593},{"type":"node","id":4732689634,"lat":51.1297694,"lon":3.3223954},{"type":"node","id":4732689635,"lat":51.1298034,"lon":3.3223641},{"type":"node","id":4732689636,"lat":51.1297546,"lon":3.3221883},{"type":"node","id":4732689637,"lat":51.1297088,"lon":3.3219708},{"type":"node","id":4732689638,"lat":51.1297683,"lon":3.3219402},{"type":"node","id":4732689639,"lat":51.1297781,"lon":3.3219034},{"type":"node","id":4732689640,"lat":51.1297694,"lon":3.3218478},{"type":"node","id":4732689641,"lat":51.1300088,"lon":3.32173},{"type":"node","id":6794421027,"lat":51.1341852,"lon":3.3223337},{"type":"node","id":6794421042,"lat":51.1336271,"lon":3.3220973},{"type":"node","id":7962681614,"lat":51.1336656,"lon":3.322624},{"type":"node","id":7962681615,"lat":51.1335301,"lon":3.322287},{"type":"node","id":7962681616,"lat":51.1335065,"lon":3.3222317},{"type":"node","id":7962681619,"lat":51.134306,"lon":3.3222136},{"type":"node","id":7962681620,"lat":51.1343186,"lon":3.3221995},{"type":"node","id":7962681621,"lat":51.1341453,"lon":3.321775},{"type":"node","id":7962681622,"lat":51.1341537,"lon":3.321769},{"type":"node","id":7962681623,"lat":51.1341067,"lon":3.3216811},{"type":"node","id":7962681624,"lat":51.1340675,"lon":3.3217193},{"type":"node","id":8294875888,"lat":51.1300197,"lon":3.3219403},{"type":"node","id":8360787098,"lat":51.1344583,"lon":3.3225918},{"type":"node","id":2123461969,"lat":51.1336123,"lon":3.3226786},{"type":"node","id":4732689633,"lat":51.1298776,"lon":3.3227393},{"type":"node","id":6216549604,"lat":51.1280095,"lon":3.328024},{"type":"node","id":6216549610,"lat":51.128134,"lon":3.3274542},{"type":"node","id":6794421028,"lat":51.1343476,"lon":3.3227429},{"type":"node","id":6794421041,"lat":51.1337382,"lon":3.3227794},{"type":"node","id":8328251886,"lat":51.128048,"lon":3.3255015},{"type":"node","id":8328251887,"lat":51.1280616,"lon":3.3254329},{"type":"node","id":8328251890,"lat":51.1280791,"lon":3.3253407},{"type":"node","id":8328251891,"lat":51.1280922,"lon":3.3252721},{"type":"node","id":1623924235,"lat":51.131361,"lon":3.333018},{"type":"node","id":1623924236,"lat":51.1311039,"lon":3.3325764},{"type":"node","id":1623924238,"lat":51.1310489,"lon":3.3326527},{"type":"node","id":1623924241,"lat":51.1314273,"lon":3.3331479},{"type":"node","id":1864750831,"lat":51.1313615,"lon":3.3332222},{"type":"node","id":6216549655,"lat":51.134416,"lon":3.3347284},{"type":"node","id":6216549656,"lat":51.1343187,"lon":3.3349542},{"type":"node","id":6216549657,"lat":51.1334196,"lon":3.335723},{"type":"node","id":6216549658,"lat":51.1334902,"lon":3.3357377},{"type":"node","id":6216549659,"lat":51.133716,"lon":3.335546},{"type":"node","id":6216549660,"lat":51.133883,"lon":3.3353885},{"type":"node","id":6216549661,"lat":51.133662,"lon":3.3355049},{"type":"node","id":8307316294,"lat":51.1338503,"lon":3.3353095},{"type":"node","id":1493821422,"lat":51.1320567,"lon":3.3398517},{"type":"node","id":1493821433,"lat":51.1316132,"lon":3.3408892},{"type":"node","id":1553169836,"lat":51.1311998,"lon":3.3415993},{"type":"node","id":3185248088,"lat":51.1323359,"lon":3.3389757},{"type":"node","id":7727339364,"lat":51.1321819,"lon":3.3388758},{"type":"node","id":7727339365,"lat":51.1319823,"lon":3.339559},{"type":"node","id":7727339366,"lat":51.1316011,"lon":3.3405485},{"type":"node","id":7727339367,"lat":51.1312764,"lon":3.3411848},{"type":"node","id":7727339368,"lat":51.1310889,"lon":3.3414676},{"type":"node","id":7727339369,"lat":51.1304838,"lon":3.3422395},{"type":"node","id":3185248048,"lat":51.1268693,"lon":3.3480331},{"type":"node","id":3185248049,"lat":51.1269831,"lon":3.3475504},{"type":"node","id":7727339376,"lat":51.1274147,"lon":3.3464515},{"type":"node","id":7727339377,"lat":51.1271283,"lon":3.3469817},{"type":"node","id":3185248040,"lat":51.1266778,"lon":3.3491476},{"type":"node","id":3185248042,"lat":51.126712,"lon":3.3489485},{"type":"node","id":7468171404,"lat":51.1277325,"lon":3.3553578},{"type":"node","id":7468171430,"lat":51.1270326,"lon":3.353594},{"type":"node","id":7468171432,"lat":51.1271802,"lon":3.3540454},{"type":"node","id":7468171438,"lat":51.1268064,"lon":3.3526001},{"type":"node","id":7468171442,"lat":51.1268303,"lon":3.3527746},{"type":"node","id":7468171446,"lat":51.1273659,"lon":3.3546333},{"type":"node","id":7727339378,"lat":51.1265656,"lon":3.3505324},{"type":"node","id":7727339379,"lat":51.1266463,"lon":3.350873},{"type":"node","id":7727339380,"lat":51.1266302,"lon":3.3514032},{"type":"node","id":7727339381,"lat":51.1267774,"lon":3.3523929},{"type":"node","id":7727393190,"lat":51.1276264,"lon":3.3489611},{"type":"node","id":7727393191,"lat":51.1274853,"lon":3.3497484},{"type":"node","id":7727393192,"lat":51.127332,"lon":3.350571},{"type":"node","id":7727393193,"lat":51.1273663,"lon":3.3514386},{"type":"node","id":7727393194,"lat":51.1274853,"lon":3.3519206},{"type":"node","id":7727393195,"lat":51.1276889,"lon":3.3531674},{"type":"node","id":1553169911,"lat":51.1313314,"lon":3.3425771},{"type":"node","id":7727339370,"lat":51.1300705,"lon":3.3427304},{"type":"node","id":7727339371,"lat":51.1293083,"lon":3.343643},{"type":"node","id":7727339372,"lat":51.1285642,"lon":3.3445074},{"type":"node","id":7727339373,"lat":51.1285702,"lon":3.3445781},{"type":"node","id":7727339374,"lat":51.1283181,"lon":3.3448801},{"type":"node","id":7727339375,"lat":51.1281023,"lon":3.3451404},{"type":"node","id":7727339382,"lat":51.1311196,"lon":3.3430952},{"type":"node","id":7727339383,"lat":51.1309343,"lon":3.3434996},{"type":"node","id":7727339384,"lat":51.1306234,"lon":3.343745},{"type":"node","id":7727393185,"lat":51.1300873,"lon":3.3443449},{"type":"node","id":7727393186,"lat":51.129401,"lon":3.3453846},{"type":"node","id":7727393187,"lat":51.1290865,"lon":3.345963},{"type":"node","id":7727393188,"lat":51.1285581,"lon":3.3468788},{"type":"node","id":7727393189,"lat":51.1280217,"lon":3.3479457},{"type":"node","id":7390697549,"lat":51.128429,"lon":3.354427},{"type":"node","id":7727393196,"lat":51.1279813,"lon":3.353749},{"type":"node","id":3209560114,"lat":51.1538874,"lon":3.2531858},{"type":"node","id":3209560115,"lat":51.1539649,"lon":3.2531836},{"type":"node","id":3209560116,"lat":51.1541197,"lon":3.2537986},{"type":"node","id":3209560117,"lat":51.1541021,"lon":3.253149},{"type":"node","id":3210389695,"lat":51.1539646,"lon":3.2534427},{"type":"node","id":416917618,"lat":51.1565737,"lon":3.2549365},{"type":"node","id":668981667,"lat":51.1576026,"lon":3.2555383},{"type":"node","id":668981668,"lat":51.1564046,"lon":3.2547045},{"type":"node","id":1815081998,"lat":51.1575578,"lon":3.2555439},{"type":"node","id":1948835662,"lat":51.155957,"lon":3.2562889},{"type":"node","id":1948835742,"lat":51.156182,"lon":3.2540291},{"type":"node","id":1948835950,"lat":51.1591027,"lon":3.2559292},{"type":"node","id":1948836096,"lat":51.1600831,"lon":3.2562989},{"type":"node","id":1948836149,"lat":51.1605378,"lon":3.2568906},{"type":"node","id":2026541837,"lat":51.1543652,"lon":3.2542901},{"type":"node","id":2026541841,"lat":51.1545903,"lon":3.2546809},{"type":"node","id":2026541843,"lat":51.1548384,"lon":3.2550342},{"type":"node","id":2026541846,"lat":51.155086,"lon":3.2553429},{"type":"node","id":2026541851,"lat":51.15565,"lon":3.2542965},{"type":"node","id":3209560118,"lat":51.1542244,"lon":3.2530815},{"type":"node","id":3209560119,"lat":51.1544741,"lon":3.252803},{"type":"node","id":3209560121,"lat":51.1546028,"lon":3.2526667},{"type":"node","id":3209560124,"lat":51.1547447,"lon":3.2525904},{"type":"node","id":3209560126,"lat":51.1550296,"lon":3.2525253},{"type":"node","id":3209560127,"lat":51.1551915,"lon":3.2525297},{"type":"node","id":3209560131,"lat":51.1553436,"lon":3.2525627},{"type":"node","id":3209560132,"lat":51.1554055,"lon":3.2526006},{"type":"node","id":3209560134,"lat":51.155479,"lon":3.2526651},{"type":"node","id":3209560135,"lat":51.155558,"lon":3.2527647},{"type":"node","id":3209560136,"lat":51.1556482,"lon":3.2528805},{"type":"node","id":3209560138,"lat":51.1559652,"lon":3.2534517},{"type":"node","id":3209560139,"lat":51.1560327,"lon":3.2535705},{"type":"node","id":5417515520,"lat":51.1545998,"lon":3.2545767},{"type":"node","id":5417516021,"lat":51.1545476,"lon":3.2544989},{"type":"node","id":5417516022,"lat":51.1545856,"lon":3.2544342},{"type":"node","id":5417516023,"lat":51.1546378,"lon":3.2545119},{"type":"node","id":6206789688,"lat":51.1553578,"lon":3.255668},{"type":"node","id":416917603,"lat":51.1591104,"lon":3.2595563},{"type":"node","id":416917605,"lat":51.1592829,"lon":3.2591123},{"type":"node","id":416917609,"lat":51.1597764,"lon":3.2597849},{"type":"node","id":1554514806,"lat":51.1586314,"lon":3.2636074},{"type":"node","id":1948835842,"lat":51.1570345,"lon":3.2574053},{"type":"node","id":1948835900,"lat":51.1583428,"lon":3.258761},{"type":"node","id":1948835986,"lat":51.1595419,"lon":3.2593891},{"type":"node","id":1948836023,"lat":51.1597284,"lon":3.2585312},{"type":"node","id":1948836025,"lat":51.1597477,"lon":3.2585581},{"type":"node","id":1948836029,"lat":51.1597506,"lon":3.2584887},{"type":"node","id":1948836032,"lat":51.159778,"lon":3.2585905},{"type":"node","id":1948836038,"lat":51.1597992,"lon":3.2585462},{"type":"node","id":1948836068,"lat":51.1598265,"lon":3.2595499},{"type":"node","id":1948836072,"lat":51.1598725,"lon":3.2596329},{"type":"node","id":1948836093,"lat":51.1600505,"lon":3.2592835},{"type":"node","id":1948836104,"lat":51.1601026,"lon":3.2593298},{"type":"node","id":1948836189,"lat":51.1606847,"lon":3.2577063},{"type":"node","id":5745739926,"lat":51.160615,"lon":3.2602336},{"type":"node","id":5747937642,"lat":51.1580603,"lon":3.2636348},{"type":"node","id":5962340003,"lat":51.1587851,"lon":3.2632739},{"type":"node","id":5962414276,"lat":51.158949,"lon":3.2635109},{"type":"node","id":5962415498,"lat":51.1589617,"lon":3.2635523},{"type":"node","id":5962415499,"lat":51.1589623,"lon":3.2635339},{"type":"node","id":5962415500,"lat":51.1589568,"lon":3.2635203},{"type":"node","id":5962415538,"lat":51.1589195,"lon":3.2636407},{"type":"node","id":6206789709,"lat":51.1545829,"lon":3.2585784},{"type":"node","id":8497007481,"lat":51.1588349,"lon":3.2633671},{"type":"node","id":8497007549,"lat":51.1548977,"lon":3.257909},{"type":"node","id":8768981519,"lat":51.1545715,"lon":3.2585859},{"type":"node","id":8768981520,"lat":51.1544691,"lon":3.2584642},{"type":"node","id":8768981521,"lat":51.1543652,"lon":3.2584253},{"type":"node","id":8768981522,"lat":51.1543648,"lon":3.2583401},{"type":"node","id":8768981523,"lat":51.1544439,"lon":3.2585178},{"type":"node","id":8768981524,"lat":51.1543892,"lon":3.258369},{"type":"node","id":8768981525,"lat":51.1547185,"lon":3.2575482},{"type":"node","id":8768981533,"lat":51.1545902,"lon":3.2585725},{"type":"node","id":3162627482,"lat":51.1513402,"lon":3.2701364},{"type":"node","id":3162627509,"lat":51.1517878,"lon":3.2696503},{"type":"node","id":5745963944,"lat":51.1524768,"lon":3.2700312},{"type":"node","id":5745963946,"lat":51.1519527,"lon":3.2698278},{"type":"node","id":5745963947,"lat":51.1513495,"lon":3.2697903},{"type":"node","id":5747937657,"lat":51.1538472,"lon":3.269262},{"type":"node","id":5747937658,"lat":51.1536592,"lon":3.2698471},{"type":"node","id":5747937668,"lat":51.1514068,"lon":3.2699149},{"type":"node","id":5747937669,"lat":51.1514278,"lon":3.26999},{"type":"node","id":5747937670,"lat":51.1514329,"lon":3.2701134},{"type":"node","id":5747937671,"lat":51.1514387,"lon":3.2702207},{"type":"node","id":5747937672,"lat":51.1515532,"lon":3.2702006},{"type":"node","id":5747937673,"lat":51.1515986,"lon":3.2701456},{"type":"node","id":5747937674,"lat":51.151872,"lon":3.2701201},{"type":"node","id":6142725039,"lat":51.1513841,"lon":3.2701799},{"type":"node","id":6142725060,"lat":51.1499168,"lon":3.2700268},{"type":"node","id":6142725061,"lat":51.1497438,"lon":3.2697269},{"type":"node","id":6142725064,"lat":51.1499256,"lon":3.2692437},{"type":"node","id":6142727594,"lat":51.1500369,"lon":3.2694178},{"type":"node","id":6142727597,"lat":51.1513713,"lon":3.2701053},{"type":"node","id":6143075014,"lat":51.1512852,"lon":3.2702041},{"type":"node","id":1554514655,"lat":51.1533288,"lon":3.2766885},{"type":"node","id":1554514811,"lat":51.1537898,"lon":3.2754789},{"type":"node","id":3211247019,"lat":51.1538788,"lon":3.2763248},{"type":"node","id":3211247021,"lat":51.1538471,"lon":3.2764673},{"type":"node","id":5745963922,"lat":51.1499683,"lon":3.2708447},{"type":"node","id":5745963942,"lat":51.1530892,"lon":3.2704581},{"type":"node","id":5745963943,"lat":51.1529125,"lon":3.2703349},{"type":"node","id":5747535101,"lat":51.1533021,"lon":3.2705247},{"type":"node","id":5747937659,"lat":51.1534063,"lon":3.2705828},{"type":"node","id":5747937675,"lat":51.1521092,"lon":3.2702998},{"type":"node","id":5747937676,"lat":51.1524591,"lon":3.2704822},{"type":"node","id":5747937677,"lat":51.1527839,"lon":3.2706727},{"type":"node","id":5747937678,"lat":51.1529841,"lon":3.2707276},{"type":"node","id":5747937679,"lat":51.15326,"lon":3.2708913},{"type":"node","id":5747937680,"lat":51.1535477,"lon":3.2712989},{"type":"node","id":5747937681,"lat":51.1536831,"lon":3.2717402},{"type":"node","id":5747937682,"lat":51.1536839,"lon":3.2721747},{"type":"node","id":5747937683,"lat":51.1536469,"lon":3.2724161},{"type":"node","id":5747937684,"lat":51.1534635,"lon":3.2730652},{"type":"node","id":5747937685,"lat":51.1540625,"lon":3.2735735},{"type":"node","id":5962339921,"lat":51.1535454,"lon":3.2761201},{"type":"node","id":5962496725,"lat":51.1538672,"lon":3.276374},{"type":"node","id":6142725040,"lat":51.1514014,"lon":3.2704388},{"type":"node","id":6142725041,"lat":51.1514255,"lon":3.2722713},{"type":"node","id":6142725042,"lat":51.1514044,"lon":3.2722821},{"type":"node","id":6142725043,"lat":51.1513617,"lon":3.2722639},{"type":"node","id":6142725044,"lat":51.1513141,"lon":3.2722165},{"type":"node","id":6142725045,"lat":51.1512346,"lon":3.2721372},{"type":"node","id":6142725046,"lat":51.1511314,"lon":3.2720304},{"type":"node","id":6142725047,"lat":51.1509926,"lon":3.2718816},{"type":"node","id":6142725048,"lat":51.1508222,"lon":3.2716946},{"type":"node","id":6142725049,"lat":51.1507329,"lon":3.2715909},{"type":"node","id":6142725050,"lat":51.1506561,"lon":3.2714915},{"type":"node","id":6142725051,"lat":51.1506027,"lon":3.2714102},{"type":"node","id":6142725052,"lat":51.1505293,"lon":3.2712712},{"type":"node","id":6142725053,"lat":51.1504912,"lon":3.2711826},{"type":"node","id":6142725054,"lat":51.1504464,"lon":3.2710615},{"type":"node","id":6142725055,"lat":51.1503588,"lon":3.2707712},{"type":"node","id":6142725056,"lat":51.1503432,"lon":3.2707336},{"type":"node","id":6142725057,"lat":51.1503035,"lon":3.2706647},{"type":"node","id":6142725058,"lat":51.1501763,"lon":3.2704663},{"type":"node","id":6142725059,"lat":51.1500465,"lon":3.270256},{"type":"node","id":6142725065,"lat":51.1511856,"lon":3.2703268},{"type":"node","id":6142725066,"lat":51.1510244,"lon":3.2705705},{"type":"node","id":6142725067,"lat":51.1509355,"lon":3.270823},{"type":"node","id":6142725074,"lat":51.149723,"lon":3.271666},{"type":"node","id":6142725076,"lat":51.1498322,"lon":3.2716555},{"type":"node","id":6142725077,"lat":51.1499403,"lon":3.2715209},{"type":"node","id":6142725078,"lat":51.1500262,"lon":3.2714548},{"type":"node","id":6142725079,"lat":51.1501462,"lon":3.2714359},{"type":"node","id":6142725080,"lat":51.1502306,"lon":3.2714572},{"type":"node","id":6142725081,"lat":51.1502676,"lon":3.2714288},{"type":"node","id":6142725084,"lat":51.1496118,"lon":3.2714056},{"type":"node","id":6142727585,"lat":51.1497709,"lon":3.271258},{"type":"node","id":6142727586,"lat":51.1496767,"lon":3.2713056},{"type":"node","id":6142727587,"lat":51.1498468,"lon":3.2711798},{"type":"node","id":6142727588,"lat":51.1500514,"lon":3.2703954},{"type":"node","id":6142727589,"lat":51.1503033,"lon":3.270777},{"type":"node","id":6142727590,"lat":51.1503141,"lon":3.2713705},{"type":"node","id":6142727591,"lat":51.1498992,"lon":3.2710354},{"type":"node","id":6142727592,"lat":51.1499461,"lon":3.270906},{"type":"node","id":6142727595,"lat":51.1505973,"lon":3.2702942},{"type":"node","id":6142727596,"lat":51.1508515,"lon":3.2706917},{"type":"node","id":6142727598,"lat":51.1504337,"lon":3.2712326},{"type":"node","id":6143074993,"lat":51.1501845,"lon":3.2706959},{"type":"node","id":6143075018,"lat":51.1508744,"lon":3.2707275},{"type":"node","id":8638721230,"lat":51.151458,"lon":3.2721756},{"type":"node","id":8638721239,"lat":51.1514715,"lon":3.2719839},{"type":"node","id":1554514618,"lat":51.1581789,"lon":3.2646401},{"type":"node","id":1554514658,"lat":51.1578742,"lon":3.2653982},{"type":"node","id":1554514750,"lat":51.1568056,"lon":3.2677508},{"type":"node","id":1554514755,"lat":51.1573435,"lon":3.2665694},{"type":"node","id":1554514831,"lat":51.1561729,"lon":3.2691965},{"type":"node","id":3211247042,"lat":51.1557516,"lon":3.2701591},{"type":"node","id":3211247054,"lat":51.1570321,"lon":3.2690614},{"type":"node","id":3211247058,"lat":51.1571866,"lon":3.2685962},{"type":"node","id":3211247059,"lat":51.1572111,"lon":3.2673633},{"type":"node","id":3211247060,"lat":51.1572915,"lon":3.2701354},{"type":"node","id":3211247261,"lat":51.157332,"lon":3.2685775},{"type":"node","id":3211247265,"lat":51.1575267,"lon":3.2694937},{"type":"node","id":3211247266,"lat":51.1576636,"lon":3.2677588},{"type":"node","id":3211247291,"lat":51.15873,"lon":3.2640973},{"type":"node","id":3211247328,"lat":51.1594831,"lon":3.2648765},{"type":"node","id":3211247331,"lat":51.1596428,"lon":3.2643669},{"type":"node","id":5747937641,"lat":51.1581621,"lon":3.2637783},{"type":"node","id":5747937643,"lat":51.1576288,"lon":3.2640519},{"type":"node","id":5747937644,"lat":51.1572672,"lon":3.2645347},{"type":"node","id":5747937645,"lat":51.1568533,"lon":3.2650349},{"type":"node","id":5747937646,"lat":51.1564933,"lon":3.2652213},{"type":"node","id":5747937647,"lat":51.1562275,"lon":3.2654708},{"type":"node","id":5747937648,"lat":51.1560046,"lon":3.2656894},{"type":"node","id":5747937649,"lat":51.1556867,"lon":3.2659965},{"type":"node","id":5747937650,"lat":51.1551778,"lon":3.2664082},{"type":"node","id":5747937651,"lat":51.1550608,"lon":3.2664739},{"type":"node","id":5747937652,"lat":51.1547446,"lon":3.2666805},{"type":"node","id":5747937653,"lat":51.1546747,"lon":3.2667583},{"type":"node","id":5747937654,"lat":51.1546066,"lon":3.266895},{"type":"node","id":5747937655,"lat":51.1544363,"lon":3.2672456},{"type":"node","id":5747937656,"lat":51.1543612,"lon":3.2677126},{"type":"node","id":5747937688,"lat":51.1553145,"lon":3.2701637},{"type":"node","id":5747937689,"lat":51.1564724,"lon":3.2675566},{"type":"node","id":5747937690,"lat":51.1580352,"lon":3.2640939},{"type":"node","id":5747937691,"lat":51.1581075,"lon":3.2639222},{"type":"node","id":5962338038,"lat":51.1580663,"lon":3.2649607},{"type":"node","id":5962340009,"lat":51.1585904,"lon":3.2644244},{"type":"node","id":5962340010,"lat":51.1579212,"lon":3.2658517},{"type":"node","id":5962340011,"lat":51.1575197,"lon":3.2676156},{"type":"node","id":5962340012,"lat":51.1573374,"lon":3.2674543},{"type":"node","id":5962340013,"lat":51.1574265,"lon":3.2698457},{"type":"node","id":5962415543,"lat":51.1591427,"lon":3.2638615},{"type":"node","id":5962415564,"lat":51.1563757,"lon":3.269274},{"type":"node","id":5962444841,"lat":51.1584746,"lon":3.2639653},{"type":"node","id":5962444846,"lat":51.1585428,"lon":3.2645259},{"type":"node","id":5962444849,"lat":51.1586783,"lon":3.2642185},{"type":"node","id":5962444850,"lat":51.1586559,"lon":3.2642708},{"type":"node","id":5962496715,"lat":51.1577157,"lon":3.2657479},{"type":"node","id":5962496718,"lat":51.1572172,"lon":3.2685923},{"type":"node","id":5962496719,"lat":51.1571618,"lon":3.2686709},{"type":"node","id":1554514640,"lat":51.1556541,"lon":3.2703864},{"type":"node","id":1554514735,"lat":51.1546949,"lon":3.273022},{"type":"node","id":1554514739,"lat":51.1552715,"lon":3.271391},{"type":"node","id":1554514744,"lat":51.154165,"lon":3.2744194},{"type":"node","id":3211247024,"lat":51.1541505,"lon":3.2756042},{"type":"node","id":3211247029,"lat":51.154764,"lon":3.2739293},{"type":"node","id":3211247032,"lat":51.1550284,"lon":3.2731777},{"type":"node","id":3211247034,"lat":51.1553184,"lon":3.2723493},{"type":"node","id":3211247036,"lat":51.1554324,"lon":3.2715569},{"type":"node","id":3211247037,"lat":51.1555577,"lon":3.2717139},{"type":"node","id":3211247039,"lat":51.1556614,"lon":3.2709968},{"type":"node","id":5747937686,"lat":51.1543123,"lon":3.272868},{"type":"node","id":5747937687,"lat":51.1551484,"lon":3.2706069},{"type":"node","id":5962415565,"lat":51.1558985,"lon":3.2703959},{"type":"node","id":3170562436,"lat":51.138924,"lon":3.2898032},{"type":"node","id":7114502205,"lat":51.1385818,"lon":3.2899019},{"type":"node","id":7114502206,"lat":51.1387244,"lon":3.289738},{"type":"node","id":1475188516,"lat":51.1392568,"lon":3.2899836},{"type":"node","id":1475188519,"lat":51.1391868,"lon":3.2900136},{"type":"node","id":3170562392,"lat":51.1364433,"lon":3.2910119},{"type":"node","id":3170562394,"lat":51.1368907,"lon":3.291708},{"type":"node","id":3170562395,"lat":51.137106,"lon":3.2924864},{"type":"node","id":3170562396,"lat":51.137265,"lon":3.2919875},{"type":"node","id":3170562397,"lat":51.1374825,"lon":3.2913695},{"type":"node","id":3170562402,"lat":51.1378658,"lon":3.2906394},{"type":"node","id":3170562410,"lat":51.1378512,"lon":3.2905949},{"type":"node","id":3170562431,"lat":51.138431,"lon":3.2910415},{"type":"node","id":3170562437,"lat":51.1389596,"lon":3.2905649},{"type":"node","id":3170562439,"lat":51.1391839,"lon":3.2903042},{"type":"node","id":6627605025,"lat":51.1393014,"lon":3.2899729},{"type":"node","id":7114502200,"lat":51.139377,"lon":3.2901873},{"type":"node","id":7114502201,"lat":51.1395801,"lon":3.2901445},{"type":"node","id":7114502202,"lat":51.1393183,"lon":3.290151},{"type":"node","id":7114502203,"lat":51.1395636,"lon":3.2902055},{"type":"node","id":7114502207,"lat":51.13835,"lon":3.2901225},{"type":"node","id":7114502208,"lat":51.138259,"lon":3.2902362},{"type":"node","id":7114502209,"lat":51.1381351,"lon":3.2903372},{"type":"node","id":7114502211,"lat":51.1376987,"lon":3.2921954},{"type":"node","id":7114502212,"lat":51.1373598,"lon":3.2927952},{"type":"node","id":7114502214,"lat":51.1364782,"lon":3.2933157},{"type":"node","id":7114502215,"lat":51.1356558,"lon":3.2938122},{"type":"node","id":7114502216,"lat":51.1364577,"lon":3.2922382},{"type":"node","id":7114502217,"lat":51.1365055,"lon":3.2917901},{"type":"node","id":7114502218,"lat":51.1369977,"lon":3.2911659},{"type":"node","id":7114502219,"lat":51.1367691,"lon":3.2924051},{"type":"node","id":7114502220,"lat":51.1367022,"lon":3.2927526},{"type":"node","id":7114502221,"lat":51.1367354,"lon":3.2929091},{"type":"node","id":7114502222,"lat":51.1367962,"lon":3.2930156},{"type":"node","id":7114502223,"lat":51.1369436,"lon":3.2928838},{"type":"node","id":7114502224,"lat":51.1365124,"lon":3.2914123},{"type":"node","id":7114502225,"lat":51.135804,"lon":3.2926995},{"type":"node","id":7114502226,"lat":51.1354385,"lon":3.2929897},{"type":"node","id":7114502227,"lat":51.135128,"lon":3.2935318},{"type":"node","id":7114502228,"lat":51.1352851,"lon":3.2947114},{"type":"node","id":7114502230,"lat":51.135254,"lon":3.2946241},{"type":"node","id":7114502234,"lat":51.1354035,"lon":3.2959064},{"type":"node","id":7114502235,"lat":51.1362234,"lon":3.2955042},{"type":"node","id":7114502236,"lat":51.1362859,"lon":3.2964578},{"type":"node","id":7114502240,"lat":51.1379417,"lon":3.2917937},{"type":"node","id":8294886142,"lat":51.1394294,"lon":3.290127},{"type":"node","id":7114502233,"lat":51.1354361,"lon":3.2966386},{"type":"node","id":7114502237,"lat":51.1362025,"lon":3.2964851},{"type":"node","id":7114502238,"lat":51.1362303,"lon":3.2969415},{"type":"node","id":7114502239,"lat":51.1355032,"lon":3.297292},{"type":"node","id":1494027348,"lat":51.1419125,"lon":3.3028989},{"type":"node","id":1494027349,"lat":51.1419929,"lon":3.3024731},{"type":"node","id":1951759298,"lat":51.1421456,"lon":3.3024503},{"type":"node","id":6037556099,"lat":51.1420961,"lon":3.3023333},{"type":"node","id":6037556100,"lat":51.142124,"lon":3.302398},{"type":"node","id":6037556101,"lat":51.1421476,"lon":3.3023664},{"type":"node","id":6037556102,"lat":51.1421686,"lon":3.3023966},{"type":"node","id":6037556103,"lat":51.1421392,"lon":3.3024395},{"type":"node","id":6037556104,"lat":51.1419363,"lon":3.3027154},{"type":"node","id":6037556128,"lat":51.1421612,"lon":3.3024776},{"type":"node","id":6037556129,"lat":51.1421598,"lon":3.3025191},{"type":"node","id":1554514647,"lat":51.1510862,"lon":3.2830051},{"type":"node","id":1554514679,"lat":51.1528746,"lon":3.2778124},{"type":"node","id":1554514683,"lat":51.152459,"lon":3.2789175},{"type":"node","id":1554514730,"lat":51.1514294,"lon":3.2817821},{"type":"node","id":1554514747,"lat":51.1515758,"lon":3.2812966},{"type":"node","id":1554514765,"lat":51.1518248,"lon":3.2805268},{"type":"node","id":1554514773,"lat":51.15167,"lon":3.280964},{"type":"node","id":1554514775,"lat":51.1517205,"lon":3.2808218},{"type":"node","id":3211246555,"lat":51.1516922,"lon":3.2825734},{"type":"node","id":3211246995,"lat":51.1531241,"lon":3.2787307},{"type":"node","id":3211246997,"lat":51.1532256,"lon":3.2781298},{"type":"node","id":3211247004,"lat":51.1532551,"lon":3.2780324},{"type":"node","id":3211247008,"lat":51.1532769,"lon":3.2780262},{"type":"node","id":3211247010,"lat":51.1533547,"lon":3.2780182},{"type":"node","id":3211247013,"lat":51.1534072,"lon":3.2778679},{"type":"node","id":5962338069,"lat":51.1531224,"lon":3.2785269},{"type":"node","id":5962338070,"lat":51.1532454,"lon":3.2781435},{"type":"node","id":5962338071,"lat":51.1531839,"lon":3.2785716},{"type":"node","id":9284562682,"lat":51.153154,"lon":3.2784189},{"type":"node","id":1554514649,"lat":51.1502146,"lon":3.285505},{"type":"node","id":1554514661,"lat":51.1499067,"lon":3.2861781},{"type":"node","id":1554514682,"lat":51.150038,"lon":3.2859179},{"type":"node","id":1554514693,"lat":51.1498077,"lon":3.2862946},{"type":"node","id":1554514703,"lat":51.1497368,"lon":3.2863685},{"type":"node","id":1554514726,"lat":51.1498748,"lon":3.2862129},{"type":"node","id":1554514783,"lat":51.1497118,"lon":3.2864368},{"type":"node","id":1554514787,"lat":51.1499524,"lon":3.2860908},{"type":"node","id":1554514789,"lat":51.1506254,"lon":3.2845029},{"type":"node","id":3203029856,"lat":51.1498994,"lon":3.2867119},{"type":"node","id":3211246542,"lat":51.1505988,"lon":3.2851597},{"type":"node","id":5482441357,"lat":51.1504615,"lon":3.2836968},{"type":"node","id":7459154782,"lat":51.1501541,"lon":3.2834044},{"type":"node","id":7459154784,"lat":51.14999,"lon":3.2838049},{"type":"node","id":7459257985,"lat":51.1496077,"lon":3.2846412},{"type":"node","id":7602479690,"lat":51.150018,"lon":3.2848987},{"type":"node","id":7602479691,"lat":51.149806,"lon":3.2842251},{"type":"node","id":7602479692,"lat":51.1504686,"lon":3.2836785},{"type":"node","id":7602479693,"lat":51.1504309,"lon":3.2838118},{"type":"node","id":7602479694,"lat":51.1504255,"lon":3.2838072},{"type":"node","id":7602479695,"lat":51.1503423,"lon":3.2840392},{"type":"node","id":7602479696,"lat":51.1501698,"lon":3.2845196},{"type":"node","id":7727406921,"lat":51.1497539,"lon":3.2864986},{"type":"node","id":8945026754,"lat":51.1518736,"lon":3.2973911},{"type":"node","id":8945026755,"lat":51.1521646,"lon":3.297599},{"type":"node","id":8945026756,"lat":51.1522042,"lon":3.2974333},{"type":"node","id":8945026757,"lat":51.1519287,"lon":3.2972449},{"type":"node","id":416917612,"lat":51.1610842,"lon":3.2579973},{"type":"node","id":1948836192,"lat":51.1607104,"lon":3.2576119},{"type":"node","id":1948836193,"lat":51.1607138,"lon":3.2577265},{"type":"node","id":1948836194,"lat":51.1607261,"lon":3.2576817},{"type":"node","id":1948836195,"lat":51.1607396,"lon":3.2576322},{"type":"node","id":1948836202,"lat":51.1608376,"lon":3.2582648},{"type":"node","id":1948836209,"lat":51.1608764,"lon":3.2583297},{"type":"node","id":1948836218,"lat":51.1609914,"lon":3.2580679},{"type":"node","id":1948836237,"lat":51.1610295,"lon":3.2581432},{"type":"node","id":1948836277,"lat":51.1610699,"lon":3.2580833},{"type":"node","id":5349884600,"lat":51.1623355,"lon":3.2627383},{"type":"node","id":5349884601,"lat":51.1621681,"lon":3.2630327},{"type":"node","id":5349884602,"lat":51.1622043,"lon":3.2630816},{"type":"node","id":5349884603,"lat":51.162375,"lon":3.2627913},{"type":"node","id":5349884604,"lat":51.1622594,"lon":3.2633478},{"type":"node","id":5349884605,"lat":51.1621955,"lon":3.2632528},{"type":"node","id":5349884606,"lat":51.1623824,"lon":3.2629335},{"type":"node","id":5349884607,"lat":51.1624462,"lon":3.2630285},{"type":"node","id":5745739924,"lat":51.1608677,"lon":3.2604028},{"type":"node","id":5745739925,"lat":51.160749,"lon":3.2605301},{"type":"node","id":5745739927,"lat":51.160719,"lon":3.2600865},{"type":"node","id":1494027341,"lat":51.1418334,"lon":3.3035292},{"type":"node","id":1494027359,"lat":51.1413757,"lon":3.3074828},{"type":"node","id":1494027374,"lat":51.14132,"lon":3.3086261},{"type":"node","id":1494027376,"lat":51.1415625,"lon":3.3055864},{"type":"node","id":1494027385,"lat":51.1414514,"lon":3.3065628},{"type":"node","id":1494027386,"lat":51.1416927,"lon":3.3044972},{"type":"node","id":1494027389,"lat":51.1412677,"lon":3.3093509},{"type":"node","id":6037556130,"lat":51.1420599,"lon":3.303249},{"type":"node","id":6037556131,"lat":51.1419859,"lon":3.3038109},{"type":"node","id":6037556132,"lat":51.1418857,"lon":3.3046747},{"type":"node","id":6037556133,"lat":51.1418916,"lon":3.3050562},{"type":"node","id":6037556134,"lat":51.141927,"lon":3.3054665},{"type":"node","id":6037556135,"lat":51.1419362,"lon":3.3056543},{"type":"node","id":6037556136,"lat":51.1419369,"lon":3.3060001},{"type":"node","id":6037556137,"lat":51.1419328,"lon":3.3061768},{"type":"node","id":6037556138,"lat":51.1419139,"lon":3.3062337},{"type":"node","id":6037556139,"lat":51.1419032,"lon":3.3062932},{"type":"node","id":6037556140,"lat":51.1419001,"lon":3.3065944},{"type":"node","id":6037556141,"lat":51.1419262,"lon":3.3066872},{"type":"node","id":6037556142,"lat":51.1419119,"lon":3.3074563},{"type":"node","id":6037556143,"lat":51.1419027,"lon":3.3079359},{"type":"node","id":6037556144,"lat":51.1418924,"lon":3.3090764},{"type":"node","id":6037556145,"lat":51.1418843,"lon":3.3094015},{"type":"node","id":1494027342,"lat":51.1411958,"lon":3.3123073},{"type":"node","id":1494027346,"lat":51.1411509,"lon":3.3144776},{"type":"node","id":1494027353,"lat":51.141193,"lon":3.3127209},{"type":"node","id":1494027361,"lat":51.1411944,"lon":3.3118627},{"type":"node","id":1494027366,"lat":51.1411788,"lon":3.3132011},{"type":"node","id":1494027368,"lat":51.1411457,"lon":3.3148322},{"type":"node","id":1494027372,"lat":51.1412147,"lon":3.3112199},{"type":"node","id":1494027373,"lat":51.1411641,"lon":3.3142758},{"type":"node","id":1494027378,"lat":51.1412256,"lon":3.3114828},{"type":"node","id":1494027382,"lat":51.1412174,"lon":3.3105548},{"type":"node","id":6037556098,"lat":51.1411339,"lon":3.315984},{"type":"node","id":6037556146,"lat":51.1418276,"lon":3.309789},{"type":"node","id":6037556148,"lat":51.1418583,"lon":3.3096011},{"type":"node","id":6037556149,"lat":51.1418039,"lon":3.3098357},{"type":"node","id":6037556150,"lat":51.1417743,"lon":3.3098805},{"type":"node","id":6037556151,"lat":51.1416977,"lon":3.3101207},{"type":"node","id":6037556152,"lat":51.1416834,"lon":3.3102232},{"type":"node","id":6037556153,"lat":51.1416823,"lon":3.3102705},{"type":"node","id":6037556154,"lat":51.1416302,"lon":3.3105557},{"type":"node","id":6037556155,"lat":51.1416042,"lon":3.3107844},{"type":"node","id":6037556156,"lat":51.1415929,"lon":3.3110547},{"type":"node","id":6037556157,"lat":51.1415904,"lon":3.3118741},{"type":"node","id":6037556158,"lat":51.1415817,"lon":3.3145778},{"type":"node","id":6037556159,"lat":51.14157,"lon":3.3146421},{"type":"node","id":6037556160,"lat":51.1415557,"lon":3.3146975},{"type":"node","id":6037556161,"lat":51.1415541,"lon":3.3148416},{"type":"node","id":6037556162,"lat":51.1415551,"lon":3.3149739},{"type":"node","id":6037556163,"lat":51.1415802,"lon":3.3150635},{"type":"node","id":1494027343,"lat":51.1410607,"lon":3.3204128},{"type":"node","id":1494027365,"lat":51.141078,"lon":3.3193848},{"type":"node","id":1494027369,"lat":51.1410588,"lon":3.3212214},{"type":"node","id":1494027380,"lat":51.1410813,"lon":3.317924},{"type":"node","id":6037556105,"lat":51.141131,"lon":3.31628},{"type":"node","id":6037556106,"lat":51.1411581,"lon":3.3165005},{"type":"node","id":6037556107,"lat":51.141174,"lon":3.3167222},{"type":"node","id":6037556108,"lat":51.1411155,"lon":3.3169939},{"type":"node","id":6037556109,"lat":51.1410508,"lon":3.3221866},{"type":"node","id":6037556110,"lat":51.1410676,"lon":3.3223383},{"type":"node","id":6037556164,"lat":51.1415792,"lon":3.3164565},{"type":"node","id":6037556165,"lat":51.141573,"lon":3.3172357},{"type":"node","id":6037556166,"lat":51.1415771,"lon":3.3182023},{"type":"node","id":6037556167,"lat":51.1415495,"lon":3.3182625},{"type":"node","id":6037556168,"lat":51.1415495,"lon":3.3185605},{"type":"node","id":6037556169,"lat":51.1415684,"lon":3.3186069},{"type":"node","id":6037556170,"lat":51.1415633,"lon":3.3207654},{"type":"node","id":6037556171,"lat":51.1415444,"lon":3.3214131},{"type":"node","id":6037556172,"lat":51.1415097,"lon":3.3218544},{"type":"node","id":6037556173,"lat":51.1414642,"lon":3.3225703},{"type":"node","id":1493821404,"lat":51.1410663,"lon":3.3233361},{"type":"node","id":1494027355,"lat":51.1410465,"lon":3.3227899},{"type":"node","id":1801373604,"lat":51.1410713,"lon":3.3237592},{"type":"node","id":1951759314,"lat":51.1411466,"lon":3.3245554},{"type":"node","id":2474247506,"lat":51.1411643,"lon":3.3245589},{"type":"node","id":6037556111,"lat":51.1410551,"lon":3.3241916},{"type":"node","id":6037556112,"lat":51.1410504,"lon":3.3243751},{"type":"node","id":6037556118,"lat":51.1410331,"lon":3.3245183},{"type":"node","id":6037556120,"lat":51.1411823,"lon":3.3245635},{"type":"node","id":6037556174,"lat":51.1414121,"lon":3.3230419},{"type":"node","id":6037556175,"lat":51.1413953,"lon":3.3230745},{"type":"node","id":6037556176,"lat":51.1413682,"lon":3.323164},{"type":"node","id":6037556177,"lat":51.1413426,"lon":3.3233187},{"type":"node","id":6037556178,"lat":51.1413353,"lon":3.3234317},{"type":"node","id":6037556179,"lat":51.1413527,"lon":3.3235128},{"type":"node","id":6037556180,"lat":51.141294,"lon":3.3239374},{"type":"node","id":3702878648,"lat":51.1401344,"lon":3.3337214},{"type":"node","id":3702878654,"lat":51.1395918,"lon":3.3338166},{"type":"node","id":3702926557,"lat":51.1404241,"lon":3.333592},{"type":"node","id":3702926558,"lat":51.1406229,"lon":3.3335608},{"type":"node","id":3702926559,"lat":51.1406259,"lon":3.3336496},{"type":"node","id":3702926560,"lat":51.1404301,"lon":3.333676},{"type":"node","id":3702926561,"lat":51.1403789,"lon":3.3336784},{"type":"node","id":3702926562,"lat":51.1403729,"lon":3.3335752},{"type":"node","id":3702926563,"lat":51.1403021,"lon":3.333592},{"type":"node","id":3702926564,"lat":51.1402991,"lon":3.3335295},{"type":"node","id":3702926565,"lat":51.1402253,"lon":3.3335392},{"type":"node","id":3702926566,"lat":51.1402283,"lon":3.3336112},{"type":"node","id":3702926567,"lat":51.1401304,"lon":3.3336285},{"type":"node","id":3702926568,"lat":51.1400111,"lon":3.3337421},{"type":"node","id":3702956173,"lat":51.1406298,"lon":3.3321023},{"type":"node","id":3702956174,"lat":51.140115,"lon":3.3325162},{"type":"node","id":3702956175,"lat":51.1400702,"lon":3.3323734},{"type":"node","id":3702956176,"lat":51.1405896,"lon":3.3319784},{"type":"node","id":3702969714,"lat":51.1404452,"lon":3.3324432},{"type":"node","id":3702969715,"lat":51.1402175,"lon":3.3326312},{"type":"node","id":3702969716,"lat":51.1401965,"lon":3.3325686},{"type":"node","id":3702969717,"lat":51.1404269,"lon":3.3323835},{"type":"node","id":7713176909,"lat":51.1387744,"lon":3.3335489},{"type":"node","id":7713176910,"lat":51.1389364,"lon":3.3334306},{"type":"node","id":7713176911,"lat":51.1387319,"lon":3.3327211},{"type":"node","id":7713176912,"lat":51.1385501,"lon":3.332864},{"type":"node","id":8292789053,"lat":51.1400165,"lon":3.3338082},{"type":"node","id":8292789054,"lat":51.1396286,"lon":3.333874},{"type":"node","id":8378097124,"lat":51.140324,"lon":3.3355884},{"type":"node","id":8378097125,"lat":51.1403179,"lon":3.3355055},{"type":"node","id":8378097126,"lat":51.1406041,"lon":3.3354515},{"type":"node","id":8378097127,"lat":51.1406102,"lon":3.3355344},{"type":"node","id":8378097131,"lat":51.14074,"lon":3.3354785},{"type":"node","id":8378097132,"lat":51.1407879,"lon":3.3354717},{"type":"node","id":8378097133,"lat":51.1407993,"lon":3.3356206},{"type":"node","id":1317838317,"lat":51.1372361,"lon":3.338639},{"type":"node","id":1317838328,"lat":51.1369619,"lon":3.3386232},{"type":"node","id":1317838331,"lat":51.1371806,"lon":3.3384037},{"type":"node","id":1384096112,"lat":51.1371794,"lon":3.3384971},{"type":"node","id":1625199827,"lat":51.1408446,"lon":3.3375722},{"type":"node","id":1625199950,"lat":51.1407563,"lon":3.3373232},{"type":"node","id":3227068446,"lat":51.1369433,"lon":3.3387663},{"type":"node","id":3227068456,"lat":51.1371252,"lon":3.3388226},{"type":"node","id":3227068565,"lat":51.1371943,"lon":3.3389942},{"type":"node","id":3227068568,"lat":51.1372698,"lon":3.3389467},{"type":"node","id":6227395991,"lat":51.1392741,"lon":3.3367141},{"type":"node","id":6227395992,"lat":51.1392236,"lon":3.3367356},{"type":"node","id":6227395993,"lat":51.139313,"lon":3.3369193},{"type":"node","id":6227395997,"lat":51.1392584,"lon":3.3369405},{"type":"node","id":6414352053,"lat":51.1374056,"lon":3.3395184},{"type":"node","id":6414352054,"lat":51.1371278,"lon":3.3390236},{"type":"node","id":6414352055,"lat":51.1372589,"lon":3.3395769},{"type":"node","id":6414374315,"lat":51.1369166,"lon":3.338648},{"type":"node","id":6414374316,"lat":51.1369683,"lon":3.3388767},{"type":"node","id":6414374317,"lat":51.1370053,"lon":3.3388543},{"type":"node","id":6414374318,"lat":51.1371169,"lon":3.3387872},{"type":"node","id":6414374319,"lat":51.1371271,"lon":3.3388309},{"type":"node","id":6414374320,"lat":51.137238,"lon":3.3387628},{"type":"node","id":6414374321,"lat":51.1372074,"lon":3.338651},{"type":"node","id":6414383775,"lat":51.1407766,"lon":3.3373855},{"type":"node","id":6416001161,"lat":51.1371631,"lon":3.3390024},{"type":"node","id":7274233390,"lat":51.1372936,"lon":3.3395562},{"type":"node","id":7274233391,"lat":51.137309,"lon":3.3396231},{"type":"node","id":7274233395,"lat":51.1374325,"lon":3.3396124},{"type":"node","id":7274233396,"lat":51.137422,"lon":3.3395803},{"type":"node","id":7274233397,"lat":51.1373776,"lon":3.3396587},{"type":"node","id":8279842668,"lat":51.1371603,"lon":3.3384139},{"type":"node","id":8377691836,"lat":51.1409346,"lon":3.337164},{"type":"node","id":8378081366,"lat":51.140887,"lon":3.3372065},{"type":"node","id":8378081386,"lat":51.1407701,"lon":3.3373106},{"type":"node","id":8378081429,"lat":51.1408204,"lon":3.3372657},{"type":"node","id":8378097128,"lat":51.1407837,"lon":3.3359331},{"type":"node","id":8378097129,"lat":51.1407736,"lon":3.3358962},{"type":"node","id":8378097130,"lat":51.1407627,"lon":3.3358224},{"type":"node","id":8378097134,"lat":51.1408355,"lon":3.3359157},{"type":"node","id":1625199938,"lat":51.1411535,"lon":3.3372917},{"type":"node","id":1625199951,"lat":51.1410675,"lon":3.3370397},{"type":"node","id":6100803125,"lat":51.1672329,"lon":3.3331872},{"type":"node","id":6100803128,"lat":51.1672258,"lon":3.3333568},{"type":"node","id":2577910530,"lat":51.1685713,"lon":3.3356917},{"type":"node","id":2577910542,"lat":51.1681925,"lon":3.3356582},{"type":"node","id":2577910543,"lat":51.1685972,"lon":3.3356499},{"type":"node","id":3645188881,"lat":51.1679055,"lon":3.3337545},{"type":"node","id":6100803124,"lat":51.1673065,"lon":3.3331116},{"type":"node","id":6100803126,"lat":51.1672788,"lon":3.3336938},{"type":"node","id":6100803127,"lat":51.1672758,"lon":3.3333629},{"type":"node","id":6100803129,"lat":51.1675567,"lon":3.3331312},{"type":"node","id":6100803130,"lat":51.1675525,"lon":3.3333096},{"type":"node","id":6100803131,"lat":51.1679171,"lon":3.3333454},{"type":"node","id":2577910520,"lat":51.1681983,"lon":3.3360484},{"type":"node","id":2577910526,"lat":51.1687824,"lon":3.3362878},{"type":"node","id":2577910545,"lat":51.16885,"lon":3.3360431},{"type":"node","id":6145151107,"lat":51.1694008,"lon":3.3386946},{"type":"node","id":6145151108,"lat":51.1688319,"lon":3.3385737},{"type":"node","id":6145151109,"lat":51.1688258,"lon":3.3386467},{"type":"node","id":6145151110,"lat":51.1693942,"lon":3.3387681},{"type":"node","id":6145151114,"lat":51.1691188,"lon":3.3387104},{"type":"node","id":6145151115,"lat":51.1688569,"lon":3.3386537},{"type":"node","id":6418533335,"lat":51.1685948,"lon":3.3361624},{"type":"node","id":3190107371,"lat":51.1741471,"lon":3.3384365},{"type":"node","id":3190107374,"lat":51.1741746,"lon":3.3388275},{"type":"node","id":3190107377,"lat":51.1741968,"lon":3.3384276},{"type":"node","id":3190107393,"lat":51.1743618,"lon":3.3383982},{"type":"node","id":3190107400,"lat":51.1744043,"lon":3.3384036},{"type":"node","id":3190107407,"lat":51.1744809,"lon":3.3386827},{"type":"node","id":3190107408,"lat":51.1744875,"lon":3.3387716},{"type":"node","id":3190107415,"lat":51.1746495,"lon":3.3386505},{"type":"node","id":3190107416,"lat":51.1746548,"lon":3.3387211},{"type":"node","id":3190107420,"lat":51.1747424,"lon":3.3387044},{"type":"node","id":3190107423,"lat":51.1747681,"lon":3.3390477},{"type":"node","id":3190107424,"lat":51.1747706,"lon":3.3384763},{"type":"node","id":3190107428,"lat":51.1747993,"lon":3.3384858},{"type":"node","id":3190107432,"lat":51.1748198,"lon":3.3387594},{"type":"node","id":3190107435,"lat":51.1750772,"lon":3.3389888},{"type":"node","id":3190107439,"lat":51.1752356,"lon":3.3387751},{"type":"node","id":3190107442,"lat":51.1752492,"lon":3.338956},{"type":"node","id":7390697534,"lat":51.1297479,"lon":3.3578326},{"type":"node","id":7390697550,"lat":51.1297706,"lon":3.3588263},{"type":"node","id":7468171405,"lat":51.1279967,"lon":3.3559306},{"type":"node","id":7468171406,"lat":51.1288847,"lon":3.3598888},{"type":"node","id":7468171407,"lat":51.1288383,"lon":3.3606949},{"type":"node","id":7468171408,"lat":51.128796,"lon":3.3619912},{"type":"node","id":7468171422,"lat":51.1285744,"lon":3.3574498},{"type":"node","id":7468171423,"lat":51.1288319,"lon":3.3586353},{"type":"node","id":7468171426,"lat":51.1287158,"lon":3.3579031},{"type":"node","id":7468171428,"lat":51.1288787,"lon":3.3588438},{"type":"node","id":7468171429,"lat":51.1288942,"lon":3.3595607},{"type":"node","id":7468171431,"lat":51.1288954,"lon":3.3592459},{"type":"node","id":7468171433,"lat":51.1287831,"lon":3.3582062},{"type":"node","id":7468171444,"lat":51.1287924,"lon":3.361646},{"type":"node","id":7727393197,"lat":51.1288566,"lon":3.3555067},{"type":"node","id":7727393198,"lat":51.1292196,"lon":3.356551},{"type":"node","id":7727393199,"lat":51.129399,"lon":3.3566378},{"type":"node","id":7190873584,"lat":51.1287267,"lon":3.3682604},{"type":"node","id":7190927785,"lat":51.1287057,"lon":3.3681343},{"type":"node","id":7190927786,"lat":51.1287121,"lon":3.3673045},{"type":"node","id":7190927787,"lat":51.1286419,"lon":3.3641562},{"type":"node","id":7190927788,"lat":51.1286407,"lon":3.3644331},{"type":"node","id":7190927789,"lat":51.128655,"lon":3.3650286},{"type":"node","id":7190927790,"lat":51.128688,"lon":3.3661227},{"type":"node","id":7190927791,"lat":51.1286681,"lon":3.3635132},{"type":"node","id":7190927792,"lat":51.1286863,"lon":3.3631709},{"type":"node","id":7190927793,"lat":51.1286419,"lon":3.3639077},{"type":"node","id":7468171409,"lat":51.1288502,"lon":3.3621534},{"type":"node","id":7468171410,"lat":51.1288454,"lon":3.3623212},{"type":"node","id":7468171411,"lat":51.1287924,"lon":3.36282},{"type":"node","id":7468171412,"lat":51.1287335,"lon":3.363023},{"type":"node","id":7468171413,"lat":51.1286942,"lon":3.363003},{"type":"node","id":7602692242,"lat":51.1287128,"lon":3.3675239},{"type":"node","id":7727393200,"lat":51.129492,"lon":3.3624712},{"type":"node","id":7727393201,"lat":51.1294385,"lon":3.3629631},{"type":"node","id":7727393202,"lat":51.1293629,"lon":3.3638402},{"type":"node","id":7727393203,"lat":51.1293586,"lon":3.3662748},{"type":"node","id":7727393204,"lat":51.1292824,"lon":3.3662748},{"type":"node","id":7727393205,"lat":51.1292881,"lon":3.3667997},{"type":"node","id":7727393206,"lat":51.1293315,"lon":3.3682391},{"type":"node","id":7190873576,"lat":51.1287907,"lon":3.36923},{"type":"node","id":7190873577,"lat":51.1289144,"lon":3.369348},{"type":"node","id":7190873578,"lat":51.1288472,"lon":3.3692931},{"type":"node","id":7190873582,"lat":51.1287752,"lon":3.3691898},{"type":"node","id":7468171450,"lat":51.1287442,"lon":3.3685677},{"type":"node","id":7468171451,"lat":51.1290764,"lon":3.3693851},{"type":"node","id":7468171455,"lat":51.1289835,"lon":3.3693823},{"type":"node","id":7727393207,"lat":51.1293768,"lon":3.368773},{"type":"node","id":7727393208,"lat":51.1293116,"lon":3.3692219},{"type":"node","id":7727393209,"lat":51.1293718,"lon":3.368916},{"type":"node","id":7727393210,"lat":51.1292845,"lon":3.3692843},{"type":"node","id":7727393211,"lat":51.1292517,"lon":3.3693264},{"type":"node","id":7727393212,"lat":51.1291932,"lon":3.3693491},{"type":"node","id":8781449489,"lat":51.1293725,"lon":3.3688971},{"type":"way","id":640979978,"nodes":[6037556099,6037556100,6037556101,6037556102,6037556103,1951759298,6037556128,6037556129,6037556130,6037556131,6037556132,6037556133,6037556134,6037556135,6037556136,6037556137,6037556138,6037556139,6037556140,6037556141,6037556142,6037556143,6037556144,6037556145,6037556148,6037556146,6037556149,6037556150,6037556151,6037556152,6037556153,6037556154,6037556155,6037556156,6037556157,6037556158,6037556159,6037556160,6037556161,6037556162,6037556163,6037556164,6037556165,6037556166,6037556167,6037556168,6037556169,6037556170,6037556171,6037556172,6037556173,6037556174,6037556175,6037556176,6037556177,6037556178,6037556179,6037556180,6037556120,2474247506,1951759314,6037556118]},{"type":"way","id":640979982,"nodes":[6037556099,1494027349,6037556104,1494027348,1494027341,1494027386,1494027376,1494027385,1494027359,1494027374,1494027389,1494027382,1494027372,1494027378,1494027361,1494027342,1494027353,1494027366,1494027373,1494027346,1494027368,6037556098,6037556105,6037556106,6037556107,6037556108,1494027380,1494027365,1494027343,1494027369,6037556109,6037556110,1494027355,1493821404,1801373604,6037556111,6037556112,6037556118]},{"type":"way","id":184402325,"nodes":[1948835900,416917603,416917605,1948835986,416917609,1948836072,1948836068,1948836093,1948836104,1948836209,1948836202,1948836218,1948836237,1948836277,416917612,1948836149,1948836096,1948835950]},{"type":"way","id":184402326,"nodes":[1948835900,1948835842,1948835662]},{"type":"way","id":314899865,"nodes":[2026541851,2026541846,2026541843,2026541841,2026541837,3209560116,3210389695,3209560114,3209560115,3209560117,3209560118,3209560119,3209560121,3209560124,3209560126,3209560127,3209560131,3209560132,3209560134,3209560135,3209560136,3209560138]},{"type":"way","id":315041273,"nodes":[1554514739,1554514640,3211247042,1554514831,1554514750,1554514755,5962496715,1554514658,5962338038,1554514618,5962444841,1554514806,5962340003,8497007481,5962414276,5962415500,5962415499,5962415498,5962415538,5962415543,3211247331,3211247328,3211247291,5962444849,5962444850,5962340009,5962444846,5962340010,3211247059,5962340012,5962340011,3211247266,3211247261,5962496718,3211247058,5962496719,3211247054,3211247265,5962340013,3211247060,5962415564,5962415565]},{"type":"way","id":606165130,"nodes":[5747937641,5747937642,5747937643,5747937644,5747937645,5747937646,5747937647,5747937648,5747937649,5747937650,5747937651,5747937652,5747937653,5747937654,5747937655,5747937656,5747937657,5747937658,5747937659,5747535101,5745963942,5745963943,5745963944,5745963946,3162627509,5745963947,5747937668,5747937669,5747937670,5747937671,5747937672,5747937673,5747937674,5747937675,5747937676,5747937677,5747937678,5747937679,5747937680,5747937681,5747937682,5747937683,5747937684,5747937685,5747937686,5747937687,5747937688,5747937689,5747937690,5747937691,5747937641]},{"type":"way","id":184402332,"nodes":[668981668,416917618,1815081998,668981667,1948835950]},{"type":"way","id":184402334,"nodes":[6206789688,1948835742,668981668]},{"type":"way","id":314956402,"nodes":[2026541851,3209560139,3209560138]},{"type":"way","id":663050030,"nodes":[1948835662,6206789688]},{"type":"way","id":631371232,"nodes":[3211247019,5962496725]},{"type":"way","id":631377344,"nodes":[5962496725,3211247021]},{"type":"way","id":655652321,"nodes":[6142727588,6143074993,6142727589,6142727598,6142727590,6142725081,6142725080,6142725079,6142725078,6142725077,6142725076,6142725074,6142725084,6142727586,6142727585,6142727587,6142727591,6142727592,5745963922,6142727588]},{"type":"way","id":631371231,"nodes":[3211247019,3211247024]},{"type":"way","id":631371234,"nodes":[3211247013,3211247021]},{"type":"way","id":631377343,"nodes":[1554514739,1554514735,1554514744,1554514811,5962339921,1554514655,1554514679,1554514683,1554514765,1554514775,1554514773,1554514747,1554514730,1554514647,1554514789,1554514649,1554514682,1554514787,1554514661,1554514726,1554514693,1554514703,1554514783]},{"type":"way","id":655652319,"nodes":[6142725039,6142725040,8638721239,8638721230,6142725041,6142725042,6142725043,6142725044,6142725045,6142725046,6142725047,6142725048,6142725049,6142725050,6142725051,6142725052,6142725053,6142725054,6142725055,6142725056,6142725057,6142725058,6142725059,6142725060,6142725061,6142725064,6142727594,6142727595,6142727596,6143075018,6142725067,6142725066,6142725065,6143075014,3162627482,6142727597,6142725039]},{"type":"way","id":315041261,"nodes":[3211247039,3211247036]},{"type":"way","id":315041263,"nodes":[3211247032,3211247029,3211247024]},{"type":"way","id":631371223,"nodes":[5962415565,3211247039]},{"type":"way","id":631371228,"nodes":[3211247034,3211247032]},{"type":"way","id":631377341,"nodes":[3211247036,3211247037,3211247034]},{"type":"way","id":631371236,"nodes":[3211247013,3211247010,3211247008,3211247004,3211246997,5962338070,9284562682,5962338069,5962338071,3211246995]},{"type":"way","id":631371237,"nodes":[3211246995,3211246555,3211246542,3203029856,7727406921,1554514783]}]} + ) + + + +} + + +describe("GenerateCache", () => { + + it("should generate a cached file for the Natuurpunt-theme", async () => { + if (existsSync("/tmp/np-cache")) { + ScriptUtils.readDirRecSync("/tmp/np-cache").forEach(p => unlinkSync(p)) + rmdirSync("/tmp/np-cache") + } + mkdirSync("/tmp/np-cache") + initDownloads( + "(nwr%5B%22amenity%22%3D%22toilets%22%5D%3Bnwr%5B%22amenity%22%3D%22parking%22%5D%3Bnwr%5B%22amenity%22%3D%22bench%22%5D%3Bnwr%5B%22id%22%3D%22location_track%22%5D%3Bnwr%5B%22id%22%3D%22gps%22%5D%3Bnwr%5B%22information%22%3D%22board%22%5D%3Bnwr%5B%22leisure%22%3D%22picnic_table%22%5D%3Bnwr%5B%22man_made%22%3D%22watermill%22%5D%3Bnwr%5B%22user%3Ahome%22%3D%22yes%22%5D%3Bnwr%5B%22user%3Alocation%22%3D%22yes%22%5D%3Bnwr%5B%22leisure%22%3D%22nature_reserve%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22boundary%22%3D%22protected_area%22%5D%5B%22protect_class%22!~%22%5E98%24%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22information%22%3D%22visitor_centre%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22information%22%3D%22office%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22route%22~%22%5E.*foot.*%24%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22route%22~%22%5E.*hiking.*%24%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22route%22~%22%5E.*bycicle.*%24%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22route%22~%22%5E.*horse.*%24%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22leisure%22%3D%22bird_hide%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22amenity%22%3D%22drinking_water%22%5D%5B%22access%22!~%22%5Epermissive%24%22%5D%5B%22access%22!~%22%5Eprivate%24%22%5D%3B)%3Bout%20body%3Bout%20meta%3B%3E%3Bout%20skel%20qt%3B" + ); + await main([ + "natuurpunt", + "12", + "/tmp/np-cache", + "51.15423567022531", "3.250579833984375", "51.162821593316934", "3.262810707092285", + "--generate-point-overview", "nature_reserve,visitor_information_centre" + ]) + await ScriptUtils.sleep(100) + const birdhides = JSON.parse(readFileSync("/tmp/np-cache/natuurpunt_birdhide_12_2085_1368.geojson", "UTF8")) + expect(birdhides.features.length).deep.equal(5) + expect(birdhides.features.some(f => f.properties.id === "node/5158056232"), "Didn't find birdhide node/5158056232 ").true + + }) +}) diff --git a/tests/testhooks.ts b/test/testhooks.ts similarity index 100% rename from tests/testhooks.ts rename to test/testhooks.ts diff --git a/tests/scripts/GenerateCache.spec.ts b/tests/scripts/GenerateCache.spec.ts deleted file mode 100644 index e24a72d692..0000000000 --- a/tests/scripts/GenerateCache.spec.ts +++ /dev/null @@ -1,51 +0,0 @@ -import {describe} from 'mocha' -import {expect} from 'chai' -import {Utils} from "../../Utils"; -import {existsSync, mkdirSync, readFileSync, rmdirSync, unlinkSync} from "fs"; -import ScriptUtils from "../../scripts/ScriptUtils"; -import {main} from "../../scripts/generateCache"; - - -function initDownloads(query: string){ - - - Utils.injectJsonDownloadForTests( - "https://overpass-api.de/api/interpreter?data=%5Bout%3Ajson%5D%5Btimeout%3A60%5D%5Bbbox%3A51.124212757826875%2C3.1640625%2C51.17934297928927%2C3.251953125%5D%3B"+query , - {"version":0.6,"generator":"Overpass API 0.7.57 93a4d346","osm3s":{"timestamp_osm_base":"2022-02-13T23:54:06Z","copyright":"The data included in this document is from www.openstreetmap.org. The data is made available under ODbL."},"elements":[{"type":"node","id":518224450,"lat":51.1548065,"lon":3.1880118,"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"street_side"}},{"type":"node","id":665418924,"lat":51.1575547,"lon":3.20522,"tags":{"amenity":"parking"}},{"type":"node","id":1168727903,"lat":51.1299141,"lon":3.1776123,"tags":{"amenity":"drinking_water","mapillary":"https://www.mapillary.com/app/?lat=51.129853685131906&lng=3.177603984688602&z=17&pKey=SEyKzIMUeKssni1ZLVe-9A&focus=photo&dateTo=2017-04-02&dateFrom=2017-04-01&x=0.5168826751181941&y=0.6114877557873634&zoom=0"}},{"type":"node","id":1168728245,"lat":51.1290938,"lon":3.1767502,"tags":{"amenity":"drinking_water","mapillary":"https://www.mapillary.com/app/?lat=51.129104406662464&lng=3.176675795895676&z=17&pKey=vSP3D_hWv3XCBtH75GnYUQ&focus=photo&dateTo=2017-04-02&dateFrom=2017-04-01"}},{"type":"node","id":1725842653,"lat":51.153364,"lon":3.2352655,"tags":{"amenity":"bench"}},{"type":"node","id":1744641290,"lat":51.1389321,"lon":3.2385407,"tags":{"amenity":"bench","backrest":"yes","material":"wood"}},{"type":"node","id":1746891135,"lat":51.1598841,"lon":3.2361425,"tags":{"amenity":"bench"}},{"type":"node","id":1810326078,"lat":51.1550855,"lon":3.2349358,"tags":{"amenity":"bench"}},{"type":"node","id":1810326092,"lat":51.1552302,"lon":3.234968,"tags":{"amenity":"bench"}},{"type":"node","id":2325437742,"lat":51.1770052,"lon":3.1967794,"tags":{"board_type":"board","information":"board","name":"Tillegembos","tourism":"information"}},{"type":"node","id":2325437743,"lat":51.1787363,"lon":3.1949036,"tags":{"board_type":"board","information":"board","name":"Tillegembos","tourism":"information"}},{"type":"node","id":2325437813,"lat":51.1733102,"lon":3.1895672,"tags":{"amenity":"bench","backrest":"yes","material":"wood"}},{"type":"node","id":2325437839,"lat":51.1763436,"lon":3.1984985,"tags":{"amenity":"bench","backrest":"yes","material":"wood"}},{"type":"node","id":2325437848,"lat":51.1770966,"lon":3.1963507,"tags":{"amenity":"bench","backrest":"yes","material":"wood"}},{"type":"node","id":2325437862,"lat":51.1773439,"lon":3.1948779,"tags":{"amenity":"bench","backrest":"yes","material":"wood"}},{"type":"node","id":2325437867,"lat":51.1775994,"lon":3.1888088,"tags":{"amenity":"bench","backrest":"yes","material":"wood"}},{"type":"node","id":2325437873,"lat":51.1778384,"lon":3.1913802,"tags":{"amenity":"bench","backrest":"yes","material":"wood"}},{"type":"node","id":2732486257,"lat":51.129741,"lon":3.1907419,"tags":{"board_type":"nature","information":"board","name":"Doeveren","tourism":"information"}},{"type":"node","id":3774054068,"lat":51.1586662,"lon":3.2271102,"tags":{"amenity":"bench"}},{"type":"node","id":4769106605,"lat":51.138264,"lon":3.1798655,"tags":{"backrest":"yes","leisure":"picnic_table"}},{"type":"node","id":4912238707,"lat":51.1448634,"lon":3.2455986,"tags":{"access":"yes","amenity":"parking","fee":"no","name":"Oostkamp","parking":"Carpool"}},{"type":"node","id":5637212235,"lat":51.1305439,"lon":3.1866873,"tags":{"board_type":"nature","image":"https://i.imgur.com/HehOQL9.jpg","information":"board","name":"Welkom Doeveren","tourism":"information"}},{"type":"node","id":5637224573,"lat":51.1281084,"lon":3.1881726,"tags":{"board_type":"nature","information":"board","name":"Welkom Doeveren","tourism":"information"}},{"type":"node","id":5637230107,"lat":51.1280884,"lon":3.1889798,"tags":{"information":"board","tourism":"information"}},{"type":"node","id":5637743026,"lat":51.1295973,"lon":3.1751122,"tags":{"information":"board","name":"Doeveren Wandelroute","tourism":"information"}},{"type":"node","id":5716130103,"lat":51.1767183,"lon":3.1947867,"tags":{"amenity":"bench","backrest":"yes"}},{"type":"node","id":5745783208,"lat":51.1782581,"lon":3.2410111,"tags":{"amenity":"bench"}},{"type":"node","id":5745807545,"lat":51.1784037,"lon":3.2369439,"tags":{"amenity":"bench"}},{"type":"node","id":5745807551,"lat":51.1783278,"lon":3.236678,"tags":{"amenity":"bench"}},{"type":"node","id":6535241426,"lat":51.1693142,"lon":3.1673093,"tags":{"amenity":"bench"}},{"type":"node","id":6535241427,"lat":51.169265,"lon":3.1673159,"tags":{"amenity":"bench"}},{"type":"node","id":6535241428,"lat":51.1692199,"lon":3.1673224,"tags":{"amenity":"bench"}},{"type":"node","id":6535241430,"lat":51.1685726,"lon":3.1678225,"tags":{"bench":"yes","leisure":"picnic_table","material":"wood"}},{"type":"node","id":6536026827,"lat":51.1703142,"lon":3.1691109,"tags":{"leisure":"picnic_table"}},{"type":"node","id":6536026828,"lat":51.1702795,"lon":3.1691552,"tags":{"leisure":"picnic_table"}},{"type":"node","id":6712112244,"lat":51.1595064,"lon":3.2021482,"tags":{"leisure":"picnic_table"}},{"type":"node","id":7304050040,"lat":51.1560908,"lon":3.1748919,"tags":{"amenity":"bench"}},{"type":"node","id":7304050041,"lat":51.1560141,"lon":3.1749533,"tags":{"amenity":"bench"}},{"type":"node","id":7304050042,"lat":51.156032,"lon":3.1749379,"tags":{"amenity":"bench"}},{"type":"node","id":7439979218,"lat":51.1780402,"lon":3.2178666,"tags":{"amenity":"bench","backrest":"yes"}},{"type":"node","id":7439979219,"lat":51.1780508,"lon":3.2179033,"tags":{"amenity":"bench","backrest":"yes"}},{"type":"node","id":7529262982,"lat":51.1585566,"lon":3.1715528,"tags":{"board_type":"map","information":"board","tourism":"information"}},{"type":"node","id":7529262984,"lat":51.1585786,"lon":3.1715385,"tags":{"leisure":"picnic_table"}},{"type":"node","id":7554879668,"lat":51.1573713,"lon":3.2043731,"tags":{"access":"yes","amenity":"toilets","fee":"no","toilets:disposal":"flush","unisex":"yes","wheelchair":"yes"}},{"type":"node","id":7554879669,"lat":51.1594855,"lon":3.2021507,"tags":{"leisure":"picnic_table"}},{"type":"node","id":7556988723,"lat":51.1330234,"lon":3.1839944,"tags":{"amenity":"bench","material":"wood"}},{"type":"node","id":7575825326,"lat":51.1386553,"lon":3.1797358,"tags":{"amenity":"bench"}},{"type":"node","id":7575825327,"lat":51.1382456,"lon":3.1797422,"tags":{"information":"board","tourism":"information"}},{"type":"node","id":8109498958,"lat":51.1332267,"lon":3.2341272,"tags":{"amenity":"bench","backrest":"yes"}},{"type":"node","id":8109498959,"lat":51.1335011,"lon":3.2343954,"tags":{"leisure":"picnic_table"}},{"type":"node","id":8198894646,"lat":51.125688,"lon":3.1856217,"tags":{"image":"https://i.imgur.com/O5kX20u.jpg","information":"board","tourism":"information"}},{"type":"node","id":8199012519,"lat":51.1262245,"lon":3.1802429,"tags":{"image":"https://i.imgur.com/tomw9p5.jpg","information":"board","tourism":"information"}},{"type":"node","id":8199244816,"lat":51.1252874,"lon":3.1837622,"tags":{"amenity":"bench"}},{"type":"node","id":8199301617,"lat":51.1256827,"lon":3.1853543,"tags":{"amenity":"bench","backrest":"no"}},{"type":"node","id":8255488518,"lat":51.1406698,"lon":3.235178,"tags":{"amenity":"bench","backrest":"yes"}},{"type":"node","id":9316104741,"lat":51.1330984,"lon":3.2335257,"tags":{"information":"board","tourism":"information"}},{"type":"node","id":9442532340,"lat":51.1763651,"lon":3.1947952,"tags":{"amenity":"bench","backrest":"yes","image":"https://i.imgur.com/eZ0Loii.jpg"}},{"type":"way","id":15242261,"nodes":[150996092,150996093,6754312552,6754312553,6754312550,6754312551,150996094,150996095,150996097,150996098,6754312560,6754312559,6754312558,150996099,6754312557,150996100,6754312555,6754312556,150996101,6754312554,150996092],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":16514228,"nodes":[170464837,170464839,170464840,170464841,170464837],"tags":{"access":"yes","amenity":"parking","fee":"no","maxstay":"4 hours","parking":"surface"}},{"type":"way","id":76706071,"nodes":[903903386,1038557094,1038557233,1038557143,1038557075,903903387,1038557195,903903388,903903390,903904576,903903386],"tags":{"access":"permissive","amenity":"parking"}},{"type":"way","id":89601157,"nodes":[1038557083,1038557078,1038557104,1038557072,1038557108,1038557230,1038557227,1038557102,1038557137,1038575040,1038557191,1038557014,6960473080,1038557035,1038557012,1038557083],"tags":{"amenity":"parking"}},{"type":"way","id":89604999,"nodes":[1038583404,1038583491,1038583375,1038583483,1038583479,1038583398,1038583459,1038583456,1038583446,1038583441,1038583425,1038583501,1038583451,1038583463,1038583476,1038583404],"tags":{"access":"yes","amenity":"parking","capacity":"57","carpool":"yes","description":"carpoolparking","fee":"no","name":"Loppem","parking":"surface"}},{"type":"way","id":92035679,"nodes":[1069177920,6853179264,1069177925,1069177919,6853179269,6853179268,6853179267,6853179215,6853179213,6853179214,1069178133,1069177984,6853179230,6853179228,6853179229,6853179224,6853179225,6853179227,6853179226,6853179216,6853179220,6853179219,6853179218,6853179217,6853179223,6853179221,6853179222,1069177967,1069177852,6853179211,6853179212,6853179210,6853179327,6853179208,6853179209,6853179203,1069177976,6853179207,6853179206,6853179205,6853179204,6853179202,1069177849,6852012579,6852012578,6852012580,6852012577,6852012581,6852012582,6852012583,1069177845,1759437085,1519342743,1519342742,1069178166,1069177853,1069177915,6853179235,6853179234,6853179236,1069177933,6853179237,6853179238,1069178021,6853179246,6853179244,6853179245,6853179240,6853179243,6853179241,6853179242,6853179239,6853179248,6853179249,6853179250,6853179247,1069177873,6853179262,6853179263,6853179260,6853179261,6853179256,6853179259,6853179257,6853179258,1069177920],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":101248451,"nodes":[1168728158,1168728325,1168728159,5637669355,1168728109,1168728158],"tags":{"access":"private","amenity":"parking","name":"Parking Merkenveld"}},{"type":"way","id":101248462,"nodes":[1168727876,1168728288,1168728412,1168728208,1168727876],"tags":{"amenity":"toilets","building":"yes","source:geometry:date":"2019-03-14","source:geometry:ref":"Gbg/6588148"}},{"type":"way","id":131622387,"nodes":[1448421093,1448421099,1448421091,1448421081,1448421093],"tags":{"amenity":"parking","name":"Tudor - Zeeweg","parking":"surface"}},{"type":"way","id":145691934,"nodes":[1590642859,1590642860,1590642858,1590642849,1590642859],"tags":{"amenity":"parking"}},{"type":"way","id":145691937,"nodes":[1590642829,1590642828,1590642830,1590642832,1590642829],"tags":{"amenity":"parking"}},{"type":"way","id":158901716,"nodes":[1710245713,1710245718,1710245707,1710245705,1710245703,1710245715,1710245711,1710245709,1710245701,1710245713],"tags":{"access":"yes","amenity":"parking","capacity":"14","fee":"no","parking":"surface"}},{"type":"way","id":158904558,"nodes":[1710262742,1710262745,1710262735,1710262733,1710262732,1710262743,1710262741,1710262739,1710262744,1710262737,1710262736,1710262731,1710262738,1710262742],"tags":{"access":"yes","alt_name":"Schoolparking","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":158906028,"nodes":[1710276259,1710276251,1810330766,1710276255,1710276261,1710276240,1710276232,1710276257,1710276243,1710276253,1810347217,1710276242,1710276259],"tags":{"access":"yes","amenity":"parking","fee":"no","name":"Parking Sportcentrum De Valkaart","parking":"surface"}},{"type":"way","id":160825858,"nodes":[1728421375,1728421374,1728421379,1728421377,1728421376,1728421378,1728421375],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":162602213,"nodes":[1920143232,7393009684,7393048385,1744641293,1523513488,1744641292,1920143232],"tags":{"amenity":"parking","capacity":"15"}},{"type":"way","id":165489167,"nodes":[4912197370,4912197365,4912197373,4912197364,4912197372,1770289505,4912197362,4912197371,4912197374,4912197363,4912197368,4912197366,4912197369,4912197367,4912197370],"tags":{"access":"yes","amenity":"parking","fee":"no","name":"Bad Neuheimplein","parking":"surface"}},{"type":"way","id":168291852,"nodes":[1795793399,4979389763,1795793409,1795793395,1795793393,1795793397,1795793407,1795793406,1795793408,1795793405,1795793399],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":169875513,"nodes":[1810345951,1810345955,1810345947,1810345944,1810345951],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":170015605,"nodes":[1811673425,1811673421,1811673418,1811673423,1811673425],"tags":{"access":"private","amenity":"parking","name":"gheeraert E40","operator":"Gheeraert"}},{"type":"way","id":170018487,"nodes":[1811699779,1811699778,1811699776,1811699777,1811699779],"tags":{"access":"private","amenity":"parking","name":"Gheeraert vooraan"}},{"type":"way","id":170559194,"nodes":[1817319304,1817319302,1817319297,1817319301,1817319304],"tags":{"access":"private","amenity":"parking","name":"Gheeraert laadkade"}},{"type":"way","id":170559195,"nodes":[1817319299,1817319303,1817319300,1817319292,1817319299],"tags":{"access":"private","amenity":"parking","name":"Gheeraert spoorweg trailers"}},{"type":"way","id":170559196,"nodes":[1817319293,1817319289,1817319291,1817319296,1817319293],"tags":{"access":"private","amenity":"parking","name":"Gheeraert spoorweg trucks"}},{"type":"way","id":170559197,"nodes":[1817319294,1817319298,1817319295,1817319290,1817319294],"tags":{"access":"private","amenity":"parking","name":"Gheeraert zijkant"}},{"type":"way","id":170559292,"nodes":[1817320496,1817320494,1817320493,1817320495,1817320496],"tags":{"access":"private","amenity":"parking","name":"Gheeraert vooraan gebouw"}},{"type":"way","id":170559832,"nodes":[1817324515,1817324509,1817324491,6397031888,4044172008,4044172003,4044171997,4044171962,4044171957,4044171976,1817324489,1817324488,3550860268,1817324505,3550860269,1817324513,1817324515],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":223674368,"nodes":[2325437844,8191691971,8191691973,8191691972,2325437840,8191691970,414025563,2325437844],"tags":{"amenity":"parking","name":"Tillegembos","parking":"surface"}},{"type":"way","id":237214948,"nodes":[2451574741,2451574742,2451574744,1015583939,2451574741],"tags":{"access":"private","amenity":"parking"}},{"type":"way","id":237214949,"nodes":[2451574748,2451574746,2451574747,2451574749,2451574748],"tags":{"access":"private","amenity":"parking"}},{"type":"way","id":237214950,"nodes":[2451569392,1015567837,2451574745,2451574743,2451578121,2451569392],"tags":{"access":"private","amenity":"parking"}},{"type":"way","id":325909586,"nodes":[3325315243,111759500,3325315247,3325315232,3325315230,3325315226,1169056712,3325315243],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":326834162,"nodes":[3335137807,3335137692,3335137795,9163493632,3335137802,3335137812,9163486855,9163486856,3335137823,3335137807],"tags":{"access":"customers","amenity":"parking","operator":"Best Western Weinebrugge","parking":"surface"}},{"type":"way","id":327849054,"nodes":[3346575929,3346575873,3346575876,3346575843,3346575845,3346575891,3346575901,3346575923,3346575928,3346575950,3346575929],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":327849055,"nodes":[3346575945,3346575946,3346575943,3346575933,3346575925,3346575917,3346575903,3346575908,3346575889,3346575886,3346575945],"tags":{"access":"customers","amenity":"parking","parking":"surface"}},{"type":"way","id":327849056,"nodes":[3346575865,3346575853,3346575855,3346575846,3346575840,3346575858,3346575865],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":374677860,"nodes":[3780611504,3780611502,3780611500,3780611503,3780611504],"tags":{"amenity":"parking"}},{"type":"way","id":374677861,"nodes":[3780611495,3780611493,3780611492,3780611494,3780611495],"tags":{"amenity":"parking"}},{"type":"way","id":374677862,"nodes":[3780611498,3780611497,3780611496,3780611499,3780611501,3780611498],"tags":{"amenity":"parking"}},{"type":"way","id":389912371,"nodes":[3930713440,3930713451,3930713447,3930713437,3930713440],"tags":{"amenity":"parking"}},{"type":"way","id":389912372,"nodes":[3930713454,3930713442,3930713435,3930713429,5826811614,3930713426,3930713430,6982605752,6982605754,3930713438,6982605769,6982605766,6982605767,6982605762,6982605764,3930713446,3930713454],"tags":{"access":"customers","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":401995684,"nodes":[4044171963,4044171954,4044171924,4044171936,4044171941,4044171963],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":500067820,"nodes":[4912203166,4912203165,4912203164,4912203163,4912203162,4912203161,4912203160,4912203166],"tags":{"access":"yes","amenity":"parking","parking":"surface"}},{"type":"way","id":500067821,"nodes":[4912203170,4912203169,4912203168,4912203167,4912203170],"tags":{"access":"yes","amenity":"parking","parking":"surface"}},{"type":"way","id":500067822,"nodes":[4912203174,4912203173,4912203172,4912203171,4912203174],"tags":{"access":"yes","amenity":"parking","parking":"surface"}},{"type":"way","id":500067823,"nodes":[4912203179,4912203178,4912203177,4912203176,4912203179],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":500069613,"nodes":[4912214695,4912214685,4912214694,4912214693,4912214692,4912214680,4912214695],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":500071452,"nodes":[4912225068,4912225062,4912225063,4912225053,4912225064,4912214694,4912214685,4912225068],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":500071455,"nodes":[4912225070,4912214681,4912214686,4912225052,4912225051,4912225067,4912225062,4912225068,4912225070],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":500071458,"nodes":[4912214695,4912214680,4912225069,4912225050,1525460846,4912214681,4912225070,4912214695],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":533276307,"nodes":[5173881316,5173881317,5173881318,7054196467,5173881316],"tags":{"amenity":"parking"}},{"type":"way","id":533276308,"nodes":[5173881320,5173881621,5173881622,5173881623,5173881320],"tags":{"amenity":"parking"}},{"type":"way","id":533276309,"nodes":[5173881624,5173881625,5173881626,5173881627,5173881624],"tags":{"amenity":"parking"}},{"type":"way","id":579848581,"nodes":[4043782112,5825400688,5552466020,6997096756,6997096759,6997096758,5552466018,5552466013,5552466014,6997076567,4043782112],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":584455569,"nodes":[5586765933,5586765934,5586765935,5586765936,5586765933],"tags":{"amenity":"parking"}},{"type":"way","id":585977870,"nodes":[5587844460,5599314384,5599314385,1659850846,6870850178,5587844462,5587844461,6870863414,5587844460],"tags":{"amenity":"parking"}},{"type":"way","id":587014342,"nodes":[5607796820,5607798725,5607798721,5607798722,5607796819,5607798723,5607796820],"tags":{"access":"permissive","amenity":"parking","park_ride":"no","parking":"surface","surface":"paved"}},{"type":"way","id":590167103,"nodes":[5635001277,5635001274,5635001275,5635001276,5635001277],"tags":{"amenity":"parking"}},{"type":"way","id":590167113,"nodes":[5635001312,5635001306,7767137237,7767137235,7767137236,7767137234,5635001312],"tags":{"amenity":"parking"}},{"type":"way","id":590167134,"nodes":[5635001374,5635001373,5635001372,5635001371,5635001374],"tags":{"amenity":"parking"}},{"type":"way","id":590167135,"nodes":[5635001378,5635001377,5635001376,5635001375,5635001378],"tags":{"amenity":"parking"}},{"type":"way","id":590167136,"nodes":[5635001382,5635001381,5635001380,5635001379,5635001382],"tags":{"amenity":"parking"}},{"type":"way","id":590167137,"nodes":[5635001386,5882873336,5882873337,5882873338,5882873335,6593340582,6593340583,5882873334,6593340584,5635001385,5635001384,5635001383,5635001386],"tags":{"amenity":"parking"}},{"type":"way","id":590167147,"nodes":[5635001417,5635001414,5635001415,5635001416,5635001417],"tags":{"amenity":"parking"}},{"type":"way","id":601406079,"nodes":[5716136617,5716136618,5716136619,5716136620,5716136617],"tags":{"amenity":"parking"}},{"type":"way","id":632813009,"nodes":[5974489618,1810326044,1810326087,5974489617,5972179348,5972179347,5972179346,5972179345,5972179344,5972179343,5972179331,5974489616,5974489615,5974489614,5974489618],"tags":{"amenity":"parking","name":"Gemeenteplein","parking":"surface"}},{"type":"way","id":668043297,"nodes":[6255587424,6255587425,6255587426,6255587427,6255587424],"tags":{"access":"private","amenity":"parking"}},{"type":"way","id":670104236,"nodes":[6275462768,6275462769,6275462770,6275462771,6275462768],"tags":{"amenity":"parking"}},{"type":"way","id":670104238,"nodes":[6275462772,6275462989,6275462773,6275462774,6275462775,6275462772],"tags":{"amenity":"parking"}},{"type":"way","id":670104239,"nodes":[6275462776,6275462777,6275462778,6275462779,6275462776],"tags":{"amenity":"parking"}},{"type":"way","id":670104241,"nodes":[6275462780,6275462781,6275462782,6275462783,6275462780],"tags":{"amenity":"parking"}},{"type":"way","id":670104242,"nodes":[6275462784,6275462985,6275462988,6275462986,6275462987,6275462784],"tags":{"amenity":"parking"}},{"type":"way","id":671840055,"nodes":[6291339827,6291339828,6291339816,6291339815,6291339822,6291339821,6291339829,6291339830,6291339827],"tags":{"amenity":"parking"}},{"type":"way","id":695825223,"nodes":[1519476746,6533893620,6533893621,6533893622,1519476797,1519476620,1519476746],"tags":{"access":"yes","amenity":"parking"}},{"type":"way","id":695825224,"nodes":[1519476744,6533893624,6533893625,6533893626,1519476698,1519476635,1519476744],"tags":{"access":"yes","amenity":"parking"}},{"type":"way","id":696040917,"nodes":[6536026850,6536026851,6536026852,6536026853,6536026850],"tags":{"amenity":"parking","name":"Kasteel Tudor"}},{"type":"way","id":696043218,"nodes":[6536038234,6536038235,6536038236,6536038237,6536038234],"tags":{"access":"customers","amenity":"parking"}},{"type":"way","id":700675991,"nodes":[6579962064,6579962065,6579962066,6579962068,6579962067,6579962064],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":705278707,"nodes":[6625037999,6625038000,6625038001,6625038002,6625038003,6004375826,6625038005,6625038006,6625037999],"tags":{"amenity":"parking"}},{"type":"way","id":719482833,"nodes":[6754312544,6754312543,6754312542,6754312541,6754312544],"tags":{"access":"yes","amenity":"parking","capacity":"5"}},{"type":"way","id":719482834,"nodes":[6754312565,6754312564,6754312563,6754312562,6754312565],"tags":{"access":"yes","amenity":"parking","capacity":"12"}},{"type":"way","id":737054013,"nodes":[5826811496,5826811497,5826811494,5826811495,5826811496],"tags":{"amenity":"parking"}},{"type":"way","id":737054014,"nodes":[5826810676,5826810673,5826810674,5826810675,5826810676],"tags":{"amenity":"parking"}},{"type":"way","id":737054015,"nodes":[5826810681,5826810678,5826810679,5826810680,5826810681],"tags":{"amenity":"parking"}},{"type":"way","id":737093410,"nodes":[5826811559,5826811536,5826811535,5826811561,5826811560,5826811559],"tags":{"access":"yes","amenity":"parking","capacity":"4","fee":"no","parking":"surface"}},{"type":"way","id":737093411,"nodes":[5826811551,5826811547,5826811548,5826811549,5826811550,5826811551],"tags":{"access":"yes","amenity":"parking","capacity":"4","fee":"no","parking":"surface"}},{"type":"way","id":739652949,"nodes":[6925536542,6925536541,6925536540,6925536539,6925536542],"tags":{"amenity":"parking","capacity":"6","parking":"surface"}},{"type":"way","id":741675236,"nodes":[6943148207,6943148206,6943148205,6943148204,1637742821,6943148203,6943148202,6943148201,6943148200,6943148199,6943148198,6943148197,6943148207],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":742295526,"nodes":[6949357909,6949357908,6949357907,6949357906,6949357909],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":742295527,"nodes":[6949357913,6949357912,6949357911,6949357910,6949357913],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":742295528,"nodes":[6949357917,6949357916,6949357915,6949357914,6949357917],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":742295529,"nodes":[6949357921,6949357920,6949357919,6949357918,6949357921],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":746170866,"nodes":[6982906547,6982906546,6982906545,6982906544,6982906543,6982906542,6982906547],"tags":{"access":"customers","amenity":"parking"}},{"type":"way","id":747880657,"nodes":[3325315397,6997076566,6997076565,6997076563,6997076562,6997076564,3325315395,3325315397],"tags":{"access":"customers","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":763977465,"nodes":[7137343680,7137343681,7137343682,7137343683,7137343680],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":763977466,"nodes":[7137343684,7137383185,7137383186,7137383187,7137343684],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":803821090,"nodes":[7519058290,7519058289,7519058288,7519058287,7519058290],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":803821091,"nodes":[7519058294,7519058293,7519058292,7519058291,7519058294],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":803821092,"nodes":[7519058298,7519058297,7519058296,7519058295,7519058298],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":803821093,"nodes":[7519058302,7519058301,7519058300,7519058299,7519058302],"tags":{"access":"private","amenity":"parking","capacity":"6","parking":"surface"}},{"type":"way","id":804963962,"nodes":[7529417225,7529417226,7529417227,7529417228,7529417229,7529417230,7529417232,7529417225],"tags":{"access":"customers","amenity":"parking","fee":"no","operator":"’t Kiekekot","parking":"surface","surface":"unpaved"}},{"type":"way","id":806875503,"nodes":[4042671969,7545532512,7545532514,7545532513,3359977305,4042671969],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":806963547,"nodes":[7546193222,7546193221,7546193220,7546193219,7546193222],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":865357121,"nodes":[8065883228,8065883227,8065883226,8065883225,8065883228],"tags":{"amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":865357122,"nodes":[8065883233,8065883230,8065883229,8065883232,8065883233],"tags":{"amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":879281221,"nodes":[8179735269,8179735268,8179735267,8179735266,8179735265,8179735264,8179735224,8179735269],"tags":{"access":"customers","amenity":"parking","parking":"surface"}},{"type":"way","id":881770201,"nodes":[8200275847,8200275848,8200275844,8200275853,8200275849,8200275847],"tags":{"amenity":"parking","parking":"surface","surface":"grass"}},{"type":"way","id":978360549,"nodes":[5761770202,5761770204,9052878229,9052878228,5761770202],"tags":{"amenity":"parking"}},{"type":"way","id":1009692722,"nodes":[9316118540,9316118536,9316118531,9316118535,9316118534,9316118533,9316118530,9316118532,3311835478,9316118540],"tags":{"amenity":"parking","parking":"street_side"}},{"type":"relation","id":8188853,"members":[{"type":"way","ref":577572397,"role":"outer"},{"type":"way","ref":577572399,"role":"outer"}],"tags":{"access":"guided","curator":"Luc Maene;Geert De Clercq","email":"lucmaene@hotmail.com;geert.de.clercq1@pandora.be","landuse":"meadow","leisure":"nature_reserve","name":"De Wulgenbroeken","natural":"wetland","operator":"Natuurpunt Brugge","type":"multipolygon","website":"https://natuurpuntbrugge.be/wulgenbroeken/","wetland":"wet_meadow","wikidata":"Q60061498","wikipedia":"nl:Wulgenbroeken"}},{"type":"relation","id":11163488,"members":[{"type":"way","ref":810604915,"role":"outer"},{"type":"way","ref":989393316,"role":"outer"},{"type":"way","ref":389026405,"role":"inner"},{"type":"way","ref":810607458,"role":"outer"}],"tags":{"access":"yes","curator":"Kris Lesage","description":"Wat Doeveren zo uniek maakt, zijn zijn kleine heidegebiedjes met soorten die erg verschillen van de Kempense heide. Doeveren en omstreken was vroeger één groot heidegebied, maar bestaat nu grotendeels uit bossen.","dog":"leashed","email":"doeveren@natuurpuntzedelgem.be","image":"https://i.imgur.com/NEAsQZG.jpg","image:0":"https://i.imgur.com/Dq71hyQ.jpg","image:1":"https://i.imgur.com/mAIiT4f.jpg","image:2":"https://i.imgur.com/dELZU97.jpg","image:3":"https://i.imgur.com/Bso57JC.jpg","image:4":"https://i.imgur.com/9DtcfXo.jpg","image:5":"https://i.imgur.com/0R6eBfk.jpg","image:6":"https://i.imgur.com/b0JpvbR.jpg","leisure":"nature_reserve","name":"Doeveren","operator":"Natuurpunt Zedelgem","phone":"+32 486 25 25 30","type":"multipolygon","website":"https://www.natuurpuntzedelgem.be/gebieden/doeveren/","wikidata":"Q56395754","wikipedia":"nl:Doeveren (natuurgebied)"}},{"type":"relation","id":11790117,"members":[{"type":"way","ref":863373849,"role":"outer"},{"type":"way","ref":777280458,"role":"outer"}],"tags":{"access":"no","description:0":"In gebruik als waterbuffering","leisure":"nature_reserve","name":"Kerkebeek","operator":"Natuurpunt Brugge","type":"multipolygon"}},{"type":"node","id":518224450,"lat":51.1548065,"lon":3.1880118,"timestamp":"2021-08-14T21:49:28Z","version":5,"changeset":109683837,"user":"effem","uid":16437,"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"street_side"}},{"type":"node","id":665418924,"lat":51.1575547,"lon":3.20522,"timestamp":"2012-05-12T20:13:39Z","version":2,"changeset":11580224,"user":"martino260","uid":655442,"tags":{"amenity":"parking"}},{"type":"node","id":1168727903,"lat":51.1299141,"lon":3.1776123,"timestamp":"2017-04-03T08:34:05Z","version":2,"changeset":47403889,"user":"philippec","uid":76884,"tags":{"amenity":"drinking_water","mapillary":"https://www.mapillary.com/app/?lat=51.129853685131906&lng=3.177603984688602&z=17&pKey=SEyKzIMUeKssni1ZLVe-9A&focus=photo&dateTo=2017-04-02&dateFrom=2017-04-01&x=0.5168826751181941&y=0.6114877557873634&zoom=0"}},{"type":"node","id":1168728245,"lat":51.1290938,"lon":3.1767502,"timestamp":"2019-10-07T11:06:57Z","version":3,"changeset":75370316,"user":"Hopperpop","uid":3664604,"tags":{"amenity":"drinking_water","mapillary":"https://www.mapillary.com/app/?lat=51.129104406662464&lng=3.176675795895676&z=17&pKey=vSP3D_hWv3XCBtH75GnYUQ&focus=photo&dateTo=2017-04-02&dateFrom=2017-04-01"}},{"type":"node","id":1725842653,"lat":51.153364,"lon":3.2352655,"timestamp":"2012-07-02T17:33:00Z","version":2,"changeset":12090625,"user":"martino260","uid":655442,"tags":{"amenity":"bench"}},{"type":"node","id":1744641290,"lat":51.1389321,"lon":3.2385407,"timestamp":"2012-09-18T13:29:52Z","version":3,"changeset":13156159,"user":"martino260","uid":655442,"tags":{"amenity":"bench","backrest":"yes","material":"wood"}},{"type":"node","id":1746891135,"lat":51.1598841,"lon":3.2361425,"timestamp":"2012-05-09T18:22:11Z","version":1,"changeset":11551825,"user":"martino260","uid":655442,"tags":{"amenity":"bench"}},{"type":"node","id":1810326078,"lat":51.1550855,"lon":3.2349358,"timestamp":"2012-07-02T19:50:15Z","version":1,"changeset":12093439,"user":"martino260","uid":655442,"tags":{"amenity":"bench"}},{"type":"node","id":1810326092,"lat":51.1552302,"lon":3.234968,"timestamp":"2012-07-02T19:50:16Z","version":1,"changeset":12093439,"user":"martino260","uid":655442,"tags":{"amenity":"bench"}},{"type":"node","id":2325437742,"lat":51.1770052,"lon":3.1967794,"timestamp":"2013-05-30T12:19:08Z","version":1,"changeset":16350909,"user":"peeweeke","uid":494726,"tags":{"board_type":"board","information":"board","name":"Tillegembos","tourism":"information"}},{"type":"node","id":2325437743,"lat":51.1787363,"lon":3.1949036,"timestamp":"2013-05-30T12:19:08Z","version":1,"changeset":16350909,"user":"peeweeke","uid":494726,"tags":{"board_type":"board","information":"board","name":"Tillegembos","tourism":"information"}},{"type":"node","id":2325437813,"lat":51.1733102,"lon":3.1895672,"timestamp":"2013-05-30T12:19:09Z","version":1,"changeset":16350909,"user":"peeweeke","uid":494726,"tags":{"amenity":"bench","backrest":"yes","material":"wood"}},{"type":"node","id":2325437839,"lat":51.1763436,"lon":3.1984985,"timestamp":"2013-05-30T12:19:10Z","version":1,"changeset":16350909,"user":"peeweeke","uid":494726,"tags":{"amenity":"bench","backrest":"yes","material":"wood"}},{"type":"node","id":2325437848,"lat":51.1770966,"lon":3.1963507,"timestamp":"2013-05-30T12:19:10Z","version":1,"changeset":16350909,"user":"peeweeke","uid":494726,"tags":{"amenity":"bench","backrest":"yes","material":"wood"}},{"type":"node","id":2325437862,"lat":51.1773439,"lon":3.1948779,"timestamp":"2013-05-30T12:19:10Z","version":1,"changeset":16350909,"user":"peeweeke","uid":494726,"tags":{"amenity":"bench","backrest":"yes","material":"wood"}},{"type":"node","id":2325437867,"lat":51.1775994,"lon":3.1888088,"timestamp":"2013-05-30T12:19:11Z","version":1,"changeset":16350909,"user":"peeweeke","uid":494726,"tags":{"amenity":"bench","backrest":"yes","material":"wood"}},{"type":"node","id":2325437873,"lat":51.1778384,"lon":3.1913802,"timestamp":"2013-05-30T12:19:11Z","version":1,"changeset":16350909,"user":"peeweeke","uid":494726,"tags":{"amenity":"bench","backrest":"yes","material":"wood"}},{"type":"node","id":2732486257,"lat":51.129741,"lon":3.1907419,"timestamp":"2014-03-21T21:15:28Z","version":1,"changeset":21234491,"user":"meannder","uid":149496,"tags":{"board_type":"nature","information":"board","name":"Doeveren","tourism":"information"}},{"type":"node","id":3774054068,"lat":51.1586662,"lon":3.2271102,"timestamp":"2015-10-05T20:34:04Z","version":1,"changeset":34456387,"user":"TripleBee","uid":497177,"tags":{"amenity":"bench"}},{"type":"node","id":4769106605,"lat":51.138264,"lon":3.1798655,"timestamp":"2020-05-31T19:49:45Z","version":3,"changeset":86019474,"user":"Hopperpop","uid":3664604,"tags":{"backrest":"yes","leisure":"picnic_table"}},{"type":"node","id":4912238707,"lat":51.1448634,"lon":3.2455986,"timestamp":"2017-06-13T08:12:04Z","version":1,"changeset":49491753,"user":"Jakka","uid":2403313,"tags":{"access":"yes","amenity":"parking","fee":"no","name":"Oostkamp","parking":"Carpool"}},{"type":"node","id":5637212235,"lat":51.1305439,"lon":3.1866873,"timestamp":"2021-11-22T11:54:45Z","version":4,"changeset":114095475,"user":"L'imaginaire","uid":654234,"tags":{"board_type":"nature","image":"https://i.imgur.com/HehOQL9.jpg","information":"board","name":"Welkom Doeveren","tourism":"information"}},{"type":"node","id":5637224573,"lat":51.1281084,"lon":3.1881726,"timestamp":"2020-06-01T22:39:30Z","version":2,"changeset":86065716,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"board_type":"nature","information":"board","name":"Welkom Doeveren","tourism":"information"}},{"type":"node","id":5637230107,"lat":51.1280884,"lon":3.1889798,"timestamp":"2018-05-23T11:55:01Z","version":1,"changeset":59208628,"user":"Jakka","uid":2403313,"tags":{"information":"board","tourism":"information"}},{"type":"node","id":5637743026,"lat":51.1295973,"lon":3.1751122,"timestamp":"2021-10-08T08:53:14Z","version":2,"changeset":112251989,"user":"DieterWesttoer","uid":13062237,"tags":{"information":"board","name":"Doeveren Wandelroute","tourism":"information"}},{"type":"node","id":5716130103,"lat":51.1767183,"lon":3.1947867,"timestamp":"2018-06-24T22:04:21Z","version":1,"changeset":60130942,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"amenity":"bench","backrest":"yes"}},{"type":"node","id":5745783208,"lat":51.1782581,"lon":3.2410111,"timestamp":"2018-07-07T18:42:23Z","version":1,"changeset":60494990,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"amenity":"bench"}},{"type":"node","id":5745807545,"lat":51.1784037,"lon":3.2369439,"timestamp":"2018-07-07T18:58:25Z","version":1,"changeset":60495307,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"amenity":"bench"}},{"type":"node","id":5745807551,"lat":51.1783278,"lon":3.236678,"timestamp":"2018-07-07T18:58:25Z","version":1,"changeset":60495307,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"amenity":"bench"}},{"type":"node","id":6535241426,"lat":51.1693142,"lon":3.1673093,"timestamp":"2019-06-09T13:50:19Z","version":1,"changeset":71071874,"user":"Hopperpop","uid":3664604,"tags":{"amenity":"bench"}},{"type":"node","id":6535241427,"lat":51.169265,"lon":3.1673159,"timestamp":"2019-06-09T13:50:19Z","version":1,"changeset":71071874,"user":"Hopperpop","uid":3664604,"tags":{"amenity":"bench"}},{"type":"node","id":6535241428,"lat":51.1692199,"lon":3.1673224,"timestamp":"2019-06-09T13:50:19Z","version":1,"changeset":71071874,"user":"Hopperpop","uid":3664604,"tags":{"amenity":"bench"}},{"type":"node","id":6535241430,"lat":51.1685726,"lon":3.1678225,"timestamp":"2019-06-09T13:50:19Z","version":1,"changeset":71071874,"user":"Hopperpop","uid":3664604,"tags":{"bench":"yes","leisure":"picnic_table","material":"wood"}},{"type":"node","id":6536026827,"lat":51.1703142,"lon":3.1691109,"timestamp":"2019-06-09T22:54:45Z","version":1,"changeset":71082671,"user":"Hopperpop","uid":3664604,"tags":{"leisure":"picnic_table"}},{"type":"node","id":6536026828,"lat":51.1702795,"lon":3.1691552,"timestamp":"2019-06-09T22:54:45Z","version":1,"changeset":71082671,"user":"Hopperpop","uid":3664604,"tags":{"leisure":"picnic_table"}},{"type":"node","id":6712112244,"lat":51.1595064,"lon":3.2021482,"timestamp":"2020-05-24T21:35:50Z","version":2,"changeset":85695537,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"leisure":"picnic_table"}},{"type":"node","id":7304050040,"lat":51.1560908,"lon":3.1748919,"timestamp":"2020-03-17T19:11:00Z","version":1,"changeset":82315744,"user":"Hopperpop","uid":3664604,"tags":{"amenity":"bench"}},{"type":"node","id":7304050041,"lat":51.1560141,"lon":3.1749533,"timestamp":"2020-03-17T19:11:00Z","version":1,"changeset":82315744,"user":"Hopperpop","uid":3664604,"tags":{"amenity":"bench"}},{"type":"node","id":7304050042,"lat":51.156032,"lon":3.1749379,"timestamp":"2020-03-17T19:11:00Z","version":1,"changeset":82315744,"user":"Hopperpop","uid":3664604,"tags":{"amenity":"bench"}},{"type":"node","id":7439979218,"lat":51.1780402,"lon":3.2178666,"timestamp":"2020-04-24T00:56:14Z","version":1,"changeset":84027933,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"amenity":"bench","backrest":"yes"}},{"type":"node","id":7439979219,"lat":51.1780508,"lon":3.2179033,"timestamp":"2020-04-24T00:56:14Z","version":1,"changeset":84027933,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"amenity":"bench","backrest":"yes"}},{"type":"node","id":7529262982,"lat":51.1585566,"lon":3.1715528,"timestamp":"2020-05-17T16:12:04Z","version":1,"changeset":85340264,"user":"Hopperpop","uid":3664604,"tags":{"board_type":"map","information":"board","tourism":"information"}},{"type":"node","id":7529262984,"lat":51.1585786,"lon":3.1715385,"timestamp":"2020-05-17T16:12:04Z","version":1,"changeset":85340264,"user":"Hopperpop","uid":3664604,"tags":{"leisure":"picnic_table"}},{"type":"node","id":7554879668,"lat":51.1573713,"lon":3.2043731,"timestamp":"2020-05-24T21:35:50Z","version":1,"changeset":85695537,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"access":"yes","amenity":"toilets","fee":"no","toilets:disposal":"flush","unisex":"yes","wheelchair":"yes"}},{"type":"node","id":7554879669,"lat":51.1594855,"lon":3.2021507,"timestamp":"2020-05-24T21:35:50Z","version":1,"changeset":85695537,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"leisure":"picnic_table"}},{"type":"node","id":7556988723,"lat":51.1330234,"lon":3.1839944,"timestamp":"2020-05-25T19:19:56Z","version":1,"changeset":85730259,"user":"Hopperpop","uid":3664604,"tags":{"amenity":"bench","material":"wood"}},{"type":"node","id":7575825326,"lat":51.1386553,"lon":3.1797358,"timestamp":"2020-05-31T19:49:45Z","version":1,"changeset":86019474,"user":"Hopperpop","uid":3664604,"tags":{"amenity":"bench"}},{"type":"node","id":7575825327,"lat":51.1382456,"lon":3.1797422,"timestamp":"2020-05-31T19:49:45Z","version":1,"changeset":86019474,"user":"Hopperpop","uid":3664604,"tags":{"information":"board","tourism":"information"}},{"type":"node","id":8109498958,"lat":51.1332267,"lon":3.2341272,"timestamp":"2020-11-11T20:42:45Z","version":1,"changeset":93951029,"user":"L'imaginaire","uid":654234,"tags":{"amenity":"bench","backrest":"yes"}},{"type":"node","id":8109498959,"lat":51.1335011,"lon":3.2343954,"timestamp":"2020-11-11T20:42:45Z","version":1,"changeset":93951029,"user":"L'imaginaire","uid":654234,"tags":{"leisure":"picnic_table"}},{"type":"node","id":8198894646,"lat":51.125688,"lon":3.1856217,"timestamp":"2020-12-06T23:39:34Z","version":3,"changeset":95384686,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"image":"https://i.imgur.com/O5kX20u.jpg","information":"board","tourism":"information"}},{"type":"node","id":8199012519,"lat":51.1262245,"lon":3.1802429,"timestamp":"2020-12-07T00:12:14Z","version":3,"changeset":95385124,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"image":"https://i.imgur.com/tomw9p5.jpg","information":"board","tourism":"information"}},{"type":"node","id":8199244816,"lat":51.1252874,"lon":3.1837622,"timestamp":"2020-12-06T17:14:52Z","version":1,"changeset":95374174,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"amenity":"bench"}},{"type":"node","id":8199301617,"lat":51.1256827,"lon":3.1853543,"timestamp":"2020-12-06T17:14:52Z","version":1,"changeset":95374174,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"amenity":"bench","backrest":"no"}},{"type":"node","id":8255488518,"lat":51.1406698,"lon":3.235178,"timestamp":"2020-12-23T18:20:35Z","version":1,"changeset":96342158,"user":"L'imaginaire","uid":654234,"tags":{"amenity":"bench","backrest":"yes"}},{"type":"node","id":9316104741,"lat":51.1330984,"lon":3.2335257,"timestamp":"2021-12-06T18:31:00Z","version":1,"changeset":114629890,"user":"L'imaginaire","uid":654234,"tags":{"information":"board","tourism":"information"}},{"type":"node","id":9442532340,"lat":51.1763651,"lon":3.1947952,"timestamp":"2022-01-23T16:26:28Z","version":2,"changeset":116506336,"user":"L'imaginaire","uid":654234,"tags":{"amenity":"bench","backrest":"yes","image":"https://i.imgur.com/eZ0Loii.jpg"}},{"type":"way","id":15242261,"timestamp":"2020-04-05T07:08:45Z","version":8,"changeset":83089516,"user":"Hopperpop","uid":3664604,"nodes":[150996092,150996093,6754312552,6754312553,6754312550,6754312551,150996094,150996095,150996097,150996098,6754312560,6754312559,6754312558,150996099,6754312557,150996100,6754312555,6754312556,150996101,6754312554,150996092],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":16514228,"timestamp":"2017-06-13T07:14:23Z","version":9,"changeset":49490318,"user":"Jakka","uid":2403313,"nodes":[170464837,170464839,170464840,170464841,170464837],"tags":{"access":"yes","amenity":"parking","fee":"no","maxstay":"4 hours","parking":"surface"}},{"type":"way","id":76706071,"timestamp":"2017-06-17T07:51:31Z","version":4,"changeset":49608752,"user":"rowers2","uid":2445224,"nodes":[903903386,1038557094,1038557233,1038557143,1038557075,903903387,1038557195,903903388,903903390,903904576,903903386],"tags":{"access":"permissive","amenity":"parking"}},{"type":"way","id":89601157,"timestamp":"2019-11-09T18:40:50Z","version":3,"changeset":76851428,"user":"Hopperpop","uid":3664604,"nodes":[1038557083,1038557078,1038557104,1038557072,1038557108,1038557230,1038557227,1038557102,1038557137,1038575040,1038557191,1038557014,6960473080,1038557035,1038557012,1038557083],"tags":{"amenity":"parking"}},{"type":"way","id":89604999,"timestamp":"2020-01-16T22:01:28Z","version":5,"changeset":79667667,"user":"Hopperpop","uid":3664604,"nodes":[1038583404,1038583491,1038583375,1038583483,1038583479,1038583398,1038583459,1038583456,1038583446,1038583441,1038583425,1038583501,1038583451,1038583463,1038583476,1038583404],"tags":{"access":"yes","amenity":"parking","capacity":"57","carpool":"yes","description":"carpoolparking","fee":"no","name":"Loppem","parking":"surface"}},{"type":"way","id":92035679,"timestamp":"2019-10-05T08:05:33Z","version":7,"changeset":75311122,"user":"skyman81","uid":955688,"nodes":[1069177920,6853179264,1069177925,1069177919,6853179269,6853179268,6853179267,6853179215,6853179213,6853179214,1069178133,1069177984,6853179230,6853179228,6853179229,6853179224,6853179225,6853179227,6853179226,6853179216,6853179220,6853179219,6853179218,6853179217,6853179223,6853179221,6853179222,1069177967,1069177852,6853179211,6853179212,6853179210,6853179327,6853179208,6853179209,6853179203,1069177976,6853179207,6853179206,6853179205,6853179204,6853179202,1069177849,6852012579,6852012578,6852012580,6852012577,6852012581,6852012582,6852012583,1069177845,1759437085,1519342743,1519342742,1069178166,1069177853,1069177915,6853179235,6853179234,6853179236,1069177933,6853179237,6853179238,1069178021,6853179246,6853179244,6853179245,6853179240,6853179243,6853179241,6853179242,6853179239,6853179248,6853179249,6853179250,6853179247,1069177873,6853179262,6853179263,6853179260,6853179261,6853179256,6853179259,6853179257,6853179258,1069177920],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":101248451,"timestamp":"2018-05-23T14:18:27Z","version":2,"changeset":59213416,"user":"Jakka","uid":2403313,"nodes":[1168728158,1168728325,1168728159,5637669355,1168728109,1168728158],"tags":{"access":"private","amenity":"parking","name":"Parking Merkenveld"}},{"type":"way","id":101248462,"timestamp":"2020-05-25T13:53:02Z","version":3,"changeset":85720081,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[1168727876,1168728288,1168728412,1168728208,1168727876],"tags":{"amenity":"toilets","building":"yes","source:geometry:date":"2019-03-14","source:geometry:ref":"Gbg/6588148"}},{"type":"way","id":131622387,"timestamp":"2015-01-09T12:06:51Z","version":2,"changeset":28017707,"user":"TripleBee","uid":497177,"nodes":[1448421093,1448421099,1448421091,1448421081,1448421093],"tags":{"amenity":"parking","name":"Tudor - Zeeweg","parking":"surface"}},{"type":"way","id":145691934,"timestamp":"2012-01-15T12:43:37Z","version":1,"changeset":10397429,"user":"Sanderd17","uid":253266,"nodes":[1590642859,1590642860,1590642858,1590642849,1590642859],"tags":{"amenity":"parking"}},{"type":"way","id":145691937,"timestamp":"2012-01-15T12:43:37Z","version":1,"changeset":10397429,"user":"Sanderd17","uid":253266,"nodes":[1590642829,1590642828,1590642830,1590642832,1590642829],"tags":{"amenity":"parking"}},{"type":"way","id":158901716,"timestamp":"2017-06-13T07:12:20Z","version":2,"changeset":49490264,"user":"Jakka","uid":2403313,"nodes":[1710245713,1710245718,1710245707,1710245705,1710245703,1710245715,1710245711,1710245709,1710245701,1710245713],"tags":{"access":"yes","amenity":"parking","capacity":"14","fee":"no","parking":"surface"}},{"type":"way","id":158904558,"timestamp":"2020-12-22T22:39:41Z","version":4,"changeset":96283379,"user":"M!dgard","uid":763799,"nodes":[1710262742,1710262745,1710262735,1710262733,1710262732,1710262743,1710262741,1710262739,1710262744,1710262737,1710262736,1710262731,1710262738,1710262742],"tags":{"access":"yes","alt_name":"Schoolparking","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":158906028,"timestamp":"2017-06-13T07:27:19Z","version":5,"changeset":49490646,"user":"Jakka","uid":2403313,"nodes":[1710276259,1710276251,1810330766,1710276255,1710276261,1710276240,1710276232,1710276257,1710276243,1710276253,1810347217,1710276242,1710276259],"tags":{"access":"yes","amenity":"parking","fee":"no","name":"Parking Sportcentrum De Valkaart","parking":"surface"}},{"type":"way","id":160825858,"timestamp":"2012-04-23T20:35:52Z","version":1,"changeset":11399632,"user":"martino260","uid":655442,"nodes":[1728421375,1728421374,1728421379,1728421377,1728421376,1728421378,1728421375],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":162602213,"timestamp":"2020-04-11T18:12:16Z","version":8,"changeset":83407731,"user":"JanFi","uid":672253,"nodes":[1920143232,7393009684,7393048385,1744641293,1523513488,1744641292,1920143232],"tags":{"amenity":"parking","capacity":"15"}},{"type":"way","id":165489167,"timestamp":"2020-10-12T19:06:29Z","version":3,"changeset":92371840,"user":"L'imaginaire","uid":654234,"nodes":[4912197370,4912197365,4912197373,4912197364,4912197372,1770289505,4912197362,4912197371,4912197374,4912197363,4912197368,4912197366,4912197369,4912197367,4912197370],"tags":{"access":"yes","amenity":"parking","fee":"no","name":"Bad Neuheimplein","parking":"surface"}},{"type":"way","id":168291852,"timestamp":"2017-07-19T11:17:33Z","version":3,"changeset":50402298,"user":"martino260","uid":655442,"nodes":[1795793399,4979389763,1795793409,1795793395,1795793393,1795793397,1795793407,1795793406,1795793408,1795793405,1795793399],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":169875513,"timestamp":"2017-06-13T07:26:09Z","version":2,"changeset":49490613,"user":"Jakka","uid":2403313,"nodes":[1810345951,1810345955,1810345947,1810345944,1810345951],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":170015605,"timestamp":"2017-06-17T07:51:33Z","version":4,"changeset":49608752,"user":"rowers2","uid":2445224,"nodes":[1811673425,1811673421,1811673418,1811673423,1811673425],"tags":{"access":"private","amenity":"parking","name":"gheeraert E40","operator":"Gheeraert"}},{"type":"way","id":170018487,"timestamp":"2017-06-17T07:51:33Z","version":3,"changeset":49608752,"user":"rowers2","uid":2445224,"nodes":[1811699779,1811699778,1811699776,1811699777,1811699779],"tags":{"access":"private","amenity":"parking","name":"Gheeraert vooraan"}},{"type":"way","id":170559194,"timestamp":"2017-06-17T07:51:33Z","version":2,"changeset":49608752,"user":"rowers2","uid":2445224,"nodes":[1817319304,1817319302,1817319297,1817319301,1817319304],"tags":{"access":"private","amenity":"parking","name":"Gheeraert laadkade"}},{"type":"way","id":170559195,"timestamp":"2017-06-17T07:51:33Z","version":2,"changeset":49608752,"user":"rowers2","uid":2445224,"nodes":[1817319299,1817319303,1817319300,1817319292,1817319299],"tags":{"access":"private","amenity":"parking","name":"Gheeraert spoorweg trailers"}},{"type":"way","id":170559196,"timestamp":"2017-06-17T07:51:33Z","version":2,"changeset":49608752,"user":"rowers2","uid":2445224,"nodes":[1817319293,1817319289,1817319291,1817319296,1817319293],"tags":{"access":"private","amenity":"parking","name":"Gheeraert spoorweg trucks"}},{"type":"way","id":170559197,"timestamp":"2017-06-17T07:51:33Z","version":2,"changeset":49608752,"user":"rowers2","uid":2445224,"nodes":[1817319294,1817319298,1817319295,1817319290,1817319294],"tags":{"access":"private","amenity":"parking","name":"Gheeraert zijkant"}},{"type":"way","id":170559292,"timestamp":"2017-06-17T07:51:33Z","version":2,"changeset":49608752,"user":"rowers2","uid":2445224,"nodes":[1817320496,1817320494,1817320493,1817320495,1817320496],"tags":{"access":"private","amenity":"parking","name":"Gheeraert vooraan gebouw"}},{"type":"way","id":170559832,"timestamp":"2020-10-07T10:51:41Z","version":6,"changeset":92105788,"user":"effem","uid":16437,"nodes":[1817324515,1817324509,1817324491,6397031888,4044172008,4044172003,4044171997,4044171962,4044171957,4044171976,1817324489,1817324488,3550860268,1817324505,3550860269,1817324513,1817324515],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":223674368,"timestamp":"2020-12-03T18:47:28Z","version":3,"changeset":95244226,"user":"L'imaginaire","uid":654234,"nodes":[2325437844,8191691971,8191691973,8191691972,2325437840,8191691970,414025563,2325437844],"tags":{"amenity":"parking","name":"Tillegembos","parking":"surface"}},{"type":"way","id":237214948,"timestamp":"2017-06-17T07:51:35Z","version":2,"changeset":49608752,"user":"rowers2","uid":2445224,"nodes":[2451574741,2451574742,2451574744,1015583939,2451574741],"tags":{"access":"private","amenity":"parking"}},{"type":"way","id":237214949,"timestamp":"2017-06-17T07:51:35Z","version":2,"changeset":49608752,"user":"rowers2","uid":2445224,"nodes":[2451574748,2451574746,2451574747,2451574749,2451574748],"tags":{"access":"private","amenity":"parking"}},{"type":"way","id":237214950,"timestamp":"2017-06-17T07:51:35Z","version":3,"changeset":49608752,"user":"rowers2","uid":2445224,"nodes":[2451569392,1015567837,2451574745,2451574743,2451578121,2451569392],"tags":{"access":"private","amenity":"parking"}},{"type":"way","id":325909586,"timestamp":"2016-01-05T18:51:49Z","version":2,"changeset":36387330,"user":"JanFi","uid":672253,"nodes":[3325315243,111759500,3325315247,3325315232,3325315230,3325315226,1169056712,3325315243],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":326834162,"timestamp":"2021-10-10T21:49:11Z","version":4,"changeset":112350014,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[3335137807,3335137692,3335137795,9163493632,3335137802,3335137812,9163486855,9163486856,3335137823,3335137807],"tags":{"access":"customers","amenity":"parking","operator":"Best Western Weinebrugge","parking":"surface"}},{"type":"way","id":327849054,"timestamp":"2015-02-12T20:26:22Z","version":1,"changeset":28807613,"user":"escada","uid":436365,"nodes":[3346575929,3346575873,3346575876,3346575843,3346575845,3346575891,3346575901,3346575923,3346575928,3346575950,3346575929],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":327849055,"timestamp":"2016-10-08T21:24:46Z","version":2,"changeset":42742859,"user":"maggot27","uid":118021,"nodes":[3346575945,3346575946,3346575943,3346575933,3346575925,3346575917,3346575903,3346575908,3346575889,3346575886,3346575945],"tags":{"access":"customers","amenity":"parking","parking":"surface"}},{"type":"way","id":327849056,"timestamp":"2015-02-12T20:26:22Z","version":1,"changeset":28807613,"user":"escada","uid":436365,"nodes":[3346575865,3346575853,3346575855,3346575846,3346575840,3346575858,3346575865],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":374677860,"timestamp":"2015-10-10T09:08:20Z","version":1,"changeset":34545536,"user":"Jakka","uid":2403313,"nodes":[3780611504,3780611502,3780611500,3780611503,3780611504],"tags":{"amenity":"parking"}},{"type":"way","id":374677861,"timestamp":"2015-10-10T09:08:20Z","version":1,"changeset":34545536,"user":"Jakka","uid":2403313,"nodes":[3780611495,3780611493,3780611492,3780611494,3780611495],"tags":{"amenity":"parking"}},{"type":"way","id":374677862,"timestamp":"2015-10-10T09:08:20Z","version":1,"changeset":34545536,"user":"Jakka","uid":2403313,"nodes":[3780611498,3780611497,3780611496,3780611499,3780611501,3780611498],"tags":{"amenity":"parking"}},{"type":"way","id":389912371,"timestamp":"2016-01-06T16:51:45Z","version":1,"changeset":36407948,"user":"Spectrokid","uid":19775,"nodes":[3930713440,3930713451,3930713447,3930713437,3930713440],"tags":{"amenity":"parking"}},{"type":"way","id":389912372,"timestamp":"2019-11-16T13:17:09Z","version":4,"changeset":77164376,"user":"Hopperpop","uid":3664604,"nodes":[3930713454,3930713442,3930713435,3930713429,5826811614,3930713426,3930713430,6982605752,6982605754,3930713438,6982605769,6982605766,6982605767,6982605762,6982605764,3930713446,3930713454],"tags":{"access":"customers","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":401995684,"timestamp":"2020-10-07T10:52:00Z","version":3,"changeset":92105972,"user":"effem","uid":16437,"nodes":[4044171963,4044171954,4044171924,4044171936,4044171941,4044171963],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":500067820,"timestamp":"2017-06-13T07:49:12Z","version":1,"changeset":49491219,"user":"Jakka","uid":2403313,"nodes":[4912203166,4912203165,4912203164,4912203163,4912203162,4912203161,4912203160,4912203166],"tags":{"access":"yes","amenity":"parking","parking":"surface"}},{"type":"way","id":500067821,"timestamp":"2017-06-13T07:49:12Z","version":1,"changeset":49491219,"user":"Jakka","uid":2403313,"nodes":[4912203170,4912203169,4912203168,4912203167,4912203170],"tags":{"access":"yes","amenity":"parking","parking":"surface"}},{"type":"way","id":500067822,"timestamp":"2017-06-13T07:49:12Z","version":1,"changeset":49491219,"user":"Jakka","uid":2403313,"nodes":[4912203174,4912203173,4912203172,4912203171,4912203174],"tags":{"access":"yes","amenity":"parking","parking":"surface"}},{"type":"way","id":500067823,"timestamp":"2017-06-13T07:49:12Z","version":1,"changeset":49491219,"user":"Jakka","uid":2403313,"nodes":[4912203179,4912203178,4912203177,4912203176,4912203179],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":500069613,"timestamp":"2018-10-11T09:30:48Z","version":2,"changeset":63409550,"user":"Jakka","uid":2403313,"nodes":[4912214695,4912214685,4912214694,4912214693,4912214692,4912214680,4912214695],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":500071452,"timestamp":"2018-10-11T09:30:48Z","version":2,"changeset":63409550,"user":"Jakka","uid":2403313,"nodes":[4912225068,4912225062,4912225063,4912225053,4912225064,4912214694,4912214685,4912225068],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":500071455,"timestamp":"2018-10-11T09:30:48Z","version":2,"changeset":63409550,"user":"Jakka","uid":2403313,"nodes":[4912225070,4912214681,4912214686,4912225052,4912225051,4912225067,4912225062,4912225068,4912225070],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":500071458,"timestamp":"2018-10-11T09:30:48Z","version":2,"changeset":63409550,"user":"Jakka","uid":2403313,"nodes":[4912214695,4912214680,4912225069,4912225050,1525460846,4912214681,4912225070,4912214695],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":533276307,"timestamp":"2019-12-13T10:02:12Z","version":2,"changeset":78364882,"user":"skyman81","uid":955688,"nodes":[5173881316,5173881317,5173881318,7054196467,5173881316],"tags":{"amenity":"parking"}},{"type":"way","id":533276308,"timestamp":"2017-10-17T23:36:18Z","version":1,"changeset":53027174,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[5173881320,5173881621,5173881622,5173881623,5173881320],"tags":{"amenity":"parking"}},{"type":"way","id":533276309,"timestamp":"2017-10-17T23:36:18Z","version":1,"changeset":53027174,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[5173881624,5173881625,5173881626,5173881627,5173881624],"tags":{"amenity":"parking"}},{"type":"way","id":579848581,"timestamp":"2020-04-05T07:08:57Z","version":6,"changeset":83089516,"user":"Hopperpop","uid":3664604,"nodes":[4043782112,5825400688,5552466020,6997096756,6997096759,6997096758,5552466018,5552466013,5552466014,6997076567,4043782112],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":584455569,"timestamp":"2019-10-31T19:49:18Z","version":2,"changeset":76465627,"user":"Hopperpop","uid":3664604,"nodes":[5586765933,5586765934,5586765935,5586765936,5586765933],"tags":{"amenity":"parking"}},{"type":"way","id":585977870,"timestamp":"2019-10-11T13:28:22Z","version":2,"changeset":75566739,"user":"Hopperpop","uid":3664604,"nodes":[5587844460,5599314384,5599314385,1659850846,6870850178,5587844462,5587844461,6870863414,5587844460],"tags":{"amenity":"parking"}},{"type":"way","id":587014342,"timestamp":"2018-05-09T19:13:29Z","version":1,"changeset":58829130,"user":"Sille Van Landschoot","uid":4852501,"nodes":[5607796820,5607798725,5607798721,5607798722,5607796819,5607798723,5607796820],"tags":{"access":"permissive","amenity":"parking","park_ride":"no","parking":"surface","surface":"paved"}},{"type":"way","id":590167103,"timestamp":"2018-05-22T12:37:36Z","version":1,"changeset":59179114,"user":"ForstEK","uid":1737608,"nodes":[5635001277,5635001274,5635001275,5635001276,5635001277],"tags":{"amenity":"parking"}},{"type":"way","id":590167113,"timestamp":"2020-07-29T17:45:20Z","version":2,"changeset":88691835,"user":"JanFi","uid":672253,"nodes":[5635001312,5635001306,7767137237,7767137235,7767137236,7767137234,5635001312],"tags":{"amenity":"parking"}},{"type":"way","id":590167134,"timestamp":"2018-05-22T12:37:37Z","version":1,"changeset":59179114,"user":"ForstEK","uid":1737608,"nodes":[5635001374,5635001373,5635001372,5635001371,5635001374],"tags":{"amenity":"parking"}},{"type":"way","id":590167135,"timestamp":"2018-05-22T12:37:37Z","version":1,"changeset":59179114,"user":"ForstEK","uid":1737608,"nodes":[5635001378,5635001377,5635001376,5635001375,5635001378],"tags":{"amenity":"parking"}},{"type":"way","id":590167136,"timestamp":"2018-05-22T12:37:37Z","version":1,"changeset":59179114,"user":"ForstEK","uid":1737608,"nodes":[5635001382,5635001381,5635001380,5635001379,5635001382],"tags":{"amenity":"parking"}},{"type":"way","id":590167137,"timestamp":"2019-07-06T15:58:19Z","version":3,"changeset":71962591,"user":"gjosch","uid":1776978,"nodes":[5635001386,5882873336,5882873337,5882873338,5882873335,6593340582,6593340583,5882873334,6593340584,5635001385,5635001384,5635001383,5635001386],"tags":{"amenity":"parking"}},{"type":"way","id":590167147,"timestamp":"2018-05-22T12:37:38Z","version":1,"changeset":59179114,"user":"ForstEK","uid":1737608,"nodes":[5635001417,5635001414,5635001415,5635001416,5635001417],"tags":{"amenity":"parking"}},{"type":"way","id":601406079,"timestamp":"2018-06-24T22:15:06Z","version":1,"changeset":60131072,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[5716136617,5716136618,5716136619,5716136620,5716136617],"tags":{"amenity":"parking"}},{"type":"way","id":632813009,"timestamp":"2018-10-11T09:24:42Z","version":1,"changeset":63409297,"user":"Jakka","uid":2403313,"nodes":[5974489618,1810326044,1810326087,5974489617,5972179348,5972179347,5972179346,5972179345,5972179344,5972179343,5972179331,5974489616,5974489615,5974489614,5974489618],"tags":{"amenity":"parking","name":"Gemeenteplein","parking":"surface"}},{"type":"way","id":668043297,"timestamp":"2019-04-10T18:34:27Z","version":2,"changeset":69093378,"user":"RudolpheDeer","uid":9408828,"nodes":[6255587424,6255587425,6255587426,6255587427,6255587424],"tags":{"access":"private","amenity":"parking"}},{"type":"way","id":670104236,"timestamp":"2019-02-13T00:05:02Z","version":1,"changeset":67147239,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[6275462768,6275462769,6275462770,6275462771,6275462768],"tags":{"amenity":"parking"}},{"type":"way","id":670104238,"timestamp":"2019-02-13T00:05:02Z","version":1,"changeset":67147239,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[6275462772,6275462989,6275462773,6275462774,6275462775,6275462772],"tags":{"amenity":"parking"}},{"type":"way","id":670104239,"timestamp":"2019-02-13T00:05:02Z","version":1,"changeset":67147239,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[6275462776,6275462777,6275462778,6275462779,6275462776],"tags":{"amenity":"parking"}},{"type":"way","id":670104241,"timestamp":"2019-02-13T00:05:02Z","version":1,"changeset":67147239,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[6275462780,6275462781,6275462782,6275462783,6275462780],"tags":{"amenity":"parking"}},{"type":"way","id":670104242,"timestamp":"2019-02-13T00:05:02Z","version":1,"changeset":67147239,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[6275462784,6275462985,6275462988,6275462986,6275462987,6275462784],"tags":{"amenity":"parking"}},{"type":"way","id":671840055,"timestamp":"2019-02-20T15:15:45Z","version":1,"changeset":67395313,"user":"Tim Couwelier","uid":7246683,"nodes":[6291339827,6291339828,6291339816,6291339815,6291339822,6291339821,6291339829,6291339830,6291339827],"tags":{"amenity":"parking"}},{"type":"way","id":695825223,"timestamp":"2019-06-08T15:19:24Z","version":1,"changeset":71053301,"user":"Hopperpop","uid":3664604,"nodes":[1519476746,6533893620,6533893621,6533893622,1519476797,1519476620,1519476746],"tags":{"access":"yes","amenity":"parking"}},{"type":"way","id":695825224,"timestamp":"2019-06-08T15:19:24Z","version":1,"changeset":71053301,"user":"Hopperpop","uid":3664604,"nodes":[1519476744,6533893624,6533893625,6533893626,1519476698,1519476635,1519476744],"tags":{"access":"yes","amenity":"parking"}},{"type":"way","id":696040917,"timestamp":"2019-06-09T23:24:59Z","version":2,"changeset":71082992,"user":"Hopperpop","uid":3664604,"nodes":[6536026850,6536026851,6536026852,6536026853,6536026850],"tags":{"amenity":"parking","name":"Kasteel Tudor"}},{"type":"way","id":696043218,"timestamp":"2019-06-09T23:24:59Z","version":1,"changeset":71082992,"user":"Hopperpop","uid":3664604,"nodes":[6536038234,6536038235,6536038236,6536038237,6536038234],"tags":{"access":"customers","amenity":"parking"}},{"type":"way","id":700675991,"timestamp":"2020-12-18T10:48:20Z","version":2,"changeset":96062619,"user":"Hopperpop","uid":3664604,"nodes":[6579962064,6579962065,6579962066,6579962068,6579962067,6579962064],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":705278707,"timestamp":"2020-09-30T20:36:55Z","version":2,"changeset":91787895,"user":"L'imaginaire","uid":654234,"nodes":[6625037999,6625038000,6625038001,6625038002,6625038003,6004375826,6625038005,6625038006,6625037999],"tags":{"amenity":"parking"}},{"type":"way","id":719482833,"timestamp":"2019-08-28T21:18:49Z","version":1,"changeset":73857967,"user":"Hopperpop","uid":3664604,"nodes":[6754312544,6754312543,6754312542,6754312541,6754312544],"tags":{"access":"yes","amenity":"parking","capacity":"5"}},{"type":"way","id":719482834,"timestamp":"2019-08-28T21:18:49Z","version":1,"changeset":73857967,"user":"Hopperpop","uid":3664604,"nodes":[6754312565,6754312564,6754312563,6754312562,6754312565],"tags":{"access":"yes","amenity":"parking","capacity":"12"}},{"type":"way","id":737054013,"timestamp":"2019-10-20T15:39:32Z","version":1,"changeset":75957554,"user":"Hopperpop","uid":3664604,"nodes":[5826811496,5826811497,5826811494,5826811495,5826811496],"tags":{"amenity":"parking"}},{"type":"way","id":737054014,"timestamp":"2019-10-20T15:39:32Z","version":1,"changeset":75957554,"user":"Hopperpop","uid":3664604,"nodes":[5826810676,5826810673,5826810674,5826810675,5826810676],"tags":{"amenity":"parking"}},{"type":"way","id":737054015,"timestamp":"2019-10-20T15:39:32Z","version":1,"changeset":75957554,"user":"Hopperpop","uid":3664604,"nodes":[5826810681,5826810678,5826810679,5826810680,5826810681],"tags":{"amenity":"parking"}},{"type":"way","id":737093410,"timestamp":"2021-08-14T21:52:07Z","version":2,"changeset":109683899,"user":"effem","uid":16437,"nodes":[5826811559,5826811536,5826811535,5826811561,5826811560,5826811559],"tags":{"access":"yes","amenity":"parking","capacity":"4","fee":"no","parking":"surface"}},{"type":"way","id":737093411,"timestamp":"2021-08-14T21:52:03Z","version":2,"changeset":109683899,"user":"effem","uid":16437,"nodes":[5826811551,5826811547,5826811548,5826811549,5826811550,5826811551],"tags":{"access":"yes","amenity":"parking","capacity":"4","fee":"no","parking":"surface"}},{"type":"way","id":739652949,"timestamp":"2019-10-28T20:18:16Z","version":1,"changeset":76314556,"user":"Hopperpop","uid":3664604,"nodes":[6925536542,6925536541,6925536540,6925536539,6925536542],"tags":{"amenity":"parking","capacity":"6","parking":"surface"}},{"type":"way","id":741675236,"timestamp":"2020-12-17T22:07:55Z","version":4,"changeset":96029554,"user":"Hopperpop","uid":3664604,"nodes":[6943148207,6943148206,6943148205,6943148204,1637742821,6943148203,6943148202,6943148201,6943148200,6943148199,6943148198,6943148197,6943148207],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":742295526,"timestamp":"2019-11-05T19:27:15Z","version":1,"changeset":76664875,"user":"Hopperpop","uid":3664604,"nodes":[6949357909,6949357908,6949357907,6949357906,6949357909],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":742295527,"timestamp":"2019-11-05T19:27:15Z","version":1,"changeset":76664875,"user":"Hopperpop","uid":3664604,"nodes":[6949357913,6949357912,6949357911,6949357910,6949357913],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":742295528,"timestamp":"2019-11-05T19:27:15Z","version":1,"changeset":76664875,"user":"Hopperpop","uid":3664604,"nodes":[6949357917,6949357916,6949357915,6949357914,6949357917],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":742295529,"timestamp":"2019-11-05T19:27:15Z","version":1,"changeset":76664875,"user":"Hopperpop","uid":3664604,"nodes":[6949357921,6949357920,6949357919,6949357918,6949357921],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":746170866,"timestamp":"2019-11-16T15:27:02Z","version":1,"changeset":77167609,"user":"Hopperpop","uid":3664604,"nodes":[6982906547,6982906546,6982906545,6982906544,6982906543,6982906542,6982906547],"tags":{"access":"customers","amenity":"parking"}},{"type":"way","id":747880657,"timestamp":"2021-09-19T12:40:45Z","version":2,"changeset":111407274,"user":"Hopperpop","uid":3664604,"nodes":[3325315397,6997076566,6997076565,6997076563,6997076562,6997076564,3325315395,3325315397],"tags":{"access":"customers","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":763977465,"timestamp":"2020-12-17T21:59:46Z","version":2,"changeset":96029554,"user":"Hopperpop","uid":3664604,"nodes":[7137343680,7137343681,7137343682,7137343683,7137343680],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":763977466,"timestamp":"2020-12-17T21:59:40Z","version":2,"changeset":96029554,"user":"Hopperpop","uid":3664604,"nodes":[7137343684,7137383185,7137383186,7137383187,7137343684],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":803821090,"timestamp":"2020-05-14T17:37:10Z","version":1,"changeset":85215781,"user":"Hopperpop","uid":3664604,"nodes":[7519058290,7519058289,7519058288,7519058287,7519058290],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":803821091,"timestamp":"2020-05-14T17:37:10Z","version":1,"changeset":85215781,"user":"Hopperpop","uid":3664604,"nodes":[7519058294,7519058293,7519058292,7519058291,7519058294],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":803821092,"timestamp":"2020-05-14T17:37:10Z","version":1,"changeset":85215781,"user":"Hopperpop","uid":3664604,"nodes":[7519058298,7519058297,7519058296,7519058295,7519058298],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":803821093,"timestamp":"2020-05-14T17:37:10Z","version":1,"changeset":85215781,"user":"Hopperpop","uid":3664604,"nodes":[7519058302,7519058301,7519058300,7519058299,7519058302],"tags":{"access":"private","amenity":"parking","capacity":"6","parking":"surface"}},{"type":"way","id":804963962,"timestamp":"2020-05-17T17:09:31Z","version":1,"changeset":85342199,"user":"Hopperpop","uid":3664604,"nodes":[7529417225,7529417226,7529417227,7529417228,7529417229,7529417230,7529417232,7529417225],"tags":{"access":"customers","amenity":"parking","fee":"no","operator":"’t Kiekekot","parking":"surface","surface":"unpaved"}},{"type":"way","id":806875503,"timestamp":"2020-05-21T15:48:37Z","version":1,"changeset":85563652,"user":"Hopperpop","uid":3664604,"nodes":[4042671969,7545532512,7545532514,7545532513,3359977305,4042671969],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":806963547,"timestamp":"2020-05-21T21:16:34Z","version":1,"changeset":85574048,"user":"Hopperpop","uid":3664604,"nodes":[7546193222,7546193221,7546193220,7546193219,7546193222],"tags":{"access":"private","amenity":"parking","parking":"surface"}},{"type":"way","id":865357121,"timestamp":"2020-10-30T14:45:23Z","version":1,"changeset":93296961,"user":"L'imaginaire","uid":654234,"nodes":[8065883228,8065883227,8065883226,8065883225,8065883228],"tags":{"amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":865357122,"timestamp":"2020-10-30T14:45:23Z","version":1,"changeset":93296961,"user":"L'imaginaire","uid":654234,"nodes":[8065883233,8065883230,8065883229,8065883232,8065883233],"tags":{"amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":879281221,"timestamp":"2020-11-30T14:18:18Z","version":1,"changeset":95050429,"user":"M!dgard","uid":763799,"nodes":[8179735269,8179735268,8179735267,8179735266,8179735265,8179735264,8179735224,8179735269],"tags":{"access":"customers","amenity":"parking","parking":"surface"}},{"type":"way","id":881770201,"timestamp":"2020-12-07T00:46:56Z","version":1,"changeset":95385582,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[8200275847,8200275848,8200275844,8200275853,8200275849,8200275847],"tags":{"amenity":"parking","parking":"surface","surface":"grass"}},{"type":"way","id":978360549,"timestamp":"2021-09-01T08:53:08Z","version":1,"changeset":110553113,"user":"JanFi","uid":672253,"nodes":[5761770202,5761770204,9052878229,9052878228,5761770202],"tags":{"amenity":"parking"}},{"type":"way","id":1009692722,"timestamp":"2021-12-06T18:34:20Z","version":1,"changeset":114629990,"user":"L'imaginaire","uid":654234,"nodes":[9316118540,9316118536,9316118531,9316118535,9316118534,9316118533,9316118530,9316118532,3311835478,9316118540],"tags":{"amenity":"parking","parking":"street_side"}},{"type":"relation","id":8188853,"timestamp":"2020-07-05T12:38:48Z","version":13,"changeset":87554177,"user":"Pieter Vander Vennet","uid":3818858,"members":[{"type":"way","ref":577572397,"role":"outer"},{"type":"way","ref":577572399,"role":"outer"}],"tags":{"access":"guided","curator":"Luc Maene;Geert De Clercq","email":"lucmaene@hotmail.com;geert.de.clercq1@pandora.be","landuse":"meadow","leisure":"nature_reserve","name":"De Wulgenbroeken","natural":"wetland","operator":"Natuurpunt Brugge","type":"multipolygon","website":"https://natuurpuntbrugge.be/wulgenbroeken/","wetland":"wet_meadow","wikidata":"Q60061498","wikipedia":"nl:Wulgenbroeken"}},{"type":"relation","id":11163488,"timestamp":"2021-10-04T14:09:47Z","version":15,"changeset":112079863,"user":"DieterWesttoer","uid":13062237,"members":[{"type":"way","ref":810604915,"role":"outer"},{"type":"way","ref":989393316,"role":"outer"},{"type":"way","ref":389026405,"role":"inner"},{"type":"way","ref":810607458,"role":"outer"}],"tags":{"access":"yes","curator":"Kris Lesage","description":"Wat Doeveren zo uniek maakt, zijn zijn kleine heidegebiedjes met soorten die erg verschillen van de Kempense heide. Doeveren en omstreken was vroeger één groot heidegebied, maar bestaat nu grotendeels uit bossen.","dog":"leashed","email":"doeveren@natuurpuntzedelgem.be","image":"https://i.imgur.com/NEAsQZG.jpg","image:0":"https://i.imgur.com/Dq71hyQ.jpg","image:1":"https://i.imgur.com/mAIiT4f.jpg","image:2":"https://i.imgur.com/dELZU97.jpg","image:3":"https://i.imgur.com/Bso57JC.jpg","image:4":"https://i.imgur.com/9DtcfXo.jpg","image:5":"https://i.imgur.com/0R6eBfk.jpg","image:6":"https://i.imgur.com/b0JpvbR.jpg","leisure":"nature_reserve","name":"Doeveren","operator":"Natuurpunt Zedelgem","phone":"+32 486 25 25 30","type":"multipolygon","website":"https://www.natuurpuntzedelgem.be/gebieden/doeveren/","wikidata":"Q56395754","wikipedia":"nl:Doeveren (natuurgebied)"}},{"type":"relation","id":11790117,"timestamp":"2020-10-24T19:11:01Z","version":1,"changeset":92997462,"user":"Pieter Vander Vennet","uid":3818858,"members":[{"type":"way","ref":863373849,"role":"outer"},{"type":"way","ref":777280458,"role":"outer"}],"tags":{"access":"no","description:0":"In gebruik als waterbuffering","leisure":"nature_reserve","name":"Kerkebeek","operator":"Natuurpunt Brugge","type":"multipolygon"}},{"type":"node","id":1038638696,"lat":51.1197075,"lon":3.1827007},{"type":"node","id":7578975029,"lat":51.1199041,"lon":3.1828945},{"type":"node","id":7578975030,"lat":51.1201514,"lon":3.1831942},{"type":"node","id":1038638743,"lat":51.1202445,"lon":3.1894878},{"type":"node","id":7578975002,"lat":51.1202598,"lon":3.1897155},{"type":"node","id":7578975007,"lat":51.1199771,"lon":3.1863015},{"type":"node","id":7578975008,"lat":51.1199523,"lon":3.1863031},{"type":"node","id":7578975009,"lat":51.1199279,"lon":3.1859524},{"type":"node","id":1168728109,"lat":51.1275839,"lon":3.1765505},{"type":"node","id":1168728158,"lat":51.1278835,"lon":3.1763986},{"type":"node","id":1168728159,"lat":51.1276298,"lon":3.1767808},{"type":"node","id":5637669355,"lat":51.1276039,"lon":3.1766509},{"type":"node","id":1038638723,"lat":51.1272818,"lon":3.184601},{"type":"node","id":7554434438,"lat":51.1225298,"lon":3.1847624},{"type":"node","id":7578865273,"lat":51.122084,"lon":3.1846859},{"type":"node","id":7578975032,"lat":51.1215762,"lon":3.1842866},{"type":"node","id":1168727876,"lat":51.1290569,"lon":3.1766033},{"type":"node","id":1168728208,"lat":51.1289763,"lon":3.1767696},{"type":"node","id":1168728288,"lat":51.1291195,"lon":3.1766799},{"type":"node","id":1168728325,"lat":51.1279295,"lon":3.1766288},{"type":"node","id":1168728412,"lat":51.1290389,"lon":3.1768463},{"type":"node","id":1038638712,"lat":51.1282367,"lon":3.1840296},{"type":"node","id":1168727824,"lat":51.1312478,"lon":3.182233},{"type":"node","id":3922375256,"lat":51.1301155,"lon":3.1848042},{"type":"node","id":3922380071,"lat":51.1304048,"lon":3.1838954},{"type":"node","id":3922380081,"lat":51.1305694,"lon":3.1845093},{"type":"node","id":3922380086,"lat":51.1306445,"lon":3.1848152},{"type":"node","id":3922380092,"lat":51.1307378,"lon":3.1849591},{"type":"node","id":7577430793,"lat":51.1289492,"lon":3.1836032},{"type":"node","id":7578975024,"lat":51.1299598,"lon":3.1841704},{"type":"node","id":7578975028,"lat":51.1322547,"lon":3.1833542},{"type":"node","id":7578975049,"lat":51.1313772,"lon":3.1838431},{"type":"node","id":9167054153,"lat":51.1310258,"lon":3.1823668},{"type":"node","id":9167054154,"lat":51.13145,"lon":3.1841492},{"type":"node","id":9167054156,"lat":51.1316731,"lon":3.1850331},{"type":"node","id":9274761589,"lat":51.1297088,"lon":3.1831312},{"type":"node","id":9274761596,"lat":51.1296735,"lon":3.1831518},{"type":"node","id":929120698,"lat":51.1276376,"lon":3.1903134},{"type":"node","id":1038638592,"lat":51.1264889,"lon":3.19027},{"type":"node","id":1038638661,"lat":51.1258582,"lon":3.1854626},{"type":"node","id":1038638721,"lat":51.125636,"lon":3.1855855},{"type":"node","id":1038638753,"lat":51.123845,"lon":3.1880289},{"type":"node","id":3921878998,"lat":51.1255719,"lon":3.1902463},{"type":"node","id":3921879004,"lat":51.1275463,"lon":3.188843},{"type":"node","id":3921879011,"lat":51.1271626,"lon":3.1872368},{"type":"node","id":3921879019,"lat":51.1277666,"lon":3.1868505},{"type":"node","id":7554434436,"lat":51.1252645,"lon":3.1852941},{"type":"node","id":7578865274,"lat":51.1230564,"lon":3.187978},{"type":"node","id":7578865275,"lat":51.1226417,"lon":3.188075},{"type":"node","id":7578904489,"lat":51.1247504,"lon":3.1900249},{"type":"node","id":7578974988,"lat":51.1223221,"lon":3.1906513},{"type":"node","id":7578974989,"lat":51.1224255,"lon":3.1905646},{"type":"node","id":7578974990,"lat":51.1224672,"lon":3.1905195},{"type":"node","id":7578974991,"lat":51.1228709,"lon":3.1901867},{"type":"node","id":7578974992,"lat":51.1229568,"lon":3.1901459},{"type":"node","id":7578974995,"lat":51.123814,"lon":3.1899138},{"type":"node","id":7578974996,"lat":51.1239199,"lon":3.189925},{"type":"node","id":7578974997,"lat":51.1244111,"lon":3.1899686},{"type":"node","id":7578974998,"lat":51.1248503,"lon":3.190215},{"type":"node","id":7578974999,"lat":51.1247917,"lon":3.1900516},{"type":"node","id":7578975000,"lat":51.1248293,"lon":3.1900978},{"type":"node","id":7578975001,"lat":51.1248444,"lon":3.1901483},{"type":"node","id":7578975035,"lat":51.1250798,"lon":3.1851611},{"type":"node","id":7578975045,"lat":51.1278881,"lon":3.1882941},{"type":"node","id":9199177059,"lat":51.1256647,"lon":3.1855696},{"type":"node","id":7578987409,"lat":51.1232707,"lon":3.1920382},{"type":"node","id":7578987413,"lat":51.1260416,"lon":3.1973652},{"type":"node","id":7578987414,"lat":51.1263443,"lon":3.1973775},{"type":"node","id":7578987416,"lat":51.1278708,"lon":3.1974134},{"type":"node","id":7578987417,"lat":51.126749,"lon":3.197258},{"type":"node","id":1675648152,"lat":51.1281877,"lon":3.1903323},{"type":"node","id":2732486274,"lat":51.1302553,"lon":3.1886305},{"type":"node","id":3921879018,"lat":51.1280809,"lon":3.188102},{"type":"node","id":3922380061,"lat":51.1301929,"lon":3.1895402},{"type":"node","id":3922380083,"lat":51.1305788,"lon":3.1884337},{"type":"node","id":3922380095,"lat":51.130784,"lon":3.1852632},{"type":"node","id":7578865281,"lat":51.1283938,"lon":3.1903716},{"type":"node","id":7578865283,"lat":51.1288414,"lon":3.1904911},{"type":"node","id":7578960079,"lat":51.1303025,"lon":3.1855669},{"type":"node","id":7578975012,"lat":51.1294792,"lon":3.1906231},{"type":"node","id":7578975015,"lat":51.1297374,"lon":3.1907018},{"type":"node","id":7578975016,"lat":51.1300451,"lon":3.1907679},{"type":"node","id":7578975018,"lat":51.1305785,"lon":3.186668},{"type":"node","id":7578975019,"lat":51.130956,"lon":3.1881852},{"type":"node","id":7578975021,"lat":51.1303082,"lon":3.1855908},{"type":"node","id":7578975026,"lat":51.1310167,"lon":3.1861981},{"type":"node","id":7578975027,"lat":51.1318642,"lon":3.1857905},{"type":"node","id":7578975040,"lat":51.1280348,"lon":3.1889503},{"type":"node","id":7578975044,"lat":51.1279308,"lon":3.1875031},{"type":"node","id":7578975046,"lat":51.1279329,"lon":3.1881992},{"type":"node","id":9167054157,"lat":51.1308023,"lon":3.1852517},{"type":"node","id":9274761591,"lat":51.1310994,"lon":3.1862668},{"type":"node","id":9274761592,"lat":51.1310643,"lon":3.1862655},{"type":"node","id":9274761593,"lat":51.1310386,"lon":3.1862393},{"type":"node","id":7578987418,"lat":51.128003,"lon":3.1959031},{"type":"node","id":7578987419,"lat":51.1282167,"lon":3.193723},{"type":"node","id":5745833239,"lat":51.1258572,"lon":3.1996713},{"type":"node","id":5745833240,"lat":51.1257519,"lon":3.1995939},{"type":"node","id":5745833241,"lat":51.1253365,"lon":3.1991234},{"type":"node","id":7578987410,"lat":51.1243814,"lon":3.1988516},{"type":"node","id":7578987411,"lat":51.1243992,"lon":3.1989686},{"type":"node","id":7578987412,"lat":51.1259883,"lon":3.1997074},{"type":"node","id":7578987415,"lat":51.1260745,"lon":3.1997142},{"type":"node","id":1590642829,"lat":51.1333867,"lon":3.2308055},{"type":"node","id":1590642832,"lat":51.1334371,"lon":3.2308262},{"type":"node","id":1590642849,"lat":51.1336392,"lon":3.2305316},{"type":"node","id":1590642858,"lat":51.133659,"lon":3.2303991},{"type":"node","id":1590642859,"lat":51.1336899,"lon":3.2305508},{"type":"node","id":1590642860,"lat":51.1337096,"lon":3.2304183},{"type":"node","id":1590642828,"lat":51.1333653,"lon":3.2309374},{"type":"node","id":1590642830,"lat":51.1334157,"lon":3.2309581},{"type":"node","id":3311835478,"lat":51.133195,"lon":3.2334351},{"type":"node","id":9316118530,"lat":51.1331607,"lon":3.2333604},{"type":"node","id":9316118531,"lat":51.1330927,"lon":3.2334241},{"type":"node","id":9316118532,"lat":51.1331767,"lon":3.233347},{"type":"node","id":9316118533,"lat":51.133147,"lon":3.2333808},{"type":"node","id":9316118534,"lat":51.1331302,"lon":3.2334006},{"type":"node","id":9316118535,"lat":51.1331127,"lon":3.2334144},{"type":"node","id":9316118536,"lat":51.1330784,"lon":3.2334281},{"type":"node","id":9316118540,"lat":51.1330946,"lon":3.2335103},{"type":"node","id":6579962064,"lat":51.1367061,"lon":3.1640546},{"type":"node","id":6579962065,"lat":51.1361156,"lon":3.1646435},{"type":"node","id":6579962066,"lat":51.1357413,"lon":3.1637334},{"type":"node","id":6579962067,"lat":51.1359511,"lon":3.1637408},{"type":"node","id":6579962068,"lat":51.1359389,"lon":3.1638093},{"type":"node","id":7546193219,"lat":51.1456739,"lon":3.1637073},{"type":"node","id":7546193220,"lat":51.1455706,"lon":3.1643444},{"type":"node","id":7546193221,"lat":51.1456623,"lon":3.1643821},{"type":"node","id":7546193222,"lat":51.1457656,"lon":3.1637451},{"type":"node","id":3359977305,"lat":51.1464982,"lon":3.1689911},{"type":"node","id":4042671969,"lat":51.1461398,"lon":3.169233},{"type":"node","id":7545532512,"lat":51.1463103,"lon":3.169498},{"type":"node","id":7545532513,"lat":51.1466008,"lon":3.1695349},{"type":"node","id":7545532514,"lat":51.1464331,"lon":3.16962},{"type":"node","id":8200275848,"lat":51.1409105,"lon":3.1800288},{"type":"node","id":8200275844,"lat":51.1416967,"lon":3.1797728},{"type":"node","id":8200275847,"lat":51.1411211,"lon":3.1805153},{"type":"node","id":8200275849,"lat":51.1417397,"lon":3.1802115},{"type":"node","id":8200275853,"lat":51.1417351,"lon":3.1801651},{"type":"node","id":111759500,"lat":51.1483444,"lon":3.1886487},{"type":"node","id":1169056712,"lat":51.1482974,"lon":3.1884805},{"type":"node","id":3325315226,"lat":51.147926,"lon":3.1887015},{"type":"node","id":3325315230,"lat":51.1479856,"lon":3.1889124},{"type":"node","id":3325315232,"lat":51.1480454,"lon":3.1891027},{"type":"node","id":3325315243,"lat":51.1483285,"lon":3.1885919},{"type":"node","id":3325315247,"lat":51.1484007,"lon":3.1888131},{"type":"node","id":5826810673,"lat":51.1512507,"lon":3.1914885},{"type":"node","id":5826810674,"lat":51.15126,"lon":3.1914533},{"type":"node","id":5826810675,"lat":51.1510883,"lon":3.1912776},{"type":"node","id":5826810676,"lat":51.151057,"lon":3.1912906},{"type":"node","id":5826810678,"lat":51.1509897,"lon":3.1911759},{"type":"node","id":5826810679,"lat":51.1510025,"lon":3.1911334},{"type":"node","id":5826810680,"lat":51.1509352,"lon":3.1908874},{"type":"node","id":5826810681,"lat":51.1509074,"lon":3.1908689},{"type":"node","id":5826811494,"lat":51.1512125,"lon":3.1911315},{"type":"node","id":5826811495,"lat":51.1512055,"lon":3.191187},{"type":"node","id":5826811496,"lat":51.151296,"lon":3.1914182},{"type":"node","id":5826811497,"lat":51.1513261,"lon":3.1914182},{"type":"node","id":5826811535,"lat":51.1517839,"lon":3.1959375},{"type":"node","id":5826811536,"lat":51.1518581,"lon":3.1959708},{"type":"node","id":5826811547,"lat":51.1515913,"lon":3.196115},{"type":"node","id":5826811548,"lat":51.1516307,"lon":3.1961465},{"type":"node","id":5826811549,"lat":51.1516435,"lon":3.1961076},{"type":"node","id":5826811550,"lat":51.1516087,"lon":3.1959541},{"type":"node","id":5826811551,"lat":51.1515437,"lon":3.1959024},{"type":"node","id":5826811559,"lat":51.1517896,"lon":3.1957717},{"type":"node","id":5826811560,"lat":51.1517417,"lon":3.1957528},{"type":"node","id":5826811561,"lat":51.1517365,"lon":3.1957872},{"type":"node","id":3325315395,"lat":51.1544187,"lon":3.1856685},{"type":"node","id":3325315397,"lat":51.1545358,"lon":3.1860117},{"type":"node","id":3930713426,"lat":51.1571474,"lon":3.1889324},{"type":"node","id":3930713429,"lat":51.1573669,"lon":3.1883265},{"type":"node","id":3930713430,"lat":51.1573202,"lon":3.1890776},{"type":"node","id":3930713435,"lat":51.1574561,"lon":3.1883916},{"type":"node","id":3930713437,"lat":51.1574971,"lon":3.1893349},{"type":"node","id":3930713438,"lat":51.1574907,"lon":3.1884223},{"type":"node","id":3930713440,"lat":51.1575693,"lon":3.1890951},{"type":"node","id":3930713442,"lat":51.1575932,"lon":3.1879961},{"type":"node","id":3930713446,"lat":51.1577118,"lon":3.1885611},{"type":"node","id":3930713447,"lat":51.157698,"lon":3.1894886},{"type":"node","id":3930713451,"lat":51.1577702,"lon":3.1892488},{"type":"node","id":3930713454,"lat":51.1577969,"lon":3.1882567},{"type":"node","id":4043782112,"lat":51.1549447,"lon":3.1864571},{"type":"node","id":5552466013,"lat":51.1545783,"lon":3.1874672},{"type":"node","id":5552466014,"lat":51.1543143,"lon":3.1873045},{"type":"node","id":5552466018,"lat":51.1545999,"lon":3.1873846},{"type":"node","id":5552466020,"lat":51.1548079,"lon":3.1868846},{"type":"node","id":5825400688,"lat":51.1549303,"lon":3.1867969},{"type":"node","id":5826811614,"lat":51.1572659,"lon":3.1885288},{"type":"node","id":6949357906,"lat":51.1572911,"lon":3.1915323},{"type":"node","id":6949357909,"lat":51.1573109,"lon":3.1914572},{"type":"node","id":6949357910,"lat":51.1574373,"lon":3.1913744},{"type":"node","id":6949357911,"lat":51.1574179,"lon":3.1914502},{"type":"node","id":6949357912,"lat":51.1575109,"lon":3.1915112},{"type":"node","id":6949357913,"lat":51.1575304,"lon":3.1914354},{"type":"node","id":6949357914,"lat":51.1574638,"lon":3.1912712},{"type":"node","id":6949357915,"lat":51.1574444,"lon":3.1913473},{"type":"node","id":6949357916,"lat":51.1575599,"lon":3.191423},{"type":"node","id":6949357917,"lat":51.1575803,"lon":3.1913473},{"type":"node","id":6949357918,"lat":51.157501,"lon":3.1911303},{"type":"node","id":6949357919,"lat":51.1574808,"lon":3.1912058},{"type":"node","id":6949357920,"lat":51.1577374,"lon":3.1913724},{"type":"node","id":6949357921,"lat":51.1577563,"lon":3.1912987},{"type":"node","id":6982605752,"lat":51.1574664,"lon":3.1885975},{"type":"node","id":6982605754,"lat":51.1574428,"lon":3.1885793},{"type":"node","id":6982605762,"lat":51.1576066,"lon":3.1884793},{"type":"node","id":6982605764,"lat":51.1576853,"lon":3.18854},{"type":"node","id":6982605766,"lat":51.1575125,"lon":3.1884502},{"type":"node","id":6982605767,"lat":51.1575959,"lon":3.1885145},{"type":"node","id":6982605769,"lat":51.1575152,"lon":3.1884412},{"type":"node","id":6982906542,"lat":51.1591649,"lon":3.1904238},{"type":"node","id":6982906543,"lat":51.1592937,"lon":3.1905221},{"type":"node","id":6982906544,"lat":51.1593438,"lon":3.1903659},{"type":"node","id":6982906545,"lat":51.1593158,"lon":3.1903453},{"type":"node","id":6982906546,"lat":51.1593351,"lon":3.1902852},{"type":"node","id":6982906547,"lat":51.1592385,"lon":3.1902052},{"type":"node","id":6997076562,"lat":51.1546633,"lon":3.1858333},{"type":"node","id":6997076563,"lat":51.1546293,"lon":3.1858642},{"type":"node","id":6997076564,"lat":51.154594,"lon":3.1856715},{"type":"node","id":6997076565,"lat":51.1546727,"lon":3.1859889},{"type":"node","id":6997076566,"lat":51.1545545,"lon":3.1860687},{"type":"node","id":6997076567,"lat":51.1543063,"lon":3.1869337},{"type":"node","id":6997096756,"lat":51.1547387,"lon":3.1868376},{"type":"node","id":6997096758,"lat":51.1546899,"lon":3.1870707},{"type":"node","id":6997096759,"lat":51.1546751,"lon":3.1870601},{"type":"node","id":7137343680,"lat":51.1558646,"lon":3.1876808},{"type":"node","id":7137343681,"lat":51.1558466,"lon":3.1877456},{"type":"node","id":7137343682,"lat":51.1555824,"lon":3.187559},{"type":"node","id":7137343683,"lat":51.1556004,"lon":3.1874941},{"type":"node","id":7137343684,"lat":51.1555549,"lon":3.1874612},{"type":"node","id":7137383185,"lat":51.1555369,"lon":3.1875268},{"type":"node","id":7137383186,"lat":51.1553925,"lon":3.1874261},{"type":"node","id":7137383187,"lat":51.1554105,"lon":3.1873604},{"type":"node","id":7519058287,"lat":51.1555296,"lon":3.1858152},{"type":"node","id":7519058288,"lat":51.1555027,"lon":3.1858752},{"type":"node","id":7519058289,"lat":51.1556329,"lon":3.1860234},{"type":"node","id":7519058290,"lat":51.1556597,"lon":3.1859634},{"type":"node","id":7519058291,"lat":51.1557039,"lon":3.1860155},{"type":"node","id":7519058292,"lat":51.1556789,"lon":3.1860736},{"type":"node","id":7519058293,"lat":51.1558105,"lon":3.1862177},{"type":"node","id":7519058294,"lat":51.1558355,"lon":3.1861597},{"type":"node","id":7519058295,"lat":51.1557209,"lon":3.185828},{"type":"node","id":7519058296,"lat":51.1556932,"lon":3.1858902},{"type":"node","id":7519058297,"lat":51.1558686,"lon":3.1860888},{"type":"node","id":7519058298,"lat":51.1558963,"lon":3.1860265},{"type":"node","id":7519058299,"lat":51.1555421,"lon":3.1856365},{"type":"node","id":7519058300,"lat":51.1555168,"lon":3.1856923},{"type":"node","id":7519058301,"lat":51.1556479,"lon":3.1858437},{"type":"node","id":7519058302,"lat":51.1556732,"lon":3.1857879},{"type":"node","id":150996092,"lat":51.1554945,"lon":3.1954639},{"type":"node","id":150996093,"lat":51.155531,"lon":3.1953168},{"type":"node","id":150996094,"lat":51.1554912,"lon":3.1943936},{"type":"node","id":150996095,"lat":51.155456,"lon":3.1942488},{"type":"node","id":150996097,"lat":51.155432,"lon":3.1942095},{"type":"node","id":150996098,"lat":51.155397,"lon":3.1941906},{"type":"node","id":150996099,"lat":51.1552938,"lon":3.1945134},{"type":"node","id":150996100,"lat":51.1552701,"lon":3.1949002},{"type":"node","id":150996101,"lat":51.1553901,"lon":3.1953415},{"type":"node","id":1015567837,"lat":51.1603457,"lon":3.1926746},{"type":"node","id":1015583939,"lat":51.1598982,"lon":3.1934595},{"type":"node","id":1659850846,"lat":51.1562462,"lon":3.1925019},{"type":"node","id":1811699776,"lat":51.1604859,"lon":3.1920734},{"type":"node","id":1811699777,"lat":51.1605587,"lon":3.1917984},{"type":"node","id":1817319289,"lat":51.1599853,"lon":3.1935159},{"type":"node","id":1817319290,"lat":51.1600476,"lon":3.1933385},{"type":"node","id":1817319291,"lat":51.1600745,"lon":3.1934309},{"type":"node","id":1817319292,"lat":51.1602073,"lon":3.1941751},{"type":"node","id":1817319293,"lat":51.160208,"lon":3.1941098},{"type":"node","id":1817319294,"lat":51.1602178,"lon":3.1935425},{"type":"node","id":1817319295,"lat":51.1602385,"lon":3.19297},{"type":"node","id":1817319296,"lat":51.1602972,"lon":3.1940248},{"type":"node","id":1817319297,"lat":51.1603313,"lon":3.193809},{"type":"node","id":1817319298,"lat":51.1603427,"lon":3.1930326},{"type":"node","id":1817319299,"lat":51.1603716,"lon":3.1940192},{"type":"node","id":1817319300,"lat":51.1603777,"lon":3.1946319},{"type":"node","id":1817319301,"lat":51.1604665,"lon":3.193304},{"type":"node","id":1817319302,"lat":51.1604758,"lon":3.1939077},{"type":"node","id":1817319303,"lat":51.1605421,"lon":3.194476},{"type":"node","id":1817319304,"lat":51.1606037,"lon":3.1933895},{"type":"node","id":1817320493,"lat":51.1604248,"lon":3.1927398},{"type":"node","id":1817320494,"lat":51.1604851,"lon":3.192495},{"type":"node","id":2451569392,"lat":51.1598651,"lon":3.1919974},{"type":"node","id":2451574741,"lat":51.1594995,"lon":3.1924908},{"type":"node","id":2451574742,"lat":51.1596217,"lon":3.1923259},{"type":"node","id":2451574743,"lat":51.1597161,"lon":3.1922023},{"type":"node","id":2451574744,"lat":51.1600391,"lon":3.1932123},{"type":"node","id":2451574745,"lat":51.1601904,"lon":3.192947},{"type":"node","id":2451574746,"lat":51.1603862,"lon":3.1925461},{"type":"node","id":2451574747,"lat":51.1604272,"lon":3.19257},{"type":"node","id":2451574748,"lat":51.1604837,"lon":3.1921535},{"type":"node","id":2451574749,"lat":51.1605266,"lon":3.1921769},{"type":"node","id":2451578121,"lat":51.159758,"lon":3.1921448},{"type":"node","id":5587844460,"lat":51.1562664,"lon":3.1919544},{"type":"node","id":5587844461,"lat":51.15612,"lon":3.1920681},{"type":"node","id":5587844462,"lat":51.1561808,"lon":3.1922614},{"type":"node","id":5599314384,"lat":51.1563882,"lon":3.1923707},{"type":"node","id":5599314385,"lat":51.1563587,"lon":3.1924465},{"type":"node","id":6754312541,"lat":51.154716,"lon":3.1952084},{"type":"node","id":6754312542,"lat":51.1547723,"lon":3.1953372},{"type":"node","id":6754312543,"lat":51.1548078,"lon":3.1952983},{"type":"node","id":6754312544,"lat":51.1547519,"lon":3.1951702},{"type":"node","id":6754312550,"lat":51.1555879,"lon":3.1950341},{"type":"node","id":6754312551,"lat":51.1556025,"lon":3.194956},{"type":"node","id":6754312552,"lat":51.1555664,"lon":3.1952408},{"type":"node","id":6754312553,"lat":51.1556188,"lon":3.1951751},{"type":"node","id":6754312554,"lat":51.1554565,"lon":3.195427},{"type":"node","id":6754312555,"lat":51.1552894,"lon":3.1950649},{"type":"node","id":6754312556,"lat":51.1553277,"lon":3.1951991},{"type":"node","id":6754312557,"lat":51.1552774,"lon":3.1947027},{"type":"node","id":6754312558,"lat":51.1553131,"lon":3.1943816},{"type":"node","id":6754312559,"lat":51.1553397,"lon":3.1942577},{"type":"node","id":6754312560,"lat":51.1553697,"lon":3.1942084},{"type":"node","id":6754312562,"lat":51.1548064,"lon":3.1954209},{"type":"node","id":6754312563,"lat":51.1548266,"lon":3.1954893},{"type":"node","id":6754312564,"lat":51.1550417,"lon":3.1953175},{"type":"node","id":6754312565,"lat":51.1550193,"lon":3.1952538},{"type":"node","id":6870850178,"lat":51.1561935,"lon":3.1923019},{"type":"node","id":6870863414,"lat":51.1562489,"lon":3.1919675},{"type":"node","id":6949357907,"lat":51.1575239,"lon":3.1916859},{"type":"node","id":6949357908,"lat":51.1575439,"lon":3.1916101},{"type":"node","id":1448421081,"lat":51.167491,"lon":3.1713256},{"type":"node","id":1448421091,"lat":51.1677042,"lon":3.1714548},{"type":"node","id":1448421093,"lat":51.1677455,"lon":3.1702529},{"type":"node","id":1448421099,"lat":51.1679647,"lon":3.1703977},{"type":"node","id":6536026850,"lat":51.1711159,"lon":3.1669401},{"type":"node","id":6536026851,"lat":51.1712692,"lon":3.167296},{"type":"node","id":6536026852,"lat":51.1711296,"lon":3.1674712},{"type":"node","id":6536026853,"lat":51.1709602,"lon":3.1671189},{"type":"node","id":6536038234,"lat":51.1711913,"lon":3.165543},{"type":"node","id":6536038235,"lat":51.1711301,"lon":3.1656263},{"type":"node","id":6536038236,"lat":51.1712318,"lon":3.1658161},{"type":"node","id":6536038237,"lat":51.171293,"lon":3.1657327},{"type":"node","id":1038583451,"lat":51.1625071,"lon":3.191602},{"type":"node","id":4044171936,"lat":51.1609177,"lon":3.1911926},{"type":"node","id":4044171941,"lat":51.1609801,"lon":3.191229},{"type":"node","id":4044171963,"lat":51.1611962,"lon":3.1913534},{"type":"node","id":903903386,"lat":51.1618084,"lon":3.1932127},{"type":"node","id":903903387,"lat":51.1623536,"lon":3.1936011},{"type":"node","id":903903388,"lat":51.1624429,"lon":3.1931156},{"type":"node","id":903903390,"lat":51.1618641,"lon":3.1930197},{"type":"node","id":903904576,"lat":51.1618211,"lon":3.1931711},{"type":"node","id":1038557012,"lat":51.16155,"lon":3.1931121},{"type":"node","id":1038557014,"lat":51.1613774,"lon":3.1930711},{"type":"node","id":1038557035,"lat":51.1615349,"lon":3.1931712},{"type":"node","id":1038557072,"lat":51.1616138,"lon":3.1927483},{"type":"node","id":1038557075,"lat":51.162286,"lon":3.1935989},{"type":"node","id":1038557078,"lat":51.1616517,"lon":3.1928439},{"type":"node","id":1038557083,"lat":51.1616055,"lon":3.1930249},{"type":"node","id":1038557094,"lat":51.1618993,"lon":3.193299},{"type":"node","id":1038557102,"lat":51.1613235,"lon":3.1927138},{"type":"node","id":1038557104,"lat":51.1615987,"lon":3.1928077},{"type":"node","id":1038557108,"lat":51.1615113,"lon":3.1926816},{"type":"node","id":1038557137,"lat":51.1608873,"lon":3.1924416},{"type":"node","id":1038557143,"lat":51.1622248,"lon":3.193662},{"type":"node","id":1038557191,"lat":51.1608171,"lon":3.1926951},{"type":"node","id":1038557195,"lat":51.162409,"lon":3.1933428},{"type":"node","id":1038557227,"lat":51.1613767,"lon":3.1925113},{"type":"node","id":1038557230,"lat":51.1615281,"lon":3.1926132},{"type":"node","id":1038557233,"lat":51.1619765,"lon":3.1933723},{"type":"node","id":1038575040,"lat":51.1608523,"lon":3.1925679},{"type":"node","id":1038583375,"lat":51.1625113,"lon":3.1926776},{"type":"node","id":1038583398,"lat":51.1624305,"lon":3.1925743},{"type":"node","id":1038583404,"lat":51.1627055,"lon":3.191826},{"type":"node","id":1038583425,"lat":51.1624272,"lon":3.1916637},{"type":"node","id":1038583441,"lat":51.1621479,"lon":3.1921546},{"type":"node","id":1038583446,"lat":51.1622018,"lon":3.1921814},{"type":"node","id":1038583456,"lat":51.162174,"lon":3.1922806},{"type":"node","id":1038583459,"lat":51.162259,"lon":3.1924885},{"type":"node","id":1038583463,"lat":51.162661,"lon":3.1917442},{"type":"node","id":1038583476,"lat":51.1626425,"lon":3.1918448},{"type":"node","id":1038583479,"lat":51.1624196,"lon":3.1926561},{"type":"node","id":1038583483,"lat":51.1625037,"lon":3.1927232},{"type":"node","id":1038583491,"lat":51.1625701,"lon":3.1926387},{"type":"node","id":1038583501,"lat":51.1624928,"lon":3.1917013},{"type":"node","id":1811673418,"lat":51.1618484,"lon":3.1950253},{"type":"node","id":1811673421,"lat":51.1619875,"lon":3.1951427},{"type":"node","id":1811673423,"lat":51.162144,"lon":3.193835},{"type":"node","id":1811673425,"lat":51.1622452,"lon":3.1939149},{"type":"node","id":1811699778,"lat":51.1608187,"lon":3.1922973},{"type":"node","id":1811699779,"lat":51.1608915,"lon":3.1920223},{"type":"node","id":1817320495,"lat":51.1607269,"lon":3.192929},{"type":"node","id":1817320496,"lat":51.1607872,"lon":3.1926841},{"type":"node","id":1817324488,"lat":51.1615575,"lon":3.1921423},{"type":"node","id":1817324489,"lat":51.1612682,"lon":3.1920196},{"type":"node","id":1817324491,"lat":51.1617501,"lon":3.1918468},{"type":"node","id":1817324505,"lat":51.1618272,"lon":3.1921231},{"type":"node","id":1817324509,"lat":51.1618658,"lon":3.191793},{"type":"node","id":1817324513,"lat":51.1619814,"lon":3.1920002},{"type":"node","id":1817324515,"lat":51.161985,"lon":3.191793},{"type":"node","id":3550860268,"lat":51.1617349,"lon":3.1921922},{"type":"node","id":3550860269,"lat":51.1619403,"lon":3.1920686},{"type":"node","id":4044171924,"lat":51.1608199,"lon":3.1916126},{"type":"node","id":4044171954,"lat":51.1610853,"lon":3.191781},{"type":"node","id":4044171957,"lat":51.1611433,"lon":3.1918701},{"type":"node","id":4044171962,"lat":51.1611926,"lon":3.1916807},{"type":"node","id":4044171976,"lat":51.1612826,"lon":3.1919582},{"type":"node","id":4044171997,"lat":51.1613568,"lon":3.1917787},{"type":"node","id":4044172003,"lat":51.1613248,"lon":3.1919027},{"type":"node","id":4044172008,"lat":51.1614345,"lon":3.1919767},{"type":"node","id":6397031888,"lat":51.1615029,"lon":3.1919851},{"type":"node","id":6960473080,"lat":51.1614227,"lon":3.1931004},{"type":"node","id":3335137692,"lat":51.1698302,"lon":3.1965654},{"type":"node","id":3335137795,"lat":51.1698788,"lon":3.1970728},{"type":"node","id":3335137802,"lat":51.1700082,"lon":3.1971734},{"type":"node","id":3335137807,"lat":51.1701139,"lon":3.1965001},{"type":"node","id":3335137812,"lat":51.1703247,"lon":3.197352},{"type":"node","id":3335137823,"lat":51.1703133,"lon":3.1966232},{"type":"node","id":6255587427,"lat":51.1694775,"lon":3.1980047},{"type":"node","id":9163486855,"lat":51.1703854,"lon":3.1970901},{"type":"node","id":9163486856,"lat":51.1702114,"lon":3.1969688},{"type":"node","id":9163493632,"lat":51.1699473,"lon":3.197063},{"type":"node","id":414025563,"lat":51.1768198,"lon":3.1839265},{"type":"node","id":2325437840,"lat":51.1765747,"lon":3.1839745},{"type":"node","id":2325437844,"lat":51.1768286,"lon":3.1825946},{"type":"node","id":8191691970,"lat":51.1767611,"lon":3.1839766},{"type":"node","id":8191691971,"lat":51.1767812,"lon":3.1826167},{"type":"node","id":8191691972,"lat":51.1765804,"lon":3.1826583},{"type":"node","id":8191691973,"lat":51.1766324,"lon":3.182616},{"type":"node","id":5716136617,"lat":51.1773127,"lon":3.1969033},{"type":"node","id":5716136618,"lat":51.1771859,"lon":3.1969078},{"type":"node","id":5716136619,"lat":51.177203,"lon":3.1981369},{"type":"node","id":5716136620,"lat":51.1773298,"lon":3.1981324},{"type":"node","id":6004375826,"lat":51.1786839,"lon":3.1952389},{"type":"node","id":6625037999,"lat":51.1788016,"lon":3.1950645},{"type":"node","id":6625038000,"lat":51.1789916,"lon":3.1966631},{"type":"node","id":6625038001,"lat":51.1789003,"lon":3.1966838},{"type":"node","id":6625038002,"lat":51.1788554,"lon":3.1963547},{"type":"node","id":6625038003,"lat":51.1788165,"lon":3.1963622},{"type":"node","id":6625038005,"lat":51.1785124,"lon":3.1952362},{"type":"node","id":6625038006,"lat":51.1784779,"lon":3.1950618},{"type":"node","id":6925536539,"lat":51.1522475,"lon":3.1985416},{"type":"node","id":6925536540,"lat":51.1522635,"lon":3.1986187},{"type":"node","id":6925536541,"lat":51.1523922,"lon":3.1985517},{"type":"node","id":6925536542,"lat":51.1523766,"lon":3.1984746},{"type":"node","id":1637742821,"lat":51.158524,"lon":3.199021},{"type":"node","id":5586765933,"lat":51.1566667,"lon":3.2008881},{"type":"node","id":5586765934,"lat":51.1564286,"lon":3.2012575},{"type":"node","id":5586765935,"lat":51.1562496,"lon":3.2008579},{"type":"node","id":5586765936,"lat":51.1564982,"lon":3.200522},{"type":"node","id":6943148197,"lat":51.1581916,"lon":3.1989071},{"type":"node","id":6943148198,"lat":51.1582377,"lon":3.1989899},{"type":"node","id":6943148199,"lat":51.1581859,"lon":3.1990728},{"type":"node","id":6943148200,"lat":51.1583257,"lon":3.199295},{"type":"node","id":6943148201,"lat":51.1583563,"lon":3.199246},{"type":"node","id":6943148202,"lat":51.1583988,"lon":3.1993135},{"type":"node","id":6943148203,"lat":51.1585529,"lon":3.1990669},{"type":"node","id":6943148204,"lat":51.1586554,"lon":3.1988109},{"type":"node","id":6943148205,"lat":51.1585617,"lon":3.1986619},{"type":"node","id":6943148206,"lat":51.1586782,"lon":3.1984755},{"type":"node","id":6943148207,"lat":51.1585692,"lon":3.1982996},{"type":"node","id":8065883225,"lat":51.1366029,"lon":3.233506},{"type":"node","id":8065883226,"lat":51.1364627,"lon":3.2335338},{"type":"node","id":8065883227,"lat":51.1363922,"lon":3.2326314},{"type":"node","id":8065883228,"lat":51.1365324,"lon":3.2326036},{"type":"node","id":8065883229,"lat":51.1374344,"lon":3.2333338},{"type":"node","id":8065883230,"lat":51.1373632,"lon":3.2324534},{"type":"node","id":8065883232,"lat":51.1375819,"lon":3.2333035},{"type":"node","id":8065883233,"lat":51.1375107,"lon":3.232423},{"type":"node","id":1795793393,"lat":51.1475704,"lon":3.233832},{"type":"node","id":3346575840,"lat":51.146485,"lon":3.2349284},{"type":"node","id":3346575846,"lat":51.1465127,"lon":3.2355341},{"type":"node","id":3346575853,"lat":51.1466617,"lon":3.2349708},{"type":"node","id":3346575855,"lat":51.1466787,"lon":3.2355171},{"type":"node","id":3346575858,"lat":51.1466968,"lon":3.2342532},{"type":"node","id":3346575865,"lat":51.1468756,"lon":3.2344143},{"type":"node","id":3346575873,"lat":51.1469706,"lon":3.2366779},{"type":"node","id":3346575929,"lat":51.1474307,"lon":3.2366434},{"type":"node","id":1523513488,"lat":51.1398248,"lon":3.2392608},{"type":"node","id":1744641292,"lat":51.1395814,"lon":3.2390365},{"type":"node","id":1744641293,"lat":51.1397822,"lon":3.2393867},{"type":"node","id":1920143232,"lat":51.1394724,"lon":3.2390121},{"type":"node","id":7393009684,"lat":51.1394307,"lon":3.2390001},{"type":"node","id":7393048385,"lat":51.1394135,"lon":3.2390524},{"type":"node","id":3346575843,"lat":51.1465041,"lon":3.2376453},{"type":"node","id":3346575845,"lat":51.146508,"lon":3.2378517},{"type":"node","id":3346575876,"lat":51.1470052,"lon":3.237604},{"type":"node","id":3346575886,"lat":51.147098,"lon":3.2412975},{"type":"node","id":3346575889,"lat":51.1471585,"lon":3.2428761},{"type":"node","id":3346575891,"lat":51.1471715,"lon":3.2377865},{"type":"node","id":3346575901,"lat":51.1472492,"lon":3.2398591},{"type":"node","id":3346575903,"lat":51.1472654,"lon":3.242623},{"type":"node","id":3346575908,"lat":51.1472751,"lon":3.2428571},{"type":"node","id":3346575917,"lat":51.1473518,"lon":3.2426093},{"type":"node","id":3346575923,"lat":51.1473906,"lon":3.2398205},{"type":"node","id":3346575925,"lat":51.147408,"lon":3.2424474},{"type":"node","id":3346575928,"lat":51.1474263,"lon":3.24062},{"type":"node","id":3346575933,"lat":51.1474728,"lon":3.2421565},{"type":"node","id":3346575943,"lat":51.1475354,"lon":3.2418174},{"type":"node","id":3346575945,"lat":51.1475494,"lon":3.2412786},{"type":"node","id":3346575946,"lat":51.1475667,"lon":3.2415454},{"type":"node","id":6291339815,"lat":51.1434669,"lon":3.2496811},{"type":"node","id":6291339816,"lat":51.1434103,"lon":3.2497287},{"type":"node","id":6291339821,"lat":51.1435685,"lon":3.2496576},{"type":"node","id":6291339822,"lat":51.1434825,"lon":3.2497283},{"type":"node","id":6291339827,"lat":51.1437401,"lon":3.2490327},{"type":"node","id":6291339828,"lat":51.1433037,"lon":3.2494123},{"type":"node","id":6291339829,"lat":51.1436099,"lon":3.2497855},{"type":"node","id":6291339830,"lat":51.1439041,"lon":3.249535},{"type":"node","id":170464837,"lat":51.1533286,"lon":3.236239},{"type":"node","id":170464839,"lat":51.1532379,"lon":3.2364578},{"type":"node","id":1710262731,"lat":51.1513274,"lon":3.2373199},{"type":"node","id":1710262732,"lat":51.1508759,"lon":3.2370371},{"type":"node","id":1710262733,"lat":51.1509316,"lon":3.2370599},{"type":"node","id":1710262735,"lat":51.1510166,"lon":3.2370123},{"type":"node","id":1710262738,"lat":51.1512751,"lon":3.2372984},{"type":"node","id":1710262742,"lat":51.1513127,"lon":3.237065},{"type":"node","id":1710262743,"lat":51.1508201,"lon":3.2373832},{"type":"node","id":1710262745,"lat":51.151027,"lon":3.2369479},{"type":"node","id":1795793395,"lat":51.1476158,"lon":3.2338163},{"type":"node","id":1795793397,"lat":51.1475842,"lon":3.2344427},{"type":"node","id":1795793399,"lat":51.1477641,"lon":3.233033},{"type":"node","id":1795793405,"lat":51.1477717,"lon":3.2338665},{"type":"node","id":1795793406,"lat":51.1480775,"lon":3.2344787},{"type":"node","id":1795793407,"lat":51.1478893,"lon":3.2344203},{"type":"node","id":1795793408,"lat":51.1481719,"lon":3.2342485},{"type":"node","id":1795793409,"lat":51.147607,"lon":3.2330256},{"type":"node","id":4979389763,"lat":51.1476223,"lon":3.2330288},{"type":"node","id":8179735224,"lat":51.156047,"lon":3.2252534},{"type":"node","id":8179735264,"lat":51.1560464,"lon":3.2252785},{"type":"node","id":8179735265,"lat":51.1558544,"lon":3.2252597},{"type":"node","id":8179735266,"lat":51.1556789,"lon":3.2252522},{"type":"node","id":8179735267,"lat":51.1555253,"lon":3.2252547},{"type":"node","id":8179735268,"lat":51.1555747,"lon":3.2250024},{"type":"node","id":8179735269,"lat":51.1560527,"lon":3.2250198},{"type":"node","id":1525460846,"lat":51.1550489,"lon":3.2347709},{"type":"node","id":1810326044,"lat":51.1547625,"lon":3.2355098},{"type":"node","id":1810326087,"lat":51.1547809,"lon":3.2353708},{"type":"node","id":4912203160,"lat":51.1554941,"lon":3.2364781},{"type":"node","id":4912203161,"lat":51.1554192,"lon":3.2369649},{"type":"node","id":4912203162,"lat":51.1554175,"lon":3.2371071},{"type":"node","id":4912203163,"lat":51.1554301,"lon":3.2372063},{"type":"node","id":4912203164,"lat":51.1553847,"lon":3.2372197},{"type":"node","id":4912203165,"lat":51.1553763,"lon":3.2369502},{"type":"node","id":4912203166,"lat":51.1554512,"lon":3.236462},{"type":"node","id":4912203167,"lat":51.1555218,"lon":3.2366455},{"type":"node","id":4912203168,"lat":51.1554742,"lon":3.2369592},{"type":"node","id":4912203169,"lat":51.155516,"lon":3.2369752},{"type":"node","id":4912203170,"lat":51.1555635,"lon":3.2366616},{"type":"node","id":4912203171,"lat":51.1556125,"lon":3.2360775},{"type":"node","id":4912203172,"lat":51.155547,"lon":3.2364923},{"type":"node","id":4912203173,"lat":51.1555893,"lon":3.2365092},{"type":"node","id":4912203174,"lat":51.1556547,"lon":3.2360945},{"type":"node","id":4912203176,"lat":51.1554841,"lon":3.2362949},{"type":"node","id":4912203177,"lat":51.1553752,"lon":3.2362591},{"type":"node","id":4912203178,"lat":51.1553968,"lon":3.2360924},{"type":"node","id":4912203179,"lat":51.1555056,"lon":3.2361281},{"type":"node","id":4912214680,"lat":51.1553544,"lon":3.2348128},{"type":"node","id":4912214681,"lat":51.1550186,"lon":3.2346814},{"type":"node","id":4912214685,"lat":51.1554486,"lon":3.2338965},{"type":"node","id":4912214686,"lat":51.1550098,"lon":3.2346405},{"type":"node","id":4912214692,"lat":51.155386,"lon":3.2347722},{"type":"node","id":4912214693,"lat":51.1555155,"lon":3.2338415},{"type":"node","id":4912214694,"lat":51.1554587,"lon":3.2338214},{"type":"node","id":4912214695,"lat":51.1553292,"lon":3.2347521},{"type":"node","id":4912225050,"lat":51.1553136,"lon":3.234866},{"type":"node","id":4912225051,"lat":51.1551036,"lon":3.2337751},{"type":"node","id":4912225052,"lat":51.1549825,"lon":3.2346307},{"type":"node","id":4912225053,"lat":51.1551894,"lon":3.2336789},{"type":"node","id":4912225062,"lat":51.1551528,"lon":3.233747},{"type":"node","id":4912225063,"lat":51.1551831,"lon":3.2337249},{"type":"node","id":4912225064,"lat":51.1554653,"lon":3.2337755},{"type":"node","id":4912225067,"lat":51.1551309,"lon":3.2337849},{"type":"node","id":4912225068,"lat":51.1551727,"lon":3.2337999},{"type":"node","id":4912225069,"lat":51.1553182,"lon":3.2348322},{"type":"node","id":4912225070,"lat":51.1550516,"lon":3.2346556},{"type":"node","id":5972179331,"lat":51.154488,"lon":3.2350802},{"type":"node","id":5972179343,"lat":51.1545781,"lon":3.2351138},{"type":"node","id":5972179344,"lat":51.1546444,"lon":3.2351409},{"type":"node","id":5972179345,"lat":51.1546431,"lon":3.2351485},{"type":"node","id":5972179346,"lat":51.1547126,"lon":3.2351739},{"type":"node","id":5972179347,"lat":51.154714,"lon":3.2351659},{"type":"node","id":5972179348,"lat":51.1547795,"lon":3.235188},{"type":"node","id":5974489614,"lat":51.1546386,"lon":3.2355125},{"type":"node","id":5974489615,"lat":51.1544914,"lon":3.2353516},{"type":"node","id":5974489616,"lat":51.1544813,"lon":3.2351384},{"type":"node","id":5974489617,"lat":51.1548024,"lon":3.2352003},{"type":"node","id":5974489618,"lat":51.154732,"lon":3.2356091},{"type":"node","id":7529417225,"lat":51.159095,"lon":3.2366844},{"type":"node","id":7529417226,"lat":51.1589926,"lon":3.2372825},{"type":"node","id":7529417227,"lat":51.1588687,"lon":3.2372286},{"type":"node","id":7529417228,"lat":51.1589264,"lon":3.2368918},{"type":"node","id":7529417229,"lat":51.1588879,"lon":3.236875},{"type":"node","id":7529417230,"lat":51.1589326,"lon":3.2366138},{"type":"node","id":7529417232,"lat":51.159019,"lon":3.2366513},{"type":"node","id":170464840,"lat":51.1531619,"lon":3.2376814},{"type":"node","id":170464841,"lat":51.1532306,"lon":3.2376888},{"type":"node","id":1710245701,"lat":51.1528676,"lon":3.2390068},{"type":"node","id":1710245703,"lat":51.1527703,"lon":3.239403},{"type":"node","id":1710245705,"lat":51.1527888,"lon":3.2390966},{"type":"node","id":1710245707,"lat":51.1526357,"lon":3.2390543},{"type":"node","id":1710245709,"lat":51.1528763,"lon":3.2390382},{"type":"node","id":1710245711,"lat":51.1528928,"lon":3.2390631},{"type":"node","id":1710245713,"lat":51.1528729,"lon":3.2389738},{"type":"node","id":1710245715,"lat":51.1528645,"lon":3.2394083},{"type":"node","id":1710245718,"lat":51.1526407,"lon":3.2389524},{"type":"node","id":1710262736,"lat":51.1512857,"lon":3.2375783},{"type":"node","id":1710262737,"lat":51.151234,"lon":3.2375571},{"type":"node","id":1710262739,"lat":51.151183,"lon":3.2375939},{"type":"node","id":1710262741,"lat":51.1511924,"lon":3.2375358},{"type":"node","id":1710262744,"lat":51.1512252,"lon":3.2376112},{"type":"node","id":3346575950,"lat":51.1475926,"lon":3.2406028},{"type":"node","id":1728421374,"lat":51.1554436,"lon":3.2438233},{"type":"node","id":1728421375,"lat":51.15594,"lon":3.2438649},{"type":"node","id":1728421377,"lat":51.15559,"lon":3.2439695},{"type":"node","id":1728421379,"lat":51.1554335,"lon":3.243944},{"type":"node","id":1770289505,"lat":51.1565437,"lon":3.2437924},{"type":"node","id":4912197362,"lat":51.1565535,"lon":3.2438327},{"type":"node","id":4912197363,"lat":51.1562818,"lon":3.2438374},{"type":"node","id":4912197364,"lat":51.1565321,"lon":3.2435757},{"type":"node","id":4912197365,"lat":51.1565279,"lon":3.2433181},{"type":"node","id":4912197366,"lat":51.1562804,"lon":3.2435833},{"type":"node","id":4912197367,"lat":51.1562798,"lon":3.2431702},{"type":"node","id":4912197368,"lat":51.1562813,"lon":3.2437497},{"type":"node","id":4912197369,"lat":51.1562802,"lon":3.243488},{"type":"node","id":4912197370,"lat":51.1565257,"lon":3.2431702},{"type":"node","id":4912197371,"lat":51.1565542,"lon":3.2439044},{"type":"node","id":4912197372,"lat":51.1565308,"lon":3.2437482},{"type":"node","id":4912197373,"lat":51.1565294,"lon":3.2434893},{"type":"node","id":4912197374,"lat":51.1562835,"lon":3.2439005},{"type":"node","id":1710276232,"lat":51.1572435,"lon":3.2451269},{"type":"node","id":1710276240,"lat":51.156984,"lon":3.2453481},{"type":"node","id":1710276242,"lat":51.1567167,"lon":3.2452913},{"type":"node","id":1710276243,"lat":51.1570484,"lon":3.2451},{"type":"node","id":1710276251,"lat":51.1562241,"lon":3.2457572},{"type":"node","id":1710276253,"lat":51.156868,"lon":3.2451689},{"type":"node","id":1710276255,"lat":51.1563873,"lon":3.2456553},{"type":"node","id":1710276257,"lat":51.1572402,"lon":3.2450303},{"type":"node","id":1710276259,"lat":51.1561703,"lon":3.2454299},{"type":"node","id":1710276261,"lat":51.1564411,"lon":3.2457304},{"type":"node","id":1728421376,"lat":51.1555858,"lon":3.2441572},{"type":"node","id":1728421378,"lat":51.1559348,"lon":3.2441264},{"type":"node","id":1810330766,"lat":51.1562599,"lon":3.2457349},{"type":"node","id":1810345944,"lat":51.1572859,"lon":3.2458614},{"type":"node","id":1810345947,"lat":51.1568366,"lon":3.2461909},{"type":"node","id":1810345951,"lat":51.1572074,"lon":3.2455895},{"type":"node","id":1810345955,"lat":51.1567582,"lon":3.245919},{"type":"node","id":1810347217,"lat":51.1568783,"lon":3.2452387},{"type":"node","id":6255587424,"lat":51.1699788,"lon":3.1988617},{"type":"node","id":6255587425,"lat":51.1695322,"lon":3.1995447},{"type":"node","id":6255587426,"lat":51.1690026,"lon":3.1986489},{"type":"node","id":5173881316,"lat":51.1728811,"lon":3.210692},{"type":"node","id":5173881317,"lat":51.1728829,"lon":3.21077},{"type":"node","id":5173881318,"lat":51.1726197,"lon":3.2107914},{"type":"node","id":5173881320,"lat":51.1728794,"lon":3.2108575},{"type":"node","id":5173881621,"lat":51.1728791,"lon":3.2109364},{"type":"node","id":5173881622,"lat":51.1727133,"lon":3.2109488},{"type":"node","id":5173881623,"lat":51.1727117,"lon":3.2108703},{"type":"node","id":5173881624,"lat":51.1728613,"lon":3.211069},{"type":"node","id":5173881625,"lat":51.1728601,"lon":3.2111406},{"type":"node","id":5173881626,"lat":51.1727019,"lon":3.2111316},{"type":"node","id":5173881627,"lat":51.1727041,"lon":3.2110597},{"type":"node","id":6275462772,"lat":51.1733576,"lon":3.2110928},{"type":"node","id":6275462773,"lat":51.1733528,"lon":3.2112295},{"type":"node","id":6275462774,"lat":51.1735278,"lon":3.2112449},{"type":"node","id":6275462775,"lat":51.1735325,"lon":3.2111082},{"type":"node","id":6275462776,"lat":51.1736659,"lon":3.2112568},{"type":"node","id":6275462777,"lat":51.1736113,"lon":3.2112529},{"type":"node","id":6275462784,"lat":51.1735598,"lon":3.2109277},{"type":"node","id":6275462985,"lat":51.1734626,"lon":3.2109229},{"type":"node","id":6275462986,"lat":51.1734599,"lon":3.2110592},{"type":"node","id":6275462987,"lat":51.1735572,"lon":3.211064},{"type":"node","id":6275462988,"lat":51.1734613,"lon":3.2109904},{"type":"node","id":6275462989,"lat":51.173357,"lon":3.2111476},{"type":"node","id":7054196467,"lat":51.1726209,"lon":3.2107131},{"type":"node","id":8042845810,"lat":51.1737696,"lon":3.206708},{"type":"node","id":8042845811,"lat":51.1734466,"lon":3.2056148},{"type":"node","id":5952389321,"lat":51.1668901,"lon":3.2166736},{"type":"node","id":5952389322,"lat":51.1664592,"lon":3.2166337},{"type":"node","id":5952389323,"lat":51.1659941,"lon":3.2166018},{"type":"node","id":5172938444,"lat":51.1667283,"lon":3.2192609},{"type":"node","id":5536609426,"lat":51.1664884,"lon":3.2184803},{"type":"node","id":5536620510,"lat":51.1668363,"lon":3.2197448},{"type":"node","id":5536620511,"lat":51.1671911,"lon":3.2210959},{"type":"node","id":5952389320,"lat":51.1665059,"lon":3.2183884},{"type":"node","id":5536620506,"lat":51.1675299,"lon":3.2170283},{"type":"node","id":5536620507,"lat":51.1672585,"lon":3.2168071},{"type":"node","id":6275462778,"lat":51.1736042,"lon":3.2115044},{"type":"node","id":6275462779,"lat":51.1736588,"lon":3.2115083},{"type":"node","id":6275462780,"lat":51.1735687,"lon":3.2112964},{"type":"node","id":6275462781,"lat":51.1735211,"lon":3.2112937},{"type":"node","id":6275462782,"lat":51.1735156,"lon":3.2115423},{"type":"node","id":6275462783,"lat":51.1735632,"lon":3.211545},{"type":"node","id":5536620505,"lat":51.1683944,"lon":3.2180288},{"type":"node","id":5536620512,"lat":51.1673641,"lon":3.2217199},{"type":"node","id":5536620513,"lat":51.1675007,"lon":3.2221772},{"type":"node","id":5536620514,"lat":51.1679104,"lon":3.2236675},{"type":"node","id":5536620516,"lat":51.1679955,"lon":3.224005},{"type":"node","id":5536620824,"lat":51.1700823,"lon":3.2236258},{"type":"node","id":5536620826,"lat":51.171324,"lon":3.2230929},{"type":"node","id":5536620827,"lat":51.1717731,"lon":3.2213846},{"type":"node","id":5536620828,"lat":51.170726,"lon":3.2202369},{"type":"node","id":5536620829,"lat":51.1706206,"lon":3.2201178},{"type":"node","id":5536620830,"lat":51.170049,"lon":3.2215441},{"type":"node","id":5536620831,"lat":51.1699442,"lon":3.2215294},{"type":"node","id":5536620832,"lat":51.1683757,"lon":3.2194636},{"type":"node","id":6067483781,"lat":51.1675243,"lon":3.222207},{"type":"node","id":6067483782,"lat":51.1713888,"lon":3.2231705},{"type":"node","id":7794736251,"lat":51.1688401,"lon":3.2184325},{"type":"node","id":1069177852,"lat":51.1789546,"lon":3.2021791},{"type":"node","id":1069177853,"lat":51.1801636,"lon":3.2031369},{"type":"node","id":1069177873,"lat":51.1791663,"lon":3.2034541},{"type":"node","id":1069177915,"lat":51.1799187,"lon":3.2029579},{"type":"node","id":1069177919,"lat":51.1786053,"lon":3.2030903},{"type":"node","id":1069177920,"lat":51.1790417,"lon":3.2033998},{"type":"node","id":1069177925,"lat":51.1788415,"lon":3.2032442},{"type":"node","id":1069177933,"lat":51.1798479,"lon":3.2029364},{"type":"node","id":1069177967,"lat":51.178467,"lon":3.2025563},{"type":"node","id":1069177976,"lat":51.1791427,"lon":3.2026954},{"type":"node","id":1069177984,"lat":51.1783718,"lon":3.2028231},{"type":"node","id":1069178021,"lat":51.1793534,"lon":3.2033094},{"type":"node","id":1069178133,"lat":51.1784113,"lon":3.2028156},{"type":"node","id":6853179202,"lat":51.1792037,"lon":3.2026994},{"type":"node","id":6853179203,"lat":51.1790601,"lon":3.2026755},{"type":"node","id":6853179204,"lat":51.1791861,"lon":3.2027108},{"type":"node","id":6853179205,"lat":51.1791741,"lon":3.2027122},{"type":"node","id":6853179206,"lat":51.1791634,"lon":3.2027102},{"type":"node","id":6853179207,"lat":51.1791526,"lon":3.2027048},{"type":"node","id":6853179208,"lat":51.1790128,"lon":3.202488},{"type":"node","id":6853179209,"lat":51.1790434,"lon":3.2026225},{"type":"node","id":6853179210,"lat":51.1789811,"lon":3.2023837},{"type":"node","id":6853179211,"lat":51.1789744,"lon":3.2022415},{"type":"node","id":6853179212,"lat":51.1789438,"lon":3.2022643},{"type":"node","id":6853179213,"lat":51.1784216,"lon":3.2028567},{"type":"node","id":6853179214,"lat":51.1784157,"lon":3.2028375},{"type":"node","id":6853179215,"lat":51.1784506,"lon":3.2029294},{"type":"node","id":6853179216,"lat":51.1783884,"lon":3.2026704},{"type":"node","id":6853179217,"lat":51.178422,"lon":3.2026034},{"type":"node","id":6853179218,"lat":51.1784117,"lon":3.2026185},{"type":"node","id":6853179219,"lat":51.1784021,"lon":3.2026354},{"type":"node","id":6853179220,"lat":51.1783957,"lon":3.2026505},{"type":"node","id":6853179221,"lat":51.178443,"lon":3.2025785},{"type":"node","id":6853179222,"lat":51.1784546,"lon":3.202567},{"type":"node","id":6853179223,"lat":51.1784321,"lon":3.2025906},{"type":"node","id":6853179224,"lat":51.1783719,"lon":3.2027464},{"type":"node","id":6853179225,"lat":51.1783749,"lon":3.2027238},{"type":"node","id":6853179226,"lat":51.1783827,"lon":3.2026894},{"type":"node","id":6853179227,"lat":51.1783784,"lon":3.2027066},{"type":"node","id":6853179228,"lat":51.1783697,"lon":3.2027864},{"type":"node","id":6853179229,"lat":51.1783704,"lon":3.2027651},{"type":"node","id":6853179230,"lat":51.1783703,"lon":3.2028048},{"type":"node","id":6853179234,"lat":51.1798837,"lon":3.2029379},{"type":"node","id":6853179235,"lat":51.1798988,"lon":3.2029445},{"type":"node","id":6853179236,"lat":51.1798661,"lon":3.2029354},{"type":"node","id":6853179237,"lat":51.1798345,"lon":3.2029407},{"type":"node","id":6853179238,"lat":51.1798207,"lon":3.2029479},{"type":"node","id":6853179239,"lat":51.1792634,"lon":3.2033377},{"type":"node","id":6853179240,"lat":51.1793019,"lon":3.2033359},{"type":"node","id":6853179241,"lat":51.1792828,"lon":3.20334},{"type":"node","id":6853179242,"lat":51.1792732,"lon":3.2033393},{"type":"node","id":6853179243,"lat":51.1792921,"lon":3.2033388},{"type":"node","id":6853179244,"lat":51.1793279,"lon":3.2033257},{"type":"node","id":6853179245,"lat":51.1793153,"lon":3.2033313},{"type":"node","id":6853179246,"lat":51.1793413,"lon":3.2033182},{"type":"node","id":6853179247,"lat":51.1792384,"lon":3.2033981},{"type":"node","id":6853179248,"lat":51.1792572,"lon":3.2033605},{"type":"node","id":6853179249,"lat":51.1792512,"lon":3.2033774},{"type":"node","id":6853179250,"lat":51.1792456,"lon":3.2033888},{"type":"node","id":6853179256,"lat":51.1790996,"lon":3.2034514},{"type":"node","id":6853179257,"lat":51.1790731,"lon":3.2034317},{"type":"node","id":6853179258,"lat":51.1790581,"lon":3.2034168},{"type":"node","id":6853179259,"lat":51.1790862,"lon":3.2034422},{"type":"node","id":6853179260,"lat":51.179133,"lon":3.2034648},{"type":"node","id":6853179261,"lat":51.1791191,"lon":3.203461},{"type":"node","id":6853179262,"lat":51.1791546,"lon":3.2034608},{"type":"node","id":6853179263,"lat":51.1791443,"lon":3.2034639},{"type":"node","id":6853179264,"lat":51.1789437,"lon":3.2033089},{"type":"node","id":6853179267,"lat":51.1785146,"lon":3.2030128},{"type":"node","id":6853179268,"lat":51.1785517,"lon":3.2030489},{"type":"node","id":6853179269,"lat":51.1785863,"lon":3.2030773},{"type":"node","id":6853179327,"lat":51.1789936,"lon":3.2024248},{"type":"node","id":7252820961,"lat":51.175521,"lon":3.2045972},{"type":"node","id":7252863798,"lat":51.1754304,"lon":3.2044959},{"type":"node","id":8042845806,"lat":51.1753353,"lon":3.2041851},{"type":"node","id":8042845807,"lat":51.175363,"lon":3.2043314},{"type":"node","id":8042845812,"lat":51.1752711,"lon":3.2040127},{"type":"node","id":4036885076,"lat":51.1740632,"lon":3.2050437},{"type":"node","id":4036899624,"lat":51.1767493,"lon":3.2082945},{"type":"node","id":5607796819,"lat":51.1782483,"lon":3.2091883},{"type":"node","id":5607796820,"lat":51.1785128,"lon":3.2086016},{"type":"node","id":5607798721,"lat":51.1786474,"lon":3.2090453},{"type":"node","id":5607798722,"lat":51.1782874,"lon":3.2093115},{"type":"node","id":5607798723,"lat":51.178141,"lon":3.2088491},{"type":"node","id":5607798725,"lat":51.1785713,"lon":3.2087945},{"type":"node","id":5728443539,"lat":51.1753294,"lon":3.2097039},{"type":"node","id":5728443540,"lat":51.1752216,"lon":3.2089278},{"type":"node","id":6275462768,"lat":51.174424,"lon":3.2105467},{"type":"node","id":6275462769,"lat":51.1743524,"lon":3.2105548},{"type":"node","id":6275462770,"lat":51.1743644,"lon":3.2108257},{"type":"node","id":6275462771,"lat":51.1744361,"lon":3.2108176},{"type":"node","id":7252820962,"lat":51.1756015,"lon":3.204854},{"type":"node","id":7252820963,"lat":51.1755802,"lon":3.204928},{"type":"node","id":7252820964,"lat":51.1755132,"lon":3.2049422},{"type":"node","id":7252820965,"lat":51.1754719,"lon":3.2050156},{"type":"node","id":7252820966,"lat":51.1754575,"lon":3.2051212},{"type":"node","id":7252820967,"lat":51.1755143,"lon":3.2052892},{"type":"node","id":7252820968,"lat":51.1755533,"lon":3.2055086},{"type":"node","id":7252820969,"lat":51.1755563,"lon":3.2060065},{"type":"node","id":7252820970,"lat":51.175491,"lon":3.2064409},{"type":"node","id":7252820971,"lat":51.1753674,"lon":3.2068348},{"type":"node","id":7252820972,"lat":51.1751944,"lon":3.2070531},{"type":"node","id":7252820973,"lat":51.1751195,"lon":3.2071478},{"type":"node","id":7252820974,"lat":51.1750834,"lon":3.2072467},{"type":"node","id":7252820975,"lat":51.1750963,"lon":3.2073579},{"type":"node","id":7252820976,"lat":51.1751376,"lon":3.2074032},{"type":"node","id":7252820977,"lat":51.175215,"lon":3.2073826},{"type":"node","id":7252820978,"lat":51.1752848,"lon":3.2073785},{"type":"node","id":7252820979,"lat":51.1754252,"lon":3.2073858},{"type":"node","id":7252820980,"lat":51.1754615,"lon":3.2074926},{"type":"node","id":7252820981,"lat":51.1754259,"lon":3.20756},{"type":"node","id":7252820982,"lat":51.17537,"lon":3.2076668},{"type":"node","id":7252820983,"lat":51.1753304,"lon":3.2078901},{"type":"node","id":7252820984,"lat":51.1753152,"lon":3.2079319},{"type":"node","id":7252874885,"lat":51.1754423,"lon":3.2080951},{"type":"node","id":7252874886,"lat":51.1754991,"lon":3.2083134},{"type":"node","id":7252874887,"lat":51.1755307,"lon":3.2084864},{"type":"node","id":7252874888,"lat":51.1755729,"lon":3.2087064},{"type":"node","id":7252874889,"lat":51.1753248,"lon":3.2088635},{"type":"node","id":7252874890,"lat":51.1752645,"lon":3.2092365},{"type":"node","id":7252874891,"lat":51.1747746,"lon":3.2093558},{"type":"node","id":8042845789,"lat":51.1748587,"lon":3.209526},{"type":"node","id":8042845790,"lat":51.1749489,"lon":3.2096774},{"type":"node","id":8042845791,"lat":51.1750595,"lon":3.2097458},{"type":"node","id":8042845792,"lat":51.1753557,"lon":3.2077924},{"type":"node","id":8042845793,"lat":51.1754621,"lon":3.2074425},{"type":"node","id":8042845794,"lat":51.1754531,"lon":3.2074092},{"type":"node","id":8042845795,"lat":51.1754729,"lon":3.2051839},{"type":"node","id":8042845796,"lat":51.1754907,"lon":3.2052089},{"type":"node","id":8042845797,"lat":51.1755084,"lon":3.2052355},{"type":"node","id":8042845798,"lat":51.1755235,"lon":3.2053482},{"type":"node","id":8042845799,"lat":51.1755387,"lon":3.2053805},{"type":"node","id":8042845800,"lat":51.1755584,"lon":3.2057251},{"type":"node","id":8042845801,"lat":51.1755536,"lon":3.205762},{"type":"node","id":8042845802,"lat":51.1755492,"lon":3.2061312},{"type":"node","id":8042845803,"lat":51.1755305,"lon":3.2062755},{"type":"node","id":8042845804,"lat":51.1754335,"lon":3.2066603},{"type":"node","id":8042845805,"lat":51.1755929,"lon":3.2047843},{"type":"node","id":8042845808,"lat":51.1746278,"lon":3.2090183},{"type":"node","id":8042845809,"lat":51.1740796,"lon":3.2076268},{"type":"node","id":8042845844,"lat":51.1768218,"lon":3.20861},{"type":"node","id":8042845845,"lat":51.1767935,"lon":3.2085031},{"type":"node","id":8042845846,"lat":51.1769413,"lon":3.2089936},{"type":"node","id":8042845847,"lat":51.1757541,"lon":3.2096988},{"type":"node","id":8042845848,"lat":51.1757421,"lon":3.2096812},{"type":"node","id":8042845849,"lat":51.1757312,"lon":3.2096924},{"type":"node","id":8042845850,"lat":51.1757202,"lon":3.2096478},{"type":"node","id":8042845851,"lat":51.1756902,"lon":3.2096207},{"type":"node","id":8042845852,"lat":51.1756712,"lon":3.2096143},{"type":"node","id":8042845853,"lat":51.1756602,"lon":3.2095745},{"type":"node","id":8042845854,"lat":51.1756552,"lon":3.2095537},{"type":"node","id":8042845855,"lat":51.1756657,"lon":3.2095174},{"type":"node","id":8042845856,"lat":51.175658,"lon":3.20908},{"type":"node","id":8042845857,"lat":51.1756525,"lon":3.2093366},{"type":"node","id":8042845858,"lat":51.1756466,"lon":3.2088282},{"type":"node","id":8042845859,"lat":51.1756582,"lon":3.2089151},{"type":"node","id":8042845860,"lat":51.1765521,"lon":3.20839},{"type":"node","id":1069177845,"lat":51.1809357,"lon":3.2035366},{"type":"node","id":1069177849,"lat":51.1803975,"lon":3.2017749},{"type":"node","id":1069178166,"lat":51.1804195,"lon":3.2033098},{"type":"node","id":1519342742,"lat":51.1805239,"lon":3.2032684},{"type":"node","id":1519342743,"lat":51.18064,"lon":3.2036951},{"type":"node","id":1759437085,"lat":51.1806986,"lon":3.2036647},{"type":"node","id":6852012577,"lat":51.1804541,"lon":3.2017867},{"type":"node","id":6852012578,"lat":51.1804124,"lon":3.2018177},{"type":"node","id":6852012579,"lat":51.1804106,"lon":3.2018165},{"type":"node","id":6852012580,"lat":51.1804143,"lon":3.2018177},{"type":"node","id":6852012581,"lat":51.1808363,"lon":3.2030295},{"type":"node","id":6852012582,"lat":51.1807955,"lon":3.2030595},{"type":"node","id":6852012583,"lat":51.180798,"lon":3.2030712},{"type":"node","id":1519476620,"lat":51.1786696,"lon":3.2199463},{"type":"node","id":1519476635,"lat":51.179306,"lon":3.2193119},{"type":"node","id":1519476698,"lat":51.1795485,"lon":3.2192221},{"type":"node","id":1519476744,"lat":51.1791125,"lon":3.2194529},{"type":"node","id":1519476746,"lat":51.178483,"lon":3.2203218},{"type":"node","id":1519476797,"lat":51.1788731,"lon":3.2196593},{"type":"node","id":3780611492,"lat":51.1761568,"lon":3.2238485},{"type":"node","id":3780611493,"lat":51.1762213,"lon":3.223901},{"type":"node","id":3780611494,"lat":51.1762626,"lon":3.2237172},{"type":"node","id":3780611495,"lat":51.1763208,"lon":3.2237628},{"type":"node","id":3780611496,"lat":51.1763248,"lon":3.2236414},{"type":"node","id":3780611497,"lat":51.1763881,"lon":3.2236926},{"type":"node","id":3780611498,"lat":51.1764876,"lon":3.2235544},{"type":"node","id":3780611499,"lat":51.1766551,"lon":3.2232337},{"type":"node","id":3780611500,"lat":51.176687,"lon":3.2231945},{"type":"node","id":3780611501,"lat":51.1767105,"lon":3.2232776},{"type":"node","id":3780611502,"lat":51.176751,"lon":3.2232465},{"type":"node","id":3780611503,"lat":51.1767812,"lon":3.2230729},{"type":"node","id":3780611504,"lat":51.1768505,"lon":3.2231083},{"type":"node","id":6533893620,"lat":51.178521,"lon":3.2203687},{"type":"node","id":6533893621,"lat":51.1786845,"lon":3.220025},{"type":"node","id":6533893622,"lat":51.1789011,"lon":3.2197183},{"type":"node","id":6533893624,"lat":51.1791343,"lon":3.2195235},{"type":"node","id":6533893625,"lat":51.1793269,"lon":3.2193854},{"type":"node","id":6533893626,"lat":51.1795596,"lon":3.219299},{"type":"node","id":5536620518,"lat":51.1683264,"lon":3.224863},{"type":"node","id":5536620519,"lat":51.1684352,"lon":3.2251117},{"type":"node","id":5536620520,"lat":51.1685675,"lon":3.2254022},{"type":"node","id":5536620821,"lat":51.1687379,"lon":3.2258223},{"type":"node","id":5536620822,"lat":51.1693682,"lon":3.2250177},{"type":"node","id":5536620823,"lat":51.1693734,"lon":3.225049},{"type":"node","id":5536620825,"lat":51.1707605,"lon":3.2244639},{"type":"node","id":5536620837,"lat":51.1697793,"lon":3.2260181},{"type":"node","id":5536620838,"lat":51.1699712,"lon":3.2262338},{"type":"node","id":5536620839,"lat":51.1701247,"lon":3.2263242},{"type":"node","id":5536620840,"lat":51.1704719,"lon":3.2266478},{"type":"node","id":5536620841,"lat":51.1701028,"lon":3.2281081},{"type":"node","id":5536620842,"lat":51.1698158,"lon":3.2276446},{"type":"node","id":5536620843,"lat":51.1696441,"lon":3.2273837},{"type":"node","id":5536620844,"lat":51.1695154,"lon":3.2272009},{"type":"node","id":5536620845,"lat":51.169536,"lon":3.2271664},{"type":"node","id":5536620846,"lat":51.1694515,"lon":3.2270181},{"type":"node","id":5635001306,"lat":51.1737078,"lon":3.2354437},{"type":"node","id":5635001371,"lat":51.1722128,"lon":3.2340273},{"type":"node","id":5635001372,"lat":51.1723921,"lon":3.2343394},{"type":"node","id":5635001373,"lat":51.1724213,"lon":3.2342967},{"type":"node","id":5635001374,"lat":51.1722421,"lon":3.2339846},{"type":"node","id":5635001375,"lat":51.1728995,"lon":3.2339319},{"type":"node","id":5635001376,"lat":51.1729253,"lon":3.2339922},{"type":"node","id":5635001377,"lat":51.1723583,"lon":3.2340816},{"type":"node","id":5635001378,"lat":51.1723268,"lon":3.2340173},{"type":"node","id":5635001379,"lat":51.172885,"lon":3.2337993},{"type":"node","id":5635001380,"lat":51.1728611,"lon":3.2338706},{"type":"node","id":5635001381,"lat":51.1723325,"lon":3.2339419},{"type":"node","id":5635001382,"lat":51.1723464,"lon":3.2338696},{"type":"node","id":5882873334,"lat":51.1736186,"lon":3.2330966},{"type":"node","id":5882873335,"lat":51.1735451,"lon":3.2327633},{"type":"node","id":5882873336,"lat":51.1737001,"lon":3.2327438},{"type":"node","id":5882873337,"lat":51.1736796,"lon":3.2318764},{"type":"node","id":5882873338,"lat":51.1735265,"lon":3.2318782},{"type":"node","id":6593340582,"lat":51.1727872,"lon":3.2328745},{"type":"node","id":6593340583,"lat":51.1728013,"lon":3.2332051},{"type":"node","id":6593340584,"lat":51.1736743,"lon":3.2331435},{"type":"node","id":7767137235,"lat":51.1735198,"lon":3.2355568},{"type":"node","id":7767137236,"lat":51.1735366,"lon":3.2355246},{"type":"node","id":7767137237,"lat":51.1735198,"lon":3.2356399},{"type":"node","id":5635001274,"lat":51.1751425,"lon":3.2346144},{"type":"node","id":5635001275,"lat":51.1751696,"lon":3.2347601},{"type":"node","id":5635001276,"lat":51.1750553,"lon":3.2348141},{"type":"node","id":5635001277,"lat":51.1750282,"lon":3.2346684},{"type":"node","id":5635001312,"lat":51.174002,"lon":3.2349367},{"type":"node","id":5635001383,"lat":51.1740709,"lon":3.233056},{"type":"node","id":5635001384,"lat":51.1740249,"lon":3.2330598},{"type":"node","id":5635001385,"lat":51.1740265,"lon":3.2331313},{"type":"node","id":5635001386,"lat":51.1740597,"lon":3.2327202},{"type":"node","id":5635001414,"lat":51.174281,"lon":3.2336147},{"type":"node","id":5635001415,"lat":51.174081,"lon":3.2338914},{"type":"node","id":5635001416,"lat":51.1740489,"lon":3.2338323},{"type":"node","id":5635001417,"lat":51.1742489,"lon":3.2335556},{"type":"node","id":5761770202,"lat":51.1783111,"lon":3.2342484},{"type":"node","id":5761770204,"lat":51.1782819,"lon":3.2339616},{"type":"node","id":7767137234,"lat":51.1739713,"lon":3.2348766},{"type":"node","id":9052878228,"lat":51.1781206,"lon":3.234323},{"type":"node","id":9052878229,"lat":51.1781054,"lon":3.2339448},{"type":"way","id":810604915,"nodes":[1168727824,9167054153,9274761589,9274761596,7577430793,1038638712,1038638723,1038638661,9199177059,1038638721,7554434436,7578975035,7554434438,7578865273,7578975032,7578975030,7578975029,1038638696,7578975009,7578975008,7578975007,1038638743,7578975002,7578974988,7578974989,7578974990,7578974991,7578974992,7578865275,7578865274,1038638753,7578974995,7578974996,7578974997,7578904489,7578974999,7578975000,7578975001,7578974998,3921878998,1038638592,929120698,1675648152,7578865281,7578865283,7578975012,7578975015,7578975016,3922380061,2732486274,3922380083,7578975019,7578975018,7578975021,7578960079,3922375256,7578975024,3922380071]},{"type":"way","id":989393316,"nodes":[3922380071,3922380081,3922380086,3922380092,3922380095,9167054157,7578975026,9274761593,9274761592,9274761591,7578975027,9167054156,9167054154,7578975049,7578975028,1168727824]},{"type":"way","id":389026405,"nodes":[3921879019,7578975044,3921879018,7578975046,7578975045,7578975040,3921879004,3921879011,3921879019]},{"type":"way","id":810607458,"nodes":[7578987409,7578987410,7578987411,5745833241,5745833240,5745833239,7578987412,7578987415,7578987413,7578987414,7578987417,7578987416,7578987418,7578987419,7578987409]},{"type":"way","id":777280458,"nodes":[8042845812,8042845806,8042845807,7252863798,7252820961,8042845805,7252820962,7252820963,7252820964,7252820965,7252820966,8042845795,8042845796,8042845797,7252820967,8042845798,8042845799,7252820968,8042845800,8042845801,7252820969,8042845802,8042845803,7252820970,8042845804,7252820971,7252820972,7252820973,7252820974,7252820975,7252820976,7252820977,7252820978,7252820979,8042845794,8042845793,7252820980,7252820981,7252820982,8042845792,7252820983,7252820984,7252874885,7252874886,7252874887,7252874888,7252874889,5728443540,7252874890,5728443539,8042845791,8042845790,8042845789,7252874891,8042845808,8042845809,8042845810,8042845811,4036885076,8042845812]},{"type":"way","id":577572397,"nodes":[5536620518,5536620519,5536620520,5536620821,5536620822,5536620823,5536620824,5536620825,5536620826,6067483782,5536620827,5536620828,5536620829,5536620830,5536620831,5536620832,7794736251,5536620505,5536620506,5536620507,5952389321,5952389322,5952389323,5536609426,5952389320,5172938444,5536620510,5536620511,5536620512,5536620513,6067483781,5536620514,5536620516,5536620518]},{"type":"way","id":863373849,"nodes":[4036899624,8042845845,8042845844,8042845846,8042845847,8042845848,8042845849,8042845850,8042845851,8042845852,8042845853,8042845854,8042845855,8042845857,8042845856,8042845859,8042845858,8042845860,4036899624]},{"type":"way","id":577572399,"nodes":[5536620837,5536620838,5536620839,5536620840,5536620841,5536620842,5536620843,5536620844,5536620845,5536620846,5536620837]}]} - ) - - Utils.injectJsonDownloadForTests( - "https://overpass-api.de/api/interpreter?data=%5Bout%3Ajson%5D%5Btimeout%3A60%5D%5Bbbox%3A51.124212757826875%2C3.251953125%2C51.17934297928927%2C3.33984375%5D%3B"+query , - {"version":0.6,"generator":"Overpass API 0.7.57 93a4d346","osm3s":{"timestamp_osm_base":"2022-02-14T00:02:14Z","copyright":"The data included in this document is from www.openstreetmap.org. The data is made available under ODbL."},"elements":[{"type":"node","id":668981602,"lat":51.1588243,"lon":3.2558654,"tags":{"amenity":"bench"}},{"type":"node","id":668981622,"lat":51.1565636,"lon":3.2549888,"tags":{"leisure":"bird_hide","operator":"Natuurpunt Vallei van de Zuidleie","shelter":"no"}},{"type":"node","id":1580339675,"lat":51.1395949,"lon":3.3332507,"tags":{"amenity":"parking"}},{"type":"node","id":1764571836,"lat":51.1701118,"lon":3.3363371,"tags":{"amenity":"parking"}},{"type":"node","id":2121652779,"lat":51.1268536,"lon":3.3239607,"tags":{"amenity":"parking"}},{"type":"node","id":2386053906,"lat":51.162161,"lon":3.263065,"tags":{"amenity":"toilets"}},{"type":"node","id":2978180520,"lat":51.1329149,"lon":3.3362322,"tags":{"amenity":"bench"}},{"type":"node","id":2978183271,"lat":51.1324243,"lon":3.3373735,"tags":{"amenity":"bench"}},{"type":"node","id":2978184471,"lat":51.1436385,"lon":3.2916539,"tags":{"amenity":"bench","backrest":"yes","check_date":"2021-02-26"}},{"type":"node","id":3925976407,"lat":51.1787486,"lon":3.2831866,"tags":{"leisure":"picnic_table"}},{"type":"node","id":5158056232,"lat":51.1592067,"lon":3.2567111,"tags":{"leisure":"bird_hide","operator":"Natuurpunt Vallei van de Zuidleie","shelter":"no"}},{"type":"node","id":5718776382,"lat":51.1609023,"lon":3.2582509,"tags":{"check_date":"2021-02-26","covered":"no","leisure":"picnic_table"}},{"type":"node","id":5718776383,"lat":51.1609488,"lon":3.2581877,"tags":{"check_date":"2021-02-26","covered":"no","leisure":"picnic_table"}},{"type":"node","id":5745727100,"lat":51.1594639,"lon":3.2604304,"tags":{"amenity":"bench"}},{"type":"node","id":5745739587,"lat":51.1580397,"lon":3.263101,"tags":{"check_date":"2021-02-26","leisure":"picnic_table"}},{"type":"node","id":5745739588,"lat":51.1580631,"lon":3.2630345,"tags":{"check_date":"2021-02-26","leisure":"picnic_table"}},{"type":"node","id":5961596093,"lat":51.1588103,"lon":3.2633933,"tags":{"leisure":"picnic_table"}},{"type":"node","id":5964032193,"lat":51.1514821,"lon":3.2723766,"tags":{"leisure":"picnic_table"}},{"type":"node","id":6034563379,"lat":51.1421689,"lon":3.3022271,"tags":{"leisure":"picnic_table"}},{"type":"node","id":6034564191,"lat":51.1722186,"lon":3.2823584,"tags":{"leisure":"picnic_table"}},{"type":"node","id":6034565298,"lat":51.1722796,"lon":3.282329,"tags":{"leisure":"picnic_table"}},{"type":"node","id":6145151111,"lat":51.1690435,"lon":3.3388676,"tags":{"amenity":"bench"}},{"type":"node","id":6145151112,"lat":51.1690023,"lon":3.3388636,"tags":{"amenity":"bench"}},{"type":"node","id":6216549651,"lat":51.1292813,"lon":3.332369,"tags":{"amenity":"bench"}},{"type":"node","id":6216549652,"lat":51.1292768,"lon":3.3324259,"tags":{"amenity":"bench"}},{"type":"node","id":7204447030,"lat":51.1791769,"lon":3.283116,"tags":{"board_type":"nature","information":"board","mapillary":"0BHVgU1XCyTMM9cjvidUqk","name":"De Assebroekse Meersen","tourism":"information"}},{"type":"node","id":7468175778,"lat":51.1344104,"lon":3.3348246,"tags":{"leisure":"picnic_table"}},{"type":"node","id":7602473480,"lat":51.1503874,"lon":3.2836867,"tags":{"leisure":"picnic_table"}},{"type":"node","id":7602473482,"lat":51.150244,"lon":3.2842925,"tags":{"board_type":"wildlife","information":"board","name":"Waterbeestjes","operator":"Natuurpunt Vallei van de Zuidleie","tourism":"information"}},{"type":"node","id":7602699080,"lat":51.1367031,"lon":3.3320712,"tags":{"amenity":"bench","backrest":"yes","material":"metal"}},{"type":"node","id":7680940369,"lat":51.1380074,"lon":3.3369928,"tags":{"amenity":"bench"}},{"type":"node","id":7726850522,"lat":51.1418585,"lon":3.3064234,"tags":{"image:0":"https://i.imgur.com/Bh6UjYy.jpg","information":"board","tourism":"information"}},{"type":"node","id":7727071212,"lat":51.1501173,"lon":3.2845352,"tags":{"board_type":"wildlife","image:0":"https://i.imgur.com/mFEQJWd.jpg","information":"board","name":"Vleermuizen","operator":"Natuurpunt Vallei van de Zuidleie","tourism":"information"}},{"type":"node","id":9122376662,"lat":51.1720505,"lon":3.3308524,"tags":{"amenity":"bench"}},{"type":"node","id":9425818876,"lat":51.1325315,"lon":3.3371616,"tags":{"leisure":"picnic_table","mapillary":"101961548889238"}},{"type":"way","id":149408639,"nodes":[1623924235,1623924236,1623924238,1864750831,1623924241,1623924235],"tags":{"amenity":"parking"}},{"type":"way","id":149553206,"nodes":[1625199938,1625199951,8377691836,8378081366,8378081429,8378081386,1625199950,6414383775,1625199827,1625199938],"tags":{"amenity":"parking"}},{"type":"way","id":184402308,"nodes":[1948836195,1948836194,1948836193,1948836189,1948836192,1948836195],"tags":{"building":"yes","leisure":"bird_hide","operator":"Natuurpunt Vallei van de Zuidleie","shelter":"yes","wheelchair":"yes"}},{"type":"way","id":184402309,"nodes":[1948836029,1948836038,1948836032,1948836025,1948836023,1948836029],"tags":{"building":"yes","leisure":"bird_hide","operator":"Natuurpunt Vallei van de Zuidleie","shelter":"yes","source:geometry:date":"2011-11-07","source:geometry:ref":"Gbg/3489204"}},{"type":"way","id":184402331,"nodes":[1948836104,1948836072,1948836068,1948836093,1948836104],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":236979353,"nodes":[2449323191,7962681624,7962681623,7962681621,7962681622,2449323193,7962681620,7962681619,8360787098,4350143592,6794421028,6794421027,6794421041,7962681614,2123461969,2449323198,7962681615,7962681616,6794421042,2449323191],"tags":{"amenity":"parking"}},{"type":"way","id":251590503,"nodes":[2577910543,2577910530,2577910542,2577910520,6418533335,2577910526,2577910545,2577910543],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":313090489,"nodes":[3190107423,3190107435,3190107442,3190107439,3190107432,3190107428,3190107424,3190107400,3190107393,3190107377,3190107371,3190107374,3190107408,3190107407,3190107415,3190107416,3190107420,3190107423],"tags":{"amenity":"parking"}},{"type":"way","id":314531418,"nodes":[7468171455,7468171451,7727393212,7727393211,7727393210,7727393208,7727393209,8781449489,7727393207,7727393206,7727393205,7727393204,7727393203,7727393202,7727393201,7727393200,7390697550,7390697534,7727393199,7727393198,7727393197,7390697549,7727393196,7727393195,7727393194,7727393193,7727393192,7727393191,7727393190,7727393189,7727393188,7727393187,7727393186,7727393185,7727339384,7727339383,7727339382,1553169911,1553169836,1493821433,1493821422,3185248088,7727339364,7727339365,7727339366,7727339367,7727339368,7727339369,7727339370,7727339371,7727339372,7727339373,7727339374,7727339375,7727339376,7727339377,3185248049,3185248048,3185248042,3185248040,7727339378,7727339379,7727339380,7727339381,7468171438,7468171442,7468171430,7468171432,7468171446,7468171404,7468171405,7468171422,7468171426,7468171433,7468171423,7468171428,7468171431,7468171429,7468171406,7468171407,7468171444,7468171408,7468171409,7468171410,7468171411,7468171412,7468171413,7190927792,7190927791,7190927793,7190927787,7190927788,7190927789,7190927790,7190927786,7602692242,7190927785,7190873584,7468171450,7190873582,7190873576,7190873578,7190873577,7468171455],"tags":{"access":"yes","dog":"leashed","dogs":"leashed","image":"https://i.imgur.com/cOfwWTj.jpg","image:0":"https://i.imgur.com/RliQdyi.jpg","image:1":"https://i.imgur.com/IeKHahz.jpg","image:2":"https://i.imgur.com/1K0IORH.jpg","image:3":"https://i.imgur.com/jojP09s.jpg","image:4":"https://i.imgur.com/DK6kT51.jpg","image:5":"https://i.imgur.com/RizbGM1.jpg","image:6":"https://i.imgur.com/hyoY6Cl.jpg","image:7":"https://i.imgur.com/xDd7Wrq.jpg","leisure":"nature_reserve","name":"Miseriebocht","operator":"Natuurpunt Beernem","website":"https://www.natuurpunt.be/natuurgebied/miseriebocht","wikidata":"Q97060915"}},{"type":"way","id":366318480,"nodes":[3702926557,3702926558,3702926559,3702926560,3702926557],"tags":{"amenity":"parking"}},{"type":"way","id":366318481,"nodes":[3702878648,3702926561,3702926562,3702926563,3702926564,3702926565,3702926566,3702926567,3702878648],"tags":{"amenity":"parking"}},{"type":"way","id":366318482,"nodes":[3702926568,8292789053,8292789054,3702878654,3702926568],"tags":{"amenity":"parking"}},{"type":"way","id":366320440,"nodes":[3702956173,3702956174,3702956175,3702956176,3702956173],"tags":{"amenity":"parking","name":"Kleine Beer"}},{"type":"way","id":366321706,"nodes":[3702969714,3702969715,3702969716,3702969717,3702969714],"tags":{"amenity":"parking"}},{"type":"way","id":480267681,"nodes":[4732689641,4732689640,4732689639,4732689638,4732689637,4732689636,4732689635,4732689634,4732689633,4732689632,4732689631,4732689630,4732689629,4732689628,4732689627,4732689626,8294875888,4732689641],"tags":{"amenity":"parking"}},{"type":"way","id":554341620,"nodes":[5349884603,5349884602,5349884601,5349884600,5349884603],"tags":{"amenity":"parking"}},{"type":"way","id":554341621,"nodes":[5349884607,5349884606,5349884605,5349884604,5349884607],"tags":{"amenity":"parking"}},{"type":"way","id":561902092,"nodes":[5417516023,5417515520,5417516021,5417516022,5417516023],"tags":{"building":"yes","image":"https://i.imgur.com/WmViSbL.jpg","leisure":"bird_hide","operator":"Natuurpunt Vallei van de Zuidleie","shelter":"yes","wheelchair":"no"}},{"type":"way","id":605915064,"nodes":[5745739924,5745739925,5745739926,5745739927,5745739924],"tags":{"amenity":"parking","surface":"fine2"}},{"type":"way","id":650285088,"nodes":[3645188881,6100803131,6100803130,6100803129,6100803124,6100803125,6100803128,6100803127,6100803126,3645188881],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":655944574,"nodes":[6145151107,6145151108,6145151109,6145151115,6145151114,6145151110,6145151107],"tags":{"amenity":"parking"}},{"type":"way","id":664171069,"nodes":[6216549610,6216549611,6216549612,6216549613,1413470849,1413470848,6216549605,6216549604,6216549610],"tags":{"amenity":"parking"}},{"type":"way","id":664171076,"nodes":[6216549656,6216549655,8307316294,6216549661,6216549657,6216549658,6216549659,6216549660,6216549656],"tags":{"amenity":"parking","capacity":"50"}},{"type":"way","id":665330334,"nodes":[6227395993,6227395991,6227395992,6227395997,6227395993],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface","surface":"asphalt"}},{"type":"way","id":684598363,"nodes":[3227068565,6416001161,6414352054,6414352055,7274233390,7274233391,7274233397,7274233395,7274233396,6414352053,3227068568,3227068565],"tags":{"amenity":"parking","fee":"no"}},{"type":"way","id":684599810,"nodes":[1317838331,8279842668,1384096112,1317838328,6414374315,3227068446,6414374316,6414374317,6414374318,3227068456,6414374319,6414374320,6414374321,1317838317,1317838331],"tags":{"access":"no","amenity":"parking","operator":"Politie"}},{"type":"way","id":761474468,"nodes":[7114502201,7114502203,7114502200,7114502202,3170562439,3170562437,3170562431,7114502240,7114502211,7114502212,7114502214,7114502215,7114502228,7114502234,7114502235,7114502236,7114502237,7114502238,7114502239,7114502233,7114502232,7114502231,7114502229,7114502230,7114502227,7114502226,7114502225,7114502216,7114502217,7114502224,3170562392,7114502218,3170562394,7114502219,7114502220,7114502221,7114502222,7114502223,3170562395,3170562396,3170562397,3170562402,3170562410,7114502209,7114502208,7114502207,7114502205,7114502206,3170562436,1475188519,1475188516,6627605025,8294886142,7114502201],"tags":{"image":"http://valleivandezuidleie.be/wp-content/uploads/2011/12/2011-03-24_G12_088_1_1.JPG","leisure":"nature_reserve","name":"Merlebeek-Meerberg","natural":"wetland","operator":"Natuurpunt Vallei van de Zuidleie","start_date":"2011","website":"http://valleivandezuidleie.be/info-over-de-vallei-van-de-zuidleie/merlebeek/","wetland":"wet_meadow"}},{"type":"way","id":813859435,"nodes":[7602479690,7459257985,7602479691,7459154784,7459154782,7602479692,5482441357,7602479693,7602479694,7602479695,7602479696,7602479690],"tags":{"access":"yes","image:0":"https://i.imgur.com/nb9nawa.jpg","landuse":"grass","leisure":"nature_reserve","name:signed":"no","natural":"grass","operator":"Natuurpunt Vallei van de Zuidleie"}},{"type":"way","id":826103452,"nodes":[7713176912,7713176911,7713176910,7713176909,7713176912],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":893176022,"nodes":[1927235214,8301349336,8301349335,8301349337,1927235214],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":895943476,"nodes":[8328251887,8328251886,8328251885,8328251884,8328251887],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":895943477,"nodes":[8328251891,8328251890,8328251889,8328251888,8328251891],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":895943478,"nodes":[8328251895,8328251894,8328251893,8328251892,8328251895],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":895943479,"nodes":[8328251897,8328251896,8328251901,8328251900,8328251897],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":895943480,"nodes":[8328251898,8328251899,8328251903,8328251902,8328251898],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":895943481,"nodes":[8328251907,8328251906,8328251905,8328251904,8328251907],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":895943482,"nodes":[8328251911,8328251910,8328251909,8328251908,8328251911],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":901952767,"nodes":[8378097127,8378097126,8378097125,8378097124,8378097127],"tags":{"amenity":"parking","parking":"street_side"}},{"type":"way","id":901952768,"nodes":[8378097134,8378097133,8378097132,8378097131,8378097130,8378097129,8378097128,8378097134],"tags":{"amenity":"parking","parking":"street_side"}},{"type":"way","id":947325182,"nodes":[8497007549,8768981525,8768981522,8768981524,8768981521,8768981523,8768981520,8768981519,6206789709,8768981533,8497007549],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":966827815,"nodes":[8945026757,8945026756,8945026755,8945026754,8945026757],"tags":{"access":"customers","amenity":"parking","parking":"surface"}},{"type":"relation","id":2589413,"members":[{"type":"way","ref":663050030,"role":"outer"},{"type":"way","ref":184402334,"role":"outer"},{"type":"way","ref":184402332,"role":"outer"},{"type":"way","ref":184402325,"role":"outer"},{"type":"way","ref":184402326,"role":"outer"},{"type":"way","ref":314899865,"role":"outer"},{"type":"way","ref":314956402,"role":"outer"}],"tags":{"access":"yes","image":"https://i.imgur.com/Yu4qHh5.jpg","leisure":"nature_reserve","name":"Warandeputten","operator":"Natuurpunt Vallei van de Zuidleie","type":"multipolygon","wikipedia":"nl:Warandeputten"}},{"type":"relation","id":8782624,"members":[{"type":"way","ref":315041273,"role":"outer"},{"type":"way","ref":631377343,"role":"outer"},{"type":"way","ref":631371237,"role":"outer"},{"type":"way","ref":631371236,"role":"outer"},{"type":"way","ref":631371234,"role":"outer"},{"type":"way","ref":631377344,"role":"outer"},{"type":"way","ref":631371232,"role":"outer"},{"type":"way","ref":631371231,"role":"outer"},{"type":"way","ref":315041263,"role":"outer"},{"type":"way","ref":631371228,"role":"outer"},{"type":"way","ref":631377341,"role":"outer"},{"type":"way","ref":315041261,"role":"outer"},{"type":"way","ref":631371223,"role":"outer"}],"tags":{"access":"yes","image:0":"https://i.imgur.com/VuzX5jW.jpg","image:1":"https://i.imgur.com/tPppmJG.jpg","image:2":"https://i.imgur.com/ecY3RER.jpg","image:3":"https://i.imgur.com/lr4FK6j.jpg","image:5":"https://i.imgur.com/uufEeE6.jpg","leisure":"nature_reserve","name":"Leiemeersen Noord","operator":"Natuurpunt Vallei van de Zuidleie","type":"multipolygon","website":"http://valleivandezuidleie.be/info-over-de-vallei-van-de-zuidleie/leiemeersen-noord/"}},{"type":"relation","id":8890076,"members":[{"type":"way","ref":640979982,"role":"outer"},{"type":"way","ref":640979978,"role":"outer"}],"tags":{"access":"yes","image:0":"https://i.imgur.com/SAAaKBH.jpg","image:1":"https://i.imgur.com/DGK9iBN.jpg","image:2":"https://i.imgur.com/bte1KJx.jpg","image:3":"https://i.imgur.com/f75Gxnx.jpg","leisure":"nature_reserve","name":"Gevaerts Noord","operator":"Natuurpunt Vallei van de Zuidleie","type":"multipolygon"}},{"type":"relation","id":9118029,"members":[{"type":"way","ref":606165130,"role":"outer"},{"type":"way","ref":655652319,"role":"outer"},{"type":"way","ref":655652321,"role":"outer"}],"tags":{"access":"no","image:0":"https://i.imgur.com/eBufo0v.jpg","image:1":"https://i.imgur.com/kBej2Nk.jpg","image:2":"https://i.imgur.com/QKoyIRl.jpg","leisure":"nature_reserve","name":"De Leiemeersen","note":"Door de hoge kwetsbaarheid van het gebied zijn De Leiemeersen enkel te bezoeken onder begeleiding van een gids","note:mapping":"NIET VOOR BEGINNENDE MAPPERS! Dit gebied is met relaties als multipolygonen gemapt (zo'n 50 stuks). Als je niet weet hoe dit werkt, vraag hulp.","note_1":"wetland=marsh is het veenmoerasgebied","operator":"Natuurpunt Vallei van de Zuidleie","type":"multipolygon","website":"http://valleivandezuidleie.be/info-over-de-vallei-van-de-zuidleie/leiemeersen/"}},{"type":"node","id":668981602,"lat":51.1588243,"lon":3.2558654,"timestamp":"2012-07-06T17:58:39Z","version":2,"changeset":12133044,"user":"martino260","uid":655442,"tags":{"amenity":"bench"}},{"type":"node","id":668981622,"lat":51.1565636,"lon":3.2549888,"timestamp":"2020-03-23T23:54:26Z","version":4,"changeset":82544029,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"leisure":"bird_hide","operator":"Natuurpunt Vallei van de Zuidleie","shelter":"no"}},{"type":"node","id":1580339675,"lat":51.1395949,"lon":3.3332507,"timestamp":"2012-01-07T00:44:42Z","version":1,"changeset":10317754,"user":"popaultje","uid":519184,"tags":{"amenity":"parking"}},{"type":"node","id":1764571836,"lat":51.1701118,"lon":3.3363371,"timestamp":"2012-05-24T21:06:50Z","version":1,"changeset":11693640,"user":"popaultje","uid":519184,"tags":{"amenity":"parking"}},{"type":"node","id":2121652779,"lat":51.1268536,"lon":3.3239607,"timestamp":"2013-01-20T20:12:50Z","version":1,"changeset":14725799,"user":"tomvdb","uid":437764,"tags":{"amenity":"parking"}},{"type":"node","id":2386053906,"lat":51.162161,"lon":3.263065,"timestamp":"2018-01-19T21:31:30Z","version":2,"changeset":55589374,"user":"L'imaginaire","uid":654234,"tags":{"amenity":"toilets"}},{"type":"node","id":2978180520,"lat":51.1329149,"lon":3.3362322,"timestamp":"2014-07-24T21:29:38Z","version":1,"changeset":24338416,"user":"pieterjanheyse","uid":254767,"tags":{"amenity":"bench"}},{"type":"node","id":2978183271,"lat":51.1324243,"lon":3.3373735,"timestamp":"2019-09-14T05:02:25Z","version":2,"changeset":74462201,"user":"JanFi","uid":672253,"tags":{"amenity":"bench"}},{"type":"node","id":2978184471,"lat":51.1436385,"lon":3.2916539,"timestamp":"2021-02-26T10:22:54Z","version":3,"changeset":100041319,"user":"s8evq","uid":3710738,"tags":{"amenity":"bench","backrest":"yes","check_date":"2021-02-26"}},{"type":"node","id":3925976407,"lat":51.1787486,"lon":3.2831866,"timestamp":"2019-08-12T19:48:31Z","version":2,"changeset":73281516,"user":"s8evq","uid":3710738,"tags":{"leisure":"picnic_table"}},{"type":"node","id":5158056232,"lat":51.1592067,"lon":3.2567111,"timestamp":"2021-04-17T16:21:52Z","version":5,"changeset":103110072,"user":"L'imaginaire","uid":654234,"tags":{"leisure":"bird_hide","operator":"Natuurpunt Vallei van de Zuidleie","shelter":"no"}},{"type":"node","id":5718776382,"lat":51.1609023,"lon":3.2582509,"timestamp":"2021-10-18T10:27:50Z","version":3,"changeset":112646117,"user":"s8evq","uid":3710738,"tags":{"check_date":"2021-02-26","covered":"no","leisure":"picnic_table"}},{"type":"node","id":5718776383,"lat":51.1609488,"lon":3.2581877,"timestamp":"2021-10-18T10:27:50Z","version":3,"changeset":112646117,"user":"s8evq","uid":3710738,"tags":{"check_date":"2021-02-26","covered":"no","leisure":"picnic_table"}},{"type":"node","id":5745727100,"lat":51.1594639,"lon":3.2604304,"timestamp":"2018-07-07T18:00:29Z","version":1,"changeset":60494261,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"amenity":"bench"}},{"type":"node","id":5745739587,"lat":51.1580397,"lon":3.263101,"timestamp":"2021-02-26T10:07:56Z","version":2,"changeset":100039706,"user":"s8evq","uid":3710738,"tags":{"check_date":"2021-02-26","leisure":"picnic_table"}},{"type":"node","id":5745739588,"lat":51.1580631,"lon":3.2630345,"timestamp":"2021-02-26T10:07:41Z","version":2,"changeset":100039706,"user":"s8evq","uid":3710738,"tags":{"check_date":"2021-02-26","leisure":"picnic_table"}},{"type":"node","id":5961596093,"lat":51.1588103,"lon":3.2633933,"timestamp":"2018-10-06T14:41:12Z","version":1,"changeset":63258667,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"leisure":"picnic_table"}},{"type":"node","id":5964032193,"lat":51.1514821,"lon":3.2723766,"timestamp":"2018-10-07T12:15:53Z","version":1,"changeset":63277533,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"leisure":"picnic_table"}},{"type":"node","id":6034563379,"lat":51.1421689,"lon":3.3022271,"timestamp":"2020-02-11T20:10:26Z","version":2,"changeset":80868434,"user":"s8evq","uid":3710738,"tags":{"leisure":"picnic_table"}},{"type":"node","id":6034564191,"lat":51.1722186,"lon":3.2823584,"timestamp":"2018-11-04T20:27:50Z","version":2,"changeset":64177431,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"leisure":"picnic_table"}},{"type":"node","id":6034565298,"lat":51.1722796,"lon":3.282329,"timestamp":"2018-11-04T20:27:50Z","version":2,"changeset":64177431,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"leisure":"picnic_table"}},{"type":"node","id":6145151111,"lat":51.1690435,"lon":3.3388676,"timestamp":"2018-12-18T13:13:36Z","version":1,"changeset":65580728,"user":"Siel Nollet","uid":3292414,"tags":{"amenity":"bench"}},{"type":"node","id":6145151112,"lat":51.1690023,"lon":3.3388636,"timestamp":"2018-12-18T13:13:36Z","version":1,"changeset":65580728,"user":"Siel Nollet","uid":3292414,"tags":{"amenity":"bench"}},{"type":"node","id":6216549651,"lat":51.1292813,"lon":3.332369,"timestamp":"2019-01-17T16:29:02Z","version":1,"changeset":66400781,"user":"Nilsnn","uid":4652000,"tags":{"amenity":"bench"}},{"type":"node","id":6216549652,"lat":51.1292768,"lon":3.3324259,"timestamp":"2019-01-17T16:29:03Z","version":1,"changeset":66400781,"user":"Nilsnn","uid":4652000,"tags":{"amenity":"bench"}},{"type":"node","id":7204447030,"lat":51.1791769,"lon":3.283116,"timestamp":"2021-01-01T12:18:32Z","version":3,"changeset":96768203,"user":"L'imaginaire","uid":654234,"tags":{"board_type":"nature","information":"board","mapillary":"0BHVgU1XCyTMM9cjvidUqk","name":"De Assebroekse Meersen","tourism":"information"}},{"type":"node","id":7468175778,"lat":51.1344104,"lon":3.3348246,"timestamp":"2020-04-30T19:07:49Z","version":1,"changeset":84433940,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"leisure":"picnic_table"}},{"type":"node","id":7602473480,"lat":51.1503874,"lon":3.2836867,"timestamp":"2020-06-08T10:39:07Z","version":1,"changeset":86349440,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"leisure":"picnic_table"}},{"type":"node","id":7602473482,"lat":51.150244,"lon":3.2842925,"timestamp":"2021-02-26T10:18:19Z","version":4,"changeset":100040859,"user":"s8evq","uid":3710738,"tags":{"board_type":"wildlife","information":"board","name":"Waterbeestjes","operator":"Natuurpunt Vallei van de Zuidleie","tourism":"information"}},{"type":"node","id":7602699080,"lat":51.1367031,"lon":3.3320712,"timestamp":"2020-06-08T12:08:11Z","version":1,"changeset":86353903,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"amenity":"bench","backrest":"yes","material":"metal"}},{"type":"node","id":7680940369,"lat":51.1380074,"lon":3.3369928,"timestamp":"2020-07-03T17:54:31Z","version":1,"changeset":87513827,"user":"L'imaginaire","uid":654234,"tags":{"amenity":"bench"}},{"type":"node","id":7726850522,"lat":51.1418585,"lon":3.3064234,"timestamp":"2020-07-18T15:57:43Z","version":1,"changeset":88179934,"user":"Pieter Vander Vennet","uid":3818858,"tags":{"image:0":"https://i.imgur.com/Bh6UjYy.jpg","information":"board","tourism":"information"}},{"type":"node","id":7727071212,"lat":51.1501173,"lon":3.2845352,"timestamp":"2021-02-26T10:17:39Z","version":2,"changeset":100040859,"user":"s8evq","uid":3710738,"tags":{"board_type":"wildlife","image:0":"https://i.imgur.com/mFEQJWd.jpg","information":"board","name":"Vleermuizen","operator":"Natuurpunt Vallei van de Zuidleie","tourism":"information"}},{"type":"node","id":9122376662,"lat":51.1720505,"lon":3.3308524,"timestamp":"2021-09-25T13:32:42Z","version":1,"changeset":111688164,"user":"TeamP8","uid":718373,"tags":{"amenity":"bench"}},{"type":"node","id":9425818876,"lat":51.1325315,"lon":3.3371616,"timestamp":"2022-01-28T20:13:29Z","version":3,"changeset":116721474,"user":"L'imaginaire","uid":654234,"tags":{"leisure":"picnic_table","mapillary":"101961548889238"}},{"type":"way","id":149408639,"timestamp":"2012-08-15T19:09:59Z","version":4,"changeset":12742790,"user":"tomvdb","uid":437764,"nodes":[1623924235,1623924236,1623924238,1864750831,1623924241,1623924235],"tags":{"amenity":"parking"}},{"type":"way","id":149553206,"timestamp":"2021-01-30T12:11:53Z","version":4,"changeset":98411765,"user":"L'imaginaire","uid":654234,"nodes":[1625199938,1625199951,8377691836,8378081366,8378081429,8378081386,1625199950,6414383775,1625199827,1625199938],"tags":{"amenity":"parking"}},{"type":"way","id":184402308,"timestamp":"2020-03-23T23:54:26Z","version":6,"changeset":82544029,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[1948836195,1948836194,1948836193,1948836189,1948836192,1948836195],"tags":{"building":"yes","leisure":"bird_hide","operator":"Natuurpunt Vallei van de Zuidleie","shelter":"yes","wheelchair":"yes"}},{"type":"way","id":184402309,"timestamp":"2021-12-20T11:33:54Z","version":8,"changeset":115161990,"user":"s8evq","uid":3710738,"nodes":[1948836029,1948836038,1948836032,1948836025,1948836023,1948836029],"tags":{"building":"yes","leisure":"bird_hide","operator":"Natuurpunt Vallei van de Zuidleie","shelter":"yes","source:geometry:date":"2011-11-07","source:geometry:ref":"Gbg/3489204"}},{"type":"way","id":184402331,"timestamp":"2021-02-26T10:03:17Z","version":4,"changeset":100039746,"user":"s8evq","uid":3710738,"nodes":[1948836104,1948836072,1948836068,1948836093,1948836104],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface"}},{"type":"way","id":236979353,"timestamp":"2021-01-25T12:38:22Z","version":4,"changeset":98122705,"user":"JosV","uid":170722,"nodes":[2449323191,7962681624,7962681623,7962681621,7962681622,2449323193,7962681620,7962681619,8360787098,4350143592,6794421028,6794421027,6794421041,7962681614,2123461969,2449323198,7962681615,7962681616,6794421042,2449323191],"tags":{"amenity":"parking"}},{"type":"way","id":251590503,"timestamp":"2019-04-20T22:04:54Z","version":2,"changeset":69412561,"user":"L'imaginaire","uid":654234,"nodes":[2577910543,2577910530,2577910542,2577910520,6418533335,2577910526,2577910545,2577910543],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":313090489,"timestamp":"2014-11-16T14:59:12Z","version":1,"changeset":26823403,"user":"JanFi","uid":672253,"nodes":[3190107423,3190107435,3190107442,3190107439,3190107432,3190107428,3190107424,3190107400,3190107393,3190107377,3190107371,3190107374,3190107408,3190107407,3190107415,3190107416,3190107420,3190107423],"tags":{"amenity":"parking"}},{"type":"way","id":314531418,"timestamp":"2021-05-30T17:02:49Z","version":21,"changeset":105576255,"user":"s8evq","uid":3710738,"nodes":[7468171455,7468171451,7727393212,7727393211,7727393210,7727393208,7727393209,8781449489,7727393207,7727393206,7727393205,7727393204,7727393203,7727393202,7727393201,7727393200,7390697550,7390697534,7727393199,7727393198,7727393197,7390697549,7727393196,7727393195,7727393194,7727393193,7727393192,7727393191,7727393190,7727393189,7727393188,7727393187,7727393186,7727393185,7727339384,7727339383,7727339382,1553169911,1553169836,1493821433,1493821422,3185248088,7727339364,7727339365,7727339366,7727339367,7727339368,7727339369,7727339370,7727339371,7727339372,7727339373,7727339374,7727339375,7727339376,7727339377,3185248049,3185248048,3185248042,3185248040,7727339378,7727339379,7727339380,7727339381,7468171438,7468171442,7468171430,7468171432,7468171446,7468171404,7468171405,7468171422,7468171426,7468171433,7468171423,7468171428,7468171431,7468171429,7468171406,7468171407,7468171444,7468171408,7468171409,7468171410,7468171411,7468171412,7468171413,7190927792,7190927791,7190927793,7190927787,7190927788,7190927789,7190927790,7190927786,7602692242,7190927785,7190873584,7468171450,7190873582,7190873576,7190873578,7190873577,7468171455],"tags":{"access":"yes","dog":"leashed","dogs":"leashed","image":"https://i.imgur.com/cOfwWTj.jpg","image:0":"https://i.imgur.com/RliQdyi.jpg","image:1":"https://i.imgur.com/IeKHahz.jpg","image:2":"https://i.imgur.com/1K0IORH.jpg","image:3":"https://i.imgur.com/jojP09s.jpg","image:4":"https://i.imgur.com/DK6kT51.jpg","image:5":"https://i.imgur.com/RizbGM1.jpg","image:6":"https://i.imgur.com/hyoY6Cl.jpg","image:7":"https://i.imgur.com/xDd7Wrq.jpg","leisure":"nature_reserve","name":"Miseriebocht","operator":"Natuurpunt Beernem","website":"https://www.natuurpunt.be/natuurgebied/miseriebocht","wikidata":"Q97060915"}},{"type":"way","id":366318480,"timestamp":"2015-08-18T13:50:59Z","version":1,"changeset":33415758,"user":"xras3r","uid":323672,"nodes":[3702926557,3702926558,3702926559,3702926560,3702926557],"tags":{"amenity":"parking"}},{"type":"way","id":366318481,"timestamp":"2015-08-18T13:50:59Z","version":1,"changeset":33415758,"user":"xras3r","uid":323672,"nodes":[3702878648,3702926561,3702926562,3702926563,3702926564,3702926565,3702926566,3702926567,3702878648],"tags":{"amenity":"parking"}},{"type":"way","id":366318482,"timestamp":"2021-01-05T09:04:32Z","version":2,"changeset":96964072,"user":"JosV","uid":170722,"nodes":[3702926568,8292789053,8292789054,3702878654,3702926568],"tags":{"amenity":"parking"}},{"type":"way","id":366320440,"timestamp":"2015-08-18T14:02:00Z","version":1,"changeset":33415981,"user":"xras3r","uid":323672,"nodes":[3702956173,3702956174,3702956175,3702956176,3702956173],"tags":{"amenity":"parking","name":"Kleine Beer"}},{"type":"way","id":366321706,"timestamp":"2015-08-18T14:15:30Z","version":1,"changeset":33416303,"user":"xras3r","uid":323672,"nodes":[3702969714,3702969715,3702969716,3702969717,3702969714],"tags":{"amenity":"parking"}},{"type":"way","id":480267681,"timestamp":"2021-01-05T21:32:23Z","version":2,"changeset":97006454,"user":"JosV","uid":170722,"nodes":[4732689641,4732689640,4732689639,4732689638,4732689637,4732689636,4732689635,4732689634,4732689633,4732689632,4732689631,4732689630,4732689629,4732689628,4732689627,4732689626,8294875888,4732689641],"tags":{"amenity":"parking"}},{"type":"way","id":554341620,"timestamp":"2018-01-19T21:31:30Z","version":1,"changeset":55589374,"user":"L'imaginaire","uid":654234,"nodes":[5349884603,5349884602,5349884601,5349884600,5349884603],"tags":{"amenity":"parking"}},{"type":"way","id":554341621,"timestamp":"2018-01-19T21:31:30Z","version":1,"changeset":55589374,"user":"L'imaginaire","uid":654234,"nodes":[5349884607,5349884606,5349884605,5349884604,5349884607],"tags":{"amenity":"parking"}},{"type":"way","id":561902092,"timestamp":"2021-01-17T14:52:46Z","version":6,"changeset":97640804,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[5417516023,5417515520,5417516021,5417516022,5417516023],"tags":{"building":"yes","image":"https://i.imgur.com/WmViSbL.jpg","leisure":"bird_hide","operator":"Natuurpunt Vallei van de Zuidleie","shelter":"yes","wheelchair":"no"}},{"type":"way","id":605915064,"timestamp":"2018-07-07T18:07:31Z","version":1,"changeset":60494380,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[5745739924,5745739925,5745739926,5745739927,5745739924],"tags":{"amenity":"parking","surface":"fine2"}},{"type":"way","id":650285088,"timestamp":"2021-01-29T09:37:56Z","version":2,"changeset":98352073,"user":"JosV","uid":170722,"nodes":[3645188881,6100803131,6100803130,6100803129,6100803124,6100803125,6100803128,6100803127,6100803126,3645188881],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":655944574,"timestamp":"2020-02-23T22:05:54Z","version":2,"changeset":81377451,"user":"L'imaginaire","uid":654234,"nodes":[6145151107,6145151108,6145151109,6145151115,6145151114,6145151110,6145151107],"tags":{"amenity":"parking"}},{"type":"way","id":664171069,"timestamp":"2019-01-17T16:29:08Z","version":1,"changeset":66400781,"user":"Nilsnn","uid":4652000,"nodes":[6216549610,6216549611,6216549612,6216549613,1413470849,1413470848,6216549605,6216549604,6216549610],"tags":{"amenity":"parking"}},{"type":"way","id":664171076,"timestamp":"2021-01-09T21:56:37Z","version":3,"changeset":97230316,"user":"JosV","uid":170722,"nodes":[6216549656,6216549655,8307316294,6216549661,6216549657,6216549658,6216549659,6216549660,6216549656],"tags":{"amenity":"parking","capacity":"50"}},{"type":"way","id":665330334,"timestamp":"2019-01-22T14:20:51Z","version":1,"changeset":66539354,"user":"Nilsnn","uid":4652000,"nodes":[6227395993,6227395991,6227395992,6227395997,6227395993],"tags":{"access":"yes","amenity":"parking","fee":"no","parking":"surface","surface":"asphalt"}},{"type":"way","id":684598363,"timestamp":"2020-03-07T14:21:22Z","version":3,"changeset":81900556,"user":"L'imaginaire","uid":654234,"nodes":[3227068565,6416001161,6414352054,6414352055,7274233390,7274233391,7274233397,7274233395,7274233396,6414352053,3227068568,3227068565],"tags":{"amenity":"parking","fee":"no"}},{"type":"way","id":684599810,"timestamp":"2020-12-31T20:58:28Z","version":3,"changeset":96751036,"user":"JosV","uid":170722,"nodes":[1317838331,8279842668,1384096112,1317838328,6414374315,3227068446,6414374316,6414374317,6414374318,3227068456,6414374319,6414374320,6414374321,1317838317,1317838331],"tags":{"access":"no","amenity":"parking","operator":"Politie"}},{"type":"way","id":761474468,"timestamp":"2021-01-05T21:32:23Z","version":3,"changeset":97006454,"user":"JosV","uid":170722,"nodes":[7114502201,7114502203,7114502200,7114502202,3170562439,3170562437,3170562431,7114502240,7114502211,7114502212,7114502214,7114502215,7114502228,7114502234,7114502235,7114502236,7114502237,7114502238,7114502239,7114502233,7114502232,7114502231,7114502229,7114502230,7114502227,7114502226,7114502225,7114502216,7114502217,7114502224,3170562392,7114502218,3170562394,7114502219,7114502220,7114502221,7114502222,7114502223,3170562395,3170562396,3170562397,3170562402,3170562410,7114502209,7114502208,7114502207,7114502205,7114502206,3170562436,1475188519,1475188516,6627605025,8294886142,7114502201],"tags":{"image":"http://valleivandezuidleie.be/wp-content/uploads/2011/12/2011-03-24_G12_088_1_1.JPG","leisure":"nature_reserve","name":"Merlebeek-Meerberg","natural":"wetland","operator":"Natuurpunt Vallei van de Zuidleie","start_date":"2011","website":"http://valleivandezuidleie.be/info-over-de-vallei-van-de-zuidleie/merlebeek/","wetland":"wet_meadow"}},{"type":"way","id":813859435,"timestamp":"2021-02-26T10:18:26Z","version":3,"changeset":100040879,"user":"s8evq","uid":3710738,"nodes":[7602479690,7459257985,7602479691,7459154784,7459154782,7602479692,5482441357,7602479693,7602479694,7602479695,7602479696,7602479690],"tags":{"access":"yes","image:0":"https://i.imgur.com/nb9nawa.jpg","landuse":"grass","leisure":"nature_reserve","name:signed":"no","natural":"grass","operator":"Natuurpunt Vallei van de Zuidleie"}},{"type":"way","id":826103452,"timestamp":"2020-07-14T09:05:14Z","version":1,"changeset":87965884,"user":"L'imaginaire","uid":654234,"nodes":[7713176912,7713176911,7713176910,7713176909,7713176912],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":893176022,"timestamp":"2021-01-07T23:02:07Z","version":1,"changeset":97133621,"user":"JosV","uid":170722,"nodes":[1927235214,8301349336,8301349335,8301349337,1927235214],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":895943476,"timestamp":"2021-01-16T17:56:50Z","version":1,"changeset":97614669,"user":"JosV","uid":170722,"nodes":[8328251887,8328251886,8328251885,8328251884,8328251887],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":895943477,"timestamp":"2021-01-16T17:56:50Z","version":1,"changeset":97614669,"user":"JosV","uid":170722,"nodes":[8328251891,8328251890,8328251889,8328251888,8328251891],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":895943478,"timestamp":"2021-01-16T17:56:50Z","version":1,"changeset":97614669,"user":"JosV","uid":170722,"nodes":[8328251895,8328251894,8328251893,8328251892,8328251895],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":895943479,"timestamp":"2021-01-16T17:56:50Z","version":1,"changeset":97614669,"user":"JosV","uid":170722,"nodes":[8328251897,8328251896,8328251901,8328251900,8328251897],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":895943480,"timestamp":"2021-01-16T17:56:50Z","version":1,"changeset":97614669,"user":"JosV","uid":170722,"nodes":[8328251898,8328251899,8328251903,8328251902,8328251898],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":895943481,"timestamp":"2021-01-16T17:56:50Z","version":1,"changeset":97614669,"user":"JosV","uid":170722,"nodes":[8328251907,8328251906,8328251905,8328251904,8328251907],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":895943482,"timestamp":"2021-01-16T17:56:50Z","version":1,"changeset":97614669,"user":"JosV","uid":170722,"nodes":[8328251911,8328251910,8328251909,8328251908,8328251911],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":901952767,"timestamp":"2021-01-30T12:19:15Z","version":1,"changeset":98412028,"user":"L'imaginaire","uid":654234,"nodes":[8378097127,8378097126,8378097125,8378097124,8378097127],"tags":{"amenity":"parking","parking":"street_side"}},{"type":"way","id":901952768,"timestamp":"2021-01-30T12:19:15Z","version":1,"changeset":98412028,"user":"L'imaginaire","uid":654234,"nodes":[8378097134,8378097133,8378097132,8378097131,8378097130,8378097129,8378097128,8378097134],"tags":{"amenity":"parking","parking":"street_side"}},{"type":"way","id":947325182,"timestamp":"2021-05-26T15:16:06Z","version":1,"changeset":105366812,"user":"L'imaginaire","uid":654234,"nodes":[8497007549,8768981525,8768981522,8768981524,8768981521,8768981523,8768981520,8768981519,6206789709,8768981533,8497007549],"tags":{"amenity":"parking","parking":"surface"}},{"type":"way","id":966827815,"timestamp":"2021-07-23T20:01:09Z","version":1,"changeset":108511361,"user":"L'imaginaire","uid":654234,"nodes":[8945026757,8945026756,8945026755,8945026754,8945026757],"tags":{"access":"customers","amenity":"parking","parking":"surface"}},{"type":"relation","id":2589413,"timestamp":"2021-03-06T15:13:01Z","version":7,"changeset":100540347,"user":"Pieter Vander Vennet","uid":3818858,"members":[{"type":"way","ref":663050030,"role":"outer"},{"type":"way","ref":184402334,"role":"outer"},{"type":"way","ref":184402332,"role":"outer"},{"type":"way","ref":184402325,"role":"outer"},{"type":"way","ref":184402326,"role":"outer"},{"type":"way","ref":314899865,"role":"outer"},{"type":"way","ref":314956402,"role":"outer"}],"tags":{"access":"yes","image":"https://i.imgur.com/Yu4qHh5.jpg","leisure":"nature_reserve","name":"Warandeputten","operator":"Natuurpunt Vallei van de Zuidleie","type":"multipolygon","wikipedia":"nl:Warandeputten"}},{"type":"relation","id":8782624,"timestamp":"2021-03-08T13:15:15Z","version":14,"changeset":100640534,"user":"M!dgard","uid":763799,"members":[{"type":"way","ref":315041273,"role":"outer"},{"type":"way","ref":631377343,"role":"outer"},{"type":"way","ref":631371237,"role":"outer"},{"type":"way","ref":631371236,"role":"outer"},{"type":"way","ref":631371234,"role":"outer"},{"type":"way","ref":631377344,"role":"outer"},{"type":"way","ref":631371232,"role":"outer"},{"type":"way","ref":631371231,"role":"outer"},{"type":"way","ref":315041263,"role":"outer"},{"type":"way","ref":631371228,"role":"outer"},{"type":"way","ref":631377341,"role":"outer"},{"type":"way","ref":315041261,"role":"outer"},{"type":"way","ref":631371223,"role":"outer"}],"tags":{"access":"yes","image:0":"https://i.imgur.com/VuzX5jW.jpg","image:1":"https://i.imgur.com/tPppmJG.jpg","image:2":"https://i.imgur.com/ecY3RER.jpg","image:3":"https://i.imgur.com/lr4FK6j.jpg","image:5":"https://i.imgur.com/uufEeE6.jpg","leisure":"nature_reserve","name":"Leiemeersen Noord","operator":"Natuurpunt Vallei van de Zuidleie","type":"multipolygon","website":"http://valleivandezuidleie.be/info-over-de-vallei-van-de-zuidleie/leiemeersen-noord/"}},{"type":"relation","id":8890076,"timestamp":"2020-07-18T15:56:50Z","version":6,"changeset":88179905,"user":"Pieter Vander Vennet","uid":3818858,"members":[{"type":"way","ref":640979982,"role":"outer"},{"type":"way","ref":640979978,"role":"outer"}],"tags":{"access":"yes","image:0":"https://i.imgur.com/SAAaKBH.jpg","image:1":"https://i.imgur.com/DGK9iBN.jpg","image:2":"https://i.imgur.com/bte1KJx.jpg","image:3":"https://i.imgur.com/f75Gxnx.jpg","leisure":"nature_reserve","name":"Gevaerts Noord","operator":"Natuurpunt Vallei van de Zuidleie","type":"multipolygon"}},{"type":"relation","id":9118029,"timestamp":"2020-07-11T12:04:16Z","version":4,"changeset":87852045,"user":"Pieter Vander Vennet","uid":3818858,"members":[{"type":"way","ref":606165130,"role":"outer"},{"type":"way","ref":655652319,"role":"outer"},{"type":"way","ref":655652321,"role":"outer"}],"tags":{"access":"no","image:0":"https://i.imgur.com/eBufo0v.jpg","image:1":"https://i.imgur.com/kBej2Nk.jpg","image:2":"https://i.imgur.com/QKoyIRl.jpg","leisure":"nature_reserve","name":"De Leiemeersen","note":"Door de hoge kwetsbaarheid van het gebied zijn De Leiemeersen enkel te bezoeken onder begeleiding van een gids","note:mapping":"NIET VOOR BEGINNENDE MAPPERS! Dit gebied is met relaties als multipolygonen gemapt (zo'n 50 stuks). Als je niet weet hoe dit werkt, vraag hulp.","note_1":"wetland=marsh is het veenmoerasgebied","operator":"Natuurpunt Vallei van de Zuidleie","type":"multipolygon","website":"http://valleivandezuidleie.be/info-over-de-vallei-van-de-zuidleie/leiemeersen/"}},{"type":"node","id":7114502229,"lat":51.1340508,"lon":3.2949303},{"type":"node","id":7114502231,"lat":51.1340428,"lon":3.2959613},{"type":"node","id":7114502232,"lat":51.134096,"lon":3.2971973},{"type":"node","id":1927235214,"lat":51.1267391,"lon":3.3222921},{"type":"node","id":8301349336,"lat":51.1266966,"lon":3.3223356},{"type":"node","id":1413470848,"lat":51.1276558,"lon":3.3278194},{"type":"node","id":1413470849,"lat":51.1276852,"lon":3.3274627},{"type":"node","id":6216549605,"lat":51.1276578,"lon":3.3279376},{"type":"node","id":6216549611,"lat":51.1277354,"lon":3.3273608},{"type":"node","id":6216549612,"lat":51.1277281,"lon":3.3274215},{"type":"node","id":6216549613,"lat":51.1277062,"lon":3.3274249},{"type":"node","id":8301349335,"lat":51.1269096,"lon":3.3228882},{"type":"node","id":8301349337,"lat":51.126955,"lon":3.3228466},{"type":"node","id":8328251884,"lat":51.1278701,"lon":3.3253392},{"type":"node","id":8328251885,"lat":51.127857,"lon":3.3254078},{"type":"node","id":8328251888,"lat":51.1278797,"lon":3.325168},{"type":"node","id":8328251889,"lat":51.1278665,"lon":3.3252369},{"type":"node","id":8328251892,"lat":51.1271569,"lon":3.3248958},{"type":"node","id":8328251893,"lat":51.1272208,"lon":3.3252329},{"type":"node","id":8328251894,"lat":51.1272677,"lon":3.3252111},{"type":"node","id":8328251895,"lat":51.1272033,"lon":3.3248728},{"type":"node","id":8328251896,"lat":51.1271015,"lon":3.3257575},{"type":"node","id":8328251897,"lat":51.1270872,"lon":3.3256877},{"type":"node","id":8328251898,"lat":51.1271271,"lon":3.325744},{"type":"node","id":8328251899,"lat":51.1271128,"lon":3.3256743},{"type":"node","id":8328251900,"lat":51.1270462,"lon":3.3257067},{"type":"node","id":8328251901,"lat":51.1270609,"lon":3.3257756},{"type":"node","id":8328251902,"lat":51.1272095,"lon":3.3257043},{"type":"node","id":8328251903,"lat":51.1271957,"lon":3.3256351},{"type":"node","id":8328251904,"lat":51.1269631,"lon":3.3253915},{"type":"node","id":8328251905,"lat":51.1269756,"lon":3.3254617},{"type":"node","id":8328251906,"lat":51.1271678,"lon":3.3253747},{"type":"node","id":8328251907,"lat":51.1271557,"lon":3.3253045},{"type":"node","id":8328251908,"lat":51.1270115,"lon":3.3255467},{"type":"node","id":8328251909,"lat":51.1270235,"lon":3.3256138},{"type":"node","id":8328251910,"lat":51.1271099,"lon":3.3255749},{"type":"node","id":8328251911,"lat":51.1270975,"lon":3.3255072},{"type":"node","id":2449323191,"lat":51.1340437,"lon":3.3216558},{"type":"node","id":2449323193,"lat":51.134285,"lon":3.3221086},{"type":"node","id":2449323198,"lat":51.1334724,"lon":3.3223472},{"type":"node","id":4350143592,"lat":51.1344661,"lon":3.3226292},{"type":"node","id":4732689626,"lat":51.1301038,"lon":3.3223672},{"type":"node","id":4732689627,"lat":51.1301351,"lon":3.3223533},{"type":"node","id":4732689628,"lat":51.130161,"lon":3.3224805},{"type":"node","id":4732689629,"lat":51.1301379,"lon":3.3224524},{"type":"node","id":4732689630,"lat":51.130151,"lon":3.3225204},{"type":"node","id":4732689631,"lat":51.1301375,"lon":3.3225274},{"type":"node","id":4732689632,"lat":51.1301505,"lon":3.322593},{"type":"node","id":4732689634,"lat":51.1297694,"lon":3.3223954},{"type":"node","id":4732689635,"lat":51.1298034,"lon":3.3223641},{"type":"node","id":4732689636,"lat":51.1297546,"lon":3.3221883},{"type":"node","id":4732689637,"lat":51.1297088,"lon":3.3219708},{"type":"node","id":4732689638,"lat":51.1297683,"lon":3.3219402},{"type":"node","id":4732689639,"lat":51.1297781,"lon":3.3219034},{"type":"node","id":4732689640,"lat":51.1297694,"lon":3.3218478},{"type":"node","id":4732689641,"lat":51.1300088,"lon":3.32173},{"type":"node","id":6794421027,"lat":51.1341852,"lon":3.3223337},{"type":"node","id":6794421042,"lat":51.1336271,"lon":3.3220973},{"type":"node","id":7962681614,"lat":51.1336656,"lon":3.322624},{"type":"node","id":7962681615,"lat":51.1335301,"lon":3.322287},{"type":"node","id":7962681616,"lat":51.1335065,"lon":3.3222317},{"type":"node","id":7962681619,"lat":51.134306,"lon":3.3222136},{"type":"node","id":7962681620,"lat":51.1343186,"lon":3.3221995},{"type":"node","id":7962681621,"lat":51.1341453,"lon":3.321775},{"type":"node","id":7962681622,"lat":51.1341537,"lon":3.321769},{"type":"node","id":7962681623,"lat":51.1341067,"lon":3.3216811},{"type":"node","id":7962681624,"lat":51.1340675,"lon":3.3217193},{"type":"node","id":8294875888,"lat":51.1300197,"lon":3.3219403},{"type":"node","id":8360787098,"lat":51.1344583,"lon":3.3225918},{"type":"node","id":2123461969,"lat":51.1336123,"lon":3.3226786},{"type":"node","id":4732689633,"lat":51.1298776,"lon":3.3227393},{"type":"node","id":6216549604,"lat":51.1280095,"lon":3.328024},{"type":"node","id":6216549610,"lat":51.128134,"lon":3.3274542},{"type":"node","id":6794421028,"lat":51.1343476,"lon":3.3227429},{"type":"node","id":6794421041,"lat":51.1337382,"lon":3.3227794},{"type":"node","id":8328251886,"lat":51.128048,"lon":3.3255015},{"type":"node","id":8328251887,"lat":51.1280616,"lon":3.3254329},{"type":"node","id":8328251890,"lat":51.1280791,"lon":3.3253407},{"type":"node","id":8328251891,"lat":51.1280922,"lon":3.3252721},{"type":"node","id":1623924235,"lat":51.131361,"lon":3.333018},{"type":"node","id":1623924236,"lat":51.1311039,"lon":3.3325764},{"type":"node","id":1623924238,"lat":51.1310489,"lon":3.3326527},{"type":"node","id":1623924241,"lat":51.1314273,"lon":3.3331479},{"type":"node","id":1864750831,"lat":51.1313615,"lon":3.3332222},{"type":"node","id":6216549655,"lat":51.134416,"lon":3.3347284},{"type":"node","id":6216549656,"lat":51.1343187,"lon":3.3349542},{"type":"node","id":6216549657,"lat":51.1334196,"lon":3.335723},{"type":"node","id":6216549658,"lat":51.1334902,"lon":3.3357377},{"type":"node","id":6216549659,"lat":51.133716,"lon":3.335546},{"type":"node","id":6216549660,"lat":51.133883,"lon":3.3353885},{"type":"node","id":6216549661,"lat":51.133662,"lon":3.3355049},{"type":"node","id":8307316294,"lat":51.1338503,"lon":3.3353095},{"type":"node","id":1493821422,"lat":51.1320567,"lon":3.3398517},{"type":"node","id":1493821433,"lat":51.1316132,"lon":3.3408892},{"type":"node","id":1553169836,"lat":51.1311998,"lon":3.3415993},{"type":"node","id":3185248088,"lat":51.1323359,"lon":3.3389757},{"type":"node","id":7727339364,"lat":51.1321819,"lon":3.3388758},{"type":"node","id":7727339365,"lat":51.1319823,"lon":3.339559},{"type":"node","id":7727339366,"lat":51.1316011,"lon":3.3405485},{"type":"node","id":7727339367,"lat":51.1312764,"lon":3.3411848},{"type":"node","id":7727339368,"lat":51.1310889,"lon":3.3414676},{"type":"node","id":7727339369,"lat":51.1304838,"lon":3.3422395},{"type":"node","id":3185248048,"lat":51.1268693,"lon":3.3480331},{"type":"node","id":3185248049,"lat":51.1269831,"lon":3.3475504},{"type":"node","id":7727339376,"lat":51.1274147,"lon":3.3464515},{"type":"node","id":7727339377,"lat":51.1271283,"lon":3.3469817},{"type":"node","id":3185248040,"lat":51.1266778,"lon":3.3491476},{"type":"node","id":3185248042,"lat":51.126712,"lon":3.3489485},{"type":"node","id":7468171404,"lat":51.1277325,"lon":3.3553578},{"type":"node","id":7468171430,"lat":51.1270326,"lon":3.353594},{"type":"node","id":7468171432,"lat":51.1271802,"lon":3.3540454},{"type":"node","id":7468171438,"lat":51.1268064,"lon":3.3526001},{"type":"node","id":7468171442,"lat":51.1268303,"lon":3.3527746},{"type":"node","id":7468171446,"lat":51.1273659,"lon":3.3546333},{"type":"node","id":7727339378,"lat":51.1265656,"lon":3.3505324},{"type":"node","id":7727339379,"lat":51.1266463,"lon":3.350873},{"type":"node","id":7727339380,"lat":51.1266302,"lon":3.3514032},{"type":"node","id":7727339381,"lat":51.1267774,"lon":3.3523929},{"type":"node","id":7727393190,"lat":51.1276264,"lon":3.3489611},{"type":"node","id":7727393191,"lat":51.1274853,"lon":3.3497484},{"type":"node","id":7727393192,"lat":51.127332,"lon":3.350571},{"type":"node","id":7727393193,"lat":51.1273663,"lon":3.3514386},{"type":"node","id":7727393194,"lat":51.1274853,"lon":3.3519206},{"type":"node","id":7727393195,"lat":51.1276889,"lon":3.3531674},{"type":"node","id":1553169911,"lat":51.1313314,"lon":3.3425771},{"type":"node","id":7727339370,"lat":51.1300705,"lon":3.3427304},{"type":"node","id":7727339371,"lat":51.1293083,"lon":3.343643},{"type":"node","id":7727339372,"lat":51.1285642,"lon":3.3445074},{"type":"node","id":7727339373,"lat":51.1285702,"lon":3.3445781},{"type":"node","id":7727339374,"lat":51.1283181,"lon":3.3448801},{"type":"node","id":7727339375,"lat":51.1281023,"lon":3.3451404},{"type":"node","id":7727339382,"lat":51.1311196,"lon":3.3430952},{"type":"node","id":7727339383,"lat":51.1309343,"lon":3.3434996},{"type":"node","id":7727339384,"lat":51.1306234,"lon":3.343745},{"type":"node","id":7727393185,"lat":51.1300873,"lon":3.3443449},{"type":"node","id":7727393186,"lat":51.129401,"lon":3.3453846},{"type":"node","id":7727393187,"lat":51.1290865,"lon":3.345963},{"type":"node","id":7727393188,"lat":51.1285581,"lon":3.3468788},{"type":"node","id":7727393189,"lat":51.1280217,"lon":3.3479457},{"type":"node","id":7390697549,"lat":51.128429,"lon":3.354427},{"type":"node","id":7727393196,"lat":51.1279813,"lon":3.353749},{"type":"node","id":3209560114,"lat":51.1538874,"lon":3.2531858},{"type":"node","id":3209560115,"lat":51.1539649,"lon":3.2531836},{"type":"node","id":3209560116,"lat":51.1541197,"lon":3.2537986},{"type":"node","id":3209560117,"lat":51.1541021,"lon":3.253149},{"type":"node","id":3210389695,"lat":51.1539646,"lon":3.2534427},{"type":"node","id":416917618,"lat":51.1565737,"lon":3.2549365},{"type":"node","id":668981667,"lat":51.1576026,"lon":3.2555383},{"type":"node","id":668981668,"lat":51.1564046,"lon":3.2547045},{"type":"node","id":1815081998,"lat":51.1575578,"lon":3.2555439},{"type":"node","id":1948835662,"lat":51.155957,"lon":3.2562889},{"type":"node","id":1948835742,"lat":51.156182,"lon":3.2540291},{"type":"node","id":1948835950,"lat":51.1591027,"lon":3.2559292},{"type":"node","id":1948836096,"lat":51.1600831,"lon":3.2562989},{"type":"node","id":1948836149,"lat":51.1605378,"lon":3.2568906},{"type":"node","id":2026541837,"lat":51.1543652,"lon":3.2542901},{"type":"node","id":2026541841,"lat":51.1545903,"lon":3.2546809},{"type":"node","id":2026541843,"lat":51.1548384,"lon":3.2550342},{"type":"node","id":2026541846,"lat":51.155086,"lon":3.2553429},{"type":"node","id":2026541851,"lat":51.15565,"lon":3.2542965},{"type":"node","id":3209560118,"lat":51.1542244,"lon":3.2530815},{"type":"node","id":3209560119,"lat":51.1544741,"lon":3.252803},{"type":"node","id":3209560121,"lat":51.1546028,"lon":3.2526667},{"type":"node","id":3209560124,"lat":51.1547447,"lon":3.2525904},{"type":"node","id":3209560126,"lat":51.1550296,"lon":3.2525253},{"type":"node","id":3209560127,"lat":51.1551915,"lon":3.2525297},{"type":"node","id":3209560131,"lat":51.1553436,"lon":3.2525627},{"type":"node","id":3209560132,"lat":51.1554055,"lon":3.2526006},{"type":"node","id":3209560134,"lat":51.155479,"lon":3.2526651},{"type":"node","id":3209560135,"lat":51.155558,"lon":3.2527647},{"type":"node","id":3209560136,"lat":51.1556482,"lon":3.2528805},{"type":"node","id":3209560138,"lat":51.1559652,"lon":3.2534517},{"type":"node","id":3209560139,"lat":51.1560327,"lon":3.2535705},{"type":"node","id":5417515520,"lat":51.1545998,"lon":3.2545767},{"type":"node","id":5417516021,"lat":51.1545476,"lon":3.2544989},{"type":"node","id":5417516022,"lat":51.1545856,"lon":3.2544342},{"type":"node","id":5417516023,"lat":51.1546378,"lon":3.2545119},{"type":"node","id":6206789688,"lat":51.1553578,"lon":3.255668},{"type":"node","id":416917603,"lat":51.1591104,"lon":3.2595563},{"type":"node","id":416917605,"lat":51.1592829,"lon":3.2591123},{"type":"node","id":416917609,"lat":51.1597764,"lon":3.2597849},{"type":"node","id":1554514806,"lat":51.1586314,"lon":3.2636074},{"type":"node","id":1948835842,"lat":51.1570345,"lon":3.2574053},{"type":"node","id":1948835900,"lat":51.1583428,"lon":3.258761},{"type":"node","id":1948835986,"lat":51.1595419,"lon":3.2593891},{"type":"node","id":1948836023,"lat":51.1597284,"lon":3.2585312},{"type":"node","id":1948836025,"lat":51.1597477,"lon":3.2585581},{"type":"node","id":1948836029,"lat":51.1597506,"lon":3.2584887},{"type":"node","id":1948836032,"lat":51.159778,"lon":3.2585905},{"type":"node","id":1948836038,"lat":51.1597992,"lon":3.2585462},{"type":"node","id":1948836068,"lat":51.1598265,"lon":3.2595499},{"type":"node","id":1948836072,"lat":51.1598725,"lon":3.2596329},{"type":"node","id":1948836093,"lat":51.1600505,"lon":3.2592835},{"type":"node","id":1948836104,"lat":51.1601026,"lon":3.2593298},{"type":"node","id":1948836189,"lat":51.1606847,"lon":3.2577063},{"type":"node","id":5745739926,"lat":51.160615,"lon":3.2602336},{"type":"node","id":5747937642,"lat":51.1580603,"lon":3.2636348},{"type":"node","id":5962340003,"lat":51.1587851,"lon":3.2632739},{"type":"node","id":5962414276,"lat":51.158949,"lon":3.2635109},{"type":"node","id":5962415498,"lat":51.1589617,"lon":3.2635523},{"type":"node","id":5962415499,"lat":51.1589623,"lon":3.2635339},{"type":"node","id":5962415500,"lat":51.1589568,"lon":3.2635203},{"type":"node","id":5962415538,"lat":51.1589195,"lon":3.2636407},{"type":"node","id":6206789709,"lat":51.1545829,"lon":3.2585784},{"type":"node","id":8497007481,"lat":51.1588349,"lon":3.2633671},{"type":"node","id":8497007549,"lat":51.1548977,"lon":3.257909},{"type":"node","id":8768981519,"lat":51.1545715,"lon":3.2585859},{"type":"node","id":8768981520,"lat":51.1544691,"lon":3.2584642},{"type":"node","id":8768981521,"lat":51.1543652,"lon":3.2584253},{"type":"node","id":8768981522,"lat":51.1543648,"lon":3.2583401},{"type":"node","id":8768981523,"lat":51.1544439,"lon":3.2585178},{"type":"node","id":8768981524,"lat":51.1543892,"lon":3.258369},{"type":"node","id":8768981525,"lat":51.1547185,"lon":3.2575482},{"type":"node","id":8768981533,"lat":51.1545902,"lon":3.2585725},{"type":"node","id":3162627482,"lat":51.1513402,"lon":3.2701364},{"type":"node","id":3162627509,"lat":51.1517878,"lon":3.2696503},{"type":"node","id":5745963944,"lat":51.1524768,"lon":3.2700312},{"type":"node","id":5745963946,"lat":51.1519527,"lon":3.2698278},{"type":"node","id":5745963947,"lat":51.1513495,"lon":3.2697903},{"type":"node","id":5747937657,"lat":51.1538472,"lon":3.269262},{"type":"node","id":5747937658,"lat":51.1536592,"lon":3.2698471},{"type":"node","id":5747937668,"lat":51.1514068,"lon":3.2699149},{"type":"node","id":5747937669,"lat":51.1514278,"lon":3.26999},{"type":"node","id":5747937670,"lat":51.1514329,"lon":3.2701134},{"type":"node","id":5747937671,"lat":51.1514387,"lon":3.2702207},{"type":"node","id":5747937672,"lat":51.1515532,"lon":3.2702006},{"type":"node","id":5747937673,"lat":51.1515986,"lon":3.2701456},{"type":"node","id":5747937674,"lat":51.151872,"lon":3.2701201},{"type":"node","id":6142725039,"lat":51.1513841,"lon":3.2701799},{"type":"node","id":6142725060,"lat":51.1499168,"lon":3.2700268},{"type":"node","id":6142725061,"lat":51.1497438,"lon":3.2697269},{"type":"node","id":6142725064,"lat":51.1499256,"lon":3.2692437},{"type":"node","id":6142727594,"lat":51.1500369,"lon":3.2694178},{"type":"node","id":6142727597,"lat":51.1513713,"lon":3.2701053},{"type":"node","id":6143075014,"lat":51.1512852,"lon":3.2702041},{"type":"node","id":1554514655,"lat":51.1533288,"lon":3.2766885},{"type":"node","id":1554514811,"lat":51.1537898,"lon":3.2754789},{"type":"node","id":3211247019,"lat":51.1538788,"lon":3.2763248},{"type":"node","id":3211247021,"lat":51.1538471,"lon":3.2764673},{"type":"node","id":5745963922,"lat":51.1499683,"lon":3.2708447},{"type":"node","id":5745963942,"lat":51.1530892,"lon":3.2704581},{"type":"node","id":5745963943,"lat":51.1529125,"lon":3.2703349},{"type":"node","id":5747535101,"lat":51.1533021,"lon":3.2705247},{"type":"node","id":5747937659,"lat":51.1534063,"lon":3.2705828},{"type":"node","id":5747937675,"lat":51.1521092,"lon":3.2702998},{"type":"node","id":5747937676,"lat":51.1524591,"lon":3.2704822},{"type":"node","id":5747937677,"lat":51.1527839,"lon":3.2706727},{"type":"node","id":5747937678,"lat":51.1529841,"lon":3.2707276},{"type":"node","id":5747937679,"lat":51.15326,"lon":3.2708913},{"type":"node","id":5747937680,"lat":51.1535477,"lon":3.2712989},{"type":"node","id":5747937681,"lat":51.1536831,"lon":3.2717402},{"type":"node","id":5747937682,"lat":51.1536839,"lon":3.2721747},{"type":"node","id":5747937683,"lat":51.1536469,"lon":3.2724161},{"type":"node","id":5747937684,"lat":51.1534635,"lon":3.2730652},{"type":"node","id":5747937685,"lat":51.1540625,"lon":3.2735735},{"type":"node","id":5962339921,"lat":51.1535454,"lon":3.2761201},{"type":"node","id":5962496725,"lat":51.1538672,"lon":3.276374},{"type":"node","id":6142725040,"lat":51.1514014,"lon":3.2704388},{"type":"node","id":6142725041,"lat":51.1514255,"lon":3.2722713},{"type":"node","id":6142725042,"lat":51.1514044,"lon":3.2722821},{"type":"node","id":6142725043,"lat":51.1513617,"lon":3.2722639},{"type":"node","id":6142725044,"lat":51.1513141,"lon":3.2722165},{"type":"node","id":6142725045,"lat":51.1512346,"lon":3.2721372},{"type":"node","id":6142725046,"lat":51.1511314,"lon":3.2720304},{"type":"node","id":6142725047,"lat":51.1509926,"lon":3.2718816},{"type":"node","id":6142725048,"lat":51.1508222,"lon":3.2716946},{"type":"node","id":6142725049,"lat":51.1507329,"lon":3.2715909},{"type":"node","id":6142725050,"lat":51.1506561,"lon":3.2714915},{"type":"node","id":6142725051,"lat":51.1506027,"lon":3.2714102},{"type":"node","id":6142725052,"lat":51.1505293,"lon":3.2712712},{"type":"node","id":6142725053,"lat":51.1504912,"lon":3.2711826},{"type":"node","id":6142725054,"lat":51.1504464,"lon":3.2710615},{"type":"node","id":6142725055,"lat":51.1503588,"lon":3.2707712},{"type":"node","id":6142725056,"lat":51.1503432,"lon":3.2707336},{"type":"node","id":6142725057,"lat":51.1503035,"lon":3.2706647},{"type":"node","id":6142725058,"lat":51.1501763,"lon":3.2704663},{"type":"node","id":6142725059,"lat":51.1500465,"lon":3.270256},{"type":"node","id":6142725065,"lat":51.1511856,"lon":3.2703268},{"type":"node","id":6142725066,"lat":51.1510244,"lon":3.2705705},{"type":"node","id":6142725067,"lat":51.1509355,"lon":3.270823},{"type":"node","id":6142725074,"lat":51.149723,"lon":3.271666},{"type":"node","id":6142725076,"lat":51.1498322,"lon":3.2716555},{"type":"node","id":6142725077,"lat":51.1499403,"lon":3.2715209},{"type":"node","id":6142725078,"lat":51.1500262,"lon":3.2714548},{"type":"node","id":6142725079,"lat":51.1501462,"lon":3.2714359},{"type":"node","id":6142725080,"lat":51.1502306,"lon":3.2714572},{"type":"node","id":6142725081,"lat":51.1502676,"lon":3.2714288},{"type":"node","id":6142725084,"lat":51.1496118,"lon":3.2714056},{"type":"node","id":6142727585,"lat":51.1497709,"lon":3.271258},{"type":"node","id":6142727586,"lat":51.1496767,"lon":3.2713056},{"type":"node","id":6142727587,"lat":51.1498468,"lon":3.2711798},{"type":"node","id":6142727588,"lat":51.1500514,"lon":3.2703954},{"type":"node","id":6142727589,"lat":51.1503033,"lon":3.270777},{"type":"node","id":6142727590,"lat":51.1503141,"lon":3.2713705},{"type":"node","id":6142727591,"lat":51.1498992,"lon":3.2710354},{"type":"node","id":6142727592,"lat":51.1499461,"lon":3.270906},{"type":"node","id":6142727595,"lat":51.1505973,"lon":3.2702942},{"type":"node","id":6142727596,"lat":51.1508515,"lon":3.2706917},{"type":"node","id":6142727598,"lat":51.1504337,"lon":3.2712326},{"type":"node","id":6143074993,"lat":51.1501845,"lon":3.2706959},{"type":"node","id":6143075018,"lat":51.1508744,"lon":3.2707275},{"type":"node","id":8638721230,"lat":51.151458,"lon":3.2721756},{"type":"node","id":8638721239,"lat":51.1514715,"lon":3.2719839},{"type":"node","id":1554514618,"lat":51.1581789,"lon":3.2646401},{"type":"node","id":1554514658,"lat":51.1578742,"lon":3.2653982},{"type":"node","id":1554514750,"lat":51.1568056,"lon":3.2677508},{"type":"node","id":1554514755,"lat":51.1573435,"lon":3.2665694},{"type":"node","id":1554514831,"lat":51.1561729,"lon":3.2691965},{"type":"node","id":3211247042,"lat":51.1557516,"lon":3.2701591},{"type":"node","id":3211247054,"lat":51.1570321,"lon":3.2690614},{"type":"node","id":3211247058,"lat":51.1571866,"lon":3.2685962},{"type":"node","id":3211247059,"lat":51.1572111,"lon":3.2673633},{"type":"node","id":3211247060,"lat":51.1572915,"lon":3.2701354},{"type":"node","id":3211247261,"lat":51.157332,"lon":3.2685775},{"type":"node","id":3211247265,"lat":51.1575267,"lon":3.2694937},{"type":"node","id":3211247266,"lat":51.1576636,"lon":3.2677588},{"type":"node","id":3211247291,"lat":51.15873,"lon":3.2640973},{"type":"node","id":3211247328,"lat":51.1594831,"lon":3.2648765},{"type":"node","id":3211247331,"lat":51.1596428,"lon":3.2643669},{"type":"node","id":5747937641,"lat":51.1581621,"lon":3.2637783},{"type":"node","id":5747937643,"lat":51.1576288,"lon":3.2640519},{"type":"node","id":5747937644,"lat":51.1572672,"lon":3.2645347},{"type":"node","id":5747937645,"lat":51.1568533,"lon":3.2650349},{"type":"node","id":5747937646,"lat":51.1564933,"lon":3.2652213},{"type":"node","id":5747937647,"lat":51.1562275,"lon":3.2654708},{"type":"node","id":5747937648,"lat":51.1560046,"lon":3.2656894},{"type":"node","id":5747937649,"lat":51.1556867,"lon":3.2659965},{"type":"node","id":5747937650,"lat":51.1551778,"lon":3.2664082},{"type":"node","id":5747937651,"lat":51.1550608,"lon":3.2664739},{"type":"node","id":5747937652,"lat":51.1547446,"lon":3.2666805},{"type":"node","id":5747937653,"lat":51.1546747,"lon":3.2667583},{"type":"node","id":5747937654,"lat":51.1546066,"lon":3.266895},{"type":"node","id":5747937655,"lat":51.1544363,"lon":3.2672456},{"type":"node","id":5747937656,"lat":51.1543612,"lon":3.2677126},{"type":"node","id":5747937688,"lat":51.1553145,"lon":3.2701637},{"type":"node","id":5747937689,"lat":51.1564724,"lon":3.2675566},{"type":"node","id":5747937690,"lat":51.1580352,"lon":3.2640939},{"type":"node","id":5747937691,"lat":51.1581075,"lon":3.2639222},{"type":"node","id":5962338038,"lat":51.1580663,"lon":3.2649607},{"type":"node","id":5962340009,"lat":51.1585904,"lon":3.2644244},{"type":"node","id":5962340010,"lat":51.1579212,"lon":3.2658517},{"type":"node","id":5962340011,"lat":51.1575197,"lon":3.2676156},{"type":"node","id":5962340012,"lat":51.1573374,"lon":3.2674543},{"type":"node","id":5962340013,"lat":51.1574265,"lon":3.2698457},{"type":"node","id":5962415543,"lat":51.1591427,"lon":3.2638615},{"type":"node","id":5962415564,"lat":51.1563757,"lon":3.269274},{"type":"node","id":5962444841,"lat":51.1584746,"lon":3.2639653},{"type":"node","id":5962444846,"lat":51.1585428,"lon":3.2645259},{"type":"node","id":5962444849,"lat":51.1586783,"lon":3.2642185},{"type":"node","id":5962444850,"lat":51.1586559,"lon":3.2642708},{"type":"node","id":5962496715,"lat":51.1577157,"lon":3.2657479},{"type":"node","id":5962496718,"lat":51.1572172,"lon":3.2685923},{"type":"node","id":5962496719,"lat":51.1571618,"lon":3.2686709},{"type":"node","id":1554514640,"lat":51.1556541,"lon":3.2703864},{"type":"node","id":1554514735,"lat":51.1546949,"lon":3.273022},{"type":"node","id":1554514739,"lat":51.1552715,"lon":3.271391},{"type":"node","id":1554514744,"lat":51.154165,"lon":3.2744194},{"type":"node","id":3211247024,"lat":51.1541505,"lon":3.2756042},{"type":"node","id":3211247029,"lat":51.154764,"lon":3.2739293},{"type":"node","id":3211247032,"lat":51.1550284,"lon":3.2731777},{"type":"node","id":3211247034,"lat":51.1553184,"lon":3.2723493},{"type":"node","id":3211247036,"lat":51.1554324,"lon":3.2715569},{"type":"node","id":3211247037,"lat":51.1555577,"lon":3.2717139},{"type":"node","id":3211247039,"lat":51.1556614,"lon":3.2709968},{"type":"node","id":5747937686,"lat":51.1543123,"lon":3.272868},{"type":"node","id":5747937687,"lat":51.1551484,"lon":3.2706069},{"type":"node","id":5962415565,"lat":51.1558985,"lon":3.2703959},{"type":"node","id":3170562436,"lat":51.138924,"lon":3.2898032},{"type":"node","id":7114502205,"lat":51.1385818,"lon":3.2899019},{"type":"node","id":7114502206,"lat":51.1387244,"lon":3.289738},{"type":"node","id":1475188516,"lat":51.1392568,"lon":3.2899836},{"type":"node","id":1475188519,"lat":51.1391868,"lon":3.2900136},{"type":"node","id":3170562392,"lat":51.1364433,"lon":3.2910119},{"type":"node","id":3170562394,"lat":51.1368907,"lon":3.291708},{"type":"node","id":3170562395,"lat":51.137106,"lon":3.2924864},{"type":"node","id":3170562396,"lat":51.137265,"lon":3.2919875},{"type":"node","id":3170562397,"lat":51.1374825,"lon":3.2913695},{"type":"node","id":3170562402,"lat":51.1378658,"lon":3.2906394},{"type":"node","id":3170562410,"lat":51.1378512,"lon":3.2905949},{"type":"node","id":3170562431,"lat":51.138431,"lon":3.2910415},{"type":"node","id":3170562437,"lat":51.1389596,"lon":3.2905649},{"type":"node","id":3170562439,"lat":51.1391839,"lon":3.2903042},{"type":"node","id":6627605025,"lat":51.1393014,"lon":3.2899729},{"type":"node","id":7114502200,"lat":51.139377,"lon":3.2901873},{"type":"node","id":7114502201,"lat":51.1395801,"lon":3.2901445},{"type":"node","id":7114502202,"lat":51.1393183,"lon":3.290151},{"type":"node","id":7114502203,"lat":51.1395636,"lon":3.2902055},{"type":"node","id":7114502207,"lat":51.13835,"lon":3.2901225},{"type":"node","id":7114502208,"lat":51.138259,"lon":3.2902362},{"type":"node","id":7114502209,"lat":51.1381351,"lon":3.2903372},{"type":"node","id":7114502211,"lat":51.1376987,"lon":3.2921954},{"type":"node","id":7114502212,"lat":51.1373598,"lon":3.2927952},{"type":"node","id":7114502214,"lat":51.1364782,"lon":3.2933157},{"type":"node","id":7114502215,"lat":51.1356558,"lon":3.2938122},{"type":"node","id":7114502216,"lat":51.1364577,"lon":3.2922382},{"type":"node","id":7114502217,"lat":51.1365055,"lon":3.2917901},{"type":"node","id":7114502218,"lat":51.1369977,"lon":3.2911659},{"type":"node","id":7114502219,"lat":51.1367691,"lon":3.2924051},{"type":"node","id":7114502220,"lat":51.1367022,"lon":3.2927526},{"type":"node","id":7114502221,"lat":51.1367354,"lon":3.2929091},{"type":"node","id":7114502222,"lat":51.1367962,"lon":3.2930156},{"type":"node","id":7114502223,"lat":51.1369436,"lon":3.2928838},{"type":"node","id":7114502224,"lat":51.1365124,"lon":3.2914123},{"type":"node","id":7114502225,"lat":51.135804,"lon":3.2926995},{"type":"node","id":7114502226,"lat":51.1354385,"lon":3.2929897},{"type":"node","id":7114502227,"lat":51.135128,"lon":3.2935318},{"type":"node","id":7114502228,"lat":51.1352851,"lon":3.2947114},{"type":"node","id":7114502230,"lat":51.135254,"lon":3.2946241},{"type":"node","id":7114502234,"lat":51.1354035,"lon":3.2959064},{"type":"node","id":7114502235,"lat":51.1362234,"lon":3.2955042},{"type":"node","id":7114502236,"lat":51.1362859,"lon":3.2964578},{"type":"node","id":7114502240,"lat":51.1379417,"lon":3.2917937},{"type":"node","id":8294886142,"lat":51.1394294,"lon":3.290127},{"type":"node","id":7114502233,"lat":51.1354361,"lon":3.2966386},{"type":"node","id":7114502237,"lat":51.1362025,"lon":3.2964851},{"type":"node","id":7114502238,"lat":51.1362303,"lon":3.2969415},{"type":"node","id":7114502239,"lat":51.1355032,"lon":3.297292},{"type":"node","id":1494027348,"lat":51.1419125,"lon":3.3028989},{"type":"node","id":1494027349,"lat":51.1419929,"lon":3.3024731},{"type":"node","id":1951759298,"lat":51.1421456,"lon":3.3024503},{"type":"node","id":6037556099,"lat":51.1420961,"lon":3.3023333},{"type":"node","id":6037556100,"lat":51.142124,"lon":3.302398},{"type":"node","id":6037556101,"lat":51.1421476,"lon":3.3023664},{"type":"node","id":6037556102,"lat":51.1421686,"lon":3.3023966},{"type":"node","id":6037556103,"lat":51.1421392,"lon":3.3024395},{"type":"node","id":6037556104,"lat":51.1419363,"lon":3.3027154},{"type":"node","id":6037556128,"lat":51.1421612,"lon":3.3024776},{"type":"node","id":6037556129,"lat":51.1421598,"lon":3.3025191},{"type":"node","id":1554514647,"lat":51.1510862,"lon":3.2830051},{"type":"node","id":1554514679,"lat":51.1528746,"lon":3.2778124},{"type":"node","id":1554514683,"lat":51.152459,"lon":3.2789175},{"type":"node","id":1554514730,"lat":51.1514294,"lon":3.2817821},{"type":"node","id":1554514747,"lat":51.1515758,"lon":3.2812966},{"type":"node","id":1554514765,"lat":51.1518248,"lon":3.2805268},{"type":"node","id":1554514773,"lat":51.15167,"lon":3.280964},{"type":"node","id":1554514775,"lat":51.1517205,"lon":3.2808218},{"type":"node","id":3211246555,"lat":51.1516922,"lon":3.2825734},{"type":"node","id":3211246995,"lat":51.1531241,"lon":3.2787307},{"type":"node","id":3211246997,"lat":51.1532256,"lon":3.2781298},{"type":"node","id":3211247004,"lat":51.1532551,"lon":3.2780324},{"type":"node","id":3211247008,"lat":51.1532769,"lon":3.2780262},{"type":"node","id":3211247010,"lat":51.1533547,"lon":3.2780182},{"type":"node","id":3211247013,"lat":51.1534072,"lon":3.2778679},{"type":"node","id":5962338069,"lat":51.1531224,"lon":3.2785269},{"type":"node","id":5962338070,"lat":51.1532454,"lon":3.2781435},{"type":"node","id":5962338071,"lat":51.1531839,"lon":3.2785716},{"type":"node","id":9284562682,"lat":51.153154,"lon":3.2784189},{"type":"node","id":1554514649,"lat":51.1502146,"lon":3.285505},{"type":"node","id":1554514661,"lat":51.1499067,"lon":3.2861781},{"type":"node","id":1554514682,"lat":51.150038,"lon":3.2859179},{"type":"node","id":1554514693,"lat":51.1498077,"lon":3.2862946},{"type":"node","id":1554514703,"lat":51.1497368,"lon":3.2863685},{"type":"node","id":1554514726,"lat":51.1498748,"lon":3.2862129},{"type":"node","id":1554514783,"lat":51.1497118,"lon":3.2864368},{"type":"node","id":1554514787,"lat":51.1499524,"lon":3.2860908},{"type":"node","id":1554514789,"lat":51.1506254,"lon":3.2845029},{"type":"node","id":3203029856,"lat":51.1498994,"lon":3.2867119},{"type":"node","id":3211246542,"lat":51.1505988,"lon":3.2851597},{"type":"node","id":5482441357,"lat":51.1504615,"lon":3.2836968},{"type":"node","id":7459154782,"lat":51.1501541,"lon":3.2834044},{"type":"node","id":7459154784,"lat":51.14999,"lon":3.2838049},{"type":"node","id":7459257985,"lat":51.1496077,"lon":3.2846412},{"type":"node","id":7602479690,"lat":51.150018,"lon":3.2848987},{"type":"node","id":7602479691,"lat":51.149806,"lon":3.2842251},{"type":"node","id":7602479692,"lat":51.1504686,"lon":3.2836785},{"type":"node","id":7602479693,"lat":51.1504309,"lon":3.2838118},{"type":"node","id":7602479694,"lat":51.1504255,"lon":3.2838072},{"type":"node","id":7602479695,"lat":51.1503423,"lon":3.2840392},{"type":"node","id":7602479696,"lat":51.1501698,"lon":3.2845196},{"type":"node","id":7727406921,"lat":51.1497539,"lon":3.2864986},{"type":"node","id":8945026754,"lat":51.1518736,"lon":3.2973911},{"type":"node","id":8945026755,"lat":51.1521646,"lon":3.297599},{"type":"node","id":8945026756,"lat":51.1522042,"lon":3.2974333},{"type":"node","id":8945026757,"lat":51.1519287,"lon":3.2972449},{"type":"node","id":416917612,"lat":51.1610842,"lon":3.2579973},{"type":"node","id":1948836192,"lat":51.1607104,"lon":3.2576119},{"type":"node","id":1948836193,"lat":51.1607138,"lon":3.2577265},{"type":"node","id":1948836194,"lat":51.1607261,"lon":3.2576817},{"type":"node","id":1948836195,"lat":51.1607396,"lon":3.2576322},{"type":"node","id":1948836202,"lat":51.1608376,"lon":3.2582648},{"type":"node","id":1948836209,"lat":51.1608764,"lon":3.2583297},{"type":"node","id":1948836218,"lat":51.1609914,"lon":3.2580679},{"type":"node","id":1948836237,"lat":51.1610295,"lon":3.2581432},{"type":"node","id":1948836277,"lat":51.1610699,"lon":3.2580833},{"type":"node","id":5349884600,"lat":51.1623355,"lon":3.2627383},{"type":"node","id":5349884601,"lat":51.1621681,"lon":3.2630327},{"type":"node","id":5349884602,"lat":51.1622043,"lon":3.2630816},{"type":"node","id":5349884603,"lat":51.162375,"lon":3.2627913},{"type":"node","id":5349884604,"lat":51.1622594,"lon":3.2633478},{"type":"node","id":5349884605,"lat":51.1621955,"lon":3.2632528},{"type":"node","id":5349884606,"lat":51.1623824,"lon":3.2629335},{"type":"node","id":5349884607,"lat":51.1624462,"lon":3.2630285},{"type":"node","id":5745739924,"lat":51.1608677,"lon":3.2604028},{"type":"node","id":5745739925,"lat":51.160749,"lon":3.2605301},{"type":"node","id":5745739927,"lat":51.160719,"lon":3.2600865},{"type":"node","id":1494027341,"lat":51.1418334,"lon":3.3035292},{"type":"node","id":1494027359,"lat":51.1413757,"lon":3.3074828},{"type":"node","id":1494027374,"lat":51.14132,"lon":3.3086261},{"type":"node","id":1494027376,"lat":51.1415625,"lon":3.3055864},{"type":"node","id":1494027385,"lat":51.1414514,"lon":3.3065628},{"type":"node","id":1494027386,"lat":51.1416927,"lon":3.3044972},{"type":"node","id":1494027389,"lat":51.1412677,"lon":3.3093509},{"type":"node","id":6037556130,"lat":51.1420599,"lon":3.303249},{"type":"node","id":6037556131,"lat":51.1419859,"lon":3.3038109},{"type":"node","id":6037556132,"lat":51.1418857,"lon":3.3046747},{"type":"node","id":6037556133,"lat":51.1418916,"lon":3.3050562},{"type":"node","id":6037556134,"lat":51.141927,"lon":3.3054665},{"type":"node","id":6037556135,"lat":51.1419362,"lon":3.3056543},{"type":"node","id":6037556136,"lat":51.1419369,"lon":3.3060001},{"type":"node","id":6037556137,"lat":51.1419328,"lon":3.3061768},{"type":"node","id":6037556138,"lat":51.1419139,"lon":3.3062337},{"type":"node","id":6037556139,"lat":51.1419032,"lon":3.3062932},{"type":"node","id":6037556140,"lat":51.1419001,"lon":3.3065944},{"type":"node","id":6037556141,"lat":51.1419262,"lon":3.3066872},{"type":"node","id":6037556142,"lat":51.1419119,"lon":3.3074563},{"type":"node","id":6037556143,"lat":51.1419027,"lon":3.3079359},{"type":"node","id":6037556144,"lat":51.1418924,"lon":3.3090764},{"type":"node","id":6037556145,"lat":51.1418843,"lon":3.3094015},{"type":"node","id":1494027342,"lat":51.1411958,"lon":3.3123073},{"type":"node","id":1494027346,"lat":51.1411509,"lon":3.3144776},{"type":"node","id":1494027353,"lat":51.141193,"lon":3.3127209},{"type":"node","id":1494027361,"lat":51.1411944,"lon":3.3118627},{"type":"node","id":1494027366,"lat":51.1411788,"lon":3.3132011},{"type":"node","id":1494027368,"lat":51.1411457,"lon":3.3148322},{"type":"node","id":1494027372,"lat":51.1412147,"lon":3.3112199},{"type":"node","id":1494027373,"lat":51.1411641,"lon":3.3142758},{"type":"node","id":1494027378,"lat":51.1412256,"lon":3.3114828},{"type":"node","id":1494027382,"lat":51.1412174,"lon":3.3105548},{"type":"node","id":6037556098,"lat":51.1411339,"lon":3.315984},{"type":"node","id":6037556146,"lat":51.1418276,"lon":3.309789},{"type":"node","id":6037556148,"lat":51.1418583,"lon":3.3096011},{"type":"node","id":6037556149,"lat":51.1418039,"lon":3.3098357},{"type":"node","id":6037556150,"lat":51.1417743,"lon":3.3098805},{"type":"node","id":6037556151,"lat":51.1416977,"lon":3.3101207},{"type":"node","id":6037556152,"lat":51.1416834,"lon":3.3102232},{"type":"node","id":6037556153,"lat":51.1416823,"lon":3.3102705},{"type":"node","id":6037556154,"lat":51.1416302,"lon":3.3105557},{"type":"node","id":6037556155,"lat":51.1416042,"lon":3.3107844},{"type":"node","id":6037556156,"lat":51.1415929,"lon":3.3110547},{"type":"node","id":6037556157,"lat":51.1415904,"lon":3.3118741},{"type":"node","id":6037556158,"lat":51.1415817,"lon":3.3145778},{"type":"node","id":6037556159,"lat":51.14157,"lon":3.3146421},{"type":"node","id":6037556160,"lat":51.1415557,"lon":3.3146975},{"type":"node","id":6037556161,"lat":51.1415541,"lon":3.3148416},{"type":"node","id":6037556162,"lat":51.1415551,"lon":3.3149739},{"type":"node","id":6037556163,"lat":51.1415802,"lon":3.3150635},{"type":"node","id":1494027343,"lat":51.1410607,"lon":3.3204128},{"type":"node","id":1494027365,"lat":51.141078,"lon":3.3193848},{"type":"node","id":1494027369,"lat":51.1410588,"lon":3.3212214},{"type":"node","id":1494027380,"lat":51.1410813,"lon":3.317924},{"type":"node","id":6037556105,"lat":51.141131,"lon":3.31628},{"type":"node","id":6037556106,"lat":51.1411581,"lon":3.3165005},{"type":"node","id":6037556107,"lat":51.141174,"lon":3.3167222},{"type":"node","id":6037556108,"lat":51.1411155,"lon":3.3169939},{"type":"node","id":6037556109,"lat":51.1410508,"lon":3.3221866},{"type":"node","id":6037556110,"lat":51.1410676,"lon":3.3223383},{"type":"node","id":6037556164,"lat":51.1415792,"lon":3.3164565},{"type":"node","id":6037556165,"lat":51.141573,"lon":3.3172357},{"type":"node","id":6037556166,"lat":51.1415771,"lon":3.3182023},{"type":"node","id":6037556167,"lat":51.1415495,"lon":3.3182625},{"type":"node","id":6037556168,"lat":51.1415495,"lon":3.3185605},{"type":"node","id":6037556169,"lat":51.1415684,"lon":3.3186069},{"type":"node","id":6037556170,"lat":51.1415633,"lon":3.3207654},{"type":"node","id":6037556171,"lat":51.1415444,"lon":3.3214131},{"type":"node","id":6037556172,"lat":51.1415097,"lon":3.3218544},{"type":"node","id":6037556173,"lat":51.1414642,"lon":3.3225703},{"type":"node","id":1493821404,"lat":51.1410663,"lon":3.3233361},{"type":"node","id":1494027355,"lat":51.1410465,"lon":3.3227899},{"type":"node","id":1801373604,"lat":51.1410713,"lon":3.3237592},{"type":"node","id":1951759314,"lat":51.1411466,"lon":3.3245554},{"type":"node","id":2474247506,"lat":51.1411643,"lon":3.3245589},{"type":"node","id":6037556111,"lat":51.1410551,"lon":3.3241916},{"type":"node","id":6037556112,"lat":51.1410504,"lon":3.3243751},{"type":"node","id":6037556118,"lat":51.1410331,"lon":3.3245183},{"type":"node","id":6037556120,"lat":51.1411823,"lon":3.3245635},{"type":"node","id":6037556174,"lat":51.1414121,"lon":3.3230419},{"type":"node","id":6037556175,"lat":51.1413953,"lon":3.3230745},{"type":"node","id":6037556176,"lat":51.1413682,"lon":3.323164},{"type":"node","id":6037556177,"lat":51.1413426,"lon":3.3233187},{"type":"node","id":6037556178,"lat":51.1413353,"lon":3.3234317},{"type":"node","id":6037556179,"lat":51.1413527,"lon":3.3235128},{"type":"node","id":6037556180,"lat":51.141294,"lon":3.3239374},{"type":"node","id":3702878648,"lat":51.1401344,"lon":3.3337214},{"type":"node","id":3702878654,"lat":51.1395918,"lon":3.3338166},{"type":"node","id":3702926557,"lat":51.1404241,"lon":3.333592},{"type":"node","id":3702926558,"lat":51.1406229,"lon":3.3335608},{"type":"node","id":3702926559,"lat":51.1406259,"lon":3.3336496},{"type":"node","id":3702926560,"lat":51.1404301,"lon":3.333676},{"type":"node","id":3702926561,"lat":51.1403789,"lon":3.3336784},{"type":"node","id":3702926562,"lat":51.1403729,"lon":3.3335752},{"type":"node","id":3702926563,"lat":51.1403021,"lon":3.333592},{"type":"node","id":3702926564,"lat":51.1402991,"lon":3.3335295},{"type":"node","id":3702926565,"lat":51.1402253,"lon":3.3335392},{"type":"node","id":3702926566,"lat":51.1402283,"lon":3.3336112},{"type":"node","id":3702926567,"lat":51.1401304,"lon":3.3336285},{"type":"node","id":3702926568,"lat":51.1400111,"lon":3.3337421},{"type":"node","id":3702956173,"lat":51.1406298,"lon":3.3321023},{"type":"node","id":3702956174,"lat":51.140115,"lon":3.3325162},{"type":"node","id":3702956175,"lat":51.1400702,"lon":3.3323734},{"type":"node","id":3702956176,"lat":51.1405896,"lon":3.3319784},{"type":"node","id":3702969714,"lat":51.1404452,"lon":3.3324432},{"type":"node","id":3702969715,"lat":51.1402175,"lon":3.3326312},{"type":"node","id":3702969716,"lat":51.1401965,"lon":3.3325686},{"type":"node","id":3702969717,"lat":51.1404269,"lon":3.3323835},{"type":"node","id":7713176909,"lat":51.1387744,"lon":3.3335489},{"type":"node","id":7713176910,"lat":51.1389364,"lon":3.3334306},{"type":"node","id":7713176911,"lat":51.1387319,"lon":3.3327211},{"type":"node","id":7713176912,"lat":51.1385501,"lon":3.332864},{"type":"node","id":8292789053,"lat":51.1400165,"lon":3.3338082},{"type":"node","id":8292789054,"lat":51.1396286,"lon":3.333874},{"type":"node","id":8378097124,"lat":51.140324,"lon":3.3355884},{"type":"node","id":8378097125,"lat":51.1403179,"lon":3.3355055},{"type":"node","id":8378097126,"lat":51.1406041,"lon":3.3354515},{"type":"node","id":8378097127,"lat":51.1406102,"lon":3.3355344},{"type":"node","id":8378097131,"lat":51.14074,"lon":3.3354785},{"type":"node","id":8378097132,"lat":51.1407879,"lon":3.3354717},{"type":"node","id":8378097133,"lat":51.1407993,"lon":3.3356206},{"type":"node","id":1317838317,"lat":51.1372361,"lon":3.338639},{"type":"node","id":1317838328,"lat":51.1369619,"lon":3.3386232},{"type":"node","id":1317838331,"lat":51.1371806,"lon":3.3384037},{"type":"node","id":1384096112,"lat":51.1371794,"lon":3.3384971},{"type":"node","id":1625199827,"lat":51.1408446,"lon":3.3375722},{"type":"node","id":1625199950,"lat":51.1407563,"lon":3.3373232},{"type":"node","id":3227068446,"lat":51.1369433,"lon":3.3387663},{"type":"node","id":3227068456,"lat":51.1371252,"lon":3.3388226},{"type":"node","id":3227068565,"lat":51.1371943,"lon":3.3389942},{"type":"node","id":3227068568,"lat":51.1372698,"lon":3.3389467},{"type":"node","id":6227395991,"lat":51.1392741,"lon":3.3367141},{"type":"node","id":6227395992,"lat":51.1392236,"lon":3.3367356},{"type":"node","id":6227395993,"lat":51.139313,"lon":3.3369193},{"type":"node","id":6227395997,"lat":51.1392584,"lon":3.3369405},{"type":"node","id":6414352053,"lat":51.1374056,"lon":3.3395184},{"type":"node","id":6414352054,"lat":51.1371278,"lon":3.3390236},{"type":"node","id":6414352055,"lat":51.1372589,"lon":3.3395769},{"type":"node","id":6414374315,"lat":51.1369166,"lon":3.338648},{"type":"node","id":6414374316,"lat":51.1369683,"lon":3.3388767},{"type":"node","id":6414374317,"lat":51.1370053,"lon":3.3388543},{"type":"node","id":6414374318,"lat":51.1371169,"lon":3.3387872},{"type":"node","id":6414374319,"lat":51.1371271,"lon":3.3388309},{"type":"node","id":6414374320,"lat":51.137238,"lon":3.3387628},{"type":"node","id":6414374321,"lat":51.1372074,"lon":3.338651},{"type":"node","id":6414383775,"lat":51.1407766,"lon":3.3373855},{"type":"node","id":6416001161,"lat":51.1371631,"lon":3.3390024},{"type":"node","id":7274233390,"lat":51.1372936,"lon":3.3395562},{"type":"node","id":7274233391,"lat":51.137309,"lon":3.3396231},{"type":"node","id":7274233395,"lat":51.1374325,"lon":3.3396124},{"type":"node","id":7274233396,"lat":51.137422,"lon":3.3395803},{"type":"node","id":7274233397,"lat":51.1373776,"lon":3.3396587},{"type":"node","id":8279842668,"lat":51.1371603,"lon":3.3384139},{"type":"node","id":8377691836,"lat":51.1409346,"lon":3.337164},{"type":"node","id":8378081366,"lat":51.140887,"lon":3.3372065},{"type":"node","id":8378081386,"lat":51.1407701,"lon":3.3373106},{"type":"node","id":8378081429,"lat":51.1408204,"lon":3.3372657},{"type":"node","id":8378097128,"lat":51.1407837,"lon":3.3359331},{"type":"node","id":8378097129,"lat":51.1407736,"lon":3.3358962},{"type":"node","id":8378097130,"lat":51.1407627,"lon":3.3358224},{"type":"node","id":8378097134,"lat":51.1408355,"lon":3.3359157},{"type":"node","id":1625199938,"lat":51.1411535,"lon":3.3372917},{"type":"node","id":1625199951,"lat":51.1410675,"lon":3.3370397},{"type":"node","id":6100803125,"lat":51.1672329,"lon":3.3331872},{"type":"node","id":6100803128,"lat":51.1672258,"lon":3.3333568},{"type":"node","id":2577910530,"lat":51.1685713,"lon":3.3356917},{"type":"node","id":2577910542,"lat":51.1681925,"lon":3.3356582},{"type":"node","id":2577910543,"lat":51.1685972,"lon":3.3356499},{"type":"node","id":3645188881,"lat":51.1679055,"lon":3.3337545},{"type":"node","id":6100803124,"lat":51.1673065,"lon":3.3331116},{"type":"node","id":6100803126,"lat":51.1672788,"lon":3.3336938},{"type":"node","id":6100803127,"lat":51.1672758,"lon":3.3333629},{"type":"node","id":6100803129,"lat":51.1675567,"lon":3.3331312},{"type":"node","id":6100803130,"lat":51.1675525,"lon":3.3333096},{"type":"node","id":6100803131,"lat":51.1679171,"lon":3.3333454},{"type":"node","id":2577910520,"lat":51.1681983,"lon":3.3360484},{"type":"node","id":2577910526,"lat":51.1687824,"lon":3.3362878},{"type":"node","id":2577910545,"lat":51.16885,"lon":3.3360431},{"type":"node","id":6145151107,"lat":51.1694008,"lon":3.3386946},{"type":"node","id":6145151108,"lat":51.1688319,"lon":3.3385737},{"type":"node","id":6145151109,"lat":51.1688258,"lon":3.3386467},{"type":"node","id":6145151110,"lat":51.1693942,"lon":3.3387681},{"type":"node","id":6145151114,"lat":51.1691188,"lon":3.3387104},{"type":"node","id":6145151115,"lat":51.1688569,"lon":3.3386537},{"type":"node","id":6418533335,"lat":51.1685948,"lon":3.3361624},{"type":"node","id":3190107371,"lat":51.1741471,"lon":3.3384365},{"type":"node","id":3190107374,"lat":51.1741746,"lon":3.3388275},{"type":"node","id":3190107377,"lat":51.1741968,"lon":3.3384276},{"type":"node","id":3190107393,"lat":51.1743618,"lon":3.3383982},{"type":"node","id":3190107400,"lat":51.1744043,"lon":3.3384036},{"type":"node","id":3190107407,"lat":51.1744809,"lon":3.3386827},{"type":"node","id":3190107408,"lat":51.1744875,"lon":3.3387716},{"type":"node","id":3190107415,"lat":51.1746495,"lon":3.3386505},{"type":"node","id":3190107416,"lat":51.1746548,"lon":3.3387211},{"type":"node","id":3190107420,"lat":51.1747424,"lon":3.3387044},{"type":"node","id":3190107423,"lat":51.1747681,"lon":3.3390477},{"type":"node","id":3190107424,"lat":51.1747706,"lon":3.3384763},{"type":"node","id":3190107428,"lat":51.1747993,"lon":3.3384858},{"type":"node","id":3190107432,"lat":51.1748198,"lon":3.3387594},{"type":"node","id":3190107435,"lat":51.1750772,"lon":3.3389888},{"type":"node","id":3190107439,"lat":51.1752356,"lon":3.3387751},{"type":"node","id":3190107442,"lat":51.1752492,"lon":3.338956},{"type":"node","id":7390697534,"lat":51.1297479,"lon":3.3578326},{"type":"node","id":7390697550,"lat":51.1297706,"lon":3.3588263},{"type":"node","id":7468171405,"lat":51.1279967,"lon":3.3559306},{"type":"node","id":7468171406,"lat":51.1288847,"lon":3.3598888},{"type":"node","id":7468171407,"lat":51.1288383,"lon":3.3606949},{"type":"node","id":7468171408,"lat":51.128796,"lon":3.3619912},{"type":"node","id":7468171422,"lat":51.1285744,"lon":3.3574498},{"type":"node","id":7468171423,"lat":51.1288319,"lon":3.3586353},{"type":"node","id":7468171426,"lat":51.1287158,"lon":3.3579031},{"type":"node","id":7468171428,"lat":51.1288787,"lon":3.3588438},{"type":"node","id":7468171429,"lat":51.1288942,"lon":3.3595607},{"type":"node","id":7468171431,"lat":51.1288954,"lon":3.3592459},{"type":"node","id":7468171433,"lat":51.1287831,"lon":3.3582062},{"type":"node","id":7468171444,"lat":51.1287924,"lon":3.361646},{"type":"node","id":7727393197,"lat":51.1288566,"lon":3.3555067},{"type":"node","id":7727393198,"lat":51.1292196,"lon":3.356551},{"type":"node","id":7727393199,"lat":51.129399,"lon":3.3566378},{"type":"node","id":7190873584,"lat":51.1287267,"lon":3.3682604},{"type":"node","id":7190927785,"lat":51.1287057,"lon":3.3681343},{"type":"node","id":7190927786,"lat":51.1287121,"lon":3.3673045},{"type":"node","id":7190927787,"lat":51.1286419,"lon":3.3641562},{"type":"node","id":7190927788,"lat":51.1286407,"lon":3.3644331},{"type":"node","id":7190927789,"lat":51.128655,"lon":3.3650286},{"type":"node","id":7190927790,"lat":51.128688,"lon":3.3661227},{"type":"node","id":7190927791,"lat":51.1286681,"lon":3.3635132},{"type":"node","id":7190927792,"lat":51.1286863,"lon":3.3631709},{"type":"node","id":7190927793,"lat":51.1286419,"lon":3.3639077},{"type":"node","id":7468171409,"lat":51.1288502,"lon":3.3621534},{"type":"node","id":7468171410,"lat":51.1288454,"lon":3.3623212},{"type":"node","id":7468171411,"lat":51.1287924,"lon":3.36282},{"type":"node","id":7468171412,"lat":51.1287335,"lon":3.363023},{"type":"node","id":7468171413,"lat":51.1286942,"lon":3.363003},{"type":"node","id":7602692242,"lat":51.1287128,"lon":3.3675239},{"type":"node","id":7727393200,"lat":51.129492,"lon":3.3624712},{"type":"node","id":7727393201,"lat":51.1294385,"lon":3.3629631},{"type":"node","id":7727393202,"lat":51.1293629,"lon":3.3638402},{"type":"node","id":7727393203,"lat":51.1293586,"lon":3.3662748},{"type":"node","id":7727393204,"lat":51.1292824,"lon":3.3662748},{"type":"node","id":7727393205,"lat":51.1292881,"lon":3.3667997},{"type":"node","id":7727393206,"lat":51.1293315,"lon":3.3682391},{"type":"node","id":7190873576,"lat":51.1287907,"lon":3.36923},{"type":"node","id":7190873577,"lat":51.1289144,"lon":3.369348},{"type":"node","id":7190873578,"lat":51.1288472,"lon":3.3692931},{"type":"node","id":7190873582,"lat":51.1287752,"lon":3.3691898},{"type":"node","id":7468171450,"lat":51.1287442,"lon":3.3685677},{"type":"node","id":7468171451,"lat":51.1290764,"lon":3.3693851},{"type":"node","id":7468171455,"lat":51.1289835,"lon":3.3693823},{"type":"node","id":7727393207,"lat":51.1293768,"lon":3.368773},{"type":"node","id":7727393208,"lat":51.1293116,"lon":3.3692219},{"type":"node","id":7727393209,"lat":51.1293718,"lon":3.368916},{"type":"node","id":7727393210,"lat":51.1292845,"lon":3.3692843},{"type":"node","id":7727393211,"lat":51.1292517,"lon":3.3693264},{"type":"node","id":7727393212,"lat":51.1291932,"lon":3.3693491},{"type":"node","id":8781449489,"lat":51.1293725,"lon":3.3688971},{"type":"way","id":640979978,"nodes":[6037556099,6037556100,6037556101,6037556102,6037556103,1951759298,6037556128,6037556129,6037556130,6037556131,6037556132,6037556133,6037556134,6037556135,6037556136,6037556137,6037556138,6037556139,6037556140,6037556141,6037556142,6037556143,6037556144,6037556145,6037556148,6037556146,6037556149,6037556150,6037556151,6037556152,6037556153,6037556154,6037556155,6037556156,6037556157,6037556158,6037556159,6037556160,6037556161,6037556162,6037556163,6037556164,6037556165,6037556166,6037556167,6037556168,6037556169,6037556170,6037556171,6037556172,6037556173,6037556174,6037556175,6037556176,6037556177,6037556178,6037556179,6037556180,6037556120,2474247506,1951759314,6037556118]},{"type":"way","id":640979982,"nodes":[6037556099,1494027349,6037556104,1494027348,1494027341,1494027386,1494027376,1494027385,1494027359,1494027374,1494027389,1494027382,1494027372,1494027378,1494027361,1494027342,1494027353,1494027366,1494027373,1494027346,1494027368,6037556098,6037556105,6037556106,6037556107,6037556108,1494027380,1494027365,1494027343,1494027369,6037556109,6037556110,1494027355,1493821404,1801373604,6037556111,6037556112,6037556118]},{"type":"way","id":184402325,"nodes":[1948835900,416917603,416917605,1948835986,416917609,1948836072,1948836068,1948836093,1948836104,1948836209,1948836202,1948836218,1948836237,1948836277,416917612,1948836149,1948836096,1948835950]},{"type":"way","id":184402326,"nodes":[1948835900,1948835842,1948835662]},{"type":"way","id":314899865,"nodes":[2026541851,2026541846,2026541843,2026541841,2026541837,3209560116,3210389695,3209560114,3209560115,3209560117,3209560118,3209560119,3209560121,3209560124,3209560126,3209560127,3209560131,3209560132,3209560134,3209560135,3209560136,3209560138]},{"type":"way","id":315041273,"nodes":[1554514739,1554514640,3211247042,1554514831,1554514750,1554514755,5962496715,1554514658,5962338038,1554514618,5962444841,1554514806,5962340003,8497007481,5962414276,5962415500,5962415499,5962415498,5962415538,5962415543,3211247331,3211247328,3211247291,5962444849,5962444850,5962340009,5962444846,5962340010,3211247059,5962340012,5962340011,3211247266,3211247261,5962496718,3211247058,5962496719,3211247054,3211247265,5962340013,3211247060,5962415564,5962415565]},{"type":"way","id":606165130,"nodes":[5747937641,5747937642,5747937643,5747937644,5747937645,5747937646,5747937647,5747937648,5747937649,5747937650,5747937651,5747937652,5747937653,5747937654,5747937655,5747937656,5747937657,5747937658,5747937659,5747535101,5745963942,5745963943,5745963944,5745963946,3162627509,5745963947,5747937668,5747937669,5747937670,5747937671,5747937672,5747937673,5747937674,5747937675,5747937676,5747937677,5747937678,5747937679,5747937680,5747937681,5747937682,5747937683,5747937684,5747937685,5747937686,5747937687,5747937688,5747937689,5747937690,5747937691,5747937641]},{"type":"way","id":184402332,"nodes":[668981668,416917618,1815081998,668981667,1948835950]},{"type":"way","id":184402334,"nodes":[6206789688,1948835742,668981668]},{"type":"way","id":314956402,"nodes":[2026541851,3209560139,3209560138]},{"type":"way","id":663050030,"nodes":[1948835662,6206789688]},{"type":"way","id":631371232,"nodes":[3211247019,5962496725]},{"type":"way","id":631377344,"nodes":[5962496725,3211247021]},{"type":"way","id":655652321,"nodes":[6142727588,6143074993,6142727589,6142727598,6142727590,6142725081,6142725080,6142725079,6142725078,6142725077,6142725076,6142725074,6142725084,6142727586,6142727585,6142727587,6142727591,6142727592,5745963922,6142727588]},{"type":"way","id":631371231,"nodes":[3211247019,3211247024]},{"type":"way","id":631371234,"nodes":[3211247013,3211247021]},{"type":"way","id":631377343,"nodes":[1554514739,1554514735,1554514744,1554514811,5962339921,1554514655,1554514679,1554514683,1554514765,1554514775,1554514773,1554514747,1554514730,1554514647,1554514789,1554514649,1554514682,1554514787,1554514661,1554514726,1554514693,1554514703,1554514783]},{"type":"way","id":655652319,"nodes":[6142725039,6142725040,8638721239,8638721230,6142725041,6142725042,6142725043,6142725044,6142725045,6142725046,6142725047,6142725048,6142725049,6142725050,6142725051,6142725052,6142725053,6142725054,6142725055,6142725056,6142725057,6142725058,6142725059,6142725060,6142725061,6142725064,6142727594,6142727595,6142727596,6143075018,6142725067,6142725066,6142725065,6143075014,3162627482,6142727597,6142725039]},{"type":"way","id":315041261,"nodes":[3211247039,3211247036]},{"type":"way","id":315041263,"nodes":[3211247032,3211247029,3211247024]},{"type":"way","id":631371223,"nodes":[5962415565,3211247039]},{"type":"way","id":631371228,"nodes":[3211247034,3211247032]},{"type":"way","id":631377341,"nodes":[3211247036,3211247037,3211247034]},{"type":"way","id":631371236,"nodes":[3211247013,3211247010,3211247008,3211247004,3211246997,5962338070,9284562682,5962338069,5962338071,3211246995]},{"type":"way","id":631371237,"nodes":[3211246995,3211246555,3211246542,3203029856,7727406921,1554514783]}]} - ) - - - -} - - -describe("GenerateCache", () => { - - it("should generate a cached file for the Natuurpunt-theme", async () => { - if (existsSync("/tmp/np-cache")) { - ScriptUtils.readDirRecSync("/tmp/np-cache").forEach(p => unlinkSync(p)) - rmdirSync("/tmp/np-cache") - } - mkdirSync("/tmp/np-cache") - initDownloads( - "(nwr%5B%22amenity%22%3D%22toilets%22%5D%3Bnwr%5B%22amenity%22%3D%22parking%22%5D%3Bnwr%5B%22amenity%22%3D%22bench%22%5D%3Bnwr%5B%22id%22%3D%22location_track%22%5D%3Bnwr%5B%22id%22%3D%22gps%22%5D%3Bnwr%5B%22information%22%3D%22board%22%5D%3Bnwr%5B%22leisure%22%3D%22picnic_table%22%5D%3Bnwr%5B%22man_made%22%3D%22watermill%22%5D%3Bnwr%5B%22user%3Ahome%22%3D%22yes%22%5D%3Bnwr%5B%22user%3Alocation%22%3D%22yes%22%5D%3Bnwr%5B%22leisure%22%3D%22nature_reserve%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22boundary%22%3D%22protected_area%22%5D%5B%22protect_class%22!~%22%5E98%24%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22information%22%3D%22visitor_centre%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22information%22%3D%22office%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22route%22~%22%5E.*foot.*%24%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22route%22~%22%5E.*hiking.*%24%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22route%22~%22%5E.*bycicle.*%24%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22route%22~%22%5E.*horse.*%24%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22leisure%22%3D%22bird_hide%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22amenity%22%3D%22drinking_water%22%5D%5B%22access%22!~%22%5Epermissive%24%22%5D%5B%22access%22!~%22%5Eprivate%24%22%5D%3B)%3Bout%20body%3Bout%20meta%3B%3E%3Bout%20skel%20qt%3B" - ); - await main([ - "natuurpunt", - "12", - "/tmp/np-cache", - "51.15423567022531", "3.250579833984375", "51.162821593316934", "3.262810707092285", - "--generate-point-overview", "nature_reserve,visitor_information_centre" - ]) - await ScriptUtils.sleep(100) - const birdhides = JSON.parse(readFileSync("/tmp/np-cache/natuurpunt_birdhide_12_2085_1368.geojson", "UTF8")) - expect(birdhides.features.length).deep.equal(5) - expect(birdhides.features.some(f => f.properties.id === "node/5158056232"), "Didn't find birdhide node/5158056232 ").true - - }) -}) diff --git a/tslint.json b/tslint.json new file mode 100644 index 0000000000..0cd44d3838 --- /dev/null +++ b/tslint.json @@ -0,0 +1,72 @@ +{ + "rules": { + "class-name": false, + "comment-format": [ + true + ], + "curly": false, + "eofline": false, + "forin": false, + "indent": [ + true, + "spaces" + ], + "label-position": true, + "max-line-length": false, + "member-access": false, + "member-ordering": [ + true, + "static-after-instance", + "variables-before-functions" + ], + "no-arg": true, + "no-bitwise": false, + "no-console": false, + "no-construct": true, + "no-debugger": true, + "no-duplicate-variable": true, + "no-empty": false, + "no-eval": true, + "no-inferrable-types": true, + "no-shadowed-variable": true, + "no-string-literal": false, + "no-switch-case-fall-through": true, + "no-trailing-whitespace": true, + "no-unused-expression": true, + "no-use-before-declare": false, + "no-var-keyword": true, + "object-literal-sort-keys": false, + "one-line": [ + true, + "check-open-brace", + "check-catch", + "check-else", + "check-whitespace" + ], + "quotemark": false, + "radix": true, + "semicolon": [ + "always" + ], + "triple-equals": [], + "typedef-whitespace": [ + true, + { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + } + ], + "variable-name": false, + "whitespace": [ + true, + "check-branch", + "check-decl", + "check-operator", + "check-separator", + "check-type" + ] + } +}