forked from MapComplete/MapComplete
		
	
		
			
				
	
	
		
			70 lines
		
	
	
		
			No EOL
		
	
	
		
			2.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			70 lines
		
	
	
		
			No EOL
		
	
	
		
			2.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import TileHierarchy from "./TileHierarchy";
 | |
| import FeatureSource, {FeatureSourceForLayer, Tiled} from "../FeatureSource";
 | |
| import {OsmNode, OsmObject, OsmWay} from "../../Osm/OsmObject";
 | |
| import SimpleFeatureSource from "../Sources/SimpleFeatureSource";
 | |
| import {UIEventSource} from "../../UIEventSource";
 | |
| import FilteredLayer from "../../../Models/FilteredLayer";
 | |
| 
 | |
| 
 | |
| 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
 | |
|     
 | |
|     constructor(
 | |
|         state: {
 | |
|             readonly filteredLayers: UIEventSource<FilteredLayer[]>},
 | |
|             osmFeatureSource: { rawDataHandlers: ((data: any, tileId: number) => void)[] }, 
 | |
|         onTileLoaded: ((tile: Tiled & FeatureSourceForLayer) => void)) {
 | |
|         this.onTileLoaded = onTileLoaded
 | |
|         this.layer = state.filteredLayers.data.filter(l => l.layerDef.id === "type_node")[0]
 | |
|         if(this.layer === undefined){
 | |
|             throw "Weird: tracking all nodes, but layer 'type_node' is not defined"
 | |
|         }
 | |
|         const self = this
 | |
|         osmFeatureSource.rawDataHandlers.push((osmJson, tileId) => self.handleOsmXml(osmJson, tileId))
 | |
|     }
 | |
| 
 | |
|     private handleOsmXml(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)
 | |
|         }
 | |
| 
 | |
|         const parentWaysByNodeId = new Map<number, OsmWay[]>()
 | |
|         for (const osmObj of allObjects) {
 | |
|             if (osmObj.type !== "way") {
 | |
|                 continue
 | |
|             }
 | |
|             const osmWay = <OsmWay>osmObj;
 | |
|             for (const nodeId of osmWay.nodes) {
 | |
| 
 | |
|                 if (!parentWaysByNodeId.has(nodeId)) {
 | |
|                     parentWaysByNodeId.set(nodeId, [])
 | |
|                 }
 | |
|                 parentWaysByNodeId.get(nodeId).push(osmWay)
 | |
|             }
 | |
|         }
 | |
|         parentWaysByNodeId.forEach((allWays, nodeId) => {
 | |
|             nodesById.get(nodeId).tags["parent_ways"] = JSON.stringify(allWays.map(w => w.tags))
 | |
|         })
 | |
|         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)
 | |
| 
 | |
|     }
 | |
|     
 | |
| } |