start creating extra filter

This commit is contained in:
Ward 2021-07-26 12:26:41 +02:00
parent 97c85d6909
commit e9160504a6
7 changed files with 872 additions and 800 deletions

View file

@ -1,134 +1,174 @@
import FeatureSource from "./FeatureSource";
import {UIEventSource} from "../UIEventSource";
import { UIEventSource } from "../UIEventSource";
import LayerConfig from "../../Customizations/JSON/LayerConfig";
import Loc from "../../Models/Loc";
import Hash from "../Web/Hash";
import { TagsFilter } from "../Tags/TagsFilter";
export default class FilteringFeatureSource implements FeatureSource {
public features: UIEventSource<{ feature: any; freshness: Date }[]> = new UIEventSource<{ feature: any; freshness: Date }[]>([]);
public readonly name = "FilteringFeatureSource"
public features: UIEventSource<{ feature: any; freshness: Date }[]> =
new UIEventSource<{ feature: any; freshness: Date }[]>([]);
public readonly name = "FilteringFeatureSource";
constructor(layers: UIEventSource<{
isDisplayed: UIEventSource<boolean>,
layerDef: LayerConfig
}[]>,
location: UIEventSource<Loc>,
selectedElement: UIEventSource<any>,
upstream: FeatureSource) {
constructor(
layers: UIEventSource<
{
isDisplayed: UIEventSource<boolean>;
layerDef: LayerConfig;
appliedFilters: UIEventSource<TagsFilter>;
}[]
>,
location: UIEventSource<Loc>,
selectedElement: UIEventSource<any>,
upstream: FeatureSource
) {
const self = this;
const self = this;
function update() {
const layerDict = {};
if (layers.data.length == 0) {
console.warn("No layers defined!");
return;
}
for (const layer of layers.data) {
layerDict[layer.layerDef.id] = layer;
}
function update() {
const features: { feature: any; freshness: Date }[] =
upstream.features.data;
const layerDict = {};
if (layers.data.length == 0) {
console.warn("No layers defined!")
return;
}
for (const layer of layers.data) {
layerDict[layer.layerDef.id] = layer;
}
const missingLayers = new Set<string>();
const features: { feature: any, freshness: Date }[] = upstream.features.data;
const newFeatures = features.filter((f) => {
const layerId = f.feature._matching_layer_id;
const missingLayers = new Set<string>();
const newFeatures = features.filter(f => {
const layerId = f.feature._matching_layer_id;
if(selectedElement.data?.id === f.feature.id || f.feature.id === Hash.hash.data){
// This is the selected object - it gets a free pass even if zoom is not sufficient
return true;
}
if (layerId !== undefined) {
const layer: {
isDisplayed: UIEventSource<boolean>,
layerDef: LayerConfig
} = layerDict[layerId];
if (layer === undefined) {
missingLayers.add(layerId)
return true;
}
const isShown = layer.layerDef.isShown
const tags = f.feature.properties;
if (isShown.IsKnown(tags)) {
const result = layer.layerDef.isShown.GetRenderValue(f.feature.properties).txt;
if (result !== "yes") {
return false;
}
}
if (FilteringFeatureSource.showLayer(layer, location)) {
return true;
}
}
// Does it match any other layer - e.g. because of a switch?
for (const toCheck of layers.data) {
if (!FilteringFeatureSource.showLayer(toCheck, location)) {
continue;
}
if (toCheck.layerDef.source.osmTags.matchesProperties(f.feature.properties)) {
return true;
}
}
return false;
});
console.log("Filtering layer source: input: ", upstream.features.data?.length, "output:", newFeatures.length)
self.features.setData(newFeatures);
if (missingLayers.size > 0) {
console.error("Some layers were not found: ", Array.from(missingLayers))
}
if (
selectedElement.data?.id === f.feature.id ||
f.feature.id === Hash.hash.data
) {
// This is the selected object - it gets a free pass even if zoom is not sufficient
return true;
}
if (layerId !== undefined) {
const layer: {
isDisplayed: UIEventSource<boolean>;
layerDef: LayerConfig;
appliedFilters: UIEventSource<TagsFilter>;
} = layerDict[layerId];
if (layer === undefined) {
missingLayers.add(layerId);
return true;
}
upstream.features.addCallback(() => {
update()
});
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) {
continue;
}
if (l.zoom > layer.layerDef.maxzoom) {
continue;
}
if (!layer.isDisplayed.data) {
continue;
}
displayedLayerIndexes.push(i);
const isShown = layer.layerDef.isShown;
const tags = f.feature.properties;
if (isShown.IsKnown(tags)) {
const result = layer.layerDef.isShown.GetRenderValue(
f.feature.properties
).txt;
if (result !== "yes") {
return false;
}
return displayedLayerIndexes.join(",")
}).addCallback(() => {
update();
});
}
layers.addCallback(update);
if (FilteringFeatureSource.showLayer(layer, location)) {
const tagsFilter = layer.appliedFilters.data;
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());
if (tagsFilter) {
const properties = f.feature.properties;
if (!tagsFilter.matchesProperties(properties)) {
return false;
}
}
})
return true;
}
}
// Does it match any other layer - e.g. because of a switch?
for (const toCheck of layers.data) {
if (!FilteringFeatureSource.showLayer(toCheck, location)) {
continue;
}
if (
toCheck.layerDef.source.osmTags.matchesProperties(
f.feature.properties
)
) {
return true;
}
}
return false;
});
console.log(
"Filtering layer source: input: ",
upstream.features.data?.length,
"output:",
newFeatures.length
);
self.features.setData(newFeatures);
if (missingLayers.size > 0) {
console.error(
"Some layers were not found: ",
Array.from(missingLayers)
);
}
}
upstream.features.addCallback(() => {
update();
});
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) {
continue;
}
if (l.zoom > layer.layerDef.maxzoom) {
continue;
}
if (!layer.isDisplayed.data) {
continue;
}
displayedLayerIndexes.push(i);
}
return displayedLayerIndexes.join(",");
})
.addCallback(() => {
update();
});
}
layers.addCallback(update);
private static showLayer(layer: {
isDisplayed: UIEventSource<boolean>,
layerDef: LayerConfig
}, location: UIEventSource<Loc>) {
return layer.isDisplayed.data && (layer.layerDef.minzoom <= location.data.zoom) && (layer.layerDef.maxzoom >= location.data.zoom)
}
}
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());
layer.appliedFilters.addCallback(() => update());
}
});
update();
}
private static showLayer(
layer: {
isDisplayed: UIEventSource<boolean>;
layerDef: LayerConfig;
},
location: UIEventSource<Loc>
) {
return (
layer.isDisplayed.data &&
layer.layerDef.minzoom <= location.data.zoom &&
layer.layerDef.maxzoom >= location.data.zoom
);
}
}