mapcomplete/Logic/FeatureSource/FilteringFeatureSource.ts

107 lines
3.7 KiB
TypeScript
Raw Normal View History

import FeatureSource from "./FeatureSource";
import {UIEventSource} from "../UIEventSource";
import LayerConfig from "../../Customizations/JSON/LayerConfig";
import Loc from "../../Models/Loc";
export default class FilteringFeatureSource implements FeatureSource {
public features: UIEventSource<{ feature: any; freshness: Date }[]> = new UIEventSource<{ feature: any; freshness: Date }[]>([]);
constructor(layers: UIEventSource<{
isDisplayed: UIEventSource<boolean>,
layerDef: LayerConfig
}[]>,
location: UIEventSource<Loc>,
upstream: FeatureSource) {
const self = this;
function update() {
const layerDict = {};
for (const layer of layers.data) {
layerDict[layer.layerDef.id] = layer;
}
console.log("Updating the filtering layer, input ", upstream.features.data.length, "features")
const features: { feature: any, freshness: Date }[] = upstream.features.data;
const newFeatures = features.filter(f => {
const layerId = f.feature._matching_layer_id;
2021-02-14 19:45:02 +01:00
if (layerId !== undefined) {
const layer: {
isDisplayed: UIEventSource<boolean>,
layerDef: LayerConfig
} = layerDict[layerId];
if (layer === undefined) {
console.error("No layer found with id ", layerId);
return true;
}
if (FilteringFeatureSource.showLayer(layer, location)) {
return true;
}
}
2021-02-14 19:45:02 +01:00
// Does it match any other layer - e.g. because of a switch?
for (const toCheck of layers.data) {
2021-01-08 14:23:12 +01:00
if (!FilteringFeatureSource.showLayer(toCheck, location)) {
continue;
}
2021-01-08 14:23:12 +01:00
if (toCheck.layerDef.overpassTags.matchesProperties(f.feature.properties)) {
return true;
}
}
return false;
2021-01-08 14:23:12 +01:00
});
console.log("Updating the filtering layer, output ", newFeatures.length, "features")
self.features.setData(newFeatures);
}
2021-02-14 19:45:02 +01:00
upstream.features.addCallback(() => {
2021-01-08 14:23:12 +01:00
update()
});
2021-01-05 10:56:25 +01:00
location.map(l => {
// We want something that is stable for the shown layers
const displayedLayerIndexes = [];
for (let i = 0; i < layers.data.length; i++) {
const layer = layers.data[i];
if (l.zoom < layer.layerDef.minzoom) {
2021-01-05 11:17:12 +01:00
continue;
2021-01-05 10:56:25 +01:00
}
if (!layer.isDisplayed.data) {
2021-01-05 11:17:12 +01:00
continue;
}
displayedLayerIndexes.push(i);
2021-01-05 10:56:25 +01:00
}
return displayedLayerIndexes.join(",")
}).addCallback(() => {
update();
});
layers.addCallback(update);
const registered = new Set<UIEventSource<boolean>>();
layers.addCallbackAndRun(layers => {
for (const layer of layers) {
if(registered.has(layer.isDisplayed)){
continue;
}
registered.add(layer.isDisplayed);
layer.isDisplayed.addCallback(() => update());
}
})
update();
}
2021-01-08 14:23:12 +01:00
private static showLayer(layer: {
isDisplayed: UIEventSource<boolean>,
layerDef: LayerConfig
}, location: UIEventSource<Loc>) {
return layer.isDisplayed.data && (layer.layerDef.minzoom <= location.data.zoom)
}
}