468 lines
15 KiB
Python
468 lines
15 KiB
Python
"""sn_verfahrensgebiet/functions/knickpunkt_pruefung.py – Knickpunktbasierte BROR-Prüfung.
|
||||
|
|
|
|||
|
|
Vergleicht die Knickpunkte (Stützpunkte) des BauRaumOderBodenordnungsrecht-
|
|||
|
|
Polygons mit den Punktorten der geladenen ``AX_PunktortTA``-Objekte und
|
|||
|
|
identifiziert:
|
|||
|
|
|
|||
|
|
- **Identische Punkte** (grün): An einem BROR-Knickpunkt liegt ein PunktortTA.
|
|||
|
|
- **Fehlende PunktortTA** (rot): Ein BROR-Knickpunkt hat keinen zugehörigen PunktortTA.
|
|||
|
|
- **Fehlende Knickpunkte** (orange): Ein PunktortTA liegt nahe des BROR-Umrings
|
|||
|
|
auf einer Flurstücksgrenze, hat aber keinen entsprechenden Knickpunkt im BROR.
|
|||
|
|
|
|||
|
|
**Algorithmus:**
|
|||
|
|
|
|||
|
|
1. BROR-Polygon-Stützpunkte (Knickpunkte) extrahieren.
|
|||
|
|
2. Spatial-Index auf PunktortTA aufbauen.
|
|||
|
|
3. Für jeden Knickpunkt nächsten PunktortTA im Radius von
|
|||
|
|
:data:`KOORDINATEN_TOLERANZ_M` suchen → grün oder rot.
|
|||
|
|
Gematchte PunktortTA-Feature-IDs merken.
|
|||
|
|
4. Gepufferter BROR-Umring + Flurstück-Vertex-Set ermitteln.
|
|||
|
|
5. Nicht-gematchte PunktortTA nahe BROR-Umring, die auf einer Flurstücksgrenze
|
|||
|
|
liegen → orange.
|
|||
|
|
|
|||
|
|
**Rückgabe:** ``(result_layer, identisch, kein_pta, fehlender_knick)``
|
|||
|
|
"""
|
|||
|
|
from __future__ import annotations
|
|||
|
|
|
|||
|
|
from typing import Dict, List, Optional, Set, Tuple
|
|||
|
|
|
|||
|
|
from sn_basis.functions.qgiscore_wrapper import (
|
|||
|
|
QgsVectorLayer,
|
|||
|
|
QgsFeature,
|
|||
|
|
QgsField,
|
|||
|
|
QgsGeometry,
|
|||
|
|
)
|
|||
|
|
from sn_basis.functions.qt_wrapper import QVariant
|
|||
|
|
|
|||
|
|
# ---------------------------------------------------------------------------
|
|||
|
|
# Konstanten
|
|||
|
|
# ---------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
#: Koordinatentoleranz für die Knickpunkt ↔ PunktortTA-Übereinstimmung (m).
|
|||
|
|
KOORDINATEN_TOLERANZ_M: float = 0.01
|
|||
|
|
|
|||
|
|
#: Puffer um den BROR-Umring für die Suche nach fehlenden Knickpunkten (m).
|
|||
|
|
BOUNDARY_PUFFER_M: float = 0.5
|
|||
|
|
|
|||
|
|
#: Rundungsgenauigkeit für Vertex-Koordinaten im Flurstück-Set (Dezimalstellen).
|
|||
|
|
_VERTEX_ROUND = 3
|
|||
|
|
|
|||
|
|
ERGEBNIS_LAYER_NAME = "Knickpunktprüfung"
|
|||
|
|
FELD_TYP = "typ"
|
|||
|
|
WERT_IDENTISCH = "identisch"
|
|||
|
|
WERT_KEIN_PTA = "kein_pta"
|
|||
|
|
WERT_FEHLENDER_KNICK = "fehlender_knick"
|
|||
|
|
|
|||
|
|
|
|||
|
|
# ---------------------------------------------------------------------------
|
|||
|
|
# Interne Hilfsfunktionen
|
|||
|
|
# ---------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
def _extrahiere_knickpunkte(bror_layer) -> List[object]:
|
|||
|
|
"""Extrahiert alle Stützpunkte (Knickpunkte) des BROR-Polygons.
|
|||
|
|
|
|||
|
|
Doppelte Start/End-Punkte eines Rings werden dedupliziert. Gibt eine
|
|||
|
|
flache Liste von ``QgsPointXY``-Objekten zurück.
|
|||
|
|
|
|||
|
|
Parameters
|
|||
|
|
----------
|
|||
|
|
bror_layer :
|
|||
|
|
BauRaumOderBodenordnungsrecht-Polygon-Layer.
|
|||
|
|
|
|||
|
|
Returns
|
|||
|
|
-------
|
|||
|
|
List[QgsPointXY]
|
|||
|
|
Alle eindeutigen Stützpunkte; leer bei Fehler.
|
|||
|
|
"""
|
|||
|
|
try:
|
|||
|
|
from qgis.core import QgsPointXY # type: ignore[import]
|
|||
|
|
|
|||
|
|
bror_feats = [
|
|||
|
|
f for f in bror_layer.getFeatures()
|
|||
|
|
if f.geometry() and not f.geometry().isEmpty()
|
|||
|
|
]
|
|||
|
|
if not bror_feats:
|
|||
|
|
return []
|
|||
|
|
|
|||
|
|
union_geom = QgsGeometry.unaryUnion([f.geometry() for f in bror_feats])
|
|||
|
|
if union_geom is None or union_geom.isEmpty():
|
|||
|
|
return []
|
|||
|
|
|
|||
|
|
punkte: List[object] = []
|
|||
|
|
seen: Set[Tuple[float, float]] = set()
|
|||
|
|
|
|||
|
|
def _add_ring(vertices):
|
|||
|
|
# Letzter Punkt = erster Punkt (Ring geschlossen) → überspringen
|
|||
|
|
ring_pts = list(vertices)
|
|||
|
|
n = len(ring_pts)
|
|||
|
|
if n >= 2:
|
|||
|
|
# Prüfen ob letzter Punkt identisch mit erstem
|
|||
|
|
last = n - 1
|
|||
|
|
if (
|
|||
|
|
abs(ring_pts[last].x() - ring_pts[0].x()) < 1e-9
|
|||
|
|
and abs(ring_pts[last].y() - ring_pts[0].y()) < 1e-9
|
|||
|
|
):
|
|||
|
|
ring_pts = ring_pts[:-1]
|
|||
|
|
for pt in ring_pts:
|
|||
|
|
key = (round(pt.x(), _VERTEX_ROUND), round(pt.y(), _VERTEX_ROUND))
|
|||
|
|
if key not in seen:
|
|||
|
|
seen.add(key)
|
|||
|
|
punkte.append(pt)
|
|||
|
|
|
|||
|
|
geom_type = union_geom.wkbType()
|
|||
|
|
# Polygon oder MultiPolygon
|
|||
|
|
if union_geom.isMultipart():
|
|||
|
|
for poly in union_geom.asMultiPolygon():
|
|||
|
|
for ring in poly:
|
|||
|
|
_add_ring([QgsPointXY(x, y) for x, y in ring])
|
|||
|
|
else:
|
|||
|
|
for ring in union_geom.asPolygon():
|
|||
|
|
_add_ring([QgsPointXY(x, y) for x, y in ring])
|
|||
|
|
|
|||
|
|
return punkte
|
|||
|
|
|
|||
|
|
except Exception:
|
|||
|
|
return []
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _erstelle_ergebnis_layer(crs_authid: str) -> object:
|
|||
|
|
"""Erzeugt den leeren Punkt-Ergebnislayer mit Feld ``typ``.
|
|||
|
|
|
|||
|
|
Parameters
|
|||
|
|
----------
|
|||
|
|
crs_authid :
|
|||
|
|
CRS-Kennung, z.B. ``"EPSG:25833"``.
|
|||
|
|
|
|||
|
|
Returns
|
|||
|
|
-------
|
|||
|
|
QgsVectorLayer
|
|||
|
|
Leerer Memory-Layer vom Typ Point.
|
|||
|
|
"""
|
|||
|
|
layer = QgsVectorLayer(
|
|||
|
|
f"Point?crs={crs_authid}", ERGEBNIS_LAYER_NAME, "memory"
|
|||
|
|
)
|
|||
|
|
pr = layer.dataProvider()
|
|||
|
|
pr.addAttributes([QgsField(FELD_TYP, QVariant.String)])
|
|||
|
|
layer.updateFields()
|
|||
|
|
return layer
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _setze_kategorien_symbologie(layer) -> None:
|
|||
|
|
"""Wendet Kategoriesymbologie an: grün/rot/orange Punkte.
|
|||
|
|
|
|||
|
|
- ``identisch`` → grün
|
|||
|
|
- ``kein_pta`` → rot
|
|||
|
|
- ``fehlender_knick`` → orange
|
|||
|
|
|
|||
|
|
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") -> object:
|
|||
|
|
return QgsMarkerSymbol.createSimple(
|
|||
|
|
{"color": color, "size": size, "outline_style": "no"}
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
categories = [
|
|||
|
|
QgsRendererCategory(
|
|||
|
|
WERT_IDENTISCH,
|
|||
|
|
_marker("0,180,0,255"),
|
|||
|
|
"identisch (Knickpunkt mit PunktortTA)",
|
|||
|
|
),
|
|||
|
|
QgsRendererCategory(
|
|||
|
|
WERT_KEIN_PTA,
|
|||
|
|
_marker("220,0,0,255"),
|
|||
|
|
"kein PunktortTA an Knickpunkt",
|
|||
|
|
),
|
|||
|
|
QgsRendererCategory(
|
|||
|
|
WERT_FEHLENDER_KNICK,
|
|||
|
|
_marker("255,128,0,255"),
|
|||
|
|
"fehlender Knickpunkt (PunktortTA ohne BROR-Knickpunkt)",
|
|||
|
|
),
|
|||
|
|
]
|
|||
|
|
renderer = QgsCategorizedSymbolRenderer(FELD_TYP, categories)
|
|||
|
|
layer.setRenderer(renderer)
|
|||
|
|
except Exception:
|
|||
|
|
pass # Kein QGIS-Kontext (Tests) → Standarddarstellung behalten
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _baue_pta_index(punktort_layer) -> Tuple[object, Dict[int, object]]:
|
|||
|
|
"""Baut einen QgsSpatialIndex und eine ID→Geometrie-Map für PunktortTA.
|
|||
|
|
|
|||
|
|
Parameters
|
|||
|
|
----------
|
|||
|
|
punktort_layer :
|
|||
|
|
Geladener ``AX_PunktortTA``-Layer.
|
|||
|
|
|
|||
|
|
Returns
|
|||
|
|
-------
|
|||
|
|
Tuple[QgsSpatialIndex, Dict[int, QgsGeometry]]
|
|||
|
|
Index und Feature-ID-zu-Geometrie-Dict.
|
|||
|
|
"""
|
|||
|
|
from qgis.core import QgsSpatialIndex # type: ignore[import]
|
|||
|
|
|
|||
|
|
index = QgsSpatialIndex()
|
|||
|
|
geom_map: Dict[int, object] = {}
|
|||
|
|
for feat in punktort_layer.getFeatures():
|
|||
|
|
geom = feat.geometry()
|
|||
|
|
if geom and not geom.isEmpty():
|
|||
|
|
index.insertFeature(feat)
|
|||
|
|
geom_map[feat.id()] = geom
|
|||
|
|
return index, geom_map
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _baue_flst_vertex_set(
|
|||
|
|
flst_layer,
|
|||
|
|
bror_buffer_geom,
|
|||
|
|
) -> Set[Tuple[float, float]]:
|
|||
|
|
"""Erstellt ein Set gerundeter (x, y)-Koordinaten aller Flurstück-Vertices
|
|||
|
|
innerhalb des gepufferten BROR-Umrings.
|
|||
|
|
|
|||
|
|
Parameters
|
|||
|
|
----------
|
|||
|
|
flst_layer :
|
|||
|
|
Flurstücke-Layer.
|
|||
|
|
bror_buffer_geom :
|
|||
|
|
Gepufferter BROR-Umring (Polygon-Geometrie).
|
|||
|
|
|
|||
|
|
Returns
|
|||
|
|
-------
|
|||
|
|
Set[Tuple[float, float]]
|
|||
|
|
Gerundete Vertex-Koordinaten.
|
|||
|
|
"""
|
|||
|
|
vertex_set: Set[Tuple[float, float]] = set()
|
|||
|
|
if flst_layer is None:
|
|||
|
|
return vertex_set
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
for feat in flst_layer.getFeatures():
|
|||
|
|
geom = feat.geometry()
|
|||
|
|
if geom is None or geom.isEmpty():
|
|||
|
|
continue
|
|||
|
|
try:
|
|||
|
|
# Nur Flurstücke berücksichtigen, die den Puffer berühren
|
|||
|
|
if not geom.intersects(bror_buffer_geom):
|
|||
|
|
continue
|
|||
|
|
boundary = geom.convertToType(1) # 1 = Line
|
|||
|
|
if boundary is None or boundary.isEmpty():
|
|||
|
|
continue
|
|||
|
|
if boundary.isMultipart():
|
|||
|
|
parts = boundary.asMultiPolyline()
|
|||
|
|
else:
|
|||
|
|
parts = [boundary.asPolyline()]
|
|||
|
|
for line in parts:
|
|||
|
|
for pt in line:
|
|||
|
|
vertex_set.add(
|
|||
|
|
(round(pt.x(), _VERTEX_ROUND), round(pt.y(), _VERTEX_ROUND))
|
|||
|
|
)
|
|||
|
|
except Exception:
|
|||
|
|
continue
|
|||
|
|
except Exception:
|
|||
|
|
pass
|
|||
|
|
return vertex_set
|
|||
|
|
|
|||
|
|
|
|||
|
|
# ---------------------------------------------------------------------------
|
|||
|
|
# Öffentliche API
|
|||
|
|
# ---------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
def knickpunkt_pruefung(
|
|||
|
|
bror_layer,
|
|||
|
|
punktort_layer,
|
|||
|
|
flst_layer,
|
|||
|
|
progress=None,
|
|||
|
|
knickpunkte: Optional[List] = None,
|
|||
|
|
) -> Tuple[Optional[object], int, int, int]:
|
|||
|
|
"""Knickpunktbasierte BROR-Prüfung.
|
|||
|
|
|
|||
|
|
Vergleicht BROR-Knickpunkte mit ``AX_PunktortTA``-Objekten und ermittelt
|
|||
|
|
fehlende Knickpunkte anhand von Flurstücksgrenzen.
|
|||
|
|
|
|||
|
|
Parameters
|
|||
|
|
----------
|
|||
|
|
bror_layer :
|
|||
|
|
BauRaumOderBodenordnungsrecht-Polygon-Layer.
|
|||
|
|
punktort_layer :
|
|||
|
|
Geladener ``AX_PunktortTA``-Layer (Ergebnis aus ``grenzpunkt_alkis``).
|
|||
|
|
flst_layer :
|
|||
|
|
Flurstücke-Layer für die Orange-Prüfung. Kann ``None`` sein.
|
|||
|
|
progress :
|
|||
|
|
Optionaler ``ProgressDialog`` für Fortschrittsanzeige.
|
|||
|
|
knickpunkte :
|
|||
|
|
Vorberechnete Knickpunktliste (optional). Wenn ``None``, werden die
|
|||
|
|
Knickpunkte aus ``bror_layer`` extrahiert.
|
|||
|
|
|
|||
|
|
Returns
|
|||
|
|
-------
|
|||
|
|
Tuple[Optional[QgsVectorLayer], int, int, int]
|
|||
|
|
``(result_layer, identisch_count, kein_pta_count, fehlender_knick_count)``
|
|||
|
|
|
|||
|
|
- ``result_layer``: Punkt-Layer mit grünen/roten/orangen Punkten,
|
|||
|
|
oder ``None`` bei Abbruch oder fehlgeschlagener Verarbeitung.
|
|||
|
|
- ``identisch_count``: Knickpunkte mit passendem PunktortTA (grün).
|
|||
|
|
- ``kein_pta_count``: Knickpunkte ohne passenden PunktortTA (rot).
|
|||
|
|
- ``fehlender_knick_count``: PunktortTA ohne BROR-Knickpunkt (orange).
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
def _canceled() -> bool:
|
|||
|
|
return progress is not None and progress.is_canceled()
|
|||
|
|
|
|||
|
|
def _schritt(label: str, wert: int) -> None:
|
|||
|
|
if progress is not None:
|
|||
|
|
progress.set_label(label)
|
|||
|
|
progress.set_value(wert)
|
|||
|
|
|
|||
|
|
# ------------------------------------------------------------------
|
|||
|
|
# Schritt 0: Knickpunkte ermitteln
|
|||
|
|
# ------------------------------------------------------------------
|
|||
|
|
_schritt("Knickpunktprüfung: Knickpunkte extrahieren …", 0)
|
|||
|
|
|
|||
|
|
if knickpunkte is None:
|
|||
|
|
knickpunkte = _extrahiere_knickpunkte(bror_layer)
|
|||
|
|
|
|||
|
|
if not knickpunkte:
|
|||
|
|
return None, 0, 0, 0
|
|||
|
|
|
|||
|
|
n = len(knickpunkte)
|
|||
|
|
crs_authid = bror_layer.crs().authid()
|
|||
|
|
|
|||
|
|
if _canceled():
|
|||
|
|
return None, 0, 0, 0
|
|||
|
|
|
|||
|
|
# ------------------------------------------------------------------
|
|||
|
|
# Schritt 1: Spatial-Index für PunktortTA aufbauen
|
|||
|
|
# ------------------------------------------------------------------
|
|||
|
|
_schritt("Knickpunktprüfung: PunktortTA-Index aufbauen …", 1)
|
|||
|
|
|
|||
|
|
if punktort_layer is None:
|
|||
|
|
return None, 0, 0, 0
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
pta_index, geom_map = _baue_pta_index(punktort_layer)
|
|||
|
|
except Exception:
|
|||
|
|
return None, 0, 0, 0
|
|||
|
|
|
|||
|
|
if _canceled():
|
|||
|
|
return None, 0, 0, 0
|
|||
|
|
|
|||
|
|
# ------------------------------------------------------------------
|
|||
|
|
# Schritte 2…n+1: Jeden Knickpunkt mit PunktortTA vergleichen
|
|||
|
|
# ------------------------------------------------------------------
|
|||
|
|
try:
|
|||
|
|
from qgis.core import QgsRectangle # type: ignore[import]
|
|||
|
|
except ImportError:
|
|||
|
|
return None, 0, 0, 0
|
|||
|
|
|
|||
|
|
ergebnis_layer = _erstelle_ergebnis_layer(crs_authid)
|
|||
|
|
pr = ergebnis_layer.dataProvider()
|
|||
|
|
feats_to_add: List[object] = []
|
|||
|
|
|
|||
|
|
identisch_count = 0
|
|||
|
|
kein_pta_count = 0
|
|||
|
|
matched_pta_ids: Set[int] = set()
|
|||
|
|
|
|||
|
|
for i, knick_pt in enumerate(knickpunkte):
|
|||
|
|
if _canceled():
|
|||
|
|
return None, 0, 0, 0
|
|||
|
|
|
|||
|
|
_schritt(f"Knickpunktprüfung: Knickpunkt {i + 1}/{n} prüfen …", i + 2)
|
|||
|
|
|
|||
|
|
x, y = knick_pt.x(), knick_pt.y()
|
|||
|
|
t = KOORDINATEN_TOLERANZ_M
|
|||
|
|
suchbox = QgsRectangle(x - t, y - t, x + t, y + t)
|
|||
|
|
kandidaten = pta_index.intersects(suchbox)
|
|||
|
|
|
|||
|
|
gefunden = False
|
|||
|
|
for fid in kandidaten:
|
|||
|
|
pta_geom = geom_map.get(fid)
|
|||
|
|
if pta_geom is None:
|
|||
|
|
continue
|
|||
|
|
pta_pt = pta_geom.asPoint()
|
|||
|
|
dist = ((pta_pt.x() - x) ** 2 + (pta_pt.y() - y) ** 2) ** 0.5
|
|||
|
|
if dist <= KOORDINATEN_TOLERANZ_M:
|
|||
|
|
gefunden = True
|
|||
|
|
matched_pta_ids.add(fid)
|
|||
|
|
break
|
|||
|
|
|
|||
|
|
feat = QgsFeature()
|
|||
|
|
try:
|
|||
|
|
from qgis.core import QgsPointXY # type: ignore[import]
|
|||
|
|
feat.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(x, y)))
|
|||
|
|
except Exception:
|
|||
|
|
continue
|
|||
|
|
feat.setAttributes([WERT_IDENTISCH if gefunden else WERT_KEIN_PTA])
|
|||
|
|
feats_to_add.append(feat)
|
|||
|
|
|
|||
|
|
if gefunden:
|
|||
|
|
identisch_count += 1
|
|||
|
|
else:
|
|||
|
|
kein_pta_count += 1
|
|||
|
|
|
|||
|
|
if _canceled():
|
|||
|
|
return None, 0, 0, 0
|
|||
|
|
|
|||
|
|
# ------------------------------------------------------------------
|
|||
|
|
# Schritt n+2: Fehlende Knickpunkte (orange) ermitteln
|
|||
|
|
# ------------------------------------------------------------------
|
|||
|
|
_schritt("Knickpunktprüfung: Fehlende Knickpunkte ermitteln …", n + 2)
|
|||
|
|
|
|||
|
|
fehlender_knick_count = 0
|
|||
|
|
|
|||
|
|
# BROR-Umring ermitteln und puffern
|
|||
|
|
try:
|
|||
|
|
bror_feats = [
|
|||
|
|
f for f in bror_layer.getFeatures()
|
|||
|
|
if f.geometry() and not f.geometry().isEmpty()
|
|||
|
|
]
|
|||
|
|
bror_union = QgsGeometry.unaryUnion([f.geometry() for f in bror_feats])
|
|||
|
|
bror_boundary = bror_union.convertToType(1) if bror_union else None
|
|||
|
|
bror_buffer_geom = (
|
|||
|
|
bror_boundary.buffer(BOUNDARY_PUFFER_M, 8) if bror_boundary else None
|
|||
|
|
)
|
|||
|
|
except Exception:
|
|||
|
|
bror_buffer_geom = None
|
|||
|
|
|
|||
|
|
if bror_buffer_geom is not None and flst_layer is not None:
|
|||
|
|
flst_vertex_set = _baue_flst_vertex_set(flst_layer, bror_buffer_geom)
|
|||
|
|
|
|||
|
|
for feat in punktort_layer.getFeatures():
|
|||
|
|
if _canceled():
|
|||
|
|
break
|
|||
|
|
if feat.id() in matched_pta_ids:
|
|||
|
|
continue
|
|||
|
|
geom = feat.geometry()
|
|||
|
|
if geom is None or geom.isEmpty():
|
|||
|
|
continue
|
|||
|
|
try:
|
|||
|
|
if not geom.within(bror_buffer_geom):
|
|||
|
|
continue
|
|||
|
|
pta_pt = geom.asPoint()
|
|||
|
|
key = (round(pta_pt.x(), _VERTEX_ROUND), round(pta_pt.y(), _VERTEX_ROUND))
|
|||
|
|
if key in flst_vertex_set:
|
|||
|
|
orange_feat = QgsFeature()
|
|||
|
|
orange_feat.setGeometry(geom)
|
|||
|
|
orange_feat.setAttributes([WERT_FEHLENDER_KNICK])
|
|||
|
|
feats_to_add.append(orange_feat)
|
|||
|
|
fehlender_knick_count += 1
|
|||
|
|
except Exception:
|
|||
|
|
continue
|
|||
|
|
|
|||
|
|
if _canceled():
|
|||
|
|
return None, 0, 0, 0
|
|||
|
|
|
|||
|
|
# ------------------------------------------------------------------
|
|||
|
|
# Schritt n+3: Ergebnislayer fertigstellen
|
|||
|
|
# ------------------------------------------------------------------
|
|||
|
|
_schritt("Knickpunktprüfung: Ergebnislayer erstellen …", n + 3)
|
|||
|
|
|
|||
|
|
pr.addFeatures(feats_to_add)
|
|||
|
|
ergebnis_layer.updateExtents()
|
|||
|
|
_setze_kategorien_symbologie(ergebnis_layer)
|
|||
|
|
|
|||
|
|
return ergebnis_layer, identisch_count, kein_pta_count, fehlender_knick_count
|