| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  | import { OsmNode, OsmObject, OsmWay } from "../../Osm/OsmObject" | 
					
						
							|  |  |  | import { UIEventSource } from "../../UIEventSource" | 
					
						
							|  |  |  | import { BBox } from "../../BBox" | 
					
						
							|  |  |  | import StaticFeatureSource from "../Sources/StaticFeatureSource" | 
					
						
							|  |  |  | import { Tiles } from "../../../Models/TileRange" | 
					
						
							| 
									
										
										
										
											2021-10-31 02:08:39 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  | export default class FullNodeDatabaseSource { | 
					
						
							| 
									
										
										
										
											2023-06-01 02:52:21 +02:00
										 |  |  |     private readonly loadedTiles = new Map<number, Map<number, OsmNode>>() | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     private readonly nodeByIds = new Map<number, OsmNode>() | 
					
						
							| 
									
										
										
										
											2021-12-30 20:41:45 +01:00
										 |  |  |     private readonly parentWays = new Map<number, UIEventSource<OsmWay[]>>() | 
					
						
							| 
									
										
										
										
											2021-11-03 00:44:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-01 02:52:21 +02:00
										 |  |  |     private smallestZoom = 99 | 
					
						
							|  |  |  |     private largestZoom = 0 | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |     public handleOsmJson(osmJson: any, z: number, x: number, y: number): void { | 
					
						
							| 
									
										
										
										
											2021-10-31 02:08:39 +01:00
										 |  |  |         const allObjects = OsmObject.ParseObjects(osmJson.elements) | 
					
						
							|  |  |  |         const nodesById = new Map<number, OsmNode>() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-01 02:52:21 +02:00
										 |  |  |         this.smallestZoom = Math.min(this.smallestZoom, z) | 
					
						
							|  |  |  |         this.largestZoom = Math.max(this.largestZoom, z) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-31 02:08:39 +01:00
										 |  |  |         for (const osmObj of allObjects) { | 
					
						
							|  |  |  |             if (osmObj.type !== "node") { | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             const osmNode = <OsmNode>osmObj | 
					
						
							| 
									
										
										
										
											2021-10-31 02:08:39 +01:00
										 |  |  |             nodesById.set(osmNode.id, osmNode) | 
					
						
							| 
									
										
										
										
											2021-12-23 03:36:03 +01:00
										 |  |  |             this.nodeByIds.set(osmNode.id, osmNode) | 
					
						
							| 
									
										
										
										
											2021-10-31 02:08:39 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (const osmObj of allObjects) { | 
					
						
							|  |  |  |             if (osmObj.type !== "way") { | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             const osmWay = <OsmWay>osmObj | 
					
						
							| 
									
										
										
										
											2021-10-31 02:08:39 +01:00
										 |  |  |             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) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     src.addCallback((parentWays) => { | 
					
						
							| 
									
										
										
										
											2021-12-30 20:41:45 +01:00
										 |  |  |                         const tgs = nodesById.get(nodeId).tags | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                         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
										 |  |  |                     }) | 
					
						
							| 
									
										
										
										
											2021-10-31 02:08:39 +01:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-12-30 20:41:45 +01:00
										 |  |  |                 const src = this.parentWays.get(nodeId) | 
					
						
							|  |  |  |                 src.data.push(osmWay) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 src.ping() | 
					
						
							| 
									
										
										
										
											2021-10-31 02:08:39 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-03-23 01:42:47 +01:00
										 |  |  |         const asGeojsonFeatures = Array.from(nodesById.values()).map((osmNode) => | 
					
						
							|  |  |  |             osmNode.asGeoJson() | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2021-10-31 02:08:39 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-01 02:52:21 +02:00
										 |  |  |         const featureSource = new StaticFeatureSource(asGeojsonFeatures) | 
					
						
							|  |  |  |         const tileId = Tiles.tile_index(z, x, y) | 
					
						
							|  |  |  |         this.loadedTiles.set(tileId, nodesById) | 
					
						
							| 
									
										
										
										
											2021-10-31 02:08:39 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-11-03 00:44:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2023-06-01 02:52:21 +02:00
										 |  |  |      * Gets all the ways that the given node is a part of | 
					
						
							| 
									
										
										
										
											2021-12-30 20:41:45 +01:00
										 |  |  |      * @param nodeId | 
					
						
							|  |  |  |      * @constructor | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public GetParentWays(nodeId: number): UIEventSource<OsmWay[]> { | 
					
						
							|  |  |  |         return this.parentWays.get(nodeId) | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-01 02:52:21 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Gets (at least) all nodes which are part of this BBOX; might also return some nodes that fall outside of the bbox but are closeby | 
					
						
							|  |  |  |      * @param bbox | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |     getNodesWithin(bbox: BBox): Map<number, OsmNode> { | 
					
						
							| 
									
										
										
										
											2023-06-01 02:52:21 +02:00
										 |  |  |         const allById = new Map<number, OsmNode>() | 
					
						
							|  |  |  |         for (let z = this.smallestZoom; z < this.largestZoom; z++) { | 
					
						
							|  |  |  |             const range = Tiles.tileRangeFrom(bbox, z) | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |             Tiles.MapRange(range, (x, y) => { | 
					
						
							| 
									
										
										
										
											2023-06-01 02:52:21 +02:00
										 |  |  |                 const tileId = Tiles.tile_index(z, x, y) | 
					
						
							|  |  |  |                 const nodesById = this.loadedTiles.get(tileId) | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |                 nodesById?.forEach((v, k) => allById.set(k, v)) | 
					
						
							| 
									
										
										
										
											2023-06-01 02:52:21 +02:00
										 |  |  |             }) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return allById | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-11-03 00:44:53 +01:00
										 |  |  | } |