validate_anlage, stabiler TRO-Schluessel, Verbindungen aus BricsCAD, Zeichnung aus der Anlagen-JSON

- validate_anlage.py (+ bin-Wrapper): Pruefung vor der SCL fuer beide Wege
  (Struktur, Zuordnungen, Aktualitaet der JSON, Korrekturen ohne Ziel);
  scl_skeleton ruft sie auf (Warnung, --strict bricht ab)
- DerivedTro.key: stabiler Schluessel (ID der ID-Datei); hw_overrides.ini,
  <csv>_jam_names.ini und tro_overrides.ini greifen ueber ID oder Schluessel,
  eine Umbenennung in TRO_EDIT laesst sie bestehen; JAM_AREA traegt KEY
- --read-tros liest die CONNECTION_ARROW-Bloecke mit -> [<csv>.edit_connections];
  tro_flow.apply_connection_edits wendet sie nach link_tros an
- tro_annotate --anlage zeichnet Marker/Verbindungen aus der Anlagen-JSON
- INI-Korrekturen auch mit BOM lesbar (utf-8-sig)
- Ablauf CSV/DXF+TIA -> Anlagen-JSON -> (BricsCAD) -> SCL in doc/Python_Scripts.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-27 14:32:10 +01:00
parent 6c8c235287
commit 1ac17b95e2
13 changed files with 1100 additions and 48 deletions
+49 -2
View File
@@ -217,7 +217,7 @@ from tro_catalog import (
get_tro,
mermaid_classdefs,
)
from tro_overrides import PartRef, TroEdit, load_overrides
from tro_overrides import ConnectionEdit, PartRef, TroEdit, load_overrides
# ---------------------------------------------------------------------------
# Konstanten
@@ -2428,6 +2428,47 @@ def apply_edits(tros: list[DerivedTro], edits: list[TroEdit], elements: list[Ele
return tros
def apply_connection_edits(analysis: Analysis, changes: list[ConnectionEdit]) -> None:
"""Im Plan geaenderte Verbindungen (tro_overrides.ini, edit_connections).
Laeuft nach link_tros: '-' nimmt eine abgeleitete Kante weg, '+' fuegt eine
hinzu (Art aus dem Eintrag, sonst transfer). Die Enden sind stabile
Schluessel; ueber Analysis.renamed werden sie zur aktuellen ID. Danach
werden Vorgaenger/Nachfolger neu gesetzt - die Staubereiche folgen daraus.
"""
tros = analysis.tros + analysis.boundaries
id_of = {analysis.edit_key(t.tro_id): t.tro_id for t in tros}
id_of.update({t.tro_id: t.tro_id for t in tros})
edges = set(analysis.edges)
for change in changes:
src, dst = id_of.get(change.src), id_of.get(change.dst)
if src is None or dst is None:
fehlt = change.src if src is None else change.dst
analysis.findings.append(f"Handkorrektur Verbindung {change.render()}: {fehlt} "
f"gibt es nicht - ignoriert")
continue
if change.add:
if (src, dst) not in edges:
edges.add((src, dst))
analysis.findings.append(f"Handkorrektur Verbindung: {src} -> {dst} von Hand "
f"hinzugefuegt")
analysis.edge_kinds[(src, dst)] = change.kind or "transfer"
elif change.kind:
analysis.edge_kinds[(src, dst)] = change.kind
elif (src, dst) in edges:
edges.discard((src, dst))
analysis.edge_kinds.pop((src, dst), None)
analysis.findings.append(f"Handkorrektur Verbindung: {src} -> {dst} von Hand "
f"entfernt")
else:
analysis.findings.append(f"Handkorrektur Verbindung {change.render()}: wird "
f"nicht abgeleitet - nichts zu entfernen")
analysis.edges = sorted(edges)
for tro in tros:
tro.successors = sorted(d for s, d in analysis.edges if s == tro.tro_id)
tro.predecessors = sorted(s for s, d in analysis.edges if d == tro.tro_id)
def analyse_tros(
graph: Graph,
elements: list[Element],
@@ -2435,6 +2476,7 @@ def analyse_tros(
sepliste_counts: dict[str, int] | None = None,
tro_ids: TroIds | None = None,
edits: list[TroEdit] | None = None,
connection_edits: list[ConnectionEdit] | None = None,
) -> Analysis:
"""TROs ermitteln, verknuepfen, verorten und gegen die Typdefinition pruefen.
@@ -2452,6 +2494,8 @@ def analyse_tros(
nummerieren.
edits: Handkorrekturen aus BricsCAD (tro_overrides.load_overrides
(...).edits), angewandt direkt nach derive_tros (apply_edits).
connection_edits: im Plan geaenderte Verbindungen
(load_overrides(...).connection_edits), angewandt nach link_tros.
Rueckgabe:
Analysis mit tros, boundaries, edges/edge_kinds, unknown_types
@@ -2476,6 +2520,8 @@ def analyse_tros(
# Kreisel-Bahn wird ueber ihre Koordinate bestimmt.
locate_tros(linked, elements, graph)
analysis.edges, analysis.edge_kinds = link_tros(graph, linked, elements)
if connection_edits:
apply_connection_edits(analysis, connection_edits)
analysis.unknown_types = sorted(
{tro.type_name for tro in analysis.tros if tro.definition() is None})
@@ -3598,7 +3644,8 @@ def main(argv: list[str] | None = None) -> int:
warnings.append(f"--renumber: {len(overrides.edits)} Handkorrektur(en) in "
f"{overrides.source} haengen an den alten IDs - pruefen")
analysis = analyse_tros(graph, elements, sepliste_counts=sepliste_counts,
tro_ids=tro_ids, edits=overrides.edits)
tro_ids=tro_ids, edits=overrides.edits,
connection_edits=overrides.connection_edits)
if not analysis.tros:
print(f"FEHLER: {csv_file} enthaelt keine Separatoren - keine TROs "
f"ableitbar.", file=sys.stderr)