Verfahrensgebietsprüfung auf Knickpunkte umgestellt

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
2026-05-05 19:46:08 +02:00
co-authored by Copilot
parent 8730e1bf96
commit e344a5ad4a
6 changed files with 1104 additions and 61 deletions
+152
View File
@@ -914,6 +914,158 @@ def _erstelle_joined_layer(
result_layer.updateExtents()
return result_layer
def lade_punktort_ta(
schluessel_liste: List[str],
vg_geom,
progress=None,
) -> Optional[object]:
"""Lädt ``AX_PunktortTA`` gemarkungsweise mit STARTINDEX-Paginierung.
Verwendet dieselbe Strategie wie :func:`grenzpunkte_gemarkungsweise`:
1. Gemarkungsextents laden und mit einem 200-m-VG-Puffer verschneiden.
2. Hits-Abfrage pro Gemarkung zur Batch-Planung.
3. PunktortTA je Gemarkung in 5000-Feature-Batches laden (STARTINDEX-Paging).
4. gml_id-Deduplizierung über Gemarkungsgrenzen hinweg.
Es werden keine Grenzpunkt-Batches geladen – die Funktion gibt ausschließlich
den PunktortTA-Layer zurück.
Parameters
----------
schluessel_liste :
4-stellige Gemarkungsnummern (aus dem aktuellen Workflow bereits bekannt).
vg_geom :
``QgsGeometry`` des BROR-Objekts (EPSG:25833). Wird für den 200-m-Puffer
zur Einschränkung der Gemarkungsextents verwendet.
progress :
Optionales Fortschrittsdialog-Objekt mit ``set_label()``, ``set_value()``
und ``is_canceled()``.
Returns
-------
QgsVectorLayer | None
Memory-Layer mit allen PunktortTA-Features oder ``None`` bei Fehler.
"""
from sn_basis.functions import QgsField
from sn_basis.functions import QgsFeature as _QgsFeature
from sn_basis.functions.qt_wrapper import QVariant
_BBOX_BATCH = 5000
if not schluessel_liste:
return None
if vg_geom and not vg_geom.isEmpty():
extents = _lade_gemarkung_extents_mit_puffer(schluessel_liste, vg_geom, 200.0)
else:
extents = _lade_gemarkung_extents(schluessel_liste)
if not extents:
return None
n_extents = len(extents)
alle_records: List[Dict] = []
gesehene_ids: set = set()
feld_namen: List[str] = []
for g_idx, (gemarkungsnummer, bbox) in enumerate(extents.items(), 1):
if progress is not None and progress.is_canceled():
return None
bbox_param = _punktort_ta_bbox_param(bbox)
n_hits = _wfs_hits_count(ALKIS_SF_URL, PUNKTORT_TA_TYPENAME, {'BBOX': bbox_param})
n_batches = max(1, math.ceil(n_hits / _BBOX_BATCH)) if n_hits > 0 else 1
info(
"Grenzpunkte (Diagnose)",
f"Gemarkung {gemarkungsnummer} ({g_idx}/{n_extents}): "
f"~{n_hits} PunktortTA → {n_batches} Batch(es).",
duration=2,
)
for b_idx in range(n_batches):
if progress is not None:
progress.set_label(
f"PunktortTA: Gemarkung {gemarkungsnummer} "
f"({g_idx}/{n_extents}), Batch {b_idx + 1}/{n_batches} …"
)
if progress.is_canceled():
return None
extra: dict = {'BBOX': bbox_param}
if n_batches > 1:
extra['COUNT'] = str(_BBOX_BATCH)
extra['STARTINDEX'] = str(b_idx * _BBOX_BATCH)
_gml_bytes = _wfs_get_gml(ALKIS_SF_URL, PUNKTORT_TA_TYPENAME, extra)
if not _gml_bytes:
warning(
"Grenzpunkte (Diagnose)",
f"Gemarkung {gemarkungsnummer} Batch {b_idx + 1}: "
f"GET-Anfrage fehlgeschlagen – übersprungen.",
duration=4,
)
continue
tmp = _parse_alkis_gml_memory_layer(
_gml_bytes, "AX_PunktortTA", "_TmpPTA", geom_prop="position"
)
if not tmp:
continue
cur_felder = [f.name() for f in tmp.fields()]
for n in cur_felder:
if n not in feld_namen:
feld_namen.append(n)
for feat in tmp.getFeatures():
gml_id = _extrahiere_feature_gml_id(feat, cur_felder)
if gml_id and gml_id in gesehene_ids:
continue
if gml_id:
gesehene_ids.add(gml_id)
attrs: Dict = {}
for n in cur_felder:
if n:
try:
attrs[n] = feat[n]
except Exception:
pass
alle_records.append({'geom': feat.geometry(), 'attrs': attrs})
info(
"Grenzpunkte (Diagnose)",
f"Gemarkung {gemarkungsnummer}: {len(gesehene_ids)} PunktortTA bisher.",
duration=2,
)
if not alle_records:
return None
result = QgsVectorLayer("Point?crs=EPSG:25833", PUNKTORT_LAYER_NAME, "memory")
pr = result.dataProvider()
pr.addAttributes([QgsField(n, QVariant.String) for n in feld_namen if n])
result.updateFields()
neue_features = []
for record in alle_records:
f = _QgsFeature(result.fields())
f.setGeometry(record['geom'])
for n, val in record['attrs'].items():
if n in feld_namen:
try:
f[n] = val
except Exception:
pass
neue_features.append(f)
pr.addFeatures(neue_features)
result.updateExtents()
return result
def grenzpunkt_alkis(tab_widget, extent=None) -> Tuple[Optional[object], Optional[object]]:
"""Lädt Grenzpunkte aus dem ALKIS-WFS für den angegebenen Begrenzungsrahmen.