feat: HW Planung - Symbole erzeugen, Nummerierung, Ausgabeziel-Dialog

- Symbole erzeugen (HW_SYMBOLE, Einzelbefehle HW_SYM_*): Bauteile nach
  cfg/io_regeln.json (reduzierte Kopie aus kabellaengen), Symbole aus
  cfg/hw_symbole.json katalog-identisch nachgebaut (lib/hw_symbole.py),
  REALE_POSITION mit x auf dem Bauteil, Paare uebereinander, Ausweichen
  in y ohne Ueberlappung
- Symbole nummerieren (HW_NUMMERIEREN): lib/create_numbers.py samt
  error_collector.py und cfg/enumerate.cfg aus kabellaengen uebernommen
- Ausgabeziel per Dialog dcl/hw_ausgabe.dcl: aktuelle Zeichnung,
  bestehende Datei ergaenzen oder neue Datei
- Materialfluss mit XDATA SSG_HW_MF, ergaenzt vorhandene Datei
- Doku doc/hw_planung.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Michael StanglandClaude Opus 5.5 committed 2026-11-03 16:39:37 +01:00
1 parent d2729140ff
commit 8abb6b3c65
20 files changed
+4176 -183

No files matched your search

+55 -5
View File
@@ -9,7 +9,9 @@ Aufruf:
Gestartet vom Befehl HW_MATERIALFLUSS (Lisp/HwPlanung.lsp, Menue HW Planung ->
Materialfluss erzeugen) direkt nach EXPORTCSV; die Ausgabe heisst wie die
Zeichnung mit Anhang "_HW.dxf". Alles wird flach in die XY-Ebene (Z = 0)
gezeichnet - es geht um den Grundriss des Materialflusses.
gezeichnet - es geht um den Grundriss des Materialflusses. Gibt es die Datei
schon (z.B. mit den Symbolen aus hw_symbole.py), wird nur der Inhalt der
HW_*-Layer ersetzt, alles andere bleibt.
Was gezeichnet wird:
* Kreisel/Eckrad: geschlossene Polylinie als Rechteck um die Laufbahn
@@ -200,10 +202,45 @@ def _xy(punkt):
return (punkt[0], punkt[1]) if punkt else None
def zeichnen(elemente, ausgabe, layer):
doc = ezdxf.new("R2018", setup=True)
doc.header["$INSUNITS"] = 4 # mm
# Markierung aller erzeugten Materialfluss-Objekte - daran erkennt LISP sie,
# wenn die Ausgabe in die AKTUELLE Zeichnung geht (HwPlanung.lsp,
# hw-alte-ausgabe), und ein Folgelauf, was er ersetzen darf.
XDATA_APP = "SSG_HW_MF"
def hw_dokument_oeffnen(pfad, einheitenlos=False):
"""Vorhandene Ausgabe-DXF oeffnen oder neu anlegen (R2018, mm).
Materialfluss (dieses Skript) und Symbole (hw_symbole.py) schreiben in
DIESELBE Datei und ersetzen dort nur ihren eigenen Anteil - was der
Anwender ergaenzt hat (Renamer-Rahmen, Polylinien), bleibt erhalten.
einheitenlos: $INSUNITS = 0 - fuer die Zwischendatei, die LISP als Block
in die aktuelle Zeichnung einfuegt; mit Einheit wuerde BricsCAD sie beim
Einfuegen in eine Zeichnung mit anderer Einheit skalieren.
"""
if os.path.isfile(pfad):
doc = ezdxf.readfile(pfad)
else:
doc = ezdxf.new("R2018", setup=True)
doc.header["$INSUNITS"] = 4 # mm
if einheitenlos:
doc.header["$INSUNITS"] = 0
return doc
def _ist_materialfluss(e, eigene_layer):
return e.has_xdata(XDATA_APP) or e.dxf.layer in eigene_layer
def zeichnen(elemente, ausgabe, layer, einheitenlos=False):
doc = hw_dokument_oeffnen(ausgabe, einheitenlos)
msp = doc.modelspace()
# Materialfluss des vorigen Laufs entfernen (markiert oder - aeltere
# Dateien ohne Markierung - auf den HW-Layern)
eigene = {name for name, _farbe in layer.values()}
for e in [e for e in msp if _ist_materialfluss(e, eigene)]:
msp.delete_entity(e)
vorher = {e.dxf.handle for e in msp}
for name, farbe in layer.values():
if name not in doc.layers:
doc.layers.add(name, color=farbe)
@@ -267,6 +304,12 @@ def zeichnen(elemente, ausgabe, layer):
msp.add_line(k1, k2, dxfattribs=ly("hw_entladung"))
zaehler["entladung"] += 1
if XDATA_APP not in doc.appids:
doc.appids.new(XDATA_APP)
for e in msp:
if e.dxf.handle not in vorher:
e.set_xdata(XDATA_APP, [(1000, "materialfluss")])
doc.saveas(ausgabe)
return zaehler, warnungen
@@ -277,6 +320,8 @@ def main(argv=None):
ap.add_argument("ausgabe")
ap.add_argument("--layer-cfg", default=None,
help="Pfad zu layer.cfg (Vorgabe: $DXFM_CFG/layer.cfg)")
ap.add_argument("--einheitenlos", action="store_true",
help="$INSUNITS = 0 (Zwischendatei fuer die aktuelle Zeichnung)")
args = ap.parse_args(argv)
cfg = args.layer_cfg
@@ -284,7 +329,12 @@ def main(argv=None):
cfg = os.path.join(os.environ["DXFM_CFG"], "layer.cfg")
elemente = load_elements(args.csv)
zaehler, warnungen = zeichnen(elemente, args.ausgabe, layer_cfg_lesen(cfg))
try:
zaehler, warnungen = zeichnen(elemente, args.ausgabe, layer_cfg_lesen(cfg),
args.einheitenlos)
except PermissionError:
print(f"FEHLER: {args.ausgabe} ist gesperrt (in BricsCAD geoeffnet?) - bitte schliessen.")
return 1
print(f"HW-Materialfluss geschrieben: {args.ausgabe}")
print(" " + ", ".join(f"{k}: {v}" for k, v in zaehler.items()))
for w in warnungen: