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

View file

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

View file

@ -15,6 +15,7 @@ import {UIEventSource} from "../../Logic/UIEventSource";
import {FixedUiElement} from "../../UI/Base/FixedUiElement"; import {FixedUiElement} from "../../UI/Base/FixedUiElement";
import {UIElement} from "../../UI/UIElement"; import {UIElement} from "../../UI/UIElement";
import {SubstitutedTranslation} from "../../UI/SubstitutedTranslation"; import {SubstitutedTranslation} from "../../UI/SubstitutedTranslation";
import SourceConfig from "./SourceConfig";
export default class LayerConfig { export default class LayerConfig {
@ -25,7 +26,7 @@ export default class LayerConfig {
id: string; id: string;
name: Translation name: Translation
description: Translation; description: Translation;
overpassTags: TagsFilter; source: SourceConfig;
doNotDownload: boolean; doNotDownload: boolean;
passAllFeatures: boolean; passAllFeatures: boolean;
minzoom: number; minzoom: number;
@ -49,8 +50,6 @@ export default class LayerConfig {
tagRenderings: TagRenderingConfig []; tagRenderings: TagRenderingConfig [];
private readonly configuration_warnings: string[] = []
constructor(json: LayerConfigJson, constructor(json: LayerConfigJson,
context?: string) { context?: string) {
context = context + "." + json.id; context = context + "." + json.id;
@ -58,8 +57,38 @@ export default class LayerConfig {
this.id = json.id; this.id = json.id;
this.name = Translations.T(json.name, context + ".name"); this.name = Translations.T(json.name, context + ".name");
this.description = Translations.T(json.description, context + ".description"); this.description = Translations.T(json.description, context + ".description");
this.overpassTags = FromJSON.Tag(json.overpassTags, context + ".overpasstags");
this.doNotDownload = json.doNotDownload ?? 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.passAllFeatures = json.passAllFeatures ?? false;
this.minzoom = json.minzoom; this.minzoom = json.minzoom;
this.wayHandling = json.wayHandling ?? 0; this.wayHandling = json.wayHandling ?? 0;
@ -82,16 +111,15 @@ export default class LayerConfig {
if (deflt === undefined) { if (deflt === undefined) {
return 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") { if (typeof v === "string") {
const shared = SharedTagRenderings.SharedTagRendering[v]; const shared = SharedTagRenderings.SharedTagRendering[v];
if (shared) { if (shared) {
console.log("Got shared TR:", v, "-->", shared)
return 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}`; 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.title = tr("title", undefined);
this.icon = tr("icon", Img.AsData(Svg.pin)); this.icon = tr("icon", Img.AsData(Svg.pin));
this.iconOverlays = (json.iconOverlays ?? []).map((overlay, i) => { 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) { if (typeof overlay.then === "string" && SharedTagRenderings.SharedIcons[overlay.then] !== undefined) {
tr = SharedTagRenderings.SharedIcons[overlay.then]; tr = SharedTagRenderings.SharedIcons[overlay.then];
} }
@ -281,7 +309,7 @@ export default class LayerConfig {
const iconUrlStatic = render(this.icon); const iconUrlStatic = render(this.icon);
const self = this; const self = this;
var mappedHtml = tags.map(tgs => { const mappedHtml = tags.map(tgs => {
// What do you mean, 'tgs' is never read? // What do you mean, 'tgs' is never read?
// It is read implicitly in the 'render' method // It is read implicitly in the 'render' method
const iconUrl = render(self.icon); 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 * 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. * 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 {Overpass} from "../Osm/Overpass";
import Bounds from "../../Models/Bounds"; import Bounds from "../../Models/Bounds";
import FeatureSource from "../FeatureSource/FeatureSource"; import FeatureSource from "../FeatureSource/FeatureSource";
import {Utils} from "../../Utils";
export default class UpdateFromOverpass implements FeatureSource { export default class UpdateFromOverpass implements FeatureSource {
@ -71,11 +72,12 @@ export default class UpdateFromOverpass implements FeatureSource {
this.update(); this.update();
} }
private GetFilter() { private GetFilter(): Overpass {
const filters: TagsFilter[] = []; let filters: TagsFilter[] = [];
let extraScripts: string[] = [];
for (const layer of this._layoutToUse.data.layers) { for (const layer of this._layoutToUse.data.layers) {
if (typeof (layer) === "string") { if (typeof (layer) === "string") {
continue; throw "A layer was not expanded!"
} }
if (this._location.data.zoom < layer.minzoom) { if (this._location.data.zoom < layer.minzoom) {
continue; continue;
@ -102,20 +104,21 @@ export default class UpdateFromOverpass implements FeatureSource {
if (previouslyLoaded) { if (previouslyLoaded) {
continue; 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 undefined;
} }
return new Or(filters); return new Overpass(new Or(filters), extraScripts);
} }
private update(): void { private update(): void {
const filter = this.GetFilter();
if (filter === undefined) {
return;
}
if (this.runningQuery.data) { if (this.runningQuery.data) {
console.log("Still running a query, skip"); console.log("Still running a query, skip");
return; return;
@ -133,9 +136,12 @@ export default class UpdateFromOverpass implements FeatureSource {
const z = Math.floor(this._location.data.zoom ?? 0); const z = Math.floor(this._location.data.zoom ?? 0);
this.runningQuery.setData(true);
const self = this; const self = this;
const overpass = new Overpass(filter); const overpass = this.GetFilter();
if (overpass === undefined) {
return;
}
this.runningQuery.setData(true);
overpass.queryGeoJson(queryBounds, overpass.queryGeoJson(queryBounds,
function (data, date) { function (data, date) {
self._previousBounds.get(z).push(queryBounds); self._previousBounds.get(z).push(queryBounds);
@ -168,6 +174,7 @@ export default class UpdateFromOverpass implements FeatureSource {
}, 1000 }, 1000
) )
} }
countDown(); countDown();
} }

View file

@ -30,7 +30,7 @@ export default class FeatureDuplicatorPerLayer implements FeatureSource {
let foundALayer = false; let foundALayer = false;
for (const layer of layers.data) { 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; foundALayer = true;
if (layer.layerDef.passAllFeatures) { if (layer.layerDef.passAllFeatures) {

View file

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

View file

@ -2,7 +2,7 @@ import { Utils } from "../Utils";
export default class Constants { 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 // The user journey states thresholds when a new feature gets unlocked
public static userJourney = { public static userJourney = {

View file

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

View file

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

View file

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

View file

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

View file

@ -37,11 +37,13 @@
} }
], ],
"iconSize": "50,50,bottom", "iconSize": "50,50,bottom",
"overpassTags": { "source": {
"osmTags": {
"and": [ "and": [
"amenity=vending_machine", "amenity=vending_machine",
"vending~.*bicycle_tube.*" "vending~.*bicycle_tube.*"
] ]
}
}, },
"minzoom": 13, "minzoom": 13,
"wayHandling": 2, "wayHandling": 2,

View file

@ -8,7 +8,8 @@
"de": "Fahrrad-Café" "de": "Fahrrad-Café"
}, },
"minzoom": 13, "minzoom": 13,
"overpassTags": { "source": {
"osmTags": {
"and": [ "and": [
"amenity~pub|bar|cafe|restaurant", "amenity~pub|bar|cafe|restaurant",
{ {
@ -20,6 +21,7 @@
] ]
} }
] ]
}
}, },
"title": { "title": {
"render": { "render": {

View file

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

View file

@ -4,11 +4,13 @@
"en": "Monitoring stations" "en": "Monitoring stations"
}, },
"minzoom": 12, "minzoom": 12,
"overpassTags": { "source": {
"osmTags": {
"and": [ "and": [
"man_made=monitoring_station", "man_made=monitoring_station",
"monitoring:bicycle=yes" "monitoring:bicycle=yes"
] ]
}
}, },
"title": { "title": {
"render": { "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/>", "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": { "condition": {
"and": ["url~*","url:format~*"] "and": [
"url~*",
"url:format~*"
]
} }
} }
], ],

View file

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

View file

@ -8,10 +8,12 @@
"de": "Fahrradstationen (Reparatur, Pumpe oder beides)" "de": "Fahrradstationen (Reparatur, Pumpe oder beides)"
}, },
"minzoom": 13, "minzoom": 13,
"overpassTags": { "source": {
"osmTags": {
"and": [ "and": [
"amenity=bicycle_repair_station" "amenity=bicycle_repair_station"
] ]
}
}, },
"title": { "title": {
"render": { "render": {
@ -71,7 +73,8 @@
"gl": "Bomba de ar estragada", "gl": "Bomba de ar estragada",
"de": "Kaputte Pumpe" "de": "Kaputte Pumpe"
} }
},{ },
{
"if": { "if": {
"and": [ "and": [
"service:bicycle:pump=yes", "service:bicycle:pump=yes",

View file

@ -8,7 +8,8 @@
"de": "Fahrradwerkstatt/geschäft" "de": "Fahrradwerkstatt/geschäft"
}, },
"minzoom": 13, "minzoom": 13,
"overpassTags": { "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", "#": "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": [ "or": [
"shop=bicycle", "shop=bicycle",
@ -43,6 +44,7 @@
] ]
} }
] ]
}
}, },
"title": { "title": {
"render": { "render": {

View file

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

View file

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

View file

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

View file

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

View file

@ -5,7 +5,9 @@
"nl": "Witte Fietsen", "nl": "Witte Fietsen",
"de": "Geisterrad" "de": "Geisterrad"
}, },
"overpassTags": "memorial=ghost_bike", "source": {
"osmTags": "memorial=ghost_bike"
},
"minzoom": 0, "minzoom": 0,
"title": { "title": {
"render": { "render": {

View file

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

View file

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

View file

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

View file

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

View file

@ -5,11 +5,13 @@
"en": "Playgrounds" "en": "Playgrounds"
}, },
"minzoom": 13, "minzoom": 13,
"overpassTags": { "source": {
"osmTags": {
"and": [ "and": [
"leisure=playground", "leisure=playground",
"playground!=forest" "playground!=forest"
] ]
}
}, },
"description": { "description": {
"nl": "Speeltuinen", "nl": "Speeltuinen",
@ -299,7 +301,7 @@
"render": "https://upload.wikimedia.org/wikipedia/commons/0/00/Map_icons_by_Scott_de_Jonge_-_playground.svg" "render": "https://upload.wikimedia.org/wikipedia/commons/0/00/Map_icons_by_Scott_de_Jonge_-_playground.svg"
}, },
"width": { "width": {
"render": "3" "render": "1"
}, },
"iconSize": { "iconSize": {
"render": "40,40,center" "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", "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" "fr": "Une armoire ou une boite contenant des livres en libre accès"
}, },
"overpassTags": "amenity=public_bookcase", "source": {
"osmTags": "amenity=public_bookcase"
},
"minzoom": 12, "minzoom": 12,
"wayHandling": 2, "wayHandling": 2,
"title": { "title": {
@ -257,7 +259,10 @@
"fr": "Fait partie du réseau 'Little Free Library'" "fr": "Fait partie du réseau 'Little Free Library'"
}, },
"if": { "if": {
"and": ["brand=Little Free Library","nobrand="] "and": [
"brand=Little Free Library",
"nobrand="
]
} }
}, },
{ {

View file

@ -4,7 +4,8 @@
"nl": "Trage wegen" "nl": "Trage wegen"
}, },
"minzoom": 14, "minzoom": 14,
"overpassTags": { "source": {
"osmTags": {
"or": [ "or": [
"highway=pedestrian", "highway=pedestrian",
"highway=cycleway", "highway=cycleway",
@ -14,6 +15,7 @@
"highway=living_street", "highway=living_street",
"highway=track" "highway=track"
] ]
}
}, },
"title": { "title": {
"render": { "render": {

View file

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

View file

@ -5,7 +5,8 @@
"nl": "Bewakingscamera's" "nl": "Bewakingscamera's"
}, },
"minzoom": 12, "minzoom": 12,
"overpassTags": { "source": {
"osmTags": {
"and": [ "and": [
"man_made=surveillance", "man_made=surveillance",
{ {
@ -16,6 +17,7 @@
] ]
} }
] ]
}
}, },
"title": { "title": {
"render": { "render": {

View file

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

View file

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