Files
dxfmakros/doc/hw_planung.md
T
Michael StanglandClaude Opus 5.5 4100cbfb97 refactor: create_numbers ohne Kopie von error_collector
Fehler/Warnungen als zwei einfache Listen (neue_meldungen,
meldungen_als_dict) statt der aus kabellaengen kopierten
ErrorCollector-Klasse; lib/error_collector.py entfernt. Format der
Fehlerdatei unveraendert, an sechs Testzeichnungen gegen das Original
verglichen (identische Nummern und Fehlerdateien).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 17:00:42 +01:00

11 KiB

HW-Planung: Materialfluss, Symbole, Nummerierung

Menue SSG_LIB -> HW Planung. Aus dem mechanischen Layout (Ursprungszeichnung) entstehen Materialfluss und E-Geraete-Symbole - je nach Wahl in der aktuellen Zeichnung oder in einer eigenen Planungsdatei (Vorgabe <Zeichnung>_HW.dxf in DXFM_RESULTS). Die Ursprungsdatei auf der Platte wird nie veraendert.

Ausgabeziel (Dialog vor dem Erzeugen)

Vor "Materialfluss erzeugen" und "Symbole erzeugen" (auch vor den Einzelbefehlen HW_SYM_*) fragt der Dialog dcl/hw_ausgabe.dcl, wohin:

Wahl Ergebnis
Aktuelle Zeichnung Materialfluss bzw. Symbole kommen in die offene Zeichnung, auf eigene Layer. Die fruehere Ausgabe desselben Befehls (erkannt an XDATA SSG_HW_MF bzw. SSG_HW_SYM je Geraeteart) wird ersetzt. Technisch: Python schreibt eine Zwischendatei <Zeichnung>_HW_tmp.dxf ohne Einheit, LISP fuegt sie bei 0,0 ein und loest den Block auf. Symbolbloecke, die es in der Zeichnung schon gibt, behalten ihre vorhandene Definition.
Bestehende Datei ergaenzen Datei ueber "Auswaehlen..." waehlen; der Befehl ersetzt dort nur seinen eigenen Anteil. So landen Materialfluss und Symbole nacheinander in derselben Datei.
Neue Datei Name eingeben (ohne Endung, Ordner DXFM_RESULTS). Gibt es die Datei schon, bleibt der Dialog mit einem Hinweis offen.

Die letzte Wahl wird fuer die Sitzung gemerkt. Die Datei muss beim Schreiben in BricsCAD geschlossen sein. "Symbole nummerieren" arbeitet in einer geoeffneten DXF-Zeichnung - bei Ausgabe in die aktuelle Zeichnung muss diese also eine DXF sein.

Ablauf

Schritt Menue / Befehl Wo ausfuehren Ergebnis
1 Materialfluss erzeugen (HW_MATERIALFLUSS) Ursprungszeichnung Polylinien des Materialflusses im gewaehlten Ziel
2 Symbole erzeugen (HW_SYMBOLE) Ursprungszeichnung E-Geraete-Symbole mit ID-Vorlage (z.B. MB1@@@) im gewaehlten Ziel
3 - Zieldatei oeffnen Renamer-Bereiche ziehen (Rahmen oder Polylinie, siehe unten)
4 Symbole nummerieren (HW_NUMMERIEREN) Zieldatei (DXF) @ in den Symbolen durch laufende Nummern ersetzt

Schritt 1 und 2 duerfen in beliebiger Reihenfolge und beliebig oft laufen: jeder ersetzt in der _HW.dxf nur seinen eigenen Anteil (Materialfluss = alles auf den HW_*-Layern, Symbole = Bloecke mit XDATA SSG_HW_SYM der jeweiligen Geraeteart). Was der Anwender selbst gezeichnet hat - Renamer-Bereiche, Polylinien, Notizen - bleibt stehen. Dafuer muss die _HW.dxf waehrend Schritt 1/2 in BricsCAD geschlossen sein (sonst ist sie gesperrt; das Skript meldet das).

1. Materialfluss (lib/hw_materialfluss.py)

HW_MATERIALFLUSS ruft EXPORTCSV auf und zeichnet aus der CSV flach (Z = 0):

Element Darstellung Layer
Kreisel/Eckrad geschlossenes Rechteck um die Laufbahn, Punktfolge in Drehrichtung, Pfeile HW_Kreisel, HW_Richtung
Strecke / Gefaellestrecke Polylinie AS -> Separatoren -> ES (Spalte TrackIds), Endpfeil HW_Materialfluss, HW_Richtung
Weiche kleiner Kreis am Beruehrpunkt zweier Kreisel HW_Weiche
BTMT Beladung grosser Kreis auf K1, kleiner Kreis auf K2, Linie HW_Beladung
BTMT Entladung kleiner Kreis auf K1, grosser Kreis auf K2, Linie HW_Entladung

Layernamen/-farben: cfg/layer.cfg, Abschnitt [hw_planung].

2. Symbole (Lisp/HwPlanung.lsp + lib/hw_symbole.py)

Regelwerk cfg/io_regeln.json:

  • bauteile: Mechanik-Bloecke (Separator_SP*, AS_Element*, AN8_*, SP8_*, Vario_Motorstation*, ...) und die Rollen, die an jedem davon sitzen. Gefunden werden sie auch, wenn sie in VF_n/GF_n/KREISEL_n verschachtelt sind.

  • rollen: je Rolle Geraete-Praefix (MB, BG, MA, FC, GF, BX) und Symbol (Blockname); block_nach_name waehlt z.B. fuer eine rechte Vario-Motorstation den rechten Motor.

  • io_vorlage: die ID beim Erzeugen ist <Praefix><io_vorlage>, Vorgabe 1@@@ -> MB1@@@. Die Platzhalter-ID des Katalogblocks in VERW/BEZEICHNUNG (z.B. Motor MA0) wird ebenfalls durch die Vorlage ersetzt. Symboldefinitionen cfg/hw_symbole.json - es gibt keine Symbol-Bibliothek als Referenzdokument, hw_symbole.py baut die Bloecke bei jedem Lauf neu daraus:

  • vorlagen: gemeinsames Aussehen, derzeit io_750 (750 x 270, Sensoren, Ventile, Motoren, Motorschutz) und geraet_800 (800 x 350, Encoder, Scanner, mit Schraffur): Rahmen und je Attribut Lage, Texthoehe, Sichtbarkeit, Farbe, Layer, Ausrichtung, Textstil, Breitenfaktor, Vorgabewert.

  • symbole: je Blockname Vorlage, Layer, Farbe, versatz (Lage des Rahmens zum Einfuegepunkt - Eingaenge und Motoren haengen im Katalog nach unten, [0, -270]), attribute (Abweichungen von der Vorlage je Tag), ohne (Attribute, die das Symbol nicht hat) und die Attributwerte (IO mit Platzhalter-ID wie MB0, VERW, BEZEICHNUNG, KENNZEICHNUNG, ARTINR, BESCHR, SPS).

  • Die Symbole tragen dieselben Blocknamen wie die ILS-Katalogsymbole in kabellaengen/doc/Symbole/ILS-Symbole.dxf und sind ihnen exakt nachgebaut (Einfuegepunkt, Rahmen, Schraffur, Lage/Hoehe/Stil/Farbe aller Attribute, Vorgabewerte), damit beim Mischen beider Fassungen in einer Zeichnung keine still abweichende Definition gilt. tests/test_hw_symbole.py (test_symbole_gleichen_dem_katalog) prueft das gegen den Katalog, sofern kabellaengen daneben liegt (oder ILS_SYMBOLE_KATALOG gesetzt ist). Aendert sich ein Katalogsymbol, schlaegt der Test fehl - dann hier nachziehen.

  • Jeder Lauf baut die Blockdefinitionen in der _HW.dxf neu auf, Katalogfassungen gleichen Namens werden dort also ueberschrieben.

LISP sucht die Bauteile in der Ursprungszeichnung und schreibt je Rolle den Zielpunkt des Bauteils nach DXFM_RESULTS/<Zeichnung>_hw_symbole.json: Separator-Sensor, AS/ES-Element, Entladung, AN8/SP8-Zentrum (Kreisel-Motor bzw. Spannstation), Vario-Motor-/Umlenkstation, Scanner - jeweils deren Einfuegepunkt, flach auf Z = 0. hw_symbole.py rechnet daraus die Lage und setzt die Symbole in die _HW.dxf.

Lage der Symbole

  • Die Marke REALE_POSITION (das kleine x am rechten Rahmenrand) liegt mit ihrem x genau auf dem Zielpunkt, der Kasten daneben (links davon).
  • Mehrere Symbole eines Bauteils stehen luekenlos uebereinander, in der Reihenfolge von benoetigt (erstes oben, z.B. Ventil ueber Sensor am Separator, Motor ueber Motorschutz), als Gruppe in y um das Ziel zentriert. Ein einzelnes Symbol hat seine Marke damit genau auf dem Ziel.
  • Ohne Ueberlappung: jede Gruppe wird gegen die 2D-Bounding-Boxen der schon gesetzten Rahmen geprueft (Mindestabstand platzierung.abstand). Beruehrt sie eine, wird sie nur in y verschoben (+-schritt, +-2*schritt, ... bis max_verschiebung) - x bleibt auf dem Ziel. Findet sich keine freie Lage, bleibt sie unverschoben und das Skript meldet die Anzahl.
  • Die Lage wird immer aus dem ganzen Plan berechnet; ein Einzelbefehl wie HW_SYM_VENTILE setzt die Ventile also genau dorthin, wo sie auch mit HW_SYMBOLE laegen.
  • Gegen die Materialfluss-Polylinien und andere Geometrie wird nicht geprueft, nur Symbol gegen Symbol.

Mubea: 70 von 83 Bauteilgruppen liegen genau auf ihrem Ziel, 13 weichen in y aus (meist 50-600 mm, Scanner bis 1,7 m).

Einzelbefehle (nicht im Menue, zum schrittweisen Erzeugen und Pruefen; jeder ersetzt nur seine Geraeteart): HW_SYM_VENTILE (MB), HW_SYM_SENSOREN (BG), HW_SYM_MOTOREN (MA), HW_SYM_MOTORSCHUTZ (FC), HW_SYM_ENCODER (GF), HW_SYM_SCANNER (BX); HW_SYM_LOESCHEN entfernt alle erzeugten Symbole aus der _HW.dxf.

3. Renamer-Bereiche

Ein Renamer-Bereich ist ein Block auf einem der Layer aus cfg/enumerate.cfg (ILS_RENAMER, Omniflo_RENAMER), der eine Polylinie enthaelt und Attribute traegt - direkt oder zweistufig (aeusserer Block mit Polylinie + innerer Attribut-Block, wie die ILS_Renamer-*-Bloecke in kabellaengen/doc/Symbole/ILS-Symbole.dxf):

Attribut Bedeutung
NAME bzw. NAME1..NAME3 Nummernmuster, z.B. BG-1@@@; die Anzahl @ bestimmt die Stellen und muss zur io_vorlage passen
LAYER_NAME bzw. LAYER_NAME1..3 Layer der Symbole, die mitgezaehlt werden (z.B. ILS_Eingang, ILS_Ausgang)
DIRECTION Reihenfolge, siehe unten
KENNZEICHNUNG Zuordnung zum Unterverteiler, z.B. =A01+UC0100

DIRECTION:

  • Rechteck (geschlossene Polylinie mit 4 Ecken): LEFT_RIGHT, RIGHT_LEFT, TOP_BOTTOM, BOTTOM_TOP und die Kombinationen TOP_BOTTOM/LEFT_RIGHT, LEFT_RIGHT/TOP_BOTTOM usw. (erste Angabe = Hauptsortierung). Mitgezaehlt werden die Symbole innerhalb des Rechtecks.
  • POLYLINE_PATH: Nummerierung entlang der Polylinie in Punktfolge. Mitgezaehlt werden die Symbole hoechstens polyline_max_distance (Vorgabe 500 mm, cfg/enumerate.cfg) von der Linie entfernt. Die Polylinie darf kein Rechteck sein: offen braucht sie mindestens 5 Punkte (genau 4 offene Punkte gelten als Rechteck), eine 2-Punkt-Linie wird nicht erkannt.

Bereiche mit identischen Attributen (NAME*, LAYER_NAME*, DIRECTION, KENNZEICHNUNG) bilden eine Gruppe und werden fortlaufend gemeinsam nummeriert. Alle Symbole einer Gruppe teilen sich einen Zaehler, egal auf welchem Layer (z.B. BG 1001, BG 1002, MB 1003 in Reihenfolge entlang der Linie).

4. Nummerieren (lib/create_numbers.py)

HW_NUMMERIEREN in der geoeffneten _HW.dxf:

  1. speichert die Zeichnung (QSAVE; sie muss eine DXF sein),
  2. ruft create_numbers.py --dryrun --info ... --errorfile ... auf,
  3. traegt die Nummern in die offene Zeichnung ein (Zuordnung ueber Wert und Einfuegepunkt jedes Attributs mit @).

Ergebnisdateien neben der Zeichnung: <Name>_nummern.json (alle Umbenennungen) und

  • nur bei Problemen - <Name>_nummern_fehler.json. Gemeldet werden u.a.: Symbol mit @ ausserhalb jedes Bereichs, Symbol in mehreren Bereichen einer Gruppe, ueberlappende Rechteck-Bereiche, Bereich ohne passende Symbole, DIRECTION passt nicht zur Geometrie, Symbol im Bereich, aber auf einem nicht genannten Layer (Warnung).

Direktaufruf (z.B. fuer eine DXF ausserhalb von BricsCAD):

python lib\create_numbers.py --filename Anlage_HW.dxf [--config cfg\enumerate.cfg]
       [--info info.json] [--errorfile fehler.json] [--dryrun | --overwrite] [--show_symbol_frames]

Ohne --dryrun/--overwrite entsteht <Name>_numbered.dxf.

Die Nummer wird oktal gebildet (oct(counter), so gewollt): das 8. Symbol einer Gruppe bekommt ...010.

Herkunft

create_numbers.py, cfg/enumerate.cfg und der Test tests/test_create_numbers.py sind am 2026-11-03 aus dem Kabeltool-Repo kabellaengen hierher umgezogen (dort entfernt). Es gibt nur diesen einen Codestand: die benoetigten Helfer aus kabellaengen/lib/utils.py stehen direkt in create_numbers.py, die Fehlersammlung error_collector.py ist durch zwei einfache Listen ersetzt (gleiches Format der Fehlerdatei; gegen das Original an sechs Testzeichnungen verglichen: identische Nummern und Fehlerdateien). Bewusst doppelt bleibt nur die Konfiguration cfg/io_regeln.json (gekuerzt) - beide Repos werden von verschiedenen Abteilungen gepflegt. Die Testszenen Nummerierung1/2, BGMG, POT (Erzeugung per kabellaengen/lib/create_example.py) bleiben in kabellaengen; der Modus --all-examples ist darum hier entfallen.