refactoring

This commit is contained in:
Pieter Vander Vennet 2023-03-28 05:13:48 +02:00
parent b94a8f5745
commit 5d0fe31c41
114 changed files with 2412 additions and 2958 deletions

View file

@ -1,48 +1,59 @@
import FeatureSource from "./FeatureSource"
import { Store } from "../UIEventSource"
import FeatureSource, { FeatureSourceForLayer } from "./FeatureSource"
import FilteredLayer from "../../Models/FilteredLayer"
import SimpleFeatureSource from "./Sources/SimpleFeatureSource"
import { Feature } from "geojson"
import { Utils } from "../../Utils"
import { UIEventSource } from "../UIEventSource"
/**
* 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 {
export default class PerLayerFeatureSourceSplitter<
T extends FeatureSourceForLayer = SimpleFeatureSource
> {
public readonly perLayer: ReadonlyMap<string, T>
constructor(
layers: Store<FilteredLayer[]>,
handleLayerData: (source: FeatureSource, layer: FilteredLayer) => void,
layers: FilteredLayer[],
upstream: FeatureSource,
options?: {
tileIndex?: number
constructStore?: (features: UIEventSource<Feature[]>, layer: FilteredLayer) => T
handleLeftovers?: (featuresWithoutLayer: any[]) => void
}
) {
const knownLayers = new Map<string, SimpleFeatureSource>()
const knownLayers = new Map<string, T>()
this.perLayer = knownLayers
const layerSources = new Map<string, UIEventSource<Feature[]>>()
function update() {
const features = upstream.features?.data
const constructStore =
options?.constructStore ?? ((store, layer) => new SimpleFeatureSource(layer, store))
for (const layer of layers) {
const src = new UIEventSource<Feature[]>([])
layerSources.set(layer.layerDef.id, src)
knownLayers.set(layer.layerDef.id, <T>constructStore(src, layer))
}
upstream.features.addCallbackAndRunD((features) => {
if (features === undefined) {
return
}
if (layers.data === undefined || layers.data.length === 0) {
if (layers === undefined) {
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[]>()
const noLayerFound = []
const noLayerFound: Feature[] = []
for (const layer of layers.data) {
for (const layer of layers) {
featuresPerLayer.set(layer.layerDef.id, [])
}
for (const f of features) {
let foundALayer = false
for (const layer of layers.data) {
for (const layer of layers) {
if (layer.layerDef.source.osmTags.matchesProperties(f.properties)) {
// We have found our matching layer!
featuresPerLayer.get(layer.layerDef.id).push(f)
@ -60,7 +71,7 @@ export default class PerLayerFeatureSourceSplitter {
// 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) {
for (const layer of layers) {
const id = layer.layerDef.id
const features = featuresPerLayer.get(id)
if (features === undefined) {
@ -68,25 +79,24 @@ export default class PerLayerFeatureSourceSplitter {
continue
}
let featureSource = knownLayers.get(id)
if (featureSource === undefined) {
// Not yet initialized - now is a good time
featureSource = new SimpleFeatureSource(layer)
featureSource.features.setData(features)
knownLayers.set(id, featureSource)
handleLayerData(featureSource, layer)
} else {
featureSource.features.setData(features)
const src = layerSources.get(id)
if (Utils.sameList(src.data, features)) {
return
}
src.setData(features)
}
// AT last, the leftovers are handled
if (options?.handleLeftovers !== undefined && noLayerFound.length > 0) {
options.handleLeftovers(noLayerFound)
}
}
})
}
layers.addCallback((_) => update())
upstream.features.addCallbackAndRunD((_) => update())
public forEach(f: (featureSource: FeatureSourceForLayer) => void) {
for (const fs of this.perLayer.values()) {
f(fs)
}
}
}