forked from MapComplete/MapComplete
Huge refactoring of the feature pipeline, WIP
This commit is contained in:
parent
7793297348
commit
973b5d8bbe
25 changed files with 522 additions and 591 deletions
72
Logic/FeatureSource/TiledFeatureSource/DynamicTileSource.ts
Normal file
72
Logic/FeatureSource/TiledFeatureSource/DynamicTileSource.ts
Normal file
|
@ -0,0 +1,72 @@
|
|||
/***
|
||||
* A tiled source which dynamically loads the required tiles
|
||||
*/
|
||||
import State from "../../../State";
|
||||
import FilteredLayer from "../../../Models/FilteredLayer";
|
||||
import {FeatureSourceForLayer} from "../FeatureSource";
|
||||
import {Utils} from "../../../Utils";
|
||||
import {UIEventSource} from "../../UIEventSource";
|
||||
import Loc from "../../../Models/Loc";
|
||||
|
||||
export default class DynamicTileSource {
|
||||
private readonly _loadedTiles = new Set<number>();
|
||||
|
||||
public readonly existingTiles: Map<number, Map<number, FeatureSourceForLayer>> = new Map<number, Map<number, FeatureSourceForLayer>>()
|
||||
|
||||
constructor(
|
||||
layer: FilteredLayer,
|
||||
zoomlevel: number,
|
||||
constructTile: (xy: [number, number]) => FeatureSourceForLayer,
|
||||
state: {
|
||||
locationControl: UIEventSource<Loc>
|
||||
leafletMap: any
|
||||
}
|
||||
) {
|
||||
state = State.state
|
||||
const self = this;
|
||||
const neededTiles = state.locationControl.map(
|
||||
location => {
|
||||
if (!layer.isDisplayed.data) {
|
||||
// No need to download! - the layer is disabled
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (location.zoom < layer.layerDef.minzoom) {
|
||||
// No need to download! - the layer is disabled
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Yup, this is cheating to just get the bounds here
|
||||
const bounds = state.leafletMap.data?.getBounds()
|
||||
if (bounds === undefined) {
|
||||
// We'll retry later
|
||||
return undefined
|
||||
}
|
||||
const tileRange = Utils.TileRangeBetween(zoomlevel, bounds.getNorth(), bounds.getEast(), bounds.getSouth(), bounds.getWest())
|
||||
|
||||
const needed = Utils.MapRange(tileRange, (x, y) => Utils.tile_index(zoomlevel, x, y)).filter(i => !self._loadedTiles.has(i))
|
||||
if(needed.length === 0){
|
||||
return undefined
|
||||
}
|
||||
return needed
|
||||
}
|
||||
, [layer.isDisplayed, state.leafletMap]).stabilized(250);
|
||||
|
||||
neededTiles.addCallbackAndRunD(neededIndexes => {
|
||||
for (const neededIndex of neededIndexes) {
|
||||
self._loadedTiles.add(neededIndex)
|
||||
const xy = Utils.tile_from_index(zoomlevel, neededIndex)
|
||||
const src = constructTile(xy)
|
||||
let xmap = self.existingTiles.get(xy[0])
|
||||
if(xmap === undefined){
|
||||
xmap = new Map<number, FeatureSourceForLayer>()
|
||||
self.existingTiles.set(xy[0], xmap)
|
||||
}
|
||||
xmap.set(xy[1], src)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
3
Logic/FeatureSource/TiledFeatureSource/README.md
Normal file
3
Logic/FeatureSource/TiledFeatureSource/README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
Data in MapComplete can come from multiple sources.
|
||||
|
||||
In order to keep thins snappy, they are distributed over a tiled database
|
0
Logic/FeatureSource/TiledFeatureSource/TileHierarchy.ts
Normal file
0
Logic/FeatureSource/TiledFeatureSource/TileHierarchy.ts
Normal file
|
@ -0,0 +1,40 @@
|
|||
import FilteredLayer from "../../../Models/FilteredLayer";
|
||||
import {FeatureSourceForLayer} from "../FeatureSource";
|
||||
import {UIEventSource} from "../../UIEventSource";
|
||||
import Loc from "../../../Models/Loc";
|
||||
import GeoJsonSource from "../GeoJsonSource";
|
||||
import DynamicTileSource from "./DynamicTileSource";
|
||||
|
||||
export default class DynamicGeoJsonTileSource extends DynamicTileSource {
|
||||
constructor(layer: FilteredLayer,
|
||||
registerLayer: (layer: FeatureSourceForLayer) => void,
|
||||
state: {
|
||||
locationControl: UIEventSource<Loc>
|
||||
leafletMap: any
|
||||
}) {
|
||||
const source = layer.layerDef.source
|
||||
if (source.geojsonZoomLevel === undefined) {
|
||||
throw "Invalid layer: geojsonZoomLevel expected"
|
||||
}
|
||||
if (source.geojsonSource === undefined) {
|
||||
throw "Invalid layer: geojsonSource expected"
|
||||
}
|
||||
|
||||
super(
|
||||
layer,
|
||||
source.geojsonZoomLevel,
|
||||
(xy) => {
|
||||
const xyz: [number, number, number] = [xy[0], xy[1], source.geojsonZoomLevel]
|
||||
const src = new GeoJsonSource(
|
||||
layer,
|
||||
xyz
|
||||
)
|
||||
registerLayer(src)
|
||||
return src
|
||||
},
|
||||
state
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue