forked from MapComplete/MapComplete
refactoring
This commit is contained in:
parent
b94a8f5745
commit
5d0fe31c41
114 changed files with 2412 additions and 2958 deletions
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue