| 
									
										
										
										
											2022-10-27 01:50:41 +02:00
										 |  |  | import { ReadonlyInputElement } from "./InputElement" | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | import Loc from "../../Models/Loc" | 
					
						
							| 
									
										
										
										
											2022-10-27 01:50:41 +02:00
										 |  |  | import { Store, UIEventSource } from "../../Logic/UIEventSource" | 
					
						
							|  |  |  | import Minimap, { MinimapObj } from "../Base/Minimap" | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | import BaseLayer from "../../Models/BaseLayer" | 
					
						
							|  |  |  | import Combine from "../Base/Combine" | 
					
						
							|  |  |  | import Svg from "../../Svg" | 
					
						
							| 
									
										
										
										
											2022-10-27 01:50:41 +02:00
										 |  |  | import { GeoOperations } from "../../Logic/GeoOperations" | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | import ShowDataMultiLayer from "../ShowDataLayer/ShowDataMultiLayer" | 
					
						
							|  |  |  | import StaticFeatureSource from "../../Logic/FeatureSource/Sources/StaticFeatureSource" | 
					
						
							|  |  |  | import LayerConfig from "../../Models/ThemeConfig/LayerConfig" | 
					
						
							| 
									
										
										
										
											2022-10-27 01:50:41 +02:00
										 |  |  | import { BBox } from "../../Logic/BBox" | 
					
						
							|  |  |  | import { FixedUiElement } from "../Base/FixedUiElement" | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | import ShowDataLayer from "../ShowDataLayer/ShowDataLayer" | 
					
						
							|  |  |  | import BaseUIElement from "../BaseUIElement" | 
					
						
							|  |  |  | import Toggle from "./Toggle" | 
					
						
							| 
									
										
										
										
											2023-02-08 01:14:21 +01:00
										 |  |  | import matchpoint from "../../assets/layers/matchpoint/matchpoint.json" | 
					
						
							| 
									
										
										
										
											2022-10-27 01:50:41 +02:00
										 |  |  | import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig" | 
					
						
							|  |  |  | import FilteredLayer from "../../Models/FilteredLayer" | 
					
						
							|  |  |  | import { ElementStorage } from "../../Logic/ElementStorage" | 
					
						
							|  |  |  | import AvailableBaseLayers from "../../Logic/Actors/AvailableBaseLayers" | 
					
						
							|  |  |  | import { RelationId, WayId } from "../../Models/OsmFeature" | 
					
						
							|  |  |  | import { Feature, LineString, Polygon } from "geojson" | 
					
						
							|  |  |  | import { OsmObject, OsmWay } from "../../Logic/Osm/OsmObject" | 
					
						
							| 
									
										
										
										
											2022-01-18 18:52:42 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | export default class LocationInput | 
					
						
							|  |  |  |     extends BaseUIElement | 
					
						
							| 
									
										
										
										
											2022-10-27 01:50:41 +02:00
										 |  |  |     implements ReadonlyInputElement<Loc>, MinimapObj | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     private static readonly matchLayer = new LayerConfig( | 
					
						
							|  |  |  |         matchpoint, | 
					
						
							|  |  |  |         "LocationInput.matchpoint", | 
					
						
							|  |  |  |         true | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2021-10-19 03:00:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-27 01:50:41 +02:00
										 |  |  |     public readonly snappedOnto: UIEventSource<Feature & { properties: { id: WayId } }> = | 
					
						
							|  |  |  |         new UIEventSource(undefined) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     public readonly _matching_layer: LayerConfig | 
					
						
							| 
									
										
										
										
											2021-10-19 03:00:57 +02:00
										 |  |  |     public readonly leafletMap: UIEventSource<any> | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     public readonly bounds | 
					
						
							|  |  |  |     public readonly location | 
					
						
							| 
									
										
										
										
											2022-09-12 20:14:03 +02:00
										 |  |  |     private readonly _centerLocation: UIEventSource<Loc> | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     private readonly mapBackground: UIEventSource<BaseLayer> | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * The features to which the input should be snapped | 
					
						
							|  |  |  |      * @private | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-10-27 01:50:41 +02:00
										 |  |  |     private readonly _snapTo: Store< | 
					
						
							|  |  |  |         (Feature<LineString | Polygon> & { properties: { id: WayId } })[] | 
					
						
							|  |  |  |     > | 
					
						
							| 
									
										
										
										
											2022-09-21 02:22:22 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * The features to which the input should be snapped without cleanup of relations and memberships | 
					
						
							|  |  |  |      * Used for rendering | 
					
						
							|  |  |  |      * @private | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-10-27 01:50:41 +02:00
										 |  |  |     private readonly _snapToRaw: Store<{ feature: Feature }[]> | 
					
						
							| 
									
										
										
										
											2022-06-05 02:24:14 +02:00
										 |  |  |     private readonly _value: Store<Loc> | 
					
						
							|  |  |  |     private readonly _snappedPoint: Store<any> | 
					
						
							| 
									
										
										
										
											2021-08-07 21:19:01 +02:00
										 |  |  |     private readonly _maxSnapDistance: number | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     private readonly _snappedPointTags: any | 
					
						
							|  |  |  |     private readonly _bounds: UIEventSource<BBox> | 
					
						
							|  |  |  |     private readonly map: BaseUIElement & MinimapObj | 
					
						
							|  |  |  |     private readonly clickLocation: UIEventSource<Loc> | 
					
						
							|  |  |  |     private readonly _minZoom: number | 
					
						
							| 
									
										
										
										
											2022-09-14 12:18:51 +02:00
										 |  |  |     private readonly _state: { | 
					
						
							| 
									
										
										
										
											2022-10-27 01:50:41 +02:00
										 |  |  |         readonly filteredLayers: Store<FilteredLayer[]> | 
					
						
							|  |  |  |         readonly backgroundLayer: UIEventSource<BaseLayer> | 
					
						
							|  |  |  |         readonly layoutToUse: LayoutConfig | 
					
						
							|  |  |  |         readonly selectedElement: UIEventSource<any> | 
					
						
							| 
									
										
										
										
											2022-09-14 12:18:51 +02:00
										 |  |  |         readonly allElements: ElementStorage | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-07-14 00:17:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-21 02:22:22 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Given a list of geojson-features, will prepare these features to be snappable: | 
					
						
							|  |  |  |      * - points are removed | 
					
						
							|  |  |  |      * - LineStrings are passed as-is | 
					
						
							|  |  |  |      * - Multipolygons are decomposed into their member ways by downloading them | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @private | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-10-27 01:50:41 +02:00
										 |  |  |     private static async prepareSnapOnto( | 
					
						
							|  |  |  |         features: Feature[] | 
					
						
							|  |  |  |     ): Promise<(Feature<LineString | Polygon> & { properties: { id: WayId } })[]> { | 
					
						
							|  |  |  |         const linesAndPolygon: Feature<LineString | Polygon>[] = <any>( | 
					
						
							|  |  |  |             features.filter((f) => f.geometry.type !== "Point") | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2022-09-21 02:22:22 +02:00
										 |  |  |         // Clean the features: multipolygons are split into their it's members
 | 
					
						
							| 
									
										
										
										
											2022-10-27 01:50:41 +02:00
										 |  |  |         const linestrings: (Feature<LineString | Polygon> & { properties: { id: WayId } })[] = [] | 
					
						
							| 
									
										
										
										
											2022-09-21 02:22:22 +02:00
										 |  |  |         for (const feature of linesAndPolygon) { | 
					
						
							| 
									
										
										
										
											2022-10-27 01:50:41 +02:00
										 |  |  |             if (feature.properties.id.startsWith("way")) { | 
					
						
							| 
									
										
										
										
											2022-09-21 02:22:22 +02:00
										 |  |  |                 // A normal way - we continue
 | 
					
						
							| 
									
										
										
										
											2022-10-27 01:50:41 +02:00
										 |  |  |                 linestrings.push(<any>feature) | 
					
						
							| 
									
										
										
										
											2022-09-21 02:22:22 +02:00
										 |  |  |                 continue | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // We have a multipolygon, thus: a relation
 | 
					
						
							|  |  |  |             // Download the members
 | 
					
						
							| 
									
										
										
										
											2022-10-27 01:50:41 +02:00
										 |  |  |             const relation = await OsmObject.DownloadObjectAsync( | 
					
						
							|  |  |  |                 <RelationId>feature.properties.id, | 
					
						
							|  |  |  |                 60 * 60 | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |             const members: OsmWay[] = await Promise.all( | 
					
						
							|  |  |  |                 relation.members | 
					
						
							|  |  |  |                     .filter((m) => m.type === "way") | 
					
						
							|  |  |  |                     .map((m) => OsmObject.DownloadObjectAsync(<WayId>("way/" + m.ref), 60 * 60)) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |             linestrings.push(...members.map((m) => m.asGeoJson())) | 
					
						
							| 
									
										
										
										
											2022-09-21 02:22:22 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         return linestrings | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-17 03:24:01 +02:00
										 |  |  |     constructor(options?: { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         minZoom?: number | 
					
						
							|  |  |  |         mapBackground?: UIEventSource<BaseLayer> | 
					
						
							| 
									
										
										
										
											2022-09-21 02:22:22 +02:00
										 |  |  |         snapTo?: UIEventSource<{ feature: Feature }[]> | 
					
						
							| 
									
										
										
										
											2023-01-16 11:58:24 +01:00
										 |  |  |         renderLayerForSnappedPoint?: LayerConfig | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         maxSnapDistance?: number | 
					
						
							|  |  |  |         snappedPointTags?: any | 
					
						
							|  |  |  |         requiresSnapping?: boolean | 
					
						
							| 
									
										
										
										
											2022-09-17 03:24:01 +02:00
										 |  |  |         centerLocation?: UIEventSource<Loc> | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |         bounds?: UIEventSource<BBox> | 
					
						
							| 
									
										
										
										
											2022-09-17 03:24:01 +02:00
										 |  |  |         state?: { | 
					
						
							| 
									
										
										
										
											2022-10-27 01:50:41 +02:00
										 |  |  |             readonly filteredLayers: Store<FilteredLayer[]> | 
					
						
							|  |  |  |             readonly backgroundLayer: UIEventSource<BaseLayer> | 
					
						
							|  |  |  |             readonly layoutToUse: LayoutConfig | 
					
						
							|  |  |  |             readonly selectedElement: UIEventSource<any> | 
					
						
							| 
									
										
										
										
											2022-09-14 12:18:51 +02:00
										 |  |  |             readonly allElements: ElementStorage | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-07-14 00:17:15 +02:00
										 |  |  |     }) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         super() | 
					
						
							| 
									
										
										
										
											2022-10-27 01:50:41 +02:00
										 |  |  |         this._snapToRaw = options?.snapTo?.map((feats) => | 
					
						
							|  |  |  |             feats.filter((f) => f.feature.geometry.type !== "Point") | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         this._snapTo = options?.snapTo | 
					
						
							|  |  |  |             ?.bind((features) => | 
					
						
							|  |  |  |                 UIEventSource.FromPromise( | 
					
						
							|  |  |  |                     LocationInput.prepareSnapOnto(features.map((f) => f.feature)) | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |             ?.map((f) => f ?? []) | 
					
						
							| 
									
										
										
										
											2022-09-17 03:24:01 +02:00
										 |  |  |         this._maxSnapDistance = options?.maxSnapDistance | 
					
						
							| 
									
										
										
										
											2022-10-27 01:50:41 +02:00
										 |  |  |         this._centerLocation = | 
					
						
							|  |  |  |             options?.centerLocation ?? | 
					
						
							|  |  |  |             new UIEventSource<Loc>({ | 
					
						
							|  |  |  |                 lat: 0, | 
					
						
							|  |  |  |                 lon: 0, | 
					
						
							|  |  |  |                 zoom: 0, | 
					
						
							|  |  |  |             }) | 
					
						
							| 
									
										
										
										
											2022-09-17 03:24:01 +02:00
										 |  |  |         this._snappedPointTags = options?.snappedPointTags | 
					
						
							|  |  |  |         this._bounds = options?.bounds | 
					
						
							|  |  |  |         this._minZoom = options?.minZoom | 
					
						
							|  |  |  |         this._state = options?.state | 
					
						
							| 
									
										
										
										
											2023-01-16 11:58:24 +01:00
										 |  |  |         const self = this | 
					
						
							| 
									
										
										
										
											2021-08-07 21:19:01 +02:00
										 |  |  |         if (this._snapTo === undefined) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             this._value = this._centerLocation | 
					
						
							| 
									
										
										
										
											2021-08-07 21:19:01 +02:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2023-01-16 11:58:24 +01:00
										 |  |  |             this._matching_layer = options?.renderLayerForSnappedPoint ?? LocationInput.matchLayer | 
					
						
							| 
									
										
										
										
											2021-08-07 21:19:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-21 02:22:22 +02:00
										 |  |  |             // Calculate the location of the point based by snapping it onto a way
 | 
					
						
							|  |  |  |             // As a side-effect, the actual snapped-onto way (if any) is saved into 'snappedOnto'
 | 
					
						
							| 
									
										
										
										
											2022-09-17 03:24:01 +02:00
										 |  |  |             this._snappedPoint = this._centerLocation.map( | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 (loc) => { | 
					
						
							|  |  |  |                     if (loc === undefined) { | 
					
						
							|  |  |  |                         return undefined | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     // We reproject the location onto every 'snap-to-feature' and select the closest
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     let min = undefined | 
					
						
							| 
									
										
										
										
											2022-10-27 01:50:41 +02:00
										 |  |  |                     let matchedWay: Feature<LineString | Polygon> & { properties: { id: WayId } } = | 
					
						
							|  |  |  |                         undefined | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     for (const feature of self._snapTo.data ?? []) { | 
					
						
							|  |  |  |                         try { | 
					
						
							| 
									
										
										
										
											2022-09-21 02:22:22 +02:00
										 |  |  |                             const nearestPointOnLine = GeoOperations.nearestPoint(feature, [ | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                                 loc.lon, | 
					
						
							|  |  |  |                                 loc.lat, | 
					
						
							|  |  |  |                             ]) | 
					
						
							|  |  |  |                             if (min === undefined) { | 
					
						
							| 
									
										
										
										
											2023-03-15 22:02:29 +01:00
										 |  |  |                                 min = { ...nearestPointOnLine } | 
					
						
							| 
									
										
										
										
											2022-09-21 02:22:22 +02:00
										 |  |  |                                 matchedWay = feature | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                                 continue | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                             if (min.properties.dist > nearestPointOnLine.properties.dist) { | 
					
						
							| 
									
										
										
										
											2023-03-15 22:02:29 +01:00
										 |  |  |                                 min = { ...nearestPointOnLine } | 
					
						
							| 
									
										
										
										
											2022-09-21 02:22:22 +02:00
										 |  |  |                                 matchedWay = feature | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                             } | 
					
						
							|  |  |  |                         } catch (e) { | 
					
						
							|  |  |  |                             console.log( | 
					
						
							|  |  |  |                                 "Snapping to a nearest point failed for ", | 
					
						
							| 
									
										
										
										
											2022-09-21 02:22:22 +02:00
										 |  |  |                                 feature, | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                                 "due to ", | 
					
						
							|  |  |  |                                 e | 
					
						
							|  |  |  |                             ) | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  |                         } | 
					
						
							| 
									
										
										
										
											2021-10-31 02:08:39 +01:00
										 |  |  |                     } | 
					
						
							| 
									
										
										
										
											2021-08-07 21:19:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     if (min === undefined || min.properties.dist * 1000 > self._maxSnapDistance) { | 
					
						
							| 
									
										
										
										
											2022-09-17 03:24:01 +02:00
										 |  |  |                         if (options?.requiresSnapping) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                             return undefined | 
					
						
							|  |  |  |                         } else { | 
					
						
							| 
									
										
										
										
											2022-09-21 02:22:22 +02:00
										 |  |  |                             // No match found - the original coordinates are returned as is
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                             return { | 
					
						
							|  |  |  |                                 type: "Feature", | 
					
						
							| 
									
										
										
										
											2022-09-17 03:24:01 +02:00
										 |  |  |                                 properties: options?.snappedPointTags ?? min.properties, | 
					
						
							| 
									
										
										
										
											2022-10-27 01:50:41 +02:00
										 |  |  |                                 geometry: { type: "Point", coordinates: [loc.lon, loc.lat] }, | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                             } | 
					
						
							| 
									
										
										
										
											2021-08-07 21:19:01 +02:00
										 |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2022-09-17 03:24:01 +02:00
										 |  |  |                     min.properties = options?.snappedPointTags ?? min.properties | 
					
						
							| 
									
										
										
										
											2023-03-15 22:02:29 +01:00
										 |  |  |                     min.properties = { | 
					
						
							|  |  |  |                         ...min.properties, | 
					
						
							|  |  |  |                         _referencing_ways: JSON.stringify([matchedWay.properties.id]), | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2022-10-27 01:50:41 +02:00
										 |  |  |                     self.snappedOnto.setData(<any>matchedWay) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     return min | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |                 [this._snapTo] | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             this._value = this._snappedPoint.map((f) => { | 
					
						
							|  |  |  |                 const [lon, lat] = f.geometry.coordinates | 
					
						
							| 
									
										
										
										
											2021-08-07 21:19:01 +02:00
										 |  |  |                 return { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     lon: lon, | 
					
						
							|  |  |  |                     lat: lat, | 
					
						
							|  |  |  |                     zoom: undefined, | 
					
						
							| 
									
										
										
										
											2021-08-07 21:19:01 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-10-27 01:50:41 +02:00
										 |  |  |         this.mapBackground = | 
					
						
							|  |  |  |             options?.mapBackground ?? | 
					
						
							|  |  |  |             this._state?.backgroundLayer ?? | 
					
						
							|  |  |  |             new UIEventSource<BaseLayer>(AvailableBaseLayers.osmCarto) | 
					
						
							| 
									
										
										
										
											2021-07-14 00:17:15 +02:00
										 |  |  |         this.SetClass("block h-full") | 
					
						
							| 
									
										
										
										
											2021-10-11 00:54:35 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         this.clickLocation = new UIEventSource<Loc>(undefined) | 
					
						
							|  |  |  |         this.map = Minimap.createMiniMap({ | 
					
						
							|  |  |  |             location: this._centerLocation, | 
					
						
							|  |  |  |             background: this.mapBackground, | 
					
						
							| 
									
										
										
										
											2022-09-14 12:18:51 +02:00
										 |  |  |             attribution: this.mapBackground !== this._state?.backgroundLayer, | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             lastClickLocation: this.clickLocation, | 
					
						
							|  |  |  |             bounds: this._bounds, | 
					
						
							|  |  |  |             addLayerControl: true, | 
					
						
							|  |  |  |         }) | 
					
						
							| 
									
										
										
										
											2021-10-13 03:09:37 +02:00
										 |  |  |         this.leafletMap = this.map.leafletMap | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         this.location = this.map.location | 
					
						
							| 
									
										
										
										
											2021-07-14 00:17:15 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-05 02:24:14 +02:00
										 |  |  |     GetValue(): Store<Loc> { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         return this._value | 
					
						
							| 
									
										
										
										
											2021-07-14 00:17:15 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     IsValid(t: Loc): boolean { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         return t !== undefined | 
					
						
							| 
									
										
										
										
											2021-07-14 00:17:15 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-10-19 03:00:57 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     installBounds(factor: number | BBox, showRange?: boolean): void { | 
					
						
							|  |  |  |         this.map.installBounds(factor, showRange) | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-14 00:17:15 +02:00
										 |  |  |     protected InnerConstructElement(): HTMLElement { | 
					
						
							| 
									
										
										
										
											2021-08-07 21:19:01 +02:00
										 |  |  |         try { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             const self = this | 
					
						
							| 
									
										
										
										
											2021-10-14 03:46:09 +02:00
										 |  |  |             const hasMoved = new UIEventSource(false) | 
					
						
							| 
									
										
										
										
											2022-10-27 01:50:41 +02:00
										 |  |  |             const startLocation = { ...this._centerLocation.data } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             this._centerLocation.addCallbackD((newLocation) => { | 
					
						
							| 
									
										
										
										
											2021-10-15 19:58:02 +02:00
										 |  |  |                 const f = 100000 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 const diff = | 
					
						
							|  |  |  |                     Math.abs(newLocation.lon * f - startLocation.lon * f) + | 
					
						
							|  |  |  |                     Math.abs(newLocation.lat * f - startLocation.lat * f) | 
					
						
							| 
									
										
										
										
											2021-10-19 03:00:57 +02:00
										 |  |  |                 if (diff < 1) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     return | 
					
						
							| 
									
										
										
										
											2021-10-15 19:58:02 +02:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-10-14 03:46:09 +02:00
										 |  |  |                 hasMoved.setData(true) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 return true | 
					
						
							| 
									
										
										
										
											2021-10-14 03:46:09 +02:00
										 |  |  |             }) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             this.clickLocation.addCallbackAndRunD((location) => | 
					
						
							|  |  |  |                 this._centerLocation.setData(location) | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2022-09-21 02:22:22 +02:00
										 |  |  |             if (this._snapToRaw !== undefined) { | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |                 // Show the lines to snap to
 | 
					
						
							|  |  |  |                 new ShowDataMultiLayer({ | 
					
						
							| 
									
										
										
										
											2022-09-21 02:22:22 +02:00
										 |  |  |                     features: StaticFeatureSource.fromDateless(this._snapToRaw), | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     zoomToFeatures: false, | 
					
						
							|  |  |  |                     leafletMap: this.map.leafletMap, | 
					
						
							| 
									
										
										
										
											2022-09-14 12:18:51 +02:00
										 |  |  |                     layers: this._state.filteredLayers, | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 }) | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |                 // Show the central point
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 const matchPoint = this._snappedPoint.map((loc) => { | 
					
						
							| 
									
										
										
										
											2021-08-07 21:19:01 +02:00
										 |  |  |                     if (loc === undefined) { | 
					
						
							|  |  |  |                         return [] | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2022-10-27 01:50:41 +02:00
										 |  |  |                     return [{ feature: loc }] | 
					
						
							| 
									
										
										
										
											2021-08-07 21:19:01 +02:00
										 |  |  |                 }) | 
					
						
							| 
									
										
										
										
											2022-06-05 02:24:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-16 11:58:24 +01:00
										 |  |  |                 // The 'matchlayer' is the layer which shows the target location
 | 
					
						
							| 
									
										
										
										
											2021-10-19 03:00:57 +02:00
										 |  |  |                 new ShowDataLayer({ | 
					
						
							| 
									
										
										
										
											2022-06-05 02:24:14 +02:00
										 |  |  |                     features: StaticFeatureSource.fromDateless(matchPoint), | 
					
						
							| 
									
										
										
										
											2021-10-19 03:00:57 +02:00
										 |  |  |                     zoomToFeatures: false, | 
					
						
							|  |  |  |                     leafletMap: this.map.leafletMap, | 
					
						
							|  |  |  |                     layerToShow: this._matching_layer, | 
					
						
							| 
									
										
										
										
											2022-09-14 12:18:51 +02:00
										 |  |  |                     state: this._state, | 
					
						
							|  |  |  |                     selectedElement: this._state.selectedElement, | 
					
						
							| 
									
										
										
										
											2021-10-19 03:00:57 +02:00
										 |  |  |                 }) | 
					
						
							| 
									
										
										
										
											2021-07-14 00:17:15 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             this.mapBackground.map( | 
					
						
							|  |  |  |                 (layer) => { | 
					
						
							|  |  |  |                     const leaflet = this.map.leafletMap.data | 
					
						
							|  |  |  |                     if (leaflet === undefined || layer === undefined) { | 
					
						
							|  |  |  |                         return | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2021-08-07 21:19:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     leaflet.setMaxZoom(layer.max_zoom) | 
					
						
							|  |  |  |                     leaflet.setMinZoom(self._minZoom ?? layer.max_zoom - 2) | 
					
						
							|  |  |  |                     leaflet.setZoom(layer.max_zoom - 1) | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |                 [this.map.leafletMap] | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2021-10-19 03:00:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-29 19:48:36 +02:00
										 |  |  |             const animatedHand = Svg.hand_ui() | 
					
						
							|  |  |  |                 .SetStyle("width: 2rem; height: unset;") | 
					
						
							|  |  |  |                 .SetClass("hand-drag-animation block pointer-events-none") | 
					
						
							| 
									
										
										
										
											2021-10-19 03:00:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-07 21:19:01 +02:00
										 |  |  |             return new Combine([ | 
					
						
							|  |  |  |                 new Combine([ | 
					
						
							| 
									
										
										
										
											2021-09-08 01:36:44 +02:00
										 |  |  |                     Svg.move_arrows_ui() | 
					
						
							|  |  |  |                         .SetClass("block relative pointer-events-none") | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                         .SetStyle("left: -2.5rem; top: -2.5rem; width: 5rem; height: 5rem"), | 
					
						
							|  |  |  |                 ]) | 
					
						
							|  |  |  |                     .SetClass("block w-0 h-0 z-10 relative") | 
					
						
							|  |  |  |                     .SetStyle( | 
					
						
							|  |  |  |                         "background: rgba(255, 128, 128, 0.21); left: 50%; top: 50%; opacity: 0.5" | 
					
						
							|  |  |  |                     ), | 
					
						
							| 
									
										
										
										
											2021-10-19 03:00:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 new Toggle(undefined, animatedHand, hasMoved) | 
					
						
							| 
									
										
										
										
											2021-09-29 19:48:36 +02:00
										 |  |  |                     .SetClass("block w-0 h-0 z-10 relative") | 
					
						
							|  |  |  |                     .SetStyle("left: calc(50% + 3rem); top: calc(50% + 2rem); opacity: 0.7"), | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 this.map.SetClass("z-0 relative block w-full h-full bg-gray-100"), | 
					
						
							|  |  |  |             ]).ConstructElement() | 
					
						
							| 
									
										
										
										
											2021-08-07 21:19:01 +02:00
										 |  |  |         } catch (e) { | 
					
						
							|  |  |  |             console.error("Could not generate LocationInputElement:", e) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             return new FixedUiElement("Constructing a locationInput failed due to" + e) | 
					
						
							|  |  |  |                 .SetClass("alert") | 
					
						
							|  |  |  |                 .ConstructElement() | 
					
						
							| 
									
										
										
										
											2021-08-07 21:19:01 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-07-14 00:17:15 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-12 20:14:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-27 01:50:41 +02:00
										 |  |  |     TakeScreenshot(format: "image"): Promise<string> | 
					
						
							|  |  |  |     TakeScreenshot(format: "blob"): Promise<Blob> | 
					
						
							|  |  |  |     TakeScreenshot(format: "image" | "blob"): Promise<string | Blob> | 
					
						
							| 
									
										
										
										
											2022-09-14 12:18:51 +02:00
										 |  |  |     TakeScreenshot(format: "image" | "blob"): Promise<string | Blob> { | 
					
						
							|  |  |  |         return this.map.TakeScreenshot(format) | 
					
						
							| 
									
										
										
										
											2022-09-12 20:14:03 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | } |