| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Fetches a geojson file somewhere and passes it along | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  | import {UIEventSource} from "../../UIEventSource"; | 
					
						
							|  |  |  | import FilteredLayer from "../../../Models/FilteredLayer"; | 
					
						
							|  |  |  | import {Utils} from "../../../Utils"; | 
					
						
							|  |  |  | import {FeatureSourceForLayer, Tiled} from "../FeatureSource"; | 
					
						
							| 
									
										
										
										
											2021-09-26 17:36:39 +02:00
										 |  |  | import {Tiles} from "../../../Models/TileRange"; | 
					
						
							| 
									
										
										
										
											2021-09-28 17:30:48 +02:00
										 |  |  | import {BBox} from "../../BBox"; | 
					
						
							| 
									
										
										
										
											2021-10-27 03:52:19 +02:00
										 |  |  | import {GeoOperations} from "../../GeoOperations"; | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export default class GeoJsonSource implements FeatureSourceForLayer, Tiled { | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     public readonly features: UIEventSource<{ feature: any; freshness: Date }[]>; | 
					
						
							|  |  |  |     public readonly name; | 
					
						
							|  |  |  |     public readonly isOsmCache: boolean | 
					
						
							|  |  |  |     public readonly layer: FilteredLayer; | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |     public readonly tileIndex | 
					
						
							|  |  |  |     public readonly bbox; | 
					
						
							| 
									
										
										
										
											2022-02-11 03:57:39 +01:00
										 |  |  |     private readonly seenids: Set<string>; | 
					
						
							|  |  |  |     private readonly idKey ?: string; | 
					
						
							| 
									
										
										
										
											2021-09-29 17:48:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |     public constructor(flayer: FilteredLayer, | 
					
						
							| 
									
										
										
										
											2022-01-21 01:57:16 +01:00
										 |  |  |                        zxy?: [number, number, number] | BBox, | 
					
						
							| 
									
										
										
										
											2021-09-29 17:48:15 +02:00
										 |  |  |                        options?: { | 
					
						
							| 
									
										
										
										
											2022-02-11 03:57:39 +01:00
										 |  |  |                            featureIdBlacklist?: Set<string> | 
					
						
							| 
									
										
										
										
											2021-09-29 17:48:15 +02:00
										 |  |  |                        }) { | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (flayer.layerDef.source.geojsonZoomLevel !== undefined && zxy === undefined) { | 
					
						
							|  |  |  |             throw "Dynamic layers are not supported. Use 'DynamicGeoJsonTileSource instead" | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.layer = flayer; | 
					
						
							| 
									
										
										
										
											2022-02-11 03:57:39 +01:00
										 |  |  |         this.idKey = flayer.layerDef.source.idKey | 
					
						
							|  |  |  |         this.seenids = options?.featureIdBlacklist ?? new Set<string>() | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |         let url = flayer.layerDef.source.geojsonSource.replace("{layer}", flayer.layerDef.id); | 
					
						
							|  |  |  |         if (zxy !== undefined) { | 
					
						
							| 
									
										
										
										
											2022-01-21 01:57:16 +01:00
										 |  |  |             let tile_bbox: BBox; | 
					
						
							|  |  |  |             if (zxy instanceof BBox) { | 
					
						
							|  |  |  |                 tile_bbox = zxy; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 const [z, x, y] = zxy; | 
					
						
							|  |  |  |                 tile_bbox = BBox.fromTile(z, x, y); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 this.tileIndex = Tiles.tile_index(z, x, y) | 
					
						
							|  |  |  |                 this.bbox = BBox.fromTile(z, x, y) | 
					
						
							|  |  |  |                 url = url | 
					
						
							|  |  |  |                     .replace('{z}', "" + z) | 
					
						
							|  |  |  |                     .replace('{x}', "" + x) | 
					
						
							|  |  |  |                     .replace('{y}', "" + y) | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  |             let bounds: { minLat: number, maxLat: number, minLon: number, maxLon: number } = tile_bbox | 
					
						
							|  |  |  |             if (this.layer.layerDef.source.mercatorCrs) { | 
					
						
							| 
									
										
										
										
											2021-10-27 03:52:19 +02:00
										 |  |  |                 bounds = tile_bbox.toMercator() | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-01-21 01:57:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |             url = url | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  |                 .replace('{y_min}', "" + bounds.minLat) | 
					
						
							|  |  |  |                 .replace('{y_max}', "" + bounds.maxLat) | 
					
						
							|  |  |  |                 .replace('{x_min}', "" + bounds.minLon) | 
					
						
							|  |  |  |                 .replace('{x_max}', "" + bounds.maxLon) | 
					
						
							| 
									
										
										
										
											2021-10-27 03:52:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-21 01:57:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2021-09-26 17:36:39 +02:00
										 |  |  |             this.tileIndex = Tiles.tile_index(0, 0, 0) | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |             this.bbox = BBox.global; | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.name = "GeoJsonSource of " + url; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.isOsmCache = flayer.layerDef.source.isOsmCacheLayer; | 
					
						
							|  |  |  |         this.features = new UIEventSource<{ feature: any; freshness: Date }[]>([]) | 
					
						
							|  |  |  |         this.LoadJSONFrom(url) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private LoadJSONFrom(url: string) { | 
					
						
							|  |  |  |         const eventSource = this.features; | 
					
						
							|  |  |  |         const self = this; | 
					
						
							|  |  |  |         Utils.downloadJson(url) | 
					
						
							|  |  |  |             .then(json => { | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  |                 if (json.features === undefined || json.features === null) { | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |                     return; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 if (self.layer.layerDef.source.mercatorCrs) { | 
					
						
							| 
									
										
										
										
											2021-10-27 03:52:19 +02:00
										 |  |  |                     json = GeoOperations.GeoJsonToWGS84(json) | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2022-01-21 01:57:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |                 const time = new Date(); | 
					
						
							|  |  |  |                 const newFeatures: { feature: any, freshness: Date } [] = [] | 
					
						
							|  |  |  |                 let i = 0; | 
					
						
							|  |  |  |                 let skipped = 0; | 
					
						
							|  |  |  |                 for (const feature of json.features) { | 
					
						
							|  |  |  |                     const props = feature.properties | 
					
						
							|  |  |  |                     for (const key in props) { | 
					
						
							|  |  |  |                         if (typeof props[key] !== "string") { | 
					
						
							| 
									
										
										
										
											2021-09-29 17:48:15 +02:00
										 |  |  |                             // Make sure all the values are string, it crashes stuff otherwise
 | 
					
						
							| 
									
										
										
										
											2022-01-07 04:14:53 +01:00
										 |  |  |                             props[key] = JSON.stringify(props[key]) | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-11 03:57:39 +01:00
										 |  |  |                     if(self.idKey !== undefined){ | 
					
						
							|  |  |  |                         props.id = props[self.idKey] | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                      | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |                     if (props.id === undefined) { | 
					
						
							|  |  |  |                         props.id = url + "/" + i; | 
					
						
							|  |  |  |                         feature.id = url + "/" + i; | 
					
						
							|  |  |  |                         i++; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     if (self.seenids.has(props.id)) { | 
					
						
							|  |  |  |                         skipped++; | 
					
						
							|  |  |  |                         continue; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     self.seenids.add(props.id) | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |                     let freshness: Date = time; | 
					
						
							|  |  |  |                     if (feature.properties["_last_edit:timestamp"] !== undefined) { | 
					
						
							|  |  |  |                         freshness = new Date(props["_last_edit:timestamp"]) | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     newFeatures.push({feature: feature, freshness: freshness}) | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  |                 if (newFeatures.length == 0) { | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |                     return; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 eventSource.setData(eventSource.data.concat(newFeatures)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |             }).catch(msg => console.debug("Could not load geojson layer", url, "due to", msg)) | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |