Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7a13171714 | |||
| 041d292681 | |||
| 1f2ebe5c86 | |||
| 9f78ff7f0a | |||
| cc301b318e | |||
| fd58ef612f |
@@ -177,6 +177,8 @@ cython_debug/
|
|||||||
# Benutzerdefiniert
|
# Benutzerdefiniert
|
||||||
/work
|
/work
|
||||||
/log
|
/log
|
||||||
|
/logs
|
||||||
|
/results
|
||||||
/tests/output/
|
/tests/output/
|
||||||
|
|
||||||
# BricsCAD kompilierte Menuedateien
|
# BricsCAD kompilierte Menuedateien
|
||||||
|
|||||||
@@ -81,14 +81,14 @@ Abhaengigkeiten: `ezdxf`, Standard-Library. Benoetigen Umgebungsvariablen (`DXFM
|
|||||||
| `omniflo_utils.py` | Gemeinsame Hilfsfunktionen fuer Omniflo-Skripte: `ROW_GROUPS` (Reihen-Gruppierung), `SWITCH_FILTERS` (Schalter-Filter), `build_row_layout`, `import_element_as_block`, `draw_cross`, `load_omniflo_data` |
|
| `omniflo_utils.py` | Gemeinsame Hilfsfunktionen fuer Omniflo-Skripte: `ROW_GROUPS` (Reihen-Gruppierung), `SWITCH_FILTERS` (Schalter-Filter), `build_row_layout`, `import_element_as_block`, `draw_cross`, `load_omniflo_data` |
|
||||||
| `set_einfuegepkt.py` | Setzt `$INSBASE` (Einfuegepunkt) in Omniflo-DXF-Dateien. Schalter je Typ: `--boegen`, `--weichen45`, `--weichen90`, `--weichenkoerper`, `--weichen-parallel`, `--delta`, `--dreifachweiche`, `--sternweiche`, `--show-omniflo` |
|
| `set_einfuegepkt.py` | Setzt `$INSBASE` (Einfuegepunkt) in Omniflo-DXF-Dateien. Schalter je Typ: `--boegen`, `--weichen45`, `--weichen90`, `--weichenkoerper`, `--weichen-parallel`, `--delta`, `--dreifachweiche`, `--sternweiche`, `--show-omniflo` |
|
||||||
| `set_koords.py` | Setzt Koordinatensystem-Bloecke (K1-K4) in Omniflo-DXF-Dateien. Schalter: `--k1set` bis `--k4set`, `--set-all`, `--force`, `--show-omniflo`, `--test`, `--number` |
|
| `set_koords.py` | Setzt Koordinatensystem-Bloecke (K1-K4) in Omniflo-DXF-Dateien. Schalter: `--k1set` bis `--k4set`, `--set-all`, `--force`, `--show-omniflo`, `--test`, `--number` |
|
||||||
| `attradd.py` | Fuegt ATTDEF-Attribute zu Omniflo-DXF-Dateien hinzu. Liest Konfiguration aus `cfg/attradd.cfg`. Schalter: `--number`, `--dry-run` |
|
| `set_attributs.py` | Fuegt ATTDEF-Attribute zu Omniflo-DXF-Dateien hinzu. Liest Konfiguration aus `cfg/attradd.cfg`. Schalter: `--number`, `--dry-run` |
|
||||||
| `export_sivas.py` | Erzeugt Sivas-Export-CSV mit Summierungszeilen (ILS Automation, Omniflo Sum). Aufruf: `python export_sivas.py <export_raw.json> <data_dir> <output.csv>` |
|
| `export_sivas.py` | Erzeugt Sivas-Export-CSV mit Summierungszeilen (ILS Automation, Omniflo Sum). Aufruf: `python export_sivas.py <export_raw.json> <data_dir> <output.csv>` |
|
||||||
| `export_csv.py` | Erzeugt einfache Item-Liste als CSV (ohne Summierung). Aufruf: `python export_csv.py <export_raw.json> <data_dir> <output.csv>` |
|
| `export_csv.py` | Erzeugt einfache Item-Liste als CSV (ohne Summierung). Aufruf: `python export_csv.py <export_raw.json> <data_dir> <output.csv>` |
|
||||||
| `testpycall.py` | Testskript fuer LISP-Python-Aufruf via CALLPYTHON |
|
| `testpycall.py` | Testskript fuer LISP-Python-Aufruf via CALLPYTHON |
|
||||||
|
|
||||||
### Typische Verarbeitungskette (Omniflo-DXF)
|
### Typische Verarbeitungskette (Omniflo-DXF)
|
||||||
|
|
||||||
1. `attradd.py` - Attribute zu Quell-DXFs hinzufuegen
|
1. `set_attributs.py` - Attribute zu Quell-DXFs hinzufuegen
|
||||||
2. `set_einfuegepkt.py` - Einfuegepunkte berechnen und setzen
|
2. `set_einfuegepkt.py` - Einfuegepunkte berechnen und setzen
|
||||||
3. `set_koords.py` - Koordinatensysteme (K1-K4) setzen
|
3. `set_koords.py` - Koordinatensysteme (K1-K4) setzen
|
||||||
4. `export_sivas.py` / `export_csv.py` - Export aus Zeichnung
|
4. `export_sivas.py` / `export_csv.py` - Export aus Zeichnung
|
||||||
|
|||||||
@@ -98,7 +98,7 @@
|
|||||||
(setq startpunkt-fuer-einfuegen (getpoint "\nStartpunkt fuer AUS_Element waehlen: "))
|
(setq startpunkt-fuer-einfuegen (getpoint "\nStartpunkt fuer AUS_Element waehlen: "))
|
||||||
(if (null startpunkt-fuer-einfuegen) (setq startpunkt-fuer-einfuegen '(0 0 0)))
|
(if (null startpunkt-fuer-einfuegen) (setq startpunkt-fuer-einfuegen '(0 0 0)))
|
||||||
(setq deltaL (getreal "\nAbstand ΔL (mm): "))
|
(setq deltaL (getreal "\nAbstand ΔL (mm): "))
|
||||||
(if (or (null deltaL) (<= deltaL 0)) (setq deltaL 5000.0))
|
(if (or (null deltaL) (<= deltaL 0)) (setq deltaL (ssg-cfg-or "gefaelle" "default_delta_l" 5000.0)))
|
||||||
)
|
)
|
||||||
;; --- Modus 2: 3D-Linie ---
|
;; --- Modus 2: 3D-Linie ---
|
||||||
(progn
|
(progn
|
||||||
@@ -134,7 +134,7 @@
|
|||||||
|
|
||||||
;; --- Winkelabfrage ---
|
;; --- Winkelabfrage ---
|
||||||
(setq winkel (getreal "\n\nGefaellewinkel (°) [3]: "))
|
(setq winkel (getreal "\n\nGefaellewinkel (°) [3]: "))
|
||||||
(if (or (null winkel) (<= winkel 0)) (setq winkel 3.0))
|
(if (or (null winkel) (<= winkel 0)) (setq winkel (ssg-cfg-or "gefaelle" "default_winkel" 3.0)))
|
||||||
(setq winkel (float winkel))
|
(setq winkel (float winkel))
|
||||||
(setq rad (* winkel (/ pi 180.0)))
|
(setq rad (* winkel (/ pi 180.0)))
|
||||||
(princ (strcat "\n>>> Gewaehlter Winkel: " (rtos winkel 2 1) grad-zeichen))
|
(princ (strcat "\n>>> Gewaehlter Winkel: " (rtos winkel 2 1) grad-zeichen))
|
||||||
@@ -153,7 +153,7 @@
|
|||||||
;; --- Laengenberechnung ---
|
;; --- Laengenberechnung ---
|
||||||
;; Horizontalbilanz: deltaL = aus_dx + L_stau*cos(rad) + 300*cos(rad) + ein_dx
|
;; Horizontalbilanz: deltaL = aus_dx + L_stau*cos(rad) + 300*cos(rad) + ein_dx
|
||||||
;; L_stau (Weglaenge) = (deltaL - aus_dx - ein_dx - 300*cos(rad)) / cos(rad)
|
;; L_stau (Weglaenge) = (deltaL - aus_dx - ein_dx - 300*cos(rad)) / cos(rad)
|
||||||
(setq sep-x (* 300.0 (cos rad)))
|
(setq sep-x (* (ssg-cfg-or "gefaelle" "separator_breite" 300.0) (cos rad)))
|
||||||
(setq L_stau (/ (- deltaL aus-dx ein-dx sep-x) (cos rad)))
|
(setq L_stau (/ (- deltaL aus-dx ein-dx sep-x) (cos rad)))
|
||||||
|
|
||||||
;; --- Validierung ---
|
;; --- Validierung ---
|
||||||
|
|||||||
+16
-16
@@ -30,11 +30,11 @@
|
|||||||
(setq *block-path* block-pfad)
|
(setq *block-path* block-pfad)
|
||||||
(princ (strcat "\nBlock-Pfad aktiv: " block-pfad))
|
(princ (strcat "\nBlock-Pfad aktiv: " block-pfad))
|
||||||
|
|
||||||
;; Kreisel-Geometrie-Konstanten
|
;; Kreisel-Geometrie-Konstanten (aus Config oder Fallback)
|
||||||
(setq *kreisel-durchmesser* 800.0) ;; Kreisdurchmesser AN8/SP8
|
(setq *kreisel-durchmesser* (ssg-cfg-or "kreisel" "durchmesser" 800.0))
|
||||||
(setq *kreisel-pin-abstand* 100.0) ;; Einrueckung PIN-Linie vom Kreisrand
|
(setq *kreisel-pin-abstand* (ssg-cfg-or "kreisel" "pin_abstand" 100.0))
|
||||||
(setq *kreisel-default-laenge* 2300.0) ;; Standard-Tangentenlaenge
|
(setq *kreisel-default-laenge* (ssg-cfg-or "kreisel" "default_laenge" 2300.0))
|
||||||
(setq *kreisel-default-hoehe* 2000.0) ;; Standard-Höhe (Z-Koordinate)
|
(setq *kreisel-default-hoehe* (ssg-cfg-or "kreisel" "default_hoehe" 2000.0))
|
||||||
|
|
||||||
;; Attribut-Definitionen: ((TAG DEFAULT) ...)
|
;; Attribut-Definitionen: ((TAG DEFAULT) ...)
|
||||||
(setq *kreisel-attrib-defs*
|
(setq *kreisel-attrib-defs*
|
||||||
@@ -51,7 +51,7 @@
|
|||||||
)
|
)
|
||||||
|
|
||||||
;; Eckrad-Einstellungen
|
;; Eckrad-Einstellungen
|
||||||
(setq *eckrad-default-hoehe* 2000.0) ;; Standard-Höhe (Z-Koordinate)
|
(setq *eckrad-default-hoehe* (ssg-cfg-or "eckrad" "default_hoehe" 2000.0))
|
||||||
|
|
||||||
;; Eckrad Attribut-Definitionen: ((TAG DEFAULT) ...)
|
;; Eckrad Attribut-Definitionen: ((TAG DEFAULT) ...)
|
||||||
(setq *eckrad-attrib-defs*
|
(setq *eckrad-attrib-defs*
|
||||||
@@ -67,9 +67,9 @@
|
|||||||
|
|
||||||
;; Beschriftungs-Einstellungen (NUR EINMAL definieren!)
|
;; Beschriftungs-Einstellungen (NUR EINMAL definieren!)
|
||||||
(setq *kreisel-beschriftung-layer* "S_KRS_BESCHR")
|
(setq *kreisel-beschriftung-layer* "S_KRS_BESCHR")
|
||||||
(setq *kreisel-beschriftung-hoehe* 100.0) ;; Texthöhe in mm
|
(setq *kreisel-beschriftung-hoehe* (ssg-cfg-or "kreisel" "label_hoehe" 100.0))
|
||||||
(setq *kreisel-beschriftung-farbe* 7) ;; 7 = weiß
|
(setq *kreisel-beschriftung-farbe* (ssg-cfg-or "kreisel" "label_farbe" 7))
|
||||||
(setq *kreisel-beschriftung-abstand-oben* 0.0) ;; Abstand über Kreisel-Mitte
|
(setq *kreisel-beschriftung-abstand-oben* (ssg-cfg-or "kreisel" "label_abstand_oben" 0.0))
|
||||||
(setq *kreisel-beschriftung-schriftart* "Arial") ;; Schriftart
|
(setq *kreisel-beschriftung-schriftart* "Arial") ;; Schriftart
|
||||||
|
|
||||||
|
|
||||||
@@ -230,7 +230,7 @@
|
|||||||
(setq cross (abs (- (* (car d1) (cadr d2)) (* (cadr d1) (car d2))))
|
(setq cross (abs (- (* (car d1) (cadr d2)) (* (cadr d1) (car d2))))
|
||||||
len1 (sqrt (+ (* (car d1) (car d1)) (* (cadr d1) (cadr d1))))
|
len1 (sqrt (+ (* (car d1) (car d1)) (* (cadr d1) (cadr d1))))
|
||||||
len2 (sqrt (+ (* (car d2) (car d2)) (* (cadr d2) (cadr d2)))))
|
len2 (sqrt (+ (* (car d2) (car d2)) (* (cadr d2) (cadr d2)))))
|
||||||
(< (/ cross (* len1 len2)) 0.01)
|
(< (/ cross (* len1 len2)) (ssg-cfg-or "kreisel" "toleranz_kollinear" 0.01))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -373,8 +373,8 @@
|
|||||||
;; Tangenten auf Layer S_LP
|
;; Tangenten auf Layer S_LP
|
||||||
(ssg-make-layer "S_LP" "7" T)
|
(ssg-make-layer "S_LP" "7" T)
|
||||||
(if is-pin
|
(if is-pin
|
||||||
(setvar "CECOLOR" "5")
|
(setvar "CECOLOR" (itoa (ssg-cfg-or "kreisel" "color_linie_1" 5)))
|
||||||
(setvar "CECOLOR" "1")
|
(setvar "CECOLOR" (itoa (ssg-cfg-or "kreisel" "color_linie_2" 1)))
|
||||||
)
|
)
|
||||||
|
|
||||||
;; Obere Tangente
|
;; Obere Tangente
|
||||||
@@ -385,8 +385,8 @@
|
|||||||
;; PIN-Linien
|
;; PIN-Linien
|
||||||
(if is-pin
|
(if is-pin
|
||||||
(progn
|
(progn
|
||||||
(ssg-make-layer "pinbereich" "3" T)
|
(ssg-make-layer "pinbereich" (itoa (ssg-cfg-or "kreisel" "color_pin" 3)) T)
|
||||||
(setvar "CECOLOR" "3")
|
(setvar "CECOLOR" (itoa (ssg-cfg-or "kreisel" "color_pin" 3)))
|
||||||
|
|
||||||
;; Obere PIN-Linie
|
;; Obere PIN-Linie
|
||||||
(command "_.LINE" (list *kreisel-durchmesser* pin-y 0) (list (float abstand) pin-y 0) "")
|
(command "_.LINE" (list *kreisel-durchmesser* pin-y 0) (list (float abstand) pin-y 0) "")
|
||||||
@@ -745,7 +745,7 @@
|
|||||||
(foreach entry *kreisel-ausrichtungen*
|
(foreach entry *kreisel-ausrichtungen*
|
||||||
(setq diff (abs (- (rem (+ rot 360.0) 360.0)
|
(setq diff (abs (- (rem (+ rot 360.0) 360.0)
|
||||||
(rem (+ (cadr entry) 360.0) 360.0))))
|
(rem (+ (cadr entry) 360.0) 360.0))))
|
||||||
(if (< diff 1.0) (setq idx i))
|
(if (< diff (ssg-cfg-or "kreisel" "toleranz_winkel" 1.0)) (setq idx i))
|
||||||
(setq i (1+ i))
|
(setq i (1+ i))
|
||||||
)
|
)
|
||||||
idx
|
idx
|
||||||
@@ -966,7 +966,7 @@
|
|||||||
dy (- (cadr ptDir) (cadr ptTangent)))
|
dy (- (cadr ptDir) (cadr ptTangent)))
|
||||||
(setq dist (sqrt (+ (* dx dx) (* dy dy))))
|
(setq dist (sqrt (+ (* dx dx) (* dy dy))))
|
||||||
|
|
||||||
(if (<= dist 0.001)
|
(if (<= dist (ssg-cfg-or "kreisel" "toleranz_min_distanz" 0.001))
|
||||||
(progn
|
(progn
|
||||||
(princ "\nFehler: Beruehr- und Richtungspunkt sind identisch!")
|
(princ "\nFehler: Beruehr- und Richtungspunkt sind identisch!")
|
||||||
(dbgreturn nil)
|
(dbgreturn nil)
|
||||||
|
|||||||
+18
-18
@@ -450,8 +450,8 @@
|
|||||||
(if (null *OMNI-BOEGEN*) (omni:load-data))
|
(if (null *OMNI-BOEGEN*) (omni:load-data))
|
||||||
|
|
||||||
;; Defaults
|
;; Defaults
|
||||||
(if (null init-hoehe) (setq init-hoehe "2000"))
|
(if (null init-hoehe) (setq init-hoehe (ssg-cfg-or "omniflo" "default_hoehe" "2000")))
|
||||||
(if (null init-drehung) (setq init-drehung "0"))
|
(if (null init-drehung) (setq init-drehung (ssg-cfg-or "omniflo" "default_drehung" "0")))
|
||||||
|
|
||||||
;; Boegen nach Winkel filtern
|
;; Boegen nach Winkel filtern
|
||||||
(setq boegen-liste (omni:filter *OMNI-BOEGEN* "KurvenWinkel" winkel))
|
(setq boegen-liste (omni:filter *OMNI-BOEGEN* "KurvenWinkel" winkel))
|
||||||
@@ -591,8 +591,8 @@
|
|||||||
srcAttribs attribDefs attribs
|
srcAttribs attribDefs attribs
|
||||||
ok)
|
ok)
|
||||||
|
|
||||||
(setq textHeight 100.0)
|
(setq textHeight (ssg-cfg-or "omniflo" "text_height" 100.0))
|
||||||
(setq textGap 20.0)
|
(setq textGap (ssg-cfg-or "omniflo" "text_gap" 20.0))
|
||||||
|
|
||||||
;; 0. Attribute aus der Quell-.dwg lesen (vor ssg-start, da eigene INSERT/ERASE)
|
;; 0. Attribute aus der Quell-.dwg lesen (vor ssg-start, da eigene INSERT/ERASE)
|
||||||
(setq srcAttribs (ssg-attrib-read-dwg (strcat *block-path* blockname ".dwg")))
|
(setq srcAttribs (ssg-attrib-read-dwg (strcat *block-path* blockname ".dwg")))
|
||||||
@@ -728,15 +728,15 @@
|
|||||||
)
|
)
|
||||||
|
|
||||||
(defun c:OMNI_AP60 ()
|
(defun c:OMNI_AP60 ()
|
||||||
(omni:insert-block "AP60" 7000.0)
|
(omni:insert-block "AP60" (ssg-cfg-or "omniflo" "laengemax_ap60" 7000.0))
|
||||||
(princ)
|
(princ)
|
||||||
)
|
)
|
||||||
(defun c:OMNI_AP110 ()
|
(defun c:OMNI_AP110 ()
|
||||||
(omni:insert-block "AP110" 6000.0)
|
(omni:insert-block "AP110" (ssg-cfg-or "omniflo" "laengemax_ap110" 6000.0))
|
||||||
(princ)
|
(princ)
|
||||||
)
|
)
|
||||||
(defun c:OMNI_APG110 ()
|
(defun c:OMNI_APG110 ()
|
||||||
(omni:insert-block "APG110" 6000.0)
|
(omni:insert-block "APG110" (ssg-cfg-or "omniflo" "laengemax_apg110" 6000.0))
|
||||||
(princ)
|
(princ)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -844,8 +844,8 @@
|
|||||||
(if (null *OMNI-WEICHEN*) (omni:load-data))
|
(if (null *OMNI-WEICHEN*) (omni:load-data))
|
||||||
|
|
||||||
;; Defaults
|
;; Defaults
|
||||||
(if (null init-hoehe) (setq init-hoehe "2000"))
|
(if (null init-hoehe) (setq init-hoehe (ssg-cfg-or "omniflo" "default_hoehe" "2000")))
|
||||||
(if (null init-drehung) (setq init-drehung "0"))
|
(if (null init-drehung) (setq init-drehung (ssg-cfg-or "omniflo" "default_drehung" "0")))
|
||||||
|
|
||||||
;; Weichen nach Winkel filtern (nil = alle Winkel)
|
;; Weichen nach Winkel filtern (nil = alle Winkel)
|
||||||
(if winkel
|
(if winkel
|
||||||
@@ -981,13 +981,13 @@
|
|||||||
;; HOEHE und DREHUNG Attribute setzen
|
;; HOEHE und DREHUNG Attribute setzen
|
||||||
(if (and blockEnt (= (cdr (assoc 0 (entget blockEnt))) "INSERT"))
|
(if (and blockEnt (= (cdr (assoc 0 (entget blockEnt))) "INSERT"))
|
||||||
(ssg-attrib-set-on blockEnt
|
(ssg-attrib-set-on blockEnt
|
||||||
(list (cons "HOEHE" (if hoehe hoehe "2000"))
|
(list (cons "HOEHE" (if hoehe hoehe (ssg-cfg-or "omniflo" "default_hoehe" "2000")))
|
||||||
(cons "DREHUNG" (if drehung drehung "0"))))
|
(cons "DREHUNG" (if drehung drehung (ssg-cfg-or "omniflo" "default_drehung" "0")))))
|
||||||
)
|
)
|
||||||
|
|
||||||
(princ (strcat "\n[OMNI] " sivasnr-str " eingefuegt."
|
(princ (strcat "\n[OMNI] " sivasnr-str " eingefuegt."
|
||||||
" Hoehe=" (if hoehe hoehe "2000")
|
" Hoehe=" (if hoehe hoehe (ssg-cfg-or "omniflo" "default_hoehe" "2000"))
|
||||||
" Drehung=" (if drehung drehung "0")))
|
" Drehung=" (if drehung drehung (ssg-cfg-or "omniflo" "default_drehung" "0"))))
|
||||||
(ssg-end)
|
(ssg-end)
|
||||||
pt
|
pt
|
||||||
)
|
)
|
||||||
@@ -1199,7 +1199,7 @@
|
|||||||
(setq drehung (cdr (assoc "DREHUNG" attribs)))
|
(setq drehung (cdr (assoc "DREHUNG" attribs)))
|
||||||
|
|
||||||
;; Fallbacks
|
;; Fallbacks
|
||||||
(if (null hoehe) (setq hoehe "2000"))
|
(if (null hoehe) (setq hoehe (ssg-cfg-or "omniflo" "default_hoehe" "2000")))
|
||||||
(if (null drehung) (setq drehung (rtos rotation 2 1)))
|
(if (null drehung) (setq drehung (rtos rotation 2 1)))
|
||||||
|
|
||||||
;; 3. Typ bestimmen: Bogen oder Weiche
|
;; 3. Typ bestimmen: Bogen oder Weiche
|
||||||
@@ -1294,13 +1294,13 @@
|
|||||||
;; Attribute setzen
|
;; Attribute setzen
|
||||||
(if (and blockEnt (= (cdr (assoc 0 (entget blockEnt))) "INSERT"))
|
(if (and blockEnt (= (cdr (assoc 0 (entget blockEnt))) "INSERT"))
|
||||||
(ssg-attrib-set-on blockEnt
|
(ssg-attrib-set-on blockEnt
|
||||||
(list (cons "HOEHE" (if new-hoehe new-hoehe "2000"))
|
(list (cons "HOEHE" (if new-hoehe new-hoehe (ssg-cfg-or "omniflo" "default_hoehe" "2000")))
|
||||||
(cons "DREHUNG" (if new-drehung new-drehung "0"))))
|
(cons "DREHUNG" (if new-drehung new-drehung (ssg-cfg-or "omniflo" "default_drehung" "0")))))
|
||||||
)
|
)
|
||||||
|
|
||||||
(princ (strcat "\n[OMNI] Element aktualisiert: " sivasnr-str
|
(princ (strcat "\n[OMNI] Element aktualisiert: " sivasnr-str
|
||||||
" Hoehe=" (if new-hoehe new-hoehe "2000")
|
" Hoehe=" (if new-hoehe new-hoehe (ssg-cfg-or "omniflo" "default_hoehe" "2000"))
|
||||||
" Drehung=" (if new-drehung new-drehung "0")))
|
" Drehung=" (if new-drehung new-drehung (ssg-cfg-or "omniflo" "default_drehung" "0"))))
|
||||||
|
|
||||||
(ssg-end)
|
(ssg-end)
|
||||||
(princ)
|
(princ)
|
||||||
|
|||||||
+24
-13
@@ -35,8 +35,8 @@
|
|||||||
(setq aus-dx nil aus-dy nil aus-dz nil)
|
(setq aus-dx nil aus-dy nil aus-dz nil)
|
||||||
(setq ein-dx nil ein-dy nil ein-dz nil)
|
(setq ein-dx nil ein-dy nil ein-dz nil)
|
||||||
(setq separator-laenge nil umlenk-laenge nil motorstation-laenge nil)
|
(setq separator-laenge nil umlenk-laenge nil motorstation-laenge nil)
|
||||||
(setq staustrecke-basis 1000)
|
(setq staustrecke-basis (ssg-cfg-or "vario" "staustrecke_basis" 1000))
|
||||||
(setq FESTE_HORIZONTAL 1600)
|
(setq FESTE_HORIZONTAL (ssg-cfg-or "vario" "feste_horizontal" 1600))
|
||||||
|
|
||||||
;; Bogen-Tabellen (werden aus Bibliothek befüllt)
|
;; Bogen-Tabellen (werden aus Bibliothek befüllt)
|
||||||
(setq bogen-auf '()) ;; Format: ((winkel dx dy dz) ...)
|
(setq bogen-auf '()) ;; Format: ((winkel dx dy dz) ...)
|
||||||
@@ -400,7 +400,7 @@
|
|||||||
(princ "\n Extrahiere Bogen-Masse...")
|
(princ "\n Extrahiere Bogen-Masse...")
|
||||||
(setq bogen-auf '())
|
(setq bogen-auf '())
|
||||||
(setq bogen-ab '())
|
(setq bogen-ab '())
|
||||||
(setq bogen-winkel '(3 6 9 12 15 18 21 27 33 39 45 51))
|
(setq bogen-winkel (ssg-cfg-or "vario" "bogen_winkel" '(3 6 9 12 15 18 21 27 33 39 45 51)))
|
||||||
|
|
||||||
(foreach w bogen-winkel
|
(foreach w bogen-winkel
|
||||||
;; Aufwaertsbogen
|
;; Aufwaertsbogen
|
||||||
@@ -547,7 +547,7 @@
|
|||||||
(ensure-block-loaded blockname)
|
(ensure-block-loaded blockname)
|
||||||
(princ (strcat "\n Fuege '" blockname "' ein (Laenge=" (rtos laenge 2 2) " mm, Winkel=" (itoa winkel) "°)"))
|
(princ (strcat "\n Fuege '" blockname "' ein (Laenge=" (rtos laenge 2 2) " mm, Winkel=" (itoa winkel) "°)"))
|
||||||
|
|
||||||
(setq scale (/ laenge 1000.0))
|
(setq scale (/ laenge (ssg-cfg-or "vario" "skalierung_basis" 1000.0)))
|
||||||
(setq rad (* winkel (/ pi 180.0)))
|
(setq rad (* winkel (/ pi 180.0)))
|
||||||
|
|
||||||
;; Block am Ursprung einfuegen, damit TransformBy um (0,0,0) rotiert (= Block-Einfuegepunkt)
|
;; Block am Ursprung einfuegen, damit TransformBy um (0,0,0) rotiert (= Block-Einfuegepunkt)
|
||||||
@@ -647,10 +647,11 @@
|
|||||||
(setq abs-dz-AUS (abs aus-dz) abs-dz-EIN (abs ein-dz))
|
(setq abs-dz-AUS (abs aus-dz) abs-dz-EIN (abs ein-dz))
|
||||||
|
|
||||||
;; ALLE in der Bibliothek verfügbaren Winkel
|
;; ALLE in der Bibliothek verfügbaren Winkel
|
||||||
(setq winkel-list '(3 6 9 12 15 18 21 27 33 39 45 51))
|
(setq winkel-list (ssg-cfg-or "vario" "bogen_winkel" '(3 6 9 12 15 18 21 27 33 39 45 51)))
|
||||||
|
|
||||||
(setq ergebnis-liste '())
|
(setq ergebnis-liste '())
|
||||||
(setq cos3 (cos (* 3 (/ pi 180.0))) sin3 (sin (* 3 (/ pi 180.0))))
|
(setq cos3 (cos (* (ssg-cfg-or "vario" "gefaelle_winkel" 3) (/ pi 180.0)))
|
||||||
|
sin3 (sin (* (ssg-cfg-or "vario" "gefaelle_winkel" 3) (/ pi 180.0))))
|
||||||
|
|
||||||
(princ "\n\n=========================================\n BERECHNUNG FÜR ALLE WINKEL\n=========================================")
|
(princ "\n\n=========================================\n BERECHNUNG FÜR ALLE WINKEL\n=========================================")
|
||||||
(princ (strcat "\nΔL = " (rtos deltaL 2 2) " mm\nΔH = " (rtos deltaH 2 2) " mm\nRichtung: " richtung))
|
(princ (strcat "\nΔL = " (rtos deltaL 2 2) " mm\nΔH = " (rtos deltaH 2 2) " mm\nRichtung: " richtung))
|
||||||
@@ -773,18 +774,23 @@
|
|||||||
(if (> L_GF1 0.1)
|
(if (> L_GF1 0.1)
|
||||||
(progn
|
(progn
|
||||||
(princ (strcat "\n\n2/11: Gefaellestrecke (3°, Laenge=" (rtos L_GF1 2 2) " mm)"))
|
(princ (strcat "\n\n2/11: Gefaellestrecke (3°, Laenge=" (rtos L_GF1 2 2) " mm)"))
|
||||||
(setq aktueller-punkt (insert-inclined-scaled-block "Staustrecke_SP_1000_mm" aktueller-punkt L_GF1 3))
|
(setq aktueller-punkt (insert-inclined-scaled-block "Staustrecke_SP_1000_mm" aktueller-punkt L_GF1 (ssg-cfg-or "vario" "gefaelle_winkel" 3)))
|
||||||
)
|
)
|
||||||
(princ "\n\n2/11: (uebersprungen)")
|
(princ "\n\n2/11: (uebersprungen)")
|
||||||
)
|
)
|
||||||
|
|
||||||
;; 3. Separator
|
;; 3. Separator
|
||||||
(princ "\n\n3/11: Separator (300mm, 3° geneigt)")
|
(princ "\n\n3/11: Separator (300mm, 3° geneigt)")
|
||||||
(setq aktueller-punkt (insert-rotated-block-with-ks "Staustrecke_Separator_SP_300_mm" aktueller-punkt 3 300 0))
|
(setq aktueller-punkt (insert-rotated-block-with-ks "Staustrecke_Separator_SP_300_mm" aktueller-punkt
|
||||||
|
(ssg-cfg-or "vario" "gefaelle_winkel" 3)
|
||||||
|
(ssg-cfg-or "vario" "separator_block_dx" 300)
|
||||||
|
(ssg-cfg-or "vario" "separator_block_dz" 0)))
|
||||||
|
|
||||||
;; 4. Umlenkstation – Block bereits 3° vorgeneigt, keine zusaetzliche Rotation
|
;; 4. Umlenkstation – Block bereits 3° vorgeneigt, keine zusaetzliche Rotation
|
||||||
(princ "\n\n4/11: Umlenkstation (500mm, 3° geneigt)")
|
(princ "\n\n4/11: Umlenkstation (500mm, 3° geneigt)")
|
||||||
(setq aktueller-punkt (insert-rotated-block-with-ks "Vario_Umlenkstation_500mm" aktueller-punkt 0 499 -26))
|
(setq aktueller-punkt (insert-rotated-block-with-ks "Vario_Umlenkstation_500mm" aktueller-punkt 0
|
||||||
|
(ssg-cfg-or "vario" "station_block_dx" 499)
|
||||||
|
(ssg-cfg-or "vario" "station_block_dz" -26)))
|
||||||
|
|
||||||
;; 5. 1. Vertikalbogen
|
;; 5. 1. Vertikalbogen
|
||||||
(if (= richtung "Auf")
|
(if (= richtung "Auf")
|
||||||
@@ -799,7 +805,7 @@
|
|||||||
)
|
)
|
||||||
(setq bogen-dx (car bogen-mass) bogen-dz (caddr bogen-mass))
|
(setq bogen-dx (car bogen-mass) bogen-dz (caddr bogen-mass))
|
||||||
(princ (strcat "\n\n5/11: " bogen-name " (3° geneigt)"))
|
(princ (strcat "\n\n5/11: " bogen-name " (3° geneigt)"))
|
||||||
(setq aktueller-punkt (insert-rotated-block-with-ks bogen-name aktueller-punkt 3 bogen-dx bogen-dz))
|
(setq aktueller-punkt (insert-rotated-block-with-ks bogen-name aktueller-punkt (ssg-cfg-or "vario" "gefaelle_winkel" 3) bogen-dx bogen-dz))
|
||||||
|
|
||||||
;; 6. Variable Strecke L_VF
|
;; 6. Variable Strecke L_VF
|
||||||
(if (> L_VF 0.1)
|
(if (> L_VF 0.1)
|
||||||
@@ -835,20 +841,25 @@
|
|||||||
|
|
||||||
;; 8. Motorstation – gleiche Behandlung wie Umlenkstation
|
;; 8. Motorstation – gleiche Behandlung wie Umlenkstation
|
||||||
(princ "\n\n8/11: Motorstation (500mm, 3° geneigt)")
|
(princ "\n\n8/11: Motorstation (500mm, 3° geneigt)")
|
||||||
(setq aktueller-punkt (insert-rotated-block-with-ks "Vario_Motorstation_500mm" aktueller-punkt 0 499 -26))
|
(setq aktueller-punkt (insert-rotated-block-with-ks "Vario_Motorstation_500mm" aktueller-punkt 0
|
||||||
|
(ssg-cfg-or "vario" "station_block_dx" 499)
|
||||||
|
(ssg-cfg-or "vario" "station_block_dz" -26)))
|
||||||
|
|
||||||
;; 9. 2. Gefällestrecke
|
;; 9. 2. Gefällestrecke
|
||||||
(if (> L_GF2 0.1)
|
(if (> L_GF2 0.1)
|
||||||
(progn
|
(progn
|
||||||
(princ (strcat "\n\n9/11: Gefaellestrecke (3°, Laenge=" (rtos L_GF2 2 2) " mm)"))
|
(princ (strcat "\n\n9/11: Gefaellestrecke (3°, Laenge=" (rtos L_GF2 2 2) " mm)"))
|
||||||
(setq aktueller-punkt (insert-inclined-scaled-block "Staustrecke_SP_1000_mm" aktueller-punkt L_GF2 3))
|
(setq aktueller-punkt (insert-inclined-scaled-block "Staustrecke_SP_1000_mm" aktueller-punkt L_GF2 (ssg-cfg-or "vario" "gefaelle_winkel" 3)))
|
||||||
)
|
)
|
||||||
(princ "\n\n9/11: (uebersprungen)")
|
(princ "\n\n9/11: (uebersprungen)")
|
||||||
)
|
)
|
||||||
|
|
||||||
;; 10. Separator 2
|
;; 10. Separator 2
|
||||||
(princ "\n\n10/11: Separator (300mm, 3° geneigt)")
|
(princ "\n\n10/11: Separator (300mm, 3° geneigt)")
|
||||||
(setq aktueller-punkt (insert-rotated-block-with-ks "Staustrecke_Separator_SP_300_mm" aktueller-punkt 3 300 0))
|
(setq aktueller-punkt (insert-rotated-block-with-ks "Staustrecke_Separator_SP_300_mm" aktueller-punkt
|
||||||
|
(ssg-cfg-or "vario" "gefaelle_winkel" 3)
|
||||||
|
(ssg-cfg-or "vario" "separator_block_dx" 300)
|
||||||
|
(ssg-cfg-or "vario" "separator_block_dz" 0)))
|
||||||
|
|
||||||
;; 11. EIN_Element
|
;; 11. EIN_Element
|
||||||
(princ (strcat "\n\n11/11: " es-block " (0°)"))
|
(princ (strcat "\n\n11/11: " es-block " (0°)"))
|
||||||
|
|||||||
+6
-6
@@ -282,7 +282,7 @@
|
|||||||
(setq winkel (or (csv:get-attrib ename "WINKEL") "0"))
|
(setq winkel (or (csv:get-attrib ename "WINKEL") "0"))
|
||||||
(setq radius (or (csv:get-attrib ename "RADIUS") "0"))
|
(setq radius (or (csv:get-attrib ename "RADIUS") "0"))
|
||||||
(setq sivasnr (or (csv:get-attrib ename "ARTINR") ""))
|
(setq sivasnr (or (csv:get-attrib ename "ARTINR") ""))
|
||||||
(setq hoehe (or (csv:get-attrib ename "HOEHE") "2000"))
|
(setq hoehe (or (csv:get-attrib ename "HOEHE") (ssg-cfg-or "omniflo" "default_hoehe" "2000")))
|
||||||
(setq drehung (or (csv:get-attrib ename "DREHUNG") (rtos rotation 2 1)))
|
(setq drehung (or (csv:get-attrib ename "DREHUNG") (rtos rotation 2 1)))
|
||||||
(strcat "{\"Kurvenwinkel\":" winkel
|
(strcat "{\"Kurvenwinkel\":" winkel
|
||||||
",\"Radius\":" radius
|
",\"Radius\":" radius
|
||||||
@@ -298,7 +298,7 @@
|
|||||||
(setq winkel (or (csv:get-attrib ename "WINKEL") "0"))
|
(setq winkel (or (csv:get-attrib ename "WINKEL") "0"))
|
||||||
(setq sivasnr (or (csv:get-attrib ename "ARTINR") ""))
|
(setq sivasnr (or (csv:get-attrib ename "ARTINR") ""))
|
||||||
(setq tef-str (csv:get-attrib ename "SIVASNR_TEF"))
|
(setq tef-str (csv:get-attrib ename "SIVASNR_TEF"))
|
||||||
(setq hoehe (or (csv:get-attrib ename "HOEHE") "2000"))
|
(setq hoehe (or (csv:get-attrib ename "HOEHE") (ssg-cfg-or "omniflo" "default_hoehe" "2000")))
|
||||||
(setq drehung (or (csv:get-attrib ename "DREHUNG") (rtos rotation 2 1)))
|
(setq drehung (or (csv:get-attrib ename "DREHUNG") (rtos rotation 2 1)))
|
||||||
(strcat "{\"Weichentyp\":\"" (csv:json-escape wtyp) "\""
|
(strcat "{\"Weichentyp\":\"" (csv:json-escape wtyp) "\""
|
||||||
",\"Richtung\":\"False\""
|
",\"Richtung\":\"False\""
|
||||||
@@ -314,11 +314,11 @@
|
|||||||
(defun csv:omni-gerade-merkmale (ename rotation / laenge hoehe drehung)
|
(defun csv:omni-gerade-merkmale (ename rotation / laenge hoehe drehung)
|
||||||
(setq laenge (csv:get-attrib ename "LAENGE"))
|
(setq laenge (csv:get-attrib ename "LAENGE"))
|
||||||
(if (null laenge) (setq laenge (csv:get-attrib ename "A")))
|
(if (null laenge) (setq laenge (csv:get-attrib ename "A")))
|
||||||
(if (null laenge) (setq laenge "2000"))
|
(if (null laenge) (setq laenge (ssg-cfg-or "omniflo" "default_gerade_laenge" "2000")))
|
||||||
(setq hoehe (or (csv:get-attrib ename "HOEHE") "2000"))
|
(setq hoehe (or (csv:get-attrib ename "HOEHE") (ssg-cfg-or "omniflo" "default_hoehe" "2000")))
|
||||||
(setq drehung (or (csv:get-attrib ename "DREHUNG") (rtos rotation 2 1)))
|
(setq drehung (or (csv:get-attrib ename "DREHUNG") (rtos rotation 2 1)))
|
||||||
(strcat "{\"Anzahl der Separatoren\":\"0\""
|
(strcat "{\"Anzahl der Separatoren\":\"0\""
|
||||||
",\"L\\u00e4nge in Meter\":\"" (csv:json-escape (rtos (/ (atof laenge) 1000.0) 2 2)) "\""
|
",\"L\\u00e4nge in Meter\":\"" (csv:json-escape (rtos (/ (atof laenge) (ssg-cfg-or "infrastruktur" "mm_pro_meter" 1000.0)) 2 2)) "\""
|
||||||
",\"Winkel\":\"0\""
|
",\"Winkel\":\"0\""
|
||||||
",\"Anzahl der Scanner\":0"
|
",\"Anzahl der Scanner\":0"
|
||||||
",\"H\\u00f6he oben\":\"" (csv:json-escape hoehe) "\""
|
",\"H\\u00f6he oben\":\"" (csv:json-escape hoehe) "\""
|
||||||
@@ -426,7 +426,7 @@
|
|||||||
(if (null laenge-str) (setq laenge-str (csv:get-attrib ename "A")))
|
(if (null laenge-str) (setq laenge-str (csv:get-attrib ename "A")))
|
||||||
(if (and laenge-str (> (strlen laenge-str) 0))
|
(if (and laenge-str (> (strlen laenge-str) 0))
|
||||||
(setq len-ap110 (+ len-ap110 (atof laenge-str)))
|
(setq len-ap110 (+ len-ap110 (atof laenge-str)))
|
||||||
(setq len-ap110 (+ len-ap110 2000.0))
|
(setq len-ap110 (+ len-ap110 (float (atoi (ssg-cfg-or "omniflo" "default_gerade_laenge" "2000")))))
|
||||||
)
|
)
|
||||||
(setq merkmale (csv:omni-gerade-merkmale ename rotation))
|
(setq merkmale (csv:omni-gerade-merkmale ename rotation))
|
||||||
(setq lines (cons
|
(setq lines (cons
|
||||||
|
|||||||
+215
-1
@@ -352,7 +352,7 @@
|
|||||||
(cons 2 (car def))
|
(cons 2 (car def))
|
||||||
'(70 . 1)
|
'(70 . 1)
|
||||||
))
|
))
|
||||||
(setq ypos (- ypos (* text-height 2.0)))
|
(setq ypos (- ypos (* text-height (ssg-cfg-or "infrastruktur" "attdef_y_spacing_factor" 2.0))))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -501,5 +501,219 @@
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
;; ------------------------------------------------------------
|
||||||
|
;; KONFIGURATION AUS JSON LADEN
|
||||||
|
;; Liest data/json/component_defaults.json und stellt Werte
|
||||||
|
;; ueber (ssg-cfg "section" "key") bereit.
|
||||||
|
;; Struktur: {"section": {"key": wert, ...}, ...}
|
||||||
|
;; Ergebnis: *ssg-config* = (("section" ("key" . wert) ...) ...)
|
||||||
|
;; ------------------------------------------------------------
|
||||||
|
|
||||||
|
(setq *ssg-config* nil)
|
||||||
|
|
||||||
|
;; Datei zeilenweise einlesen (wie omni:read-file-lines)
|
||||||
|
(defun ssg-read-file-lines (datei / f zeile ergebnis)
|
||||||
|
(setq f (open datei "r"))
|
||||||
|
(if (null f)
|
||||||
|
nil
|
||||||
|
(progn
|
||||||
|
(setq ergebnis nil)
|
||||||
|
(while (setq zeile (read-line f))
|
||||||
|
(setq ergebnis (cons zeile ergebnis))
|
||||||
|
)
|
||||||
|
(close f)
|
||||||
|
(reverse ergebnis)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
;; Whitespace und Komma trimmen
|
||||||
|
(defun ssg-cfg-trim (s / len)
|
||||||
|
(setq s (vl-string-trim " \t\r\n" s))
|
||||||
|
(setq len (strlen s))
|
||||||
|
(if (and (> len 0) (= (substr s len 1) ","))
|
||||||
|
(setq s (substr s 1 (1- len)))
|
||||||
|
)
|
||||||
|
(vl-string-trim " \t\r\n" s)
|
||||||
|
)
|
||||||
|
|
||||||
|
;; JSON-Wert parsen (String, Zahl, null, true, false, Array)
|
||||||
|
(defun ssg-cfg-parse-value (val-str / len)
|
||||||
|
(setq val-str (ssg-cfg-trim val-str))
|
||||||
|
(cond
|
||||||
|
((= val-str "null") nil)
|
||||||
|
((= val-str "true") T)
|
||||||
|
((= val-str "false") nil)
|
||||||
|
;; String
|
||||||
|
((= (substr val-str 1 1) "\"")
|
||||||
|
(setq len (strlen val-str))
|
||||||
|
(if (and (> len 1) (= (substr val-str len 1) "\""))
|
||||||
|
(substr val-str 2 (- len 2))
|
||||||
|
val-str
|
||||||
|
)
|
||||||
|
)
|
||||||
|
;; Array [...] -> Liste von Werten parsen
|
||||||
|
((= (substr val-str 1 1) "[")
|
||||||
|
(ssg-cfg-parse-array val-str)
|
||||||
|
)
|
||||||
|
;; Zahl
|
||||||
|
(T
|
||||||
|
(if (vl-string-search "." val-str)
|
||||||
|
(atof val-str)
|
||||||
|
(atoi val-str)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
;; Einfaches JSON-Array parsen: [1, 2, 3.5, "text"]
|
||||||
|
(defun ssg-cfg-parse-array (arr-str / inhalt teile ergebnis item)
|
||||||
|
(setq inhalt (ssg-cfg-trim arr-str))
|
||||||
|
;; Klammern entfernen
|
||||||
|
(setq inhalt (substr inhalt 2 (- (strlen inhalt) 2)))
|
||||||
|
;; An Kommas aufteilen (einfach: kein verschachteltes Array)
|
||||||
|
(setq teile (ssg-cfg-split-comma inhalt))
|
||||||
|
(setq ergebnis nil)
|
||||||
|
(foreach item teile
|
||||||
|
(setq ergebnis (cons (ssg-cfg-parse-value item) ergebnis))
|
||||||
|
)
|
||||||
|
(reverse ergebnis)
|
||||||
|
)
|
||||||
|
|
||||||
|
;; String an Kommas aufteilen -> Liste von Strings
|
||||||
|
(defun ssg-cfg-split-comma (s / result current i ch)
|
||||||
|
(setq result nil current "" i 1)
|
||||||
|
(repeat (strlen s)
|
||||||
|
(setq ch (substr s i 1))
|
||||||
|
(if (= ch ",")
|
||||||
|
(progn
|
||||||
|
(setq result (cons current result))
|
||||||
|
(setq current "")
|
||||||
|
)
|
||||||
|
(setq current (strcat current ch))
|
||||||
|
)
|
||||||
|
(setq i (1+ i))
|
||||||
|
)
|
||||||
|
(if (> (strlen (vl-string-trim " " current)) 0)
|
||||||
|
(setq result (cons current result))
|
||||||
|
)
|
||||||
|
(reverse result)
|
||||||
|
)
|
||||||
|
|
||||||
|
;; Key-Value-Zeile parsen: "key": wert -> ("key" . wert)
|
||||||
|
(defun ssg-cfg-parse-kv (zeile / pos key rest pos2 val)
|
||||||
|
(setq zeile (ssg-cfg-trim zeile))
|
||||||
|
(if (and (> (strlen zeile) 0) (= (substr zeile 1 1) "\""))
|
||||||
|
(progn
|
||||||
|
(setq pos (vl-string-search "\"" zeile 1))
|
||||||
|
(if pos
|
||||||
|
(progn
|
||||||
|
(setq key (substr zeile 2 (1- pos)))
|
||||||
|
(setq rest (substr zeile (+ pos 2)))
|
||||||
|
(setq pos2 (vl-string-search ":" rest))
|
||||||
|
(if pos2
|
||||||
|
(cons key (ssg-cfg-parse-value (substr rest (+ pos2 2))))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
;; Verschachteltes JSON-Objekt parsen (1 Ebene tief)
|
||||||
|
;; {"section": {"key": val, ...}, ...}
|
||||||
|
;; -> (("section" ("key" . val) ...) ...)
|
||||||
|
(defun ssg-cfg-parse-nested (zeilen / ergebnis section section-data
|
||||||
|
trimmed kv in-section in-inner)
|
||||||
|
(setq ergebnis nil
|
||||||
|
section nil
|
||||||
|
section-data nil
|
||||||
|
in-section nil
|
||||||
|
in-inner nil
|
||||||
|
)
|
||||||
|
(foreach zeile zeilen
|
||||||
|
(setq trimmed (ssg-cfg-trim zeile))
|
||||||
|
(cond
|
||||||
|
;; Aeusseres { oder } ignorieren (Wurzel-Objekt)
|
||||||
|
((and (not in-section) (= trimmed "{")) nil)
|
||||||
|
((and (not in-section) (= trimmed "}")) nil)
|
||||||
|
|
||||||
|
;; Section-Start: "name": {
|
||||||
|
((and (not in-inner) (vl-string-search ": {" trimmed))
|
||||||
|
(setq kv (ssg-cfg-parse-kv
|
||||||
|
(substr trimmed 1 (vl-string-search ": {" trimmed))))
|
||||||
|
;; kv ist hier nur der Key-Teil, der Rest ist ": {"
|
||||||
|
;; Einfacher: Key direkt extrahieren
|
||||||
|
(setq section (substr trimmed 2
|
||||||
|
(1- (vl-string-search "\"" trimmed 1))))
|
||||||
|
(setq section-data nil)
|
||||||
|
(setq in-section T in-inner T)
|
||||||
|
)
|
||||||
|
|
||||||
|
;; Section-Ende: }
|
||||||
|
((and in-inner (or (= trimmed "}") (= trimmed "},")))
|
||||||
|
(if section
|
||||||
|
(setq ergebnis (cons (cons section (reverse section-data)) ergebnis))
|
||||||
|
)
|
||||||
|
(setq in-section nil in-inner nil section nil section-data nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
;; Key-Value innerhalb einer Section
|
||||||
|
(in-inner
|
||||||
|
(setq kv (ssg-cfg-parse-kv trimmed))
|
||||||
|
(if kv (setq section-data (cons kv section-data)))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(reverse ergebnis)
|
||||||
|
)
|
||||||
|
|
||||||
|
;; Konfiguration laden
|
||||||
|
;; Sucht data/json/component_defaults.json ueber DXFM_DATA
|
||||||
|
(defun ssg-load-config ( / data-pfad cfg-datei zeilen)
|
||||||
|
(setq data-pfad (getenv "DXFM_DATA"))
|
||||||
|
(if (null data-pfad)
|
||||||
|
(princ "\n[CFG] WARNUNG: DXFM_DATA nicht gesetzt, Config nicht geladen.")
|
||||||
|
(progn
|
||||||
|
(setq cfg-datei (strcat data-pfad "/json/component_defaults.json"))
|
||||||
|
(if (not (findfile cfg-datei))
|
||||||
|
(princ (strcat "\n[CFG] WARNUNG: " cfg-datei " nicht gefunden."))
|
||||||
|
(progn
|
||||||
|
(setq zeilen (ssg-read-file-lines cfg-datei))
|
||||||
|
(if zeilen
|
||||||
|
(progn
|
||||||
|
(setq *ssg-config* (ssg-cfg-parse-nested zeilen))
|
||||||
|
(princ (strcat "\n[CFG] Config geladen: "
|
||||||
|
(itoa (length *ssg-config*)) " Sektionen."))
|
||||||
|
)
|
||||||
|
(princ (strcat "\n[CFG] WARNUNG: Leere Config-Datei: " cfg-datei))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(princ)
|
||||||
|
)
|
||||||
|
|
||||||
|
;; Wert aus Config lesen: (ssg-cfg "section" "key")
|
||||||
|
;; Gibt den Wert oder nil zurueck.
|
||||||
|
(defun ssg-cfg (section key / sec-data)
|
||||||
|
(if *ssg-config*
|
||||||
|
(progn
|
||||||
|
(setq sec-data (cdr (assoc section *ssg-config*)))
|
||||||
|
(if sec-data
|
||||||
|
(cdr (assoc key sec-data))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
;; Wert mit Fallback: (ssg-cfg-or "section" "key" default)
|
||||||
|
(defun ssg-cfg-or (section key default / val)
|
||||||
|
(setq val (ssg-cfg section key))
|
||||||
|
(if val val default)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
(prompt "\nssg_core.lsp geladen.")
|
(prompt "\nssg_core.lsp geladen.")
|
||||||
(princ)
|
(princ)
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@
|
|||||||
hoehe (dimy_tile tile-name)
|
hoehe (dimy_tile tile-name)
|
||||||
)
|
)
|
||||||
(start_image tile-name)
|
(start_image tile-name)
|
||||||
(fill_image 0 0 breite hoehe -18)
|
(fill_image 0 0 breite hoehe (ssg-cfg-or "infrastruktur" "dialog_preview_bg_color" -18))
|
||||||
(slide_image 0 0 breite hoehe (strcat slide-lib "(" slide-name ")"))
|
(slide_image 0 0 breite hoehe (strcat slide-lib "(" slide-name ")"))
|
||||||
(end_image)
|
(end_image)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
(load (strcat base-path "ssg_core.lsp") "ssg_core.lsp nicht gefunden")
|
(load (strcat base-path "ssg_core.lsp") "ssg_core.lsp nicht gefunden")
|
||||||
|
(ssg-load-config)
|
||||||
(load (strcat base-path "ssg_dialog.lsp") "ssg_dialog.lsp nicht gefunden")
|
(load (strcat base-path "ssg_dialog.lsp") "ssg_dialog.lsp nicht gefunden")
|
||||||
(load (strcat base-path "ssg_layer.lsp") "ssg_layer.lsp nicht gefunden")
|
(load (strcat base-path "ssg_layer.lsp") "ssg_layer.lsp nicht gefunden")
|
||||||
;; KreiselInsert.lsp entfernt - ersetzt durch Python/PyRx (lib/elemente/kreisel.py, eckrad.py)
|
;; KreiselInsert.lsp entfernt - ersetzt durch Python/PyRx (lib/elemente/kreisel.py, eckrad.py)
|
||||||
|
|||||||
@@ -5,4 +5,4 @@ REM ================================================================
|
|||||||
|
|
||||||
call "%~dp0setenv.bat"
|
call "%~dp0setenv.bat"
|
||||||
|
|
||||||
python "%DXFM_LIB%\attradd.py" %*
|
python "%DXFM_LIB%\set_attributs.py" %*
|
||||||
+3
-6
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
# Layer-Zuordnung nach Elementkategorie
|
# Layer-Zuordnung nach Elementkategorie
|
||||||
# attradd.py bestimmt die Kategorie anhand KurvenWinkel und
|
# set_attributs.py bestimmt die Kategorie anhand KurvenWinkel und
|
||||||
# WeichenTyp aus den JSON-Daten und setzt LAYER entsprechend.
|
# WeichenTyp aus den JSON-Daten und setzt LAYER entsprechend.
|
||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
[layer]
|
[layer]
|
||||||
@@ -45,8 +45,7 @@ TEILEART = "Omniflo Kurve"
|
|||||||
RADIUS = Radius
|
RADIUS = Radius
|
||||||
WINKEL = KurvenWinkel
|
WINKEL = KurvenWinkel
|
||||||
SIVASNR_TEF = SivasnrTEF
|
SIVASNR_TEF = SivasnrTEF
|
||||||
HOEHE = "2000"
|
|
||||||
DREHUNG = "0"
|
|
||||||
|
|
||||||
[weiche]
|
[weiche]
|
||||||
BESCHR = ProfilTyp
|
BESCHR = ProfilTyp
|
||||||
@@ -56,8 +55,6 @@ TEILEART = "Omniflo Weiche"
|
|||||||
# LAYER = "A-OF-Weiche"
|
# LAYER = "A-OF-Weiche"
|
||||||
WEICHENTYP = WeichenTyp
|
WEICHENTYP = WeichenTyp
|
||||||
WINKEL = KurvenWinkel
|
WINKEL = KurvenWinkel
|
||||||
RADIUS = Breite
|
|
||||||
RICHTUNG = KurvenRichtung
|
RICHTUNG = KurvenRichtung
|
||||||
SIVASNR_TEF = SivasnrTEF
|
SIVASNR_TEF = SivasnrTEF
|
||||||
HOEHE = "2000"
|
|
||||||
DREHUNG = "0"
|
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
{
|
||||||
|
"kreisel": {
|
||||||
|
"durchmesser": 800.0,
|
||||||
|
"pin_abstand": 100.0,
|
||||||
|
"default_laenge": 2300.0,
|
||||||
|
"default_hoehe": 2000.0,
|
||||||
|
"label_hoehe": 100.0,
|
||||||
|
"label_farbe": 7,
|
||||||
|
"label_abstand_oben": 0.0,
|
||||||
|
"color_linie_1": 5,
|
||||||
|
"color_linie_2": 1,
|
||||||
|
"color_pin": 3,
|
||||||
|
"toleranz_kollinear": 0.01,
|
||||||
|
"toleranz_winkel": 1.0,
|
||||||
|
"toleranz_min_distanz": 0.001
|
||||||
|
},
|
||||||
|
"eckrad": {
|
||||||
|
"default_hoehe": 2000.0
|
||||||
|
},
|
||||||
|
"omniflo": {
|
||||||
|
"text_height": 100.0,
|
||||||
|
"text_gap": 20.0,
|
||||||
|
"default_hoehe": "2000",
|
||||||
|
"default_drehung": "0",
|
||||||
|
"laengemax_ap60": 7000.0,
|
||||||
|
"laengemax_ap110": 6000.0,
|
||||||
|
"laengemax_apg110": 6000.0,
|
||||||
|
"default_gerade_laenge": "2000",
|
||||||
|
"bogen_winkel": [180, 90, 67.5, 45, 22.5],
|
||||||
|
"weichen_winkel_90": 90,
|
||||||
|
"weichen_winkel_45": 45,
|
||||||
|
"weichen_winkel_parallel": 0,
|
||||||
|
"weichen_winkel_koerper": 22.5
|
||||||
|
},
|
||||||
|
"vario": {
|
||||||
|
"staustrecke_basis": 1000,
|
||||||
|
"feste_horizontal": 1600,
|
||||||
|
"bogen_winkel": [3, 6, 9, 12, 15, 18, 21, 27, 33, 39, 45, 51],
|
||||||
|
"gefaelle_winkel": 3,
|
||||||
|
"separator_block_dx": 300,
|
||||||
|
"separator_block_dz": 0,
|
||||||
|
"station_block_dx": 499,
|
||||||
|
"station_block_dz": -26,
|
||||||
|
"skalierung_basis": 1000.0
|
||||||
|
},
|
||||||
|
"gefaelle": {
|
||||||
|
"default_delta_l": 5000.0,
|
||||||
|
"default_winkel": 3.0,
|
||||||
|
"separator_breite": 300.0
|
||||||
|
},
|
||||||
|
"infrastruktur": {
|
||||||
|
"attdef_y_spacing_factor": 2.0,
|
||||||
|
"dialog_preview_bg_color": -18,
|
||||||
|
"mm_pro_meter": 1000.0
|
||||||
|
}
|
||||||
|
}
|
||||||
+62
-28
@@ -35,7 +35,7 @@ Diese Werkzeuge ermöglichen die massenhafte Aufbereitung von einzelnen dxf Date
|
|||||||
- [--number SIVASNR](#--number-sivasnr-1)
|
- [--number SIVASNR](#--number-sivasnr-1)
|
||||||
- [Uebersicht K-Zuordnung](#uebersicht-k-zuordnung)
|
- [Uebersicht K-Zuordnung](#uebersicht-k-zuordnung)
|
||||||
- [Umgebungsvariablen](#umgebungsvariablen-1)
|
- [Umgebungsvariablen](#umgebungsvariablen-1)
|
||||||
- [attradd](#attradd)
|
- [set_attributs](#set_attributs)
|
||||||
- [Aufruf](#aufruf-2)
|
- [Aufruf](#aufruf-2)
|
||||||
- [Datenquellen](#datenquellen-2)
|
- [Datenquellen](#datenquellen-2)
|
||||||
- [Ablauf](#ablauf-2)
|
- [Ablauf](#ablauf-2)
|
||||||
@@ -149,7 +149,7 @@ Alle 107 Items (27 Boegen + 80 Weichen) sind exklusiv genau einem Schalter zugeo
|
|||||||
## Uebersicht aller Schalter
|
## Uebersicht aller Schalter
|
||||||
|
|
||||||
| Schalter | Items | WeichenTyp | KurvenWinkel | Einfuegepunkt-Kriterium |
|
| Schalter | Items | WeichenTyp | KurvenWinkel | Einfuegepunkt-Kriterium |
|
||||||
|---|---|---|---|---|
|
| --- | --- | --- | --- | --- |
|
||||||
| `--boegen` | 27 | - | 22.5, 45, 67.5, 90, 180 | Tangentenschnittpunkt am Bogen (180: Mittelpunkt) |
|
| `--boegen` | 27 | - | 22.5, 45, 67.5, 90, 180 | Tangentenschnittpunkt am Bogen (180: Mittelpunkt) |
|
||||||
| `--weichen45` | 32 | Einzel-, Doppel-, Dreiwegeweiche | 45 | Tangente oberer Bogenpunkt x laengste Vertikale |
|
| `--weichen45` | 32 | Einzel-, Doppel-, Dreiwegeweiche | 45 | Tangente oberer Bogenpunkt x laengste Vertikale |
|
||||||
| `--weichen90` | 24 | Einzel-, Doppel-, Dreiwegeweiche | 90 | Tangente oberer Bogenpunkt x laengste Vertikale |
|
| `--weichen90` | 24 | Einzel-, Doppel-, Dreiwegeweiche | 90 | Tangente oberer Bogenpunkt x laengste Vertikale |
|
||||||
@@ -259,7 +259,7 @@ Nur die angegebene 9-stellige Sivasnr verarbeiten. Kombinierbar mit jedem Schalt
|
|||||||
## Uebersicht K-Zuordnung
|
## Uebersicht K-Zuordnung
|
||||||
|
|
||||||
| K | Boegen | Weichen | Weichenkoerper | Dreifach/Delta/Stern |
|
| K | Boegen | Weichen | Weichenkoerper | Dreifach/Delta/Stern |
|
||||||
|---|---|---|---|---|
|
| --- | --- | --- | --- | --- |
|
||||||
| K1 | Oberste H-Linie (rz=0) | Unterste V-Linie (rz=90) | Unterste V-Linie (rz=90) | Unterste V-Linie (rz=90) |
|
| K1 | Oberste H-Linie (rz=0) | Unterste V-Linie (rz=90) | Unterste V-Linie (rz=90) | Unterste V-Linie (rz=90) |
|
||||||
| K2 | Anderes Kettenende | Linker Bogenzweig | Linke Diagonale | Linkes H-Linienende |
|
| K2 | Anderes Kettenende | Linker Bogenzweig | Linke Diagonale | Linkes H-Linienende |
|
||||||
| K3 | - | Rechter Bogenzweig (2+ Boegen) | Rechte Diagonale (2+ Diag.) | Rechtes H-Linienende |
|
| K3 | - | Rechter Bogenzweig (2+ Boegen) | Rechte Diagonale (2+ Diag.) | Rechtes H-Linienende |
|
||||||
@@ -274,14 +274,14 @@ Nur die angegebene 9-stellige Sivasnr verarbeiten. Kombinierbar mit jedem Schalt
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# attradd
|
# set_attributs
|
||||||
|
|
||||||
Fuegt Attribute (ATTDEF) zu allen Omniflo DXF-Dateien hinzu. Die Attribut-Tags und deren Werte werden ueber eine Konfigurationsdatei gesteuert.
|
Fuegt Attribute (ATTDEF) zu allen Omniflo DXF-Dateien hinzu. Die Attribut-Tags und deren Werte werden ueber eine Konfigurationsdatei gesteuert.
|
||||||
|
|
||||||
## Aufruf
|
## Aufruf
|
||||||
|
|
||||||
```
|
```
|
||||||
python lib/attradd.py [--number SIVASNR] [--dry-run]
|
python lib/set_attributs.py [--number SIVASNR] [--dry-run]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Datenquellen
|
## Datenquellen
|
||||||
@@ -303,34 +303,68 @@ python lib/attradd.py [--number SIVASNR] [--dry-run]
|
|||||||
|
|
||||||
## Konfiguration (attradd.cfg)
|
## Konfiguration (attradd.cfg)
|
||||||
|
|
||||||
Die Config-Datei ist im INI-Format mit Abschnitten je Elementtyp:
|
Die Config-Datei ist im INI-Format mit Abschnitten je Elementtyp.
|
||||||
|
|
||||||
```ini
|
|
||||||
[bogen]
|
|
||||||
BESCHR = ProfilTyp
|
|
||||||
ARTINR = Sivasnr
|
|
||||||
TEILEART = "Omniflo Kurve"
|
|
||||||
LAYER = "A-OF-Bogen"
|
|
||||||
RADIUS = Radius
|
|
||||||
WINKEL = KurvenWinkel
|
|
||||||
SIVASNR_TEF = SivasnrTEF
|
|
||||||
|
|
||||||
[weiche]
|
|
||||||
BESCHR = ProfilTyp
|
|
||||||
ARTINR = Sivasnr
|
|
||||||
TEILEART = "Omniflo Weiche"
|
|
||||||
LAYER = "A-OF-Weiche"
|
|
||||||
WEICHENTYP = WeichenTyp
|
|
||||||
WINKEL = KurvenWinkel
|
|
||||||
RADIUS = Breite
|
|
||||||
SIVASNR_TEF = SivasnrTEF
|
|
||||||
```
|
|
||||||
|
|
||||||
Quellwerte koennen sein:
|
Quellwerte koennen sein:
|
||||||
- **JSON-Feldname** (z.B. `ProfilTyp`) - Wert wird aus dem JSON-Eintrag gelesen
|
- **JSON-Feldname** (z.B. `ProfilTyp`) - Wert wird aus dem JSON-Eintrag gelesen
|
||||||
- **Fester Text** in Anfuehrungszeichen (z.B. `"Omniflo Kurve"`)
|
- **Fester Text** in Anfuehrungszeichen (z.B. `"Omniflo Kurve"`)
|
||||||
- **Platzhalter** `{sivasnr}` - wird durch die Sivasnr ersetzt
|
- **Platzhalter** `{sivasnr}` - wird durch die Sivasnr ersetzt
|
||||||
|
|
||||||
|
### Attribute Omniflo Kurve (Bogen)
|
||||||
|
|
||||||
|
| ATTDEF-Tag | Quelle | Beschreibung |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `BESCHR` | `ProfilTyp` | Profilbezeichnung aus JSON |
|
||||||
|
| `ARTINR` | `Sivasnr` | Sivas-Artikelnummer |
|
||||||
|
| `TEILEART` | `"Omniflo Kurve"` | Fester Typname |
|
||||||
|
| `RADIUS` | `Radius` | Kurvenradius in mm |
|
||||||
|
| `WINKEL` | `KurvenWinkel` | Kurvenwinkel in Grad |
|
||||||
|
| `SIVASNR_TEF` | `SivasnrTEF` | Sivas-Nr. des TEF-Antriebs (leer = kein Antrieb) |
|
||||||
|
| `HOEHE` | `"2000"` | Montagehoehe in mm (wird beim Export aus Z-Koordinate aktualisiert) |
|
||||||
|
| `DREHUNG` | `"0"` | Drehwinkel in Grad (wird beim Export aus CAD-Rotation aktualisiert) |
|
||||||
|
| `LAYER` | *(aus [layer])* | Layer-Name gemaess Kategorisierung |
|
||||||
|
|
||||||
|
### Attribute Omniflo Weiche
|
||||||
|
|
||||||
|
| ATTDEF-Tag | Quelle | Beschreibung |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `BESCHR` | `ProfilTyp` | Profilbezeichnung aus JSON |
|
||||||
|
| `ARTINR` | `Sivasnr` | Sivas-Artikelnummer |
|
||||||
|
| `TEILEART` | `"Omniflo Weiche"` | Fester Typname |
|
||||||
|
| `WEICHENTYP` | `WeichenTyp` | Weichentyp (Einzelweiche, Doppelweiche, Dreiwegeweiche, ...) |
|
||||||
|
| `WINKEL` | `KurvenWinkel` | Kurvenwinkel in Grad |
|
||||||
|
| `RICHTUNG` | `KurvenRichtung` | Richtungskennung (1=Links, 2=Rechts, 3=Beide, 7=Dreiweg) |
|
||||||
|
| `SIVASNR_TEF` | `SivasnrTEF` | Sivas-Nr. des TEF-Antriebs (leer = kein Antrieb) |
|
||||||
|
| `HOEHE` | `"2000"` | Montagehoehe in mm (wird beim Export aus Z-Koordinate aktualisiert) |
|
||||||
|
| `DREHUNG` | `"0"` | Drehwinkel in Grad (wird beim Export aus CAD-Rotation aktualisiert) |
|
||||||
|
| `LAYER` | *(aus [layer])* | Layer-Name gemaess Kategorisierung |
|
||||||
|
|
||||||
|
### CSV-Export-Felder (Merkmale)
|
||||||
|
|
||||||
|
Die Attribute werden beim CSV-Export (`export_csv.py` / `OMNI_EXPORT`) wie folgt in CSV-Merkmale ueberfuehrt.
|
||||||
|
CSV-Format: `Elementnummer;TeileArt;TeileId;Bezeichnung;Anzahl;Merkmale`
|
||||||
|
|
||||||
|
**Omniflo Kurve:**
|
||||||
|
|
||||||
|
| Merkmal | Quelle | Typ |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `Kurvenwinkel` | JSON `KurvenWinkel` | float |
|
||||||
|
| `Radius` | JSON `Radius` | float |
|
||||||
|
| `Höhe` | Attribut `HOEHE` / Z-Koordinate | string |
|
||||||
|
| `Drehung` | Attribut `DREHUNG` / CAD-Rotation | float |
|
||||||
|
| `SivasNummer` | JSON `Sivasnr` | string |
|
||||||
|
|
||||||
|
**Omniflo Weiche:**
|
||||||
|
|
||||||
|
| Merkmal | Quelle | Typ |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `Weichentyp` | JSON `WeichenTyp` | string |
|
||||||
|
| `Richtung` | JSON `KurvenRichtung` | string |
|
||||||
|
| `Weichenwinkel` | JSON `KurvenWinkel` | float |
|
||||||
|
| `Höhe` | Attribut `HOEHE` / Z-Koordinate | string |
|
||||||
|
| `Drehung` | Attribut `DREHUNG` / CAD-Rotation | float |
|
||||||
|
| `Antrieb Kurve` | `SivasnrTEF` != null | bool |
|
||||||
|
| `SivasNummer` | JSON `Sivasnr` | string |
|
||||||
|
|
||||||
## Schalter
|
## Schalter
|
||||||
|
|
||||||
### --number SIVASNR / -n SIVASNR
|
### --number SIVASNR / -n SIVASNR
|
||||||
|
|||||||
+6
-30
@@ -63,8 +63,8 @@ def get_drehung(block):
|
|||||||
|
|
||||||
def build_bogen_merkmale(block, eintrag):
|
def build_bogen_merkmale(block, eintrag):
|
||||||
return {
|
return {
|
||||||
"Kurvenwinkel": eintrag.get("KurvenWinkel", 0),
|
"Kurvenwinkel": float(eintrag.get("KurvenWinkel", 0)),
|
||||||
"Radius": eintrag.get("Radius", 0),
|
"Radius": float(eintrag.get("Radius", 0)),
|
||||||
"Höhe": get_hoehe(block),
|
"Höhe": get_hoehe(block),
|
||||||
"Drehung": get_drehung(block),
|
"Drehung": get_drehung(block),
|
||||||
"SivasNummer": str(eintrag.get("Sivasnr", ""))
|
"SivasNummer": str(eintrag.get("Sivasnr", ""))
|
||||||
@@ -76,7 +76,7 @@ def build_weiche_merkmale(block, eintrag):
|
|||||||
return {
|
return {
|
||||||
"Weichentyp": wt,
|
"Weichentyp": wt,
|
||||||
"Richtung": str(eintrag.get("KurvenRichtung", "")),
|
"Richtung": str(eintrag.get("KurvenRichtung", "")),
|
||||||
"Weichenwinkel": eintrag.get("KurvenWinkel", 0),
|
"Weichenwinkel": float(eintrag.get("KurvenWinkel", 0)),
|
||||||
"Höhe": get_hoehe(block),
|
"Höhe": get_hoehe(block),
|
||||||
"Drehung": get_drehung(block),
|
"Drehung": get_drehung(block),
|
||||||
"Antrieb Kurve": eintrag.get("SivasnrTEF") is not None,
|
"Antrieb Kurve": eintrag.get("SivasnrTEF") is not None,
|
||||||
@@ -129,23 +129,13 @@ def build_kreisel_merkmale(block):
|
|||||||
SKIP_BLOCKS = {"K1", "K2", "K3", "K4", "KS_EIN", "KS_AUS"}
|
SKIP_BLOCKS = {"K1", "K2", "K3", "K4", "KS_EIN", "KS_AUS"}
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
# Planquadrat aus Block-Koordinaten
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def format_planquadrat(block):
|
|
||||||
x = block.get("x", 0.0)
|
|
||||||
y = block.get("y", 0.0)
|
|
||||||
return f"X:{x:.2f} Y:{y:.2f}"
|
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Bloecke verarbeiten (einfache Liste, keine Summierung)
|
# Bloecke verarbeiten (einfache Liste, keine Summierung)
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
def process_blocks(blocks, lookup):
|
def process_blocks(blocks, lookup):
|
||||||
items = []
|
items = []
|
||||||
elem_nr = -1
|
elem_nr = 0
|
||||||
bogen_count = 0
|
bogen_count = 0
|
||||||
weiche_count = {}
|
weiche_count = {}
|
||||||
gerade_count = 0
|
gerade_count = 0
|
||||||
@@ -169,10 +159,7 @@ def process_blocks(blocks, lookup):
|
|||||||
"nr": elem_nr,
|
"nr": elem_nr,
|
||||||
"teileart": "Omniflo Kurve",
|
"teileart": "Omniflo Kurve",
|
||||||
"teileid": shape_id,
|
"teileid": shape_id,
|
||||||
"nachbarids": "",
|
|
||||||
"bezeichnung": f"OFBogen :{bogen_count}",
|
"bezeichnung": f"OFBogen :{bogen_count}",
|
||||||
"planquadrat": format_planquadrat(block),
|
|
||||||
"rotation": block.get("rotation", 0.0),
|
|
||||||
"merkmale": build_bogen_merkmale(block, eintrag),
|
"merkmale": build_bogen_merkmale(block, eintrag),
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -183,10 +170,7 @@ def process_blocks(blocks, lookup):
|
|||||||
"nr": elem_nr,
|
"nr": elem_nr,
|
||||||
"teileart": "Omniflo Weiche",
|
"teileart": "Omniflo Weiche",
|
||||||
"teileid": shape_id,
|
"teileid": shape_id,
|
||||||
"nachbarids": "",
|
|
||||||
"bezeichnung": f"OFWeiche :{weiche_count[wt]}",
|
"bezeichnung": f"OFWeiche :{weiche_count[wt]}",
|
||||||
"planquadrat": format_planquadrat(block),
|
|
||||||
"rotation": block.get("rotation", 0.0),
|
|
||||||
"merkmale": build_weiche_merkmale(block, eintrag),
|
"merkmale": build_weiche_merkmale(block, eintrag),
|
||||||
})
|
})
|
||||||
continue
|
continue
|
||||||
@@ -199,10 +183,7 @@ def process_blocks(blocks, lookup):
|
|||||||
"nr": elem_nr,
|
"nr": elem_nr,
|
||||||
"teileart": "Omniflo Gerade",
|
"teileart": "Omniflo Gerade",
|
||||||
"teileid": generate_shape_id(),
|
"teileid": generate_shape_id(),
|
||||||
"nachbarids": "",
|
|
||||||
"bezeichnung": f"OFGerade :{gerade_count}",
|
"bezeichnung": f"OFGerade :{gerade_count}",
|
||||||
"planquadrat": format_planquadrat(block),
|
|
||||||
"rotation": block.get("rotation", 0.0),
|
|
||||||
"merkmale": build_gerade_merkmale(block),
|
"merkmale": build_gerade_merkmale(block),
|
||||||
})
|
})
|
||||||
continue
|
continue
|
||||||
@@ -215,10 +196,7 @@ def process_blocks(blocks, lookup):
|
|||||||
"nr": elem_nr,
|
"nr": elem_nr,
|
||||||
"teileart": "ILS 2.0 Kreisel",
|
"teileart": "ILS 2.0 Kreisel",
|
||||||
"teileid": generate_shape_id(),
|
"teileid": generate_shape_id(),
|
||||||
"nachbarids": "",
|
|
||||||
"bezeichnung": f"Kreisel :{kreisel_count}",
|
"bezeichnung": f"Kreisel :{kreisel_count}",
|
||||||
"planquadrat": format_planquadrat(block),
|
|
||||||
"rotation": block.get("rotation", 0.0),
|
|
||||||
"merkmale": build_kreisel_merkmale(block),
|
"merkmale": build_kreisel_merkmale(block),
|
||||||
})
|
})
|
||||||
continue
|
continue
|
||||||
@@ -236,10 +214,8 @@ def format_csv_line(item):
|
|||||||
f'{item["nr"]}'
|
f'{item["nr"]}'
|
||||||
f';"{item["teileart"]}"'
|
f';"{item["teileart"]}"'
|
||||||
f';"{item["teileid"]}"'
|
f';"{item["teileid"]}"'
|
||||||
f';{item["nachbarids"]}'
|
|
||||||
f';"{item["bezeichnung"]}"'
|
f';"{item["bezeichnung"]}"'
|
||||||
f';"{item["planquadrat"]}"'
|
f';1'
|
||||||
f';'
|
|
||||||
f';{merkmale_json}'
|
f';{merkmale_json}'
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -271,7 +247,7 @@ def main():
|
|||||||
|
|
||||||
items = process_blocks(blocks, lookup)
|
items = process_blocks(blocks, lookup)
|
||||||
|
|
||||||
header = "Elementnummer;TeileArt;TeileId;NachbarIds;Bezeichnung;Planquadrat;rotation;Merkmale"
|
header = "Elementnummer;TeileArt;TeileId;Bezeichnung;Anzahl;Merkmale"
|
||||||
with open(output_csv, "w", encoding="utf-8") as f:
|
with open(output_csv, "w", encoding="utf-8") as f:
|
||||||
f.write(header + "\n")
|
f.write(header + "\n")
|
||||||
for item in items:
|
for item in items:
|
||||||
|
|||||||
+12
-2
@@ -212,11 +212,21 @@ def build_row_layout(data_dir, results_dir):
|
|||||||
|
|
||||||
|
|
||||||
def import_element_as_block(source_doc, target_doc, block_name):
|
def import_element_as_block(source_doc, target_doc, block_name):
|
||||||
"""Importiert alle Modelspace-Entities eines Quell-Dokuments als Block."""
|
"""
|
||||||
|
Importiert ein Quell-Dokument als Block in target_doc.
|
||||||
|
|
||||||
|
Wenn das Quell-Dokument eine Blockdefinition mit dem Namen block_name
|
||||||
|
enthaelt (erzeugt durch set_attributs.py), wird diese direkt importiert.
|
||||||
|
Andernfalls werden alle Modelspace-Entities als Block importiert.
|
||||||
|
"""
|
||||||
importer = Importer(source_doc, target_doc)
|
importer = Importer(source_doc, target_doc)
|
||||||
importer.import_tables()
|
importer.import_tables()
|
||||||
blk = target_doc.blocks.new(name=block_name)
|
blk = target_doc.blocks.new(name=block_name)
|
||||||
for entity in source_doc.modelspace():
|
if block_name in source_doc.blocks:
|
||||||
|
source_layout = source_doc.blocks[block_name]
|
||||||
|
else:
|
||||||
|
source_layout = source_doc.modelspace()
|
||||||
|
for entity in source_layout:
|
||||||
importer.import_entity(entity, blk)
|
importer.import_entity(entity, blk)
|
||||||
importer.finalize()
|
importer.finalize()
|
||||||
return block_name
|
return block_name
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""
|
"""
|
||||||
attradd.py - Fuegt Attribute (ATTDEF) zu allen Omniflo DXF-Dateien hinzu.
|
set_attributs.py - Fuegt Attribute (ATTDEF) zu allen Omniflo DXF-Dateien hinzu.
|
||||||
|
|
||||||
Liest die Attribut-Konfiguration aus cfg/attradd.cfg und die Element-Daten
|
Liest die Attribut-Konfiguration aus cfg/attradd.cfg und die Element-Daten
|
||||||
aus data/json/omniflo_boegen.json und omniflo_weichen.json.
|
aus data/json/omniflo_boegen.json und omniflo_weichen.json.
|
||||||
@@ -13,7 +13,7 @@ Umgebungsvariablen:
|
|||||||
DXFM_RESULTS - Pfad zum results/-Verzeichnis
|
DXFM_RESULTS - Pfad zum results/-Verzeichnis
|
||||||
|
|
||||||
Aufruf:
|
Aufruf:
|
||||||
python lib/attradd.py [--number SIVASNR] [--dry-run]
|
python lib/set_attributs.py [--number SIVASNR] [--dry-run]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
@@ -157,11 +157,32 @@ ATTDEF_HEIGHT = 5.0
|
|||||||
ATTDEF_LAYER = "ATTRIB"
|
ATTDEF_LAYER = "ATTRIB"
|
||||||
|
|
||||||
|
|
||||||
|
def wrap_entities_in_block(doc, block_name):
|
||||||
|
"""
|
||||||
|
Verschiebt alle Entities aus dem Modelspace in eine Blockdefinition
|
||||||
|
mit dem Namen block_name und fuegt eine Blockreferenz bei (0, 0) ein.
|
||||||
|
Vorhandene Blockdefinition mit gleichem Namen wird ersetzt (fuer Re-Runs).
|
||||||
|
"""
|
||||||
|
msp = doc.modelspace()
|
||||||
|
|
||||||
|
# Vorhandene Blockdefinition entfernen
|
||||||
|
if block_name in doc.blocks:
|
||||||
|
doc.blocks.delete_block(block_name, safe=False)
|
||||||
|
|
||||||
|
blk = doc.blocks.new(block_name)
|
||||||
|
|
||||||
|
for entity in list(msp):
|
||||||
|
msp.move_to_layout(entity, blk)
|
||||||
|
|
||||||
|
msp.add_blockref(block_name, (0, 0))
|
||||||
|
|
||||||
|
|
||||||
def add_attdefs_to_dxf(dxf_path, output_path, attr_defs, json_entry, sivasnr,
|
def add_attdefs_to_dxf(dxf_path, output_path, attr_defs, json_entry, sivasnr,
|
||||||
layer_value=""):
|
layer_value=""):
|
||||||
"""
|
"""
|
||||||
Oeffnet eine DXF-Datei, fuegt ATTDEF-Entities in den Modelspace ein
|
Oeffnet eine DXF-Datei, fuegt ATTDEF-Entities in den Modelspace ein,
|
||||||
und speichert das Ergebnis.
|
fasst alle Entities anschliessend in einen Block mit dem Namen sivasnr
|
||||||
|
zusammen und speichert das Ergebnis.
|
||||||
|
|
||||||
attr_defs: Liste von (TAG, source_expression) aus der Config
|
attr_defs: Liste von (TAG, source_expression) aus der Config
|
||||||
json_entry: Dict mit den JSON-Daten fuer dieses Element
|
json_entry: Dict mit den JSON-Daten fuer dieses Element
|
||||||
@@ -205,6 +226,9 @@ def add_attdefs_to_dxf(dxf_path, output_path, attr_defs, json_entry, sivasnr,
|
|||||||
y_pos += ATTDEF_SPACING
|
y_pos += ATTDEF_SPACING
|
||||||
count += 1
|
count += 1
|
||||||
|
|
||||||
|
# Alle Entities (Geometrie + ATTDEFs) in Block mit Sivasnr-Namen fassen
|
||||||
|
wrap_entities_in_block(doc, sivasnr)
|
||||||
|
|
||||||
doc.saveas(output_path)
|
doc.saveas(output_path)
|
||||||
return count
|
return count
|
||||||
|
|
||||||
@@ -219,7 +243,7 @@ def process_all(data_dir, cfg_path, results_dir, single_nr=None, dry_run=False):
|
|||||||
# Config laden
|
# Config laden
|
||||||
attr_config = load_config(cfg_path)
|
attr_config = load_config(cfg_path)
|
||||||
layer_map = attr_config.pop("layer", {})
|
layer_map = attr_config.pop("layer", {})
|
||||||
print(f"[attradd] Config geladen: {list(attr_config.keys())}")
|
print(f"[set_attributs] Config geladen: {list(attr_config.keys())}")
|
||||||
if layer_map:
|
if layer_map:
|
||||||
print(f" [layer] {len(layer_map)} Zuordnungen: "
|
print(f" [layer] {len(layer_map)} Zuordnungen: "
|
||||||
f"{', '.join(f'{k}={v}' for k, v in layer_map.items())}")
|
f"{', '.join(f'{k}={v}' for k, v in layer_map.items())}")
|
||||||
@@ -231,7 +255,7 @@ def process_all(data_dir, cfg_path, results_dir, single_nr=None, dry_run=False):
|
|||||||
boegen = load_json(os.path.join(data_dir, "json", "omniflo_boegen.json"))
|
boegen = load_json(os.path.join(data_dir, "json", "omniflo_boegen.json"))
|
||||||
weichen = load_json(os.path.join(data_dir, "json", "omniflo_weichen.json"))
|
weichen = load_json(os.path.join(data_dir, "json", "omniflo_weichen.json"))
|
||||||
lookup = build_lookup(boegen, weichen)
|
lookup = build_lookup(boegen, weichen)
|
||||||
print(f"[attradd] {len(boegen)} Boegen, {len(weichen)} Weichen geladen.")
|
print(f"[set_attributs] {len(boegen)} Boegen, {len(weichen)} Weichen geladen.")
|
||||||
|
|
||||||
# Ausgabeverzeichnis
|
# Ausgabeverzeichnis
|
||||||
out_dir = os.path.join(results_dir, "omniflo")
|
out_dir = os.path.join(results_dir, "omniflo")
|
||||||
@@ -284,10 +308,10 @@ def process_all(data_dir, cfg_path, results_dir, single_nr=None, dry_run=False):
|
|||||||
errors += 1
|
errors += 1
|
||||||
print(f" FEHLER: {sivasnr}: {e}")
|
print(f" FEHLER: {sivasnr}: {e}")
|
||||||
|
|
||||||
print(f"\n[attradd] Fertig: {processed} verarbeitet, "
|
print(f"\n[set_attributs] Fertig: {processed} verarbeitet, "
|
||||||
f"{skipped} uebersprungen, {errors} Fehler.")
|
f"{skipped} uebersprungen, {errors} Fehler.")
|
||||||
if not dry_run:
|
if not dry_run:
|
||||||
print(f"[attradd] Ausgabe in: {out_dir}")
|
print(f"[set_attributs] Ausgabe in: {out_dir}")
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@@ -317,7 +341,7 @@ def main():
|
|||||||
|
|
||||||
cfg_path = os.path.join(cfg_dir, "attradd.cfg")
|
cfg_path = os.path.join(cfg_dir, "attradd.cfg")
|
||||||
if not os.path.exists(cfg_path):
|
if not os.path.exists(cfg_path):
|
||||||
print(f"[attradd] FEHLER: Config nicht gefunden: {cfg_path}")
|
print(f"[set_attributs] FEHLER: Config nicht gefunden: {cfg_path}")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
process_all(data_dir, cfg_path, results_dir,
|
process_all(data_dir, cfg_path, results_dir,
|
||||||
@@ -36,6 +36,34 @@ def _load_json(path):
|
|||||||
return json.load(f)
|
return json.load(f)
|
||||||
|
|
||||||
|
|
||||||
|
# --- Omniflo Fixtures ---
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def omniflo_testdata():
|
||||||
|
"""Laedt die Omniflo-Testdefinitionen aus testdata/omniflo_tests.json."""
|
||||||
|
path = os.path.join(_testdata_dir(), "omniflo_tests.json")
|
||||||
|
return _load_json(path)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def omniflo_csv():
|
||||||
|
"""Laedt den Inhalt der omniflo_export.csv aus output/."""
|
||||||
|
import csv as _csv
|
||||||
|
path = os.path.join(_output_dir(), "omniflo_export.csv")
|
||||||
|
if not os.path.exists(path):
|
||||||
|
pytest.skip(
|
||||||
|
"omniflo_export.csv nicht vorhanden - "
|
||||||
|
"TEST_OMNIFLO_EXPORT in BricsCAD ausfuehren"
|
||||||
|
)
|
||||||
|
rows = []
|
||||||
|
with open(path, "r", encoding="utf-8") as f:
|
||||||
|
reader = _csv.reader(f, delimiter=";")
|
||||||
|
header = next(reader)
|
||||||
|
for row in reader:
|
||||||
|
rows.append(row)
|
||||||
|
return {"header": header, "rows": rows}
|
||||||
|
|
||||||
|
|
||||||
# --- Kreisel Fixtures ---
|
# --- Kreisel Fixtures ---
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|||||||
@@ -0,0 +1,173 @@
|
|||||||
|
;; ============================================================
|
||||||
|
;; test_omniflo.lsp - Automatischer Integrationstest fuer Omniflo
|
||||||
|
;;
|
||||||
|
;; Laedt Testfaelle aus tests/testdata/omniflo_tests.json,
|
||||||
|
;; fuegt je einen Bogen und Weiche jeden Typs in verschiedenen
|
||||||
|
;; Hoehen ein (Versatz in x-Richtung je 200mm) und exportiert
|
||||||
|
;; die CSV-Datei nach tests/output/omniflo_export.csv.
|
||||||
|
;;
|
||||||
|
;; Voraussetzungen:
|
||||||
|
;; - SSG_LIB geladen (OmniModulInsert.lsp, export.lsp)
|
||||||
|
;; - Umgebungsvariablen DXFMAKRO, DXFM_DATA gesetzt
|
||||||
|
;;
|
||||||
|
;; Aufruf in BricsCAD:
|
||||||
|
;; (load "tests/test_omniflo.lsp")
|
||||||
|
;; TEST_OMNIFLO_EXPORT
|
||||||
|
;; ============================================================
|
||||||
|
|
||||||
|
|
||||||
|
;; --- Omniflo Block non-interaktiv an gegebenem Punkt einfuegen ---
|
||||||
|
;; sivasnr-str : String der SivasNr (= Dateiname ohne .dxf)
|
||||||
|
;; insert-pt : Einfuegepunkt als Liste (x y z)
|
||||||
|
;; hoehe-str : Hoehe als String (fuer HOEHE-Attribut)
|
||||||
|
;; drehung-str : Drehung als String (fuer DREHUNG-Attribut)
|
||||||
|
(defun omni:test-insert (sivasnr-str insert-pt hoehe-str drehung-str /
|
||||||
|
dxf-pfad data-pfad blockEnt angleDeg)
|
||||||
|
(setq data-pfad (getenv "DXFM_DATA"))
|
||||||
|
(if (null data-pfad)
|
||||||
|
(progn
|
||||||
|
(princ "\n[TEST_OMNIFLO] FEHLER: DXFM_DATA nicht gesetzt!")
|
||||||
|
nil
|
||||||
|
)
|
||||||
|
(progn
|
||||||
|
(setq dxf-pfad (strcat data-pfad "/omniflo/" sivasnr-str ".dxf"))
|
||||||
|
(if (not (findfile dxf-pfad))
|
||||||
|
(progn
|
||||||
|
(princ (strcat "\n[TEST_OMNIFLO] WARNUNG: DXF nicht gefunden: " dxf-pfad))
|
||||||
|
nil
|
||||||
|
)
|
||||||
|
(progn
|
||||||
|
(setq angleDeg (if drehung-str (atof drehung-str) 0.0))
|
||||||
|
(setvar "ATTREQ" 0)
|
||||||
|
(setvar "ATTDIA" 0)
|
||||||
|
(command "_.INSERT" dxf-pfad insert-pt "" "" angleDeg)
|
||||||
|
(setq blockEnt (entlast))
|
||||||
|
(if (and blockEnt
|
||||||
|
(= (cdr (assoc 0 (entget blockEnt))) "INSERT"))
|
||||||
|
(ssg-attrib-set-on blockEnt
|
||||||
|
(list (cons "HOEHE" (if hoehe-str hoehe-str "2000"))
|
||||||
|
(cons "DREHUNG" (if drehung-str drehung-str "0"))))
|
||||||
|
)
|
||||||
|
(princ (strcat "\n[TEST_OMNIFLO] OK: " sivasnr-str
|
||||||
|
" H=" (if hoehe-str hoehe-str "2000")))
|
||||||
|
blockEnt
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
;; ============================================================
|
||||||
|
;; C:TEST_OMNIFLO_EXPORT
|
||||||
|
;;
|
||||||
|
;; Liest omniflo_tests.json, fuegt alle Testbloecke ein,
|
||||||
|
;; exportiert CSV nach tests/output/.
|
||||||
|
;; ============================================================
|
||||||
|
(defun c:TEST_OMNIFLO_EXPORT (/ tests-json-pfad testfaelle
|
||||||
|
x-pos x-schritt
|
||||||
|
idx eintrag sivasnr hoehe-str drehung-str
|
||||||
|
insert-pt anzahl-ok anzahl-fehler
|
||||||
|
tests-out-dir old-results)
|
||||||
|
|
||||||
|
(if (not *lib-initialized*)
|
||||||
|
(init-bibliothek)
|
||||||
|
)
|
||||||
|
|
||||||
|
(ssg-start "TEST_OMNIFLO_EXPORT"
|
||||||
|
'(("OSMODE") ("ATTREQ") ("ATTDIA")))
|
||||||
|
(setvar "OSMODE" 0)
|
||||||
|
(setvar "ATTREQ" 0)
|
||||||
|
(setvar "ATTDIA" 0)
|
||||||
|
|
||||||
|
;; Testdaten laden
|
||||||
|
(setq tests-json-pfad
|
||||||
|
(strcat (getenv "DXFMAKRO") "/tests/testdata/omniflo_tests.json"))
|
||||||
|
|
||||||
|
(if (not (findfile tests-json-pfad))
|
||||||
|
(progn
|
||||||
|
(princ (strcat "\n[TEST_OMNIFLO] FEHLER: Testdaten nicht gefunden: "
|
||||||
|
tests-json-pfad))
|
||||||
|
(ssg-end)
|
||||||
|
(princ)
|
||||||
|
)
|
||||||
|
(progn
|
||||||
|
(setq testfaelle (omni:load-json tests-json-pfad))
|
||||||
|
(if (null testfaelle)
|
||||||
|
(progn
|
||||||
|
(princ "\n[TEST_OMNIFLO] FEHLER: Testdaten konnten nicht geladen werden.")
|
||||||
|
(ssg-end)
|
||||||
|
(princ)
|
||||||
|
)
|
||||||
|
(progn
|
||||||
|
(princ "\n================================================================")
|
||||||
|
(princ "\n TEST_OMNIFLO_EXPORT")
|
||||||
|
(princ (strcat "\n " (itoa (length testfaelle)) " Testfaelle geladen"))
|
||||||
|
(princ "\n================================================================")
|
||||||
|
|
||||||
|
;; Alle Bloecke einfuegen
|
||||||
|
(setq x-pos 0.0)
|
||||||
|
(setq x-schritt 200.0)
|
||||||
|
(setq anzahl-ok 0)
|
||||||
|
(setq anzahl-fehler 0)
|
||||||
|
(setq idx 0)
|
||||||
|
|
||||||
|
(foreach eintrag testfaelle
|
||||||
|
(setq idx (1+ idx))
|
||||||
|
(setq sivasnr (omni:val eintrag "sivasnr"))
|
||||||
|
(setq hoehe-str (omni:val eintrag "hoehe"))
|
||||||
|
(if (null hoehe-str) (setq hoehe-str "2000"))
|
||||||
|
(if (numberp hoehe-str)
|
||||||
|
(setq hoehe-str (rtos hoehe-str 2 0))
|
||||||
|
)
|
||||||
|
(setq drehung-str (omni:val eintrag "drehung"))
|
||||||
|
(if (null drehung-str) (setq drehung-str "0"))
|
||||||
|
(if (numberp drehung-str)
|
||||||
|
(setq drehung-str (rtos drehung-str 2 1))
|
||||||
|
)
|
||||||
|
|
||||||
|
(setq insert-pt (list x-pos 0.0 (atof hoehe-str)))
|
||||||
|
|
||||||
|
(princ (strcat "\n " (itoa idx) ". "
|
||||||
|
(or (omni:val eintrag "description") sivasnr)
|
||||||
|
" -> (" (rtos x-pos 2 0) ", 0, " hoehe-str ")"))
|
||||||
|
|
||||||
|
(if (omni:test-insert sivasnr insert-pt hoehe-str drehung-str)
|
||||||
|
(setq anzahl-ok (1+ anzahl-ok))
|
||||||
|
(setq anzahl-fehler (1+ anzahl-fehler))
|
||||||
|
)
|
||||||
|
|
||||||
|
(setq x-pos (+ x-pos x-schritt))
|
||||||
|
)
|
||||||
|
|
||||||
|
;; Zusammenfassung
|
||||||
|
(princ "\n================================================================")
|
||||||
|
(princ (strcat "\n Eingefuegt: " (itoa anzahl-ok)
|
||||||
|
" OK, " (itoa anzahl-fehler) " Fehler"))
|
||||||
|
(princ "\n================================================================")
|
||||||
|
|
||||||
|
;; CSV-Export nach tests/output/
|
||||||
|
(setq tests-out-dir
|
||||||
|
(strcat (getenv "DXFMAKRO") "/tests/output"))
|
||||||
|
(vl-mkdir tests-out-dir)
|
||||||
|
|
||||||
|
(setq old-results (getenv "DXFM_RESULTS"))
|
||||||
|
(setenv "DXFM_RESULTS" tests-out-dir)
|
||||||
|
|
||||||
|
(princ "\n[TEST_OMNIFLO] Starte OMNI_EXPORT -> tests/output/omniflo_export.csv")
|
||||||
|
(c:OMNI_EXPORT)
|
||||||
|
|
||||||
|
(setenv "DXFM_RESULTS" (if old-results old-results ""))
|
||||||
|
|
||||||
|
(ssg-end)
|
||||||
|
|
||||||
|
(princ "\n================================================================")
|
||||||
|
(princ "\n TEST_OMNIFLO_EXPORT abgeschlossen.")
|
||||||
|
(princ (strcat "\n CSV: " tests-out-dir "/omniflo_export.csv"))
|
||||||
|
(princ "\n================================================================")
|
||||||
|
(princ)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
@@ -0,0 +1,350 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
test_omniflo.py - Validiert Omniflo Bogen/Weiche Export.
|
||||||
|
|
||||||
|
Prueft:
|
||||||
|
1. CSV-Inhalt gegen Testdefinitionen (Unit-Test, ohne BricsCAD)
|
||||||
|
2. Merkmale-Werte gegen JSON-Katalog
|
||||||
|
3. Korrekte Anzahl und Reihenfolge der Elemente
|
||||||
|
4. Integrationstest: liest CSV aus BricsCAD-Lauf (falls vorhanden)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import csv
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
# export_csv aus lib/ importieren
|
||||||
|
_LIB_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "lib")
|
||||||
|
sys.path.insert(0, _LIB_DIR)
|
||||||
|
|
||||||
|
from export_csv import (
|
||||||
|
build_lookup, process_blocks, build_bogen_merkmale,
|
||||||
|
build_weiche_merkmale, load_json
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Hilfsfunktionen
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def _data_dir():
|
||||||
|
base = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
return os.path.join(base, "data")
|
||||||
|
|
||||||
|
|
||||||
|
def _testdata_dir():
|
||||||
|
return os.getenv("DXFM_TESTDATA",
|
||||||
|
os.path.join(os.path.dirname(os.path.abspath(__file__)), "testdata"))
|
||||||
|
|
||||||
|
|
||||||
|
def _output_dir():
|
||||||
|
return os.getenv("DXFM_TESTOUT",
|
||||||
|
os.path.join(os.path.dirname(os.path.abspath(__file__)), "output"))
|
||||||
|
|
||||||
|
|
||||||
|
def _make_block(block_name, x=0.0, y=0.0, z=0.0, rotation=0.0, hoehe=None, drehung=None):
|
||||||
|
"""Erzeugt einen Mock-Block wie ihn export.lsp (csv:block-to-json) schreibt."""
|
||||||
|
attribs = {}
|
||||||
|
if hoehe is not None:
|
||||||
|
attribs["HOEHE"] = str(int(hoehe))
|
||||||
|
if drehung is not None:
|
||||||
|
attribs["DREHUNG"] = str(drehung)
|
||||||
|
return {
|
||||||
|
"block_name": block_name,
|
||||||
|
"x": x, "y": y, "z": z,
|
||||||
|
"rotation": rotation,
|
||||||
|
"attribs": attribs,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _load_omniflo_tests():
|
||||||
|
path = os.path.join(_testdata_dir(), "omniflo_tests.json")
|
||||||
|
with open(path, "r", encoding="utf-8") as f:
|
||||||
|
return json.load(f)
|
||||||
|
|
||||||
|
|
||||||
|
def _load_lookup():
|
||||||
|
data_dir = _data_dir()
|
||||||
|
boegen_path = os.path.join(data_dir, "json", "omniflo_boegen.json")
|
||||||
|
weichen_path = os.path.join(data_dir, "json", "omniflo_weichen.json")
|
||||||
|
boegen = load_json(boegen_path) if os.path.exists(boegen_path) else []
|
||||||
|
weichen = load_json(weichen_path) if os.path.exists(weichen_path) else []
|
||||||
|
return build_lookup(boegen, weichen)
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Unit-Tests: process_blocks mit Mock-Daten
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class TestOmnifloExportUnit:
|
||||||
|
"""Unit-Tests fuer export_csv.py mit synthetischen Mock-Bloecken."""
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def setup(self):
|
||||||
|
self.tests = _load_omniflo_tests()
|
||||||
|
self.lookup = _load_lookup()
|
||||||
|
# Mock-Bloecke aus Testfaellen erzeugen
|
||||||
|
self.blocks = []
|
||||||
|
for i, tc in enumerate(self.tests):
|
||||||
|
self.blocks.append(_make_block(
|
||||||
|
block_name=tc["sivasnr"],
|
||||||
|
x=float(i) * 200.0,
|
||||||
|
y=0.0,
|
||||||
|
z=float(tc["hoehe"]),
|
||||||
|
rotation=float(tc["drehung"]),
|
||||||
|
hoehe=float(tc["hoehe"]),
|
||||||
|
drehung=float(tc["drehung"]),
|
||||||
|
))
|
||||||
|
self.items = process_blocks(self.blocks, self.lookup)
|
||||||
|
|
||||||
|
def test_item_count_matches_testcases(self):
|
||||||
|
"""Anzahl exportierter Elemente muss Anzahl Testfaelle entsprechen."""
|
||||||
|
assert len(self.items) == len(self.tests), (
|
||||||
|
f"Erwartet {len(self.tests)} Elemente, erhalten {len(self.items)}"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_numbering_starts_at_one(self):
|
||||||
|
"""Element-Nummerierung muss bei 1 beginnen."""
|
||||||
|
assert self.items[0]["nr"] == 1, (
|
||||||
|
f"Erstes Element: nr={self.items[0]['nr']}, erwartet 1"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_numbering_is_consecutive(self):
|
||||||
|
"""Element-Nummern muessen lueckenlos aufsteigen."""
|
||||||
|
for i, item in enumerate(self.items):
|
||||||
|
assert item["nr"] == i + 1, (
|
||||||
|
f"Element {i}: nr={item['nr']}, erwartet {i + 1}"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_bogen_teileart(self):
|
||||||
|
"""Boegen muessen TeileArt 'Omniflo Kurve' haben."""
|
||||||
|
bogen_tests = [tc for tc in self.tests if tc["type"] == "bogen"]
|
||||||
|
bogen_items = [it for it in self.items if it["teileart"] == "Omniflo Kurve"]
|
||||||
|
assert len(bogen_items) == len(bogen_tests), (
|
||||||
|
f"Erwartet {len(bogen_tests)} Boegen, erhalten {len(bogen_items)}"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_weiche_teileart(self):
|
||||||
|
"""Weichen muessen TeileArt 'Omniflo Weiche' haben."""
|
||||||
|
weiche_tests = [tc for tc in self.tests if tc["type"] == "weiche"]
|
||||||
|
weiche_items = [it for it in self.items if it["teileart"] == "Omniflo Weiche"]
|
||||||
|
assert len(weiche_items) == len(weiche_tests), (
|
||||||
|
f"Erwartet {len(weiche_tests)} Weichen, erhalten {len(weiche_items)}"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_bogen_merkmale_felder(self):
|
||||||
|
"""Boegen-Merkmale muessen alle Pflichtfelder enthalten."""
|
||||||
|
required = {"Kurvenwinkel", "Radius", "Höhe", "Drehung", "SivasNummer"}
|
||||||
|
for item in self.items:
|
||||||
|
if item["teileart"] != "Omniflo Kurve":
|
||||||
|
continue
|
||||||
|
merkmale = item["merkmale"]
|
||||||
|
missing = required - set(merkmale.keys())
|
||||||
|
assert not missing, (
|
||||||
|
f"{item['bezeichnung']}: Fehlende Felder: {missing}"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_weiche_merkmale_felder(self):
|
||||||
|
"""Weichen-Merkmale muessen alle Pflichtfelder enthalten."""
|
||||||
|
required = {"Weichentyp", "Richtung", "Weichenwinkel",
|
||||||
|
"Höhe", "Drehung", "Antrieb Kurve", "SivasNummer"}
|
||||||
|
for item in self.items:
|
||||||
|
if item["teileart"] != "Omniflo Weiche":
|
||||||
|
continue
|
||||||
|
merkmale = item["merkmale"]
|
||||||
|
missing = required - set(merkmale.keys())
|
||||||
|
assert not missing, (
|
||||||
|
f"{item['bezeichnung']}: Fehlende Felder: {missing}"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_bogen_merkmale_werte(self):
|
||||||
|
"""Bogen-Merkmale muessen mit JSON-Katalog uebereinstimmen."""
|
||||||
|
for tc, item in zip(
|
||||||
|
[t for t in self.tests if t["type"] == "bogen"],
|
||||||
|
[it for it in self.items if it["teileart"] == "Omniflo Kurve"]
|
||||||
|
):
|
||||||
|
sivasnr = tc["sivasnr"]
|
||||||
|
assert sivasnr in self.lookup, f"SivasNr {sivasnr} nicht im Katalog"
|
||||||
|
_, eintrag = self.lookup[sivasnr]
|
||||||
|
m = item["merkmale"]
|
||||||
|
assert m["Kurvenwinkel"] == float(eintrag["KurvenWinkel"]), (
|
||||||
|
f"{sivasnr}: Kurvenwinkel erwartet={eintrag['KurvenWinkel']}, "
|
||||||
|
f"erhalten={m['Kurvenwinkel']}"
|
||||||
|
)
|
||||||
|
assert m["Radius"] == float(eintrag["Radius"]), (
|
||||||
|
f"{sivasnr}: Radius erwartet={eintrag['Radius']}, "
|
||||||
|
f"erhalten={m['Radius']}"
|
||||||
|
)
|
||||||
|
assert m["Höhe"] == str(int(tc["hoehe"])), (
|
||||||
|
f"{sivasnr}: Hoehe erwartet={tc['hoehe']}, erhalten={m['Höhe']}"
|
||||||
|
)
|
||||||
|
assert m["SivasNummer"] == str(eintrag["Sivasnr"]), (
|
||||||
|
f"{sivasnr}: SivasNummer erwartet={eintrag['Sivasnr']}, "
|
||||||
|
f"erhalten={m['SivasNummer']}"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_weiche_merkmale_werte(self):
|
||||||
|
"""Weichen-Merkmale muessen mit JSON-Katalog uebereinstimmen."""
|
||||||
|
for tc, item in zip(
|
||||||
|
[t for t in self.tests if t["type"] == "weiche"],
|
||||||
|
[it for it in self.items if it["teileart"] == "Omniflo Weiche"]
|
||||||
|
):
|
||||||
|
sivasnr = tc["sivasnr"]
|
||||||
|
assert sivasnr in self.lookup, f"SivasNr {sivasnr} nicht im Katalog"
|
||||||
|
_, eintrag = self.lookup[sivasnr]
|
||||||
|
m = item["merkmale"]
|
||||||
|
assert m["Weichentyp"] == eintrag["WeichenTyp"], (
|
||||||
|
f"{sivasnr}: Weichentyp erwartet={eintrag['WeichenTyp']}, "
|
||||||
|
f"erhalten={m['Weichentyp']}"
|
||||||
|
)
|
||||||
|
assert m["Weichenwinkel"] == float(eintrag["KurvenWinkel"]), (
|
||||||
|
f"{sivasnr}: Weichenwinkel erwartet={eintrag['KurvenWinkel']}, "
|
||||||
|
f"erhalten={m['Weichenwinkel']}"
|
||||||
|
)
|
||||||
|
assert m["Höhe"] == str(int(tc["hoehe"])), (
|
||||||
|
f"{sivasnr}: Hoehe erwartet={tc['hoehe']}, erhalten={m['Höhe']}"
|
||||||
|
)
|
||||||
|
assert m["SivasNummer"] == str(eintrag["Sivasnr"]), (
|
||||||
|
f"{sivasnr}: SivasNummer erwartet={eintrag['Sivasnr']}, "
|
||||||
|
f"erhalten={m['SivasNummer']}"
|
||||||
|
)
|
||||||
|
expected_antrieb = eintrag.get("SivasnrTEF") is not None
|
||||||
|
assert m["Antrieb Kurve"] == expected_antrieb, (
|
||||||
|
f"{sivasnr}: Antrieb Kurve erwartet={expected_antrieb}, "
|
||||||
|
f"erhalten={m['Antrieb Kurve']}"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_bogen_hoehe_als_string(self):
|
||||||
|
"""Bogen-Hoehe muss als String vorliegen (z.B. '2000', nicht 2000)."""
|
||||||
|
for item in self.items:
|
||||||
|
if item["teileart"] != "Omniflo Kurve":
|
||||||
|
continue
|
||||||
|
assert isinstance(item["merkmale"]["Höhe"], str), (
|
||||||
|
f"{item['bezeichnung']}: Hoehe muss String sein, "
|
||||||
|
f"ist {type(item['merkmale']['Höhe'])}"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_weiche_hoehe_als_string(self):
|
||||||
|
"""Weichen-Hoehe muss als String vorliegen."""
|
||||||
|
for item in self.items:
|
||||||
|
if item["teileart"] != "Omniflo Weiche":
|
||||||
|
continue
|
||||||
|
assert isinstance(item["merkmale"]["Höhe"], str), (
|
||||||
|
f"{item['bezeichnung']}: Hoehe muss String sein"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_kurvenwinkel_als_float(self):
|
||||||
|
"""Kurvenwinkel muss als Float vorliegen (90.0, nicht 90)."""
|
||||||
|
for item in self.items:
|
||||||
|
if item["teileart"] == "Omniflo Kurve":
|
||||||
|
assert isinstance(item["merkmale"]["Kurvenwinkel"], float), (
|
||||||
|
f"{item['bezeichnung']}: Kurvenwinkel muss float sein"
|
||||||
|
)
|
||||||
|
elif item["teileart"] == "Omniflo Weiche":
|
||||||
|
assert isinstance(item["merkmale"]["Weichenwinkel"], float), (
|
||||||
|
f"{item['bezeichnung']}: Weichenwinkel muss float sein"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_weiche_alle_typen_vorhanden(self):
|
||||||
|
"""Test muss alle Weichen-Typen aus dem Katalog abdecken."""
|
||||||
|
typen_in_tests = {
|
||||||
|
self.lookup[tc["sivasnr"]][1].get("WeichenTyp")
|
||||||
|
for tc in self.tests
|
||||||
|
if tc["type"] == "weiche" and tc["sivasnr"] in self.lookup
|
||||||
|
}
|
||||||
|
# Mindestens Einzelweiche, Doppelweiche, Dreiwegeweiche muessen vorhanden sein
|
||||||
|
for pflicht in ("Einzelweiche", "Doppelweiche", "Dreiwegeweiche"):
|
||||||
|
assert pflicht in typen_in_tests, (
|
||||||
|
f"Weichen-Typ '{pflicht}' fehlt in Testfaellen"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Integrations-Tests: CSV aus BricsCAD-Lauf validieren
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class TestOmnifloExportCSV:
|
||||||
|
"""Validiert CSV-Datei aus dem BricsCAD-Lauf (c:TEST_OMNIFLO_EXPORT)."""
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def setup(self):
|
||||||
|
csv_path = os.path.join(_output_dir(), "omniflo_export.csv")
|
||||||
|
if not os.path.exists(csv_path):
|
||||||
|
pytest.skip(
|
||||||
|
"omniflo_export.csv nicht vorhanden - "
|
||||||
|
"TEST_OMNIFLO_EXPORT in BricsCAD ausfuehren"
|
||||||
|
)
|
||||||
|
self.csv_path = csv_path
|
||||||
|
self.rows = []
|
||||||
|
with open(csv_path, "r", encoding="utf-8") as f:
|
||||||
|
reader = csv.reader(f, delimiter=";")
|
||||||
|
self.header = next(reader)
|
||||||
|
for row in reader:
|
||||||
|
self.rows.append(row)
|
||||||
|
|
||||||
|
def test_header_felder(self):
|
||||||
|
"""CSV-Header muss korrekte Spaltenbezeichnungen haben."""
|
||||||
|
assert self.header[0] == "Elementnummer"
|
||||||
|
assert self.header[1] == "TeileArt"
|
||||||
|
assert self.header[2] == "TeileId"
|
||||||
|
assert self.header[3] == "Bezeichnung"
|
||||||
|
assert self.header[4] == "Anzahl"
|
||||||
|
assert self.header[5] == "Merkmale"
|
||||||
|
|
||||||
|
def test_mindest_anzahl_zeilen(self):
|
||||||
|
"""CSV muss mindestens so viele Zeilen haben wie Testfaelle."""
|
||||||
|
tests = _load_omniflo_tests()
|
||||||
|
assert len(self.rows) >= len(tests), (
|
||||||
|
f"CSV hat {len(self.rows)} Zeilen, "
|
||||||
|
f"erwartet mind. {len(tests)}"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_anzahl_spalte_ist_eins(self):
|
||||||
|
"""Anzahl-Spalte muss fuer alle Zeilen '1' sein."""
|
||||||
|
for i, row in enumerate(self.rows):
|
||||||
|
if len(row) < 5:
|
||||||
|
continue
|
||||||
|
assert row[4] == "1", (
|
||||||
|
f"Zeile {i + 2}: Anzahl={row[4]}, erwartet 1"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_merkmale_sind_valides_json(self):
|
||||||
|
"""Merkmale-Spalte muss valides JSON enthalten."""
|
||||||
|
for i, row in enumerate(self.rows):
|
||||||
|
if len(row) < 6:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
json.loads(row[5])
|
||||||
|
except json.JSONDecodeError as e:
|
||||||
|
pytest.fail(
|
||||||
|
f"Zeile {i + 2}: Merkmale ist kein valides JSON: {e}\n"
|
||||||
|
f" Inhalt: {row[5][:100]}"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_bogen_merkmale_felder_in_csv(self):
|
||||||
|
"""Bogen-Zeilen muessen Pflichtfelder in Merkmale haben."""
|
||||||
|
required = {"Kurvenwinkel", "Radius", "Höhe", "Drehung", "SivasNummer"}
|
||||||
|
for i, row in enumerate(self.rows):
|
||||||
|
if len(row) < 6 or row[1].strip('"') != "Omniflo Kurve":
|
||||||
|
continue
|
||||||
|
merkmale = json.loads(row[5])
|
||||||
|
missing = required - set(merkmale.keys())
|
||||||
|
assert not missing, (
|
||||||
|
f"Zeile {i + 2}: Fehlende Bogen-Felder: {missing}"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_weiche_merkmale_felder_in_csv(self):
|
||||||
|
"""Weichen-Zeilen muessen Pflichtfelder in Merkmale haben."""
|
||||||
|
required = {"Weichentyp", "Richtung", "Weichenwinkel",
|
||||||
|
"Höhe", "Drehung", "Antrieb Kurve", "SivasNummer"}
|
||||||
|
for i, row in enumerate(self.rows):
|
||||||
|
if len(row) < 6 or row[1].strip('"') != "Omniflo Weiche":
|
||||||
|
continue
|
||||||
|
merkmale = json.loads(row[5])
|
||||||
|
missing = required - set(merkmale.keys())
|
||||||
|
assert not missing, (
|
||||||
|
f"Zeile {i + 2}: Fehlende Weichen-Felder: {missing}"
|
||||||
|
)
|
||||||
Vendored
+114
@@ -0,0 +1,114 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "OF_Bogen_225_R550",
|
||||||
|
"type": "bogen",
|
||||||
|
"sivasnr": "821104025",
|
||||||
|
"hoehe": 2000,
|
||||||
|
"drehung": 0.0,
|
||||||
|
"description": "Omniflo Bogen 22,5 Grad R550"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "OF_Bogen_45_R400",
|
||||||
|
"type": "bogen",
|
||||||
|
"sivasnr": "821104021",
|
||||||
|
"hoehe": 2500,
|
||||||
|
"drehung": 0.0,
|
||||||
|
"description": "Omniflo Bogen 45 Grad R400"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "OF_Bogen_675_R400",
|
||||||
|
"type": "bogen",
|
||||||
|
"sivasnr": "821104024",
|
||||||
|
"hoehe": 3000,
|
||||||
|
"drehung": 0.0,
|
||||||
|
"description": "Omniflo Bogen 67,5 Grad R400"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "OF_Bogen_90_R630",
|
||||||
|
"type": "bogen",
|
||||||
|
"sivasnr": "821104033",
|
||||||
|
"hoehe": 3500,
|
||||||
|
"drehung": 0.0,
|
||||||
|
"description": "Omniflo Bogen 90 Grad R630"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "OF_Bogen_180_R650",
|
||||||
|
"type": "bogen",
|
||||||
|
"sivasnr": "821104043",
|
||||||
|
"hoehe": 4000,
|
||||||
|
"drehung": 0.0,
|
||||||
|
"description": "Omniflo Bogen 180 Grad R650"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "OF_Weiche_Einzel_45L",
|
||||||
|
"type": "weiche",
|
||||||
|
"sivasnr": "834372001",
|
||||||
|
"hoehe": 2000,
|
||||||
|
"drehung": 0.0,
|
||||||
|
"description": "Omniflo Einzelweiche 45 Grad Links"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "OF_Weiche_Einzel_90L",
|
||||||
|
"type": "weiche",
|
||||||
|
"sivasnr": "834372021",
|
||||||
|
"hoehe": 2500,
|
||||||
|
"drehung": 0.0,
|
||||||
|
"description": "Omniflo Einzelweiche 90 Grad Links"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "OF_Weiche_Doppel_45",
|
||||||
|
"type": "weiche",
|
||||||
|
"sivasnr": "834372100",
|
||||||
|
"hoehe": 3000,
|
||||||
|
"drehung": 0.0,
|
||||||
|
"description": "Omniflo Doppelweiche 45 Grad"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "OF_Weiche_Doppel_90",
|
||||||
|
"type": "weiche",
|
||||||
|
"sivasnr": "834372109",
|
||||||
|
"hoehe": 3500,
|
||||||
|
"drehung": 0.0,
|
||||||
|
"description": "Omniflo Doppelweiche 90 Grad"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "OF_Weiche_Dreiwege_45",
|
||||||
|
"type": "weiche",
|
||||||
|
"sivasnr": "834372200",
|
||||||
|
"hoehe": 4000,
|
||||||
|
"drehung": 0.0,
|
||||||
|
"description": "Omniflo Dreiwegeweiche 45 Grad"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "OF_Weiche_Dreifach_90",
|
||||||
|
"type": "weiche",
|
||||||
|
"sivasnr": "834372404",
|
||||||
|
"hoehe": 2000,
|
||||||
|
"drehung": 0.0,
|
||||||
|
"description": "Omniflo Dreifachweiche 90 Grad"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "OF_Weiche_Delta_90",
|
||||||
|
"type": "weiche",
|
||||||
|
"sivasnr": "834372401",
|
||||||
|
"hoehe": 2500,
|
||||||
|
"drehung": 0.0,
|
||||||
|
"description": "Omniflo Deltaweiche 90 Grad"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "OF_Weiche_Stern",
|
||||||
|
"type": "weiche",
|
||||||
|
"sivasnr": "834372420",
|
||||||
|
"hoehe": 3000,
|
||||||
|
"drehung": 0.0,
|
||||||
|
"description": "Omniflo Sternweiche"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "OF_Weichenkoerper_L",
|
||||||
|
"type": "weiche",
|
||||||
|
"sivasnr": "834342011",
|
||||||
|
"hoehe": 3500,
|
||||||
|
"drehung": 0.0,
|
||||||
|
"description": "Omniflo Weichenkoerper Links"
|
||||||
|
}
|
||||||
|
]
|
||||||
Reference in New Issue
Block a user