Add metatagging, fritures

This commit is contained in:
Pieter Vander Vennet 2020-10-19 12:08:42 +02:00
parent 1e0a1fdf97
commit 99225957cc
15 changed files with 406 additions and 38 deletions

View file

@ -110,31 +110,6 @@ export class FilteredLayer {
const tags = TagUtils.proprtiesToKV(feature.properties);
if (this.filters.matches(tags)) {
const centerPoint = GeoOperations.centerpoint(feature);
const sqMeters = GeoOperations.surfaceAreaInSqMeters(feature);
feature.properties["_surface"] = "" + sqMeters;
feature.properties["_surface:ha"] = "" + Math.floor(sqMeters / 1000)/10;
const lat = centerPoint.geometry.coordinates[1];
const lon = centerPoint.geometry.coordinates[0]
feature.properties["_lon"] = "" + lat; // We expect a string here for lat/lon
feature.properties["_lat"] = "" + lon;
// But the codegrid SHOULD be a number!
CodeGrid.getCode(lat, lon, (error, code) => {
if (error === null) {
feature.properties["_country"] = code;
} else {
console.warn("Could not determine country for", feature.properties.id, error);
}
})
if (feature.geometry.type !== "Point") {
if (this._wayHandling === LayerDefinition.WAYHANDLING_CENTER_AND_WAY) {
selfFeatures.push(centerPoint);
} else if (this._wayHandling === LayerDefinition.WAYHANDLING_CENTER_ONLY) {
feature = centerPoint;
}
}
selfFeatures.push(feature);
} else {
leftoverFeatures.push(feature);

124
Logic/MetaTagging.ts Normal file
View file

@ -0,0 +1,124 @@
import {GeoOperations} from "./GeoOperations";
import CodeGrid from "./Web/CodeGrid";
import State from "../State";
import opening_hours from "opening_hours";
class SimpleMetaTagger {
private _f: (feature: any) => void;
public readonly keys: string[];
public readonly doc: string;
constructor(keys: string[], doc: string, f: ((feature: any) => void)) {
this.keys = keys;
this.doc = doc;
this._f = f;
for (const key of keys) {
if (!key.startsWith('_')) {
throw `Incorrect metakey ${key}: it should start with underscore (_)`
}
}
}
addMetaTags(features: any[]) {
for (const feature of features) {
this._f(feature);
}
}
}
/**
* Metatagging adds various tags to the elements, e.g. lat, lon, surface area, ...
*
* All metatags start with an underscore
*/
export default class MetaTagging {
public static metatags = [
new SimpleMetaTagger(["_lat", "_lon"], "The latitude and longitude of the point (or centerpoint in the case of a way/area)",
(feature => {
const centerPoint = GeoOperations.centerpoint(feature);
const lat = centerPoint.geometry.coordinates[1];
const lon = centerPoint.geometry.coordinates[0];
feature.properties["_lat"] = "" + lat;
feature.properties["_lon"] = "" + lon;
})
),
new SimpleMetaTagger(
["_surface", "_surface:ha"], "The surface area of the feature, in square meters and in hectare. Not set on points and ways",
(feature => {
const sqMeters = GeoOperations.surfaceAreaInSqMeters(feature);
feature.properties["_surface"] = "" + sqMeters;
feature.properties["_surface:ha"] = "" + Math.floor(sqMeters / 1000) / 10;
})
),
new SimpleMetaTagger(
["_country"], "The country code of the point",
(feature => {
const centerPoint = GeoOperations.centerpoint(feature);
const lat = centerPoint.geometry.coordinates[1];
const lon = centerPoint.geometry.coordinates[0]
// But the codegrid SHOULD be a number!
CodeGrid.getCode(lat, lon, (error, code) => {
if (error === null) {
feature.properties["_country"] = code;
State.state.allElements.addOrGetElement(feature).ping();
} else {
console.warn("Could not determine country for", feature.properties.id, error);
}
});
})
),
new SimpleMetaTagger(
["_isOpen", "_isOpen:description"], "If 'opening_hours' is present, it will add the current state of the feature (being 'yes' or 'no",
(feature => {
const tagsSource = State.state.allElements.addOrGetElement(feature);
tagsSource.addCallback(tags => {
if (tags["opening_hours"] !== undefined && tags["_country"] !== undefined) {
const oh = new opening_hours(tags["opening_hours"], {
lat: tags._lat,
lon: tags._lon,
address: {
country_code: tags._country
}
}, {tag_key: "opening_hours"});
const updateTags = () => {
tags["_isOpen"] = oh.getState() ? "yes" : "no";
const comment = oh.getComment();
if (comment) {
tags["_isOpen:description"] = comment;
}
const nextChange = oh.getNextChange() as Date;
window.setTimeout(
updateTags,
(nextChange.getTime() - (new Date()).getTime())
)
}
updateTags();
}
})
})
)
];
static addMetatags(features: any[]) {
for (const metatag of MetaTagging.metatags) {
metatag.addMetaTags(features);
}
}
}

View file

@ -5,8 +5,9 @@ import {Bounds} from "./Bounds";
import {Overpass} from "./Osm/Overpass";
import State from "../State";
import {LayerDefinition} from "../Customizations/LayerDefinition";
import MetaTagging from "./MetaTagging";
export class LayerUpdater {
export class UpdateFromOverpass {
public readonly sufficentlyZoomed: UIEventSource<boolean>;
public readonly runningQuery: UIEventSource<boolean> = new UIEventSource<boolean>(false);
@ -100,6 +101,8 @@ export class LayerUpdater {
}
}
MetaTagging.addMetatags(geojson.features);
function renderLayers(layers: FilteredLayer[]) {
if (layers.length === 0) {
self.runningQuery.setData(false);

View file

@ -8,6 +8,7 @@ export default class CodeGrid {
CodeGrid.grid.getCode(lat, lon, handle);
}
private static InitGrid(): any {
const grid = codegrid.CodeGrid("./tiles/");