Files
sps_skel/tests/test_tro_annotate_jams.py
T
s.ayadi 6c8c235287 tro_annotate --read-tros: TRO-Handkorrekturen aus BricsCAD, Staubereiche vor dem TRO
- Marker tragen KEY (ID der ID-Datei) und SLOTS (Bauteil je Slot), die
  Zeichnung die Bauteiltabelle SPS_SKEL_PARTS (XRECORD) fuer "Im Plan
  waehlen" im Dialog TRO_EDIT (dxfmakros)
- --read-tros schreibt geaenderte, neue und geloeschte Marker als
  Abschnitte edit/edit_add nach cfg/tro_overrides.ini; tro_flow.apply_edits
  wendet nur diese Arten an (Bauteile mit Lage, exportfest)
- --emit-lisp schreibt dazu *TRO-SLOTS* und *TRO-SLOT-KINDS*
- model: Lagerlinien zaehlen je TRO (Katalog nur Vorgabe), Mubea-Speicher
  jetzt 20 Linien (Golden-Datei)
- Staubereich als stehendes graues Rechteck direkt vor seinem TRO-Marker
  (jam_abstand statt jam_versatz); Marker 150 mm, Text 120 mm

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 14:35:04 +01:00

147 lines
5.8 KiB
Python

# -*- coding: utf-8 -*-
"""Tests fuer die Staubereiche in tro_annotate.py (--anlage, --read-jams).
Kleine Anlage: ein Kreisel mit zwei TROs hintereinander (K0042). Die Bloecke
JAM_AREA tragen Name, Foerderer, Nummer und den stabilen Schluessel TRO +
Eingang; --read-jams uebernimmt im Dialog JAM_EDIT geaenderte Nummern nach
<csv>_jam_names.ini, und scl_context setzt sie in die SCL ein.
"""
import ezdxf
import tro_annotate
from dxf_registration import Transform
from model import (
AnlageDocument,
Analysis,
ConveyorBinding,
DerivedTro,
LayoutPart,
TroDocument,
)
from scl_context import build_context, load_jam_overrides
IDENT = Transform(dx=0.0, dy=0.0)
def _tro(tro_id, sep, x, vor, nach):
return DerivedTro(tro_id=tro_id, type_name="1Sep", label=tro_id, hosts=["0004-L"],
separators=[sep], scanners=[], reason="Test",
predecessors=vor, successors=nach, position=(x, 0.0, 0.0))
def anlage() -> AnlageDocument:
tros = [_tro("TRO01", "0101", 0.0, ["SYS1"], ["TRO02"]),
_tro("TRO02", "0102", 5000.0, ["TRO01"], ["SYS2"])]
parts = [
LayoutPart(layout_id="0004", kind="Kreisel", name="Kreisel4",
position=(2500.0, 0.0, 0.0), bbox=(8000.0, 800.0, 1.0)),
LayoutPart(layout_id="0101", kind="Separator", name="S1", position=(0.0, 0.0, 0.0)),
LayoutPart(layout_id="0102", kind="Separator", name="S2", position=(5000.0, 0.0, 0.0)),
]
layout = TroDocument.from_analysis(Analysis(tros=tros), source="x.csv", parts=parts)
return AnlageDocument(layout=layout, conveyors=[
ConveyorBinding(eplan_name="K0042", layout_id="0004", motor="MA0042")])
def _zeichnen(overrides=None):
doc = ezdxf.new()
tro_annotate.ensure_appid(doc)
layers = tro_annotate.build_layers(doc, tro_annotate.LAYER_PREFIX)
warnings: list[str] = []
n = tro_annotate.place_jams(doc.modelspace(), doc, anlage(), overrides or {}, IDENT,
layers, 200.0, warnings)
return doc, n, warnings
def _jams(doc) -> dict[str, dict]:
out = {}
for ref in doc.modelspace().query(f'INSERT[name=="{tro_annotate.JAM_BLOCK}"]'):
a = {t.dxf.tag: t.dxf.text for t in ref.attribs}
a["pos"] = (round(ref.dxf.insert.x), round(ref.dxf.insert.y))
out[a["TRO"]] = a
return out
def test_staubereiche_als_block_mit_name_und_schluessel():
doc, n, warnings = _zeichnen()
assert n == 2 and warnings == []
jams = _jams(doc)
assert {k: v["NAME"] for k, v in jams.items()} == {"TRO01": "Jam0042_1",
"TRO02": "Jam0042_2"}
t2 = jams["TRO02"]
assert (t2["CONVEYOR"], t2["NUMBER"], t2["ENTRY"], t2["AREA"], t2["AUTO"]) == (
"0042", "2", "1", "J0102", "0042_2")
# direkt vor dem Marker, Richtung Vorgaenger TRO01 (gegen den Fluss):
# Markerradius + Luft + halbe Rechteckbreite
abstand = (tro_annotate.DEFAULT_MARKER + tro_annotate.JAM_ABSTAND
+ 200.0 * tro_annotate.JAM_HALB_BREITE)
assert t2["pos"] == (5000 - round(abstand), 0)
# TRO01 hat nur eine Station als Vorgaenger: gegen die Richtung zum Nachfolger
assert jams["TRO01"]["pos"] == (-round(abstand), 0)
def test_staubereich_ist_stehendes_graues_rechteck():
doc, _, _ = _zeichnen()
blk = doc.blocks.get(tro_annotate.JAM_BLOCK)
rahmen = next(iter(blk.query("LWPOLYLINE")))
xs = [p[0] for p in rahmen.get_points()]
ys = [p[1] for p in rahmen.get_points()]
assert max(ys) - min(ys) > 3 * (max(xs) - min(xs))
assert rahmen.dxf.color == 8 and len(blk.query("HATCH")) == 1
name = next(a for a in blk.query("ATTDEF") if a.dxf.tag == "NAME")
assert name.dxf.rotation == 90.0
def test_korrektur_wird_gezeichnet():
doc, _, _ = _zeichnen({"TRO02.1": ("0042", 7)})
t2 = _jams(doc)["TRO02"]
assert (t2["NAME"], t2["NUMBER"], t2["AUTO"]) == ("Jam0042_7", "7", "0042_2")
def test_geaenderte_nummer_zurueck_in_die_korrekturdatei(tmp_path):
doc, _, _ = _zeichnen()
# wie der Dialog JAM_EDIT: NUMBER und NAME neu
for ref in doc.modelspace().query(f'INSERT[name=="{tro_annotate.JAM_BLOCK}"]'):
a = {t.dxf.tag: t for t in ref.attribs}
if a["TRO"].dxf.text == "TRO02":
a["NUMBER"].dxf.text = "7"
a["NAME"].dxf.text = "Jam0042_7"
dxf = tmp_path / "x_annotated.dxf"
doc.saveas(dxf)
ini = tmp_path / "x_jam_names.ini"
overrides, meldungen = tro_annotate.read_jams(dxf, ini)
assert overrides == {"TRO02.1": ("0042", 7)}
assert load_jam_overrides(ini) == overrides
assert any("TRO02.1: Jam0042_7" in m for m in meldungen)
# in der SCL: Ein- und Ausgang tragen die korrigierte Nummer
a = anlage()
ctx = build_context(a.layout, "x_anlage.json", anlage=a, jam_overrides=overrides)
tro1, tro2 = ctx.tros
assert tro2.jam_entries[0].db.value == '"DB_JamArea0042".stJam0042_7'
assert tro1.jam_exits[0].db.value == '"DB_JamArea0042".stJam0042_7'
# zurueck auf die abgeleitete Nummer -> Eintrag (und Datei) weg
for ref in doc.modelspace().query(f'INSERT[name=="{tro_annotate.JAM_BLOCK}"]'):
a2 = {t.dxf.tag: t for t in ref.attribs}
if a2["TRO"].dxf.text == "TRO02":
a2["NUMBER"].dxf.text = "2"
doc.saveas(dxf)
overrides, _ = tro_annotate.read_jams(dxf, ini)
assert overrides == {} and not ini.exists()
def test_ungueltige_nummer_wird_nicht_uebernommen(tmp_path):
doc, _, _ = _zeichnen()
for ref in doc.modelspace().query(f'INSERT[name=="{tro_annotate.JAM_BLOCK}"]'):
a = {t.dxf.tag: t for t in ref.attribs}
if a["TRO"].dxf.text == "TRO01":
a["CONVEYOR"].dxf.text = "42"
dxf = tmp_path / "x_annotated.dxf"
doc.saveas(dxf)
overrides, meldungen = tro_annotate.read_jams(dxf, tmp_path / "x_jam_names.ini")
assert overrides == {}
assert any("TRO01.1" in m and "ungueltig" in m for m in meldungen)