84 lines
No EOL
3.3 KiB
TypeScript
84 lines
No EOL
3.3 KiB
TypeScript
/**
|
|
* Applies geometry changes from 'Changes' onto every feature of a featureSource
|
|
*/
|
|
import {Changes} from "../../Osm/Changes";
|
|
import {UIEventSource} from "../../UIEventSource";
|
|
import {FeatureSourceForLayer, IndexedFeatureSource} from "../FeatureSource";
|
|
import FilteredLayer from "../../../Models/FilteredLayer";
|
|
import {ChangeDescription, ChangeDescriptionTools} from "../../Osm/Actions/ChangeDescription";
|
|
|
|
|
|
export default class ChangeGeometryApplicator implements FeatureSourceForLayer {
|
|
public readonly features: UIEventSource<{ feature: any; freshness: Date }[]> = new UIEventSource<{ feature: any; freshness: Date }[]>([]);
|
|
public readonly name: string;
|
|
public readonly layer: FilteredLayer
|
|
private readonly source: IndexedFeatureSource;
|
|
private readonly changes: Changes;
|
|
|
|
constructor(source: (IndexedFeatureSource & FeatureSourceForLayer), changes: Changes) {
|
|
this.source = source;
|
|
this.changes = changes;
|
|
this.layer = source.layer
|
|
|
|
this.name = "ChangesApplied(" + source.name + ")"
|
|
this.features = new UIEventSource<{ feature: any; freshness: Date }[]>(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.containedIds.data
|
|
const changesToApply = this.changes.allChanges.data
|
|
?.filter(ch =>
|
|
// Does upsteram 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<string, ChangeDescription[]>()
|
|
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: any, freshness: Date }[] = []
|
|
for (const feature of upstreamFeatures) {
|
|
const changesForFeature = changesPerId.get(feature.feature.properties.id)
|
|
if (changesForFeature === undefined) {
|
|
// No changes for this element
|
|
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.feature.geometry = ChangeDescriptionTools.getGeojsonGeometry(change)
|
|
console.log("Applying a geometry change onto ", feature, change, copy)
|
|
newFeatures.push(copy)
|
|
}
|
|
this.features.setData(newFeatures)
|
|
|
|
}
|
|
|
|
} |