174 lines
6.4 KiB
Python
174 lines
6.4 KiB
Python
"""sn_verfahrensgebiet/functions/verfahrensgebiet_alkis.py – ALKIS-Integration.
|
||
Lädt Verfahrensgebiete aus dem ALKIS-WFS-Dienst.
|
||
"""
|
||
|
||
from enum import Enum
|
||
from sn_basis.functions import (
|
||
QgsVectorLayer, QgsProject, QgsFeature, QgsField, QgsGeometry
|
||
)
|
||
from sn_basis.functions import QMessageBox
|
||
from sn_basis.functions.qt_wrapper import QVariant
|
||
from sn_basis.functions.variable_wrapper import get_variable
|
||
from sn_basis.functions.dialog_wrapper import ask_bror_kombination
|
||
|
||
alkis_sf_url = "https://geodienste.sachsen.de/aaa/public_alkis/sf/wfs"
|
||
typename = "adv:AX_BauRaumOderBodenordnungsrecht"
|
||
|
||
#: Attribute, die aus dem BROR-WFS-Dienst geladen und im Memory-Layer gespeichert werden.
|
||
BROR_ATTRIBUTE_FELDER = [
|
||
"artderfestlegung",
|
||
"ausfuehrendestelle_ax_dienststelle_schluessel_stelle",
|
||
"adv_name",
|
||
"bezeichnung",
|
||
"datumanordnung",
|
||
"datumbesitzeinweisung",
|
||
"datumrechtskraft",
|
||
"datumabgabe",
|
||
]
|
||
|
||
class LoadStatus(Enum):
|
||
"""Status eines Layer-Ladevorgangs.
|
||
|
||
Attributes:
|
||
NONE: Nichts geladen
|
||
FIRST: Erstmalig geladen
|
||
RELOAD: Neu geladen
|
||
KEEP: Vorhandener Layer behalten
|
||
"""
|
||
NONE = "none" # nichts geladen
|
||
FIRST = "first" # erstmalig geladen
|
||
RELOAD = "reload" # neu geladen
|
||
KEEP = "keep" # vorhandener Layer behalten
|
||
|
||
|
||
def _check_existing_layer(tab_widget):
|
||
"""Prüft, ob ein Verfahrensgebiet-Layer bereits existiert.
|
||
|
||
Args:
|
||
tab_widget: Parent-Widget für Dialoge
|
||
|
||
Returns:
|
||
Tuple[Optional[QgsVectorLayer], LoadStatus]: Layer und Status
|
||
"""
|
||
project = QgsProject.instance()
|
||
existing_layers = project.mapLayersByName("Verfahrensgebiet")
|
||
if not existing_layers:
|
||
return None, LoadStatus.FIRST
|
||
|
||
reply = QMessageBox.question(
|
||
tab_widget,
|
||
"Layer bereits vorhanden",
|
||
"Der Layer 'Verfahrensgebiet' existiert bereits.\n"
|
||
"Möchten Sie ihn löschen und neu laden?",
|
||
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
|
||
QMessageBox.StandardButton.No
|
||
)
|
||
if reply == QMessageBox.StandardButton.Yes:
|
||
for lyr in existing_layers:
|
||
project.removeMapLayer(lyr.id())
|
||
return None, LoadStatus.RELOAD
|
||
else:
|
||
return existing_layers[0], LoadStatus.KEEP
|
||
|
||
|
||
def verfahrensgebiet_alkis(tab_widget):
|
||
"""Lädt Verfahrensgebiet aus ALKIS-WFS basierend auf Verfahrensnummer.
|
||
|
||
Args:
|
||
tab_widget: Parent-Widget für Dialoge und Meldungen
|
||
|
||
Returns:
|
||
Tuple[Optional[QgsVectorLayer], LoadStatus, List[QgsFeature]]:
|
||
Geladener Memory-Layer, Lade-Status und Liste der Roh-WFS-Features
|
||
(für geometriebasierte Weiterverarbeitung, z.B. Gemarkungsschlüssel-
|
||
Ermittlung via Spatial-Join). Bei Abbruch oder Fehler: ``(None,
|
||
LoadStatus.NONE, [])``. Bei ``LoadStatus.KEEP`` werden keine
|
||
WFS-Features neu geladen; die Feature-Liste ist in diesem Fall leer.
|
||
"""
|
||
verfahrensnummer = get_variable("verfahrensnummer")
|
||
if not verfahrensnummer:
|
||
QMessageBox.critical(tab_widget, "Fehler",
|
||
"In den Projekteigenschaften ist noch keine Verfahrensnummer eingetragen!")
|
||
return None, LoadStatus.NONE, []
|
||
|
||
# Vorhandenen Layer prüfen
|
||
existing, status = _check_existing_layer(tab_widget)
|
||
if status == LoadStatus.KEEP:
|
||
return existing, status, []
|
||
|
||
# WFS mit Filter laden – nur erste 5 Stellen der VKZ für den Vergleich verwenden,
|
||
# da die Daten im Dienst ggf. abweichende Suffixe führen.
|
||
vkz_prefix = verfahrensnummer[:5]
|
||
wfs_uri_find = (
|
||
f"url='{alkis_sf_url}' typename='{typename}' srsname='EPSG:25833' "
|
||
f"sql=SELECT * FROM AX_BauRaumOderBodenordnungsrecht "
|
||
f"WHERE bezeichnung LIKE '{vkz_prefix}%'"
|
||
)
|
||
temp_layer = QgsVectorLayer(wfs_uri_find, "TempVerfahrensgebiet", "WFS")
|
||
|
||
if not temp_layer.isValid():
|
||
QMessageBox.critical(tab_widget, "Fehler", "Layer konnte nicht geladen werden.")
|
||
return None, LoadStatus.NONE, []
|
||
|
||
features = list(temp_layer.getFeatures())
|
||
if not features:
|
||
QMessageBox.critical(tab_widget, "Fehler",
|
||
f"Verfahrenskennzeichen {verfahrensnummer} nicht im WFS gefunden.")
|
||
return None, LoadStatus.NONE, []
|
||
|
||
# Objekte nach (adv_name, bezeichnung) gruppieren
|
||
kombinationen: dict[tuple[str, str], list] = {}
|
||
for feat in features:
|
||
try:
|
||
adv_name_val = str(feat.attribute("adv_name") or "")
|
||
bezeichnung_val = str(feat.attribute("bezeichnung") or "")
|
||
except Exception:
|
||
adv_name_val = ""
|
||
bezeichnung_val = ""
|
||
key = (adv_name_val, bezeichnung_val)
|
||
if key not in kombinationen:
|
||
kombinationen[key] = []
|
||
kombinationen[key].append(feat)
|
||
|
||
if len(kombinationen) == 1:
|
||
selected_key = next(iter(kombinationen))
|
||
selected_feats = kombinationen[selected_key]
|
||
else:
|
||
# Mehrere Kombinationen → Nutzerauswahl
|
||
key_list = sorted(kombinationen.keys())
|
||
selected_key = ask_bror_kombination(tab_widget, key_list)
|
||
if selected_key is None:
|
||
return None, LoadStatus.NONE, []
|
||
selected_feats = kombinationen[selected_key]
|
||
|
||
union_geom = QgsGeometry.unaryUnion([f.geometry() for f in selected_feats])
|
||
if union_geom is None or union_geom.isEmpty():
|
||
QMessageBox.critical(tab_widget, "Fehler", "Keine Geometrien zum Verschmelzen gefunden.")
|
||
return None, LoadStatus.NONE, []
|
||
|
||
# Memory-Layer erzeugen
|
||
crs = temp_layer.crs().authid()
|
||
memory_layer = QgsVectorLayer(f"Polygon?crs={crs}", "Verfahrensgebiet", "memory")
|
||
pr = memory_layer.dataProvider()
|
||
pr.addAttributes([QgsField(attr, QVariant.String) for attr in BROR_ATTRIBUTE_FELDER])
|
||
memory_layer.updateFields()
|
||
|
||
# Attributwerte aus dem ersten Feature der gewählten Kombination übernehmen
|
||
first_feat = selected_feats[0]
|
||
attrs = []
|
||
for attr in BROR_ATTRIBUTE_FELDER:
|
||
try:
|
||
val = first_feat.attribute(attr)
|
||
attrs.append(str(val) if val is not None else "")
|
||
except Exception:
|
||
attrs.append("")
|
||
|
||
feat_union = QgsFeature()
|
||
feat_union.setGeometry(union_geom)
|
||
feat_union.setAttributes(attrs)
|
||
pr.addFeatures([feat_union])
|
||
memory_layer.updateExtents()
|
||
|
||
# Status: FIRST oder RELOAD; selected_feats für Gemarkungsermittlung weitergeben
|
||
return memory_layer, status, selected_feats
|