2021-09-22 05:02:09 +02:00
|
|
|
import FeatureSource, {FeatureSourceForLayer, Tiled} from "./FeatureSource";
|
2021-09-20 17:14:55 +02:00
|
|
|
import {UIEventSource} from "../UIEventSource";
|
|
|
|
import FilteredLayer from "../../Models/FilteredLayer";
|
2021-09-21 02:10:42 +02:00
|
|
|
import SimpleFeatureSource from "./Sources/SimpleFeatureSource";
|
2021-09-20 17:14:55 +02:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
* In any case, this featureSource marks the objects with _matching_layer_id
|
|
|
|
*/
|
|
|
|
export default class PerLayerFeatureSourceSplitter {
|
|
|
|
|
|
|
|
constructor(layers: UIEventSource<FilteredLayer[]>,
|
2021-09-22 05:02:09 +02:00
|
|
|
handleLayerData: (source: FeatureSourceForLayer & Tiled) => void,
|
|
|
|
upstream: FeatureSource,
|
2021-11-07 16:34:51 +01:00
|
|
|
options?: {
|
|
|
|
tileIndex?: number,
|
|
|
|
handleLeftovers?: (featuresWithoutLayer: any[]) => void
|
2021-09-22 05:02:09 +02:00
|
|
|
}) {
|
2021-09-20 17:14:55 +02:00
|
|
|
|
2021-09-22 05:02:09 +02:00
|
|
|
const knownLayers = new Map<string, FeatureSourceForLayer & Tiled>()
|
2021-09-20 17:14:55 +02:00
|
|
|
|
|
|
|
function update() {
|
2021-11-08 14:18:45 +01:00
|
|
|
const features = upstream.features?.data;
|
2021-09-20 17:14:55 +02:00
|
|
|
if (features === undefined) {
|
|
|
|
return;
|
|
|
|
}
|
2022-01-07 17:31:39 +01:00
|
|
|
if (layers.data === undefined || layers.data.length === 0) {
|
2021-09-20 17:14:55 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We try to figure out (for each feature) in which feature store it should be saved.
|
|
|
|
// Note that this splitter is only run when it is invoked by the overpass feature source, so we can't be sure in which layer it should go
|
|
|
|
|
|
|
|
const featuresPerLayer = new Map<string, { feature, freshness } []>();
|
2021-09-22 05:02:09 +02:00
|
|
|
const noLayerFound = []
|
2021-11-07 16:34:51 +01:00
|
|
|
|
2021-12-13 02:05:34 +01:00
|
|
|
for (const layer of layers.data) {
|
|
|
|
featuresPerLayer.set(layer.layerDef.id, [])
|
2021-09-20 17:14:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
for (const f of features) {
|
2022-04-28 11:47:54 +02:00
|
|
|
let foundALayer = false;
|
2021-09-20 17:14:55 +02:00
|
|
|
for (const layer of layers.data) {
|
|
|
|
if (layer.layerDef.source.osmTags.matchesProperties(f.feature.properties)) {
|
|
|
|
// We have found our matching layer!
|
2021-12-13 20:51:44 +01:00
|
|
|
featuresPerLayer.get(layer.layerDef.id).push(f)
|
2022-04-28 11:47:54 +02:00
|
|
|
foundALayer = true;
|
2021-09-20 17:14:55 +02:00
|
|
|
if (!layer.layerDef.passAllFeatures) {
|
|
|
|
// If not 'passAllFeatures', we are done for this feature
|
2022-04-28 11:47:54 +02:00
|
|
|
break
|
2021-09-20 17:14:55 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-04-28 11:47:54 +02:00
|
|
|
if(!foundALayer){
|
|
|
|
noLayerFound.push(f)
|
|
|
|
}
|
2021-09-20 17:14:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// At this point, we have our features per layer as a list
|
|
|
|
// We assign them to the correct featureSources
|
|
|
|
for (const layer of layers.data) {
|
|
|
|
const id = layer.layerDef.id;
|
|
|
|
const features = featuresPerLayer.get(id)
|
|
|
|
if (features === undefined) {
|
|
|
|
// No such features for this layer
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
let featureSource = knownLayers.get(id)
|
|
|
|
if (featureSource === undefined) {
|
|
|
|
// Not yet initialized - now is a good time
|
2021-09-28 17:30:48 +02:00
|
|
|
featureSource = new SimpleFeatureSource(layer, options?.tileIndex)
|
2021-09-21 02:10:42 +02:00
|
|
|
featureSource.features.setData(features)
|
2021-09-20 17:14:55 +02:00
|
|
|
knownLayers.set(id, featureSource)
|
|
|
|
handleLayerData(featureSource)
|
2021-09-21 02:10:42 +02:00
|
|
|
} else {
|
|
|
|
featureSource.features.setData(features)
|
2021-09-20 17:14:55 +02:00
|
|
|
}
|
|
|
|
}
|
2021-11-07 16:34:51 +01:00
|
|
|
|
2021-09-22 05:02:09 +02:00
|
|
|
// AT last, the leftovers are handled
|
2021-11-07 16:34:51 +01:00
|
|
|
if (options?.handleLeftovers !== undefined && noLayerFound.length > 0) {
|
2021-09-22 05:02:09 +02:00
|
|
|
options.handleLeftovers(noLayerFound)
|
|
|
|
}
|
2021-09-20 17:14:55 +02:00
|
|
|
}
|
2021-09-21 02:10:42 +02:00
|
|
|
|
|
|
|
layers.addCallback(_ => update())
|
2021-09-20 17:14:55 +02:00
|
|
|
upstream.features.addCallbackAndRunD(_ => update())
|
|
|
|
}
|
|
|
|
}
|