Add possibility to use a cutom overpass script, add 'grassfields in parks'-layer

This commit is contained in:
pietervdvn 2021-03-20 23:45:52 +01:00
parent 0d51015cc8
commit f659bc1141
40 changed files with 499 additions and 222 deletions

View file

@ -28,6 +28,8 @@ import * as sport_pitch from "../assets/layers/sport_pitch/sport_pitch.json"
import * as slow_roads from "../assets/layers/slow_roads/slow_roads.json"
import LayerConfig from "./JSON/LayerConfig";
import {LayerConfigJson} from "./JSON/LayerConfigJson";
import * as grass_in_parks from "../assets/layers/village_green/grass_in_parks.json"
import * as village_green from "../assets/layers/village_green/village_green.json"
export default class AllKnownLayers {
@ -60,7 +62,9 @@ export default class AllKnownLayers {
play_forest,
playground,
sport_pitch,
slow_roads
slow_roads,
grass_in_parks,
village_green
];
// Must be below the list...

View file

@ -9,7 +9,6 @@ export class FromJSON {
const tag = Utils.SplitFirst(json, "=");
return new Tag(tag[0], tag[1]);
}
public static Tag(json: AndOrTagConfigJson | string, context: string = ""): TagsFilter {
try{
return this.TagUnsafe(json, context);

View file

@ -15,6 +15,7 @@ import {UIEventSource} from "../../Logic/UIEventSource";
import {FixedUiElement} from "../../UI/Base/FixedUiElement";
import {UIElement} from "../../UI/UIElement";
import {SubstitutedTranslation} from "../../UI/SubstitutedTranslation";
import SourceConfig from "./SourceConfig";
export default class LayerConfig {
@ -25,7 +26,7 @@ export default class LayerConfig {
id: string;
name: Translation
description: Translation;
overpassTags: TagsFilter;
source: SourceConfig;
doNotDownload: boolean;
passAllFeatures: boolean;
minzoom: number;
@ -49,8 +50,6 @@ export default class LayerConfig {
tagRenderings: TagRenderingConfig [];
private readonly configuration_warnings: string[] = []
constructor(json: LayerConfigJson,
context?: string) {
context = context + "." + json.id;
@ -58,9 +57,39 @@ export default class LayerConfig {
this.id = json.id;
this.name = Translations.T(json.name, context + ".name");
this.description = Translations.T(json.description, context + ".description");
this.overpassTags = FromJSON.Tag(json.overpassTags, context + ".overpasstags");
this.doNotDownload = json.doNotDownload ?? false,
this.passAllFeatures = json.passAllFeatures ?? false;
let legacy = undefined;
if (json["overpassTags"] !== undefined) {
// @ts-ignore
legacy = FromJSON.Tag(json["overpassTags"], context + ".overpasstags");
}
if(json.source !== undefined){
if (legacy !== undefined ) {
throw context+"Both the legacy 'layer.overpasstags' and the new 'layer.source'-field are defined"
}
let osmTags: TagsFilter = legacy;
if (json.source["osmTags"]) {
osmTags = FromJSON.Tag(json.source["osmTags"], context + "source.osmTags");
}
this.source = new SourceConfig({
osmTags: osmTags,
geojsonSource: json.source["geoJsonSource"],
overpassScript: json.source["overpassScript"],
});
}else{
this.source = new SourceConfig({
osmTags : legacy
})
}
this.doNotDownload = json.doNotDownload ?? false;
this.passAllFeatures = json.passAllFeatures ?? false;
this.minzoom = json.minzoom;
this.wayHandling = json.wayHandling ?? 0;
this.hideUnderlayingFeaturesMinPercentage = json.hideUnderlayingFeaturesMinPercentage ?? 0;
@ -82,16 +111,15 @@ export default class LayerConfig {
if (deflt === undefined) {
return undefined;
}
return new TagRenderingConfig(deflt, self.overpassTags, `${context}.${key}.default value`);
return new TagRenderingConfig(deflt, self.source.osmTags, `${context}.${key}.default value`);
}
if (typeof v === "string") {
const shared = SharedTagRenderings.SharedTagRendering[v];
if (shared) {
console.log("Got shared TR:", v, "-->", shared)
return shared;
}
}
return new TagRenderingConfig(v, self.overpassTags, `${context}.${key}`);
return new TagRenderingConfig(v, self.source.osmTags, `${context}.${key}`);
}
/**
@ -119,7 +147,7 @@ export default class LayerConfig {
}
throw `Predefined tagRendering ${renderingJson} not found in ${context}`;
}
return new TagRenderingConfig(renderingJson, self.overpassTags, `${context}.tagrendering[${i}]`);
return new TagRenderingConfig(renderingJson, self.source.osmTags, `${context}.tagrendering[${i}]`);
});
}
@ -142,7 +170,7 @@ export default class LayerConfig {
this.title = tr("title", undefined);
this.icon = tr("icon", Img.AsData(Svg.pin));
this.iconOverlays = (json.iconOverlays ?? []).map((overlay, i) => {
let tr = new TagRenderingConfig(overlay.then, self.overpassTags, `iconoverlays.${i}`);
let tr = new TagRenderingConfig(overlay.then, self.source.osmTags, `iconoverlays.${i}`);
if (typeof overlay.then === "string" && SharedTagRenderings.SharedIcons[overlay.then] !== undefined) {
tr = SharedTagRenderings.SharedIcons[overlay.then];
}
@ -281,7 +309,7 @@ export default class LayerConfig {
const iconUrlStatic = render(this.icon);
const self = this;
var mappedHtml = tags.map(tgs => {
const mappedHtml = tags.map(tgs => {
// What do you mean, 'tgs' is never read?
// It is read implicitly in the 'render' method
const iconUrl = render(self.icon);

View file

@ -26,8 +26,23 @@ export interface LayerConfigJson {
/**
* The tags to load from overpass. Either a simple 'key=value'-string, otherwise an advanced configuration
* DEPRECATED
* shorthand for source: {osmTags: "key=value"}
*/
overpassTags: AndOrTagConfigJson | string;
//overpassTags: AndOrTagConfigJson | string;
/**
* This determines where the data for the layer is fetched.
* There are some options:
*
* source: {osmTags: "key=value"} will fetch all objects with given tags from OSM. Currently, this will create a query to overpass and fetch the data - in the future this might fetch from the OSM API
* source: {geoJsonSource: "https://my.source.net/some-geo-data.geojson"} to fetch a geojson from a third party source
*
* source: {overpassScript: "<custom overpass tags>"} when you want to do special things. _This should be really rare_.
* This means that the data will be pulled from overpass with this script, and will ignore the osmTags for the query
* However, for the rest of the pipeline, the OsmTags will _still_ be used. This is important to enable layers etc...
*/
source: {osmTags: AndOrTagConfigJson | string} | {geoJsonSource: string} | {overpassScript: string}
/**
* If set, this layer will not query overpass; but it'll still match the tags above which are by chance returned by other layers.

View file

@ -0,0 +1,32 @@
import {TagsFilter} from "../../Logic/Tags";
export default class SourceConfig {
osmTags?: TagsFilter;
overpassScript?: string;
geojsonSource?: string;
constructor(params: {
osmTags?: TagsFilter,
overpassScript?: string,
geojsonSource?: string
}) {
let defined = 0;
if (params.osmTags) {
defined++;
}
if (params.overpassScript) {
defined++;
}
if (params.geojsonSource) {
defined++;
}
if (defined == 0) {
throw "Source: nothing correct defined in the source"
}
this.osmTags = params.osmTags;
this.overpassScript = params.overpassScript;
this.geojsonSource = params.geojsonSource;
}
}

View file

@ -5,6 +5,7 @@ import LayoutConfig from "../../Customizations/JSON/LayoutConfig";
import {Overpass} from "../Osm/Overpass";
import Bounds from "../../Models/Bounds";
import FeatureSource from "../FeatureSource/FeatureSource";
import {Utils} from "../../Utils";
export default class UpdateFromOverpass implements FeatureSource {
@ -71,11 +72,12 @@ export default class UpdateFromOverpass implements FeatureSource {
this.update();
}
private GetFilter() {
const filters: TagsFilter[] = [];
private GetFilter(): Overpass {
let filters: TagsFilter[] = [];
let extraScripts: string[] = [];
for (const layer of this._layoutToUse.data.layers) {
if (typeof (layer) === "string") {
continue;
throw "A layer was not expanded!"
}
if (this._location.data.zoom < layer.minzoom) {
continue;
@ -102,20 +104,21 @@ export default class UpdateFromOverpass implements FeatureSource {
if (previouslyLoaded) {
continue;
}
filters.push(layer.overpassTags);
if (layer.source.overpassScript !== undefined) {
extraScripts.push(layer.source.overpassScript)
} else {
filters.push(layer.source.osmTags);
}
}
if (filters.length === 0) {
filters = Utils.NoNull(filters)
extraScripts = Utils.NoNull(extraScripts)
if (filters.length + extraScripts.length === 0) {
return undefined;
}
return new Or(filters);
return new Overpass(new Or(filters), extraScripts);
}
private update(): void {
const filter = this.GetFilter();
if (filter === undefined) {
return;
}
if (this.runningQuery.data) {
console.log("Still running a query, skip");
return;
@ -133,9 +136,12 @@ export default class UpdateFromOverpass implements FeatureSource {
const z = Math.floor(this._location.data.zoom ?? 0);
this.runningQuery.setData(true);
const self = this;
const overpass = new Overpass(filter);
const overpass = this.GetFilter();
if (overpass === undefined) {
return;
}
this.runningQuery.setData(true);
overpass.queryGeoJson(queryBounds,
function (data, date) {
self._previousBounds.get(z).push(queryBounds);
@ -165,9 +171,10 @@ export default class UpdateFromOverpass implements FeatureSource {
self.timeout.setData(0);
self.update()
}
}, 1000
}, 1000
)
}
countDown();
}

View file

@ -30,7 +30,7 @@ export default class FeatureDuplicatorPerLayer implements FeatureSource {
let foundALayer = false;
for (const layer of layers.data) {
if (layer.layerDef.overpassTags.matchesProperties(f.feature.properties)) {
if (layer.layerDef.source.osmTags.matchesProperties(f.feature.properties)) {
foundALayer = true;
if (layer.layerDef.passAllFeatures) {

View file

@ -9,9 +9,11 @@ import Bounds from "../../Models/Bounds";
export class Overpass {
private _filter: TagsFilter
public static testUrl: string = null
private readonly _extraScripts: string[];
constructor(filter: TagsFilter) {
constructor(filter: TagsFilter, extraScripts: string[]) {
this._filter = filter
this._extraScripts = extraScripts;
}
@ -21,6 +23,9 @@ export class Overpass {
for (const filterOr of filters) {
filter += 'nwr' + filterOr + ';'
}
for (const extraScript of this._extraScripts){
filter += '('+extraScript+');';
}
const query =
'[out:json][timeout:25]' + bbox + ';(' + filter + ');out body;>;out skel qt;'
return "https://overpass-api.de/api/interpreter?data=" + encodeURIComponent(query)
@ -48,6 +53,7 @@ export class Overpass {
}
// @ts-ignore
const geojson = OsmToGeoJson.default(json);
console.log("Received geojson", geojson)
const osmTime = new Date(json.osm3s.timestamp_osm_base);
continuation(geojson, osmTime);
}).fail(onFail)

View file

@ -2,7 +2,7 @@ import { Utils } from "../Utils";
export default class Constants {
public static vNumber = "0.5.14";
public static vNumber = "0.6.0";
// The user journey states thresholds when a new feature gets unlocked
public static userJourney = {

View file

@ -6,7 +6,9 @@
"fr": "Bancs"
},
"minzoom": 14,
"overpassTags": "amenity=bench",
"source": {
"osmTags": "amenity=bench"
},
"title": {
"render": {
"en": "Bench",

View file

@ -6,11 +6,13 @@
"fr": "Bancs des arrêts de transport en commun"
},
"minzoom": 14,
"overpassTags": {
"or": [
"bench=yes",
"bench=stand_up_bench"
]
"source": {
"osmTags": {
"or": [
"bench=yes",
"bench=stand_up_bench"
]
}
},
"title": {
"render": {

View file

@ -5,7 +5,9 @@
"nl": "Picnictafels"
},
"minzoom": 12,
"overpassTags": "leisure=picnic_table",
"source": {
"osmTags": "leisure=picnic_table"
},
"title": {
"render": {
"en": "Picnic table",

View file

@ -5,7 +5,8 @@
"nl": "Fietsbibliotheek"
},
"minzoom": 8 ,
"overpassTags": "amenity=bicycle_library",
"source": {
"osmTags": "amenity=bicycle_library"},
"title": {
"render": {
"en": "Bicycle library",

View file

@ -37,11 +37,13 @@
}
],
"iconSize": "50,50,bottom",
"overpassTags": {
"and": [
"amenity=vending_machine",
"vending~.*bicycle_tube.*"
]
"source": {
"osmTags": {
"and": [
"amenity=vending_machine",
"vending~.*bicycle_tube.*"
]
}
},
"minzoom": 13,
"wayHandling": 2,
@ -104,7 +106,7 @@
"mappings": [
{
"if": "payment:coins=yes",
"ifnot": "payment:coins=no",
"ifnot": "payment:coins=no",
"then": "Payment with coins is possible"
},
{

View file

@ -8,18 +8,20 @@
"de": "Fahrrad-Café"
},
"minzoom": 13,
"overpassTags": {
"and": [
"amenity~pub|bar|cafe|restaurant",
{
"#": "Note the double tilde in 'service:bicycle' which interprets the key as regex too",
"or": [
"pub~cycling|bicycle",
"theme~cycling|bicycle",
"service:bicycle:.*~~*"
]
}
]
"source": {
"osmTags": {
"and": [
"amenity~pub|bar|cafe|restaurant",
{
"#": "Note the double tilde in 'service:bicycle' which interprets the key as regex too",
"or": [
"pub~cycling|bicycle",
"theme~cycling|bicycle",
"service:bicycle:.*~~*"
]
}
]
}
},
"title": {
"render": {

View file

@ -23,12 +23,14 @@
"render": "./assets/layers/bike_cleaning/bike_cleaning.svg"
},
"iconSize": "50,50,bottom",
"overpassTags": {
"or": [
"service:bicycle:cleaning=yes",
"service:bicycle:cleaning=diy",
"amenity=bicycle_wash"
]
"source": {
"osmTags": {
"or": [
"service:bicycle:cleaning=yes",
"service:bicycle:cleaning=diy",
"amenity=bicycle_wash"
]
}
},
"minzoom": 13,
"wayHandling": 1,

View file

@ -1,14 +1,16 @@
{
{
"id": "bike_monitoring_station",
"name": {
"en": "Monitoring stations"
},
"minzoom": 12,
"overpassTags": {
"and": [
"man_made=monitoring_station",
"monitoring:bicycle=yes"
]
"source": {
"osmTags": {
"and": [
"man_made=monitoring_station",
"monitoring:bicycle=yes"
]
}
},
"title": {
"render": {
@ -32,12 +34,15 @@
}
]
},
"tagRenderings": [ "images",
"tagRenderings": [
"images",
{
"render": "<b>{live({url},{url:format},hour)}</b> cyclists last hour<br/><b>{live({url},{url:format},day)}</b> cyclists today<br/><b>{live({url},{url:format},year)}</b> cyclists this year<br/>",
"condition": {
"and": ["url~*","url:format~*"]
"and": [
"url~*",
"url:format~*"
]
}
}
],

View file

@ -8,10 +8,12 @@
"de": "Fahrrad-Parkplätze"
},
"minzoom": 17,
"overpassTags": {
"and": [
"amenity=bicycle_parking"
]
"source": {
"osmTags": {
"and": [
"amenity=bicycle_parking"
]
}
},
"icon": {
"render": {

View file

@ -8,10 +8,12 @@
"de": "Fahrradstationen (Reparatur, Pumpe oder beides)"
},
"minzoom": 13,
"overpassTags": {
"and": [
"amenity=bicycle_repair_station"
]
"source": {
"osmTags": {
"and": [
"amenity=bicycle_repair_station"
]
}
},
"title": {
"render": {
@ -71,7 +73,8 @@
"gl": "Bomba de ar estragada",
"de": "Kaputte Pumpe"
}
},{
},
{
"if": {
"and": [
"service:bicycle:pump=yes",
@ -107,7 +110,7 @@
"titleIcons": [
{
"render": "<a href='https://fietsambassade.gent.be/' target='_blank'><img src='./assets/themes/cyclofix/fietsambassade_gent_logo_small.svg'/></a>",
"condition": "operator=De Fietsambassade Gent",
"condition": "operator=De Fietsambassade Gent",
"roaming": true
},
"defaults"

View file

@ -8,41 +8,43 @@
"de": "Fahrradwerkstatt/geschäft"
},
"minzoom": 13,
"overpassTags": {
"#": "We select all bicycle shops, sport shops (but we try to weed out non-bicycle related shops), and any shop with a bicycle related tag",
"or": [
"shop=bicycle",
{
"#": "A bicycle rental with a network is something such as villo, bluebike, ... We don't want them",
"and": [
"amenity=bicycle_rental",
"network="
]
},
{
"#": "if sport is defined and is not bicycle, it is retrackted; if bicycle retail/repair is marked as 'no', it is retracted too.",
"##": "There will be a few false-positives with this. They will get filtered out by people marking both 'not selling bikes' and 'not repairing bikes'. Furthermore, the OSMers will add a sports-subcategory on it",
"and": [
"shop=sports",
"service:bicycle:retail!=no",
"service:bicycle:repair!=no",
{
"or": [
"sport=bicycle",
"sport=cycling",
"sport="
]
}
]
},
{
"#": "Any shop with any bicycle service",
"and": [
"shop~*",
"service:bicycle:.*~~.*"
]
}
]
"source": {
"osmTags": {
"#": "We select all bicycle shops, sport shops (but we try to weed out non-bicycle related shops), and any shop with a bicycle related tag",
"or": [
"shop=bicycle",
{
"#": "A bicycle rental with a network is something such as villo, bluebike, ... We don't want them",
"and": [
"amenity=bicycle_rental",
"network="
]
},
{
"#": "if sport is defined and is not bicycle, it is retrackted; if bicycle retail/repair is marked as 'no', it is retracted too.",
"##": "There will be a few false-positives with this. They will get filtered out by people marking both 'not selling bikes' and 'not repairing bikes'. Furthermore, the OSMers will add a sports-subcategory on it",
"and": [
"shop=sports",
"service:bicycle:retail!=no",
"service:bicycle:repair!=no",
{
"or": [
"sport=bicycle",
"sport=cycling",
"sport="
]
}
]
},
{
"#": "Any shop with any bicycle service",
"and": [
"shop~*",
"service:bicycle:.*~~.*"
]
}
]
}
},
"title": {
"render": {
@ -575,7 +577,7 @@
"badge": true
},
{
"if": "service:bicycle:pump=yes",
"if": "service:bicycle:pump=yes",
"then": "circle:#e2783d;./assets/layers/bike_repair_station/pump.svg",
"badge": true
}

View file

@ -4,10 +4,12 @@
"nl": "Vogelkijkhutten"
},
"minzoom": 14,
"overpassTags": {
"and": [
"leisure=bird_hide"
]
"source": {
"osmTags": {
"and": [
"leisure=bird_hide"
]
}
},
"title": {
"render": {

View file

@ -7,14 +7,16 @@
"de": "Mit Fahrrad zusammenhängendes Objekt"
},
"minzoom": 13,
"overpassTags": {
"or": [
"theme~cycling|bicycle",
"sport=cycling",
"association~cycling|bicycle",
"ngo~cycling|bicycle",
"club~bicycle|cycling"
]
"source": {
"osmTags": {
"or": [
"theme~cycling|bicycle",
"sport=cycling",
"association~cycling|bicycle",
"ngo~cycling|bicycle",
"club~bicycle|cycling"
]
}
},
"title": {
"render": {

View file

@ -4,11 +4,13 @@
"en": "Direction visualization"
},
"minzoom": 16,
"overpassTags": {
"or": [
"camera:direction~*",
"direction~*"
]
"source": {
"osmTags": {
"or": [
"camera:direction~*",
"direction~*"
]
}
},
"doNotDownload": true,
"passAllFeatures": true,

View file

@ -31,14 +31,15 @@
"badge": true
}
],
"iconSize": "40,40,bottom",
"overpassTags": {
"and": [
"amenity=drinking_water",
"access!=permissive",
"access!=private"
]
"source": {
"osmTags": {
"and": [
"amenity=drinking_water",
"access!=permissive",
"access!=private"
]
}
},
"minzoom": 13,
"wayHandling": 1,

View file

@ -5,7 +5,9 @@
"nl": "Witte Fietsen",
"de": "Geisterrad"
},
"overpassTags": "memorial=ghost_bike",
"source": {
"osmTags": "memorial=ghost_bike"
},
"minzoom": 0,
"title": {
"render": {
@ -43,7 +45,7 @@
}
],
"tagRenderings": [
{
{
"render": {
"en": "A <b>ghost bike</b> is a memorial for a cyclist who died in a traffic accident, in the form of a white bicycle placed permanently near the accident location.",
"nl": "Een Witte Fiets (of Spookfiets) is een aandenken aan een fietser die bij een verkeersongeval om het leven kwam. Het gaat over een witgeschilderde fiets die geplaatst werd in de buurt van het ongeval.",

View file

@ -5,10 +5,12 @@
"en": "Information boards"
},
"minzoom": 12,
"overpassTags": {
"and": [
"information=board"
]
"source": {
"osmTags": {
"and": [
"information=board"
]
}
},
"title": {
"render": {
@ -16,7 +18,9 @@
"en": "Information board"
}
},
"tagRenderings": [ "images"],
"tagRenderings": [
"images"
],
"hideUnderlayingFeaturesMinPercentage": 0,
"icon": {
"render": "./assets/layers/information_board/board.svg"

View file

@ -5,11 +5,13 @@
"nl": "Kaarten"
},
"minzoom": 12,
"overpassTags": {
"or": [
"tourism=map",
"information=map"
]
"source": {
"osmTags": {
"or": [
"tourism=map",
"information=map"
]
}
},
"title": {
"render": {

View file

@ -4,11 +4,13 @@
"nl": "Natuurgebied"
},
"minzoom": 12,
"overpassTags": {
"or": [
"leisure=nature_reserve",
"boundary=protected_area"
]
"source": {
"osmTags": {
"or": [
"leisure=nature_reserve",
"boundary=protected_area"
]
}
},
"title": {
"render": {
@ -330,7 +332,8 @@
"key": "description:0"
}
},
{"#": "Surface are",
{
"#": "Surface are",
"render": {
"en": "Surface area: {_surface:ha}Ha",
"mappings": {

View file

@ -4,10 +4,12 @@
"nl": "Speelbossen"
},
"minzoom": 13,
"overpassTags": {
"and": [
"playground=forest"
]
"source": {
"osmTags": {
"and": [
"playground=forest"
]
}
},
"title": {
"render": {

View file

@ -5,11 +5,13 @@
"en": "Playgrounds"
},
"minzoom": 13,
"overpassTags": {
"and": [
"leisure=playground",
"playground!=forest"
]
"source": {
"osmTags": {
"and": [
"leisure=playground",
"playground!=forest"
]
}
},
"description": {
"nl": "Speeltuinen",
@ -299,7 +301,7 @@
"render": "https://upload.wikimedia.org/wikipedia/commons/0/00/Map_icons_by_Scott_de_Jonge_-_playground.svg"
},
"width": {
"render": "3"
"render": "1"
},
"iconSize": {
"render": "40,40,center"

View file

@ -12,7 +12,9 @@
"de": "Ein Bücherschrank am Straßenrand mit Büchern, für jedermann zugänglich",
"fr": "Une armoire ou une boite contenant des livres en libre accès"
},
"overpassTags": "amenity=public_bookcase",
"source": {
"osmTags": "amenity=public_bookcase"
},
"minzoom": 12,
"wayHandling": 2,
"title": {
@ -256,9 +258,12 @@
"de": "Teil des Netzwerks 'Little Free Library'",
"fr": "Fait partie du réseau 'Little Free Library'"
},
"if":{
"and": ["brand=Little Free Library","nobrand="]
}
"if": {
"and": [
"brand=Little Free Library",
"nobrand="
]
}
},
{
"if": {

View file

@ -4,16 +4,18 @@
"nl": "Trage wegen"
},
"minzoom": 14,
"overpassTags": {
"or": [
"highway=pedestrian",
"highway=cycleway",
"highway=footway",
"highway=path",
"highway=bridleway",
"highway=living_street",
"highway=track"
]
"source": {
"osmTags": {
"or": [
"highway=pedestrian",
"highway=cycleway",
"highway=footway",
"highway=path",
"highway=bridleway",
"highway=living_street",
"highway=track"
]
}
},
"title": {
"render": {

View file

@ -5,10 +5,11 @@
},
"wayHandling": 2,
"minzoom": 12,
"overpassTags": {
"source": {
"osmTags": {
"and": [
"leisure=pitch"
]
]}
},
"title": {
"render": {
@ -211,13 +212,13 @@
"render": "./assets/layers/sport_pitch/tabletennis.svg"
},
"width": {
"render": "8"
"render": "1"
},
"iconSize": {
"render": "40,40,center"
},
"color": {
"render": "#00f"
"render": "#009"
},
"presets": [
{

View file

@ -5,17 +5,19 @@
"nl": "Bewakingscamera's"
},
"minzoom": 12,
"overpassTags": {
"and": [
"man_made=surveillance",
{
"or": [
"surveillance:type=camera",
"surveillance:type=ALPR",
"surveillance:type=ANPR"
]
}
]
"source": {
"osmTags": {
"and": [
"man_made=surveillance",
{
"or": [
"surveillance:type=camera",
"surveillance:type=ALPR",
"surveillance:type=ANPR"
]
}
]
}
},
"title": {
"render": {

View file

@ -5,7 +5,9 @@
"de": "Toiletten",
"fr": "Toilettes"
},
"overpassTags": "amenity=toilets",
"source": {
"osmTags": "amenity=toilets"
},
"title": {
"render": {
"en": "Toilet",

View file

@ -5,8 +5,12 @@
"en": "Tree"
},
"minzoom": 14,
"overpassTags": {
"and": ["natural=tree"]
"source": {
"osmTags": {
"and": [
"natural=tree"
]
}
},
"title": {
"render": {
@ -38,7 +42,9 @@
"mappings": [
{
"if": {
"and": ["height~^[0-9.]+$"]
"and": [
"height~^[0-9.]+$"
]
},
"then": {
"nl": "Hoogte: {height}&nbsp;m",
@ -55,7 +61,9 @@
"mappings": [
{
"if": {
"and": ["leaf_type=broadleaved"]
"and": [
"leaf_type=broadleaved"
]
},
"then": {
"nl": "<img src=\"./assets/themes/trees/broadleaved.svg\" style=\"width:1.5em;height:1.5em\" alt=\"\"/> Loofboom",
@ -64,7 +72,9 @@
},
{
"if": {
"and": ["leaf_type=needleleaved"]
"and": [
"leaf_type=needleleaved"
]
},
"then": {
"nl": "<img src=\"./assets/themes/trees/needleleaved.svg\" style=\"width:1.5em;height:1.5em\" alt=\"\"/> Naaldboom",
@ -73,7 +83,9 @@
},
{
"if": {
"and": ["leaf_type=leafless"]
"and": [
"leaf_type=leafless"
]
},
"then": {
"nl": "<img src=\"./assets/themes/trees/leafless.svg\" style=\"width:1.5em;height:1.5em\" alt=\"\"/> Permanent bladloos",
@ -91,7 +103,9 @@
"mappings": [
{
"if": {
"and": ["denotation=landmark"]
"and": [
"denotation=landmark"
]
},
"then": {
"nl": "De boom valt op door zijn grootte of prominente locatie. Hij is nuttig voor navigatie.",
@ -100,7 +114,9 @@
},
{
"if": {
"and": ["denotation=natural_monument"]
"and": [
"denotation=natural_monument"
]
},
"then": {
"nl": "De boom is een natuurlijk monument, bijvoorbeeld doordat hij bijzonder oud of van een waardevolle soort is.",
@ -109,7 +125,9 @@
},
{
"if": {
"and": ["denotation=agricultural"]
"and": [
"denotation=agricultural"
]
},
"then": {
"nl": "De boom wordt voor landbouwdoeleinden gebruikt, bijvoorbeeld in een boomgaard.",
@ -118,7 +136,9 @@
},
{
"if": {
"and": ["denotation=park"]
"and": [
"denotation=park"
]
},
"then": {
"nl": "De boom staat in een park of dergelijke (begraafplaats, schoolterrein, …).",
@ -127,7 +147,9 @@
},
{
"if": {
"and": ["denotation=garden"]
"and": [
"denotation=garden"
]
},
"then": {
"nl": "De boom staat in de tuin bij een woning/flatgebouw.",
@ -136,7 +158,9 @@
},
{
"if": {
"and": ["denotation=avenue"]
"and": [
"denotation=avenue"
]
},
"then": {
"nl": "Dit is een laanboom.",
@ -145,7 +169,9 @@
},
{
"if": {
"and": ["denotation=urban"]
"and": [
"denotation=urban"
]
},
"then": {
"nl": "De boom staat in een woonkern.",
@ -154,7 +180,9 @@
},
{
"if": {
"and": ["denotation=none"]
"and": [
"denotation=none"
]
},
"then": {
"nl": "De boom staat buiten een woonkern.",
@ -171,7 +199,9 @@
"mappings": [
{
"if": {
"and": ["leaf_cycle=deciduous"]
"and": [
"leaf_cycle=deciduous"
]
},
"then": {
"nl": "Bladverliezend: de boom is een periode van het jaar kaal.",
@ -180,7 +210,9 @@
},
{
"if": {
"and": ["leaf_cycle=evergreen"]
"and": [
"leaf_cycle=evergreen"
]
},
"then": {
"nl": "Groenblijvend.",
@ -189,7 +221,9 @@
}
],
"condition": {
"and": ["leaf_type!~^leafless$"]
"and": [
"leaf_type!~^leafless$"
]
}
},
{
@ -351,13 +385,17 @@
"mappings": [
{
"if": {
"and": ["leaf_type=broadleaved"]
"and": [
"leaf_type=broadleaved"
]
},
"then": "circle:#ffffff;./assets/themes/trees/broadleaved.svg"
},
{
"if": {
"and": ["leaf_type=needleleaved"]
"and": [
"leaf_type=needleleaved"
]
},
"then": "circle:#ffffff;./assets/themes/trees/needleleaved.svg"
}

View file

@ -10,7 +10,9 @@
"nl": "Een mooi uitzicht - ideaal om een foto toe te voegen wanneer iets niet in een andere categorie past",
"de": "Ein schöner Aussichtspunkt oder eine schöne Aussicht. Ideal zum Hinzufügen eines Bildes, wenn keine andere Kategorie passt"
},
"overpassTags": "tourism=viewpoint",
"source": {
"osmTags": "tourism=viewpoint"
},
"minzoom": 14,
"icon": "./assets/layers/viewpoint/viewpoint.svg",
"iconSize": "20,20,center",

View file

@ -0,0 +1,48 @@
{
"id": "grass_in_parks",
"name": {
"nl": "Toegankelijke grasvelden in parken"
},
"source": {
"osmTags": {
"and": [
"landuse=grass",
{
"or": [
"access=public",
"access=yes"
]
}
]
},
"overpassScript": "way[\"leisure\"=\"park\"];node(w);is_in;area._[\"leisure\"=\"park\"];(way(area)[\"landuse\"=\"grass\"]; node(w); );"
},
"minzoom": 0,
"title": {
"render": {
"nl": "Speelweide in een park"
},
"mappings": [
{
"if": "name~*",
"then": {
"nl": "{name}"
}
}
]
},
"icon": "./assets/themes/playgrounds/playground.svg",
"iconSize": "40,40,bottom",
"width": "1",
"color": "#0f0",
"wayHandling": 2,
"tagRenderings": [
"images",
{
"render": "Op dit grasveld in het park mag je spelen, picnicken, zitten, ..."
},
{
"render": "{reviews(name, landuse=grass )}"
}
]
}

View file

@ -0,0 +1,37 @@
{
"id": "village_green",
"name": {
"nl": "Speelweide"
},
"source": {
"osmTags": "landuse=village_green"
},
"minzoom": 0,
"title": {
"render": {
"nl": "Speelweide"
},
"mappings": [
{
"if": "name~*",
"then": {
"nl": "{name}"
}
}
]
},
"icon": "./assets/themes/playgrounds/playground.svg",
"iconSize": "40,40,bottom",
"width": "1",
"color": "#0f0",
"wayHandling": 2,
"tagRenderings": [
"images",
{
"render": "Dit is een klein stukje openbaar groen waar je mag spelen, picnicken, zitten, ..."
},
{
"render": "{reviews(name, landuse=village_green )}"
}
]
}

View file

@ -27,7 +27,9 @@
"play_forest",
"playground",
"sport_pitch",
"slow_roads"
"slow_roads",
"grass_in_parks",
"village_green"
],
"roamingRenderings": []
}