tro_annotate: selten gebrauchte Optionen entfernt
- --max-residual: feste Grenze DEFAULT_MAX_RESIDUAL (600 mm), Meldung verweist auf --offset - --layer-prefix: Layer immer mit Praefix TRO_ - --use-overrides: cfg/tro_overrides.ini wird nie gelesen, Marker passen damit immer zum TRO-Fluss - damit toter Code entfernt: draw_open_points, Layer TRO_OPENPOINT, Berichtszeilen Offene Punkte/Typkorrekturen (Daten kamen nur aus der INI) - --emit-lisp bleibt (einziger Weg, tro_types.lsp fuer TRO_INSERT/TRO_EDIT nach einem neuen Katalogtyp neu zu schreiben) - doc/Python_Scripts.md nachgezogen Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
e2f1a558a2
commit
a5fab7e2dc
+12
-11
@@ -337,19 +337,21 @@ overridden.
|
||||
| `--legend` | — | off | Draw a legend of the color groups. |
|
||||
| `--marker-size` | `MM` (float) | `300.0` | Marker radius in mm. |
|
||||
| `--text-height` | `MM` (float) | `220.0` | Text height in mm. |
|
||||
| `--layer-prefix` | `P` | `TRO_` | Prefix for the layers this tool creates. |
|
||||
| `--offset` | `DX,DY` | — | Set the CSV↔DXF offset by hand instead of deriving/loading it. |
|
||||
| `--offset` | `DX,DY` | — | Set the CSV↔DXF offset by hand instead of deriving/loading it. For a drawing built with dxfmakros (CSV exported from the same drawing) this is `0,0`. |
|
||||
| `--re-register` | — | off | Re-derive the coordinate offset even if a verified one is already cached in `%SKEL_CFG%`. |
|
||||
| `--max-residual` | `MM` (float) | `600.0` | Largest residual error of the coordinate registration that is still accepted; above it the run fails (exit 4). |
|
||||
| `--check` | — | off | Dry run: only analyze and report, write no output file. |
|
||||
| `--emit-lisp` | — | off | Regenerate `cad/tro_types.lsp` (the type list for the `TRO_INSERT`/`TRO_EDIT` dialogs) from `tro_catalog.py` and exit — no `--dxf` needed. Written under `%DXFM_LISP%` if set (next to the `dxfmakros` SSG_LIB modules that provide the dialogs), otherwise under `<SPS_SKEL>/cad`. |
|
||||
|
||||
Layers always carry the prefix `TRO_`. `cfg/tro_overrides.ini` is never read,
|
||||
so the markers always match `tro_flow.py` (which reads it only with
|
||||
`--use-overrides`).
|
||||
|
||||
**Output** (in `%SKEL_RESULTS%`, unless `--check`): `<name>_annotated.dxf`,
|
||||
`<name>_registration.json` (the coordinate transform used, with its proof).
|
||||
|
||||
**Exit codes:** `0` ok · `1` input/CLI error · `4` coordinate registration
|
||||
could not be proven (or exceeds `--max-residual`) — resolve with `--offset` or
|
||||
by raising `--max-residual`.
|
||||
could not be proven (or its residual error exceeds 600 mm) — resolve with
|
||||
`--offset`.
|
||||
|
||||
## 5a. `tro_extract.py` — read the TROs back out of the drawing into JSON
|
||||
|
||||
@@ -534,13 +536,12 @@ Three kinds of entry, deliberately different in weight:
|
||||
flow node is primary, the rest stay attached so the linking still sees both
|
||||
sides of a transition. Like splits, this renumbers.
|
||||
- **`openpoint`** — a spot reported in a review that is **not** turned into a
|
||||
TRO. The structure stays untouched; the point is only marked, in the doc
|
||||
(section 6) and in the annotated drawing on layer `TRO_OPENPOINT` as a red
|
||||
crossed circle with plain-text label. This keeps "derived" and "asserted"
|
||||
distinguishable until the spot has been checked in BricsCAD.
|
||||
TRO. The structure stays untouched; the point is only marked in the doc
|
||||
(section 6). This keeps "derived" and "asserted" distinguishable until the
|
||||
spot has been checked in BricsCAD.
|
||||
|
||||
Consumers: `tro_flow.py` (type corrections + doc section 6), `tro_annotate.py`
|
||||
(corrected marker types + open-point markers), `material_flow.py` (writes the
|
||||
Consumers: `tro_flow.py` (only with `--use-overrides`: type corrections + doc
|
||||
section 6), `material_flow.py` (writes the
|
||||
`[<plant>.manual]` section into `connect.ini`). Unknown TRO IDs and types are
|
||||
not applied silently — they are reported as warnings in the console output and
|
||||
in doc section 6.3, which catches the common trap: **TRO IDs are running
|
||||
|
||||
+9
-73
@@ -109,7 +109,6 @@ from tro_flow import (
|
||||
_station_positionen,
|
||||
analyse_tros,
|
||||
)
|
||||
from tro_overrides import Overrides, load_overrides
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Konstanten
|
||||
@@ -319,15 +318,13 @@ def build_layers(doc, prefix: str) -> dict[str, str]:
|
||||
doc.layers.add(name, dxfattribs={
|
||||
"true_color": ezdxf.rgb2int(hex_to_rgb(style.stroke)),
|
||||
})
|
||||
# openpoint: im Review gemeldete Stellen, die noch KEIN TRO sind. Kraeftiges
|
||||
# Rot, damit sie sich von den abgeleiteten Markern klar abheben.
|
||||
# Kantenfarben wie im TRO-Fluss-SVG (tro_flow.render_dot): Uebergabe blau,
|
||||
# Weiche orange, Materialeingang gruen, Materialausgang rot.
|
||||
for key, colour in (("label", "#404040"), ("flow", "#2f5597"),
|
||||
("weiche", "#cc8800"),
|
||||
("eingang", STATION_FARBE[BOUNDARY_ENTRY]),
|
||||
("ausgang", STATION_FARBE[BOUNDARY_EXIT]),
|
||||
("legend", "#808080"), ("openpoint", "#e00000")):
|
||||
("legend", "#808080")):
|
||||
name = f"{prefix}{key.upper()}"
|
||||
names[key] = name
|
||||
if name not in doc.layers:
|
||||
@@ -530,47 +527,6 @@ def place_markers(
|
||||
return placed, internal
|
||||
|
||||
|
||||
def draw_open_points(
|
||||
msp, analysis: Analysis, transform: Transform, layers: dict[str, str],
|
||||
marker: float, text: float,
|
||||
) -> int:
|
||||
"""Offene Punkte aus cfg/tro_overrides.ini als Fragezeichen-Marker setzen.
|
||||
|
||||
Das sind im Review gemeldete Stellen, die noch kein TRO sind. Sie werden
|
||||
bewusst NICHT als TRO-Symbol gezeichnet, sondern als durchgestrichener
|
||||
Kreis mit Klartext daneben - damit in der Zeichnung sofort erkennbar ist,
|
||||
dass hier eine Entscheidung aussteht und nichts abgeleitet wurde.
|
||||
"""
|
||||
drawn = 0
|
||||
radius = marker * 1.35
|
||||
for point in analysis.overrides.open_points:
|
||||
x, y = transform.to_dxf(point.x, point.y)
|
||||
ring = msp.add_circle((x, y), radius,
|
||||
dxfattribs={"layer": layers["openpoint"]})
|
||||
tag(ring, f"OFFEN:{point.name}")
|
||||
diag = radius * 0.7071
|
||||
for (x1, y1), (x2, y2) in (((-diag, -diag), (diag, diag)),
|
||||
((-diag, diag), (diag, -diag))):
|
||||
line = msp.add_line((x + x1, y + y1), (x + x2, y + y2),
|
||||
dxfattribs={"layer": layers["openpoint"]})
|
||||
tag(line, f"OFFEN:{point.name}")
|
||||
|
||||
lines = [f"OFFEN - noch kein TRO: {point.name}"]
|
||||
if point.expect:
|
||||
lines.append(f"erwartet: {point.expect}")
|
||||
if point.belongs_to:
|
||||
lines.append(f"heute Teil von: {point.belongs_to}")
|
||||
lines.append(f"Anlage x/y: {point.describe_position()}")
|
||||
label = msp.add_mtext("\\P".join(lines), dxfattribs={
|
||||
"layer": layers["openpoint"],
|
||||
"char_height": text,
|
||||
})
|
||||
label.set_location((x + radius * 1.3, y + radius))
|
||||
tag(label, f"OFFEN:{point.name}")
|
||||
drawn += 1
|
||||
return drawn
|
||||
|
||||
|
||||
def place_stations(
|
||||
msp, analysis: Analysis, placed: dict[str, tuple[float, float]],
|
||||
layers: dict[str, str], text: float,
|
||||
@@ -826,13 +782,6 @@ def report(
|
||||
if counts.get("first_id"):
|
||||
print(f"Interne IDs ab = {format_internal_id(counts['first_id'])} "
|
||||
f"(ID-Raum von SSG_LIB, siehe IDSCHECK)")
|
||||
print(f"Offene Punkte = {counts['openpoints']} (Layer TRO_OPENPOINT, "
|
||||
f"noch kein TRO)")
|
||||
if analysis.overrides.applied:
|
||||
print(f"Typkorrekturen = {len(analysis.overrides.applied)} aus "
|
||||
f"{analysis.overrides.source}")
|
||||
for entry in analysis.overrides.applied:
|
||||
print(f" * {entry}")
|
||||
print(f"Entfernte Objekte= {counts['removed']} (aus frueherem Lauf)")
|
||||
print(f"Layer = {counts['layers']}, Bloecke: {counts['blocks']}")
|
||||
print(f"DXF = {out_file if out_file else '- (--check)'}")
|
||||
@@ -887,26 +836,16 @@ def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
|
||||
metavar="MM", help="Markerradius in mm. Standard: %(default)s")
|
||||
parser.add_argument("--text-height", type=float, default=DEFAULT_TEXT,
|
||||
metavar="MM", help="Texthoehe in mm. Standard: %(default)s")
|
||||
parser.add_argument("--layer-prefix", default=LAYER_PREFIX, metavar="P",
|
||||
help="Praefix der erzeugten Layer. Standard: %(default)s")
|
||||
parser.add_argument("--offset", metavar="DX,DY",
|
||||
help="Lagebezug von Hand setzen statt ermitteln.")
|
||||
parser.add_argument("--re-register", action="store_true",
|
||||
help="Lagebezug neu ermitteln, auch wenn in %%SKEL_CFG%% "
|
||||
"einer abgelegt ist.")
|
||||
parser.add_argument("--max-residual", type=float, default=DEFAULT_MAX_RESIDUAL,
|
||||
metavar="MM",
|
||||
help="Groesster zugelassener Restfehler des Lagebezugs. "
|
||||
"Standard: %(default)s")
|
||||
parser.add_argument("--check", action="store_true",
|
||||
help="Nur pruefen und berichten, keine Datei schreiben.")
|
||||
parser.add_argument("--emit-lisp", action="store_true",
|
||||
help="cad/tro_types.lsp aus dem Typkatalog neu schreiben "
|
||||
"(Auswahlliste des Dialogs TROEDIT) und beenden.")
|
||||
parser.add_argument("--use-overrides", action="store_true",
|
||||
help="Manuelle Korrekturen aus cfg/tro_overrides.ini "
|
||||
"anwenden. Standard ist AUS - wie bei tro_flow, "
|
||||
"damit Marker und Flussdiagramm zusammenpassen.")
|
||||
return parser.parse_args(argv)
|
||||
|
||||
|
||||
@@ -959,9 +898,9 @@ def main(argv: list[str] | None = None) -> int:
|
||||
print(f"FEHLER: {csv_file} nicht lesbar: {exc}", file=sys.stderr)
|
||||
return 1
|
||||
graph = build_graph(elements, csv_file.name, read_warnings)
|
||||
overrides = (load_overrides(csv_file.name, cfg_dir) if args.use_overrides
|
||||
else Overrides())
|
||||
analysis = analyse_tros(graph, elements, overrides)
|
||||
# Ohne cfg/tro_overrides.ini - wie tro_flow, damit Marker und
|
||||
# Flussdiagramm zusammenpassen.
|
||||
analysis = analyse_tros(graph, elements)
|
||||
if not analysis.tros:
|
||||
print(f"FEHLER: keine TROs aus {csv_file} ableitbar.", file=sys.stderr)
|
||||
return 1
|
||||
@@ -981,16 +920,15 @@ def main(argv: list[str] | None = None) -> int:
|
||||
except RegistrationError as exc:
|
||||
print(f"FEHLER: Lagebezug nicht bestimmbar: {exc}", file=sys.stderr)
|
||||
return 4
|
||||
if transform.residual_max > args.max_residual:
|
||||
if transform.residual_max > DEFAULT_MAX_RESIDUAL:
|
||||
print(f"FEHLER: Restfehler des Lagebezugs {transform.residual_max:.1f} mm "
|
||||
f"ueber der Grenze von {args.max_residual:.1f} mm.", file=sys.stderr)
|
||||
f"ueber der Grenze von {DEFAULT_MAX_RESIDUAL:.1f} mm.", file=sys.stderr)
|
||||
print(f" {transform.describe()}", file=sys.stderr)
|
||||
print(" Mit --offset von Hand setzen oder --max-residual anheben.",
|
||||
file=sys.stderr)
|
||||
print(" Mit --offset von Hand setzen.", file=sys.stderr)
|
||||
return 4
|
||||
|
||||
counts = {"marker": 0, "flow": 0, "removed": 0, "layers": 0, "blocks": 0,
|
||||
"openpoints": 0, "first_id": 0}
|
||||
"first_id": 0}
|
||||
|
||||
if args.check:
|
||||
counts["marker"] = sum(1 for t in analysis.tros if t.position)
|
||||
@@ -999,7 +937,7 @@ def main(argv: list[str] | None = None) -> int:
|
||||
|
||||
ensure_appid(doc)
|
||||
counts["removed"] = remove_previous(msp)
|
||||
layers = build_layers(doc, args.layer_prefix)
|
||||
layers = build_layers(doc, LAYER_PREFIX)
|
||||
counts["layers"] = len({v for v in layers.values()})
|
||||
|
||||
# Interne IDs erst NACH remove_previous suchen: die Marker des letzten Laufs
|
||||
@@ -1013,8 +951,6 @@ def main(argv: list[str] | None = None) -> int:
|
||||
counts["blocks"] = sum(1 for b in doc.blocks if b.name.startswith(BLOCK_PREFIX))
|
||||
counts["first_id"] = next_id
|
||||
|
||||
counts["openpoints"] = draw_open_points(msp, analysis, transform, layers,
|
||||
args.marker_size, args.text_height)
|
||||
|
||||
if args.flow:
|
||||
# Stationen nur mit --flow: sie bestehen aus ihrem Zu-/Ablaufpfeil
|
||||
|
||||
Reference in New Issue
Block a user