2026-04-22 14:53:45 +02:00
|
|
|
|
"""sn_verfahrensgebiet/functions/verfahrensgebiet_alkis_komplett.py – Vollständiger VG-Lade-Workflow.
|
|
|
|
|
|
|
|
|
|
|
|
Orchestriert den vollständigen Arbeitsablauf zum Laden eines Verfahrensgebiets
|
2026-04-23 22:24:14 +02:00
|
|
|
|
aus ALKIS mit anschließender Flurstücks-Verschneidung, Flächenvergleich und
|
|
|
|
|
|
optionaler Umringsprüfung:
|
2026-04-22 14:53:45 +02:00
|
|
|
|
|
|
|
|
|
|
1. Verfahrensgebiet aus ``AX_BauRaumOderBodenordnungsrecht`` per VKZ laden.
|
2026-04-23 22:24:14 +02:00
|
|
|
|
2. Gemarkungsschlüssel per Geometrie aus ``AX_Gemarkung`` vorschlagen.
|
|
|
|
|
|
3. Flurstücke per Dialog (mit Vorschlag) laden.
|
|
|
|
|
|
4. Flurstücke räumlich auf das VG einschränken (``selectByLocation``).
|
|
|
|
|
|
5. Aus der Auswahl den enriched Verfahrensgebiet-Memory-Layer erzeugen.
|
|
|
|
|
|
6. Flächenvergleich zwischen BROR-Objekt und abgeleitetem Verfahrensgebiet.
|
2026-04-22 14:53:45 +02:00
|
|
|
|
|
2026-04-23 22:24:14 +02:00
|
|
|
|
- **Übereinstimmung** (≤ Toleranz): modale OK-Meldung, Ablauf beendet.
|
|
|
|
|
|
- **Abweichung**: Ja/Nein-Abfrage für Detailprüfung.
|
|
|
|
|
|
|
|
|
|
|
|
7. Optionale Umringsprüfung (Variante 1):
|
|
|
|
|
|
|
|
|
|
|
|
- BROR-Umring gegen Flurstücksgrenzen vergleichen.
|
|
|
|
|
|
- Ergebnislayer (grün/rot) ins Projekt einfügen.
|
|
|
|
|
|
- Abschlussmeldung mit Konfliktanzahl.
|
|
|
|
|
|
|
|
|
|
|
|
Das BROR-Objekt (``AX_BauRaumOderBodenordnungsrecht``) bleibt bei Erfolg als
|
|
|
|
|
|
temporärer Layer ``BauRaumOrdnungsrecht (ALKIS)`` im Projekt erhalten.
|
|
|
|
|
|
|
|
|
|
|
|
**Rückgabe:**
|
|
|
|
|
|
``Tuple[enriched_layer, flst_layer, bror_layer, LoadStatus]``
|
2026-04-22 14:53:45 +02:00
|
|
|
|
|
|
|
|
|
|
**Abbruchverhalten:** Jeder Schritt, der :attr:`LoadStatus.NONE` zurückgibt
|
2026-04-23 22:24:14 +02:00
|
|
|
|
oder kein Ergebnis liefert, bricht den Workflow ab. Der BROR-Layer wird nur
|
|
|
|
|
|
bei Fehler/Abbruch entfernt (wenn er in diesem Lauf hinzugefügt wurde).
|
2026-04-22 14:53:45 +02:00
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
|
|
from typing import Optional, Tuple
|
|
|
|
|
|
|
|
|
|
|
|
from sn_basis.functions import QgsProject
|
|
|
|
|
|
from sn_basis.functions import QMessageBox
|
2026-04-23 22:24:14 +02:00
|
|
|
|
from sn_basis.functions.message_wrapper import warning
|
2026-04-22 14:53:45 +02:00
|
|
|
|
from sn_basis.functions.variable_wrapper import get_variable
|
2026-04-23 22:24:14 +02:00
|
|
|
|
from sn_basis.functions.dialog_wrapper import (
|
|
|
|
|
|
create_progress_dialog,
|
|
|
|
|
|
show_info_dialog,
|
|
|
|
|
|
ask_yes_no,
|
|
|
|
|
|
)
|
2026-04-22 14:53:45 +02:00
|
|
|
|
|
|
|
|
|
|
from sn_verfahrensgebiet.functions.verfahrensgebiet_alkis import (
|
|
|
|
|
|
verfahrensgebiet_alkis,
|
|
|
|
|
|
LoadStatus,
|
|
|
|
|
|
)
|
|
|
|
|
|
from sn_verfahrensgebiet.functions.gemarkung_alkis import (
|
|
|
|
|
|
gemarkung_schluessel_und_namen_von_vg_geometrie,
|
|
|
|
|
|
)
|
|
|
|
|
|
from sn_verfahrensgebiet.functions.flurstueck_alkis import flurstueck_alkis
|
|
|
|
|
|
from sn_verfahrensgebiet.functions.verfahrensgebiet_edit_service import (
|
|
|
|
|
|
erstelle_verfahrensgebiet_aus_auswahl,
|
|
|
|
|
|
VERF_LAYER_NAME,
|
|
|
|
|
|
)
|
2026-04-23 22:24:14 +02:00
|
|
|
|
from sn_verfahrensgebiet.functions.umringspruefung import umringspruefung
|
2026-04-22 14:53:45 +02:00
|
|
|
|
|
2026-04-23 22:24:14 +02:00
|
|
|
|
# Feldname für das Verfahrenskennzeichen im enriched Layer
|
2026-04-22 14:53:45 +02:00
|
|
|
|
FELD_VKZ = "verfahrensnummer"
|
2026-04-23 22:24:14 +02:00
|
|
|
|
#: Anzeigename des BROR-Layers im Projekt
|
|
|
|
|
|
BROR_LAYER_NAME = "BauRaumOrdnungsrecht (ALKIS)"
|
|
|
|
|
|
#: Projektvariable für die Flächentoleranz (in m²); Default 0
|
|
|
|
|
|
FLAECHEN_TOLERANZ_VARIABLE = "flaechen_toleranz_m2"
|
|
|
|
|
|
|
2026-04-22 14:53:45 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
# Interne Hilfsfunktionen
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
def _entferne_hilfs_layer(project, layer_name: str) -> None:
|
|
|
|
|
|
"""Entfernt alle Layer mit dem angegebenen Namen aus dem Projekt.
|
|
|
|
|
|
|
2026-04-23 22:24:14 +02:00
|
|
|
|
Wird verwendet, um temporäre WFS-Hilfs-Layer nach der Verschneidung
|
2026-04-22 14:53:45 +02:00
|
|
|
|
aus dem Projekt zu bereinigen.
|
|
|
|
|
|
|
|
|
|
|
|
Parameters
|
|
|
|
|
|
----------
|
|
|
|
|
|
project :
|
|
|
|
|
|
Aktuelles QGIS-Projekt.
|
|
|
|
|
|
layer_name :
|
|
|
|
|
|
Anzeigename des zu entfernenden Layers.
|
|
|
|
|
|
"""
|
|
|
|
|
|
for lyr in project.mapLayersByName(layer_name):
|
|
|
|
|
|
project.removeMapLayer(lyr.id())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _select_by_location(flst_layer, vg_layer) -> int:
|
2026-04-23 22:24:14 +02:00
|
|
|
|
"""Selektiert Flurstücke, die innerhalb des Verfahrensgebiets liegen.
|
2026-04-22 14:53:45 +02:00
|
|
|
|
|
2026-04-23 22:24:14 +02:00
|
|
|
|
Verwendet ``processing.run("native:selectbylocation")`` mit Prädikat 6
|
|
|
|
|
|
(within). Flurstücke, die das VG nur berühren, werden ausgeschlossen.
|
2026-04-22 14:53:45 +02:00
|
|
|
|
|
|
|
|
|
|
Parameters
|
|
|
|
|
|
----------
|
|
|
|
|
|
flst_layer :
|
2026-04-23 22:24:14 +02:00
|
|
|
|
Flurstücks-Layer (Quelle der Selektion).
|
2026-04-22 14:53:45 +02:00
|
|
|
|
vg_layer :
|
2026-04-23 22:24:14 +02:00
|
|
|
|
Verfahrensgebiet-Layer (Schnittmaske).
|
2026-04-22 14:53:45 +02:00
|
|
|
|
|
|
|
|
|
|
Returns
|
|
|
|
|
|
-------
|
|
|
|
|
|
int
|
2026-04-23 22:24:14 +02:00
|
|
|
|
Anzahl der selektierten Features; 0 bei Fehler oder leerem Ergebnis.
|
2026-04-22 14:53:45 +02:00
|
|
|
|
"""
|
|
|
|
|
|
try:
|
|
|
|
|
|
import processing # type: ignore[import]
|
|
|
|
|
|
|
|
|
|
|
|
processing.run(
|
|
|
|
|
|
"native:selectbylocation",
|
|
|
|
|
|
{
|
|
|
|
|
|
"INPUT": flst_layer,
|
2026-04-23 22:24:14 +02:00
|
|
|
|
"PREDICATE": [6], # 6 = within; schließt reines Berühren aus
|
2026-04-22 14:53:45 +02:00
|
|
|
|
"INTERSECT": vg_layer,
|
2026-04-23 22:24:14 +02:00
|
|
|
|
"METHOD": 0, # 0 = neue Selektion
|
2026-04-22 14:53:45 +02:00
|
|
|
|
},
|
|
|
|
|
|
)
|
|
|
|
|
|
return flst_layer.selectedFeatureCount()
|
|
|
|
|
|
|
|
|
|
|
|
except Exception:
|
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _fuege_vkz_feld_hinzu(layer, vkz: str) -> None:
|
|
|
|
|
|
"""Fügt das Feld ``verfahrensnummer`` zum enriched Layer hinzu und befüllt
|
|
|
|
|
|
es mit dem Verfahrenskennzeichen, sofern dieses nicht leer ist.
|
|
|
|
|
|
|
|
|
|
|
|
Parameters
|
|
|
|
|
|
----------
|
|
|
|
|
|
layer :
|
|
|
|
|
|
Enriched Verfahrensgebiet-Memory-Layer (in-place geändert).
|
|
|
|
|
|
vkz :
|
|
|
|
|
|
Verfahrenskennzeichen aus der Projektvariable ``verfahrensnummer``.
|
|
|
|
|
|
"""
|
|
|
|
|
|
if not vkz:
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
from sn_basis.functions import QgsField
|
|
|
|
|
|
from sn_basis.functions.qt_wrapper import QVariant
|
|
|
|
|
|
|
|
|
|
|
|
pr = layer.dataProvider()
|
|
|
|
|
|
pr.addAttributes([QgsField(FELD_VKZ, QVariant.String)])
|
|
|
|
|
|
layer.updateFields()
|
|
|
|
|
|
|
|
|
|
|
|
idx = layer.fields().indexFromName(FELD_VKZ)
|
|
|
|
|
|
if idx < 0:
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
changes = {}
|
|
|
|
|
|
for feat in layer.getFeatures():
|
|
|
|
|
|
changes[feat.id()] = {idx: vkz}
|
|
|
|
|
|
pr.changeAttributeValues(changes)
|
|
|
|
|
|
layer.updateFields()
|
|
|
|
|
|
|
|
|
|
|
|
except Exception:
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-04-23 22:24:14 +02:00
|
|
|
|
def _lese_flaechen_toleranz() -> float:
|
|
|
|
|
|
"""Liest die Flächentoleranz aus der Projektvariable (Default: 0.0 m²).
|
|
|
|
|
|
|
|
|
|
|
|
Die Projektvariable :data:`FLAECHEN_TOLERANZ_VARIABLE` kann in den
|
|
|
|
|
|
Projekteigenschaften gesetzt werden. Fehlt sie oder ist sie ungültig,
|
|
|
|
|
|
wird 0.0 zurückgegeben (exakter Vergleich).
|
|
|
|
|
|
|
|
|
|
|
|
Returns
|
|
|
|
|
|
-------
|
|
|
|
|
|
float
|
|
|
|
|
|
Toleranz in m² (bei EPSG:25833 identisch mit den Flächen-Einheiten).
|
|
|
|
|
|
"""
|
|
|
|
|
|
try:
|
|
|
|
|
|
raw = get_variable(FLAECHEN_TOLERANZ_VARIABLE)
|
|
|
|
|
|
if raw is not None and str(raw).strip():
|
|
|
|
|
|
return float(str(raw).strip())
|
|
|
|
|
|
except Exception:
|
|
|
|
|
|
pass
|
|
|
|
|
|
return 0.0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _flaeche_des_layers(layer) -> float:
|
|
|
|
|
|
"""Summiert die Flächen aller Features eines Layers (in CRS-Einheiten²).
|
|
|
|
|
|
|
|
|
|
|
|
Parameters
|
|
|
|
|
|
----------
|
|
|
|
|
|
layer :
|
|
|
|
|
|
Beliebiger Polygon-Layer.
|
|
|
|
|
|
|
|
|
|
|
|
Returns
|
|
|
|
|
|
-------
|
|
|
|
|
|
float
|
|
|
|
|
|
Summe aller Feature-Flächen; 0.0 wenn keine Features vorhanden.
|
|
|
|
|
|
"""
|
|
|
|
|
|
total = 0.0
|
|
|
|
|
|
for feat in layer.getFeatures():
|
|
|
|
|
|
try:
|
|
|
|
|
|
geom = feat.geometry()
|
|
|
|
|
|
if geom and not geom.isEmpty():
|
|
|
|
|
|
total += geom.area()
|
|
|
|
|
|
except Exception:
|
|
|
|
|
|
pass
|
|
|
|
|
|
return total
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _vergleiche_flaechen(
|
|
|
|
|
|
bror_layer, vg_layer, toleranz_m2: float = 0.0
|
|
|
|
|
|
) -> Tuple[float, float, bool]:
|
|
|
|
|
|
"""Vergleicht Flächen von BROR- und Verfahrensgebiet-Layer.
|
|
|
|
|
|
|
|
|
|
|
|
Parameters
|
|
|
|
|
|
----------
|
|
|
|
|
|
bror_layer :
|
|
|
|
|
|
BauRaumOrdnungsrecht-Layer.
|
|
|
|
|
|
vg_layer :
|
|
|
|
|
|
Enriched Verfahrensgebiet-Layer.
|
|
|
|
|
|
toleranz_m2 :
|
|
|
|
|
|
Maximale zulässige Flächendifferenz in m².
|
|
|
|
|
|
|
|
|
|
|
|
Returns
|
|
|
|
|
|
-------
|
|
|
|
|
|
Tuple[float, float, bool]
|
|
|
|
|
|
``(bror_flaeche, vg_flaeche, stimmt_ueberein)``
|
|
|
|
|
|
"""
|
|
|
|
|
|
bror_flaeche = _flaeche_des_layers(bror_layer)
|
|
|
|
|
|
vg_flaeche = _flaeche_des_layers(vg_layer)
|
|
|
|
|
|
stimmt_ueberein = abs(bror_flaeche - vg_flaeche) <= toleranz_m2
|
|
|
|
|
|
return bror_flaeche, vg_flaeche, stimmt_ueberein
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-04-22 14:53:45 +02:00
|
|
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
# Öffentliche API
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
def verfahrensgebiet_alkis_komplett(
|
|
|
|
|
|
tab_widget,
|
2026-04-23 22:24:14 +02:00
|
|
|
|
) -> Tuple[Optional[object], Optional[object], Optional[object], LoadStatus]:
|
|
|
|
|
|
"""Vollständiger VG-Lade-Workflow: ALKIS-VG → Gemarkungen →
|
|
|
|
|
|
Flurstücke → Verschneidung → Flächenvergleich → opt. Umringsprüfung.
|
2026-04-22 14:53:45 +02:00
|
|
|
|
|
|
|
|
|
|
Schrittfolge:
|
|
|
|
|
|
|
2026-04-23 22:24:14 +02:00
|
|
|
|
1. ``verfahrensgebiet_alkis(tab_widget)`` – BROR-Objekt als Memory-Layer.
|
|
|
|
|
|
2. ``gemarkung_schluessel_und_namen_von_vg_geometrie(geom)`` – Schlüssel.
|
|
|
|
|
|
3. ``flurstueck_alkis(...)`` – Flurstücke laden.
|
|
|
|
|
|
4. ``_select_by_location(...)`` – räumliche Selektion.
|
|
|
|
|
|
5. ``erstelle_verfahrensgebiet_aus_auswahl(...)`` – enriched Layer.
|
|
|
|
|
|
6. ``_vergleiche_flaechen(...)`` – Flächenvergleich als Gate.
|
|
|
|
|
|
7. Ggf. ``umringspruefung(...)`` nach Nutzerbestätigung.
|
|
|
|
|
|
|
|
|
|
|
|
Der BROR-Layer (``BauRaumOrdnungsrecht (ALKIS)``) bleibt bei Erfolg
|
|
|
|
|
|
im Projekt. Bei Abbruch/Fehler wird er entfernt, falls er in diesem
|
|
|
|
|
|
Lauf hinzugefügt wurde.
|
2026-04-22 14:53:45 +02:00
|
|
|
|
|
|
|
|
|
|
Parameters
|
|
|
|
|
|
----------
|
|
|
|
|
|
tab_widget :
|
2026-04-23 22:24:14 +02:00
|
|
|
|
Eltern-Widget für alle Dialoge.
|
2026-04-22 14:53:45 +02:00
|
|
|
|
|
|
|
|
|
|
Returns
|
|
|
|
|
|
-------
|
2026-04-23 22:24:14 +02:00
|
|
|
|
Tuple[Optional[enriched_layer], Optional[flst_layer], Optional[bror_layer], LoadStatus]
|
|
|
|
|
|
- ``enriched_layer``: Memory-Layer „Verfahrensgebiet".
|
|
|
|
|
|
- ``flst_layer``: Flurstücke-Layer (bleibt im Projekt).
|
|
|
|
|
|
- ``bror_layer``: BROR-Layer ``BauRaumOrdnungsrecht (ALKIS)``
|
|
|
|
|
|
(bleibt bei Erfolg im Projekt).
|
|
|
|
|
|
- :class:`LoadStatus`: ``FIRST``, ``RELOAD`` oder ``NONE``.
|
2026-04-22 14:53:45 +02:00
|
|
|
|
"""
|
|
|
|
|
|
project = QgsProject.instance()
|
|
|
|
|
|
alkis_vg_layer = None
|
2026-04-23 22:24:14 +02:00
|
|
|
|
bror_was_added_by_us = False
|
|
|
|
|
|
abgeschlossen = False
|
|
|
|
|
|
|
|
|
|
|
|
# Fortschrittsdialog für den Basisworkflow (7 Schritte)
|
|
|
|
|
|
progress = create_progress_dialog(
|
|
|
|
|
|
7, "Verfahrensgebiet laden", "Initialisierung …"
|
|
|
|
|
|
)
|
2026-04-22 14:53:45 +02:00
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
# ------------------------------------------------------------------
|
2026-04-23 22:24:14 +02:00
|
|
|
|
# Schritt 1: VG aus ALKIS laden (BROR-Objekt → Memory-Layer)
|
2026-04-22 14:53:45 +02:00
|
|
|
|
# ------------------------------------------------------------------
|
2026-04-23 22:24:14 +02:00
|
|
|
|
progress.set_label("Schritt 1/6: Verfahrensgebiet aus ALKIS laden …")
|
|
|
|
|
|
progress.set_value(0)
|
|
|
|
|
|
if progress.is_canceled():
|
|
|
|
|
|
return None, None, None, LoadStatus.NONE
|
|
|
|
|
|
|
|
|
|
|
|
alkis_vg_layer, vg_status, _ = verfahrensgebiet_alkis(tab_widget)
|
2026-04-22 14:53:45 +02:00
|
|
|
|
|
|
|
|
|
|
if vg_status == LoadStatus.NONE or not alkis_vg_layer:
|
2026-04-23 22:24:14 +02:00
|
|
|
|
return None, None, None, LoadStatus.NONE
|
|
|
|
|
|
|
|
|
|
|
|
# BROR-Layer umbenennen, um Namenskonflikt mit enriched VG-Layer zu vermeiden
|
|
|
|
|
|
alkis_vg_layer.setName(BROR_LAYER_NAME)
|
2026-04-22 14:53:45 +02:00
|
|
|
|
|
|
|
|
|
|
if vg_status in (LoadStatus.FIRST, LoadStatus.RELOAD):
|
|
|
|
|
|
project.addMapLayer(alkis_vg_layer)
|
2026-04-23 22:24:14 +02:00
|
|
|
|
bror_was_added_by_us = True
|
|
|
|
|
|
|
|
|
|
|
|
progress.set_value(1)
|
2026-04-22 14:53:45 +02:00
|
|
|
|
|
|
|
|
|
|
# ------------------------------------------------------------------
|
2026-04-23 22:24:14 +02:00
|
|
|
|
# Schritt 2: Gemarkungsschlüssel per Geometrie-Spatial-Join ermitteln
|
2026-04-22 14:53:45 +02:00
|
|
|
|
# ------------------------------------------------------------------
|
2026-04-23 22:24:14 +02:00
|
|
|
|
progress.set_label("Schritt 2/6: Gemarkungsschlüssel ermitteln …")
|
|
|
|
|
|
if progress.is_canceled():
|
|
|
|
|
|
return None, None, None, LoadStatus.NONE
|
2026-04-22 14:53:45 +02:00
|
|
|
|
|
2026-04-23 22:24:14 +02:00
|
|
|
|
bror_feats = list(alkis_vg_layer.getFeatures())
|
|
|
|
|
|
vg_geom = bror_feats[0].geometry() if bror_feats else None
|
|
|
|
|
|
|
|
|
|
|
|
schluessel_namen = (
|
|
|
|
|
|
gemarkung_schluessel_und_namen_von_vg_geometrie(vg_geom)
|
|
|
|
|
|
if vg_geom else []
|
|
|
|
|
|
)
|
2026-04-22 14:53:45 +02:00
|
|
|
|
vorgabe_schluessel = [nr for nr, _ in schluessel_namen]
|
|
|
|
|
|
vorgabe_namen = [nm for _, nm in schluessel_namen if nm]
|
|
|
|
|
|
|
|
|
|
|
|
if not vorgabe_schluessel:
|
|
|
|
|
|
warning(
|
|
|
|
|
|
"VG laden",
|
|
|
|
|
|
"Keine Gemarkungen in der BBox gefunden. Bitte Schlüssel manuell eingeben.",
|
|
|
|
|
|
duration=5,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2026-04-23 22:24:14 +02:00
|
|
|
|
progress.set_value(2)
|
|
|
|
|
|
|
2026-04-22 14:53:45 +02:00
|
|
|
|
# ------------------------------------------------------------------
|
2026-04-23 22:24:14 +02:00
|
|
|
|
# Schritt 3: Flurstücke laden (mit Nutzer-Dialog, Vorschlag befüllt)
|
2026-04-22 14:53:45 +02:00
|
|
|
|
# ------------------------------------------------------------------
|
2026-04-23 22:24:14 +02:00
|
|
|
|
progress.set_label("Schritt 3/6: Flurstücke aus ALKIS laden …")
|
|
|
|
|
|
if progress.is_canceled():
|
|
|
|
|
|
return None, None, None, LoadStatus.NONE
|
|
|
|
|
|
|
2026-04-22 14:53:45 +02:00
|
|
|
|
flst_layer, flst_status = flurstueck_alkis(
|
|
|
|
|
|
tab_widget,
|
|
|
|
|
|
vorgabe_schluessel=vorgabe_schluessel,
|
|
|
|
|
|
vorgabe_namen=vorgabe_namen if vorgabe_namen else None,
|
2026-04-23 22:24:14 +02:00
|
|
|
|
ohne_dialog=True,
|
2026-04-22 14:53:45 +02:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if flst_status == LoadStatus.NONE or not flst_layer:
|
2026-04-23 22:24:14 +02:00
|
|
|
|
return None, None, None, LoadStatus.NONE
|
|
|
|
|
|
|
|
|
|
|
|
progress.set_value(3)
|
2026-04-22 14:53:45 +02:00
|
|
|
|
|
|
|
|
|
|
# ------------------------------------------------------------------
|
2026-04-23 22:24:14 +02:00
|
|
|
|
# Schritt 4: Räumliche Selektion
|
2026-04-22 14:53:45 +02:00
|
|
|
|
# ------------------------------------------------------------------
|
2026-04-23 22:24:14 +02:00
|
|
|
|
progress.set_label("Schritt 4/6: Flurstücke räumlich selektieren …")
|
|
|
|
|
|
if progress.is_canceled():
|
|
|
|
|
|
return None, None, None, LoadStatus.NONE
|
|
|
|
|
|
|
2026-04-22 14:53:45 +02:00
|
|
|
|
anzahl = _select_by_location(flst_layer, alkis_vg_layer)
|
|
|
|
|
|
|
|
|
|
|
|
if anzahl == 0:
|
|
|
|
|
|
QMessageBox.warning(
|
|
|
|
|
|
tab_widget,
|
|
|
|
|
|
"Keine Flurstücke im VG",
|
|
|
|
|
|
"Es wurden keine Flurstücke gefunden, die das Verfahrensgebiet schneiden.\n"
|
|
|
|
|
|
"Bitte Gemarkungsschlüssel und Ausdehnung prüfen.",
|
|
|
|
|
|
)
|
2026-04-23 22:24:14 +02:00
|
|
|
|
return None, flst_layer, None, LoadStatus.NONE
|
|
|
|
|
|
|
|
|
|
|
|
progress.set_value(4)
|
2026-04-22 14:53:45 +02:00
|
|
|
|
|
|
|
|
|
|
# ------------------------------------------------------------------
|
2026-04-23 22:24:14 +02:00
|
|
|
|
# Schritt 5: Enriched Memory-Layer aus Auswahl erzeugen
|
2026-04-22 14:53:45 +02:00
|
|
|
|
# ------------------------------------------------------------------
|
2026-04-23 22:24:14 +02:00
|
|
|
|
progress.set_label("Schritt 5/6: Verfahrensgebiet-Layer erzeugen …")
|
|
|
|
|
|
if progress.is_canceled():
|
|
|
|
|
|
return None, None, None, LoadStatus.NONE
|
|
|
|
|
|
|
2026-04-22 14:53:45 +02:00
|
|
|
|
enriched_layer, erfolgreich, fehlgeschlagen = erstelle_verfahrensgebiet_aus_auswahl(
|
|
|
|
|
|
flst_layer
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if not enriched_layer or not enriched_layer.isValid():
|
|
|
|
|
|
QMessageBox.critical(
|
|
|
|
|
|
tab_widget,
|
|
|
|
|
|
"Fehler",
|
|
|
|
|
|
"Verfahrensgebiet-Layer konnte nicht erstellt werden.",
|
|
|
|
|
|
)
|
2026-04-23 22:24:14 +02:00
|
|
|
|
return None, flst_layer, None, LoadStatus.NONE
|
2026-04-22 14:53:45 +02:00
|
|
|
|
|
|
|
|
|
|
vkz = get_variable("verfahrensnummer") or ""
|
|
|
|
|
|
_fuege_vkz_feld_hinzu(enriched_layer, vkz)
|
|
|
|
|
|
|
2026-04-23 22:24:14 +02:00
|
|
|
|
progress.set_value(5)
|
|
|
|
|
|
|
|
|
|
|
|
# ------------------------------------------------------------------
|
|
|
|
|
|
# Schritt 6: Flächenvergleich als Gate
|
|
|
|
|
|
# ------------------------------------------------------------------
|
|
|
|
|
|
progress.set_label("Schritt 6/6: Flächenvergleich …")
|
|
|
|
|
|
if progress.is_canceled():
|
|
|
|
|
|
return None, None, None, LoadStatus.NONE
|
|
|
|
|
|
|
|
|
|
|
|
toleranz = _lese_flaechen_toleranz()
|
|
|
|
|
|
bror_flaeche, vg_flaeche, stimmt_ueberein = _vergleiche_flaechen(
|
|
|
|
|
|
alkis_vg_layer, enriched_layer, toleranz
|
2026-04-22 14:53:45 +02:00
|
|
|
|
)
|
|
|
|
|
|
|
2026-04-23 22:24:14 +02:00
|
|
|
|
progress.set_value(6)
|
|
|
|
|
|
|
|
|
|
|
|
if stimmt_ueberein:
|
|
|
|
|
|
progress.set_value(7)
|
|
|
|
|
|
progress.close()
|
|
|
|
|
|
show_info_dialog(
|
|
|
|
|
|
"Flächenvergleich",
|
|
|
|
|
|
"Verfahrensgebiet mit erwarteter Geometrie erzeugt",
|
|
|
|
|
|
parent=tab_widget,
|
|
|
|
|
|
)
|
|
|
|
|
|
abgeschlossen = True
|
|
|
|
|
|
return enriched_layer, flst_layer, alkis_vg_layer, vg_status
|
|
|
|
|
|
|
|
|
|
|
|
# ------------------------------------------------------------------
|
|
|
|
|
|
# Flächenabweichung → Nutzerabfrage für Detailprüfung
|
|
|
|
|
|
# ------------------------------------------------------------------
|
|
|
|
|
|
progress.close()
|
|
|
|
|
|
diff = abs(bror_flaeche - vg_flaeche)
|
|
|
|
|
|
starten = ask_yes_no(
|
|
|
|
|
|
"Abweichung erkannt",
|
|
|
|
|
|
f"Abweichung zwischen BauRaumOrdnungsrecht-Objekt und abgeleitetem "
|
|
|
|
|
|
f"Verfahrensgebiet erkannt. Detailprüfung starten?\n\n"
|
|
|
|
|
|
f"BauRaumOrdnungsrecht: {bror_flaeche:.2f} m²\n"
|
|
|
|
|
|
f"Verfahrensgebiet: {vg_flaeche:.2f} m²\n"
|
|
|
|
|
|
f"Differenz: {diff:.2f} m²",
|
|
|
|
|
|
default=True,
|
|
|
|
|
|
parent=tab_widget,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if not starten:
|
|
|
|
|
|
abgeschlossen = True
|
|
|
|
|
|
return enriched_layer, flst_layer, alkis_vg_layer, vg_status
|
|
|
|
|
|
|
|
|
|
|
|
# ------------------------------------------------------------------
|
|
|
|
|
|
# Umringsprüfung (Variante 1: linienbasierter Umringvergleich)
|
|
|
|
|
|
# ------------------------------------------------------------------
|
|
|
|
|
|
umring_progress = create_progress_dialog(
|
|
|
|
|
|
3, "Detailprüfung (Umringe)", "Starte Umringsprüfung …"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
ergebnis_layer, konflikt_anzahl = umringspruefung(
|
|
|
|
|
|
alkis_vg_layer, flst_layer, progress=umring_progress
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if umring_progress.is_canceled():
|
|
|
|
|
|
umring_progress.close()
|
|
|
|
|
|
abgeschlossen = True
|
|
|
|
|
|
return enriched_layer, flst_layer, alkis_vg_layer, vg_status
|
|
|
|
|
|
|
|
|
|
|
|
umring_progress.set_value(3)
|
|
|
|
|
|
umring_progress.close()
|
|
|
|
|
|
|
|
|
|
|
|
if ergebnis_layer and ergebnis_layer.isValid():
|
|
|
|
|
|
project.addMapLayer(ergebnis_layer)
|
|
|
|
|
|
|
|
|
|
|
|
show_info_dialog(
|
|
|
|
|
|
"Detailprüfung",
|
|
|
|
|
|
f"Detailprüfung abgeschlossen. "
|
|
|
|
|
|
f"Es wurden {konflikt_anzahl} Konfliktstellen identifiziert.",
|
|
|
|
|
|
parent=tab_widget,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
abgeschlossen = True
|
|
|
|
|
|
return enriched_layer, flst_layer, alkis_vg_layer, vg_status
|
2026-04-22 14:53:45 +02:00
|
|
|
|
|
|
|
|
|
|
finally:
|
2026-04-23 22:24:14 +02:00
|
|
|
|
# WFS-Temp-Layer stets aus dem Projekt entfernen
|
|
|
|
|
|
_entferne_hilfs_layer(project, "TempVerfahrensgebiet")
|
|
|
|
|
|
# BROR-Layer bei Fehler/Abbruch entfernen (nur wenn in diesem Lauf hinzugefügt)
|
|
|
|
|
|
if not abgeschlossen and bror_was_added_by_us and alkis_vg_layer is not None:
|
2026-04-22 14:53:45 +02:00
|
|
|
|
try:
|
|
|
|
|
|
project.removeMapLayer(alkis_vg_layer.id())
|
|
|
|
|
|
except Exception:
|
|
|
|
|
|
pass
|
2026-04-23 22:24:14 +02:00
|
|
|
|
|