2021-10-15 05:20:02 +02:00
|
|
|
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig";
|
|
|
|
import FeaturePipeline from "../FeatureSource/FeaturePipeline";
|
|
|
|
import {Tiles} from "../../Models/TileRange";
|
|
|
|
import ShowDataLayer from "../../UI/ShowDataLayer/ShowDataLayer";
|
|
|
|
import {TileHierarchyAggregator} from "../../UI/ShowDataLayer/TileHierarchyAggregator";
|
|
|
|
import ShowTileInfo from "../../UI/ShowDataLayer/ShowTileInfo";
|
|
|
|
import {UIEventSource} from "../UIEventSource";
|
|
|
|
import MapState from "./MapState";
|
|
|
|
import SelectedFeatureHandler from "../Actors/SelectedFeatureHandler";
|
|
|
|
import Hash from "../Web/Hash";
|
2021-12-07 17:46:57 +01:00
|
|
|
import {BBox} from "../BBox";
|
2022-01-19 20:34:04 +01:00
|
|
|
import FeatureInfoBox from "../../UI/Popup/FeatureInfoBox";
|
2021-10-15 05:20:02 +02:00
|
|
|
|
|
|
|
export default class FeaturePipelineState extends MapState {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The piece of code which fetches data from various sources and shows it on the background map
|
|
|
|
*/
|
|
|
|
public readonly featurePipeline: FeaturePipeline;
|
|
|
|
private readonly featureAggregator: TileHierarchyAggregator;
|
|
|
|
|
|
|
|
constructor(layoutToUse: LayoutConfig) {
|
|
|
|
super(layoutToUse);
|
|
|
|
|
|
|
|
const clustering = layoutToUse.clustering
|
2021-10-15 18:48:33 +02:00
|
|
|
this.featureAggregator = TileHierarchyAggregator.createHierarchy(this);
|
2021-10-15 05:20:02 +02:00
|
|
|
const clusterCounter = this.featureAggregator
|
|
|
|
const self = this;
|
|
|
|
this.featurePipeline = new FeaturePipeline(
|
|
|
|
source => {
|
|
|
|
|
|
|
|
clusterCounter.addTile(source)
|
|
|
|
|
2021-12-07 17:46:57 +01:00
|
|
|
const sourceBBox = source.features.map(allFeatures => BBox.bboxAroundAll(allFeatures.map(f => BBox.get(f.feature))))
|
|
|
|
|
2022-01-07 17:31:39 +01:00
|
|
|
// Do show features indicates if the respective 'showDataLayer' should be shown. It can be hidden by e.g. clustering
|
2021-10-15 05:20:02 +02:00
|
|
|
const doShowFeatures = source.features.map(
|
|
|
|
f => {
|
2021-10-15 13:43:11 +02:00
|
|
|
const z = self.locationControl.data.zoom
|
2021-10-15 05:20:02 +02:00
|
|
|
|
|
|
|
if (!source.layer.isDisplayed.data) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-10-15 13:43:11 +02:00
|
|
|
const bounds = self.currentBounds.data
|
2021-10-15 05:20:02 +02:00
|
|
|
if (bounds === undefined) {
|
|
|
|
// Map is not yet displayed
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-12-07 17:46:57 +01:00
|
|
|
if (!sourceBBox.data.overlapsWith(bounds)) {
|
2021-10-15 05:20:02 +02:00
|
|
|
// 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
|
2021-12-07 17:46:57 +01:00
|
|
|
}, [this.currentBounds, source.layer.isDisplayed, sourceBBox]
|
2021-10-15 05:20:02 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
new ShowDataLayer(
|
|
|
|
{
|
|
|
|
features: source,
|
|
|
|
leafletMap: self.leafletMap,
|
|
|
|
layerToShow: source.layer.layerDef,
|
|
|
|
doShowLayer: doShowFeatures,
|
2022-01-19 20:34:04 +01:00
|
|
|
selectedElement: self.selectedElement,
|
|
|
|
state: self,
|
|
|
|
popup: (tags, layer) => new FeatureInfoBox(tags, layer, self)
|
2021-10-15 05:20:02 +02:00
|
|
|
}
|
|
|
|
);
|
|
|
|
}, this
|
|
|
|
);
|
|
|
|
new SelectedFeatureHandler(Hash.hash, this)
|
2021-11-07 16:34:51 +01:00
|
|
|
|
2021-10-15 05:20:02 +02:00
|
|
|
this.AddClusteringToMap(this.leafletMap)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds the cluster-tiles to the given map
|
|
|
|
* @param leafletMap: a UIEventSource possible having a leaflet map
|
|
|
|
* @constructor
|
|
|
|
*/
|
|
|
|
public AddClusteringToMap(leafletMap: UIEventSource<any>) {
|
|
|
|
const clustering = this.layoutToUse.clustering
|
2022-01-19 20:34:04 +01:00
|
|
|
const self = this;
|
2021-10-15 05:20:02 +02:00
|
|
|
new ShowDataLayer({
|
|
|
|
features: this.featureAggregator.getCountsForZoom(clustering, this.locationControl, clustering.minNeededElements),
|
|
|
|
leafletMap: leafletMap,
|
|
|
|
layerToShow: ShowTileInfo.styling,
|
2022-01-19 20:34:04 +01:00
|
|
|
popup: this.featureSwitchIsDebugging.data ? (tags, layer) => new FeatureInfoBox(tags, layer, self) : undefined,
|
|
|
|
state: this
|
2021-10-15 05:20:02 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|