| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  | import {Or, TagsFilter} from "./TagsFilter"; | 
					
						
							|  |  |  | import {UIEventSource} from "../UI/UIEventSource"; | 
					
						
							|  |  |  | import {FilteredLayer} from "./FilteredLayer"; | 
					
						
							| 
									
										
										
										
											2020-07-30 00:59:08 +02:00
										 |  |  | import {Bounds} from "./Bounds"; | 
					
						
							|  |  |  | import {Overpass} from "./Osm/Overpass"; | 
					
						
							|  |  |  | import {Basemap} from "./Leaflet/Basemap"; | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | export class LayerUpdater { | 
					
						
							|  |  |  |     private _map: Basemap; | 
					
						
							|  |  |  |     private _layers: FilteredLayer[]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public readonly runningQuery: UIEventSource<boolean> = new UIEventSource<boolean>(false); | 
					
						
							| 
									
										
										
										
											2020-06-28 02:42:22 +02:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * The previous bounds for which the query has been run | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2020-07-30 00:59:08 +02:00
										 |  |  |     private previousBounds: Bounds; | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     private _overpass: Overpass; | 
					
						
							|  |  |  |     private _minzoom: number; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * The most important layer should go first, as that one gets first pick for the questions | 
					
						
							|  |  |  |      * @param map | 
					
						
							|  |  |  |      * @param minzoom | 
					
						
							|  |  |  |      * @param layers | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     constructor(map: Basemap, | 
					
						
							|  |  |  |                 minzoom: number, | 
					
						
							|  |  |  |                 layers: FilteredLayer[]) { | 
					
						
							|  |  |  |         this._map = map; | 
					
						
							|  |  |  |         this._layers = layers; | 
					
						
							|  |  |  |         this._minzoom = minzoom; | 
					
						
							|  |  |  |         var filters: TagsFilter[] = []; | 
					
						
							|  |  |  |         for (const layer of layers) { | 
					
						
							|  |  |  |             filters.push(layer.filters); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         this._overpass = new Overpass(new Or(filters)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const self = this; | 
					
						
							|  |  |  |         map.Location.addCallback(function () { | 
					
						
							|  |  |  |             self.update(); | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2020-07-24 01:12:57 +02:00
										 |  |  |         self.update(); | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private handleData(geojson: any) { | 
					
						
							| 
									
										
										
										
											2020-07-27 00:14:34 +02:00
										 |  |  |         const self = this; | 
					
						
							|  |  |  |         function renderLayers(layers: FilteredLayer[]) { | 
					
						
							|  |  |  |             if (layers.length === 0) { | 
					
						
							|  |  |  |                 self.runningQuery.setData(false); | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-27 00:14:34 +02:00
										 |  |  |                 if (geojson.features.length > 0) { | 
					
						
							|  |  |  |                     console.log("Got some leftovers: ", geojson) | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             window.setTimeout(() => { | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-27 00:14:34 +02:00
										 |  |  |                 const layer = layers[0]; | 
					
						
							|  |  |  |                 const rest = layers.slice(1, layers.length); | 
					
						
							|  |  |  |                 geojson = layer.SetApplicableData(geojson); | 
					
						
							|  |  |  |                 renderLayers(rest); | 
					
						
							|  |  |  |             }, 50) | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-07-27 00:14:34 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         renderLayers(this._layers); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-24 15:52:21 +02:00
										 |  |  |     private _failCount = 0; | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |     private handleFail(reason: any) { | 
					
						
							| 
									
										
										
										
											2020-07-27 13:04:38 +02:00
										 |  |  |         console.log("QUERY FAILED (retrying in 5 sec)", reason); | 
					
						
							| 
									
										
										
										
											2020-06-27 03:06:51 +02:00
										 |  |  |         this.previousBounds = undefined; | 
					
						
							|  |  |  |         const self = this; | 
					
						
							| 
									
										
										
										
											2020-07-24 15:52:21 +02:00
										 |  |  |         this._failCount++; | 
					
						
							| 
									
										
										
										
											2020-07-25 18:00:08 +02:00
										 |  |  |         window?.setTimeout( | 
					
						
							| 
									
										
										
										
											2020-07-27 13:04:38 +02:00
										 |  |  |             function(){self.update()}, this._failCount * 5000 | 
					
						
							| 
									
										
										
										
											2020-06-27 03:06:51 +02:00
										 |  |  |         ) | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private update(): void { | 
					
						
							|  |  |  |         if (this.IsInBounds()) { | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-07-01 21:21:29 +02:00
										 |  |  |         console.log("Zoom level: ",this._map.map.getZoom(), "Least needed zoom:", this._minzoom) | 
					
						
							|  |  |  |         if (this._map.map.getZoom() < this._minzoom || this._map.Location.data.zoom < this._minzoom) { | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (this.runningQuery.data) { | 
					
						
							|  |  |  |             console.log("Still running a query, skip"); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-07-30 00:59:08 +02:00
										 |  |  |          | 
					
						
							|  |  |  |         const bounds = this._map.map.getBounds(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const diff =0.07; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const n = bounds.getNorth() + diff; | 
					
						
							|  |  |  |         const e = bounds.getEast() +  diff; | 
					
						
							|  |  |  |         const s = bounds.getSouth() - diff; | 
					
						
							|  |  |  |         const w = bounds.getWest() -  diff; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.previousBounds = {north: n, east: e, south: s, west: w}; | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |         this.runningQuery.setData(true); | 
					
						
							|  |  |  |         const self = this; | 
					
						
							| 
									
										
										
										
											2020-07-30 00:59:08 +02:00
										 |  |  |         this._overpass.queryGeoJson(this.previousBounds, | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |             function (data) { | 
					
						
							|  |  |  |                 self.handleData(data) | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             function (reason) { | 
					
						
							|  |  |  |                 self.handleFail(reason) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-30 00:59:08 +02:00
										 |  |  |     | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     private IsInBounds(): boolean { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (this.previousBounds === undefined) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const b = this._map.map.getBounds(); | 
					
						
							|  |  |  |         if (b.getSouth() < this.previousBounds.south) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (b.getNorth() > this.previousBounds.north) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (b.getEast() > this.previousBounds.east) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (b.getWest() < this.previousBounds.west) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |