forked from MapComplete/MapComplete
Full code cleanup
This commit is contained in:
parent
3a4a2a2016
commit
fa971ffbbf
300 changed files with 16352 additions and 19284 deletions
|
@ -14,7 +14,7 @@ class MetatagUpdater {
|
|||
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) {
|
||||
|
@ -31,14 +31,14 @@ class MetatagUpdater {
|
|||
if (oldBbox === undefined) {
|
||||
self.neededLayerBboxes.set(layerId, bbox);
|
||||
} else if (!bbox.isContainedIn(oldBbox)) {
|
||||
self.neededLayerBboxes.set(layerId,oldBbox.unionWith(bbox))
|
||||
self.neededLayerBboxes.set(layerId, oldBbox.unionWith(bbox))
|
||||
}
|
||||
return featurePipeline.GetFeaturesWithin(layerId, bbox)
|
||||
},
|
||||
memberships: featurePipeline.relationTracker
|
||||
}
|
||||
this.isDirty.stabilized(100).addCallback(dirty => {
|
||||
if(dirty){
|
||||
if (dirty) {
|
||||
self.updateMetaTags()
|
||||
}
|
||||
})
|
||||
|
@ -46,10 +46,10 @@ class MetatagUpdater {
|
|||
|
||||
}
|
||||
|
||||
public requestUpdate(){
|
||||
public requestUpdate() {
|
||||
this.isDirty.setData(true)
|
||||
}
|
||||
|
||||
|
||||
private updateMetaTags() {
|
||||
const features = this.source.features.data
|
||||
|
||||
|
@ -74,7 +74,8 @@ export default class MetaTagRecalculator {
|
|||
};
|
||||
private _featurePipeline: FeaturePipeline;
|
||||
private readonly _alreadyRegistered: Set<FeatureSourceForLayer & Tiled> = new Set<FeatureSourceForLayer & Tiled>()
|
||||
private readonly _notifiers : MetatagUpdater[] = []
|
||||
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
|
||||
|
@ -92,16 +93,16 @@ private readonly _notifiers : MetatagUpdater[] = []
|
|||
return;
|
||||
}
|
||||
this._alreadyRegistered.add(source)
|
||||
this._notifiers.push(new MetatagUpdater(source,this._state,this._featurePipeline))
|
||||
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 ) {
|
||||
for (const updater of self._notifiers) {
|
||||
const neededBbox = updater.neededLayerBboxes.get(layerName)
|
||||
if(neededBbox == undefined){
|
||||
if (neededBbox == undefined) {
|
||||
continue
|
||||
}
|
||||
if(source.bbox === undefined || neededBbox.overlapsWith(source.bbox)){
|
||||
if (source.bbox === undefined || neededBbox.overlapsWith(source.bbox)) {
|
||||
updater.requestUpdate()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ export default class SaveTileToLocalStorageActor {
|
|||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
public LoadTilesFromDisk(currentBounds: UIEventSource<BBox>, location: UIEventSource<Loc>,
|
||||
registerFreshness: (tileId: number, freshness: Date) => void,
|
||||
registerTile: ((src: FeatureSource & Tiled) => void)) {
|
||||
|
@ -55,7 +55,7 @@ export default class SaveTileToLocalStorageActor {
|
|||
}
|
||||
currentBounds.addCallbackAndRunD(bbox => {
|
||||
|
||||
if(self._layer.minzoomVisible > location.data.zoom){
|
||||
if (self._layer.minzoomVisible > location.data.zoom) {
|
||||
// Not enough zoom
|
||||
return;
|
||||
}
|
||||
|
@ -119,9 +119,9 @@ export default class SaveTileToLocalStorageActor {
|
|||
}
|
||||
|
||||
private SetIdb(tileIndex, data) {
|
||||
try{
|
||||
try {
|
||||
IdbLocalStorage.SetDirectly(this._layer.id + "_" + tileIndex, data)
|
||||
}catch(e){
|
||||
} catch (e) {
|
||||
console.error("Could not save tile to indexed-db: ", e, "tileIndex is:", tileIndex, "for layer", this._layer.id)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,40 +43,33 @@ export default class FeaturePipeline {
|
|||
public readonly timeout: UIEventSource<number>;
|
||||
public readonly somethingLoaded: UIEventSource<boolean> = new UIEventSource<boolean>(false)
|
||||
public readonly newDataLoadedSignal: UIEventSource<FeatureSource> = new UIEventSource<FeatureSource>(undefined)
|
||||
|
||||
|
||||
|
||||
public readonly relationTracker: RelationsTracker
|
||||
/**
|
||||
* Keeps track of all raw OSM-nodes.
|
||||
* Only initialized if 'type_node' is defined as layer
|
||||
*/
|
||||
public readonly fullNodeDatabase?: FullNodeDatabaseSource
|
||||
private readonly overpassUpdater: OverpassFeatureSource
|
||||
private state: MapState;
|
||||
public readonly relationTracker: RelationsTracker
|
||||
private readonly perLayerHierarchy: Map<string, TileHierarchyMerger>;
|
||||
|
||||
/**
|
||||
* Keeps track of the age of the loaded data.
|
||||
* Has one freshness-Calculator for every layer
|
||||
* @private
|
||||
*/
|
||||
private readonly freshnesses = new Map<string, TileFreshnessCalculator>();
|
||||
|
||||
private readonly oldestAllowedDate: Date;
|
||||
private readonly osmSourceZoomLevel
|
||||
|
||||
private readonly localStorageSavers = new Map<string, SaveTileToLocalStorageActor>()
|
||||
|
||||
/**
|
||||
* Keeps track of all raw OSM-nodes.
|
||||
* Only initialized if 'type_node' is defined as layer
|
||||
*/
|
||||
public readonly fullNodeDatabase? : FullNodeDatabaseSource
|
||||
|
||||
|
||||
constructor(
|
||||
handleFeatureSource: (source: FeatureSourceForLayer & Tiled) => void,
|
||||
state: MapState,
|
||||
options? : {
|
||||
options?: {
|
||||
/*Used for metatagging - will receive all the sources with changeGeometry applied but without filtering*/
|
||||
handleRawFeatureSource: (source: FeatureSourceForLayer) => void
|
||||
}
|
||||
) {
|
||||
) {
|
||||
this.state = state;
|
||||
|
||||
const self = this
|
||||
|
@ -104,7 +97,7 @@ export default class FeaturePipeline {
|
|||
return location.zoom >= minzoom;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
const neededTilesFromOsm = this.getNeededTilesFromOsm(this.sufficientlyZoomed)
|
||||
|
||||
const perLayerHierarchy = new Map<string, TileHierarchyMerger>()
|
||||
|
@ -114,10 +107,10 @@ export default class FeaturePipeline {
|
|||
function patchedHandleFeatureSource(src: FeatureSourceForLayer & IndexedFeatureSource & Tiled) {
|
||||
// This will already contain the merged features for this tile. In other words, this will only be triggered once for every tile
|
||||
const withChanges = new ChangeGeometryApplicator(src, state.changes);
|
||||
const srcFiltered = new FilteringFeatureSource(state, src.tileIndex,withChanges)
|
||||
const srcFiltered = new FilteringFeatureSource(state, src.tileIndex, withChanges)
|
||||
|
||||
handleFeatureSource(srcFiltered)
|
||||
if(options?.handleRawFeatureSource){
|
||||
if (options?.handleRawFeatureSource) {
|
||||
options.handleRawFeatureSource(withChanges)
|
||||
}
|
||||
self.somethingLoaded.setData(true)
|
||||
|
@ -267,7 +260,7 @@ export default class FeaturePipeline {
|
|||
})
|
||||
})
|
||||
|
||||
if(this.fullNodeDatabase !== undefined){
|
||||
if (this.fullNodeDatabase !== undefined) {
|
||||
osmFeatureSource.rawDataHandlers.push((osmJson, tileId) => this.fullNodeDatabase.handleOsmJson(osmJson, tileId))
|
||||
}
|
||||
|
||||
|
@ -289,7 +282,7 @@ export default class FeaturePipeline {
|
|||
self.localStorageSavers.get(tile.layer.layerDef.id)?.addTile(tile)
|
||||
perLayerHierarchy.get(source.layer.layerDef.id).registerTile(new RememberingSource(tile))
|
||||
tile.features.addCallbackAndRunD(f => {
|
||||
if(f.length === 0){
|
||||
if (f.length === 0) {
|
||||
return
|
||||
}
|
||||
self.onNewDataLoaded(tile)
|
||||
|
@ -298,9 +291,11 @@ export default class FeaturePipeline {
|
|||
}
|
||||
}),
|
||||
updater,
|
||||
{handleLeftovers: (leftOvers) => {
|
||||
console.warn("Overpass returned a few non-matched features:", leftOvers)
|
||||
}})
|
||||
{
|
||||
handleLeftovers: (leftOvers) => {
|
||||
console.warn("Overpass returned a few non-matched features:", leftOvers)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
// Also load points/lines that are newly added.
|
||||
|
@ -308,7 +303,7 @@ export default class FeaturePipeline {
|
|||
newGeometry.features.addCallbackAndRun(geometries => {
|
||||
console.debug("New geometries are:", geometries)
|
||||
})
|
||||
|
||||
|
||||
new RegisteringAllFromFeatureSourceActor(newGeometry, state.allElements)
|
||||
// A NewGeometryFromChangesFeatureSource does not split per layer, so we do this next
|
||||
new PerLayerFeatureSourceSplitter(state.filteredLayers,
|
||||
|
@ -322,9 +317,11 @@ export default class FeaturePipeline {
|
|||
|
||||
},
|
||||
newGeometry,
|
||||
{handleLeftovers: (leftOvers) => {
|
||||
console.warn("Got some leftovers from the filteredLayers: ", leftOvers)
|
||||
}}
|
||||
{
|
||||
handleLeftovers: (leftOvers) => {
|
||||
console.warn("Got some leftovers from the filteredLayers: ", leftOvers)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
this.runningQuery = updater.runningQuery.map(
|
||||
|
@ -337,10 +334,6 @@ export default class FeaturePipeline {
|
|||
|
||||
}
|
||||
|
||||
private onNewDataLoaded(src: FeatureSource){
|
||||
this.newDataLoadedSignal.setData(src)
|
||||
}
|
||||
|
||||
public GetAllFeaturesWithin(bbox: BBox): any[][] {
|
||||
const self = this
|
||||
const tiles = []
|
||||
|
@ -369,6 +362,10 @@ export default class FeaturePipeline {
|
|||
})
|
||||
}
|
||||
|
||||
private onNewDataLoaded(src: FeatureSource) {
|
||||
this.newDataLoadedSignal.setData(src)
|
||||
}
|
||||
|
||||
private freshnessForVisibleLayers(z: number, x: number, y: number): Date {
|
||||
let oldestDate = undefined;
|
||||
for (const flayer of this.state.filteredLayers.data) {
|
||||
|
@ -378,11 +375,11 @@ export default class FeaturePipeline {
|
|||
if (this.state.locationControl.data.zoom < flayer.layerDef.minzoom) {
|
||||
continue;
|
||||
}
|
||||
if(flayer.layerDef.maxAgeOfCache === 0){
|
||||
if (flayer.layerDef.maxAgeOfCache === 0) {
|
||||
return undefined;
|
||||
}
|
||||
const freshnessCalc = this.freshnesses.get(flayer.layerDef.id)
|
||||
if(freshnessCalc === undefined){
|
||||
if (freshnessCalc === undefined) {
|
||||
console.warn("No freshness tracker found for ", flayer.layerDef.id)
|
||||
return undefined
|
||||
}
|
||||
|
|
|
@ -19,8 +19,8 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti
|
|||
};
|
||||
private readonly _alreadyRegistered = new Set<UIEventSource<any>>();
|
||||
private readonly _is_dirty = new UIEventSource(false)
|
||||
private previousFeatureSet : Set<any> = undefined;
|
||||
|
||||
private previousFeatureSet: Set<any> = undefined;
|
||||
|
||||
constructor(
|
||||
state: {
|
||||
locationControl: UIEventSource<{ zoom: number }>,
|
||||
|
@ -54,7 +54,7 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti
|
|||
self.update()
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
metataggingUpdated?.addCallback(_ => {
|
||||
self._is_dirty.setData(true)
|
||||
})
|
||||
|
@ -66,7 +66,7 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti
|
|||
const self = this;
|
||||
const layer = this.upstream.layer;
|
||||
const features: { feature: any; freshness: Date }[] = (this.upstream.features.data ?? []);
|
||||
const includedFeatureIds = new Set<string>();
|
||||
const includedFeatureIds = new Set<string>();
|
||||
const newFeatures = (features ?? []).filter((f) => {
|
||||
|
||||
self.registerCallback(f.feature)
|
||||
|
@ -97,29 +97,29 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti
|
|||
|
||||
const previousSet = this.previousFeatureSet;
|
||||
this._is_dirty.setData(false)
|
||||
|
||||
|
||||
// Is there any difference between the two sets?
|
||||
if(previousSet !== undefined && previousSet.size === includedFeatureIds.size){
|
||||
if (previousSet !== undefined && previousSet.size === includedFeatureIds.size) {
|
||||
// The size of the sets is the same - they _might_ be identical
|
||||
const newItemFound = Array.from(includedFeatureIds).some(id => !previousSet.has(id))
|
||||
if(!newItemFound){
|
||||
if (!newItemFound) {
|
||||
// We know that:
|
||||
// - The sets have the same size
|
||||
// - Every item from the new set has been found in the old set
|
||||
// which means they are identical!
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Something new has been found!
|
||||
this.features.setData(newFeatures);
|
||||
|
||||
|
||||
}
|
||||
|
||||
private registerCallback(feature: any) {
|
||||
const src = this.state?.allElements?.addOrGetElement(feature)
|
||||
if(src == undefined){
|
||||
if (src == undefined) {
|
||||
return
|
||||
}
|
||||
if (this._alreadyRegistered.has(src)) {
|
||||
|
|
|
@ -65,7 +65,7 @@ export class NewGeometryFromChangesFeatureSource implements FeatureSource {
|
|||
for (const kv of change.tags) {
|
||||
feat.tags[kv.k] = kv.v
|
||||
}
|
||||
const geojson= feat.asGeoJson();
|
||||
const geojson = feat.asGeoJson();
|
||||
allElementStorage.addOrGetElement(geojson)
|
||||
self.features.data.push({feature: geojson, freshness: new Date()})
|
||||
self.features.ping()
|
||||
|
@ -81,7 +81,7 @@ export class NewGeometryFromChangesFeatureSource implements FeatureSource {
|
|||
continue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
try {
|
||||
const tags = {}
|
||||
for (const kv of change.tags) {
|
||||
|
|
|
@ -10,7 +10,7 @@ export default class SimpleFeatureSource implements FeatureSourceForLayer, Tiled
|
|||
public readonly bbox: BBox = BBox.global;
|
||||
public readonly tileIndex: number;
|
||||
|
||||
constructor(layer: FilteredLayer, tileIndex: number, featureSource?: UIEventSource<{ feature:any; freshness: Date }[]>) {
|
||||
constructor(layer: FilteredLayer, tileIndex: number, featureSource?: UIEventSource<{ feature: any; freshness: Date }[]>) {
|
||||
this.name = "SimpleFeatureSource(" + layer.layerDef.id + ")"
|
||||
this.layer = layer
|
||||
this.tileIndex = tileIndex ?? 0;
|
||||
|
|
|
@ -40,7 +40,7 @@ export default class DynamicGeoJsonTileSource extends DynamicTileSource {
|
|||
json => {
|
||||
const data = new Map<number, Set<number>>();
|
||||
for (const x in json) {
|
||||
if(x === "zoom"){
|
||||
if (x === "zoom") {
|
||||
continue
|
||||
}
|
||||
data.set(Number(x), new Set(json[x]))
|
||||
|
@ -91,7 +91,7 @@ export default class DynamicGeoJsonTileSource extends DynamicTileSource {
|
|||
public static RegisterWhitelist(url: string, json: any) {
|
||||
const data = new Map<number, Set<number>>();
|
||||
for (const x in json) {
|
||||
if(x === "zoom"){
|
||||
if (x === "zoom") {
|
||||
continue
|
||||
}
|
||||
data.set(Number(x), new Set(json[x]))
|
||||
|
|
|
@ -44,11 +44,11 @@ export default class DynamicTileSource implements TileHierarchy<FeatureSourceFor
|
|||
return undefined
|
||||
}
|
||||
const tileRange = Tiles.TileRangeBetween(zoomlevel, bounds.getNorth(), bounds.getEast(), bounds.getSouth(), bounds.getWest())
|
||||
if(tileRange.total > 10000){
|
||||
if (tileRange.total > 10000) {
|
||||
console.error("Got a really big tilerange, bounds and location might be out of sync")
|
||||
return undefined
|
||||
}
|
||||
|
||||
|
||||
const needed = Tiles.MapRange(tileRange, (x, y) => Tiles.tile_index(zoomlevel, x, y)).filter(i => !self._loadedTiles.has(i))
|
||||
if (needed.length === 0) {
|
||||
return undefined
|
||||
|
|
|
@ -45,8 +45,8 @@ export default class FullNodeDatabaseSource implements TileHierarchy<FeatureSour
|
|||
for (const nodeId of osmWay.nodes) {
|
||||
|
||||
if (!this.parentWays.has(nodeId)) {
|
||||
const src = new UIEventSource<OsmWay[]>([])
|
||||
this.parentWays.set(nodeId,src)
|
||||
const src = new UIEventSource<OsmWay[]>([])
|
||||
this.parentWays.set(nodeId, src)
|
||||
src.addCallback(parentWays => {
|
||||
const tgs = nodesById.get(nodeId).tags
|
||||
tgs ["parent_ways"] = JSON.stringify(parentWays.map(w => w.tags))
|
||||
|
|
|
@ -89,8 +89,8 @@ export default class OsmFeatureSource {
|
|||
if (z > 20) {
|
||||
throw "This is an absurd high zoom level"
|
||||
}
|
||||
|
||||
if( z < 14){
|
||||
|
||||
if (z < 14) {
|
||||
throw `Zoom ${z} is too much for OSM to handle! Use a higher zoom level!`
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue