| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  | import FeatureSource, {FeatureSourceForLayer, Tiled} from "./FeatureSource"; | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  | import {UIEventSource} from "../UIEventSource"; | 
					
						
							|  |  |  | import FilteredLayer from "../../Models/FilteredLayer"; | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  | import SimpleFeatureSource from "./Sources/SimpleFeatureSource"; | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * In some rare cases, some elements are shown on multiple layers (when 'passthrough' is enabled) | 
					
						
							|  |  |  |  * If this is the case, multiple objects with a different _matching_layer_id are generated. | 
					
						
							|  |  |  |  * In any case, this featureSource marks the objects with _matching_layer_id | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | export default class PerLayerFeatureSourceSplitter { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     constructor(layers: UIEventSource<FilteredLayer[]>, | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |                 handleLayerData: (source: FeatureSourceForLayer & Tiled) => void, | 
					
						
							|  |  |  |                 upstream: FeatureSource, | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  |                 options?: { | 
					
						
							|  |  |  |                     tileIndex?: number, | 
					
						
							|  |  |  |                     handleLeftovers?: (featuresWithoutLayer: any[]) => void | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |                 }) { | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |         const knownLayers = new Map<string, FeatureSourceForLayer & Tiled>() | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         function update() { | 
					
						
							| 
									
										
										
										
											2021-11-08 14:18:45 +01:00
										 |  |  |             const features = upstream.features?.data; | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |             if (features === undefined) { | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-01-07 17:31:39 +01:00
										 |  |  |             if (layers.data === undefined || layers.data.length === 0) { | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // We try to figure out (for each feature) in which feature store it should be saved.
 | 
					
						
							|  |  |  |             // Note that this splitter is only run when it is invoked by the overpass feature source, so we can't be sure in which layer it should go
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             const featuresPerLayer = new Map<string, { feature, freshness } []>(); | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |             const noLayerFound = [] | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |             for (const layer of layers.data) { | 
					
						
							|  |  |  |                 featuresPerLayer.set(layer.layerDef.id, []) | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for (const f of features) { | 
					
						
							|  |  |  |                 for (const layer of layers.data) { | 
					
						
							|  |  |  |                     if (layer.layerDef.source.osmTags.matchesProperties(f.feature.properties)) { | 
					
						
							|  |  |  |                         // We have found our matching layer!
 | 
					
						
							| 
									
										
										
										
											2021-12-13 20:51:44 +01:00
										 |  |  |                         featuresPerLayer.get(layer.layerDef.id).push(f) | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |                         if (!layer.layerDef.passAllFeatures) { | 
					
						
							|  |  |  |                             // If not 'passAllFeatures', we are done for this feature
 | 
					
						
							|  |  |  |                             break; | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |                     noLayerFound.push(f) | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // At this point, we have our features per layer as a list
 | 
					
						
							|  |  |  |             // We assign them to the correct featureSources
 | 
					
						
							|  |  |  |             for (const layer of layers.data) { | 
					
						
							|  |  |  |                 const id = layer.layerDef.id; | 
					
						
							|  |  |  |                 const features = featuresPerLayer.get(id) | 
					
						
							|  |  |  |                 if (features === undefined) { | 
					
						
							|  |  |  |                     // No such features for this layer
 | 
					
						
							|  |  |  |                     continue; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 let featureSource = knownLayers.get(id) | 
					
						
							|  |  |  |                 if (featureSource === undefined) { | 
					
						
							|  |  |  |                     // Not yet initialized - now is a good time
 | 
					
						
							| 
									
										
										
										
											2021-09-28 17:30:48 +02:00
										 |  |  |                     featureSource = new SimpleFeatureSource(layer, options?.tileIndex) | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |                     featureSource.features.setData(features) | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |                     knownLayers.set(id, featureSource) | 
					
						
							|  |  |  |                     handleLayerData(featureSource) | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |                 } else { | 
					
						
							|  |  |  |                     featureSource.features.setData(features) | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |             // AT last, the leftovers are handled
 | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  |             if (options?.handleLeftovers !== undefined && noLayerFound.length > 0) { | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |                 options.handleLeftovers(noLayerFound) | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         layers.addCallback(_ => update()) | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |         upstream.features.addCallbackAndRunD(_ => update()) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |