import {GeoOperations} from "./GeoOperations"; import {UIElement} from "../UI/UIElement"; import Combine from "../UI/Base/Combine"; export class ExtraFunction { static readonly intro = `

Calculating tags with Javascript

In some cases, it is useful to have some tags calculated based on other properties. Some useful tags are available by default (e.g. lat, lon, _country), as detailed above.

It is also possible to calculate your own tags - but this requires some javascript knowledge.

Before proceeding, some warnings: In the layer object, add a field calculatedTags, e.g.:
"calculatedTags": [ "_someKey=javascript-expression", "name=feat.properties.name ?? feat.properties.ref ?? feat.properties.operator", "_distanceCloserThen3Km=feat.distanceTo( some_lon, some_lat) < 3 ? 'yes' : 'no'" ]
The above code will be executed for every feature in the layer. The feature is accessible as feat and is an amended geojson object: - area contains the surface area (in square meters) of the object - lat and lon contain the latitude and longitude Some advanced functions are available on feat as well: ` private static OverlapFunc = new ExtraFunction( "overlapWith", "Gives a list of features from the specified layer which this feature overlaps with, the amount of overlap in m². The returned value is { feat: GeoJSONFeature, overlap: number}", ["...layerIds - one or more layer ids of the layer from which every feature is checked for overlap)"], (featuresPerLayer, feat) => { return (...layerIds: string[]) => { const result = [] for (const layerId of layerIds) { const otherLayer = featuresPerLayer.get(layerId); if (otherLayer === undefined) { continue; } if (otherLayer.length === 0) { continue; } result.push(...GeoOperations.calculateOverlap(feat, otherLayer)); } return result; } } ) private static DistanceToFunc = new ExtraFunction( "distanceTo", "Calculates the distance between the feature and a specified point", ["longitude", "latitude"], (featuresPerLayer, 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, ExtraFunction.OverlapFunc]; private readonly _name: string; private readonly _args: string[]; private readonly _doc: string; private readonly _f: (featuresPerLayer: Map, feat: any) => any; constructor(name: string, doc: string, args: string[], f: ((featuresPerLayer: Map, feat: any) => any)) { this._name = name; this._doc = doc; this._args = args; this._f = f; } public static FullPatchFeature(featuresPerLayer: Map, feature) { for (const func of ExtraFunction.allFuncs) { func.PatchFeature(featuresPerLayer, feature); } } public static HelpText(): UIElement { return new Combine([ ExtraFunction.intro, "
    ", ...ExtraFunction.allFuncs.map(func => new Combine([ "
  • ", func._name, "
  • " ]) ), "
", ...ExtraFunction.allFuncs.map(func => new Combine([ "

" + func._name + "

", func._doc, "
    ", ...func._args.map(arg => "
  • " + arg + "
  • "), "
" ]) ) ]); } public PatchFeature(featuresPerLayer: Map, feature: any) { feature[this._name] = this._f(featuresPerLayer, feature); } }