From e93dd9b8678c4b498babe38ef251a3810839f4ed Mon Sep 17 00:00:00 2001 From: livio Date: Tue, 22 Sep 2026 10:47:35 +0200 Subject: [PATCH] Generate missing imported sheet outline --- Components/Pages/Home.razor | 14 +++--- LMEMappeCatastaliApp.csproj | 4 +- Services/AzureMapsService.cs | 2 +- Services/NetworkLocationService.cs | 2 +- wwwroot/js/lme-map.js | 76 ++++++++++++++++++++++++++++-- 5 files changed, 81 insertions(+), 17 deletions(-) diff --git a/Components/Pages/Home.razor b/Components/Pages/Home.razor index 57b6dcd..171e6b0 100644 --- a/Components/Pages/Home.razor +++ b/Components/Pages/Home.razor @@ -161,7 +161,7 @@ @@ -170,7 +170,7 @@ : "Disattivato: importa solo i poligoni delle particelle riconosciute.") La cornice grande resta separata dalle particelle e puo essere nascosta anche nei progetti salvati. @@ -295,7 +295,7 @@

Visualizzazione progetto

Il comando agisce subito sulla mappa e sui dati del progetto caricato. @@ -973,18 +973,16 @@ } private Task AddProjectMarker() => JS.InvokeVoidAsync("lmeMap.addProjectMarker", PoiName).AsTask(); - private async Task ToggleKmlSheetLayer(ChangeEventArgs args) + private async Task ApplyKmlSheetLayerOption() { - IncludeKmlSheetLayer = (bool?)args.Value == true; ShowImportedSheetLayer = IncludeKmlSheetLayer; await JS.InvokeVoidAsync("lmeMap.setIncludeKmlSheetLayer", IncludeKmlSheetLayer); await JS.InvokeVoidAsync("lmeMap.setImportedSheetLayerVisible", ShowImportedSheetLayer); } - private async Task ToggleImportedSheetLayer(ChangeEventArgs args) + private Task ApplyImportedSheetLayerVisibility() { - ShowImportedSheetLayer = (bool?)args.Value == true; - await JS.InvokeVoidAsync("lmeMap.setImportedSheetLayerVisible", ShowImportedSheetLayer); + return JS.InvokeVoidAsync("lmeMap.setImportedSheetLayerVisible", ShowImportedSheetLayer).AsTask(); } private async Task ToggleImportedMeasurements(ChangeEventArgs args) diff --git a/LMEMappeCatastaliApp.csproj b/LMEMappeCatastaliApp.csproj index 91d563d..d067e8e 100644 --- a/LMEMappeCatastaliApp.csproj +++ b/LMEMappeCatastaliApp.csproj @@ -28,8 +28,8 @@ com.companyname.lmemappecatastaliapp - 0.2.15 - 19 + 0.2.16 + 20 None diff --git a/Services/AzureMapsService.cs b/Services/AzureMapsService.cs index ecc3a03..31a5d1f 100644 --- a/Services/AzureMapsService.cs +++ b/Services/AzureMapsService.cs @@ -13,7 +13,7 @@ public sealed class AzureMapsService public AzureMapsService() { - _httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("LMEMappeCatastali/0.2.15"); + _httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("LMEMappeCatastali/0.2.16"); _httpClient.DefaultRequestHeaders.Accept.ParseAdd("application/json"); } diff --git a/Services/NetworkLocationService.cs b/Services/NetworkLocationService.cs index 8adeb3e..26d8033 100644 --- a/Services/NetworkLocationService.cs +++ b/Services/NetworkLocationService.cs @@ -13,7 +13,7 @@ public sealed class NetworkLocationService public NetworkLocationService() { - httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("LMEMappeCatastali/0.2.15"); + httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("LMEMappeCatastali/0.2.16"); } public async Task GetApproximateLocationAsync( diff --git a/wwwroot/js/lme-map.js b/wwwroot/js/lme-map.js index cce2a41..68ab857 100644 --- a/wwwroot/js/lme-map.js +++ b/wwwroot/js/lme-map.js @@ -132,6 +132,8 @@ function init() { }); lmeState.currentBase = lmeState.baseLayers.satellite.addTo(lmeState.map); + const importedSheetPane = lmeState.map.createPane("importedSheetPane"); + importedSheetPane.style.zIndex = "520"; lmeState.imported = L.featureGroup().addTo(lmeState.map); lmeState.importedSheets = L.featureGroup(); lmeState.drawings = L.featureGroup().addTo(lmeState.map); @@ -887,13 +889,76 @@ function setIncludeKmlSheetLayer(enabled) { function setImportedSheetLayerVisible(enabled) { migrateMisclassifiedImportedSheets(); lmeState.importedSheetsVisible = Boolean(enabled); + const generated = lmeState.importedSheetsVisible && ensureImportedSheetOutline(); applyImportedSheetVisibility(); const count = lmeState.importedSheets?.toGeoJSON()?.features?.length || 0; setInfo(lmeState.importedSheetsVisible - ? (count ? `Layer del foglio importato visibile (${count} elementi).` : "Nessun layer del foglio importato: ricarica il KML/KMZ con 'includi anche il layer del foglio' attivo.") + ? (count + ? `${generated ? "Cornice generata dai dati importati" : "Layer del foglio importato visibile"} (${count} elementi).` + : "Nessun dato importato da cui ricavare la cornice del foglio.") : "Layer del foglio importato nascosto; le particelle restano visibili."); } +function ensureImportedSheetOutline() { + if (!lmeState.imported || !lmeState.importedSheets) { + return false; + } + + const currentSheets = lmeState.importedSheets.toGeoJSON(); + const hasAreaOutline = (currentSheets.features || []).some(feature => + ["Polygon", "MultiPolygon"].includes(feature?.geometry?.type)); + if (hasAreaOutline) { + return false; + } + + const imported = lmeState.imported.toGeoJSON(); + const points = collectGeoJsonCoordinates(imported); + if (!points.length) { + return false; + } + + const bounds = points.reduce((result, point) => ({ + west: Math.min(result.west, point[0]), + south: Math.min(result.south, point[1]), + east: Math.max(result.east, point[0]), + north: Math.max(result.north, point[1]) + }), { west: Infinity, south: Infinity, east: -Infinity, north: -Infinity }); + if (!Number.isFinite(bounds.west) + || !Number.isFinite(bounds.south) + || bounds.east <= bounds.west + || bounds.north <= bounds.south) { + return false; + } + + const longitudePadding = Math.max((bounds.east - bounds.west) * 0.01, 0.000001); + const latitudePadding = Math.max((bounds.north - bounds.south) * 0.01, 0.000001); + const west = bounds.west - longitudePadding; + const south = bounds.south - latitudePadding; + const east = bounds.east + longitudePadding; + const north = bounds.north + latitudePadding; + addImportedSheetFeatures({ + type: "FeatureCollection", + features: [{ + type: "Feature", + properties: { + name: "Cornice del foglio importato", + _lmeGeneratedSheetOutline: true + }, + geometry: { + type: "Polygon", + coordinates: [[ + [west, south], + [east, south], + [east, north], + [west, north], + [west, south] + ]] + } + }] + }); + return true; +} + function migrateMisclassifiedImportedSheets() { if (!lmeState.imported || !lmeState.importedSheets) { return 0; @@ -928,8 +993,10 @@ function addImportedFeatures(geojson) { function addImportedSheetFeatures(geojson) { return L.geoJSON(geojson || emptyFeatureCollection(), { + pane: "importedSheetPane", style: { color: "#f59e0b", weight: 4, opacity: 1, fillOpacity: 0.03, dashArray: "10 6" }, pointToLayer: (feature, latlng) => L.circleMarker(latlng, { + pane: "importedSheetPane", radius: 7, color: "#f59e0b", fillColor: "#ffffff", @@ -948,10 +1015,6 @@ function applyImportedSheetVisibility() { lmeState.importedSheets.addTo(lmeState.map); } lmeState.importedSheets.bringToFront(); - lmeState.imported.bringToFront(); - lmeState.selectedParcelsLayer.bringToFront(); - lmeState.gpsParcelLayer.bringToFront(); - lmeState.drawings.bringToFront(); return; } if (lmeState.map.hasLayer(lmeState.importedSheets)) { @@ -1568,6 +1631,9 @@ function loadProjectSnapshot(raw, projectName) { lmeState.importedSheetsVisible = projectDisplayOptions ? Boolean(projectDisplayOptions.importedSheetsVisible) : data.schemaVersion >= 2 && Boolean(data.importedSheetsVisible); + if (lmeState.importedSheetsVisible) { + ensureImportedSheetOutline(); + } applyImportedSheetVisibility(); L.geoJSON(data.selectedParcels || emptyFeatureCollection(), { style: { color: "#ef4444", weight: 4, opacity: 1, fillColor: "#fbbf24", fillOpacity: 0.26 },