mapcomplete/Logic/FeatureSource/TiledFeatureSource/FullNodeDatabaseSource.ts

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

87 lines
3.3 KiB
TypeScript
Raw Normal View History

import TileHierarchy from "./TileHierarchy"
import FeatureSource, { FeatureSourceForLayer, Tiled } from "../FeatureSource"
import { OsmNode, OsmObject, OsmWay } from "../../Osm/OsmObject"
import SimpleFeatureSource from "../Sources/SimpleFeatureSource"
import FilteredLayer from "../../../Models/FilteredLayer"
2021-12-30 20:41:45 +01:00
import { UIEventSource } from "../../UIEventSource"
export default class FullNodeDatabaseSource implements TileHierarchy<FeatureSource & Tiled> {
public readonly loadedTiles = new Map<number, FeatureSource & Tiled>()
private readonly onTileLoaded: (tile: Tiled & FeatureSourceForLayer) => void
private readonly layer: FilteredLayer
2021-12-23 03:36:03 +01:00
private readonly nodeByIds = new Map<number, OsmNode>()
2021-12-30 20:41:45 +01:00
private readonly parentWays = new Map<number, UIEventSource<OsmWay[]>>()
constructor(layer: FilteredLayer, onTileLoaded: (tile: Tiled & FeatureSourceForLayer) => void) {
this.onTileLoaded = onTileLoaded
this.layer = layer
if (this.layer === undefined) {
throw "Layer is undefined"
}
}
2021-11-07 16:34:51 +01:00
public handleOsmJson(osmJson: any, tileId: number) {
const allObjects = OsmObject.ParseObjects(osmJson.elements)
const nodesById = new Map<number, OsmNode>()
for (const osmObj of allObjects) {
if (osmObj.type !== "node") {
continue
}
const osmNode = <OsmNode>osmObj
nodesById.set(osmNode.id, osmNode)
2021-12-23 03:36:03 +01:00
this.nodeByIds.set(osmNode.id, osmNode)
}
for (const osmObj of allObjects) {
if (osmObj.type !== "way") {
continue
}
const osmWay = <OsmWay>osmObj
for (const nodeId of osmWay.nodes) {
2021-12-30 20:41:45 +01:00
if (!this.parentWays.has(nodeId)) {
2022-01-26 21:40:38 +01:00
const src = new UIEventSource<OsmWay[]>([])
this.parentWays.set(nodeId, src)
2021-12-30 20:41:45 +01:00
src.addCallback((parentWays) => {
const tgs = nodesById.get(nodeId).tags
tgs["parent_ways"] = JSON.stringify(parentWays.map((w) => w.tags))
tgs["parent_way_ids"] = JSON.stringify(parentWays.map((w) => w.id))
})
}
2021-12-30 20:41:45 +01:00
const src = this.parentWays.get(nodeId)
src.data.push(osmWay)
src.ping()
}
}
const now = new Date()
const asGeojsonFeatures = Array.from(nodesById.values()).map((osmNode) => ({
feature: osmNode.asGeoJson(),
freshness: now,
}))
const featureSource = new SimpleFeatureSource(this.layer, tileId)
featureSource.features.setData(asGeojsonFeatures)
this.loadedTiles.set(tileId, featureSource)
this.onTileLoaded(featureSource)
}
2021-12-23 03:36:03 +01:00
/**
* Returns the OsmNode with the corresponding id (undefined if not found)
* Note that this OsmNode will have a calculated tag 'parent_ways' and 'parent_way_ids', which are resp. stringified lists of parent way tags and ids
* @param id
* @constructor
*/
2021-12-30 20:41:45 +01:00
public GetNode(id: number): OsmNode {
2021-12-23 03:36:03 +01:00
return this.nodeByIds.get(id)
}
2021-12-30 20:41:45 +01:00
/**
* Gets the parent way list
* @param nodeId
* @constructor
*/
public GetParentWays(nodeId: number): UIEventSource<OsmWay[]> {
return this.parentWays.get(nodeId)
}
}