forked from MapComplete/MapComplete
Performance optimazations
This commit is contained in:
parent
632e7e9f9a
commit
d2b245ab54
15 changed files with 321 additions and 214 deletions
112
Logic/FeatureSource/Actors/MetaTagRecalculator.ts
Normal file
112
Logic/FeatureSource/Actors/MetaTagRecalculator.ts
Normal file
|
@ -0,0 +1,112 @@
|
|||
import {FeatureSourceForLayer, Tiled} from "../FeatureSource";
|
||||
import MetaTagging from "../../MetaTagging";
|
||||
import {ElementStorage} from "../../ElementStorage";
|
||||
import {ExtraFuncParams} from "../../ExtraFunctions";
|
||||
import FeaturePipeline from "../FeaturePipeline";
|
||||
import {BBox} from "../../BBox";
|
||||
import {UIEventSource} from "../../UIEventSource";
|
||||
|
||||
/****
|
||||
* Concerned with the logic of updating the right layer at the right time
|
||||
*/
|
||||
class MetatagUpdater {
|
||||
public readonly neededLayerBboxes = new Map<string /*layerId*/, BBox>()
|
||||
private source: FeatureSourceForLayer & Tiled;
|
||||
private readonly params: ExtraFuncParams
|
||||
private state: { allElements?: ElementStorage };
|
||||
|
||||
private readonly isDirty = new UIEventSource(false)
|
||||
|
||||
constructor(source: FeatureSourceForLayer & Tiled, state: { allElements?: ElementStorage }, featurePipeline: FeaturePipeline) {
|
||||
this.state = state;
|
||||
this.source = source;
|
||||
const self = this;
|
||||
this.params = {
|
||||
getFeatureById(id) {
|
||||
return state.allElements.ContainingFeatures.get(id)
|
||||
},
|
||||
getFeaturesWithin(layerId, bbox) {
|
||||
// We keep track of the BBOX that this source needs
|
||||
let oldBbox: BBox = self.neededLayerBboxes.get(layerId)
|
||||
if (oldBbox === undefined) {
|
||||
self.neededLayerBboxes.set(layerId, bbox);
|
||||
} else if (!bbox.isContainedIn(oldBbox)) {
|
||||
self.neededLayerBboxes.set(layerId,oldBbox.unionWith(bbox))
|
||||
}
|
||||
return featurePipeline.GetFeaturesWithin(layerId, bbox)
|
||||
},
|
||||
memberships: featurePipeline.relationTracker
|
||||
}
|
||||
this.isDirty.stabilized(100).addCallback(dirty => {
|
||||
if(dirty){
|
||||
self.updateMetaTags()
|
||||
}
|
||||
})
|
||||
this.source.features.addCallbackAndRunD(_ => self.isDirty.setData(true))
|
||||
|
||||
}
|
||||
|
||||
public requestUpdate(){
|
||||
this.isDirty.setData(true)
|
||||
}
|
||||
|
||||
private updateMetaTags() {
|
||||
const features = this.source.features.data
|
||||
|
||||
if (features.length === 0) {
|
||||
this.isDirty.setData(false)
|
||||
return
|
||||
}
|
||||
MetaTagging.addMetatags(
|
||||
features,
|
||||
this.params,
|
||||
this.source.layer.layerDef,
|
||||
this.state)
|
||||
this.isDirty.setData(false)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default class MetaTagRecalculator {
|
||||
private _state: {
|
||||
allElements?: ElementStorage
|
||||
};
|
||||
private _featurePipeline: FeaturePipeline;
|
||||
private readonly _alreadyRegistered: Set<FeatureSourceForLayer & Tiled> = new Set<FeatureSourceForLayer & Tiled>()
|
||||
private readonly _notifiers : MetatagUpdater[] = []
|
||||
/**
|
||||
* The meta tag recalculator receives tiles of layers.
|
||||
* It keeps track of which sources have had their share calculated, and which should be re-updated if some other data is loaded
|
||||
*/
|
||||
constructor(state: { allElements?: ElementStorage }, featurePipeline: FeaturePipeline) {
|
||||
this._featurePipeline = featurePipeline;
|
||||
this._state = state;
|
||||
}
|
||||
|
||||
public registerSource(source: FeatureSourceForLayer & Tiled, recalculateOnEveryChange = false) {
|
||||
if (source === undefined) {
|
||||
return;
|
||||
}
|
||||
if (this._alreadyRegistered.has(source)) {
|
||||
return;
|
||||
}
|
||||
this._alreadyRegistered.add(source)
|
||||
this._notifiers.push(new MetatagUpdater(source,this._state,this._featurePipeline))
|
||||
const self = this;
|
||||
source.features.addCallbackAndRunD(_ => {
|
||||
const layerName = source.layer.layerDef.id
|
||||
for (const updater of self._notifiers ) {
|
||||
const neededBbox = updater.neededLayerBboxes.get(layerName)
|
||||
if(neededBbox == undefined){
|
||||
continue
|
||||
}
|
||||
if(source.bbox === undefined || neededBbox.overlapsWith(source.bbox)){
|
||||
updater.requestUpdate()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue