| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  | <script lang="ts"> | 
					
						
							| 
									
										
										
										
											2023-05-18 23:44:15 +02:00
										 |  |  |     import type {SpecialVisualizationState} from "../SpecialVisualization"; | 
					
						
							|  |  |  |     import LocationInput from "../InputElement/Helpers/LocationInput.svelte"; | 
					
						
							|  |  |  |     import {UIEventSource} from "../../Logic/UIEventSource"; | 
					
						
							|  |  |  |     import {Tiles} from "../../Models/TileRange"; | 
					
						
							|  |  |  |     import {Map as MlMap} from "maplibre-gl"; | 
					
						
							|  |  |  |     import {BBox} from "../../Logic/BBox"; | 
					
						
							|  |  |  |     import type {MapProperties} from "../../Models/MapProperties"; | 
					
						
							|  |  |  |     import ShowDataLayer from "../Map/ShowDataLayer"; | 
					
						
							|  |  |  |     import type {FeatureSource, FeatureSourceForLayer} from "../../Logic/FeatureSource/FeatureSource"; | 
					
						
							|  |  |  |     import SnappingFeatureSource from "../../Logic/FeatureSource/Sources/SnappingFeatureSource"; | 
					
						
							|  |  |  |     import FeatureSourceMerger from "../../Logic/FeatureSource/Sources/FeatureSourceMerger"; | 
					
						
							|  |  |  |     import LayerConfig from "../../Models/ThemeConfig/LayerConfig"; | 
					
						
							|  |  |  |     import {Utils} from "../../Utils"; | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-18 23:44:15 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * An advanced location input, which has support to: | 
					
						
							|  |  |  |      * - Show more layers | 
					
						
							|  |  |  |      * - Snap to layers | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * This one is mostly used to insert new points | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     export let state: SpecialVisualizationState; | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * The start coordinate | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     export let coordinate: { lon: number, lat: number }; | 
					
						
							|  |  |  |     export let snapToLayers: string[] | undefined; | 
					
						
							|  |  |  |     export let targetLayer: LayerConfig; | 
					
						
							|  |  |  |     export let maxSnapDistance: number = undefined; | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-18 23:44:15 +02:00
										 |  |  |     export let snappedTo: UIEventSource<string | undefined>; | 
					
						
							| 
									
										
										
										
											2023-05-19 01:37:31 +02:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2023-05-18 23:44:15 +02:00
										 |  |  |     export let value: UIEventSource<{ lon: number, lat: number }>; | 
					
						
							|  |  |  |     if (value.data === undefined) { | 
					
						
							|  |  |  |         value.setData(coordinate); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-18 23:44:15 +02:00
										 |  |  |     let preciseLocation: UIEventSource<{ lon: number, lat: number }> = new UIEventSource<{ | 
					
						
							|  |  |  |         lon: number; | 
					
						
							|  |  |  |         lat: number | 
					
						
							| 
									
										
										
										
											2023-05-19 01:37:31 +02:00
										 |  |  |     }>(undefined); | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2023-05-18 23:44:15 +02:00
										 |  |  |     const xyz = Tiles.embedded_tile(coordinate.lat, coordinate.lon, 16); | 
					
						
							|  |  |  |     const map: UIEventSource<MlMap> = new UIEventSource<MlMap>(undefined); | 
					
						
							|  |  |  |     let initialMapProperties: Partial<MapProperties> = { | 
					
						
							|  |  |  |         zoom: new UIEventSource<number>(19), | 
					
						
							|  |  |  |         maxbounds: new UIEventSource(undefined), | 
					
						
							|  |  |  |         /*If no snapping needed: the value is simply the map location; | 
					
						
							|  |  |  |         * If snapping is needed: the value will be set later on by the snapping feature source | 
					
						
							|  |  |  |         * */ | 
					
						
							|  |  |  |         location: snapToLayers?.length > 0 ? new UIEventSource<{ lon: number; lat: number }>(coordinate) : value, | 
					
						
							|  |  |  |         bounds: new UIEventSource<BBox>(undefined), | 
					
						
							|  |  |  |         allowMoving: new UIEventSource<boolean>(true), | 
					
						
							|  |  |  |         allowZooming: new UIEventSource<boolean>(true), | 
					
						
							| 
									
										
										
										
											2023-05-19 01:37:31 +02:00
										 |  |  |         minzoom: new UIEventSource<number>(18), | 
					
						
							|  |  |  |         rasterLayer: UIEventSource.feedFrom(state.mapProperties.rasterLayer) | 
					
						
							| 
									
										
										
										
											2023-05-18 23:44:15 +02:00
										 |  |  |     }; | 
					
						
							|  |  |  |    | 
					
						
							| 
									
										
										
										
											2023-05-19 01:37:31 +02:00
										 |  |  |      | 
					
						
							|  |  |  |     const featuresForLayer = state.perLayer.get(targetLayer.id) | 
					
						
							|  |  |  |     if(featuresForLayer){ | 
					
						
							|  |  |  |         new ShowDataLayer(map, { | 
					
						
							|  |  |  |             layer: targetLayer, | 
					
						
							|  |  |  |             features: featuresForLayer | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-18 23:44:15 +02:00
										 |  |  |     if (snapToLayers?.length > 0) { | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-18 23:44:15 +02:00
										 |  |  |         const snapSources: FeatureSource[] = []; | 
					
						
							|  |  |  |         for (const layerId of (snapToLayers ?? [])) { | 
					
						
							|  |  |  |             const layer: FeatureSourceForLayer = state.perLayer.get(layerId); | 
					
						
							|  |  |  |             snapSources.push(layer); | 
					
						
							|  |  |  |             if (layer.features === undefined) { | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             new ShowDataLayer(map, { | 
					
						
							|  |  |  |                 layer: layer.layer.layerDef, | 
					
						
							|  |  |  |                 zoomToFeatures: false, | 
					
						
							|  |  |  |                 features: layer | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         const snappedLocation = new SnappingFeatureSource( | 
					
						
							|  |  |  |             new FeatureSourceMerger(...Utils.NoNull(snapSources)), | 
					
						
							|  |  |  |             // We snap to the (constantly updating) map location | 
					
						
							|  |  |  |             initialMapProperties.location, | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 maxDistance: maxSnapDistance ?? 15, | 
					
						
							|  |  |  |                 allowUnsnapped: true, | 
					
						
							|  |  |  |                 snappedTo, | 
					
						
							|  |  |  |                 snapLocation: value | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         ); | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-18 23:44:15 +02:00
										 |  |  |         new ShowDataLayer(map, { | 
					
						
							|  |  |  |             layer: targetLayer, | 
					
						
							|  |  |  |             features: snappedLocation | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </script> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-17 13:57:26 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-18 23:44:15 +02:00
										 |  |  | <LocationInput {map} mapProperties={initialMapProperties} | 
					
						
							| 
									
										
										
										
											2023-05-19 01:37:31 +02:00
										 |  |  |                value={preciseLocation} initialCoordinate={{...coordinate}} maxDistanceInMeters=50 /> |