/** * Applies geometry changes from 'Changes' onto every feature of a featureSource */ import { Changes } from "../../Osm/Changes" import { UIEventSource } from "../../UIEventSource" import { FeatureSource, IndexedFeatureSource } from "../FeatureSource" import { ChangeDescription, ChangeDescriptionTools } from "../../Osm/Actions/ChangeDescription" import { Feature } from "geojson" export default class ChangeGeometryApplicator implements FeatureSource { public readonly features: UIEventSource = new UIEventSource([]) private readonly source: IndexedFeatureSource private readonly changes: Changes constructor(source: IndexedFeatureSource, changes: Changes) { this.source = source this.changes = changes this.features = new UIEventSource(undefined) const self = this source.features.addCallbackAndRunD((_) => self.update()) changes.allChanges.addCallbackAndRunD((_) => self.update()) } private update() { const upstreamFeatures = this.source.features.data const upstreamIds = this.source.featuresById.data const changesToApply = this.changes.allChanges.data?.filter( (ch) => // Does upstream have this element? If not, we skip upstreamIds.has(ch.type + "/" + ch.id) && // Are any (geometry) changes defined? ch.changes !== undefined && // Ignore new elements, they are handled by the NewGeometryFromChangesFeatureSource ch.id > 0 ) if (changesToApply === undefined || changesToApply.length === 0) { // No changes to apply! // Pass the original feature and lets continue our day this.features.setData(upstreamFeatures) return } const changesPerId = new Map() for (const ch of changesToApply) { const key = ch.type + "/" + ch.id if (changesPerId.has(key)) { changesPerId.get(key).push(ch) } else { changesPerId.set(key, [ch]) } } const newFeatures: Feature[] = [] for (const feature of upstreamFeatures) { const changesForFeature = changesPerId.get(feature.properties.id) if (changesForFeature === undefined) { // No changes for this element - simply pass it along to downstream newFeatures.push(feature) continue } // Allright! We have a feature to rewrite! const copy = { ...feature, } // We only apply the last change as that one'll have the latest geometry const change = changesForFeature[changesForFeature.length - 1] copy.geometry = ChangeDescriptionTools.getGeojsonGeometry(change) console.log( "Applying a geometry change onto:", feature, "The change is:", change, "which becomes:", copy ) newFeatures.push(copy) } this.features.setData(newFeatures) } }