From a30444278f64a5f33a443b8a8ba16db827a007fb Mon Sep 17 00:00:00 2001 From: Rafael Araujo Lehmkuhl Date: Wed, 29 Oct 2025 09:38:01 -0300 Subject: [PATCH] wip --- src/components/widgets/Map.vue | 240 +++++++++++++++++++++++++++++++-- src/stores/mission.ts | 4 +- 2 files changed, 230 insertions(+), 14 deletions(-) diff --git a/src/components/widgets/Map.vue b/src/components/widgets/Map.vue index 45a1c6bebf..82236ac3b3 100644 --- a/src/components/widgets/Map.vue +++ b/src/components/widgets/Map.vue @@ -110,7 +110,7 @@ - + Map widget settings + + + + Custom WMS Service + + + + + + + + + + + + + + + + + + + + + Apply WMS Configuration + @@ -297,6 +399,18 @@ onBeforeMount(() => { if (widget.value.options.showCoordinateGrid === undefined) { widget.value.options.showCoordinateGrid = false } + // Initialize WMS options with defaults if they don't exist + if (widget.value.options.wmsEnabled === undefined) { + widget.value.options.wmsEnabled = true + widget.value.options.wmsUrl = 'http://10.144.37.83:40801/geoserver/ows' + widget.value.options.wmsLayers = 'dct:height_grid_layer_view_2m_aggregated' + widget.value.options.wmsLayerName = 'Bathymetry Height Data (2m)' + widget.value.options.wmsFormat = 'image/png' + widget.value.options.wmsVersion = '1.3.0' + widget.value.options.wmsTransparent = true + widget.value.options.wmsMaxZoom = 19 + widget.value.options.wmsAttribution = '' + } targetFollower.enableAutoUpdate() }) @@ -332,14 +446,41 @@ const marineProfile = L.tileLayer.wms('https://geoserver.openseamap.org/geoserve maxZoom: 19, }) +// Custom WMS layer (will be created dynamically) +const customWmsLayer = ref(undefined) + +const createCustomWmsLayer = (): L.TileLayer.WMS | undefined => { + if (!widget.value.options.wmsEnabled || !widget.value.options.wmsUrl || !widget.value.options.wmsLayers) { + return undefined + } + + return L.tileLayer.wms(widget.value.options.wmsUrl, { + layers: widget.value.options.wmsLayers, + format: widget.value.options.wmsFormat || 'image/png', + transparent: widget.value.options.wmsTransparent ?? true, + version: widget.value.options.wmsVersion || '1.1.1', + attribution: widget.value.options.wmsAttribution || '', + maxZoom: widget.value.options.wmsMaxZoom || 19, + }) +} + const baseMaps = { 'OpenStreetMap': osm, 'Esri World Imagery': esri, } -const overlays = { - 'Seamarks': seamarks, - 'Marine Profile': marineProfile, +const getOverlays = (): { [key: string]: L.Layer } => { + const overlayMap: { [key: string]: L.Layer } = { + 'Seamarks': seamarks, + 'Marine Profile': marineProfile, + } + + if (customWmsLayer.value) { + const layerName = widget.value.options.wmsLayerName || 'Custom WMS' + overlayMap[layerName] = customWmsLayer.value as unknown as L.Layer + } + + return overlayMap } // Show buttons when the mouse is over the widget @@ -347,26 +488,85 @@ const mapBase = ref() const isMouseOver = useElementHover(mapBase) const zoomControl = L.control.zoom({ position: 'bottomright' }) -const layerControl = L.control.layers(baseMaps, overlays) +const layerControl = ref(undefined) const gridLayer = ref(undefined) +// Function to recreate the layer control with updated overlays +const updateLayerControl = (): void => { + if (!map.value) return + + // Remove existing layer control if present + if (layerControl.value) { + map.value.removeControl(layerControl.value) + } + + // Create new layer control with updated overlays + const updatedOverlays = getOverlays() + layerControl.value = L.control.layers(baseMaps, updatedOverlays) + + // Add to map if buttons are visible + if (showButtons.value) { + map.value.addControl(layerControl.value) + } +} + +// Function to apply WMS configuration +const applyWmsConfig = (): void => { + if (!map.value) { + openSnackbar({ message: 'Map is not initialized yet', variant: 'warning' }) + return + } + + if (!widget.value.options.wmsUrl || !widget.value.options.wmsLayers) { + openSnackbar({ message: 'Please provide both WMS URL and Layers', variant: 'warning' }) + return + } + + try { + // Remove old custom WMS layer if it exists + if (customWmsLayer.value && map.value.hasLayer(customWmsLayer.value as unknown as L.Layer)) { + map.value.removeLayer(customWmsLayer.value as unknown as L.Layer) + } + + // Create new custom WMS layer + customWmsLayer.value = createCustomWmsLayer() + + // Update the layer control to include the new layer + updateLayerControl() + + openSnackbar({ + message: 'WMS layer configured successfully! Use the layer control to toggle visibility.', + variant: 'success', + duration: 4000, + }) + } catch (error) { + console.error('Failed to configure WMS layer:', error) + openSnackbar({ + message: `Failed to configure WMS layer: ${(error as Error).message}`, + variant: 'error', + }) + } +} + watch(showButtons, () => { if (map.value === undefined) return if (showButtons.value) { map.value.addControl(zoomControl) - map.value.addControl(layerControl) + if (layerControl.value) { + map.value.addControl(layerControl.value) + } else { + updateLayerControl() + } createScaleControl() } else { map.value.removeControl(zoomControl) - map.value.removeControl(layerControl) + if (layerControl.value) { + map.value.removeControl(layerControl.value) + } removeScaleControl() } }) -watch(isMouseOver, () => { - showButtons.value = isMouseOver.value -}) - // Watch for grid overlay option changes watch( () => widget.value.options.showCoordinateGrid, @@ -440,15 +640,31 @@ onMounted(async () => { mapBase.value?.addEventListener('touchstart', onTouchStart, { passive: true }) mapBase.value?.addEventListener('touchend', onTouchEnd, { passive: true }) + // Initialize custom WMS layer if configuration exists + if (widget.value.options.wmsEnabled && widget.value.options.wmsUrl && widget.value.options.wmsLayers) { + customWmsLayer.value = createCustomWmsLayer() + } + + // Build initial layers array - only include base layers by default + const initialLayers: L.Layer[] = [osm, esri] + + // Add custom WMS layer if enabled + if (customWmsLayer.value) { + initialLayers.push(customWmsLayer.value as unknown as L.Layer) + } + // Bind leaflet instance to map element map.value = L.map(mapId.value, { - layers: [osm, esri, seamarks, marineProfile], + layers: initialLayers, attributionControl: false, }).setView(mapCenter.value as LatLngTuple, zoom.value) as Map // Remove default zoom control map.value.removeControl(map.value.zoomControl) + // Initialize layer control + updateLayerControl() + map.value.on('click', (event: LeafletMouseEvent) => { clickedLocation.value = [event.latlng.lat, event.latlng.lng] }) diff --git a/src/stores/mission.ts b/src/stores/mission.ts index 3e5dd22057..186c027e09 100644 --- a/src/stores/mission.ts +++ b/src/stores/mission.ts @@ -18,8 +18,8 @@ import { import { useMainVehicleStore } from './mainVehicle' -// Default map position (centered on Florianópolis, Brazil) -const DEFAULT_MAP_CENTER: WaypointCoordinates = [-27.5935, -48.55854] +// Default map position (centered on Hawaii) +const DEFAULT_MAP_CENTER: WaypointCoordinates = [19.669511014021392, -156.0242794325606] const DEFAULT_MAP_ZOOM = 15 export const useMissionStore = defineStore('mission', () => {