Add switch to hide certain features, cleanup of code

This commit is contained in:
pietervdvn 2021-03-25 15:19:44 +01:00
parent aa0989b72a
commit 1b1ec9f15d
18 changed files with 230 additions and 173 deletions

View file

@ -24,6 +24,7 @@ export default class LayerConfig {
static WAYHANDLING_DEFAULT = 0; static WAYHANDLING_DEFAULT = 0;
static WAYHANDLING_CENTER_ONLY = 1; static WAYHANDLING_CENTER_ONLY = 1;
static WAYHANDLING_CENTER_AND_WAY = 2; static WAYHANDLING_CENTER_AND_WAY = 2;
id: string; id: string;
name: Translation name: Translation
description: Translation; description: Translation;
@ -31,6 +32,7 @@ export default class LayerConfig {
calculatedTags: [string, string][] calculatedTags: [string, string][]
doNotDownload: boolean; doNotDownload: boolean;
passAllFeatures: boolean; passAllFeatures: boolean;
isShown: TagRenderingConfig;
minzoom: number; minzoom: number;
maxzoom: number; maxzoom: number;
title?: TagRenderingConfig; title?: TagRenderingConfig;
@ -205,6 +207,7 @@ export default class LayerConfig {
throw "Builtin SVG asset not found: " + iconPath throw "Builtin SVG asset not found: " + iconPath
} }
} }
this.isShown = tr("isShown", "yes");
this.iconSize = tr("iconSize", "40,40,center"); this.iconSize = tr("iconSize", "40,40,center");
this.color = tr("color", "#0000ff"); this.color = tr("color", "#0000ff");
this.width = tr("width", "7"); this.width = tr("width", "7");

View file

@ -1,5 +1,6 @@
import {TagRenderingConfigJson} from "./TagRenderingConfigJson"; import {TagRenderingConfigJson} from "./TagRenderingConfigJson";
import {AndOrTagConfigJson} from "./TagConfigJson"; import {AndOrTagConfigJson} from "./TagConfigJson";
import TagRenderingConfig from "./TagRenderingConfig";
/** /**
* Configuration for a single layer * Configuration for a single layer
@ -51,7 +52,15 @@ export interface LayerConfigJson {
* Works well together with 'passAllFeatures', to add decoration * Works well together with 'passAllFeatures', to add decoration
*/ */
doNotDownload?: boolean; doNotDownload?: boolean;
/**
* This tagrendering should either be 'yes' or 'no'. If 'no' is returned, then the feature will be hidden from view.
* This is useful to hide certain features from view
* The default value is 'yes'
*/
isShown?: TagRenderingConfigJson;
/** /**
* The zoomlevel at which point the data is shown and loaded. * The zoomlevel at which point the data is shown and loaded.
* Default: 0 * Default: 0

View file

@ -384,26 +384,7 @@ export class InitUiElements {
State.state.layerUpdater = updater; State.state.layerUpdater = updater;
const source = new FeaturePipeline(state.filteredLayers, updater, state.layoutToUse, state.changes, state.locationControl); const source = new FeaturePipeline(state.filteredLayers, updater, state.layoutToUse, state.changes, state.locationControl);
new ShowDataLayer(source.features, State.state.leafletMap, State.state.layoutToUse);
source.features.addCallbackAndRun((featuresFreshness: { feature: any, freshness: Date }[]) => {
if (featuresFreshness === undefined) {
return;
}
featuresFreshness.forEach(featureFresh => {
const feature = featureFresh.feature;
State.state.allElements.addOrGetElement(feature);
if (Hash.hash.data === feature.properties.id) {
State.state.selectedElement.setData(feature);
}
})
MetaTagging.addMetatags(featuresFreshness, state.layoutToUse.data.layers);
})
new ShowDataLayer(source.features, State.state.leafletMap,
State.state.layoutToUse);
new SelectedFeatureHandler(Hash.hash, State.state.selectedElement, source); new SelectedFeatureHandler(Hash.hash, State.state.selectedElement, source);

View file

@ -43,7 +43,7 @@ class TitleElement extends UIElement {
} }
if (layer.source.osmTags.matchesProperties(properties)) { if (layer.source.osmTags.matchesProperties(properties)) {
const title = new TagRenderingAnswer( const title = new TagRenderingAnswer(
this._allElementsStorage.getEventSourceFor(feature), this._allElementsStorage.addOrGetElement(feature),
layer.title layer.title
) )
return new Combine([defaultTitle, " | ", title]).Render(); return new Combine([defaultTitle, " | ", title]).Render();

View file

@ -15,30 +15,42 @@ export class ElementStorage {
this._elements[id] = eventSource; this._elements[id] = eventSource;
} }
addElement(element): UIEventSource<any> { /**
const eventSource = new UIEventSource<any>(element.properties, "tags of "+element.properties.id); * Creates a UIEventSource for the tags of the given feature.
this._elements[element.properties.id] = eventSource; * If an UIEventsource has been created previously, the same UIEventSource will be returned
return eventSource; *
} * Note: it will cleverly merge the tags, if needed
*/
addOrGetElement(element: any) : UIEventSource<any>{ addOrGetElement(feature: any): UIEventSource<any> {
const elementId = element.properties.id; const elementId = feature.properties.id;
if (elementId in this._elements) { if (elementId in this._elements) {
const es = this._elements[elementId]; const es = this._elements[elementId];
if (es.data == feature.properties) {
// Reference comparison gives the same object! we can just return the event source
return es;
}
const keptKeys = es.data; const keptKeys = es.data;
// The element already exists // The element already exists
// We add all the new keys to the old keys // We add all the new keys to the old keys
for (const k in element.properties) { let somethingChanged = false;
const v = element.properties[k]; for (const k in feature.properties) {
const v = feature.properties[k];
if (keptKeys[k] !== v) { if (keptKeys[k] !== v) {
keptKeys[k] = v; keptKeys[k] = v;
es.ping(); somethingChanged = true;
} }
} }
if (somethingChanged) {
es.ping();
}
return es; return es;
}else{ } else {
return this.addElement(element); const eventSource = new UIEventSource<any>(feature.properties, "tags of " + feature.properties.id);
this._elements[feature.properties.id] = eventSource;
return eventSource;
} }
} }
@ -48,8 +60,4 @@ export class ElementStorage {
} }
console.error("Can not find eventsource with id ", elementId); console.error("Can not find eventsource with id ", elementId);
} }
getEventSourceFor(feature): UIEventSource<any> {
return this.getEventSourceById(feature.properties.id);
}
} }

81
Logic/ExtraFunction.ts Normal file
View file

@ -0,0 +1,81 @@
import {GeoOperations} from "./GeoOperations";
import {UIElement} from "../UI/UIElement";
import Combine from "../UI/Base/Combine";
export class ExtraFunction {
private static DistanceToFunc = new ExtraFunction(
"distanceTo",
"Calculates the distance between the feature and a specified point",
["longitude", "latitude"],
(feature) => {
return (lon, lat) => {
// Feature._lon and ._lat is conveniently place by one of the other metatags
return GeoOperations.distanceBetween([lon, lat], [feature._lon, feature._lat]);
}
}
)
private static readonly allFuncs: ExtraFunction[] = [ExtraFunction.DistanceToFunc];
private readonly _name: string;
private readonly _args: string[];
private readonly _doc: string;
private readonly _f: (feat: any) => any;
constructor(name: string, doc: string, args: string[], f: ((feat: any) => any)) {
this._name = name;
this._doc = doc;
this._args = args;
this._f = f;
}
public static FullPatchFeature(feature) {
for (const func of ExtraFunction.allFuncs) {
func.PatchFeature(feature);
}
}
public static HelpText(): UIElement {
return new Combine([
ExtraFunction.intro,
...ExtraFunction.allFuncs.map(func =>
new Combine([
"<h3>" + func._name + "</h3>",
func._doc,
"<ul>",
...func._args.map(arg => "<li>" + arg + "</li>"),
"</ul>"
])
)
]);
}
public PatchFeature(feature: any) {
feature[this._name] = this._f(feature);
}
static readonly intro = `<h2>Calculating tags with Javascript</h2>
<p>In some cases, it is useful to have some tags calculated based on other properties. Some useful tags are available by default (e.g. <b>_lat</b>, <b>lon</b>, <b>_country</b>), as detailed above.</p>
<p>It is also possible to calculate your own tags - but this requires some javascript knowledge. </p>
Before proceeding, some warnings:
<ul>
<li> DO NOT DO THIS AS BEGINNER</li>
<li> <b>Only do this if all other techniques fail</b>. This should <i>not</i> be done to create a rendering effect, only to calculate a specific value</li>
<li> <b>THIS MIGHT BE DISABLED WITHOUT ANY NOTICE ON UNOFFICIAL THEMES</b>. As unofficial themes might be loaded from the internet, this is the equivalent of injecting arbitrary code into the client. It'll be disabled if abuse occurs.</li>
</ul>
In the layer object, add a field <b>calculatedTags</b>, e.g.:
<div class="code">
"calculatedTags": {
"_someKey": "javascript-expression",
"name": "feat.properties.name ?? feat.properties.ref ?? feat.properties.operator",
"_distanceCloserThen3Km": "feat.distanceTo( some_lon, some_lat) < 3 ? 'yes' : 'no'"
}
</div>
`
}

View file

@ -6,7 +6,7 @@ import LayerConfig from "../../Customizations/JSON/LayerConfig";
/** /**
* In some rare cases, some elements are shown on multiple layers (when 'passthrough' is enabled) * In some rare cases, some elements are shown on multiple layers (when 'passthrough' is enabled)
* If this is the case, multiple objects with a different _matching_layer_id are generated. * If this is the case, multiple objects with a different _matching_layer_id are generated.
* If not, the _feature_layter_id is added * In any case, this featureSource marks the objects with _matching_layer_id
*/ */
export default class FeatureDuplicatorPerLayer implements FeatureSource { export default class FeatureDuplicatorPerLayer implements FeatureSource {
public readonly features: UIEventSource<{ feature: any; freshness: Date }[]>; public readonly features: UIEventSource<{ feature: any; freshness: Date }[]>;

View file

@ -12,6 +12,7 @@ import LocalStorageSource from "./LocalStorageSource";
import LayoutConfig from "../../Customizations/JSON/LayoutConfig"; import LayoutConfig from "../../Customizations/JSON/LayoutConfig";
import Loc from "../../Models/Loc"; import Loc from "../../Models/Loc";
import GeoJsonSource from "./GeoJsonSource"; import GeoJsonSource from "./GeoJsonSource";
import MetaTaggingFeatureSource from "./MetaTaggingFeatureSource";
export default class FeaturePipeline implements FeatureSource { export default class FeaturePipeline implements FeatureSource {
@ -25,42 +26,42 @@ export default class FeaturePipeline implements FeatureSource {
const amendedOverpassSource = const amendedOverpassSource =
new RememberingSource( new RememberingSource(
new WayHandlingApplyingFeatureSource(flayers, new NoOverlapSource(flayers, new FeatureDuplicatorPerLayer(flayers,
new NoOverlapSource(flayers, new FeatureDuplicatorPerLayer(flayers, new LocalStorageSaver(updater, layout)))
new LocalStorageSaver(updater, layout)))
)
); );
const geojsonSources: GeoJsonSource [] = [] const geojsonSources: GeoJsonSource [] = []
for (const flayer of flayers.data) { for (const flayer of flayers.data) {
const sourceUrl = flayer.layerDef.source.geojsonSource const sourceUrl = flayer.layerDef.source.geojsonSource
if (sourceUrl !== undefined) { if (sourceUrl !== undefined) {
geojsonSources.push(new WayHandlingApplyingFeatureSource(flayers, geojsonSources.push(
new GeoJsonSource(flayer.layerDef.id, sourceUrl))) new GeoJsonSource(flayer.layerDef.id, sourceUrl))
} }
} }
const amendedLocalStorageSource = const amendedLocalStorageSource =
new RememberingSource( new RememberingSource(
new WayHandlingApplyingFeatureSource(flayers, new NoOverlapSource(flayers, new FeatureDuplicatorPerLayer(flayers, new LocalStorageSource(layout)))
new NoOverlapSource(flayers, new FeatureDuplicatorPerLayer(flayers, new LocalStorageSource(layout))) );
));
newPoints = new FeatureDuplicatorPerLayer(flayers, newPoints); newPoints = new FeatureDuplicatorPerLayer(flayers, newPoints);
const merged = new FeatureSourceMerger([ const merged =
amendedOverpassSource, new MetaTaggingFeatureSource(
amendedLocalStorageSource, new FeatureSourceMerger([
newPoints, amendedOverpassSource,
...geojsonSources amendedLocalStorageSource,
]); newPoints,
...geojsonSources
]));
const source = const source =
new FilteringFeatureSource( new WayHandlingApplyingFeatureSource(flayers,
flayers, new FilteringFeatureSource(
locationControl, flayers,
merged locationControl,
); merged
));
this.features = source.features; this.features = source.features;
} }

View file

@ -29,6 +29,7 @@ export default class FilteringFeatureSource implements FeatureSource {
const newFeatures = features.filter(f => { const newFeatures = features.filter(f => {
const layerId = f.feature._matching_layer_id; const layerId = f.feature._matching_layer_id;
if (layerId !== undefined) { if (layerId !== undefined) {
const layer: { const layer: {
isDisplayed: UIEventSource<boolean>, isDisplayed: UIEventSource<boolean>,
@ -38,6 +39,17 @@ export default class FilteringFeatureSource implements FeatureSource {
console.error("No layer found with id ", layerId); console.error("No layer found with id ", layerId);
return true; return true;
} }
const isShown = layer.layerDef.isShown
const tags = f.feature.properties;
console.log("Is shown: ", isShown," known? ", isShown.IsKnown(tags), " result: ", isShown.GetRenderValue(tags).txt)
if(isShown.IsKnown(tags)){
const result = layer.layerDef.isShown.GetRenderValue(f.feature.properties).txt;
if(result !== "yes"){
return false;
}
}
if (FilteringFeatureSource.showLayer(layer, location)) { if (FilteringFeatureSource.showLayer(layer, location)) {
return true; return true;
} }

View file

@ -0,0 +1,30 @@
import FeatureSource from "./FeatureSource";
import {UIEventSource} from "../UIEventSource";
import State from "../../State";
import Hash from "../Web/Hash";
import MetaTagging from "../MetaTagging";
export default class MetaTaggingFeatureSource implements FeatureSource {
features: UIEventSource<{ feature: any; freshness: Date }[]> = new UIEventSource<{feature: any; freshness: Date}[]>(undefined);
constructor(source: FeatureSource) {
const self = this;
source.features.addCallbackAndRun((featuresFreshness: { feature: any, freshness: Date }[]) => {
if (featuresFreshness === undefined) {
return;
}
featuresFreshness.forEach(featureFresh => {
const feature = featureFresh.feature;
State.state.allElements.addOrGetElement(feature);
if (Hash.hash.data === feature.properties.id) {
State.state.selectedElement.setData(feature);
}
})
MetaTagging.addMetatags(featuresFreshness, State.state.layoutToUse.data.layers);
self.features.setData(featuresFreshness);
});
}
}

View file

@ -3,6 +3,9 @@ import {UIEventSource} from "../UIEventSource";
import LayerConfig from "../../Customizations/JSON/LayerConfig"; import LayerConfig from "../../Customizations/JSON/LayerConfig";
import {GeoOperations} from "../GeoOperations"; import {GeoOperations} from "../GeoOperations";
/**
* This is the part of the pipeline which introduces extra points at the center of an area (but only if this is demanded by the wayhandling)
*/
export default class WayHandlingApplyingFeatureSource implements FeatureSource { export default class WayHandlingApplyingFeatureSource implements FeatureSource {
features: UIEventSource<{ feature: any; freshness: Date }[]>; features: UIEventSource<{ feature: any; freshness: Date }[]>;
@ -46,6 +49,7 @@ export default class WayHandlingApplyingFeatureSource implements FeatureSource {
continue; continue;
} }
// Create the copy
const centerPoint = GeoOperations.centerpoint(feat); const centerPoint = GeoOperations.centerpoint(feat);
centerPoint._matching_layer_id = feat._matching_layer_id; centerPoint._matching_layer_id = feat._matching_layer_id;
newFeatures.push({feature: centerPoint, freshness: f.freshness}); newFeatures.push({feature: centerPoint, freshness: f.freshness});

View file

@ -1,85 +1,6 @@
import {GeoOperations} from "./GeoOperations";
import LayerConfig from "../Customizations/JSON/LayerConfig"; import LayerConfig from "../Customizations/JSON/LayerConfig";
import SimpleMetaTagger from "./SimpleMetaTagger"; import SimpleMetaTagger from "./SimpleMetaTagger";
import {UIElement} from "../UI/UIElement"; import {ExtraFunction} from "./ExtraFunction";
import Combine from "../UI/Base/Combine";
export class ExtraFunction {
static readonly intro = `<h2>Calculating tags with Javascript</h2>
<p>In some cases, it is useful to have some tags calculated based on other properties. Some useful tags are available by default (e.g. <b>_lat</b>, <b>lon</b>, <b>_country</b>), as detailed above.</p>
<p>It is also possible to calculate your own tags - but this requires some javascript knowledge. </p>
Before proceeding, some warnings:
<ul>
<li> DO NOT DO THIS AS BEGINNER</li>
<li> <b>Only do this if all other techniques fail</b>. This should <i>not</i> be done to create a rendering effect, only to calculate a specific value</li>
<li> <b>THIS MIGHT BE DISABLED WITHOUT ANY NOTICE ON UNOFFICIAL THEMES</b>. As unofficial themes might be loaded from the internet, this is the equivalent of injecting arbitrary code into the client. It'll be disabled if abuse occurs.</li>
</ul>
In the layer object, add a field <b>calculatedTags</b>, e.g.:
<div class="code">
"calculatedTags": {
"_someKey": "javascript-expression",
"name": "feat.properties.name ?? feat.properties.ref ?? feat.properties.operator",
"_distanceCloserThen3Km": "feat.distanceTo( some_lon, some_lat) < 3 ? 'yes' : 'no'"
}
</div>
`
private static DistanceToFunc = new ExtraFunction(
"distanceTo",
"Calculates the distance between the feature and a specified point",
["longitude", "latitude"],
(feature) => {
return (lon, lat) => {
// Feature._lon and ._lat is conveniently place by one of the other metatags
return GeoOperations.distanceBetween([lon, lat], [feature._lon, feature._lat]);
}
}
)
private static readonly allFuncs: ExtraFunction[] = [ExtraFunction.DistanceToFunc];
private readonly _name: string;
private readonly _args: string[];
private readonly _doc: string;
private readonly _f: (feat: any) => any;
constructor(name: string, doc: string, args: string[], f: ((feat: any) => any)) {
this._name = name;
this._doc = doc;
this._args = args;
this._f = f;
}
public static FullPatchFeature(feature) {
for (const func of ExtraFunction.allFuncs) {
func.PatchFeature(feature);
}
}
public static HelpText(): UIElement {
return new Combine([
ExtraFunction.intro,
...ExtraFunction.allFuncs.map(func =>
new Combine([
"<h3>" + func._name + "</h3>",
func._doc,
"<ul>",
...func._args.map(arg => "<li>" + arg + "</li>"),
"</ul>"
])
)
]);
}
public PatchFeature(feature: any) {
feature[this._name] = this._f(feature);
}
}
/** /**
* Metatagging adds various tags to the elements, e.g. lat, lon, surface area, ... * Metatagging adds various tags to the elements, e.g. lat, lon, surface area, ...
@ -163,4 +84,6 @@ export default class MetaTagging {
} }
} }
} }
} }

View file

@ -7,30 +7,15 @@ import {TagsFilter} from "../TagsFilter";
* Interfaces overpass to get all the latest data * Interfaces overpass to get all the latest data
*/ */
export class Overpass { export class Overpass {
private _filter: TagsFilter
public static testUrl: string = null public static testUrl: string = null
private readonly _extraScripts: string[]; private _filter: TagsFilter
private readonly _extraScripts: string[];
constructor(filter: TagsFilter, extraScripts: string[]) { constructor(filter: TagsFilter, extraScripts: string[]) {
this._filter = filter this._filter = filter
this._extraScripts = extraScripts; this._extraScripts = extraScripts;
} }
private buildQuery(bbox: string): string {
const filters = this._filter.asOverpass()
let filter = ""
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)
}
queryGeoJson(bounds: Bounds, continuation: ((any, date: Date) => void), onFail: ((reason) => void)): void { queryGeoJson(bounds: Bounds, continuation: ((any, date: Date) => void), onFail: ((reason) => void)): void {
let query = this.buildQuery("[bbox:" + bounds.south + "," + bounds.west + "," + bounds.north + "," + bounds.east + "]") let query = this.buildQuery("[bbox:" + bounds.south + "," + bounds.west + "," + bounds.north + "," + bounds.east + "]")
@ -52,11 +37,27 @@ export class Overpass {
onFail("Runtime error (timeout)") onFail("Runtime error (timeout)")
return; return;
} }
// @ts-ignore // @ts-ignore
const geojson = OsmToGeoJson.default(json); const geojson = OsmToGeoJson.default(json);
console.log("Received geojson", geojson) 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)
} }
private buildQuery(bbox: string): string {
const filters = this._filter.asOverpass()
let filter = ""
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)
}
} }

View file

@ -64,7 +64,7 @@ export default class SimpleMetaTagger {
SimpleMetaTagger.GetCountryCodeFor(lon, lat, (countries) => { SimpleMetaTagger.GetCountryCodeFor(lon, lat, (countries) => {
try { try {
feature.properties["_country"] = countries[0].trim().toLowerCase(); feature.properties["_country"] = countries[0].trim().toLowerCase();
const tagsSource = State.state.allElements.getEventSourceFor(feature); const tagsSource = State.state.allElements.addOrGetElement(feature);
tagsSource.ping(); tagsSource.ping();
} catch (e) { } catch (e) {
console.warn(e) console.warn(e)
@ -77,7 +77,7 @@ export default class SimpleMetaTagger {
"If 'opening_hours' is present, it will add the current state of the feature (being 'yes' or 'no')", "If 'opening_hours' is present, it will add the current state of the feature (being 'yes' or 'no')",
(feature => { (feature => {
const tagsSource = State.state.allElements.getEventSourceFor(feature); const tagsSource = State.state.allElements.addOrGetElement(feature);
tagsSource.addCallbackAndRun(tags => { tagsSource.addCallbackAndRun(tags => {
if (tags.opening_hours === undefined || tags._country === undefined) { if (tags.opening_hours === undefined || tags._country === undefined) {
return; return;

View file

@ -86,7 +86,7 @@ export default class ShowDataLayer {
marker.openPopup(); marker.openPopup();
const popup = marker.getPopup(); const popup = marker.getPopup();
const tags = State.state.allElements.getEventSourceFor(selected); const tags = State.state.allElements.addOrGetElement(selected);
const layer: LayerConfig = this._layerDict[selected._matching_layer_id]; const layer: LayerConfig = this._layerDict[selected._matching_layer_id];
const infoBox = FeatureInfoBox.construct(tags, layer); const infoBox = FeatureInfoBox.construct(tags, layer);
@ -105,7 +105,7 @@ export default class ShowDataLayer {
private createStyleFor(feature) { private createStyleFor(feature) {
const tagsSource = State.state.allElements.getEventSourceFor(feature); const tagsSource = State.state.allElements.addOrGetElement(feature);
// Every object is tied to exactly one layer // Every object is tied to exactly one layer
const layer = this._layerDict[feature._matching_layer_id]; const layer = this._layerDict[feature._matching_layer_id];
return layer?.GenerateLeafletStyle(tagsSource, layer._showOnPopup !== undefined); return layer?.GenerateLeafletStyle(tagsSource, layer._showOnPopup !== undefined);

View file

@ -15,9 +15,6 @@
"source": { "source": {
"osmTags": "amenity=public_bookcase" "osmTags": "amenity=public_bookcase"
}, },
"calculatedTags": {
"_distanceToPietervdn": "feat.distanceTo(3.704388, 51.05281) < 1 ? 'closeby' : 'faraway'"
},
"minzoom": 12, "minzoom": 12,
"wayHandling": 2, "wayHandling": 2,
"title": { "title": {

View file

@ -6,13 +6,19 @@
"minzoom": 16, "minzoom": 16,
"source": { "source": {
"osmTags": { "osmTags": {
"or": [ "and": [
"highway=pedestrian", {
"highway=footway", "or": [
"highway=path", "highway=pedestrian",
"highway=bridleway", "highway=footway",
"highway=living_street", "highway=path",
"highway=track" "highway=bridleway",
"highway=living_street",
"highway=track"
]
},
"access!=no",
"access!=private"
] ]
} }
}, },
@ -51,7 +57,8 @@
"nl": "Woonerf" "nl": "Woonerf"
} }
}, },
{"if": "highway=path", {
"if": "highway=path",
"then": "Klein pad" "then": "Klein pad"
} }
] ]

View file

@ -4,8 +4,8 @@ import SpecialVisualizations from "../UI/SpecialVisualizations";
import {writeFileSync} from "fs"; import {writeFileSync} from "fs";
import {UIElement} from "../UI/UIElement"; import {UIElement} from "../UI/UIElement";
import SimpleMetaTagger from "../Logic/SimpleMetaTagger"; import SimpleMetaTagger from "../Logic/SimpleMetaTagger";
import {ExtraFunction} from "../Logic/MetaTagging";
import Combine from "../UI/Base/Combine"; import Combine from "../UI/Base/Combine";
import {ExtraFunction} from "../Logic/ExtraFunction";