Statisitik Umringsgrenzpunkte ergänzt
This commit is contained in:
@@ -227,6 +227,7 @@ def _parse_alkis_gml_memory_layer(
|
|||||||
feature_local_name: str,
|
feature_local_name: str,
|
||||||
layer_name: str,
|
layer_name: str,
|
||||||
geom_prop: Optional[str] = "position",
|
geom_prop: Optional[str] = "position",
|
||||||
|
extract_qualitaet: bool = False,
|
||||||
) -> Optional[object]:
|
) -> Optional[object]:
|
||||||
"""Parst ALKIS-GML-Bytes und erstellt einen QGIS Memory-Layer.
|
"""Parst ALKIS-GML-Bytes und erstellt einen QGIS Memory-Layer.
|
||||||
|
|
||||||
@@ -243,6 +244,11 @@ def _parse_alkis_gml_memory_layer(
|
|||||||
Anzeigename des resultierenden Memory-Layers.
|
Anzeigename des resultierenden Memory-Layers.
|
||||||
geom_prop :
|
geom_prop :
|
||||||
Lokaler Name des Geometrie-Attributs (``None`` = kein Geometrie-Layer).
|
Lokaler Name des Geometrie-Attributs (``None`` = kein Geometrie-Layer).
|
||||||
|
extract_qualitaet :
|
||||||
|
Wenn ``True``, wird das verschachtelte Attribut
|
||||||
|
``qualitaetsangaben_ax_dqpunktort_genauigkeitsstufe`` aus
|
||||||
|
``adv:qualitaetsangaben/adv:genauigkeitsstufe`` extrahiert.
|
||||||
|
Nur für ``AX_PunktortTA`` sinnvoll.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
@@ -271,12 +277,18 @@ def _parse_alkis_gml_memory_layer(
|
|||||||
|
|
||||||
# Felder aus ALLEN Features ermitteln (2-Pass), damit optionale Felder
|
# Felder aus ALLEN Features ermitteln (2-Pass), damit optionale Felder
|
||||||
# wie "istTeilVon" nicht verloren gehen, wenn sie im ersten Feature fehlen.
|
# wie "istTeilVon" nicht verloren gehen, wenn sie im ersten Feature fehlen.
|
||||||
|
_QUALITAET_CONTAINER = "qualitaetsangaben"
|
||||||
|
_QUALITAET_FELD = "qualitaetsangaben_ax_dqpunktort_genauigkeitsstufe"
|
||||||
feld_namen: List[str] = ["gml_id"]
|
feld_namen: List[str] = ["gml_id"]
|
||||||
for feat_el in feat_elems:
|
for feat_el in feat_elems:
|
||||||
for child in feat_el:
|
for child in feat_el:
|
||||||
local = child.tag.split("}")[-1] if "}" in child.tag else child.tag
|
local = child.tag.split("}")[-1] if "}" in child.tag else child.tag
|
||||||
|
if extract_qualitaet and local == _QUALITAET_CONTAINER:
|
||||||
|
continue # Container wird durch verschachteltes Einzelfeld ersetzt
|
||||||
if local not in feld_namen and local != geom_prop:
|
if local not in feld_namen and local != geom_prop:
|
||||||
feld_namen.append(local)
|
feld_namen.append(local)
|
||||||
|
if extract_qualitaet and _QUALITAET_FELD not in feld_namen:
|
||||||
|
feld_namen.append(_QUALITAET_FELD)
|
||||||
|
|
||||||
# Memory-Layer anlegen
|
# Memory-Layer anlegen
|
||||||
mem_uri = f"Point?crs=EPSG:25833" if geom_prop else "none"
|
mem_uri = f"Point?crs=EPSG:25833" if geom_prop else "none"
|
||||||
@@ -312,6 +324,15 @@ def _parse_alkis_gml_memory_layer(
|
|||||||
|
|
||||||
for child in feat_elem:
|
for child in feat_elem:
|
||||||
local = child.tag.split("}")[-1] if "}" in child.tag else child.tag
|
local = child.tag.split("}")[-1] if "}" in child.tag else child.tag
|
||||||
|
if extract_qualitaet and local == _QUALITAET_CONTAINER:
|
||||||
|
# Verschachtelten Genauigkeitswert extrahieren
|
||||||
|
qual_el = child.find(f".//{{{_ADV}}}genauigkeitsstufe")
|
||||||
|
if qual_el is not None and qual_el.text:
|
||||||
|
try:
|
||||||
|
qgs_feat[_QUALITAET_FELD] = qual_el.text.strip()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
continue
|
||||||
if local == geom_prop or local not in feld_namen:
|
if local == geom_prop or local not in feld_namen:
|
||||||
continue
|
continue
|
||||||
href = child.get(f"{{{_XLINK}}}href", "")
|
href = child.get(f"{{{_XLINK}}}href", "")
|
||||||
@@ -781,7 +802,7 @@ def _lade_punktort_ta_batches_per_gemarkung(
|
|||||||
duration=4,
|
duration=4,
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
tmp = _parse_alkis_gml_memory_layer(_gml_bytes, "AX_PunktortTA", "_TmpPTA", geom_prop="position")
|
tmp = _parse_alkis_gml_memory_layer(_gml_bytes, "AX_PunktortTA", "_TmpPTA", geom_prop="position", extract_qualitaet=True)
|
||||||
if not tmp:
|
if not tmp:
|
||||||
warning(
|
warning(
|
||||||
"Grenzpunkte (Diagnose)",
|
"Grenzpunkte (Diagnose)",
|
||||||
@@ -1010,7 +1031,7 @@ def lade_punktort_ta(
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
tmp = _parse_alkis_gml_memory_layer(
|
tmp = _parse_alkis_gml_memory_layer(
|
||||||
_gml_bytes, "AX_PunktortTA", "_TmpPTA", geom_prop="position"
|
_gml_bytes, "AX_PunktortTA", "_TmpPTA", geom_prop="position", extract_qualitaet=True
|
||||||
)
|
)
|
||||||
if not tmp:
|
if not tmp:
|
||||||
continue
|
continue
|
||||||
@@ -1401,7 +1422,7 @@ def grenzpunkte_gemarkungsweise(
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
tmp = _parse_alkis_gml_memory_layer(
|
tmp = _parse_alkis_gml_memory_layer(
|
||||||
_gml_bytes, "AX_PunktortTA", "_TmpPTA", geom_prop="position"
|
_gml_bytes, "AX_PunktortTA", "_TmpPTA", geom_prop="position", extract_qualitaet=True
|
||||||
)
|
)
|
||||||
if not tmp:
|
if not tmp:
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -0,0 +1,373 @@
|
|||||||
|
"""sn_verfahrensgebiet/functions/umringstatistik_grenzpunkte.py – Umringstatistik Grenzpunkte.
|
||||||
|
|
||||||
|
Extrahiert aus einem vorhandenen ``Grenzpunkte (ALKIS)``-Layer alle Punkte,
|
||||||
|
die auf dem Umring des Verfahrensgebiets liegen, und klassifiziert sie in
|
||||||
|
drei Kategorien:
|
||||||
|
|
||||||
|
1. **FGP** (grün): ``gp_festgestellterGrenzpunkt == "true"``
|
||||||
|
2. **<3cm** (gelb): ``gp_festgestellterGrenzpunkt != "true"``
|
||||||
|
UND ``qualitaetsangaben_ax_dqpunktort_genauigkeitsstufe == 2100``
|
||||||
|
3. **>3cm** (rot): ``gp_festgestellterGrenzpunkt != "true"``
|
||||||
|
UND ``qualitaetsangaben_ax_dqpunktort_genauigkeitsstufe > 2100``
|
||||||
|
4. **unbekannt** (grau): keiner der obigen Fälle
|
||||||
|
|
||||||
|
Der Umring-Test verwendet einen Abstandsschwellwert von :data:`UMRING_TOLERANZ_M`.
|
||||||
|
|
||||||
|
**Rückgabe:** Memory-Layer ``Umringstatistik Grenzpunkte`` oder ``None`` bei Fehler.
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from sn_basis.functions import QgsProject
|
||||||
|
from sn_basis.functions.qt_wrapper import QMessageBox
|
||||||
|
from sn_basis.functions.dialog_wrapper import create_progress_dialog
|
||||||
|
from sn_basis.functions.message_wrapper import warning
|
||||||
|
from sn_basis.functions.qgiscore_wrapper import (
|
||||||
|
QgsVectorLayer,
|
||||||
|
QgsFeature,
|
||||||
|
QgsField,
|
||||||
|
QgsGeometry,
|
||||||
|
polygon_zu_linie,
|
||||||
|
)
|
||||||
|
from sn_basis.functions.qt_wrapper import QVariant
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Konstanten
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#: Anzeigename des Ergebnis-Layers.
|
||||||
|
ERGEBNIS_LAYER_NAME = "Umringstatistik Grenzpunkte"
|
||||||
|
|
||||||
|
#: Feldname für die Klassifikationskategorie im Ergebnis-Layer.
|
||||||
|
FELD_KATEGORIE = "kategorie"
|
||||||
|
|
||||||
|
#: Feldname für ``gp_festgestellterGrenzpunkt`` im Grenzpunkte(ALKIS)-Layer.
|
||||||
|
FELD_FESTGESTELLT = "gp_festgestellterGrenzpunkt"
|
||||||
|
|
||||||
|
#: Feldname für das Genauigkeitsattribut im Grenzpunkte(ALKIS)-Layer.
|
||||||
|
FELD_GENAUIGKEIT = "qualitaetsangaben_ax_dqpunktort_genauigkeitsstufe"
|
||||||
|
|
||||||
|
#: Feldname für die GML-ID im Grenzpunkte(ALKIS)-Layer.
|
||||||
|
FELD_GML_ID = "gml_id"
|
||||||
|
|
||||||
|
#: Kategoriewert: festgestellter Grenzpunkt.
|
||||||
|
KATEGORIE_FGP = "FGP"
|
||||||
|
#: Kategoriewert: Lagegenauigkeit ≤ 3 cm (Gütestufe 2100).
|
||||||
|
KATEGORIE_KLEIN = "<3cm"
|
||||||
|
#: Kategoriewert: Lagegenauigkeit > 3 cm (schlechtere Gütestufe).
|
||||||
|
KATEGORIE_GROSS = ">3cm"
|
||||||
|
#: Kategoriewert: Kategorie konnte nicht bestimmt werden.
|
||||||
|
KATEGORIE_UNBEKANNT = "unbekannt"
|
||||||
|
|
||||||
|
#: Maximaler Abstand (m) eines Punktes vom Umring, um als „auf dem Umring" zu gelten.
|
||||||
|
UMRING_TOLERANZ_M: float = 0.1
|
||||||
|
|
||||||
|
#: Grenzwert für ``qualitaetsangaben_ax_dqpunktort_genauigkeitsstufe`` (3-cm-Schwelle).
|
||||||
|
GENAUIGKEIT_GRENZWERT: int = 2100
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Interne Hilfsfunktionen
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def _setze_kategorien_symbologie(layer) -> None:
|
||||||
|
"""Wendet Kategoriesymbologie an: grün / gelb / rot / grau.
|
||||||
|
|
||||||
|
Wird bei fehlendem QGIS-Kontext still ignoriert.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
from qgis.core import ( # type: ignore[import]
|
||||||
|
QgsCategorizedSymbolRenderer,
|
||||||
|
QgsRendererCategory,
|
||||||
|
QgsMarkerSymbol,
|
||||||
|
)
|
||||||
|
|
||||||
|
def _marker(color: str, size: str = "2.5") -> object:
|
||||||
|
return QgsMarkerSymbol.createSimple(
|
||||||
|
{"color": color, "size": size, "outline_style": "no"}
|
||||||
|
)
|
||||||
|
|
||||||
|
categories = [
|
||||||
|
QgsRendererCategory(
|
||||||
|
KATEGORIE_FGP,
|
||||||
|
_marker("0,180,0,255"),
|
||||||
|
f"{KATEGORIE_FGP} – festgestellter Grenzpunkt",
|
||||||
|
),
|
||||||
|
QgsRendererCategory(
|
||||||
|
KATEGORIE_KLEIN,
|
||||||
|
_marker("255,220,0,255"),
|
||||||
|
f"{KATEGORIE_KLEIN} – Gütestufe {GENAUIGKEIT_GRENZWERT}",
|
||||||
|
),
|
||||||
|
QgsRendererCategory(
|
||||||
|
KATEGORIE_GROSS,
|
||||||
|
_marker("220,0,0,255"),
|
||||||
|
f"{KATEGORIE_GROSS} – Gütestufe > {GENAUIGKEIT_GRENZWERT}",
|
||||||
|
),
|
||||||
|
QgsRendererCategory(
|
||||||
|
KATEGORIE_UNBEKANNT,
|
||||||
|
_marker("128,128,128,255"),
|
||||||
|
f"{KATEGORIE_UNBEKANNT} – Kategorie nicht bestimmbar",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
renderer = QgsCategorizedSymbolRenderer(FELD_KATEGORIE, categories)
|
||||||
|
layer.setRenderer(renderer)
|
||||||
|
except Exception:
|
||||||
|
pass # Kein QGIS-Kontext (Tests) → Standarddarstellung behalten
|
||||||
|
|
||||||
|
|
||||||
|
def _klassifiziere(feat) -> str:
|
||||||
|
"""Bestimmt die Kategorie eines Grenzpunkts anhand seiner Attribute.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
feat :
|
||||||
|
Feature aus dem Grenzpunkte(ALKIS)-Layer.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
str
|
||||||
|
Einer der Kategorienwerte :data:`KATEGORIE_FGP`, :data:`KATEGORIE_KLEIN`,
|
||||||
|
:data:`KATEGORIE_GROSS` oder :data:`KATEGORIE_UNBEKANNT`.
|
||||||
|
"""
|
||||||
|
# festgestellterGrenzpunkt
|
||||||
|
try:
|
||||||
|
festgestellt_raw = feat[FELD_FESTGESTELLT]
|
||||||
|
festgestellt = str(festgestellt_raw).lower().strip() == "true" if festgestellt_raw else False
|
||||||
|
except Exception:
|
||||||
|
festgestellt = False
|
||||||
|
|
||||||
|
if festgestellt:
|
||||||
|
return KATEGORIE_FGP
|
||||||
|
|
||||||
|
# Genauigkeitsstufe auslesen
|
||||||
|
try:
|
||||||
|
gen_raw = feat[FELD_GENAUIGKEIT]
|
||||||
|
genauigkeit = int(str(gen_raw).strip()) if gen_raw else None
|
||||||
|
except (ValueError, TypeError, Exception):
|
||||||
|
genauigkeit = None
|
||||||
|
|
||||||
|
if genauigkeit is None:
|
||||||
|
return KATEGORIE_UNBEKANNT
|
||||||
|
if genauigkeit == GENAUIGKEIT_GRENZWERT:
|
||||||
|
return KATEGORIE_KLEIN
|
||||||
|
if genauigkeit > GENAUIGKEIT_GRENZWERT:
|
||||||
|
return KATEGORIE_GROSS
|
||||||
|
# Genauigkeit < 2100 (besser als 3 cm, aber nicht festgestellt)
|
||||||
|
return KATEGORIE_UNBEKANNT
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Öffentliche API
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def umringstatistik_grenzpunkte(
|
||||||
|
tab_widget,
|
||||||
|
grenzpunkte_layer,
|
||||||
|
vg_layer,
|
||||||
|
) -> Optional[object]:
|
||||||
|
"""Klassifiziert Grenzpunkte auf dem VG-Umring nach Lagegenauigkeit.
|
||||||
|
|
||||||
|
Ablauf:
|
||||||
|
|
||||||
|
1. VG-Geometrie aus ``vg_layer`` berechnen → Umringslinie.
|
||||||
|
2. Alle Features aus ``grenzpunkte_layer`` auf Abstand ≤ :data:`UMRING_TOLERANZ_M`
|
||||||
|
zum Umring prüfen.
|
||||||
|
3. Treffer klassifizieren (FGP / <3cm / >3cm / unbekannt).
|
||||||
|
4. Ergebnis-Memory-Layer aufbauen und Kategoriesymbologie setzen.
|
||||||
|
5. Layer ins Projekt einfügen, Zusammenfassungs-MessageBox anzeigen.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
tab_widget :
|
||||||
|
Eltern-Widget für Dialoge.
|
||||||
|
grenzpunkte_layer :
|
||||||
|
Geladener ``Grenzpunkte (ALKIS)``-Layer mit Attributen ``gp_festgestellterGrenzpunkt``
|
||||||
|
und ``qualitaetsangaben_ax_dqpunktort_genauigkeitsstufe``.
|
||||||
|
vg_layer :
|
||||||
|
Verfahrensgebiet-Layer (Polygon, EPSG:25833).
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
QgsVectorLayer | None
|
||||||
|
Ergebnis-Memory-Layer oder ``None`` bei Fehler/Abbruch.
|
||||||
|
"""
|
||||||
|
project = QgsProject.instance()
|
||||||
|
prog = create_progress_dialog(5, "Umringstatistik Grenzpunkte", "Schritt 1/5: VG-Umring berechnen …")
|
||||||
|
abgeschlossen = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
prog.set_value(0)
|
||||||
|
if prog.is_canceled():
|
||||||
|
return None
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
# Schritt 1: VG-Umring berechnen
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
feats_vg = [f for f in vg_layer.getFeatures() if f.hasGeometry() and not f.geometry().isEmpty()]
|
||||||
|
if not feats_vg:
|
||||||
|
prog.close()
|
||||||
|
warning("Umringstatistik", "Verfahrensgebiet-Layer enthält keine Geometrien.", duration=6)
|
||||||
|
return None
|
||||||
|
|
||||||
|
vg_geom = QgsGeometry.unaryUnion([f.geometry() for f in feats_vg])
|
||||||
|
if vg_geom is None or vg_geom.isEmpty():
|
||||||
|
prog.close()
|
||||||
|
warning("Umringstatistik", "Verfahrensgebiet-Geometrie konnte nicht vereint werden.", duration=6)
|
||||||
|
return None
|
||||||
|
|
||||||
|
umring_geom = polygon_zu_linie(vg_geom)
|
||||||
|
if umring_geom is None or umring_geom.isEmpty():
|
||||||
|
prog.close()
|
||||||
|
warning("Umringstatistik", "Umringslinie konnte aus der VG-Geometrie nicht extrahiert werden.", duration=6)
|
||||||
|
return None
|
||||||
|
|
||||||
|
prog.set_value(1)
|
||||||
|
if prog.is_canceled():
|
||||||
|
return None
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
# Schritt 2: Grenzpunkte auf dem Umring filtern
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
prog.set_label("Schritt 2/5: Grenzpunkte auf Umring prüfen …")
|
||||||
|
|
||||||
|
n_gesamt = grenzpunkte_layer.featureCount()
|
||||||
|
treffer: list = []
|
||||||
|
|
||||||
|
for i, feat in enumerate(grenzpunkte_layer.getFeatures()):
|
||||||
|
if i % 200 == 0:
|
||||||
|
prog.set_label(
|
||||||
|
f"Schritt 2/5: Grenzpunkte prüfen … ({i}/{n_gesamt})"
|
||||||
|
)
|
||||||
|
if prog.is_canceled():
|
||||||
|
return None
|
||||||
|
|
||||||
|
if not feat.hasGeometry() or feat.geometry().isEmpty():
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
dist = feat.geometry().distance(umring_geom)
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
if dist <= UMRING_TOLERANZ_M:
|
||||||
|
treffer.append(feat)
|
||||||
|
|
||||||
|
prog.set_value(2)
|
||||||
|
if prog.is_canceled():
|
||||||
|
return None
|
||||||
|
|
||||||
|
if not treffer:
|
||||||
|
prog.close()
|
||||||
|
QMessageBox.information(
|
||||||
|
tab_widget,
|
||||||
|
"Umringstatistik Grenzpunkte",
|
||||||
|
"Es wurden keine Grenzpunkte auf dem Umring des Verfahrensgebiets gefunden.\n\n"
|
||||||
|
f"Geprüft: {n_gesamt} Grenzpunkte\n"
|
||||||
|
f"Toleranz: {UMRING_TOLERANZ_M} m",
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
# Schritt 3: Klassifizieren
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
prog.set_label(f"Schritt 3/5: {len(treffer)} Treffer klassifizieren …")
|
||||||
|
|
||||||
|
n_fgp = 0
|
||||||
|
n_klein = 0
|
||||||
|
n_gross = 0
|
||||||
|
n_unbekannt = 0
|
||||||
|
|
||||||
|
klassifiziert: list = [] # [(feat, kategorie), ...]
|
||||||
|
for feat in treffer:
|
||||||
|
kat = _klassifiziere(feat)
|
||||||
|
klassifiziert.append((feat, kat))
|
||||||
|
if kat == KATEGORIE_FGP:
|
||||||
|
n_fgp += 1
|
||||||
|
elif kat == KATEGORIE_KLEIN:
|
||||||
|
n_klein += 1
|
||||||
|
elif kat == KATEGORIE_GROSS:
|
||||||
|
n_gross += 1
|
||||||
|
else:
|
||||||
|
n_unbekannt += 1
|
||||||
|
|
||||||
|
prog.set_value(3)
|
||||||
|
if prog.is_canceled():
|
||||||
|
return None
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
# Schritt 4: Ergebnis-Layer aufbauen
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
prog.set_label("Schritt 4/5: Ergebnis-Layer aufbauen …")
|
||||||
|
|
||||||
|
crs_authid = vg_layer.crs().authid() or "EPSG:25833"
|
||||||
|
result_layer = QgsVectorLayer(
|
||||||
|
f"Point?crs={crs_authid}", ERGEBNIS_LAYER_NAME, "memory"
|
||||||
|
)
|
||||||
|
pr = result_layer.dataProvider()
|
||||||
|
|
||||||
|
felder = [
|
||||||
|
QgsField(FELD_KATEGORIE, QVariant.String),
|
||||||
|
QgsField(FELD_GML_ID, QVariant.String),
|
||||||
|
QgsField(FELD_FESTGESTELLT, QVariant.String),
|
||||||
|
QgsField(FELD_GENAUIGKEIT, QVariant.String),
|
||||||
|
]
|
||||||
|
pr.addAttributes(felder)
|
||||||
|
result_layer.updateFields()
|
||||||
|
|
||||||
|
neue_features = []
|
||||||
|
for feat, kat in klassifiziert:
|
||||||
|
new_f = QgsFeature(result_layer.fields())
|
||||||
|
new_f.setGeometry(feat.geometry())
|
||||||
|
|
||||||
|
new_f[FELD_KATEGORIE] = kat
|
||||||
|
|
||||||
|
for src_feld in (FELD_GML_ID, FELD_FESTGESTELLT, FELD_GENAUIGKEIT):
|
||||||
|
try:
|
||||||
|
new_f[src_feld] = feat[src_feld]
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
neue_features.append(new_f)
|
||||||
|
|
||||||
|
pr.addFeatures(neue_features)
|
||||||
|
result_layer.updateExtents()
|
||||||
|
_setze_kategorien_symbologie(result_layer)
|
||||||
|
|
||||||
|
prog.set_value(4)
|
||||||
|
if prog.is_canceled():
|
||||||
|
return None
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
# Schritt 5: Layer ins Projekt + Ergebnis-MessageBox
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
prog.set_label("Schritt 5/5: Layer ins Projekt einfügen …")
|
||||||
|
|
||||||
|
# Bestehenden Ergebnis-Layer ggf. ersetzen
|
||||||
|
vorhandene = project.mapLayersByName(ERGEBNIS_LAYER_NAME)
|
||||||
|
for lyr in vorhandene:
|
||||||
|
project.removeMapLayer(lyr.id())
|
||||||
|
|
||||||
|
project.addMapLayer(result_layer)
|
||||||
|
|
||||||
|
prog.set_value(5)
|
||||||
|
abgeschlossen = True
|
||||||
|
prog.close()
|
||||||
|
|
||||||
|
n_umring = len(treffer)
|
||||||
|
QMessageBox.information(
|
||||||
|
tab_widget,
|
||||||
|
"Umringstatistik Grenzpunkte",
|
||||||
|
f"Grenzpunkte auf dem Umring: {n_umring}\n"
|
||||||
|
f"\n"
|
||||||
|
f" FGP (festgestellt): {n_fgp}\n"
|
||||||
|
f" < 3 cm (Gütestufe {GENAUIGKEIT_GRENZWERT}): {n_klein}\n"
|
||||||
|
f" > 3 cm (schlechtere Güte): {n_gross}\n"
|
||||||
|
f" Unbekannt: {n_unbekannt}\n"
|
||||||
|
f"\n"
|
||||||
|
f"(Geprüft: {n_gesamt} Grenzpunkte, Toleranz: {UMRING_TOLERANZ_M} m)",
|
||||||
|
)
|
||||||
|
|
||||||
|
return result_layer
|
||||||
|
|
||||||
|
finally:
|
||||||
|
if not abgeschlossen:
|
||||||
|
prog.close()
|
||||||
+46
-1
@@ -16,8 +16,9 @@ from qgis.utils import iface
|
|||||||
from sn_verfahrensgebiet.functions.verfahrensgebiet_alkis import LoadStatus
|
from sn_verfahrensgebiet.functions.verfahrensgebiet_alkis import LoadStatus
|
||||||
from sn_verfahrensgebiet.functions.flurstueck_alkis import flurstueck_alkis
|
from sn_verfahrensgebiet.functions.flurstueck_alkis import flurstueck_alkis
|
||||||
from sn_verfahrensgebiet.functions.verfahrensgebiet_alkis_komplett import verfahrensgebiet_alkis_komplett
|
from sn_verfahrensgebiet.functions.verfahrensgebiet_alkis_komplett import verfahrensgebiet_alkis_komplett
|
||||||
from sn_verfahrensgebiet.functions.grenzpunkt_alkis import grenzpunkte_gemarkungsweise
|
from sn_verfahrensgebiet.functions.grenzpunkt_alkis import grenzpunkte_gemarkungsweise, JOINED_LAYER_NAME
|
||||||
from sn_verfahrensgebiet.functions.gemarkung_alkis import gemarkung_schluessel_und_namen_von_vg_geometrie
|
from sn_verfahrensgebiet.functions.gemarkung_alkis import gemarkung_schluessel_und_namen_von_vg_geometrie
|
||||||
|
from sn_verfahrensgebiet.functions.umringstatistik_grenzpunkte import umringstatistik_grenzpunkte
|
||||||
from sn_verfahrensgebiet.functions.verfahrensgebiet_edit_service import (
|
from sn_verfahrensgebiet.functions.verfahrensgebiet_edit_service import (
|
||||||
pruefe_flurstueck_layer,
|
pruefe_flurstueck_layer,
|
||||||
pruefe_auswahl,
|
pruefe_auswahl,
|
||||||
@@ -104,6 +105,11 @@ class WorkingTab(QWidget):
|
|||||||
row_grenz_buttons.addWidget(self.btn_grenz_alkis)
|
row_grenz_buttons.addWidget(self.btn_grenz_alkis)
|
||||||
layout.addLayout(row_grenz_buttons)
|
layout.addLayout(row_grenz_buttons)
|
||||||
|
|
||||||
|
row_umring_buttons = QHBoxLayout()
|
||||||
|
self.btn_umring_statistik = QPushButton("Umringstatistik Grenzpunkte")
|
||||||
|
row_umring_buttons.addWidget(self.btn_umring_statistik)
|
||||||
|
layout.addLayout(row_umring_buttons)
|
||||||
|
|
||||||
# Abschnitt 3: Verfahrensgebiet erstellen
|
# Abschnitt 3: Verfahrensgebiet erstellen
|
||||||
row_verf_erstellen_header = QHBoxLayout()
|
row_verf_erstellen_header = QHBoxLayout()
|
||||||
lbl_verf_erstellen = QLabel("<b>Verfahrensgebiet erstellen</b>")
|
lbl_verf_erstellen = QLabel("<b>Verfahrensgebiet erstellen</b>")
|
||||||
@@ -128,6 +134,7 @@ class WorkingTab(QWidget):
|
|||||||
self.btn_verf_alkis.clicked.connect(self.handle_verf_alkis)
|
self.btn_verf_alkis.clicked.connect(self.handle_verf_alkis)
|
||||||
self.btn_flurst_alkis.clicked.connect(self.handle_flurst_alkis)
|
self.btn_flurst_alkis.clicked.connect(self.handle_flurst_alkis)
|
||||||
self.btn_grenz_alkis.clicked.connect(self.handle_grenz_alkis)
|
self.btn_grenz_alkis.clicked.connect(self.handle_grenz_alkis)
|
||||||
|
self.btn_umring_statistik.clicked.connect(self.handle_umringstatistik)
|
||||||
self.btn_verf_aus_auswahl.clicked.connect(self.handle_verf_aus_auswahl)
|
self.btn_verf_aus_auswahl.clicked.connect(self.handle_verf_aus_auswahl)
|
||||||
self.btn_verf_aus_liste.clicked.connect(self.handle_verf_aus_liste)
|
self.btn_verf_aus_liste.clicked.connect(self.handle_verf_aus_liste)
|
||||||
# self.btn_verf_shape.clicked.connect(self.handle_verf_shape)
|
# self.btn_verf_shape.clicked.connect(self.handle_verf_shape)
|
||||||
@@ -488,6 +495,44 @@ class WorkingTab(QWidget):
|
|||||||
finally:
|
finally:
|
||||||
self._set_busy(self.btn_grenz_alkis, False, "Grenzpunkte aus ALKIS laden")
|
self._set_busy(self.btn_grenz_alkis, False, "Grenzpunkte aus ALKIS laden")
|
||||||
|
|
||||||
|
def handle_umringstatistik(self) -> None:
|
||||||
|
"""Klassifiziert Grenzpunkte auf dem VG-Umring nach Lagegenauigkeit.
|
||||||
|
|
||||||
|
Sucht den vorhandenen ``Grenzpunkte (ALKIS)``-Layer im Projekt und
|
||||||
|
kombiniert ihn mit dem gewählten Verfahrensgebiet-Layer, um die
|
||||||
|
Umringstatistik zu berechnen.
|
||||||
|
"""
|
||||||
|
# 1. Grenzpunkte-Layer aus dem Projekt holen
|
||||||
|
project = QgsProject.instance()
|
||||||
|
gp_layers = project.mapLayersByName(JOINED_LAYER_NAME)
|
||||||
|
if not gp_layers:
|
||||||
|
warning(
|
||||||
|
"Umringstatistik",
|
||||||
|
f"Kein Layer '{JOINED_LAYER_NAME}' im Projekt gefunden. "
|
||||||
|
"Bitte zuerst 'Grenzpunkte aus ALKIS laden' ausführen.",
|
||||||
|
duration=8,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
grenzpunkte_layer = gp_layers[0]
|
||||||
|
|
||||||
|
# 2. Verfahrensgebiet-Layer aus Dropdown
|
||||||
|
vg_layer = self.verf_layer_combo.currentLayer()
|
||||||
|
if not vg_layer or not vg_layer.isValid():
|
||||||
|
warning(
|
||||||
|
"Umringstatistik",
|
||||||
|
"Kein Verfahrensgebiet-Layer gewählt. Bitte zuerst ein Verfahrensgebiet laden.",
|
||||||
|
duration=6,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
self._set_busy(self.btn_umring_statistik, True, "Umringstatistik Grenzpunkte")
|
||||||
|
try:
|
||||||
|
result_layer = umringstatistik_grenzpunkte(self, grenzpunkte_layer, vg_layer)
|
||||||
|
if result_layer and result_layer.isValid():
|
||||||
|
iface.mapCanvas().refresh()
|
||||||
|
finally:
|
||||||
|
self._set_busy(self.btn_umring_statistik, False, "Umringstatistik Grenzpunkte")
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Modul-Hilfsfunktionen
|
# Modul-Hilfsfunktionen
|
||||||
|
|||||||
Reference in New Issue
Block a user