Merge branch 'master' into develop

This commit is contained in:
Pieter Vander Vennet 2024-03-04 15:36:34 +01:00
commit 5215662a0c
67 changed files with 1571 additions and 1276 deletions

View file

@ -1,4 +1,28 @@
{
"id": "aerialway",
"name": {
"en": "Aerialways",
"de": "Seilbahnen"
},
"description": {
"en": "Various forms of transport for passengers and goods that use wires, including cable cars, gondolas, chair lifts, drag lifts, and zip lines. ",
"de": "Alle Arten von seil- oder drahtgestütztem Personen- oder Gütertransport, wie Seilbahnen, Gondeln, Sessellifte, Schlepplifte. "
},
"source": {
"osmTags": {
"and": [
"aerialway~*",
"aerialway!=pylon",
"aerialway!=station"
]
}
},
"title": {
"render": {
"en": "Aerialway {name}",
"de": "Seilbahn {name}"
}
},
"pointRendering": [
{
"location": [
@ -27,6 +51,27 @@
"labelCssClasses": "bg-white px-2 py-1 no-weblate"
}
],
"lineRendering": [
{
"width": "4",
"color": "black",
"imageAlongWay": [
{
"if": "oneway=no",
"then": "./assets/png/twoway.png"
},
{
"if": {
"or": [
"oneway=yes",
"oneway="
]
},
"then": "./assets/png/oneway.png"
}
]
}
],
"tagRenderings": [
"images",
{
@ -183,50 +228,5 @@
"de": "Die Seilbahn hat eine Länge von {_length:km} km"
}
}
],
"lineRendering": [
{
"width": "4",
"color": "black",
"imageAlongWay": [
{
"if": "oneway=no",
"then": "./assets/png/twoway.png"
},
{
"if": {
"or": [
"oneway=yes",
"oneway="
]
},
"then": "./assets/png/oneway.png"
}
]
}
],
"id": "aerialway",
"name": {
"en": "Aerialways",
"de": "Seilbahnen"
},
"description": {
"en": "Various forms of transport for passengers and goods that use wires, including cable cars, gondolas, chair lifts, drag lifts, and zip lines. ",
"de": "Alle Arten von seil- oder drahtgestütztem Personen- oder Gütertransport, wie Seilbahnen, Gondeln, Sessellifte, Schlepplifte. "
},
"source": {
"osmTags": {
"and": [
"aerialway~*",
"aerialway!=pylon",
"aerialway!=station"
]
}
},
"title": {
"render": {
"en": "Aerialway {name}",
"de": "Seilbahn {name}"
}
}
]
}

View file

@ -1,8 +1,5 @@
{
"allowMove": {
"enableRelocation": false,
"enableImproveAccuracy": true
},
"id": "assembly_point",
"name": {
"en": "Emergency assembly points",
"it": "Punti di raccolta per emergenze",
@ -13,9 +10,6 @@
"it": "Questo livello contiene punti di raccolta e aree di attesa in cui tutti i dipendenti, i passeggeri o una grande folla si riuniscono in caso di emergenza.",
"de": "Diese Ebene enthält Sammelplätze und Wartebereiche, in denen sich alle Mitarbeiter, Fahrgäste oder eine große Menschenmenge im Notfall versammeln."
},
"docs": "https://wiki.openstreetmap.org/wiki/Tag:emergency%3Dassembly_point",
"id": "assembly_point",
"minzoom": 10,
"source": {
"osmTags": {
"and": [
@ -23,6 +17,13 @@
]
}
},
"minzoom": 10,
"title": {
"render": {
"en": "Assembly point during emergencies",
"de": "Sammelplatz bei Notfällen"
}
},
"pointRendering": [
{
"iconSize": "20,20",
@ -50,12 +51,6 @@
]
}
],
"title": {
"render": {
"en": "Assembly point during emergencies",
"de": "Sammelplatz bei Notfällen"
}
},
"tagRenderings": [
"images",
{
@ -154,5 +149,10 @@
}
]
}
]
],
"allowMove": {
"enableRelocation": false,
"enableImproveAccuracy": true
},
"docs": "https://wiki.openstreetmap.org/wiki/Tag:emergency%3Dassembly_point"
}

View file

@ -5,7 +5,12 @@
"nl": "Oplaadpunten",
"de": "Ladestationen"
},
"minzoom": 10,
"description": {
"en": "A charging station",
"nl": "Oplaadpunten",
"ca": "Una estació de càrrega",
"de": "Eine Ladestation"
},
"source": {
"osmTags": {
"and": [
@ -20,6 +25,7 @@
]
}
},
"minzoom": 10,
"title": {
"render": {
"en": "Charging station",
@ -65,13 +71,103 @@
}
]
},
"description": {
"en": "A charging station",
"nl": "Oplaadpunten",
"ca": "Una estació de càrrega",
"de": "Eine Ladestation"
},
"#": "no-question-hint-check",
"pointRendering": [
{
"location": [
"point",
"centroid"
],
"marker": [
{
"icon": "pin",
"color": "#fff"
},
{
"icon": {
"render": "./assets/themes/charging_stations/plug.svg",
"mappings": [
{
"if": "bicycle=yes",
"then": "./assets/themes/charging_stations/bicycle.svg"
},
{
"if": {
"or": [
"car=yes",
"motorcar=yes"
]
},
"then": "./assets/themes/charging_stations/car.svg"
}
]
}
}
],
"iconBadges": [
{
"if": {
"or": [
"disused:amenity=charging_station",
"operational_status=broken"
]
},
"then": "close:#c22;"
},
{
"if": {
"or": [
"proposed:amenity=charging_station",
"planned:amenity=charging_station"
]
},
"then": "./assets/layers/charging_station/under_construction.svg"
},
{
"if": {
"and": [
"bicycle=yes",
{
"or": [
"motorcar=yes",
"car=yes"
]
}
]
},
"then": "circle:#fff;./assets/themes/charging_stations/car.svg"
}
],
"anchor": "bottom",
"iconSize": "50,50"
}
],
"lineRendering": [],
"presets": [
{
"tags": [
"amenity=charging_station",
"motorcar=no",
"bicycle=yes"
],
"title": {
"en": "charging station for electrical bikes",
"nl": "oplaadpunt voor elektrische fietsen",
"de": "Ladestation für Elektrofahrräder"
}
},
{
"tags": [
"amenity=charging_station",
"motorcar=yes",
"bicycle=no"
],
"title": {
"en": "charging station for cars",
"nl": "oplaadstation voor elektrische auto's",
"de": "Ladestation für Elektrofahrräder"
}
}
],
"tagRenderings": [
"images",
{
@ -2316,103 +2412,6 @@
}
}
],
"lineRendering": [],
"pointRendering": [
{
"location": [
"point",
"centroid"
],
"marker": [
{
"icon": "pin",
"color": "#fff"
},
{
"icon": {
"render": "./assets/themes/charging_stations/plug.svg",
"mappings": [
{
"if": "bicycle=yes",
"then": "./assets/themes/charging_stations/bicycle.svg"
},
{
"if": {
"or": [
"car=yes",
"motorcar=yes"
]
},
"then": "./assets/themes/charging_stations/car.svg"
}
]
}
}
],
"iconBadges": [
{
"if": {
"or": [
"disused:amenity=charging_station",
"operational_status=broken"
]
},
"then": "close:#c22;"
},
{
"if": {
"or": [
"proposed:amenity=charging_station",
"planned:amenity=charging_station"
]
},
"then": "./assets/layers/charging_station/under_construction.svg"
},
{
"if": {
"and": [
"bicycle=yes",
{
"or": [
"motorcar=yes",
"car=yes"
]
}
]
},
"then": "circle:#fff;./assets/themes/charging_stations/car.svg"
}
],
"anchor": "bottom",
"iconSize": "50,50"
}
],
"presets": [
{
"tags": [
"amenity=charging_station",
"motorcar=no",
"bicycle=yes"
],
"title": {
"en": "charging station for electrical bikes",
"nl": "oplaadpunt voor elektrische fietsen",
"de": "Ladestation für Elektrofahrräder"
}
},
{
"tags": [
"amenity=charging_station",
"motorcar=yes",
"bicycle=no"
],
"title": {
"en": "charging station for cars",
"nl": "oplaadstation voor elektrische auto's",
"de": "Ladestation für Elektrofahrräder"
}
}
],
"filter": [
{
"id": "vehicle-type",
@ -2611,6 +2610,20 @@
]
}
],
"deletion": {
"softDeletionTags": {
"and": [
"amenity=",
"disused:amenity=charging_station"
]
},
"neededChangesets": 10
},
"allowMove": {
"enableRelocation": false,
"enableImproveAccuracy": true
},
"#": "no-question-hint-check",
"units": [
{
"maxstay": {
@ -2759,18 +2772,5 @@
]
}
}
],
"allowMove": {
"enableRelocation": false,
"enableImproveAccuracy": true
},
"deletion": {
"softDeletionTags": {
"and": [
"amenity=",
"disused:amenity=charging_station"
]
},
"neededChangesets": 10
}
}
]
}

View file

@ -35,7 +35,6 @@
}
},
"minzoom": 19,
"doCount": false,
"title": {
"render": {
"en": "Climbing opportunity?",
@ -148,5 +147,6 @@
}
]
}
]
],
"doCount": false
}

View file

@ -5,8 +5,7 @@
"source": {
"osmTags": "HUISNR~*",
"geoJson": "https://raw.githubusercontent.com/pietervdvn/MapComplete-data/main/CRAB_2021_10_26/tile_{z}_{x}_{y}.geojson",
"geoJsonZoomLevel": 18,
"maxCacheAge": 0
"geoJsonZoomLevel": 18
},
"calculatedTags": [
"_HNRLABEL=(() => {const lbl = feat.properties.HNRLABEL?.split('-')?.map(l => Number(l))?.filter(i => !isNaN (i)) ;if(lbl?.length != 2) {return feat.properties.HNRLABEL}; const addresses = []; for(let i = lbl[0]; i <= lbl[1]; i += 1){addresses.push(''+i);}; return addresses.join(';') })()"

View file

@ -1,12 +1,5 @@
{
"id": "disaster_response",
"title": {
"render": {
"en": "Disaster response organization",
"it": "Organizzazione per la risposta ai disastri",
"de": "Katastrophenschutzorganisation"
}
},
"name": {
"en": "Disaster response organizations",
"de": "Katastrophenschutzorganisationen"
@ -16,8 +9,36 @@
"it": "Questo livello contiene organizzazioni che hanno come obiettivo principale quello di aiutare la popolazione civile durante e dopo disastri naturali o antropogenici, lavorando nell'area colpita.",
"de": "Diese Ebene umfasst Organisationen, deren Hauptziel es ist, der Zivilbevölkerung während und nach Natur- oder anthropogenen Katastrophen zu helfen, indem sie in dem betroffenen Gebiet tätig sind."
},
"docs": "https://wiki.openstreetmap.org/wiki/Tag:emergency%3Ddisaster_response",
"source": {
"osmTags": {
"and": [
"emergency=disaster_response"
]
}
},
"minzoom": 10,
"title": {
"render": {
"en": "Disaster response organization",
"it": "Organizzazione per la risposta ai disastri",
"de": "Katastrophenschutzorganisation"
}
},
"pointRendering": [
{
"iconSize": "40,40",
"location": [
"point",
"centroid"
],
"anchor": "bottom",
"marker": [
{
"icon": "./assets/themes/disaster_response/CivilDefence.svg"
}
]
}
],
"lineRendering": [
{
"color": "#6BC4F7",
@ -36,28 +57,6 @@
]
}
],
"source": {
"osmTags": {
"and": [
"emergency=disaster_response"
]
}
},
"pointRendering": [
{
"iconSize": "40,40",
"location": [
"point",
"centroid"
],
"anchor": "bottom",
"marker": [
{
"icon": "./assets/themes/disaster_response/CivilDefence.svg"
}
]
}
],
"tagRenderings": [
"images",
"website",
@ -77,5 +76,6 @@
"de": "Diese Organisation heißt <b>{name}</b>"
}
}
]
],
"docs": "https://wiki.openstreetmap.org/wiki/Tag:emergency%3Ddisaster_response"
}

View file

@ -441,4 +441,4 @@
],
"deletion": true,
"allowMove": true
}
}

View file

@ -4,7 +4,6 @@
"en": "Ice cream parlors",
"de": "Eisdielen"
},
"minzoom": 14,
"description": {
"en": "A place where ice cream is sold over the counter",
"de": "Ein Ort, an dem Eiscreme an der Theke verkauft wird"
@ -12,6 +11,7 @@
"source": {
"osmTags": "amenity=ice_cream"
},
"minzoom": 14,
"title": {
"render": {
"en": "Ice cream parlor",

View file

@ -1,7 +1,9 @@
{
"id": "item_with_image",
"name": {
"en": "Items with at least one image"
},
"description": "All items with an image. All alone, not a layer which is relevant for any MapComplete theme, as it is a random collection of items. However, when put into the databank, this allows to quickly fetch (the URL of) pictures nearby a different object, to quickly link this",
"minzoom": 14,
"source": {
"osmTags": {
"or": [
@ -15,9 +17,7 @@
]
}
},
"tagRenderings": [
"images"
],
"minzoom": 14,
"title": {
"render": {
"en": "POI with image"
@ -31,10 +31,6 @@
}
]
},
"name": {
"en": "Items with at least one image"
},
"lineRendering": [],
"pointRendering": [
{
"marker": [
@ -47,5 +43,9 @@
"point"
]
}
],
"lineRendering": [],
"tagRenderings": [
"images"
]
}

View file

@ -10,8 +10,7 @@
},
"source": {
"osmTags": "mr_taskId~*",
"geoJson": "https://maproulette.org/api/v2/challenge/view/27971",
"isOsmCache": false
"geoJson": "https://maproulette.org/api/v2/challenge/view/27971"
},
"title": {
"render": {

View file

@ -1,6 +1,23 @@
{
"credits": "Not logged in",
"id": "mountain_rescue",
"name": {
"en": "Mountain rescue stations",
"de": "Bergrettungsstationen"
},
"description": {
"en": "A building where first aid responders store material and might be on watch",
"de": "Ein Gebäude, in dem die Ersthelfer Material lagern und möglicherweise Wache halten"
},
"source": {
"osmTags": "emergency=mountain_rescue"
},
"minzoom": 10,
"title": {
"render": {
"en": "Mountain rescue station",
"de": "Bergrettungsstation"
}
},
"pointRendering": [
{
"location": [
@ -19,37 +36,12 @@
"rotation": "45"
}
],
"tagRenderings": [
"images"
],
"lineRendering": [
{
"width": "3",
"color": "#ed333b"
}
],
"id": "mountain_rescue",
"name": {
"en": "Mountain rescue stations",
"de": "Bergrettungsstationen"
},
"description": {
"en": "A building where first aid responders store material and might be on watch",
"de": "Ein Gebäude, in dem die Ersthelfer Material lagern und möglicherweise Wache halten"
},
"source": {
"osmTags": "emergency=mountain_rescue"
},
"title": {
"render": {
"en": "Mountain rescue station",
"de": "Bergrettungsstation"
}
},
"deletion": true,
"allowMove": {
"enableRelocation": false
},
"presets": [
{
"title": {
@ -60,5 +52,13 @@
"emergency=mountain_rescue"
]
}
]
],
"tagRenderings": [
"images"
],
"deletion": true,
"allowMove": {
"enableRelocation": false
},
"credits": "Not logged in"
}

View file

@ -12,9 +12,7 @@
"source": {
"osmTags": "date_created~*",
"geoJson": "https://api.openstreetmap.org/api/0.6/notes.json?limit=10000&closed=7&bbox={x_min},{y_min},{x_max},{y_max}",
"geoJsonZoomLevel": 12,
"maxCacheAge": 0,
"isOsmCache": false
"geoJsonZoomLevel": 12
},
"calculatedTags": [
"_total_comments:=get(feat)('comments').length",

View file

@ -19,8 +19,7 @@
"source": {
"geoJson": "https://raw.githubusercontent.com/pietervdvn/MapComplete-data/main/community_index/tile_{z}_{x}_{y}.geojson",
"geoJsonZoomLevel": 6,
"osmTags": "resources~*",
"isOsmCache": false
"osmTags": "resources~*"
},
"calculatedTags": [
"_community_links=Object.values(JSON.parse(feat.properties.resources || '{}')).map(value =>{return value.resolved.nameHTML + '<br>&emsp;' + value.resolved.descriptionHTML}).join('<br>')"

View file

@ -1,5 +1,20 @@
{
"id": "playground_equipment",
"name": {
"en": "Playground equipment"
},
"description": {
"en": "Layer showing playground equipment"
},
"source": {
"osmTags": "playground~*"
},
"minzoom": 18,
"title": {
"render": {
"en": "Playground device"
}
},
"pointRendering": [
{
"location": [
@ -18,6 +33,25 @@
"iconSize": "20,20"
}
],
"lineRendering": [
{
"width": 1,
"color": "blue"
}
],
"presets": [
{
"tags": [
"playground=yes"
],
"title": {
"en": "a playground device"
},
"description": {
"en": "An exact type is asked later"
}
}
],
"tagRenderings": [
"images",
{
@ -299,39 +333,5 @@
}
}
],
"lineRendering": [
{
"width": 1,
"color": "blue"
}
],
"id": "playground_equipment",
"name": {
"en": "Playground equipment"
},
"description": {
"en": "Layer showing playground equipment"
},
"source": {
"osmTags": "playground~*"
},
"title": {
"render": {
"en": "Playground device"
}
},
"allowMove": true,
"presets": [
{
"tags": [
"playground=yes"
],
"title": {
"en": "a playground device"
},
"description": {
"en": "An exact type is asked later"
}
}
]
}
"allowMove": true
}

View file

@ -634,4 +634,4 @@
]
}
]
}
}

View file

@ -1,4 +1,32 @@
{
"id": "ski_piste",
"name": {
"en": "Ski and snowboard pistes",
"de": "Ski- und Snowboardpisten"
},
"description": {
"en": "Ski and snowboard pistes",
"de": "Ski- und Snowboardpisten"
},
"source": {
"osmTags": {
"and": [
{
"or": [
"piste:type=downhill",
"piste:type=connection"
]
},
"area!=yes"
]
}
},
"title": {
"render": {
"en": "Ski piste {name}",
"de": "Skipiste {name}"
}
},
"pointRendering": [
{
"location": [
@ -12,6 +40,40 @@
]
}
],
"lineRendering": [
{
"width": "10",
"color": {
"mappings": [
{
"then": "green",
"if": "piste:difficulty=novice"
},
{
"if": "piste:difficulty=easy",
"then": "blue"
},
{
"if": "piste:difficulty=intermediate",
"then": "red"
},
{
"if": "piste:difficulty=advanced",
"then": "black"
},
{
"if": "piste:difficulty=expert",
"then": "orange"
},
{
"if": "piste:difficulty=",
"then": "gray"
}
]
},
"imageAlongWay": "./assets/png/oneway.png"
}
],
"tagRenderings": [
"images",
{
@ -73,67 +135,5 @@
"de": "Dieser Teil der Skipiste hat eine Länge von {_length:km} km"
}
}
],
"lineRendering": [
{
"width": "10",
"color": {
"mappings": [
{
"then": "green",
"if": "piste:difficulty=novice"
},
{
"if": "piste:difficulty=easy",
"then": "blue"
},
{
"if": "piste:difficulty=intermediate",
"then": "red"
},
{
"if": "piste:difficulty=advanced",
"then": "black"
},
{
"if": "piste:difficulty=expert",
"then": "orange"
},
{
"if": "piste:difficulty=",
"then": "gray"
}
]
},
"imageAlongWay": "./assets/png/oneway.png"
}
],
"id": "ski_piste",
"name": {
"en": "Ski and snowboard pistes",
"de": "Ski- und Snowboardpisten"
},
"description": {
"en": "Ski and snowboard pistes",
"de": "Ski- und Snowboardpisten"
},
"source": {
"osmTags": {
"and": [
{
"or": [
"piste:type=downhill",
"piste:type=connection"
]
},
"area!=yes"
]
}
},
"title": {
"render": {
"en": "Ski piste {name}",
"de": "Skipiste {name}"
}
}
]
}

View file

@ -1,4 +1,24 @@
{
"id": "souvenir_coin",
"name": {
"en": "Souvenir Coin Machines"
},
"description": {
"en": "Layer showing machines selling souvenir coins"
},
"source": {
"osmTags": {
"and": [
"amenity=vending_machine",
"vending~.*souvenir_coins.*"
]
}
},
"title": {
"render": {
"en": "Souvenir Coin Machine"
}
},
"pointRendering": [
{
"location": [
@ -22,6 +42,26 @@
]
}
],
"lineRendering": [
{
"width": 1,
"color": "blue"
}
],
"presets": [
{
"title": {
"en": "a souvenir coin machine"
},
"description": {
"en": "Add a machine selling souvenir coins"
},
"tags": [
"amenity=vending_machine",
"vending=souvenir_coins"
]
}
],
"tagRenderings": [
"images",
"opening_hours_24_7",
@ -110,46 +150,6 @@
"level",
"check_date"
],
"lineRendering": [
{
"width": 1,
"color": "blue"
}
],
"id": "souvenir_coin",
"name": {
"en": "Souvenir Coin Machines"
},
"description": {
"en": "Layer showing machines selling souvenir coins"
},
"source": {
"osmTags": {
"and": [
"amenity=vending_machine",
"vending~.*souvenir_coins.*"
]
}
},
"title": {
"render": {
"en": "Souvenir Coin Machine"
}
},
"presets": [
{
"title": {
"en": "a souvenir coin machine"
},
"description": {
"en": "Add a machine selling souvenir coins"
},
"tags": [
"amenity=vending_machine",
"vending=souvenir_coins"
]
}
],
"filter": [
"open_now",
"accepts_debit_cards",
@ -157,4 +157,4 @@
],
"deletion": true,
"allowMove": true
}
}

View file

@ -1,4 +1,24 @@
{
"id": "souvenir_note",
"name": {
"en": "Souvenir Banknote Machines"
},
"description": {
"en": "Layer showing machines selling souvenir banknotes"
},
"source": {
"osmTags": {
"and": [
"amenity=vending_machine",
"vending~.*souvenir_notes.*"
]
}
},
"title": {
"render": {
"en": "Souvenir Banknote Machine"
}
},
"pointRendering": [
{
"location": [
@ -22,6 +42,26 @@
]
}
],
"lineRendering": [
{
"width": 1,
"color": "blue"
}
],
"presets": [
{
"title": {
"en": "a souvenir banknote machine"
},
"description": {
"en": "Add a machine selling souvenir banknotes"
},
"tags": [
"amenity=vending_machine",
"vending=souvenir_notes"
]
}
],
"tagRenderings": [
"images",
"opening_hours_24_7",
@ -128,46 +168,6 @@
"level",
"check_date"
],
"lineRendering": [
{
"width": 1,
"color": "blue"
}
],
"id": "souvenir_note",
"name": {
"en": "Souvenir Banknote Machines"
},
"description": {
"en": "Layer showing machines selling souvenir banknotes"
},
"source": {
"osmTags": {
"and": [
"amenity=vending_machine",
"vending~.*souvenir_notes.*"
]
}
},
"title": {
"render": {
"en": "Souvenir Banknote Machine"
}
},
"presets": [
{
"title": {
"en": "a souvenir banknote machine"
},
"description": {
"en": "Add a machine selling souvenir banknotes"
},
"tags": [
"amenity=vending_machine",
"vending=souvenir_notes"
]
}
],
"filter": [
"open_now",
"accepts_debit_cards",
@ -175,4 +175,4 @@
],
"deletion": true,
"allowMove": true
}
}

View file

@ -9,8 +9,7 @@
"de": "Ein Ort, an dem erotische Tanz-, Striptease- oder Lapdances kommerziell durchgeführt werden. "
},
"source": {
"osmTags": "amenity=stripclub",
"isOsmCache": false
"osmTags": "amenity=stripclub"
},
"minzoom": 6,
"title": {

View file

@ -7,9 +7,6 @@
"en": "Summary"
}
},
"tagRenderings": [
"all_tags"
],
"pointRendering": [
{
"location": [
@ -17,11 +14,12 @@
"centroid"
],
"iconSize": "40,40",
"label": {
"render": "{total_metric}"
},
"label": "{total_metric}",
"labelCss": "background: #ffffffbb",
"labelCssClasses": "w-12 text-lg rounded-xl p-1 px-2"
}
],
"tagRenderings": [
"all_tags"
]
}

View file

@ -8,19 +8,42 @@
"en": "Find trolley bays for shopping trolleys.",
"de": "Finde Einkaufswagenbuchten für Einkaufswagen."
},
"title": {
"en": "Trolley Bay",
"de": "Einkaufswagenbucht"
},
"source": {
"osmTags": "amenity=trolley_bay"
},
"minzoom": 18,
"allowMove": {
"enableImproveAccuracy": true,
"enableRelocation": true
"title": {
"en": "Trolley Bay",
"de": "Einkaufswagenbucht"
},
"deletion": true,
"pointRendering": [
{
"location": [
"point",
"centroid"
],
"marker": [
{
"icon": "./assets/layers/trolley_bay/trolley_bay.svg"
}
]
}
],
"presets": [
{
"title": {
"en": "a trolley bay",
"de": "eine Einkaufswagenbucht"
},
"tags": [
"amenity=trolley_bay"
],
"description": {
"en": "A trolley bay for parking shopping carts.",
"de": "Ein Platz zum Abstellen von Einkaufswagen."
}
}
],
"tagRenderings": [
{
"id": "covered",
@ -194,32 +217,9 @@
"id": "indoor"
}
],
"presets": [
{
"title": {
"en": "a trolley bay",
"de": "eine Einkaufswagenbucht"
},
"tags": [
"amenity=trolley_bay"
],
"description": {
"en": "A trolley bay for parking shopping carts.",
"de": "Ein Platz zum Abstellen von Einkaufswagen."
}
}
],
"pointRendering": [
{
"location": [
"point",
"centroid"
],
"marker": [
{
"icon": "./assets/layers/trolley_bay/trolley_bay.svg"
}
]
}
]
}
"deletion": true,
"allowMove": {
"enableImproveAccuracy": true,
"enableRelocation": true
}
}

View file

@ -31,7 +31,6 @@
],
"minzoom": 18,
"shownByDefault": false,
"isCounted": false,
"title": {
"render": {
"en": "Wall or building",
@ -122,6 +121,7 @@
"condition": "_biggest_width_id~*"
}
],
"isCounted": false,
"units": [
{
"width": {

View file

@ -50,8 +50,7 @@
"title": "OSM Building",
"description": "Layer showing buildings that are in OpenStreetMap",
"source": {
"osmTags": "building~*",
"maxCacheAge": 0
"osmTags": "building~*"
},
"minzoom": 18,
"doCount": false,
@ -161,8 +160,7 @@
"addr:postcode~*",
"addr:street~*"
]
},
"maxCacheAge": 0
}
},
"minzoom": 18,
"doCount": false,
@ -204,8 +202,7 @@
"source": {
"geoJson": "https://service.pdok.nl/lv/bag/wfs/v2_0?request=GetFeature&service=WFS&version=2.0.0&outputFormat=application%2Fjson%3B%20subtype%3Dgeojson&typeName=bag%3Apand&bbox={x_min}%2C{y_min}%2C{x_max}%2C{y_max}%2CCRS84&srsName=EPSG%3A4326",
"geoJsonZoomLevel": 18,
"osmTags": "identificatie~*",
"maxCacheAge": 0
"osmTags": "identificatie~*"
},
"minzoom": 18,
"calculatedTags": [
@ -395,8 +392,7 @@
"source": {
"geoJson": "https://service.pdok.nl/lv/bag/wfs/v2_0?request=GetFeature&service=WFS&version=2.0.0&outputFormat=application%2Fjson%3B%20subtype%3Dgeojson&typeName=bag%3Averblijfsobject&bbox={x_min}%2C{y_min}%2C{x_max}%2C{y_max}%2CCRS84&srsName=EPSG%3A4326",
"geoJsonZoomLevel": 19,
"osmTags": "identificatie~*",
"maxCacheAge": 0
"osmTags": "identificatie~*"
},
"minzoom": 18,
"calculatedTags": [

View file

@ -0,0 +1,19 @@
{
"id": "bicycle_parkings",
"description": {
"en": "A map showing all types of bicycle parkings"
},
"title": {
"en": "Bicycle parkings"
},
"icon": "./assets/themes/bicycle_parkings/logo.svg",
"layers": [
{
"builtin":
"bike_parking",
"override": {
"minzoom": 12
}
}
]
}

View file

@ -0,0 +1,10 @@
[
{
"path": "logo.svg",
"license": "CC0-1.0",
"authors": [
"Pieter Vander Vennet"
],
"sources": []
}
]

View file

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="500"
height="500"
viewBox="0 0 500 500"
version="1.1"
id="svg7"
sodipodi:docname="logo.svg"
xml:space="preserve"
inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#999999"
borderopacity="1"
inkscape:showpageshadow="2"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="1.0223248"
inkscape:cx="-12.716115"
inkscape:cy="188.29632"
inkscape:window-width="1920"
inkscape:window-height="995"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg7" /><defs
id="defs11" /><path
id="path2"
class="selectable"
style="fill:#282ded;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.04664"
d="m 335.64322,2.3247809 c -90.74626,0 -164.30895,73.3909791 -164.30895,163.9246191 0,77.86541 54.43926,143.00359 127.40699,159.71768 l 26.6932,58.04717 c 5.97726,13.00114 24.49773,13.00114 30.47908,0 L 383.9968,322.9437 c 67.14417,-20.59822 115.95536,-82.95509 115.95536,-156.6943 0,-90.53364 -73.56269,-163.9246191 -164.30894,-163.9246191 z" /><path
path-name="a"
unicode="á"
horiz-adv-x="661"
d="m 243.53703,263.69785 c 63.70594,0 115.35771,51.63479 115.34704,115.34063 0,63.70595 -51.63682,115.34277 -115.34277,115.34277 -63.69441,0 -115.34276,-51.63682 -115.34276,-115.34277 0,-47.06659 28.20579,-87.52188 68.62872,-105.45341 L 186.16824,239.9539 46.122901,379.99924 58.938765,416.58831 h 8.661755 c 6.557077,0 11.864715,5.31908 11.864715,11.87614 0,6.55706 -5.307614,11.87615 -11.864715,11.87615 H 33.178716 c -6.557072,0 -11.876141,-5.31909 -11.876141,-11.87615 0,-6.55706 5.319085,-11.87614 11.876141,-11.87614 h 2.755501 L 24.271889,388.53278 H -9.1778317 C -14.004637,447.78533 -63.60253,494.38156 -124.10408,494.38156 c -63.69441,0 -115.33103,-51.63682 -115.33103,-115.34277 0,-63.70594 51.63683,-115.34276 115.33103,-115.34276 12.49568,0 24.51055,2.01812 35.788084,5.69247 l 34.997454,-72.49498 -14.759923,-36.65369 h -24.681642 c -6.921069,0 -7.006597,-5.60693 -7.006597,-12.5165 0,-6.90957 0.08554,-12.51651 7.006597,-12.51651 h 80.386962 c 6.9095964,0 12.52696553,5.60694 12.52696553,12.51651 0,6.92107 -5.61736913,12.51757 -12.52696553,12.51757 H -41.10247 l 9.718282,24.0621 H 168.54326 l -9.76103,-30.8434 c -0.79056,-1.67707 -5.87395,-11.61961 -16.52147,-11.61961 h -30.07477 c -6.9096,0 -6.98469,-5.60694 -6.98469,-12.5165 0,-6.90957 0.0751,-12.52697 6.98469,-12.52697 h 30.07477 c 22.6311,0 35.68171,17.25891 39.82529,27.45798 0.11785,0.33062 9.38767,29.59396 21.32742,67.27282 0.12828,0.28785 0.18147,0.57571 0.27743,0.87504 5.3295,16.81037 11.17116,35.26553 16.95955,53.57054 v 0.0106 c 7.40083,-1.48413 15.04774,-2.28513 22.88667,-2.28513 z m -319.922375,38.55225 -29.560535,61.22788 h 70.903327 c -4.485761,-25.82364 -19.907941,-47.87803 -41.342792,-61.22788 z m -47.705985,167.19403 c 46.724501,0 85.160658,-35.44696 89.902954,-80.91156 h -91.708274 c -4.31472,0 -8.30924,-2.23192 -10.60584,-5.87394 -2.28512,-3.64201 -2.54168,-8.22372 -0.66228,-12.10041 l 37.881238,-78.45445 c -7.892068,-2.24235 -16.211748,-3.47095 -24.808838,-3.47095 -49.93894,0 -90.4046,40.47719 -90.4046,90.40566 0,49.92846 40.4772,90.40565 90.40567,90.40565 z M -9.8283011,363.47894 13.870791,363.48957 2.7956404,336.00969 -4.1139537,335.98884 C -10.67103,335.96798 -15.9682,330.8846 -15.947376,324.63729 c 0.02086,-5.53184 4.174965,-10.11356 9.6755196,-11.0856 L -40.661301,228.26177 -65.5025,279.70668 c 29.722227,17.56862 50.857719,48.06995 55.6741345,83.77248 z m 46.7778961,-9.708 140.706425,-140.69684 -1.17438,-3.73795 H -21.288473 l 41.961272,104.08617 9.707841,0.0324 c 6.557077,0.0209 11.854255,5.10424 11.833423,11.36297 -0.02086,6.24732 -5.350383,11.29943 -11.907435,11.27849 H 29.825823 Z M 243.55091,469.44413 c 49.92847,0 90.40353,-40.47719 90.40353,-90.40565 0,-49.92847 -40.4772,-90.40566 -90.40566,-90.40566 -5.2221,0 -10.3159,0.47037 -15.29285,1.31412 v 0.0106 c 14.97266,47.27933 25.3533,82.88596 25.3533,82.88596 2.08279,6.5894 -1.56966,13.62732 -8.15907,15.72047 -6.59982,2.07235 -13.62731,-1.58008 -15.72046,-8.15906 l -25.32201,-82.85467 -0.0106,-0.0208 c -30.31976,14.58893 -51.25202,45.60331 -51.25202,81.5092 0,49.92846 40.4772,90.40566 90.40566,90.40566 z"
id="path2-3"
style="stroke-width:1.06799" /><path
d="m 347.80865,43.702499 q 44.29025,0 64.5097,19.256626 20.5404,18.935698 20.5404,52.313845 0,19.89852 -8.34454,37.55041 -8.34453,17.33097 -27.92211,27.92211 -19.25663,10.59114 -52.63478,10.59114 h -20.86134 v 81.51972 H 274.63347 V 43.702499 Z M 345.2411,83.499525 H 323.09598 V 151.5396 h 16.04719 q 20.5404,0 32.41531,-8.02357 12.19585,-8.34454 12.19585,-26.63834 0,-33.378165 -38.51323,-33.378165 z"
style="font-weight:bold;font-size:266.667px;line-height:1.25;letter-spacing:0px;word-spacing:0px;white-space:pre;fill:#ffffff;stroke-width:1.20354"
id="path19001" /></svg>

After

Width:  |  Height:  |  Size: 5.2 KiB

View file

@ -0,0 +1,2 @@
SPDX-FileCopyrightText: Pieter Vander Vennet
SPDX-License-Identifier: CC0-1.0

View file

@ -1,23 +1,23 @@
{
"description": {
"en": "This map contains elements meant for disaster preparedness and response.",
"it": "Questa mappa contiene elementi pensati per la preparazione e risposta ai disastri.",
"de": "Diese Karte enthält Elemente, die der Katastrophenvorsorge und dem Katastrophenschutz dienen.",
"es": "Este mapa contiene elementos destinados a la preparación y respuesta ante desastres."
},
"docs": "https://wiki.openstreetmap.org/wiki/Emergency_facilities_and_amenities",
"icon": "./assets/themes/disaster_response/CivilDefence.svg",
"id": "disaster_response",
"socialImage": "./assets/themes/disaster_response/social.svg",
"title": {
"en": "Disaster response",
"it": "Risposta ai disastri",
"de": "Katastrophenschutz",
"es": "Respuesta ante desastres"
},
"description": {
"en": "This map contains elements meant for disaster preparedness and response.",
"it": "Questa mappa contiene elementi pensati per la preparazione e risposta ai disastri.",
"de": "Diese Karte enthält Elemente, die der Katastrophenvorsorge und dem Katastrophenschutz dienen.",
"es": "Este mapa contiene elementos destinados a la preparación y respuesta ante desastres."
},
"icon": "./assets/themes/disaster_response/CivilDefence.svg",
"socialImage": "./assets/themes/disaster_response/social.svg",
"layers": [
"hospital",
"assembly_point",
"disaster_response"
]
],
"docs": "https://wiki.openstreetmap.org/wiki/Emergency_facilities_and_amenities"
}

View file

@ -42,8 +42,7 @@
},
"building~*"
]
},
"maxCacheAge": 0
}
},
"title": "OSM-gebouw",
"tagRenderings": [
@ -290,7 +289,6 @@
"geoJson": "https://betadata.grbosm.site/grb?bbox={x_min},{y_min},{x_max},{y_max}",
"geoJsonZoomLevel": 18,
"mercatorCrs": true,
"maxCacheAge": 0,
"idKey": "osm_id"
},
"name": "GRB geometries",
@ -587,8 +585,7 @@
]
}
]
},
"maxCacheAge": 0
}
},
"title": {
"render": {

View file

@ -1,6 +1,5 @@
{
"id": "items_with_image",
"hideFromOverview": true,
"title": {
"en": "All items with images"
},
@ -8,6 +7,7 @@
"en": "A map showing all items on OSM which have an image. This theme is a very bad fit for MapComplete as someone is not able to directly add a picture. However, this theme is mostly here to include this all into the database, which'll allow this to quickly fetch images nearby for other features"
},
"icon": "./assets/layers/item_with_image/camera.svg",
"hideFromOverview": true,
"layers": [
"item_with_image"
]

View file

@ -14,8 +14,6 @@
"startLat": 0,
"startLon": 0,
"startZoom": 1,
"widenFactor": 0.05,
"clustering": false,
"layers": [
{
"id": "mapcomplete-changes",
@ -26,8 +24,7 @@
"source": {
"osmTags": "editor~*",
"geoJson": "https://raw.githubusercontent.com/pietervdvn/MapComplete-data/main/mapcomplete-changes/tile_{z}_{x}_{y}.geojson",
"geoJsonZoomLevel": 8,
"maxCacheAge": 0
"geoJsonZoomLevel": 8
},
"title": {
"render": {
@ -152,6 +149,10 @@
"if": "theme=benches",
"then": "./assets/themes/benches/bench_poi.svg"
},
{
"if": "theme=bicycle_parkings",
"then": "./assets/themes/bicycle_parkings/logo.svg"
},
{
"if": "theme=bicycle_rental",
"then": "./assets/themes/bicycle_rental/logo.svg"

View file

@ -14,8 +14,6 @@
"startLat": 0,
"startLon": 0,
"startZoom": 1,
"widenFactor": 0.05,
"clustering": false,
"layers": [
{
"id": "mapcomplete-changes",
@ -26,8 +24,7 @@
"source": {
"osmTags": "editor~*",
"geoJson": "https://raw.githubusercontent.com/pietervdvn/MapComplete-data/main/mapcomplete-changes/tile_{z}_{x}_{y}.geojson",
"geoJsonZoomLevel": 8,
"maxCacheAge": 0
"geoJsonZoomLevel": 8
},
"title": {
"render": {

View file

@ -32,6 +32,5 @@
"note",
"fixme"
],
"enableDownload": true,
"clustering": false
"enableDownload": true
}

View file

@ -41,8 +41,5 @@
],
"layers": [
"windturbine"
],
"clustering": {
"maxZoom": 8
}
]
}

View file

@ -36,6 +36,5 @@
"startLon": 4.351697,
"layers": [
"osm_community_index"
],
"clustering": false
]
}

View file

@ -44,8 +44,5 @@
"enableNoteImports": false,
"widenFactor": 1.2,
"overpassMaxZoom": 15,
"clustering": {
"maxZoom": 19
},
"#note": "The 'overpassMaxZoom' should be exactly the same as or less then the minzzom in overrideAll"
}

View file

@ -231,6 +231,5 @@
}
],
"overpassTimeout": 180,
"widenFactor": 0.05,
"clustering": false
"widenFactor": 0.05
}

View file

@ -103,9 +103,5 @@
}
}
],
"widenFactor": 1.5,
"clustering": {
"maxZoom": 14,
"minNeededElements": 100
}
"widenFactor": 1.5
}

View file

@ -11,7 +11,6 @@
"es": "Todo lo que necesitas para esquiar"
},
"icon": "./assets/layers/aerialway/chair_lift.svg",
"enableTerrain": true,
"layers": [
"ski_piste",
"aerialway",
@ -50,5 +49,6 @@
]
}
}
]
],
"enableTerrain": true
}

View file

@ -23,8 +23,7 @@
"title": null,
"source": {
"geoJson": "https://raw.githubusercontent.com/pietervdvn/MapComplete/master/assets/themes/speelplekken/shadow.geojson",
"osmTags": "shadow=yes",
"isOsmCache": false
"osmTags": "shadow=yes"
},
"pointRendering": null,
"lineRendering": [
@ -37,11 +36,6 @@
{
"builtin": "play_forest",
"override": {
"source": {
"geoJson": "https://raw.githubusercontent.com/pietervdvn/MapComplete-data/main/speelplekken_cache/speelplekken_{layer}_{z}_{x}_{y}.geojson",
"geoJsonZoomLevel": 14,
"isOsmCache": true
},
"minzoom": 12,
"calculatedTags": [
"_is_shadowed=overlapWith(feat)('shadow').length > 0 ? 'yes': ''",
@ -53,12 +47,6 @@
"builtin": "playground",
"override": {
"minzoom": 14,
"source": {
"geoJsonLocal": "http://127.0.0.1:8080/speelplekken_{layer}_{z}_{x}_{y}.geojson",
"geoJson": "https://raw.githubusercontent.com/pietervdvn/MapComplete-data/main/speelplekken_cache/speelplekken_{layer}_{z}_{x}_{y}.geojson",
"geoJsonZoomLevel": 14,
"isOsmCache": true
},
"calculatedTags": [
"_is_shadowed=overlapWith(feat)('shadow').length > 0 ? 'yes': ''",
"_video:id=feat.properties.video === undefined ? undefined : new URL(feat.properties.video).searchParams.get('v')"
@ -69,12 +57,6 @@
"builtin": "village_green",
"override": {
"minzoom": 14,
"source": {
"geoJsonLocal": "http://127.0.0.1:8080/speelplekken_{layer}_{z}_{x}_{y}.geojson",
"geoJson": "https://raw.githubusercontent.com/pietervdvn/MapComplete-data/main/speelplekken_cache/speelplekken_{layer}_{z}_{x}_{y}.geojson",
"geoJsonZoomLevel": 14,
"isOsmCache": true
},
"calculatedTags": [
"_is_shadowed=overlapWith(feat)('shadow').length > 0 ? 'yes': ''",
"_video:id=feat.properties.video === undefined ? undefined : new URL(feat.properties.video).searchParams.get('v')"
@ -85,12 +67,6 @@
"builtin": "sport_pitch",
"override": {
"minzoom": 15,
"source": {
"geoJsonLocal": "http://127.0.0.1:8080/speelplekken_{layer}_{z}_{x}_{y}.geojson",
"geoJson": "https://raw.githubusercontent.com/pietervdvn/MapComplete-data/main/speelplekken_cache/speelplekken_{layer}_{z}_{x}_{y}.geojson",
"geoJsonZoomLevel": 14,
"isOsmCache": true
},
"calculatedTags": [
"_is_shadowed=overlapWith(feat)('shadow').length > 0 ? 'yes': ''",
"_video:id=feat.properties.video === undefined ? undefined : new URL(feat.properties.video).searchParams.get('v')"
@ -102,13 +78,7 @@
"override": {
"calculatedTags": [
"_is_shadowed=overlapWith(feat)('shadow').length > 0 ? 'yes': ''"
],
"source": {
"geoJsonLocal": "http://127.0.0.1:8080/speelplekken_{layer}_{z}_{x}_{y}.geojson",
"geoJson": "https://raw.githubusercontent.com/pietervdvn/MapComplete-data/main/speelplekken_cache/speelplekken_{layer}_{z}_{x}_{y}.geojson",
"geoJsonZoomLevel": 14,
"isOsmCache": true
}
]
}
},
{
@ -124,10 +94,7 @@
"route=foot",
"operator~[pP]rovincie Antwerpen"
]
},
"geoJson": "https://raw.githubusercontent.com/pietervdvn/MapComplete-data/main/speelplekken_cache/speelplekken_{layer}_{z}_{x}_{y}.geojson",
"geoJsonZoomLevel": 14,
"isOsmCache": true
}
},
"title": {
"render": "Wandeling <i>{name}</i>",
@ -260,9 +227,5 @@
51.23978120350654
]
],
"widenFactor": 1.2,
"clustering": {
"maxZoom": 6,
"minNeededElements": 100
}
"widenFactor": 1.2
}

View file

@ -358,6 +358,10 @@
{
"if": "lit=no",
"then": "#303030"
},
{
"if": "lit=yes",
"then": "#ff0"
}
]
}

View file

@ -23,8 +23,7 @@
"osmTags": "Lichtmastnummer~*",
"#geoJson": "https://opendata.arcgis.com/datasets/ba37cdb372064b3199c548b75d16a609_0.geojson",
"geoJson": "https://robinlinde.github.io/tiles/assen_street_lighting/{z}/{x}/{y}.json",
"geoJsonZoomLevel": 16,
"isOsmCache": false
"geoJsonZoomLevel": 16
},
"calculatedTags": [
"_closest_osm_street_lamp=closest(feat)('street_lamps')?.properties?.id",

View file

@ -71,9 +71,5 @@
"tree_node"
],
"widenFactor": 0.2,
"osmApiTileSize": 18,
"clustering": {
"maxZoom": 19,
"minNeededElements": 25
}
"osmApiTileSize": 18
}

View file

@ -32,8 +32,7 @@
"source": {
"geoJson": "https://osm-uk-addresses.russss.dev/inspire/{z}/{x}/{y}.json",
"osmTags": "inspireid~*",
"geoJsonZoomLevel": 18,
"isOsmCache": false
"geoJsonZoomLevel": 18
},
"minzoom": 18,
"calculatedTags": [
@ -69,8 +68,7 @@
"id!~node/.*"
]
},
"geoJsonZoomLevel": 16,
"isOsmCache": false
"geoJsonZoomLevel": 16
},
"name": "Addresses to check",
"minzoom": 18,
@ -703,9 +701,5 @@
],
"enableShareScreen": false,
"enableMoreQuests": false,
"widenFactor": 1.01,
"clustering": {
"minNeededFeatures": 25,
"maxZoom": 16
}
"widenFactor": 1.01
}

View file

@ -3,45 +3,33 @@
"title": {
"nl": "Velopark naar OpenStreetMap sync tool"
},
"shortDescription": {
"en": "A tool to import data from velopark.be into OpenStreetMap",
"nl": "Een hulpmiddel om data van velopark.be in OpenStreetMap in te laden"
},
"mustHaveLanguage": [
"nl"
],
"description": {
"en": "<p><a href='https://velopark.be' target='_blank'>Velopark.be</a> is a website collecting data about bicycle parkings in a semi-crowdsourced way. However, only 'authorized' instances are allowed to make changes there, in practice the operator of the bicycle parking such as SNCB, de Lijn or the municipality. They have now decided to synchronize their dataset with OpenStreetMap, and this MapComplete-instance is set up to help link and import their data into OpenStreetMap.</p> How to use: <ul><li>A velopark-icon on the map (yellow with bicycle silhouette) represents a bicycle known by Velopark but not yet known by OpenStreetMap</li><li>Blue pins are bicycle parkings known by OpenStreetMap</li><li>Light blue pins are bicycle parkings known by OpenStreetMap with a reference to Velopark.be (<span class='literal-code'>ref-velopark=*</span>)</li><li>Click a velopark item, you can either link it with a nearby OSM-bicycle parking or create a new bicycle parking. Note that the geometry of Velopark is often incorrect and can be a few up till 100 meters away from the actual bicycle parking. Use aerial imagery, linked images and streetview to determine the correct location</li><li>Once linked, you can compare the Velopark- and OSM-attributes and apply correct attributes</li><li>If Velopark has an image, you can also link the image</li></ul> That's it! Thanks for helping to import this!",
"nl": "<p><a href='https://velopark.be' target='_blank'>Velopark.be</a> is een website die data verzamelt over fietsenstallingen in een semi-crowdsource manier. Hierbij kunnen enkel geautorizeerde gebruikers data bijdragen, in de praktijk de uitbaters van de fietsenstallingen zoals de bevoegde gemeentebesturen, de NMBS of de Lijn. Velopark.be heeft nu beslist om hun data met OpenStreetMap te synchronizeren. Deze website is de tool om van Velopark.be naar OpenStreetMap te gaan en hun data te importeren.</p> Hoe te gebruiken? <ul><li>Een velopark-logo op de kaart (geel met een fietssilhouette) duidt een fietsenstalling aan die gekend is in Velopark maar nog niet gekend (of gelinkt) is aan een fietsenstalling in OpenStreetMap</li><li>Een blauwe pin duidt een fietsenstalling aan die gekend is in OpenStreetMap</li><li>Een licht-blauwe pin duidt een fietsenstalling aan uit OpenStreetMap die een link heeft naar Velopark.be (<span class='literal-code'>ref-velopark=*</span>)</li><li>Als je op een velopark-item klikt op, kan je deze linken met een fietsenstalling in de buurt (<25m) of een nieuwe fietstalling aan OpenStreetMap toevoegen. Let op: de geometrie van Velopark is zelden correct en wijkt makkelijk 10 meter of meer af van de echte locatie - in uitzonderlijke gevallen zelfs tot meer dan 100 meter. Gebruik de meest recente luchtfoto's, de gelinkte foto's en mapillary om de correcte locatie te bepalen</li><li>Eens gelinkt, kan je de Velopark- en OSM-attributen vergelijken en de correcte attributen toepassen in OpenStreetMap</li><li>Indien velopark een foto heeft, kan je die ook nog linken</li></ul> Dat is het! Bedankt om mee te helpen!"
},
"shortDescription": {
"en": "A tool to import data from velopark.be into OpenStreetMap",
"nl": "Een hulpmiddel om data van velopark.be in OpenStreetMap in te laden"
},
"descriptionTail": {
"*": "<h3>Maintainer tools</h3><ul><li><a class='link-underline' href='https://maproulette.org/api/v2/challenge/view/43282' download='Velopark_sync_2024-01-15.geojson'>Download the first sync results</a></li></ul>"
},
"hideFromOverview": true,
"icon": "./assets/themes/velopark/velopark.svg",
"mustHaveLanguage": [
"nl"
],
"lockLocation": [
[
2.51357303225,
49.5294835476
],
[
6.15665815596,
51.4750237087
]
],
"startZoom": 18,
"startLat": 51.03753,
"startLon": 3.71025,
"startZoom": 18,
"defaultBackgroundId": "photo",
"enableNoteImports": false,
"hideFromOverview": true,
"layers": [
{
"id": "velopark_maproulette",
"description": "Maproulette challenge containing velopark data",
"source": {
"osmTags": "mr_taskId~*",
"geoJson": "https://maproulette.org/api/v2/challenge/view/43282",
"isOsmCache": false
"geoJson": "https://maproulette.org/api/v2/challenge/view/43282"
},
"title": {
"render": "Velopark parking <b>{mr_velopark_id}</b>"
@ -348,5 +336,16 @@
}
}
]
}
},
"lockLocation": [
[
2.51357303225,
49.5294835476
],
[
6.15665815596,
51.4750237087
]
],
"enableNoteImports": false
}

View file

@ -27,8 +27,7 @@
"description": "Laag op basis van externe data",
"source": {
"osmTags": "OBJECTID~*",
"geoJson": "https://opendata.arcgis.com/datasets/5b6953ac5a9d4616a7dc75ab0beeac2f_0.geojson",
"isOsmCache": false
"geoJson": "https://opendata.arcgis.com/datasets/5b6953ac5a9d4616a7dc75ab0beeac2f_0.geojson"
},
"calculatedTags": [
"_closest_osm_waste_basket=closest(feat)('waste_basket')?.properties?.id",
@ -71,8 +70,7 @@
"description": "Laag op basis van externe data",
"source": {
"osmTags": "OBJECTID~*",
"geoJson": "https://opendata.arcgis.com/datasets/edb893998e27461b8ed82aad9854d27d_0.geojson",
"isOsmCache": false
"geoJson": "https://opendata.arcgis.com/datasets/edb893998e27461b8ed82aad9854d27d_0.geojson"
},
"calculatedTags": [
"_closest_osm_recycling=closest(feat)('recycling')?.properties?.id",

View file

@ -275,6 +275,5 @@
"enableLayers": false,
"enableSearch": false,
"enableBackgroundLayerSelection": false,
"widenFactor": 0.05,
"clustering": false
"widenFactor": 0.05
}

File diff suppressed because it is too large Load diff

View file

@ -33,6 +33,16 @@
"1": {
"title": "un panneau à affiches scellé au sol"
},
"10": {
"description": "Désigne une enseigne publicitaire, une enseigne néon, les logos ou des indications d'entrées",
"title": "une enseigne"
},
"11": {
"title": "une sculpture"
},
"12": {
"title": "une peinture murale"
},
"2": {
"title": "un panneau à affiches monté sur un mur"
},
@ -59,16 +69,6 @@
},
"9": {
"title": "un totem"
},
"10": {
"description": "Désigne une enseigne publicitaire, une enseigne néon, les logos ou des indications d'entrées",
"title": "une enseigne"
},
"11": {
"title": "une sculpture"
},
"12": {
"title": "une peinture murale"
}
},
"tagRenderings": {
@ -160,6 +160,9 @@
"1": {
"then": "C'est un petit panneau"
},
"10": {
"then": "C'est une peinture murale"
},
"2": {
"then": "C'est une colonne"
},
@ -183,9 +186,6 @@
},
"9": {
"then": "C'est un totem"
},
"10": {
"then": "C'est une peinture murale"
}
},
"question": "De quel type de dispositif publicitaire s'agit-il ?"
@ -196,6 +196,9 @@
"1": {
"then": "Petit panneau"
},
"10": {
"then": "Peinture murale"
},
"3": {
"then": "Colonne"
},
@ -216,9 +219,6 @@
},
"9": {
"then": "Totem"
},
"10": {
"then": "Peinture murale"
}
}
}
@ -300,6 +300,15 @@
"1": {
"then": "Peinture murale"
},
"10": {
"then": "Azulejo (faïence latine)"
},
"11": {
"then": "Carrelage"
},
"12": {
"then": "Sculpture sur bois"
},
"2": {
"then": "Peinture"
},
@ -323,15 +332,6 @@
},
"9": {
"then": "Relief"
},
"10": {
"then": "Azulejo (faïence latine)"
},
"11": {
"then": "Carrelage"
},
"12": {
"then": "Sculpture sur bois"
}
},
"question": "Quel est le type de cette œuvre d'art ?",
@ -1644,7 +1644,7 @@
},
"2": {
"description": "Un <b>café</b> pour prendre un thé, un café ou une boisson alcoolisée dans un environnement calme",
"title": "un café"
"title": "un café adama"
},
"3": {
"description": "Une <b>boîte de nuit</b> ou discothèque pour danser sur de la musique de DJ accompagnée de jeux de lumière et un bar pour prendre une boisson (alcoolisée)",
@ -2408,6 +2408,15 @@
"1": {
"then": "Cette piste cyclable est goudronée"
},
"10": {
"then": "Cette piste cyclable est faite en graviers fins"
},
"11": {
"then": "Cette piste cyclable est en cailloux"
},
"12": {
"then": "Cette piste cyclable est faite en sol brut"
},
"2": {
"then": "Cette piste cyclable est asphaltée"
},
@ -2431,15 +2440,6 @@
},
"9": {
"then": "Cette piste cyclable est faite en graviers"
},
"10": {
"then": "Cette piste cyclable est faite en graviers fins"
},
"11": {
"then": "Cette piste cyclable est en cailloux"
},
"12": {
"then": "Cette piste cyclable est faite en sol brut"
}
},
"question": "De quoi est faite la surface de la piste cyclable ?",
@ -2488,6 +2488,15 @@
"1": {
"then": "Cette piste cyclable est pavée"
},
"10": {
"then": "Cette piste cyclable est faite en graviers fins"
},
"11": {
"then": "Cette piste cyclable est en cailloux"
},
"12": {
"then": "Cette piste cyclable est faite en sol brut"
},
"2": {
"then": "Cette piste cyclable est asphaltée"
},
@ -2511,15 +2520,6 @@
},
"9": {
"then": "Cette piste cyclable est faite en graviers"
},
"10": {
"then": "Cette piste cyclable est faite en graviers fins"
},
"11": {
"then": "Cette piste cyclable est en cailloux"
},
"12": {
"then": "Cette piste cyclable est faite en sol brut"
}
},
"question": "De quel materiel est faite cette rue ?",
@ -3351,6 +3351,21 @@
"1": {
"then": "C'est une friterie"
},
"10": {
"then": "Des plats chinois sont servis ici"
},
"11": {
"then": "Des plats grecs sont servis ici"
},
"12": {
"then": "Des plats indiens sont servis ici"
},
"13": {
"then": "Des plats turcs sont servis ici"
},
"14": {
"then": "Des plats thaïlandais sont servis ici"
},
"2": {
"then": "Restaurant Italien"
},
@ -3374,21 +3389,6 @@
},
"9": {
"then": "Des plats français sont servis ici"
},
"10": {
"then": "Des plats chinois sont servis ici"
},
"11": {
"then": "Des plats grecs sont servis ici"
},
"12": {
"then": "Des plats indiens sont servis ici"
},
"13": {
"then": "Des plats turcs sont servis ici"
},
"14": {
"then": "Des plats thaïlandais sont servis ici"
}
},
"question": "Quelle type de nourriture est servie ici ?",
@ -4933,30 +4933,6 @@
"1": {
"question": "Recyclage de piles et batteries domestiques"
},
"2": {
"question": "Recyclage d'emballage de boissons"
},
"3": {
"question": "Recyclage de boites de conserve et de canettes"
},
"4": {
"question": "Recyclage de vêtements"
},
"5": {
"question": "Recyclage des huiles de friture"
},
"6": {
"question": "Recyclage des huiles de moteur"
},
"7": {
"question": "Recyclage des lampes fluorescentes"
},
"8": {
"question": "Recyclage des déchets verts"
},
"9": {
"question": "Recyclage des bouteilles en verre et des bocaux"
},
"10": {
"question": "Recyclage de tout type de verre"
},
@ -4987,11 +4963,35 @@
"19": {
"question": "Recyclage des autres déchets"
},
"2": {
"question": "Recyclage d'emballage de boissons"
},
"20": {
"question": "Recyclage des cartouches d'imprimante"
},
"21": {
"question": "Recyclage des vélos"
},
"3": {
"question": "Recyclage de boites de conserve et de canettes"
},
"4": {
"question": "Recyclage de vêtements"
},
"5": {
"question": "Recyclage des huiles de friture"
},
"6": {
"question": "Recyclage des huiles de moteur"
},
"7": {
"question": "Recyclage des lampes fluorescentes"
},
"8": {
"question": "Recyclage des déchets verts"
},
"9": {
"question": "Recyclage des bouteilles en verre et des bocaux"
}
}
},
@ -5054,30 +5054,6 @@
"1": {
"then": "Les briques alimentaires en carton peuvent être recyclées ici"
},
"2": {
"then": "Les boites de conserve et canettes peuvent être recyclées ici"
},
"3": {
"then": "Les vêtements peuvent être recyclés ici"
},
"4": {
"then": "Les huiles de friture peuvent être recyclées ici"
},
"5": {
"then": "Les huiles de moteur peuvent être recyclées ici"
},
"6": {
"then": "Les lampes fluorescentes peuvent être recyclées ici"
},
"7": {
"then": "Les déchets verts peuvent être recyclés ici"
},
"8": {
"then": "Les déchets organiques peuvent être recyclés ici"
},
"9": {
"then": "Les bouteilles en verre et bocaux peuvent être recyclés ici"
},
"10": {
"then": "Tout type de verre peut être recyclé ici"
},
@ -5108,6 +5084,9 @@
"19": {
"then": "Les chaussures peuvent être recyclées ici"
},
"2": {
"then": "Les boites de conserve et canettes peuvent être recyclées ici"
},
"20": {
"then": "Les petits appareils électriques peuvent être recyclés ici"
},
@ -5122,6 +5101,27 @@
},
"24": {
"then": "Les vélos peuvent être recyclés ici"
},
"3": {
"then": "Les vêtements peuvent être recyclés ici"
},
"4": {
"then": "Les huiles de friture peuvent être recyclées ici"
},
"5": {
"then": "Les huiles de moteur peuvent être recyclées ici"
},
"6": {
"then": "Les lampes fluorescentes peuvent être recyclées ici"
},
"7": {
"then": "Les déchets verts peuvent être recyclés ici"
},
"8": {
"then": "Les déchets organiques peuvent être recyclés ici"
},
"9": {
"then": "Les bouteilles en verre et bocaux peuvent être recyclés ici"
}
},
"question": "Que peut-on recycler ici ?"
@ -6428,6 +6428,27 @@
"1": {
"question": "Vente de boissons"
},
"10": {
"question": "Vente de lait"
},
"11": {
"question": "Vente de pain"
},
"12": {
"question": "Vente d'œufs"
},
"13": {
"question": "Vente de fromage"
},
"14": {
"question": "Vente de miel"
},
"15": {
"question": "Vente de pommes de terre"
},
"19": {
"question": "Vente de fleurs"
},
"2": {
"question": "Ventre de confiseries"
},
@ -6451,27 +6472,6 @@
},
"9": {
"question": "Vente de chambres à air pour vélo"
},
"10": {
"question": "Vente de lait"
},
"11": {
"question": "Vente de pain"
},
"12": {
"question": "Vente d'œufs"
},
"13": {
"question": "Vente de fromage"
},
"14": {
"question": "Vente de miel"
},
"15": {
"question": "Vente de pommes de terre"
},
"19": {
"question": "Vente de fleurs"
}
}
}
@ -6512,6 +6512,24 @@
"1": {
"then": "Vent des confiseries"
},
"10": {
"then": "Vent du pain"
},
"11": {
"then": "Vent des œufs"
},
"12": {
"then": "Vent du fromage"
},
"13": {
"then": "Vent du miel"
},
"14": {
"then": "Vent des pommes de terre"
},
"18": {
"then": "Vent des fleurs"
},
"2": {
"then": "Vent de la nourriture"
},
@ -6535,24 +6553,6 @@
},
"9": {
"then": "Vent du lait"
},
"10": {
"then": "Vent du pain"
},
"11": {
"then": "Vent des œufs"
},
"12": {
"then": "Vent du fromage"
},
"13": {
"then": "Vent du miel"
},
"14": {
"then": "Vent des pommes de terre"
},
"18": {
"then": "Vent des fleurs"
}
},
"question": "Que vent ce distributeur ?",
@ -6755,4 +6755,4 @@
"render": "éolienne"
}
}
}
}

View file

@ -1,6 +1,6 @@
{
"name": "mapcomplete",
"version": "0.40.0",
"version": "0.40.2",
"repository": "https://github.com/pietervdvn/MapComplete",
"description": "A small website to edit OSM easily",
"bugs": "https://github.com/pietervdvn/MapComplete/issues",

View file

@ -162,7 +162,7 @@ class CachedSqlCount {
const connectionString = "postgresql://user:password@localhost:5444/osm-poi"
const tcs = new OsmPoiDatabase(connectionString)
const withCache = new CachedSqlCount(tcs, 60 * 60 * 24)
const withCache = new CachedSqlCount(tcs, 14 * 60 * 60 * 24)
new Server(2345, { ignorePathPrefix: ["summary"] }, [
{
mustMatch: "status.json",

View file

@ -1,26 +1,12 @@
/**
* This actor will download the latest version of the selected element from OSM and update the tags if necessary.
*/
import { UIEventSource } from "../UIEventSource"
import { Changes } from "../Osm/Changes"
import { OsmConnection } from "../Osm/OsmConnection"
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"
import SimpleMetaTagger from "../SimpleMetaTagger"
import { Feature } from "geojson"
import { OsmTags } from "../../Models/OsmFeature"
import OsmObjectDownloader from "../Osm/OsmObjectDownloader"
import { IndexedFeatureSource } from "../FeatureSource/FeatureSource"
import { Utils } from "../../Utils"
interface TagsUpdaterState {
selectedElement: UIEventSource<Feature>
featureProperties: { getStore: (id: string) => UIEventSource<Record<string, string>> }
changes: Changes
osmConnection: OsmConnection
layout: LayoutConfig
osmObjectDownloader: OsmObjectDownloader
indexedFeatures: IndexedFeatureSource
}
import ThemeViewState from "../../Models/ThemeViewState"
import { BBox } from "../BBox"
import { Feature } from "geojson"
export default class SelectedElementTagsUpdater {
private static readonly metatags = new Set([
@ -31,19 +17,21 @@ export default class SelectedElementTagsUpdater {
"uid",
"id",
])
private readonly state: ThemeViewState
constructor(state: TagsUpdaterState) {
constructor(state: ThemeViewState) {
this.state = state
state.osmConnection.isLoggedIn.addCallbackAndRun((isLoggedIn) => {
if (!isLoggedIn && !Utils.runningFromConsole) {
return
}
this.installCallback(state)
this.installCallback()
// We only have to do this once...
return true
})
}
public static applyUpdate(latestTags: OsmTags, id: string, state: TagsUpdaterState) {
public static applyUpdate(latestTags: OsmTags, id: string, state: ThemeViewState) {
try {
const leftRightSensitive = state.layout.isLeftRightSensitive()
@ -120,8 +108,13 @@ export default class SelectedElementTagsUpdater {
console.error("Updating the tags of selected element ", id, "failed due to", e)
}
}
private installCallback(state: TagsUpdaterState) {
private invalidateCache(s: Feature) {
const state = this.state
const wasPartOfLayer = state.layout.getMatchingLayer(s.properties)
state.toCacheSavers.get(wasPartOfLayer.id).invalidateCacheAround(BBox.get(s))
}
private installCallback() {
const state = this.state
state.selectedElement.addCallbackAndRunD(async (s) => {
let id = s.properties?.id
if (!id) {
@ -146,9 +139,9 @@ export default class SelectedElementTagsUpdater {
const osmObject = await state.osmObjectDownloader.DownloadObjectAsync(id)
if (osmObject === "deleted") {
console.debug("The current selected element has been deleted upstream!", id)
this.invalidateCache(s)
const currentTagsSource = state.featureProperties.getStore(id)
currentTagsSource.data["_deleted"] = "yes"
currentTagsSource.addCallbackAndRun((tags) => console.trace("Tags are", tags))
currentTagsSource.ping()
return
}
@ -158,6 +151,7 @@ export default class SelectedElementTagsUpdater {
const oldGeometry = oldFeature?.geometry
if (oldGeometry !== undefined && !Utils.SameObject(newGeometry, oldGeometry)) {
console.log("Detected a difference in geometry for ", id)
this.invalidateCache(s)
oldFeature.geometry = newGeometry
state.featureProperties.getStore(id)?.ping()
}

View file

@ -45,15 +45,16 @@ export class BBox {
])
}
static get(feature): BBox {
if (feature.bbox?.overlapsWith === undefined) {
static get(feature: Feature): BBox {
const f = <any>feature
if (f.bbox?.overlapsWith === undefined) {
const turfBbox: number[] = turf.bbox(feature)
feature.bbox = new BBox([
f["bbox"] = new BBox([
[turfBbox[0], turfBbox[1]],
[turfBbox[2], turfBbox[3]],
])
}
return feature.bbox
return f["bbox"]
}
static bboxAroundAll(bboxes: BBox[]): BBox {

View file

@ -5,6 +5,8 @@ import { GeoOperations } from "../../GeoOperations"
import FeaturePropertiesStore from "./FeaturePropertiesStore"
import { UIEventSource } from "../../UIEventSource"
import { Utils } from "../../../Utils"
import { Tiles } from "../../../Models/TileRange"
import { BBox } from "../../BBox"
class SingleTileSaver {
private readonly _storage: UIEventSource<Feature[]>
@ -54,6 +56,8 @@ class SingleTileSaver {
* Also see the sibling class
*/
export default class SaveFeatureSourceToLocalStorage {
public readonly storage: TileLocalStorage<Feature[]>
private zoomlevel: number
constructor(
backend: string,
layername: string,
@ -62,7 +66,9 @@ export default class SaveFeatureSourceToLocalStorage {
featureProperties: FeaturePropertiesStore,
maxCacheAge: number
) {
this.zoomlevel = zoomlevel
const storage = TileLocalStorage.construct<Feature[]>(backend, layername, maxCacheAge)
this.storage = storage
const singleTileSavers: Map<number, SingleTileSaver> = new Map<number, SingleTileSaver>()
features.features.addCallbackAndRunD((features) => {
const sliced = GeoOperations.slice(zoomlevel, features)
@ -80,4 +86,12 @@ export default class SaveFeatureSourceToLocalStorage {
})
})
}
public invalidateCacheAround(bbox: BBox) {
const range = Tiles.tileRangeFrom(bbox, this.zoomlevel)
Tiles.MapRange(range, (x, y) => {
const index = Tiles.tile_index(this.zoomlevel, x, y)
this.storage.invalidate(index)
})
}
}

View file

@ -1,5 +1,6 @@
import { IdbLocalStorage } from "../../Web/IdbLocalStorage"
import { UIEventSource } from "../../UIEventSource"
import { Tiles } from "../../../Models/TileRange"
/**
* A class which allows to read/write a tile to local storage.
@ -91,9 +92,17 @@ export default class TileLocalStorage<T> {
await IdbLocalStorage.GetDirectly(this._layername + "_" + tileIndex + "_date")
)
const maxAge = this._maxAgeSeconds
const timeDiff = Date.now() - date
const timeDiff = (Date.now() - date) / 1000
if (timeDiff >= maxAge) {
console.debug("Dropping cache for", this._layername, tileIndex, "out of date")
console.debug(
"Dropping cache for",
this._layername,
tileIndex,
"out of date. Max allowed age is",
maxAge,
"current age is",
timeDiff
)
await IdbLocalStorage.SetDirectly(this._layername + "_" + tileIndex, undefined)
return undefined
@ -102,7 +111,8 @@ export default class TileLocalStorage<T> {
return <any>data
}
invalidate(zoomlevel: number, tileIndex) {
public invalidate(tileIndex: number) {
console.log("Invalidated tile", tileIndex)
this.getTileSource(tileIndex).setData(undefined)
}
}

View file

@ -26,6 +26,8 @@ export default class LayoutSource extends FeatureSourceMerger {
private readonly supportsForceDownload: UpdatableFeatureSource[]
private readonly fromCache: Map<string, LocalStorageFeatureSource>
public static readonly fromCacheZoomLevel = 15
constructor(
layers: LayerConfig[],
featureSwitches: FeatureSwitchState,
@ -43,13 +45,21 @@ export default class LayoutSource extends FeatureSourceMerger {
const geojsonlayers = layers.filter((layer) => layer.source.geojsonSource !== undefined)
const osmLayers = layers.filter((layer) => layer.source.geojsonSource === undefined)
const fromCache = osmLayers.map(
(l) =>
new LocalStorageFeatureSource(backend, l, 15, mapProperties, {
isActive: isDisplayed(l.id),
maxAge: l.maxAgeOfCache,
})
)
const fromCache = new Map<string, LocalStorageFeatureSource>()
for (const layer of osmLayers) {
const src = new LocalStorageFeatureSource(
backend,
layer,
LayoutSource.fromCacheZoomLevel,
mapProperties,
{
isActive: isDisplayed(layer.id),
maxAge: layer.maxAgeOfCache,
}
)
fromCache.set(layer.id, src)
}
const mvtSources: UpdatableFeatureSource[] = osmLayers
.filter((f) => mvtAvailableLayers.has(f.id))
.map((l) => LayoutSource.setupMvtSource(l, mapProperties, isDisplayed(l.id)))
@ -92,9 +102,10 @@ export default class LayoutSource extends FeatureSourceMerger {
LayoutSource.setupGeojsonSource(l, mapProperties, isDisplayed(l.id))
)
super(...geojsonSources, ...fromCache, ...mvtSources, ...nonMvtSources)
super(...geojsonSources, ...Array.from(fromCache.values()), ...mvtSources, ...nonMvtSources)
this.isLoading = isLoading
this.fromCache = fromCache
supportsForceDownload.push(...geojsonSources)
supportsForceDownload.push(...mvtSources) // Non-mvt sources are handled by overpass
this.supportsForceDownload = supportsForceDownload

View file

@ -27,14 +27,14 @@ export default class LocalStorageFeatureSource extends DynamicTileSource {
options?.maxAge ?? 24 * 60 * 60
)
super(
new ImmutableStore(zoomlevel),
new ImmutableStore(zoomlevel),
layer.minzoom,
(tileIndex) =>
new StaticFeatureSource(
storage.getTileSource(tileIndex).mapD((features) => {
if (features.length === undefined) {
console.trace("These are not features:", features)
storage.invalidate(zoomlevel, tileIndex)
storage.invalidate(tileIndex)
return []
}
return features.filter((f) => !f.properties.id.match(/(node|way)\/-[0-9]+/))

View file

@ -92,7 +92,6 @@ export default class CreateNoteImportLayer extends Conversion<LayerConfigJson, L
this._includeClosedNotesDays +
"&bbox={x_min},{y_min},{x_max},{y_max}",
geoJsonZoomLevel: 10,
maxCacheAge: 0,
},
/* We need to set 'pass_all_features'
There are probably many note_import-layers, and we don't want the first one to gobble up all notes and then discard them...

View file

@ -135,6 +135,10 @@ export class UpdateLegacyLayer extends DesugaringStep<
delete config["rotation"]
delete config["wayHandling"]
delete config["hideUnderlayingFeaturesMinPercentage"]
const src = config.source
delete src["isOsmCache"]
delete src["maxCacheAge"]
delete src["widenFactor"]
for (const mapRenderingElement of config["mapRendering"] ?? []) {
if (mapRenderingElement["iconOverlays"] !== undefined) {

View file

@ -1622,6 +1622,18 @@ export class ValidateLayer extends Conversion<
context.enters("doCount").err("Use `isCounted` instead of `doCount`")
}
if (json.source) {
const src = json.source
if (src["isOsmCache"] !== undefined) {
context.enters("source").err("isOsmCache is deprecated")
}
if (src["maxCacheAge"] !== undefined) {
context
.enters("source")
.err("maxCacheAge is deprecated; it is " + src["maxCacheAge"])
}
}
return { raw: json, parsed: layerConfig }
}
}

View file

@ -74,15 +74,6 @@ export interface LayerConfigJson {
* Every source must set which tags have to be present in order to load the given layer.
*/
osmTags: TagConfigJson
/**
* question: How long (in seconds) is the data allowed to remain cached until it must be refreshed?
* The maximum amount of seconds that a tile is allowed to linger in the cache
*
* type: nat
* default: 30 days
* group: expert
*/
maxCacheAge?: number
}
| {
/**
@ -109,17 +100,6 @@ export interface LayerConfigJson {
* ifunset: This is not a tiled geojson
*/
geoJsonZoomLevel?: number
/**
* Indicates that the upstream geojson data is OSM-derived.
* Useful for e.g. merging or for scripts generating this cache.
* This also indicates that making changes on this data is possible
*
* question: Is this geojson a cache of OpenStreetMap data?
* ifunset: This is not an OpenStreetMap cache
* iftrue: this is based on OpenStreetMap and can thus be edited
* group: expert
*/
isOsmCache?: boolean
/**
* Some API's use a mercator-projection (EPSG:900913) instead of WGS84. Set the flag `mercatorCrs: true` in the source for this
*

View file

@ -417,14 +417,6 @@ export interface LayoutConfigJson {
*/
overpassTimeout?: number
/**
* When a query is run, the data within bounds of the visible map is loaded.
* However, users tend to pan and zoom a lot. It is pretty annoying if every single pan means a reloading of the data.
* For this, the bounds are widened in order to make a small pan still within bounds of the loaded data.
*
* IF widenfactor is 1, this feature is disabled. A recommended value is between 1 and 3
*/
widenFactor?: number
/**
* At low zoom levels, overpass is used to query features.
* At high zoom level, the OSM api is used to fetch one or more BBOX aligning with a slippy tile.

View file

@ -146,6 +146,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
* Triggered by navigating the map with arrows or by pressing 'space' or 'enter'
*/
public readonly visualFeedback: UIEventSource<boolean> = new UIEventSource<boolean>(false)
public readonly toCacheSavers: ReadonlyMap<string, SaveFeatureSourceToLocalStorage>
constructor(layout: LayoutConfig, mvtAvailableLayers: Set<string>) {
Utils.initDomPurify()
@ -295,16 +296,6 @@ export default class ThemeViewState implements SpecialVisualizationState {
)
this.perLayer = perLayer.perLayer
}
this.perLayer.forEach((fs) => {
new SaveFeatureSourceToLocalStorage(
this.osmConnection.Backend(),
fs.layer.layerDef.id,
15,
fs,
this.featureProperties,
fs.layer.layerDef.maxAgeOfCache
)
})
this.floors = this.featuresInView.features.stabilized(500).map((features) => {
if (!features) {
@ -366,6 +357,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
this.favourites = new FavouritesFeatureSource(this)
this.featureSummary = this.setupSummaryLayer()
this.toCacheSavers = this.initSaveToLocalStorage()
this.initActors()
this.drawSpecialLayers()
this.initHotkeys()
@ -391,6 +383,25 @@ export default class ThemeViewState implements SpecialVisualizationState {
})
}
public initSaveToLocalStorage() {
const toLocalStorage = new Map<string, SaveFeatureSourceToLocalStorage>()
this.perLayer.forEach((fs, layerId) => {
if (fs.layer.layerDef.source.geojsonSource !== undefined) {
return // We don't cache external data layers
}
console.log("Setting up a local store feature sink for", layerId)
const storage = new SaveFeatureSourceToLocalStorage(
this.osmConnection.Backend(),
fs.layer.layerDef.id,
LayoutSource.fromCacheZoomLevel,
fs,
this.featureProperties,
fs.layer.layerDef.maxAgeOfCache
)
toLocalStorage.set(layerId, storage)
})
return toLocalStorage
}
public showNormalDataOn(map: Store<MlMap>): ReadonlyMap<string, FilteringFeatureSource> {
const filteringFeatureSource = new Map<string, FilteringFeatureSource>()
this.perLayer.forEach((fs, layerName) => {

View file

@ -13,12 +13,15 @@
export let layer: LayerConfig
export let selectedElement: Feature
let tags: UIEventSource<Record<string, string>> = state.featureProperties.getStore(
selectedElement.properties.id
selectedElement.properties.id,
)
$: {
tags = state.featureProperties.getStore(selectedElement.properties.id)
}
let isTesting = state.featureSwitchIsTesting
let isDebugging = state.featureSwitches.featureSwitchIsDebugging
let metatags: Store<Record<string, string>> = state.userRelatedState.preferencesAsTags
</script>
@ -39,7 +42,7 @@
class="no-weblate title-icons links-as-button mr-2 flex flex-row flex-wrap items-center gap-x-0.5 pt-0.5 sm:pt-1"
>
{#each layer.titleIcons as titleIconConfig}
{#if (titleIconConfig.condition?.matchesProperties($tags) ?? true) && (titleIconConfig.metacondition?.matchesProperties( { ...$metatags, ...$tags } ) ?? true) && titleIconConfig.IsKnown($tags)}
{#if (titleIconConfig.condition?.matchesProperties($tags) ?? true) && (titleIconConfig.metacondition?.matchesProperties({ ...$metatags, ...$tags }) ?? true) && titleIconConfig.IsKnown($tags)}
<div class={titleIconConfig.renderIconClass ?? "flex h-8 w-8 items-center"}>
<TagRenderingAnswer
config={titleIconConfig}
@ -52,6 +55,10 @@
</div>
{/if}
{/each}
{#if $isTesting || $isDebugging}
<a class="subtle" href="https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Layers/{layer.id}.md" target="_blank" rel="noreferrer noopener " >{layer.id}</a>
{/if}
</div>
</div>
</div>
@ -68,7 +75,7 @@
{/if}
<style>
:global(.title-icons a) {
display: block !important;
}
:global(.title-icons a) {
display: block !important;
}
</style>

View file

@ -11,10 +11,11 @@
import Tr from "../Base/Tr.svelte"
import Translations from "../i18n/Translations"
import { Utils } from "../../Utils"
import Svg from "../../Svg"
import ToSvelte from "../Base/ToSvelte.svelte"
import { DocumentDuplicateIcon } from "@rgossiaux/svelte-heroicons/outline"
import Share from "../../assets/svg/Share.svelte"
import ToSvelte from "../Base/ToSvelte.svelte"
import Img from "../Base/Img"
import Qr from "../../Utils/Qr"
export let state: ThemeViewState
const tr = Translations.t.general.sharescreen
@ -69,22 +70,32 @@
}
</script>
<div>
<Tr t={tr.intro} />
<div class="flex">
{#if typeof navigator?.share === "function"}
<button class="h-8 w-8 shrink-0 p-1" on:click={shareCurrentLink}>
<Share />
</button>
{/if}
{#if navigator.clipboard !== undefined}
<button class="no-image-background h-8 w-8 shrink-0 p-1" on:click={copyCurrentLink}>
<DocumentDuplicateIcon />
</button>
{/if}
<div class="literal-code" on:click={(e) => Utils.selectTextIn(e.target)}>
{linkToShare}
<div class="flex flex-col">
<div class="flex justify-between items-start">
<div class="flex flex-col">
<Tr t={tr.intro} />
<div class="flex">
{#if typeof navigator?.share === "function"}
<button class="h-8 w-8 shrink-0 p-1" on:click={shareCurrentLink}>
<Share />
</button>
{/if}
{#if navigator.clipboard !== undefined}
<button class="no-image-background h-8 w-8 shrink-0 p-1" on:click={copyCurrentLink}>
<DocumentDuplicateIcon />
</button>
{/if}
<div class="literal-code" on:click={(e) => Utils.selectTextIn(e.target)}>
{linkToShare}
</div>
</div>
</div>
<ToSvelte construct={() => new Img(new Qr(linkToShare).toImageElement(125)).SetStyle(
"width: 125px"
)} />
</div>
<div class="flex justify-center">
@ -95,29 +106,31 @@
<Tr t={tr.embedIntro} />
<div class="link-underline my-1 flex flex-col">
<label>
<input bind:checked={showWelcomeMessage} type="checkbox" />
<Tr t={tr.fsWelcomeMessage} />
</label>
<div class="flex flex-col interactive p-1">
<label>
<input bind:checked={enableLogin} type="checkbox" />
<Tr t={tr.fsUserbadge} />
</label>
</div>
<div class="literal-code m-1">
&lt;span class="literal-code iframe-code-block"&gt; <br />
&lt;iframe src="{linkToShare}"
<br />
allow="geolocation" width="100%" height="100%" style="min-width: 250px; min-height: 250px"
<br />
title="{state.layout.title?.txt ?? "MapComplete"} with MapComplete"&gt;
<br />
&lt;/iframe&gt;
<br />
&lt;/span&gt;
</div>
<div class="link-underline my-1 flex flex-col">
<label>
<input bind:checked={showWelcomeMessage} type="checkbox" id="share_show_welcome" />
<Tr t={tr.fsWelcomeMessage} />
</label>
<div class="literal-code m-1">
&lt;span class="literal-code iframe-code-block"&gt; <br />
&lt;iframe src="${url}"
<br />
allow="geolocation" width="100%" height="100%" style="min-width: 250px; min-height: 250px"
<br />
title="${state.layout.title?.txt ?? "MapComplete"} with MapComplete"&gt;
<br />
&lt;/iframe&gt;
<br />
&lt;/span&gt;
<label>
<input bind:checked={enableLogin} type="checkbox" id="share_enable_login"/>
<Tr t={tr.fsUserbadge} />
</label>
</div>
</div>
<Tr t={tr.documentation} cls="link-underline" />
<Tr cls="link-underline" t={tr.documentation} />
</div>

View file

@ -276,7 +276,6 @@ class LineRenderingLayer {
},
}
const filter = img.if?.asMapboxExpression()
console.log(">>>", this._layername, imgId, img.if, "-->", filter)
if (filter) {
spec.filter = filter
}
@ -552,14 +551,13 @@ export default class ShowDataLayer {
}
private initDrawFeatures(map: MlMap) {
let { features, doShowLayer, fetchStore, selectedElement, selectedLayer } = this._options
let { features, doShowLayer, fetchStore, selectedElement } = this._options
const onClick =
this._options.onClick ??
(this._options.layer.title === undefined
? undefined
: (feature: Feature) => {
selectedElement?.setData(feature)
selectedLayer?.setData(this._options.layer)
})
if (this._options.drawLines !== false) {
for (let i = 0; i < this._options.layer.lineRendering.length; i++) {

View file

@ -62,7 +62,6 @@ describe("ReplaceGeometryAction", () => {
name: "All OSM-buildings",
source: {
osmTags: "building~*",
maxCacheAge: 0,
},
calculatedTags: ["_surface:strict:=feat.get('_surface')"],
lineRendering: [
@ -269,7 +268,6 @@ describe("ReplaceGeometryAction", () => {
"https://betadata.grbosm.site/grb?bbox={x_min},{y_min},{x_max},{y_max}",
geoJsonZoomLevel: 18,
mercatorCrs: true,
maxCacheAge: 0,
},
name: "GRB geometries",
title: "GRB outline",