Verfahrensgebietsprüfung auf Knickpunkte umgestellt
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
@@ -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.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user