| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  | import FeatureSource from "../FeatureSource"; | 
					
						
							|  |  |  | import {UIEventSource} from "../../UIEventSource"; | 
					
						
							|  |  |  | import Loc from "../../../Models/Loc"; | 
					
						
							|  |  |  | import FilteredLayer from "../../../Models/FilteredLayer"; | 
					
						
							|  |  |  | import {Utils} from "../../../Utils"; | 
					
						
							|  |  |  | import {OsmObject} from "../../Osm/OsmObject"; | 
					
						
							| 
									
										
										
										
											2021-05-06 01:33:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export default class OsmApiFeatureSource implements FeatureSource { | 
					
						
							|  |  |  |     public readonly features: UIEventSource<{ feature: any; freshness: Date }[]> = new UIEventSource<{ feature: any; freshness: Date }[]>([]); | 
					
						
							|  |  |  |     public readonly name: string = "OsmApiFeatureSource"; | 
					
						
							| 
									
										
										
										
											2021-05-06 03:03:54 +02:00
										 |  |  |     private readonly loadedTiles: Set<string> = new Set<string>(); | 
					
						
							| 
									
										
										
										
											2021-09-10 01:18:51 +02:00
										 |  |  |     private readonly _state: { | 
					
						
							|  |  |  |         leafletMap: UIEventSource<any>; | 
					
						
							|  |  |  |         locationControl: UIEventSource<Loc>, filteredLayers: UIEventSource<FilteredLayer[]>}; | 
					
						
							| 
									
										
										
										
											2021-05-06 03:03:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |     constructor(state: {locationControl: UIEventSource<Loc>, filteredLayers: UIEventSource<FilteredLayer[]>, leafletMap: UIEventSource<any>, | 
					
						
							|  |  |  |     overpassMaxZoom: UIEventSource<number>}) { | 
					
						
							| 
									
										
										
										
											2021-09-10 01:18:51 +02:00
										 |  |  |         this._state = state; | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |         const self = this; | 
					
						
							|  |  |  |         function update(){ | 
					
						
							|  |  |  |             const minZoom = state.overpassMaxZoom.data; | 
					
						
							|  |  |  |             const location = state.locationControl.data | 
					
						
							|  |  |  |             if(minZoom === undefined || location === undefined){ | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-09-10 01:18:51 +02:00
										 |  |  |             if(minZoom < 14){ | 
					
						
							|  |  |  |                 throw "MinZoom should be at least 14 or higher, OSM-api won't work otherwise" | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |             if(location.zoom > minZoom){ | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             self.loadArea() | 
					
						
							| 
									
										
										
										
											2021-09-10 01:18:51 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-05-06 03:03:54 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public load(id: string) { | 
					
						
							| 
									
										
										
										
											2021-07-18 14:52:09 +02:00
										 |  |  |         if (id.indexOf("-") >= 0) { | 
					
						
							| 
									
										
										
										
											2021-05-09 18:56:51 +02:00
										 |  |  |             // Newly added point - not yet in OSM
 | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-05-13 13:04:17 +02:00
										 |  |  |         console.debug("Downloading", id, "from the OSM-API") | 
					
						
							| 
									
										
										
										
											2021-06-30 16:02:46 +02:00
										 |  |  |         OsmObject.DownloadObject(id).addCallbackAndRunD(element => { | 
					
						
							| 
									
										
										
										
											2021-07-18 14:52:09 +02:00
										 |  |  |             try { | 
					
						
							|  |  |  |                 const geojson = element.asGeoJson(); | 
					
						
							|  |  |  |                 geojson.id = geojson.properties.id; | 
					
						
							|  |  |  |                 this.features.setData([{feature: geojson, freshness: element.timestamp}]) | 
					
						
							|  |  |  |             } catch (e) { | 
					
						
							|  |  |  |                 console.error(e) | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-05-06 01:33:09 +02:00
										 |  |  |         }) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-06 03:03:54 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Loads the current inview-area | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-09-10 01:18:51 +02:00
										 |  |  |     public loadArea(z: number = 14): boolean { | 
					
						
							|  |  |  |         const layers = this._state.filteredLayers.data; | 
					
						
							| 
									
										
										
										
											2021-05-06 03:03:54 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         const disabledLayers = layers.filter(layer => layer.layerDef.source.overpassScript !== undefined || layer.layerDef.source.geojsonSource !== undefined) | 
					
						
							|  |  |  |         if (disabledLayers.length > 0) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-09-10 01:18:51 +02:00
										 |  |  |         if (this._state.leafletMap.data === undefined) { | 
					
						
							| 
									
										
										
										
											2021-05-06 03:03:54 +02:00
										 |  |  |             return false; // Not yet inited
 | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-09-10 01:18:51 +02:00
										 |  |  |         const bounds = this._state.leafletMap.data.getBounds() | 
					
						
							| 
									
										
										
										
											2021-05-06 03:03:54 +02:00
										 |  |  |         const tileRange = Utils.TileRangeBetween(z, bounds.getNorth(), bounds.getEast(), bounds.getSouth(), bounds.getWest()) | 
					
						
							|  |  |  |         const self = this; | 
					
						
							|  |  |  |         Utils.MapRange(tileRange, (x, y) => { | 
					
						
							|  |  |  |             const key = x + "/" + y; | 
					
						
							|  |  |  |             if (self.loadedTiles.has(key)) { | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             self.loadedTiles.add(key); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             const bounds = Utils.tile_bounds(z, x, y); | 
					
						
							|  |  |  |             console.log("Loading OSM data tile", z, x, y, " with bounds", bounds) | 
					
						
							|  |  |  |             OsmObject.LoadArea(bounds, objects => { | 
					
						
							| 
									
										
										
										
											2021-07-18 14:52:09 +02:00
										 |  |  |                 const keptGeoJson: { feature: any, freshness: Date }[] = [] | 
					
						
							| 
									
										
										
										
											2021-05-06 03:03:54 +02:00
										 |  |  |                 // Which layer does the object match?
 | 
					
						
							|  |  |  |                 for (const object of objects) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     for (const flayer of layers) { | 
					
						
							|  |  |  |                         const layer = flayer.layerDef; | 
					
						
							|  |  |  |                         const tags = object.tags | 
					
						
							|  |  |  |                         const doesMatch = layer.source.osmTags.matchesProperties(tags); | 
					
						
							|  |  |  |                         if (doesMatch) { | 
					
						
							|  |  |  |                             const geoJson = object.asGeoJson(); | 
					
						
							|  |  |  |                             geoJson._matching_layer_id = layer.id | 
					
						
							| 
									
										
										
										
											2021-07-18 14:52:09 +02:00
										 |  |  |                             keptGeoJson.push({feature: geoJson, freshness: object.timestamp}) | 
					
						
							| 
									
										
										
										
											2021-05-06 03:03:54 +02:00
										 |  |  |                             break; | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 self.features.setData(keptGeoJson) | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-06 01:33:09 +02:00
										 |  |  | } |