forked from MapComplete/MapComplete
Performance optimazations
This commit is contained in:
parent
632e7e9f9a
commit
d2b245ab54
15 changed files with 321 additions and 214 deletions
|
@ -10,6 +10,8 @@ import SelectedFeatureHandler from "../Actors/SelectedFeatureHandler";
|
|||
import Hash from "../Web/Hash";
|
||||
import {BBox} from "../BBox";
|
||||
import FeatureInfoBox from "../../UI/Popup/FeatureInfoBox";
|
||||
import {FeatureSourceForLayer, Tiled} from "../FeatureSource/FeatureSource";
|
||||
import MetaTagRecalculator from "../FeatureSource/Actors/MetaTagRecalculator";
|
||||
|
||||
export default class FeaturePipelineState extends MapState {
|
||||
|
||||
|
@ -18,7 +20,7 @@ export default class FeaturePipelineState extends MapState {
|
|||
*/
|
||||
public readonly featurePipeline: FeaturePipeline;
|
||||
private readonly featureAggregator: TileHierarchyAggregator;
|
||||
|
||||
private readonly metatagRecalculator : MetaTagRecalculator
|
||||
constructor(layoutToUse: LayoutConfig) {
|
||||
super(layoutToUse);
|
||||
|
||||
|
@ -26,81 +28,106 @@ export default class FeaturePipelineState extends MapState {
|
|||
this.featureAggregator = TileHierarchyAggregator.createHierarchy(this);
|
||||
const clusterCounter = this.featureAggregator
|
||||
const self = this;
|
||||
this.featurePipeline = new FeaturePipeline(
|
||||
source => {
|
||||
|
||||
clusterCounter.addTile(source)
|
||||
/**
|
||||
* We are a bit in a bind:
|
||||
* There is the featurePipeline, which creates some sources during construction
|
||||
* THere is the metatagger, which needs to have these sources registered AND which takes a FeaturePipeline as argument
|
||||
*
|
||||
* This is a bit of a catch-22 (except that it isn't)
|
||||
* The sources that are registered in the constructor are saved into 'registeredSources' temporary
|
||||
*
|
||||
*/
|
||||
const sourcesToRegister = []
|
||||
|
||||
function registerRaw(source: FeatureSourceForLayer & Tiled){
|
||||
if(self.metatagRecalculator === undefined){
|
||||
sourcesToRegister.push(source)
|
||||
}else{
|
||||
self.metatagRecalculator.registerSource(source)
|
||||
}
|
||||
}
|
||||
|
||||
function registerSource(source: FeatureSourceForLayer & Tiled) {
|
||||
|
||||
const sourceBBox = source.features.map(allFeatures => BBox.bboxAroundAll(allFeatures.map(f => BBox.get(f.feature))))
|
||||
|
||||
// Do show features indicates if the respective 'showDataLayer' should be shown. It can be hidden by e.g. clustering
|
||||
const doShowFeatures = source.features.map(
|
||||
f => {
|
||||
const z = self.locationControl.data.zoom
|
||||
clusterCounter.addTile(source)
|
||||
const sourceBBox = source.features.map(allFeatures => BBox.bboxAroundAll(allFeatures.map(f => BBox.get(f.feature))))
|
||||
|
||||
if (!source.layer.isDisplayed.data) {
|
||||
return false;
|
||||
}
|
||||
// Do show features indicates if the respective 'showDataLayer' should be shown. It can be hidden by e.g. clustering
|
||||
const doShowFeatures = source.features.map(
|
||||
f => {
|
||||
const z = self.locationControl.data.zoom
|
||||
|
||||
const bounds = self.currentBounds.data
|
||||
if (bounds === undefined) {
|
||||
// Map is not yet displayed
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sourceBBox.data.overlapsWith(bounds)) {
|
||||
// Not within range -> features are hidden
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
if (z < source.layer.layerDef.minzoom) {
|
||||
// Layer is always hidden for this zoom level
|
||||
return false;
|
||||
}
|
||||
|
||||
if (z > clustering.maxZoom) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (f.length > clustering.minNeededElements) {
|
||||
// This tile alone already has too much features
|
||||
return false
|
||||
}
|
||||
|
||||
let [tileZ, tileX, tileY] = Tiles.tile_from_index(source.tileIndex);
|
||||
if (tileZ >= z) {
|
||||
|
||||
while (tileZ > z) {
|
||||
tileZ--
|
||||
tileX = Math.floor(tileX / 2)
|
||||
tileY = Math.floor(tileY / 2)
|
||||
}
|
||||
|
||||
if (clusterCounter.getTile(Tiles.tile_index(tileZ, tileX, tileY))?.totalValue > clustering.minNeededElements) {
|
||||
// To much elements
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true
|
||||
}, [this.currentBounds, source.layer.isDisplayed, sourceBBox]
|
||||
)
|
||||
|
||||
new ShowDataLayer(
|
||||
{
|
||||
features: source,
|
||||
leafletMap: self.leafletMap,
|
||||
layerToShow: source.layer.layerDef,
|
||||
doShowLayer: doShowFeatures,
|
||||
selectedElement: self.selectedElement,
|
||||
state: self,
|
||||
popup: (tags, layer) => new FeatureInfoBox(tags, layer, self)
|
||||
if (!source.layer.isDisplayed.data) {
|
||||
return false;
|
||||
}
|
||||
);
|
||||
}, this
|
||||
);
|
||||
|
||||
const bounds = self.currentBounds.data
|
||||
if (bounds === undefined) {
|
||||
// Map is not yet displayed
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sourceBBox.data.overlapsWith(bounds)) {
|
||||
// Not within range -> features are hidden
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
if (z < source.layer.layerDef.minzoom) {
|
||||
// Layer is always hidden for this zoom level
|
||||
return false;
|
||||
}
|
||||
|
||||
if (z > clustering.maxZoom) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (f.length > clustering.minNeededElements) {
|
||||
// This tile alone already has too much features
|
||||
return false
|
||||
}
|
||||
|
||||
let [tileZ, tileX, tileY] = Tiles.tile_from_index(source.tileIndex);
|
||||
if (tileZ >= z) {
|
||||
|
||||
while (tileZ > z) {
|
||||
tileZ--
|
||||
tileX = Math.floor(tileX / 2)
|
||||
tileY = Math.floor(tileY / 2)
|
||||
}
|
||||
|
||||
if (clusterCounter.getTile(Tiles.tile_index(tileZ, tileX, tileY))?.totalValue > clustering.minNeededElements) {
|
||||
// To much elements
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true
|
||||
}, [self.currentBounds, source.layer.isDisplayed, sourceBBox]
|
||||
)
|
||||
|
||||
new ShowDataLayer(
|
||||
{
|
||||
features: source,
|
||||
leafletMap: self.leafletMap,
|
||||
layerToShow: source.layer.layerDef,
|
||||
doShowLayer: doShowFeatures,
|
||||
selectedElement: self.selectedElement,
|
||||
state: self,
|
||||
popup: (tags, layer) => new FeatureInfoBox(tags, layer, self)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
this.featurePipeline = new FeaturePipeline(registerSource, this, {handleRawFeatureSource: registerRaw});
|
||||
this.metatagRecalculator = new MetaTagRecalculator(this, this.featurePipeline)
|
||||
this.metatagRecalculator.registerSource(this.currentView, true)
|
||||
|
||||
sourcesToRegister.forEach(source => self.metatagRecalculator.registerSource(source))
|
||||
|
||||
new SelectedFeatureHandler(Hash.hash, this)
|
||||
|
||||
this.AddClusteringToMap(this.leafletMap)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue