| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  | <script lang="ts"> | 
					
						
							| 
									
										
										
										
											2024-02-20 13:33:38 +01: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" | 
					
						
							|  |  |  |   import { createEventDispatcher } from "svelte" | 
					
						
							|  |  |  |   import Move_arrows from "../../assets/svg/Move_arrows.svelte" | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-20 13:33:38 +01:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * An advanced location input, which has support to: | 
					
						
							|  |  |  |    * - Show more layers | 
					
						
							|  |  |  |    * - Snap to layers | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * This one is mostly used to insert new points, including when importing | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   export let state: SpecialVisualizationState | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |    * The start coordinate | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   export let coordinate: { lon: number; lat: number } | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-20 13:33:38 +01:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * The center of the map at all times | 
					
						
							|  |  |  |    * If undefined at the beginning, 'coordinate' will be used | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   export let value: UIEventSource<{ lon: number; lat: number }> | 
					
						
							|  |  |  |   if (value.data === undefined) { | 
					
						
							|  |  |  |     value.setData(coordinate) | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (coordinate === undefined) { | 
					
						
							|  |  |  |     coordinate = value.data | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   export let snapToLayers: string[] | undefined | 
					
						
							|  |  |  |   export let targetLayer: LayerConfig | undefined | 
					
						
							|  |  |  |   export let maxSnapDistance: number = undefined | 
					
						
							| 
									
										
										
										
											2023-06-15 16:12:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-20 13:33:38 +01:00
										 |  |  |   export let snappedTo: UIEventSource<string | undefined> | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-20 13:33:38 +01:00
										 |  |  |   let preciseLocation: UIEventSource<{ lon: number; lat: number }> = new UIEventSource<{ | 
					
						
							|  |  |  |     lon: number | 
					
						
							|  |  |  |     lat: number | 
					
						
							|  |  |  |   }>(undefined) | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-20 13:33:38 +01:00
										 |  |  |   const dispatch = createEventDispatcher<{ click: { lon: number; lat: number } }>() | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-20 13:33:38 +01:00
										 |  |  |   const xyz = Tiles.embedded_tile(coordinate.lat, coordinate.lon, 16) | 
					
						
							|  |  |  |   const map: UIEventSource<MlMap> = new UIEventSource<MlMap>(undefined) | 
					
						
							|  |  |  |   let initialMapProperties: Partial<MapProperties> & { location } = { | 
					
						
							|  |  |  |     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), | 
					
						
							|  |  |  |     minzoom: new UIEventSource<number>(18), | 
					
						
							|  |  |  |     rasterLayer: UIEventSource.feedFrom(state.mapProperties.rasterLayer), | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-20 13:33:38 +01:00
										 |  |  |   if (targetLayer) { | 
					
						
							|  |  |  |     const featuresForLayer = state.perLayer.get(targetLayer.id) | 
					
						
							|  |  |  |     if (featuresForLayer) { | 
					
						
							|  |  |  |       new ShowDataLayer(map, { | 
					
						
							|  |  |  |         layer: targetLayer, | 
					
						
							|  |  |  |         features: featuresForLayer, | 
					
						
							|  |  |  |       }) | 
					
						
							| 
									
										
										
										
											2024-01-31 11:37:09 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-02-20 13:33:38 +01:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2024-01-16 04:20:25 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-20 13:33:38 +01:00
										 |  |  |   if (snapToLayers?.length > 0) { | 
					
						
							|  |  |  |     const snapSources: FeatureSource[] = [] | 
					
						
							|  |  |  |     for (const layerId of snapToLayers ?? []) { | 
					
						
							| 
									
										
										
										
											2024-02-24 21:05:46 +01:00
										 |  |  |       // We assume that the layer contains the data, as the OSM-API-Feature-source should have loaded them, even though the layer might not be displayed | 
					
						
							| 
									
										
										
										
											2024-02-20 13:33:38 +01:00
										 |  |  |       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, | 
					
						
							|  |  |  |       }) | 
					
						
							| 
									
										
										
										
											2024-01-16 04:20:25 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-02-20 13:33:38 +01:00
										 |  |  |     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, | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     new ShowDataLayer(map, { | 
					
						
							|  |  |  |       layer: targetLayer, | 
					
						
							|  |  |  |       features: snappedLocation, | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  | </script> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  | <LocationInput | 
					
						
							|  |  |  |   {map} | 
					
						
							| 
									
										
										
										
											2024-01-16 04:20:25 +01:00
										 |  |  |   on:click={(data) => dispatch("click", data)} | 
					
						
							| 
									
										
										
										
											2024-01-31 11:37:09 +01:00
										 |  |  |   mapProperties={initialMapProperties} | 
					
						
							| 
									
										
										
										
											2023-06-14 20:39:36 +02:00
										 |  |  |   value={preciseLocation} | 
					
						
							| 
									
										
										
										
											2024-01-31 11:37:09 +01:00
										 |  |  |   initialCoordinate={coordinate} | 
					
						
							|  |  |  |   maxDistanceInMeters={50} | 
					
						
							| 
									
										
										
										
											2023-10-15 10:55:56 +02:00
										 |  |  | > | 
					
						
							|  |  |  |   <slot name="image" slot="image"> | 
					
						
							| 
									
										
										
										
											2023-12-01 15:23:28 +01:00
										 |  |  |     <Move_arrows class="h-full max-h-24" /> | 
					
						
							| 
									
										
										
										
											2023-10-15 10:55:56 +02:00
										 |  |  |   </slot> | 
					
						
							|  |  |  | </LocationInput> |