Skip to content

Commit 8157163

Browse files
pigrecoclaude
andcommitted
Aggiorna versione a 1.4.3: WMS Cartografia Catastale AdE, versione in GUI
Aggiunta opzione per caricare il WMS del Catasto (Agenzia delle Entrate) con 7 sublayer (province, mappe, acque, strade, vestizioni, fabbricati, particelle). Connessione WMS salvata nel profilo QGIS. Layer posizionato sopra eventuali basemap XYZ. Versione plugin nel titolo della finestra. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent f6e7f3b commit 8157163

3 files changed

Lines changed: 137 additions & 15 deletions

File tree

metadata.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
name=WFS Catasto Download Particelle BBox
77
qgisMinimumVersion=3.0
88
description=Download particelle catastali dal WFS dell'Agenzia delle Entrate tramite BBox, selezione poligono, linea con buffer o layer di punti.
9-
version=1.4.2
9+
version=1.4.3
1010
author=Salvatore Fiandaca
1111
email=pigrecoinfinito@gmail.com
1212

@@ -30,6 +30,11 @@ repository=https://github.com/pigreco/wfs_catasto_download_particelle_bbox
3030

3131
hasProcessingProvider=no
3232
changelog=
33+
1.4.3 - Opzione per caricare il WMS Cartografia Catastale dell'Agenzia delle Entrate
34+
(province, mappe, acque, strade, vestizioni, fabbricati, particelle).
35+
Connessione WMS aggiunta automaticamente al profilo QGIS se non presente.
36+
Layer posizionato sopra eventuali basemap XYZ (es. OpenStreetMap).
37+
Versione plugin visualizzata nel titolo della finestra di dialogo.
3338
1.4.2 - Nuova funzione per il calcolatore di campi: get_particella_info($geometry)
3439
nel gruppo 'Catasto'. Restituisce un array con riferimento catastale,
3540
foglio, label, codice comune, geometria WKT, sezione e allegato

wfs_catasto_download_particelle_bbox_d.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
Compatibile con QGIS 3 (Qt5) e QGIS 4 (Qt6).
77
"""
88

9+
import configparser
910
import os
1011

1112
from qgis.PyQt.QtCore import Qt
@@ -44,6 +45,14 @@
4445
_SmoothTransformation = Qt.SmoothTransformation
4546

4647

48+
def _plugin_version():
49+
"""Legge la versione dal file metadata.txt del plugin."""
50+
meta_path = os.path.join(os.path.dirname(__file__), "metadata.txt")
51+
cfg = configparser.ConfigParser()
52+
cfg.read(meta_path)
53+
return cfg.get("general", "version", fallback="")
54+
55+
4756
class AvvisoDialog(QDialog):
4857
"""Finestra di avviso sull'uso responsabile del plugin (una volta per sessione QGIS)."""
4958

@@ -180,7 +189,11 @@ def __init__(self, parent=None, default_buffer_m=50,
180189
self._init_ui()
181190

182191
def _init_ui(self):
183-
self.setWindowTitle("WFS Catasto - Scelta modalità")
192+
ver = _plugin_version()
193+
titolo = "WFS Catasto - Scelta modalità"
194+
if ver:
195+
titolo += f" v{ver}"
196+
self.setWindowTitle(titolo)
184197
self.setMinimumWidth(500)
185198
self.setWindowFlags(
186199
self.windowFlags()
@@ -241,6 +254,12 @@ def _init_ui(self):
241254
self.check_espandi_catastale.setStyleSheet("font-weight: normal;")
242255
self.check_espandi_catastale.setChecked(False)
243256
go_layout.addWidget(self.check_espandi_catastale)
257+
self.check_carica_wms = QCheckBox(
258+
"Carica WMS Cartografia Catastale"
259+
)
260+
self.check_carica_wms.setStyleSheet("font-weight: normal;")
261+
self.check_carica_wms.setChecked(False)
262+
go_layout.addWidget(self.check_carica_wms)
244263
group_opzioni.setLayout(go_layout)
245264
layout.addWidget(group_opzioni)
246265

@@ -447,6 +466,10 @@ def _svg_label(self, filename, max_w=140, max_h=121):
447466
def espandi_catastale(self):
448467
return self.check_espandi_catastale.isChecked()
449468

469+
@property
470+
def carica_wms(self):
471+
return self.check_carica_wms.isChecked()
472+
450473
# ---- Slot ----
451474

452475
def _on_disegna(self):

wfs_catasto_download_particelle_bbox_p.py

Lines changed: 107 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
Qgis,
2222
QgsProject,
2323
QgsVectorLayer,
24+
QgsRasterLayer,
2425
QgsCoordinateReferenceSystem,
2526
QgsCoordinateTransform,
2627
QgsRectangle,
@@ -33,7 +34,7 @@
3334
QgsExpression,
3435
)
3536
from qgis.gui import QgsMapTool, QgsRubberBand
36-
from qgis.PyQt.QtCore import Qt, QVariant, QTimer
37+
from qgis.PyQt.QtCore import Qt, QVariant, QTimer, QSettings
3738
from qgis.PyQt.QtGui import QColor, QIcon
3839
from qgis.PyQt.QtWidgets import (
3940
QAction,
@@ -136,6 +137,20 @@ def _is_point_layer(layer):
136137
# Distanza buffer in metri di default
137138
BUFFER_DISTANCE_M = 50
138139

140+
# WMS Catasto
141+
WMS_BASE_URL = "https://wms.cartografia.agenziaentrate.gov.it/inspire/wms/ows01.php"
142+
WMS_LAYERS = [
143+
"province",
144+
"CP.CadastralZoning",
145+
"acque",
146+
"strade",
147+
"vestizioni",
148+
"fabbricati",
149+
"CP.CadastralParcel",
150+
]
151+
WMS_CONNECTION_NAME = "Catasto AdE"
152+
WMS_LAYER_NAME = "Cartografia Catastale WMS AdE"
153+
139154

140155
# =============================================================================
141156
# FUNZIONI COMUNI
@@ -215,6 +230,68 @@ def _determina_utm_epsg(lon, lat):
215230
return f"EPSG:{epsg}"
216231

217232

233+
def carica_wms_catasto():
234+
"""
235+
Aggiunge la connessione WMS del Catasto al profilo QGIS (se non presente)
236+
e carica un layer WMS combinato nel progetto corrente.
237+
Il layer viene posizionato in fondo al pannello Layer, prima di eventuali basemap XYZ.
238+
"""
239+
# Controlla se il layer WMS è già nel progetto
240+
for layer in QgsProject.instance().mapLayers().values():
241+
if layer.providerType() == "wms" and WMS_BASE_URL in layer.source():
242+
print(f"[WMS] Layer WMS Catasto già presente nel progetto: {layer.name()}")
243+
return
244+
245+
# Aggiungi connessione WMS in QSettings se non presente
246+
settings = QSettings()
247+
key_prefix = f"qgis/connections-wms/{WMS_CONNECTION_NAME}"
248+
existing_url = settings.value(f"{key_prefix}/url", "")
249+
if not existing_url:
250+
settings.setValue(f"{key_prefix}/url", WMS_BASE_URL)
251+
print(f"[WMS] Connessione '{WMS_CONNECTION_NAME}' aggiunta al profilo QGIS")
252+
else:
253+
print(f"[WMS] Connessione '{WMS_CONNECTION_NAME}' già presente nel profilo")
254+
255+
# Costruisci URI con tutti i layer combinati
256+
layers_params = "&".join(f"layers={l}" for l in WMS_LAYERS)
257+
styles_params = "&".join("styles=" for _ in WMS_LAYERS)
258+
uri = (
259+
f"contextualWMSLegend=0"
260+
f"&crs=EPSG:6706"
261+
f"&dpiMode=7"
262+
f"&featureCount=10"
263+
f"&format=image/png"
264+
f"&{layers_params}"
265+
f"&{styles_params}"
266+
f"&url={WMS_BASE_URL}"
267+
)
268+
269+
wms_layer = QgsRasterLayer(uri, WMS_LAYER_NAME, "wms")
270+
if not wms_layer.isValid():
271+
print("[WMS] ERRORE: impossibile caricare il layer WMS Catasto")
272+
return
273+
274+
QgsProject.instance().addMapLayer(wms_layer, False)
275+
root = QgsProject.instance().layerTreeRoot()
276+
277+
# Inserisci in fondo ma prima di eventuali mappe di sfondo (XYZ tiles)
278+
children = root.children()
279+
pos = len(children) # default: ultima posizione
280+
for i in range(len(children) - 1, -1, -1):
281+
node = children[i]
282+
if hasattr(node, "layer") and node.layer():
283+
src = node.layer().source()
284+
if "type=xyz" in src:
285+
pos = i
286+
else:
287+
break
288+
else:
289+
break
290+
root.insertLayer(pos, wms_layer)
291+
292+
print(f"[WMS] Layer '{WMS_LAYER_NAME}' caricato nel progetto")
293+
294+
218295
def calcola_griglia_tile(min_lat, min_lon, max_lat, max_lon, max_tile_km2):
219296
"""
220297
Suddivide il bbox in una griglia di tile, ciascuna con area <= max_tile_km2.
@@ -308,7 +385,8 @@ def scarica_singolo_tile(min_lat, min_lon, max_lat, max_lon):
308385
def esegui_download_e_caricamento(min_lat, min_lon, max_lat, max_lon, filter_geom=None,
309386
layer_name="Particelle WFS",
310387
espandi_catastale=False,
311-
post_filter_points=None):
388+
post_filter_points=None,
389+
carica_wms=False):
312390
"""
313391
Gestisce il download WFS: singolo o multi-tile con progress bar.
314392
@@ -744,6 +822,10 @@ def esegui_download_e_caricamento(min_lat, min_lon, max_lat, max_lon, filter_geo
744822
canvas.setExtent(extent_proj)
745823
canvas.refresh()
746824

825+
# Carica WMS Catasto se richiesto
826+
if carica_wms:
827+
carica_wms_catasto()
828+
747829
# Riepilogo finale
748830
print("\n" + "=" * 60)
749831
print(" COMPLETATO!")
@@ -776,13 +858,15 @@ class BBoxDrawTool(QgsMapTool):
776858
clicca il secondo angolo per confermare e avviare il download.
777859
"""
778860

779-
def __init__(self, canvas, on_completed=None, espandi_catastale=False):
861+
def __init__(self, canvas, on_completed=None, espandi_catastale=False,
862+
carica_wms=False):
780863
super().__init__(canvas)
781864
self.canvas = canvas
782865
self.first_point = None
783866
self.preview_rb = None
784867
self.on_completed = on_completed
785868
self.espandi_catastale = espandi_catastale
869+
self.carica_wms = carica_wms
786870
self._create_preview_rubberband()
787871

788872
def _create_preview_rubberband(self):
@@ -835,7 +919,8 @@ def canvasPressEvent(self, event):
835919
esegui_download_e_caricamento(
836920
min_lat, min_lon, max_lat, max_lon,
837921
layer_name="Particelle WFS (BBox)",
838-
espandi_catastale=self.espandi_catastale
922+
espandi_catastale=self.espandi_catastale,
923+
carica_wms=self.carica_wms,
839924
)
840925

841926
# Ripristina Pan e riapri dialog
@@ -875,11 +960,13 @@ class PolySelectTool(QgsMapTool):
875960
Estrae il bbox della geometria e avvia il download WFS.
876961
"""
877962

878-
def __init__(self, canvas, on_completed=None, espandi_catastale=False):
963+
def __init__(self, canvas, on_completed=None, espandi_catastale=False,
964+
carica_wms=False):
879965
super().__init__(canvas)
880966
self.canvas = canvas
881967
self.on_completed = on_completed
882968
self.espandi_catastale = espandi_catastale
969+
self.carica_wms = carica_wms
883970

884971
def canvasPressEvent(self, event):
885972
click_map_point = self.toMapCoordinates(event.pos())
@@ -968,7 +1055,8 @@ def canvasPressEvent(self, event):
9681055
min_lat, min_lon, max_lat, max_lon,
9691056
filter_geom=poly_geom_wfs,
9701057
layer_name="Particelle WFS (Poligono)",
971-
espandi_catastale=self.espandi_catastale
1058+
espandi_catastale=self.espandi_catastale,
1059+
carica_wms=self.carica_wms,
9721060
)
9731061

9741062
qgis_iface.actionPan().trigger()
@@ -1001,12 +1089,13 @@ class LineSelectTool(QgsMapTool):
10011089
"""
10021090

10031091
def __init__(self, canvas, buffer_distance=BUFFER_DISTANCE_M, on_completed=None,
1004-
espandi_catastale=False):
1092+
espandi_catastale=False, carica_wms=False):
10051093
super().__init__(canvas)
10061094
self.canvas = canvas
10071095
self.buffer_distance = buffer_distance
10081096
self.buffer_rb = None # Rubberband per visualizzare il buffer
10091097
self.espandi_catastale = espandi_catastale
1098+
self.carica_wms = carica_wms
10101099
self.on_completed = on_completed
10111100
# Stato per modalità disegno polilinea
10121101
self._draw_points = [] # Vertici della polilinea in coordinate mappa
@@ -1075,7 +1164,8 @@ def _esegui_download_da_linea(self, line_geom, geom_crs):
10751164
min_lat, min_lon, max_lat, max_lon,
10761165
filter_geom=buffer_geom_wfs,
10771166
layer_name=f"Particelle WFS (Linea buffer {self.buffer_distance} m)",
1078-
espandi_catastale=self.espandi_catastale
1167+
espandi_catastale=self.espandi_catastale,
1168+
carica_wms=self.carica_wms,
10791169
)
10801170

10811171
qgis_iface.actionPan().trigger()
@@ -1334,13 +1424,14 @@ class PointSelectTool(QgsMapTool):
13341424
"""
13351425

13361426
def __init__(self, canvas, buffer_distance=1, snap_tolerance=15,
1337-
on_completed=None, espandi_catastale=False):
1427+
on_completed=None, espandi_catastale=False, carica_wms=False):
13381428
super().__init__(canvas)
13391429
self.canvas = canvas
13401430
self.buffer_distance = buffer_distance
13411431
self.snap_tolerance = snap_tolerance
13421432
self.buffer_rb = None
13431433
self.espandi_catastale = espandi_catastale
1434+
self.carica_wms = carica_wms
13441435
self.on_completed = on_completed
13451436

13461437
def _visualizza_buffer(self, buffer_geom, buffer_crs):
@@ -1598,6 +1689,7 @@ def _processa_layer_punti(self, layer):
15981689
layer_name=f"Particelle WFS (Punti buffer {self.buffer_distance} m)",
15991690
espandi_catastale=self.espandi_catastale,
16001691
post_filter_points=wfs_points,
1692+
carica_wms=self.carica_wms,
16011693
)
16021694

16031695
qgis_iface.actionPan().trigger()
@@ -1663,6 +1755,7 @@ def _processa_click_singolo(self, click_point, click_crs):
16631755
layer_name="Particelle WFS (click punto)",
16641756
espandi_catastale=self.espandi_catastale,
16651757
post_filter_points=[pt_wfs],
1758+
carica_wms=self.carica_wms,
16661759
)
16671760

16681761
qgis_iface.actionPan().trigger()
@@ -1761,6 +1854,7 @@ def _on_modalita_scelta(self):
17611854
dlg = self._dlg
17621855
canvas = self.iface.mapCanvas()
17631856
espandi = dlg.espandi_catastale
1857+
wms = dlg.carica_wms
17641858

17651859
if dlg.scelta == "disegna":
17661860
print("\n MODALITÀ: Disegna BBox")
@@ -1769,7 +1863,7 @@ def _on_modalita_scelta(self):
17691863
print(" >>> Clicca per il SECONDO angolo")
17701864
print(" >>> Il download partirà automaticamente\n")
17711865
tool = BBoxDrawTool(canvas, on_completed=self._reopen_dialog,
1772-
espandi_catastale=espandi)
1866+
espandi_catastale=espandi, carica_wms=wms)
17731867
canvas.setMapTool(tool)
17741868
self._active_tool = tool
17751869

@@ -1779,7 +1873,7 @@ def _on_modalita_scelta(self):
17791873
print(" >>> Il bbox verrà estratto e il CRS verificato")
17801874
print(" >>> Il download partirà automaticamente\n")
17811875
tool = PolySelectTool(canvas, on_completed=self._reopen_dialog,
1782-
espandi_catastale=espandi)
1876+
espandi_catastale=espandi, carica_wms=wms)
17831877
canvas.setMapTool(tool)
17841878
self._active_tool = tool
17851879

@@ -1792,7 +1886,7 @@ def _on_modalita_scelta(self):
17921886
print(" >>> ATTENZIONE: Il layer deve avere un CRS proiettato (metri)\n")
17931887
tool = LineSelectTool(canvas, buffer_distance=buffer_m,
17941888
on_completed=self._reopen_dialog,
1795-
espandi_catastale=espandi)
1889+
espandi_catastale=espandi, carica_wms=wms)
17961890
canvas.setMapTool(tool)
17971891
self._active_tool = tool
17981892

@@ -1808,7 +1902,7 @@ def _on_modalita_scelta(self):
18081902
tool = PointSelectTool(canvas, buffer_distance=buffer_m,
18091903
snap_tolerance=snap_px,
18101904
on_completed=self._reopen_dialog,
1811-
espandi_catastale=espandi)
1905+
espandi_catastale=espandi, carica_wms=wms)
18121906
canvas.setMapTool(tool)
18131907
self._active_tool = tool
18141908

0 commit comments

Comments
 (0)