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>
199 lines
11 KiB
Markdown
199 lines
11 KiB
Markdown
# 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):
|
|
|
|
```bat
|
|
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.
|