[FIX] Export: Schnittpunkte zwischen Kreiseln werden erkannt und Weichen entsprechend gezählt und als Teil mit Merkmalen im Export befüllt - nur Kreisel mit gleicher Höhe können einen Schnittpunkt für Weiche bilden - Funktion der Weichenzählung manuell aufrufbar; [FIX] Eckrad nun korrekt angelegt und exportiert
This commit is contained in:
@@ -1524,5 +1524,381 @@
|
||||
(princ)
|
||||
)
|
||||
|
||||
|
||||
;; ============================================================
|
||||
;; TEIL 5: BERUEHRPUNKTE / WEICHEN ZWISCHEN KREISELN UND ECKRAEDERN
|
||||
;; ============================================================
|
||||
;; Ermittelt, wo sich Kreisel (KREISEL_n) und Eckraeder (ECKRAD_n) gleicher
|
||||
;; Hoehe beruehren - dort sitzt eine ILS-Weiche. Gerechnet wird NUR aus den
|
||||
;; Blockparametern (Einfuegepunkt, Drehung, ABSTAND), nicht aus der
|
||||
;; gezeichneten Geometrie - dasselbe Modell wie draw-module:
|
||||
;; Kreisel: Rad AN8 bei P+R(r,0), Rad SP8 bei P+R(r+abstand,0), Laufprofile
|
||||
;; = die beiden Tangenten bei lokal y=+-r. Frei ist je Rad nur der
|
||||
;; aeussere Halbkreis (die "drei freien Seiten": vorn + beide
|
||||
;; Flanken), die innere Haelfte liegt zwischen den Laufprofilen.
|
||||
;; Eckrad: Vollkreis um P, ganz frei, kein Laufprofil.
|
||||
;; Paar-Logik:
|
||||
;; - Mindestabstand der Achsen (Kapsel-Modell) < 2r - tol -> KOLLISION
|
||||
;; (Rad ragt hinein, Laufprofile kreuzen sich) - keine Weiche.
|
||||
;; - Sonst je Rad: Rad/Rad mit |Abstand - 2r| <= tol bzw. Rad/Laufprofil
|
||||
;; mit |Lot - r| <= tol, Beruehrpunkt auf einer freien Radseite ->
|
||||
;; BERUEHRUNG ("Kreis/Kreis" bzw. "Kreis/Tangente", Namen wie im Python-
|
||||
;; Export export_neighbors.compute_kreisel_touch_switches).
|
||||
;; - Beruehren sich nur Laufprofile (Kreisel liegen Seite an Seite) ->
|
||||
;; KOLLISION "Tangente/Tangente".
|
||||
;; Die reinen Kerne (kreisel-bp-element/-paar/-berechnen) laufen ohne
|
||||
;; Zeichnung und sind in tests/test_unit.lsp getestet.
|
||||
|
||||
(setq *kreisel-bp-app* "SSG_KR_WEICHE")
|
||||
|
||||
;; --- 2D-Vektorhelfer (Punkte als (x y)) ---
|
||||
(defun kreisel-bp-plus (a b) (list (+ (car a) (car b)) (+ (cadr a) (cadr b))))
|
||||
(defun kreisel-bp-minus (a b) (list (- (car a) (car b)) (- (cadr a) (cadr b))))
|
||||
(defun kreisel-bp-mal (a s) (list (* (car a) s) (* (cadr a) s)))
|
||||
(defun kreisel-bp-dot (a b) (+ (* (car a) (car b)) (* (cadr a) (cadr b))))
|
||||
(defun kreisel-bp-abst (a b) (distance (list (car a) (cadr a)) (list (car b) (cadr b))))
|
||||
(defun kreisel-bp-mitte (a b) (kreisel-bp-mal (kreisel-bp-plus a b) 0.5))
|
||||
|
||||
;; Element-Record aus Blockparametern (reiner Kern).
|
||||
;; typ "KREISEL" oder "ECKRAD"
|
||||
;; p Einfuegepunkt (x y [z]) - Kreisel: AN-seitige Tangente, Eckrad: Mitte
|
||||
;; z Hoehe (Einfuege-Z)
|
||||
;; rot Drehung in Grad
|
||||
;; abstand Achsabstand AN8->SP8 (Kreisel), beim Eckrad ignoriert
|
||||
;; r Radradius
|
||||
;; id/handle/name nur zur Ausgabe/Zuordnung
|
||||
;; Rueckgabe: alist mit "raeder" ((label mitte freie-richtung|nil) ...),
|
||||
;; "profile" ((p1 p2) (p1 p2)) und "achse" (a b) fuer den Kapsel-Abstand.
|
||||
(defun kreisel-bp-element (typ p z rot abstand r id handle name / u n p2 a b)
|
||||
(setq u (list (cos (* pi (/ rot 180.0))) (sin (* pi (/ rot 180.0))))
|
||||
n (list (- (cadr u)) (car u))
|
||||
p2 (list (car p) (cadr p)))
|
||||
(if (= typ "KREISEL")
|
||||
(progn
|
||||
(setq a (kreisel-bp-plus p2 (kreisel-bp-mal u r))
|
||||
b (kreisel-bp-plus p2 (kreisel-bp-mal u (+ r abstand))))
|
||||
(list (cons "typ" typ) (cons "id" id) (cons "handle" handle) (cons "name" name)
|
||||
(cons "z" z) (cons "r" r)
|
||||
(cons "achse" (list a b))
|
||||
(cons "raeder" (list (list "AN8" a (kreisel-bp-mal u -1.0))
|
||||
(list "SP8" b u)))
|
||||
(cons "profile" (list (list (kreisel-bp-plus a (kreisel-bp-mal n r))
|
||||
(kreisel-bp-plus b (kreisel-bp-mal n r)))
|
||||
(list (kreisel-bp-minus a (kreisel-bp-mal n r))
|
||||
(kreisel-bp-minus b (kreisel-bp-mal n r)))))))
|
||||
(list (cons "typ" typ) (cons "id" id) (cons "handle" handle) (cons "name" name)
|
||||
(cons "z" z) (cons "r" r)
|
||||
(cons "achse" (list p2 p2))
|
||||
(cons "raeder" (list (list "ECKRAD" p2 nil)))
|
||||
(cons "profile" nil)))
|
||||
)
|
||||
|
||||
(defun kreisel-bp-get (key elem) (cdr (assoc key elem)))
|
||||
|
||||
;; Naechstgelegene Punkte zweier Strecken [p1,q1] und [p2,q2] (Ericson,
|
||||
;; Real-Time Collision Detection - wie export_neighbors._closest_pts_segments).
|
||||
;; Rueckgabe (c1 c2).
|
||||
(defun kreisel-bp-naechste-punkte (p1 q1 p2 q2 / eps d1 d2 rr a e f c b den s tt)
|
||||
(setq eps 1e-9
|
||||
d1 (kreisel-bp-minus q1 p1)
|
||||
d2 (kreisel-bp-minus q2 p2)
|
||||
rr (kreisel-bp-minus p1 p2)
|
||||
a (kreisel-bp-dot d1 d1)
|
||||
e (kreisel-bp-dot d2 d2)
|
||||
f (kreisel-bp-dot d2 rr))
|
||||
(cond
|
||||
((and (<= a eps) (<= e eps)) (setq s 0.0 tt 0.0))
|
||||
((<= a eps) (setq s 0.0 tt (max 0.0 (min 1.0 (/ f e)))))
|
||||
(t
|
||||
(setq c (kreisel-bp-dot d1 rr))
|
||||
(if (<= e eps)
|
||||
(setq tt 0.0 s (max 0.0 (min 1.0 (/ (- c) a))))
|
||||
(progn
|
||||
(setq b (kreisel-bp-dot d1 d2)
|
||||
den (- (* a e) (* b b)))
|
||||
(setq s (if (> den eps) (max 0.0 (min 1.0 (/ (- (* b f) (* c e)) den))) 0.0))
|
||||
(setq tt (/ (+ (* b s) f) e))
|
||||
(cond
|
||||
((< tt 0.0) (setq tt 0.0 s (max 0.0 (min 1.0 (/ (- c) a)))))
|
||||
((> tt 1.0) (setq tt 1.0 s (max 0.0 (min 1.0 (/ (- b c) a)))))
|
||||
)
|
||||
)
|
||||
))
|
||||
)
|
||||
(list (kreisel-bp-plus p1 (kreisel-bp-mal d1 s))
|
||||
(kreisel-bp-plus p2 (kreisel-bp-mal d2 tt)))
|
||||
)
|
||||
|
||||
;; Liegt Punkt pt auf der freien Seite des Rades (label mitte richtung)?
|
||||
;; Richtung nil = Vollkreis (Eckrad). Die Flanken (90 Grad) zaehlen mit.
|
||||
(defun kreisel-bp-frei-p (rad pt tol)
|
||||
(or (null (caddr rad))
|
||||
(>= (kreisel-bp-dot (kreisel-bp-minus pt (cadr rad)) (caddr rad)) (- tol)))
|
||||
)
|
||||
|
||||
;; Liegt pt genau auf einer Flanke (90 Grad zur Achse) eines Kreiselrades?
|
||||
;; Dort beginnt das eigene Laufprofil - eine Beruehrung NUR an der Flanke
|
||||
;; bedeutet parallel aneinanderliegende Kreisel, keine Weiche.
|
||||
(defun kreisel-bp-flanke-p (rad pt tol)
|
||||
(and (caddr rad)
|
||||
(<= (abs (kreisel-bp-dot (kreisel-bp-minus pt (cadr rad)) (caddr rad))) tol))
|
||||
)
|
||||
|
||||
;; Lotfusspunkt von c auf die Strecke (p1 p2). Rueckgabe (t fusspunkt), t
|
||||
;; unbegrenzt (0 = p1, 1 = p2).
|
||||
(defun kreisel-bp-lot (c p1 p2 / d l2 tt)
|
||||
(setq d (kreisel-bp-minus p2 p1)
|
||||
l2 (kreisel-bp-dot d d))
|
||||
(setq tt (if (> l2 1e-12) (/ (kreisel-bp-dot (kreisel-bp-minus c p1) d) l2) 0.0))
|
||||
(list tt (kreisel-bp-plus p1 (kreisel-bp-mal d tt)))
|
||||
)
|
||||
|
||||
;; Ergebnis-Record (reiner Kern)
|
||||
(defun kreisel-bp-treffer (status art ea eb pt rad-elem rad detail)
|
||||
(list (cons "status" status) (cons "art" art)
|
||||
(cons "a" ea) (cons "b" eb)
|
||||
(cons "p" pt)
|
||||
(cons "z" (/ (+ (kreisel-bp-get "z" ea) (kreisel-bp-get "z" eb)) 2.0))
|
||||
(cons "achse_von" rad-elem)
|
||||
;; Ausrichtung der Weiche: Radiale vom beruehrenden Rad zum Punkt
|
||||
(cons "achse_rot" (if rad (* (/ 180.0 pi) (angle (cadr rad) pt)) 0.0))
|
||||
(cons "detail" detail))
|
||||
)
|
||||
|
||||
;; Alle Beruehrungen eines Rades von ew mit Raedern/Profilen von eo.
|
||||
;; Rueckgabe: Liste von (pt art rad detail).
|
||||
(defun kreisel-bp-rad-kontakte (ew eo tol / r res d pt lot tt l)
|
||||
(setq r (kreisel-bp-get "r" ew))
|
||||
(foreach rad (kreisel-bp-get "raeder" ew)
|
||||
;; Rad/Rad
|
||||
(foreach rad2 (kreisel-bp-get "raeder" eo)
|
||||
(setq d (kreisel-bp-abst (cadr rad) (cadr rad2)))
|
||||
(if (<= (abs (- d (+ r (kreisel-bp-get "r" eo)))) tol)
|
||||
(progn
|
||||
(setq pt (kreisel-bp-mitte (cadr rad) (cadr rad2)))
|
||||
;; Beide Kreiselraeder nur an der Flanke = Kreisel Seite an Seite
|
||||
(if (and (kreisel-bp-frei-p rad pt tol) (kreisel-bp-frei-p rad2 pt tol)
|
||||
(not (and (kreisel-bp-flanke-p rad pt tol)
|
||||
(kreisel-bp-flanke-p rad2 pt tol))))
|
||||
(setq res (cons (list pt "Kreis/Kreis" rad
|
||||
(strcat (car rad) "/" (car rad2)))
|
||||
res))))))
|
||||
;; Rad/Laufprofil
|
||||
(foreach pr (kreisel-bp-get "profile" eo)
|
||||
(setq lot (kreisel-bp-lot (cadr rad) (car pr) (cadr pr))
|
||||
tt (car lot)
|
||||
pt (cadr lot)
|
||||
l (kreisel-bp-abst (car pr) (cadr pr)))
|
||||
(if (and (> l 0.0)
|
||||
(>= tt (- (/ tol l))) (<= tt (+ 1.0 (/ tol l)))
|
||||
(<= (abs (- (kreisel-bp-abst (cadr rad) pt) r)) tol)
|
||||
(kreisel-bp-frei-p rad pt tol)
|
||||
;; Flanke an Laufprofil = Profile liegen parallel aufeinander
|
||||
(not (kreisel-bp-flanke-p rad pt tol)))
|
||||
(setq res (cons (list pt "Kreis/Tangente" rad (strcat (car rad) "/Profil")) res))))
|
||||
)
|
||||
(reverse res)
|
||||
)
|
||||
|
||||
;; Ein Paar pruefen (reiner Kern). Rueckgabe: Liste von Treffer-Records
|
||||
;; (leer = kein Kontakt). Unterschiedliche Hoehe wird VORHER ausgefiltert.
|
||||
(defun kreisel-bp-paar (ea eb tol / ac bc cp dmin soll res kont pt doppelt)
|
||||
(setq ac (kreisel-bp-get "achse" ea)
|
||||
bc (kreisel-bp-get "achse" eb)
|
||||
cp (kreisel-bp-naechste-punkte (car ac) (cadr ac) (car bc) (cadr bc))
|
||||
dmin (kreisel-bp-abst (car cp) (cadr cp))
|
||||
soll (+ (kreisel-bp-get "r" ea) (kreisel-bp-get "r" eb)))
|
||||
(cond
|
||||
;; Weit auseinander - nichts
|
||||
((> dmin (+ soll tol)) nil)
|
||||
;; Ueberschneidung - Kollision, keine Weiche
|
||||
((< dmin (- soll tol))
|
||||
(list (kreisel-bp-treffer "kollision" "Ueberschneidung" ea eb
|
||||
(kreisel-bp-mitte (car cp) (cadr cp)) (kreisel-bp-get "id" ea) nil
|
||||
(strcat "Achsabstand " (rtos dmin 2 1)))))
|
||||
;; Beruehrung innerhalb Toleranz - Kontaktpunkte aufzaehlen
|
||||
(t
|
||||
(foreach k (append
|
||||
(mapcar '(lambda (x) (cons ea x)) (kreisel-bp-rad-kontakte ea eb tol))
|
||||
(mapcar '(lambda (x) (cons eb x)) (kreisel-bp-rad-kontakte eb ea tol)))
|
||||
;; k = (elem pt art rad detail); Dubletten (gleicher Punkt) verwerfen
|
||||
(setq pt (cadr k) doppelt nil)
|
||||
(foreach t2 res
|
||||
(if (<= (kreisel-bp-abst pt (kreisel-bp-get "p" t2)) (+ (* 2.0 tol) 1.0))
|
||||
(setq doppelt T)))
|
||||
(if (not doppelt)
|
||||
(setq res (append res
|
||||
(list (kreisel-bp-treffer "beruehrung" (nth 2 k) ea eb pt
|
||||
(kreisel-bp-get "id" (car k)) (nth 3 k) (nth 4 k)))))))
|
||||
(if res
|
||||
res
|
||||
;; Nur Laufprofile liegen aneinander (Seite an Seite) - keine Weiche
|
||||
(list (kreisel-bp-treffer "kollision" "Tangente/Tangente" ea eb
|
||||
(kreisel-bp-mitte (car cp) (cadr cp)) (kreisel-bp-get "id" ea) nil
|
||||
"Laufprofile liegen aneinander"))))
|
||||
)
|
||||
)
|
||||
|
||||
;; Alle Paare auswerten (reiner Kern).
|
||||
;; elemente = Liste von kreisel-bp-element-Records
|
||||
;; Rueckgabe: (beruehrungen kollisionen)
|
||||
(defun kreisel-bp-berechnen (elemente tol tol-z / rest ea ber kol)
|
||||
(setq rest elemente)
|
||||
(while rest
|
||||
(setq ea (car rest) rest (cdr rest))
|
||||
(foreach eb rest
|
||||
(if (<= (abs (- (kreisel-bp-get "z" ea) (kreisel-bp-get "z" eb))) tol-z)
|
||||
(foreach tr (kreisel-bp-paar ea eb tol)
|
||||
(if (= (kreisel-bp-get "status" tr) "kollision")
|
||||
(setq kol (cons tr kol))
|
||||
(setq ber (cons tr ber)))))))
|
||||
(list (reverse ber) (reverse kol))
|
||||
)
|
||||
|
||||
;; ABSTAND eines Kreisels: Attribut, sonst letzter Token des Blocknamens
|
||||
;; KREISEL_n_TYP_ABSTAND (reiner Kern).
|
||||
(defun kreisel-bp-abstand (attr-wert bname / pos)
|
||||
(cond
|
||||
((and attr-wert (> (atof attr-wert) 0.0)) (atof attr-wert))
|
||||
((setq pos (vl-string-position (ascii "_") bname 0 T))
|
||||
(atof (substr bname (+ pos 2))))
|
||||
(t 0.0))
|
||||
)
|
||||
|
||||
;; Toleranzen aus data/json/component_defaults.json (Sektion kreisel)
|
||||
(defun kreisel-bp-toleranz () (float (ssg-cfg-or "kreisel" "toleranz_beruehrung" 1.0)))
|
||||
(defun kreisel-bp-toleranz-z () (float (ssg-cfg-or "kreisel" "toleranz_hoehe" 1.0)))
|
||||
|
||||
;; Alle KREISEL_n/ECKRAD_n im Modellbereich als Element-Records sammeln.
|
||||
;; Bloecke auf gefrorenen Layern bleiben aussen vor (wie im Export).
|
||||
(defun kreisel-bp-elemente-sammeln ( / ss i ent ed bname typ attribs p r res)
|
||||
(setq r (/ *kreisel-durchmesser* 2.0))
|
||||
(if (setq ss (ssget "_X" '((0 . "INSERT") (2 . "KREISEL_*,ECKRAD_*") (410 . "Model"))))
|
||||
(progn
|
||||
(setq i 0)
|
||||
(while (setq ent (ssname ss i))
|
||||
(setq ed (entget ent)
|
||||
bname (strcase (cdr (assoc 2 ed)))
|
||||
typ (if (wcmatch bname "KREISEL_*") "KREISEL" "ECKRAD"))
|
||||
(if (not (and (car (atoms-family 1 '("SSG-ENT-LAYER-GEFROREN-P")))
|
||||
(ssg-ent-layer-gefroren-p ent)))
|
||||
(progn
|
||||
(setq attribs (ssg-attrib-read ent)
|
||||
p (cdr (assoc 10 ed)))
|
||||
(setq res (cons (kreisel-bp-element typ p (if (caddr p) (caddr p) 0.0)
|
||||
(* (/ 180.0 pi) (cdr (assoc 50 ed)))
|
||||
(if (= typ "KREISEL")
|
||||
(kreisel-bp-abstand (cdr (assoc "ABSTAND" attribs)) bname)
|
||||
0.0)
|
||||
r
|
||||
(cond ((cdr (assoc "ID" attribs))) (""))
|
||||
(cdr (assoc 5 ed))
|
||||
(cond ((cdr (assoc "Bezeichnung" attribs))
|
||||
(if (= (cdr (assoc "Bezeichnung" attribs)) "")
|
||||
bname (cdr (assoc "Bezeichnung" attribs))))
|
||||
(bname)))
|
||||
res))))
|
||||
(setq i (1+ i))
|
||||
)
|
||||
)
|
||||
)
|
||||
(reverse res)
|
||||
)
|
||||
|
||||
;; Einstieg fuer Befehl UND Export: (beruehrungen kollisionen) der Zeichnung
|
||||
(defun kreisel-bp-ermitteln ()
|
||||
(kreisel-bp-berechnen (kreisel-bp-elemente-sammeln)
|
||||
(kreisel-bp-toleranz) (kreisel-bp-toleranz-z))
|
||||
)
|
||||
|
||||
;; Anzeigetext eines Elements: "Kreisel3 (ID 0007)" bzw. ohne ID mit Handle
|
||||
(defun kreisel-bp-elem-text (e)
|
||||
(strcat (kreisel-bp-get "name" e)
|
||||
(if (/= (kreisel-bp-get "id" e) "")
|
||||
(strcat " (ID " (kreisel-bp-get "id" e) ")")
|
||||
(strcat " (#" (kreisel-bp-get "handle" e) ")")))
|
||||
)
|
||||
|
||||
;; Alte Marker (Kreise mit XDATA *kreisel-bp-app*) entfernen. Rueckgabe: Anzahl
|
||||
(defun kreisel-bp-marker-loeschen ( / ss i n)
|
||||
(setq n 0)
|
||||
(if (setq ss (ssget "_X" (list '(0 . "CIRCLE") (list -3 (list *kreisel-bp-app*)))))
|
||||
(progn
|
||||
(setq i 0)
|
||||
(while (< i (sslength ss))
|
||||
(entdel (ssname ss i))
|
||||
(setq i (1+ i) n (1+ n)))))
|
||||
n
|
||||
)
|
||||
|
||||
;; Marker-Kreis fuer einen Treffer zeichnen
|
||||
(defun kreisel-bp-marker (tr lay radius)
|
||||
(if (not (tblsearch "APPID" *kreisel-bp-app*)) (regapp *kreisel-bp-app*))
|
||||
(entmake (list '(0 . "CIRCLE") (cons 8 lay)
|
||||
(list 10 (car (kreisel-bp-get "p" tr)) (cadr (kreisel-bp-get "p" tr))
|
||||
(kreisel-bp-get "z" tr))
|
||||
(cons 40 radius)
|
||||
(list -3 (list *kreisel-bp-app*
|
||||
(cons 1000 (kreisel-bp-get "status" tr))
|
||||
(cons 1000 (kreisel-bp-get "art" tr))))))
|
||||
)
|
||||
|
||||
;; Layer fuer Marker: cfg/layer.cfg [allgemein] key, sonst Rueckfall
|
||||
(defun kreisel-bp-layer (key fallback farbe / lay)
|
||||
(if (null (setq lay (ssg-layer-anlegen key nil)))
|
||||
(progn (ssg-make-layer fallback farbe nil) (setq lay fallback)))
|
||||
lay
|
||||
)
|
||||
|
||||
;; Konsolenzeile fuer einen Treffer
|
||||
(defun kreisel-bp-zeile (key nr tr)
|
||||
(princ (ssg-textf key
|
||||
(list nr
|
||||
(kreisel-bp-elem-text (kreisel-bp-get "a" tr))
|
||||
(kreisel-bp-elem-text (kreisel-bp-get "b" tr))
|
||||
(strcat (kreisel-bp-get "art" tr) ", " (kreisel-bp-get "detail" tr))
|
||||
(rtos (car (kreisel-bp-get "p" tr)) 2 1)
|
||||
(rtos (cadr (kreisel-bp-get "p" tr)) 2 1)
|
||||
(rtos (kreisel-bp-get "z" tr) 2 1))))
|
||||
)
|
||||
|
||||
;; --------------------------------------------
|
||||
;; KREISEL_WEICHEN: Beruehrpunkte (Weichen) und Kollisionen aller Kreisel/
|
||||
;; Eckraeder ermitteln, in der Konsole auflisten und als Kreise markieren.
|
||||
;; Ein erneuter Aufruf ersetzt die Marker des vorigen Laufs.
|
||||
;; --------------------------------------------
|
||||
(defun c:KREISEL_WEICHEN ( / erg ber kol nr lay-w lay-k radius)
|
||||
(ssg-start (ssg-text "kreisel-bp-start") nil)
|
||||
(setq erg (kreisel-bp-ermitteln)
|
||||
ber (car erg)
|
||||
kol (cadr erg))
|
||||
(dbgmsg (strcat "KREISEL_WEICHEN: " (itoa (length ber)) " Beruehrungen, "
|
||||
(itoa (length kol)) " Kollisionen"))
|
||||
(kreisel-bp-marker-loeschen)
|
||||
(princ (ssg-textf "kreisel-bp-summe"
|
||||
(list (itoa (length ber)) (itoa (length kol)) (rtos (kreisel-bp-toleranz) 2 1))))
|
||||
(setq radius (float (ssg-cfg-or "kreisel" "weiche_marker_radius" 50.0)))
|
||||
(if ber
|
||||
(setq lay-w (kreisel-bp-layer "kreisel_weiche" "ZZ_Kreisel_Weichen" "4")))
|
||||
(if kol
|
||||
(setq lay-k (kreisel-bp-layer "kreisel_kollision" "ZZ_Kreisel_Kollision" "1")))
|
||||
(setq nr 0)
|
||||
(foreach tr ber
|
||||
(setq nr (1+ nr))
|
||||
(kreisel-bp-zeile "kreisel-bp-zeile" (itoa nr) tr)
|
||||
(kreisel-bp-marker tr lay-w radius))
|
||||
(setq nr 0)
|
||||
(foreach tr kol
|
||||
(setq nr (1+ nr))
|
||||
(kreisel-bp-zeile "kreisel-bp-kollision" (itoa nr) tr)
|
||||
(kreisel-bp-marker tr lay-k (* 2.0 radius)))
|
||||
(if (or ber kol)
|
||||
(princ (ssg-textf "kreisel-bp-marker"
|
||||
(list (itoa (+ (length ber) (length kol)))
|
||||
(cond (lay-w) (lay-k))))))
|
||||
(ssg-end)
|
||||
(princ)
|
||||
)
|
||||
|
||||
(princ "\n>>> KreiselInsert geladen")
|
||||
(princ)
|
||||
|
||||
@@ -686,6 +686,7 @@ AutoLISP-Implementierung fuer ILS Kreisel und Eckrad. Enthaelt alle Befehle fuer
|
||||
| `c:KreiselLabelHoehe` | Label-Hoehe aendern |
|
||||
| `c:ILS_Eckrad` | Eckrad an Tangentenpunkt einfuegen, Parameter per DCL-Dialog (`eckrad_edit.dcl`; ohne GUI Konsolen-Rueckfall) |
|
||||
| `c:EckradEdit` | Eckrad ueber DCL-Dialog bearbeiten (Bezeichnung, Hoehe, Drehung, Drehrichtung, Geruest; kein Abstand/Typ), Neuaufbau mit gleicher Nummer |
|
||||
| `c:KREISEL_WEICHEN` | Beruehrpunkte (= ILS-Weichen) aller Kreisel/Eckraeder gleicher Hoehe ermitteln: Rad/Rad und Rad/Laufprofil auf der freien Radseite, Toleranz `toleranz_beruehrung`/`toleranz_hoehe` (component_defaults.json). Ueberschneidungen und Seite-an-Seite-Kreisel werden als Kollision gemeldet. Konsolenliste + Kreis-Marker (Layer `kreisel_weiche`/`kreisel_kollision`), ein neuer Lauf ersetzt die Marker. Derselbe Kern (`kreisel-bp-ermitteln`) liefert beim Export `kreisel_weichen.json` fuer `export_csv.py`/`export_sivas.py` |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -149,6 +149,7 @@
|
||||
(setq *export-filenames*
|
||||
(list
|
||||
(cons "raw_json_datei" "export_raw.json")
|
||||
(cons "kreisel_weichen_datei" "kreisel_weichen.json")
|
||||
(cons "sivas_script" "export_sivas.py")
|
||||
(cons "sivas_csv" "sivas.csv")
|
||||
(cons "csv_script" "export_csv.py")
|
||||
@@ -2745,6 +2746,74 @@
|
||||
)
|
||||
)
|
||||
|
||||
;; --- Kreisel-Beruehrpunkte (Weichen) fuer den Python-Export -------------
|
||||
;; Schreibt <out-dir>/kreisel_weichen.json aus kreisel-bp-ermitteln
|
||||
;; (KreiselInsert.lsp) - derselbe Kern wie der Befehl KREISEL_WEICHEN, nur
|
||||
;; ohne Marker. Gelesen von export_neighbors.load_lisp_touch_switches
|
||||
;; (export_csv.py) und export_sivas.py (Merkmal 4403). Partner werden ueber
|
||||
;; ihr ID-Attribut (= teileid im Python-Export) UND den Handle genannt.
|
||||
;; Eine alte Datei wird vorher geloescht, damit Python nie veraltete Punkte
|
||||
;; liest, falls KreiselInsert nicht geladen ist (dann rechnet Python selbst).
|
||||
;; Rueckgabe: Pfad der geschriebenen Datei oder nil.
|
||||
(defun csv:kreisel-weichen-json-eintrag (tr / ea eb)
|
||||
(setq ea (cdr (assoc "a" tr))
|
||||
eb (cdr (assoc "b" tr)))
|
||||
(strcat
|
||||
" {\"a\":\"" (csv:json-escape (cdr (assoc "id" ea))) "\""
|
||||
",\"b\":\"" (csv:json-escape (cdr (assoc "id" eb))) "\""
|
||||
",\"a_handle\":\"" (csv:json-escape (cdr (assoc "handle" ea))) "\""
|
||||
",\"b_handle\":\"" (csv:json-escape (cdr (assoc "handle" eb))) "\""
|
||||
",\"a_typ\":\"" (cdr (assoc "typ" ea)) "\""
|
||||
",\"b_typ\":\"" (cdr (assoc "typ" eb)) "\""
|
||||
",\"x\":" (rtos (car (cdr (assoc "p" tr))) 2 4)
|
||||
",\"y\":" (rtos (cadr (cdr (assoc "p" tr))) 2 4)
|
||||
",\"z\":" (rtos (cdr (assoc "z" tr)) 2 4)
|
||||
",\"art\":\"" (csv:json-escape (cdr (assoc "art" tr))) "\""
|
||||
",\"detail\":\"" (csv:json-escape (cdr (assoc "detail" tr))) "\""
|
||||
",\"achse_von\":\"" (csv:json-escape (cdr (assoc "achse_von" tr))) "\""
|
||||
",\"achse_rot_grad\":" (rtos (cdr (assoc "achse_rot" tr)) 2 4)
|
||||
"}")
|
||||
)
|
||||
|
||||
(defun csv:kreisel-weichen-json-liste (fh treffer / first)
|
||||
(setq first T)
|
||||
(foreach tr treffer
|
||||
(if (not first) (write-line "," fh))
|
||||
(princ (csv:kreisel-weichen-json-eintrag tr) fh)
|
||||
(setq first nil))
|
||||
(if treffer (write-line "" fh))
|
||||
)
|
||||
|
||||
(defun csv:kreisel-weichen-schreiben (label out-dir / pfad erg fh)
|
||||
(setq pfad (strcat out-dir "/" (export:filename "kreisel_weichen_datei")))
|
||||
(if (findfile pfad) (vl-file-delete pfad))
|
||||
(if (car (atoms-family 1 '("KREISEL-BP-ERMITTELN")))
|
||||
(progn
|
||||
(setq erg (kreisel-bp-ermitteln))
|
||||
(if (setq fh (open pfad "w"))
|
||||
(progn
|
||||
(write-line "{" fh)
|
||||
(write-line (strcat " \"toleranz_mm\": " (rtos (kreisel-bp-toleranz) 2 4) ",") fh)
|
||||
(write-line " \"beruehrungen\": [" fh)
|
||||
(csv:kreisel-weichen-json-liste fh (car erg))
|
||||
(write-line " ]," fh)
|
||||
(write-line " \"kollisionen\": [" fh)
|
||||
(csv:kreisel-weichen-json-liste fh (cadr erg))
|
||||
(write-line " ]" fh)
|
||||
(write-line "}" fh)
|
||||
(close fh)
|
||||
(princ (ssg-textf "exp-kreisel-weichen"
|
||||
(list label (itoa (length (car erg))) (itoa (length (cadr erg))) pfad)))
|
||||
(if (cadr erg)
|
||||
(princ (ssg-textf "exp-kreisel-kollision" (list label (itoa (length (cadr erg)))))))
|
||||
pfad
|
||||
)
|
||||
(progn (princ (ssg-textf "exp-file-open-error" (list label pfad))) nil)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; py-name = Python-Skript-Name (z.B. "export_csv.py")
|
||||
;; csv-name = Ergebnis-CSV-Name (z.B. "export.csv")
|
||||
;; include-bbox = T -> Bounding-Box je Block ermitteln und mit exportieren
|
||||
@@ -2819,6 +2888,10 @@
|
||||
(list (itoa *csv-bbox-fail-count*)
|
||||
(cond (*csv-bbox-fail-first*) ("?"))))))
|
||||
|
||||
;; Kreisel-Beruehrpunkte (Weichen) neben die Raw-Datei schreiben -
|
||||
;; die Python-Skripte uebernehmen sie statt selbst zu rechnen.
|
||||
(csv:kreisel-weichen-schreiben label out-dir)
|
||||
|
||||
;; Python-Export-Skript aufrufen (ausgelagert, siehe oben).
|
||||
(csv:python-aufrufen label out-dir out-pfad py-name csv-name)
|
||||
)
|
||||
|
||||
@@ -152,6 +152,12 @@ kreisel_pinbereich = pinbereich, 3
|
||||
# Beschriftungstext des Kreisels (Laenge/Bezeichnung).
|
||||
kreisel_beschriftung = S_KRS_BESCHR, 7
|
||||
|
||||
# Marker der Kreisel-Beruehrpunkte (Weichen) und -Kollisionen, gezeichnet
|
||||
# vom Befehl KREISEL_WEICHEN (Lisp/KreiselInsert.lsp, kreisel-bp-*). Reine
|
||||
# Hilfsgeometrie, jeder Aufruf ersetzt die Marker des vorigen Laufs.
|
||||
kreisel_weiche = ZZ_Kreisel_Weichen, 4
|
||||
kreisel_kollision = ZZ_Kreisel_Kollision, 1
|
||||
|
||||
# Beschriftungstext der Vario-Foerderanlage (Hoehen-/Sektionslabel).
|
||||
vf_beschriftung = VF_Beschriftung, 7
|
||||
|
||||
|
||||
@@ -107,3 +107,11 @@ Farbe= FARBE
|
||||
# ASCII-Attributwert (GERUEST_TYP) -> Sivas-Klartext mit Umlauten/Sonder-
|
||||
# zeichen (Attribute selbst bleiben ASCII, siehe CLAUDE.md-Konvention).
|
||||
Schoenenberger Geruest= Schönenberger-Gerüst
|
||||
|
||||
[weichen]
|
||||
# ILS 2.0 Weiche (6216): eine Summenzeile, Werte aus den Kreisel-Beruehr-
|
||||
# punkten des LISP-Exports (kreisel_weichen.json). Ein Beruehrpunkt ist eine
|
||||
# Weichenkombination = 1x aktiv + 1x passiv, darum lesen beide Merkmale
|
||||
# dieselbe Zahl ANZAHL_WEICHEN (= Anzahl Beruehrpunkte, siehe export_sivas.py).
|
||||
3371= ANZAHL_WEICHEN : 0
|
||||
3372= ANZAHL_WEICHEN : 0
|
||||
|
||||
@@ -12,7 +12,10 @@
|
||||
"color_pin": 3,
|
||||
"toleranz_kollinear": 0.01,
|
||||
"toleranz_winkel": 1.0,
|
||||
"toleranz_min_distanz": 0.001
|
||||
"toleranz_min_distanz": 0.001,
|
||||
"toleranz_beruehrung": 1.0,
|
||||
"toleranz_hoehe": 1.0,
|
||||
"weiche_marker_radius": 50.0
|
||||
},
|
||||
"eckrad": {
|
||||
"default_hoehe": 2000.0
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
// ============================================================
|
||||
// eckrad_edit.dcl - Eckrad Parameter einfuegen/bearbeiten
|
||||
// Wie kreisel_edit.dcl, aber ohne Abstand und Typ (ein Eckrad
|
||||
// hat keine Laenge und keine Kreiselart). Die Drehung ist ein
|
||||
// freier Winkel (aus dem Richtungsklick), daher edit_box statt
|
||||
// der festen Kreisel-Ausrichtungen.
|
||||
// ============================================================
|
||||
|
||||
eckrad_edit : dialog {
|
||||
label = "Eckrad";
|
||||
|
||||
: column {
|
||||
|
||||
: edit_box {
|
||||
key = "name";
|
||||
label = "Bezeichnung:";
|
||||
edit_width = 30;
|
||||
}
|
||||
|
||||
: row {
|
||||
: edit_box {
|
||||
key = "hoehe";
|
||||
label = "Hoehe (mm):";
|
||||
edit_width = 10;
|
||||
}
|
||||
: edit_box {
|
||||
key = "drehung";
|
||||
label = "Drehung (Grad):";
|
||||
edit_width = 10;
|
||||
}
|
||||
}
|
||||
|
||||
: popup_list {
|
||||
key = "drehrichtung";
|
||||
label = "Motordrehrichtung:";
|
||||
width = 30;
|
||||
}
|
||||
|
||||
: toggle {
|
||||
key = "geruest_einzelmodul";
|
||||
label = "Geruest fuer Einzelmodul";
|
||||
}
|
||||
|
||||
: popup_list {
|
||||
key = "geruest_typ";
|
||||
label = "Geruestoption:";
|
||||
width = 30;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ok_cancel;
|
||||
errtile;
|
||||
}
|
||||
+8
-1
@@ -1108,6 +1108,13 @@
|
||||
"sl-erk-fahrstrecke": "Omniflo Fahrstrecke",
|
||||
"sl-erk-ap60": "Omniflo Gerade AP60",
|
||||
"sl-erk-ap110": "Omniflo Gerade AP110",
|
||||
"sl-erk-apg110": "Omniflo Gerade APG110"
|
||||
"sl-erk-apg110": "Omniflo Gerade APG110",
|
||||
"kreisel-bp-start": "Kreisel-Weichenpunkte",
|
||||
"kreisel-bp-summe": "\n=== Kreisel-Weichenpunkte: %1 Beruehrung(en), %2 Kollision(en) (Toleranz %3 mm) ===",
|
||||
"kreisel-bp-zeile": "\n Weiche %1: %2 <-> %3 [%4] bei X=%5 Y=%6 Z=%7",
|
||||
"kreisel-bp-kollision": "\n KOLLISION %1: %2 <-> %3 [%4] bei X=%5 Y=%6 Z=%7",
|
||||
"kreisel-bp-marker": "\n%1 Marker gezeichnet (Layer %2).",
|
||||
"exp-kreisel-weichen": "\n[%1] Kreisel-Weichenpunkte: %2 Beruehrung(en), %3 Kollision(en) -> %4",
|
||||
"exp-kreisel-kollision": "\n[%1] WARNUNG: %2 Kreisel-Kollision(en) - Befehl KREISEL_WEICHEN zeigt sie an."
|
||||
}
|
||||
}
|
||||
|
||||
+8
-1
@@ -1108,6 +1108,13 @@
|
||||
"sl-erk-fahrstrecke": "Omniflo track",
|
||||
"sl-erk-ap60": "Omniflo straight AP60",
|
||||
"sl-erk-ap110": "Omniflo straight AP110",
|
||||
"sl-erk-apg110": "Omniflo straight APG110"
|
||||
"sl-erk-apg110": "Omniflo straight APG110",
|
||||
"kreisel-bp-start": "Kreisel switch points",
|
||||
"kreisel-bp-summe": "\n=== Kreisel switch points: %1 contact(s), %2 collision(s) (tolerance %3 mm) ===",
|
||||
"kreisel-bp-zeile": "\n Switch %1: %2 <-> %3 [%4] at X=%5 Y=%6 Z=%7",
|
||||
"kreisel-bp-kollision": "\n COLLISION %1: %2 <-> %3 [%4] at X=%5 Y=%6 Z=%7",
|
||||
"kreisel-bp-marker": "\n%1 markers drawn (layer %2).",
|
||||
"exp-kreisel-weichen": "\n[%1] Kreisel switch points: %2 contact(s), %3 collision(s) -> %4",
|
||||
"exp-kreisel-kollision": "\n[%1] WARNING: %2 Kreisel collision(s) - command KREISEL_WEICHEN shows them."
|
||||
}
|
||||
}
|
||||
|
||||
+18
-2
@@ -40,6 +40,8 @@ from export_neighbors import (
|
||||
compute_sensor_zuordnung,
|
||||
compute_scanner_nearest_separator,
|
||||
compute_kreisel_touch_switches,
|
||||
lisp_touch_switches,
|
||||
load_lisp_kreisel_weichen,
|
||||
compute_sep_kette,
|
||||
compute_kreisel_umlauf,
|
||||
SENSOR_TEILEARTEN,
|
||||
@@ -952,7 +954,9 @@ def pruefe_ases_in_beiden_containern(items, dbg=None):
|
||||
return auffaellig
|
||||
|
||||
|
||||
def process_blocks(blocks, lookup, dbg=None):
|
||||
def process_blocks(blocks, lookup, dbg=None, lisp_weichen=None):
|
||||
# lisp_weichen = Inhalt von kreisel_weichen.json (load_lisp_kreisel_weichen)
|
||||
# oder None - dann werden die Kreisel-Beruehrpunkte hier selbst gerechnet.
|
||||
# x_origin_mm/y_origin_mm einmalig fuer diesen Exportlauf aufloesen (siehe
|
||||
# export_planquadrat.resolve_origins): automatisch aus den Bloecken, falls
|
||||
# nicht explizit in [Planquadrate] konfiguriert.
|
||||
@@ -1535,6 +1539,12 @@ def process_blocks(blocks, lookup, dbg=None):
|
||||
# compute_kreisel_umlauf (damit die Weiche als Verzweigungspunkt in
|
||||
# BEIDEN beruehrenden Kreisel-Umlaeufen auftaucht) als auch in
|
||||
# build_kreisel_weiche_items (das die tatsaechlichen Zeilen erzeugt).
|
||||
# Quelle ist der LISP-Export (kreisel_weichen.json: Kreisel UND Eckrad,
|
||||
# nur gleiche Hoehe, Kollisionen getrennt); fehlt die Datei, rechnet
|
||||
# compute_kreisel_touch_switches wie bisher (nur Kreisel, reine XY-Pruefung).
|
||||
if lisp_weichen is not None:
|
||||
touch_switches = lisp_touch_switches(lisp_weichen, element_box_mm=ELEMENT_BOX_MM, dbg=dbg)
|
||||
else:
|
||||
touch_switches = compute_kreisel_touch_switches(
|
||||
items, NEIGHBOR_TOLERANCE_MM, durchmesser_mm=KREISEL_DURCHMESSER_MM,
|
||||
element_box_mm=ELEMENT_BOX_MM, dbg=dbg)
|
||||
@@ -1693,7 +1703,13 @@ def main():
|
||||
dbg_file = None
|
||||
dbg = None
|
||||
|
||||
items = process_blocks(blocks, lookup, dbg=dbg)
|
||||
lisp_weichen = load_lisp_kreisel_weichen(raw_json_path)
|
||||
if lisp_weichen is not None:
|
||||
print(f"[export_csv] Kreisel-Weichen aus LISP: "
|
||||
f"{len(lisp_weichen['beruehrungen'])} Beruehrung(en), "
|
||||
f"{len(lisp_weichen['kollisionen'])} Kollision(en).")
|
||||
|
||||
items = process_blocks(blocks, lookup, dbg=dbg, lisp_weichen=lisp_weichen)
|
||||
|
||||
if dbg_file:
|
||||
dbg_file.close()
|
||||
|
||||
@@ -47,6 +47,7 @@ MIN_PARTNER) - Ergebnis ist die CSV-Spalte "Fehler" in export_csv.py.
|
||||
Nur von export_csv.py genutzt (EXPORTCSV), nicht von export_sivas.py.
|
||||
"""
|
||||
|
||||
import json
|
||||
import math
|
||||
import os
|
||||
|
||||
@@ -1091,6 +1092,84 @@ def compute_kreisel_touch_switches(items, tolerance_mm, durchmesser_mm=800.0,
|
||||
return switches
|
||||
|
||||
|
||||
# Dateiname der von LISP (csv:kreisel-weichen-schreiben, export.lsp) neben
|
||||
# export_raw.json geschriebenen Kreisel-Beruehrpunkte.
|
||||
LISP_KREISEL_WEICHEN_DATEI = "kreisel_weichen.json"
|
||||
|
||||
|
||||
def load_lisp_kreisel_weichen(raw_json_path):
|
||||
"""Liest kreisel_weichen.json aus dem Ordner von raw_json_path.
|
||||
|
||||
Die Datei schreibt der LISP-Export (KreiselInsert.lsp kreisel-bp-*):
|
||||
Kreisel UND Eckraeder, nur gleiche Hoehe, mehrere Punkte je Paar moeglich,
|
||||
Ueberschneidungen getrennt als "kollisionen". Rueckgabe: dict mit
|
||||
"beruehrungen"/"kollisionen" oder None, wenn die Datei fehlt/unlesbar ist
|
||||
(dann rechnet der Aufrufer selbst - compute_kreisel_touch_switches)."""
|
||||
pfad = os.path.join(os.path.dirname(os.path.abspath(raw_json_path)),
|
||||
LISP_KREISEL_WEICHEN_DATEI)
|
||||
if not os.path.exists(pfad):
|
||||
return None
|
||||
try:
|
||||
with open(pfad, encoding="utf-8", errors="replace") as f:
|
||||
daten = json.load(f)
|
||||
except (OSError, ValueError):
|
||||
return None
|
||||
if not isinstance(daten, dict):
|
||||
return None
|
||||
daten.setdefault("beruehrungen", [])
|
||||
daten.setdefault("kollisionen", [])
|
||||
return daten
|
||||
|
||||
|
||||
def lisp_touch_switches(lisp_daten, element_box_mm=None, dbg=None):
|
||||
"""Baut aus den LISP-Beruehrpunkten (load_lisp_kreisel_weichen) dieselben
|
||||
Switch-dicts wie compute_kreisel_touch_switches - damit laufen
|
||||
compute_kreisel_umlauf und build_kreisel_weiche_items unveraendert.
|
||||
|
||||
Partner-ID = ID-Attribut (= teileid), ohne ID der Handle. Mehrere Punkte
|
||||
eines Paares bekommen eindeutige Schluessel (WEICHE#a#b, WEICHE#a#b#2, ...).
|
||||
Die Box wird an achse_rot_grad (Radiale des beruehrenden Rades) ausgerichtet.
|
||||
Kollisionen werden NICHT zu Weichen, nur ins Debuglog geschrieben."""
|
||||
if element_box_mm is None:
|
||||
element_box_mm = load_element_box_mm()
|
||||
box_l, box_b, box_h = element_box_mm
|
||||
switches = []
|
||||
keys = set()
|
||||
if dbg:
|
||||
dbg("")
|
||||
dbg("=== Kreisel-Beruehrpunkte -> ILS-Weichen (aus LISP kreisel_weichen.json) ===")
|
||||
for b in lisp_daten.get("beruehrungen", []):
|
||||
id_a = b.get("a") or b.get("a_handle", "")
|
||||
id_b = b.get("b") or b.get("b_handle", "")
|
||||
key = f"WEICHE#{id_a}#{id_b}"
|
||||
n = 1
|
||||
while key in keys:
|
||||
n += 1
|
||||
key = f"WEICHE#{id_a}#{id_b}#{n}"
|
||||
keys.add(key)
|
||||
dx, dy, dz = _oriented_box_aabb(math.radians(float(b.get("achse_rot_grad", 0.0))),
|
||||
box_l, box_b, box_h)
|
||||
sw = {
|
||||
"key": key,
|
||||
"x": float(b.get("x", 0.0)), "y": float(b.get("y", 0.0)), "z": float(b.get("z", 0.0)),
|
||||
"dx": dx, "dy": dy, "dz": dz,
|
||||
"nachbarn": [id_a, id_b],
|
||||
"achse_von": b.get("achse_von", "") or id_a,
|
||||
"beruehrung": b.get("art", ""),
|
||||
}
|
||||
switches.append(sw)
|
||||
if dbg:
|
||||
dbg(f" {id_a} <-> {id_b}: {sw['beruehrung']} ({b.get('detail', '')}) "
|
||||
f"bei ({sw['x']:.0f}, {sw['y']:.0f}, {sw['z']:.0f})")
|
||||
if dbg:
|
||||
for k in lisp_daten.get("kollisionen", []):
|
||||
dbg(f" KOLLISION {k.get('a', '')} <-> {k.get('b', '')}: {k.get('art', '')} "
|
||||
f"({k.get('detail', '')}) bei ({float(k.get('x', 0)):.0f}, "
|
||||
f"{float(k.get('y', 0)):.0f})")
|
||||
dbg(f"Erzeugte ILS-Weichen: {len(switches)}")
|
||||
return switches
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Kreisel <-> Strecken-Enden: verfeinerte Kollisionsbox fuer compute_neighbor_
|
||||
# ids (die "Nachbarn"-Spalte einer GF/VF-Strecke soll nur an ihrem echten AS-/
|
||||
|
||||
+38
-3
@@ -63,6 +63,7 @@ from export_blockpatterns import (load_patterns, load_export_cfg, cfg_path_from_
|
||||
matches_any, csv_quote, safe_float, safe_int)
|
||||
from merkmalstamm import lade_merkmalstamm, bezeichnung_fuer
|
||||
import sivas_mapping
|
||||
from export_neighbors import load_lisp_kreisel_weichen
|
||||
|
||||
BLOCKPATTERNS = load_patterns()
|
||||
|
||||
@@ -297,6 +298,7 @@ def build_variofoerderer_details(block):
|
||||
SIVAS_MAPPING_KREISEL = sivas_mapping.load_section_mapping("kreisel")
|
||||
SIVAS_MAPPING_ECKRAD = sivas_mapping.load_section_mapping("eckrad")
|
||||
SIVAS_MAPPING_GERUEST = sivas_mapping.load_section_mapping("geruest")
|
||||
SIVAS_MAPPING_WEICHEN = sivas_mapping.load_section_mapping("weichen")
|
||||
|
||||
|
||||
def build_kreisel_details(block):
|
||||
@@ -414,7 +416,9 @@ ILS_SIVASNR = {
|
||||
}
|
||||
|
||||
|
||||
def process_blocks(blocks):
|
||||
def process_blocks(blocks, anzahl_weichen_ils=0):
|
||||
# anzahl_weichen_ils = Anzahl Kreisel-Beruehrpunkte aus dem LISP-Export
|
||||
# (kreisel_weichen.json, siehe main) -> Merkmal 4403 der Automation-Zeile.
|
||||
"""
|
||||
Verarbeitet alle Bloecke.
|
||||
|
||||
@@ -448,7 +452,7 @@ def process_blocks(blocks):
|
||||
"sep_kreisel_ohne_pin": 0,
|
||||
"anzahl_verbindungskreisel": 0,
|
||||
"laengen_kreisel": 0.0,
|
||||
"anzahl_weichen_ils": 0,
|
||||
"anzahl_weichen_ils": anzahl_weichen_ils,
|
||||
"anzahl_eckraeder": 0,
|
||||
"anzahl_gefaellestrecken": 0,
|
||||
"anzahl_variofoerderer": 0,
|
||||
@@ -826,6 +830,30 @@ def process_blocks(blocks):
|
||||
})
|
||||
nr += 1
|
||||
|
||||
# ILS 2.0 Weiche (6216): EINE Summenzeile fuer alle Kreisel-Beruehrpunkte
|
||||
# (kreisel_weichen.json des LISP-Exports, Anzahl = anzahl_weichen_ils).
|
||||
# Ein Beruehrpunkt = eine Weichenkombination aus 1x aktiv (3371) + 1x
|
||||
# passiv (3372); die Zuordnung Merkmal -> Wert steht in sivas.cfg
|
||||
# [weichen], beide lesen ANZAHL_WEICHEN. Anzahl-Spalte 1 wie bei der
|
||||
# Automation-Zeile - die Gesamtanzahlen stecken in den Merkmalen.
|
||||
if counters["anzahl_weichen_ils"] > 0:
|
||||
weiche_sivasnr, weiche_teileart = ILS_SIVASNR["ils_weiche"]
|
||||
items.append({
|
||||
"nr": nr,
|
||||
"teileart": weiche_teileart,
|
||||
"sivasnr": weiche_sivasnr,
|
||||
"sivasnr_quoted": True,
|
||||
"bezeichnung": "",
|
||||
"dispgruppe": 20,
|
||||
"anzahl": 1,
|
||||
"laenge_mm": "",
|
||||
"details": sivas_mapping.anwenden(
|
||||
SIVAS_MAPPING_WEICHEN,
|
||||
{"ANZAHL_WEICHEN": str(counters["anzahl_weichen_ils"])},
|
||||
TRANSFORMS),
|
||||
})
|
||||
nr += 1
|
||||
|
||||
# ILS Automation Summierungszeile (nur wenn ILS-Elemente vorhanden)
|
||||
has_ils = (counters["anzahl_kreisel"] > 0
|
||||
or counters["anzahl_eckraeder"] > 0
|
||||
@@ -986,7 +1014,14 @@ def main():
|
||||
blocks = load_json(raw_json_path)
|
||||
print(f"[export_sivas] {len(blocks)} Bloecke geladen.")
|
||||
|
||||
items, _ = process_blocks(blocks)
|
||||
# Kreisel-Beruehrpunkte (= ILS-Weichen) zaehlt der LISP-Export
|
||||
# (kreisel_weichen.json neben der Raw-Datei); fehlt sie, bleibt 4403 = 0.
|
||||
lisp_weichen = load_lisp_kreisel_weichen(raw_json_path)
|
||||
anzahl_weichen = len(lisp_weichen["beruehrungen"]) if lisp_weichen else 0
|
||||
if lisp_weichen is not None:
|
||||
print(f"[export_sivas] Kreisel-Weichen aus LISP: {anzahl_weichen}")
|
||||
|
||||
items, _ = process_blocks(blocks, anzahl_weichen_ils=anzahl_weichen)
|
||||
|
||||
header = "Nr;TeileArt;SivasNummer;Bezeichnung;Dispogruppe;Anzahl;Laenge[mm];IDs;details"
|
||||
with open(output_csv, "w", encoding="utf-8") as f:
|
||||
|
||||
+502
-465
File diff suppressed because it is too large
Load Diff
+3
-1
@@ -8,7 +8,9 @@
|
||||
[Verbinden]^C^C(ssg-ensure "KreiselInsert") KreiselConnect
|
||||
[Bearbeiten]^C^C(ssg-ensure "KreiselInsert") KreiselEdit
|
||||
[Eckrad]^C^C(ssg-ensure "KreiselInsert") ILS_Eckrad
|
||||
[<-Eckrad bearbeiten]^C^C(ssg-ensure "KreiselInsert") EckradEdit
|
||||
[Eckrad bearbeiten]^C^C(ssg-ensure "KreiselInsert") EckradEdit
|
||||
[--]
|
||||
[<-Weichenpunkte ermitteln]^C^C(ssg-ensure "KreiselInsert") KREISEL_WEICHEN
|
||||
[->Zusatzmodul]
|
||||
[BTMT-Beladung]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_BTMT_Beladung
|
||||
[BTMT-Entladung]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_BTMT_Entladung
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
test_export_sivas_eckrad.py - Sivas-Merkmale des ILS Eckrads (6210),
|
||||
am Kreisel ausgerichtet (cfg/sivas.cfg [eckrad]).
|
||||
Laeuft komplett ohne BricsCAD (reine Python-Logik).
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "lib"))
|
||||
|
||||
import export_sivas # noqa: E402
|
||||
|
||||
|
||||
def _eckrad(nr, hoehe="2000", einzelmodul="1", typ="Schoenenberger Geruest"):
|
||||
return {"block_name": f"ECKRAD_{nr}", "x": 0.0, "y": 0.0, "z": float(hoehe),
|
||||
"rotation": 0.0,
|
||||
"attribs": {"ID": f"000{nr}", "Bezeichnung": f"Eckrad {nr}",
|
||||
"NUMMER": str(nr), "HOEHE": hoehe,
|
||||
"GERUEST_EINZELMODUL": einzelmodul, "GERUEST_TYP": typ}}
|
||||
|
||||
|
||||
def test_eckrad_details_wie_kreisel():
|
||||
details = export_sivas.build_eckrad_details(_eckrad(1))
|
||||
assert details == {"2950": "2.0", "3381": "1", "3992": "Ja",
|
||||
"3993": export_sivas.geruest_typ_anzeige("Schoenenberger Geruest")}
|
||||
|
||||
|
||||
def test_eckrad_ohne_geruest_ist_nein():
|
||||
details = export_sivas.build_eckrad_details(_eckrad(1, einzelmodul="0"))
|
||||
assert details["3992"] == "Nein"
|
||||
|
||||
|
||||
def test_eckrad_hoehe_in_metern():
|
||||
assert export_sivas.build_eckrad_details(_eckrad(1, hoehe="4820"))["2950"] == "4.82"
|
||||
|
||||
|
||||
def _kreisel(nr, montagehoehe):
|
||||
return {"block_name": f"KREISEL_{nr}", "x": 0.0, "y": 0.0, "z": 0.0,
|
||||
"rotation": 0.0,
|
||||
"attribs": {"ID": f"000{nr}", "NUMMER": str(nr), "KREISELART": "STANDARD",
|
||||
"ABSTAND": "2300", "MONTAGEHOEHE_m": montagehoehe}}
|
||||
|
||||
|
||||
def test_kreisel_verschiedene_hoehen_getrennte_zeilen():
|
||||
assert (export_sivas.kreisel_signature(_kreisel(1, "4.820"))
|
||||
!= export_sivas.kreisel_signature(_kreisel(2, "2.000")))
|
||||
# numerischer Vergleich: gleiche Hoehe, andere Schreibweise -> eine Zeile
|
||||
assert (export_sivas.kreisel_signature(_kreisel(1, "4.820"))
|
||||
== export_sivas.kreisel_signature(_kreisel(2, "4.82")))
|
||||
|
||||
|
||||
def test_eckrad_verschiedene_hoehen_getrennte_zeilen():
|
||||
assert (export_sivas.eckrad_signature(_eckrad(1, hoehe="2000"))
|
||||
!= export_sivas.eckrad_signature(_eckrad(2, hoehe="2500")))
|
||||
assert (export_sivas.eckrad_signature(_eckrad(1, hoehe="2000"))
|
||||
== export_sivas.eckrad_signature(_eckrad(2, hoehe="2000")))
|
||||
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
test_kreisel_weichen_json.py - Uebernahme der LISP-Kreisel-Beruehrpunkte.
|
||||
|
||||
Der LISP-Export (export.lsp csv:kreisel-weichen-schreiben, Kern
|
||||
KreiselInsert.lsp kreisel-bp-*) schreibt kreisel_weichen.json neben
|
||||
export_raw.json. export_csv.py/export_sivas.py lesen sie statt selbst zu
|
||||
rechnen; fehlt sie, bleibt es beim alten Python-Rueckfall.
|
||||
Laeuft ohne BricsCAD.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "lib"))
|
||||
|
||||
from export_neighbors import ( # noqa: E402
|
||||
lisp_touch_switches,
|
||||
load_lisp_kreisel_weichen,
|
||||
)
|
||||
import export_sivas # noqa: E402
|
||||
|
||||
BOX = (250.0, 100.0, 30.0)
|
||||
|
||||
BEISPIEL = {
|
||||
"toleranz_mm": 1.0,
|
||||
"beruehrungen": [
|
||||
# Rad an Laufprofil, Radiale senkrecht (90 Grad)
|
||||
{"a": "0001", "b": "0002", "a_handle": "2A", "b_handle": "2B",
|
||||
"a_typ": "KREISEL", "b_typ": "KREISEL", "x": 22503.49, "y": -2821.76,
|
||||
"z": 5000.0, "art": "Kreis/Tangente", "detail": "AN8/Profil",
|
||||
"achse_von": "0002", "achse_rot_grad": 270.0},
|
||||
# Zweiter Punkt desselben Paares -> eigener Schluessel
|
||||
{"a": "0001", "b": "0002", "a_handle": "2A", "b_handle": "2B",
|
||||
"a_typ": "KREISEL", "b_typ": "KREISEL", "x": 23000.0, "y": -2821.76,
|
||||
"z": 5000.0, "art": "Kreis/Kreis", "detail": "SP8/AN8",
|
||||
"achse_von": "0001", "achse_rot_grad": 0.0},
|
||||
# Eckrad ohne ID -> Handle
|
||||
{"a": "", "b": "0003", "a_handle": "3F", "b_handle": "3C",
|
||||
"a_typ": "ECKRAD", "b_typ": "KREISEL", "x": 1.0, "y": 2.0, "z": 0.0,
|
||||
"art": "Kreis/Kreis", "detail": "ECKRAD/AN8",
|
||||
"achse_von": "", "achse_rot_grad": 0.0},
|
||||
],
|
||||
"kollisionen": [
|
||||
{"a": "0004", "b": "0005", "x": 0.0, "y": 0.0, "z": 0.0,
|
||||
"art": "Ueberschneidung", "detail": "Achsabstand 500.0",
|
||||
"achse_von": "0004", "achse_rot_grad": 0.0},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def _schreibe(tmp_path, daten):
|
||||
raw = tmp_path / "export_raw.json"
|
||||
raw.write_text("[]", encoding="utf-8")
|
||||
(tmp_path / "kreisel_weichen.json").write_text(json.dumps(daten), encoding="utf-8")
|
||||
return str(raw)
|
||||
|
||||
|
||||
def test_datei_fehlt_liefert_none(tmp_path):
|
||||
raw = tmp_path / "export_raw.json"
|
||||
raw.write_text("[]", encoding="utf-8")
|
||||
assert load_lisp_kreisel_weichen(str(raw)) is None
|
||||
|
||||
|
||||
def test_kaputte_datei_liefert_none(tmp_path):
|
||||
raw = tmp_path / "export_raw.json"
|
||||
raw.write_text("[]", encoding="utf-8")
|
||||
(tmp_path / "kreisel_weichen.json").write_text("{kaputt", encoding="utf-8")
|
||||
assert load_lisp_kreisel_weichen(str(raw)) is None
|
||||
|
||||
|
||||
def test_switches_aus_lisp(tmp_path):
|
||||
daten = load_lisp_kreisel_weichen(_schreibe(tmp_path, BEISPIEL))
|
||||
sw = lisp_touch_switches(daten, element_box_mm=BOX)
|
||||
# Kollisionen werden keine Weichen
|
||||
assert len(sw) == 3
|
||||
assert [s["key"] for s in sw] == ["WEICHE#0001#0002", "WEICHE#0001#0002#2",
|
||||
"WEICHE#3F#0003"]
|
||||
assert sw[0]["nachbarn"] == ["0001", "0002"]
|
||||
assert sw[0]["beruehrung"] == "Kreis/Tangente"
|
||||
assert sw[0]["achse_von"] == "0002"
|
||||
assert (sw[0]["x"], sw[0]["y"], sw[0]["z"]) == (22503.49, -2821.76, 5000.0)
|
||||
# Radiale 270 Grad: Laengsseite (250) quer zur Radialen -> entlang X
|
||||
assert abs(sw[0]["dx"] - 250.0) < 1e-6 and abs(sw[0]["dy"] - 100.0) < 1e-6
|
||||
# Radiale 0 Grad: Laengsseite entlang Y
|
||||
assert abs(sw[1]["dx"] - 100.0) < 1e-6 and abs(sw[1]["dy"] - 250.0) < 1e-6
|
||||
# Ohne achse_von -> erster Partner
|
||||
assert sw[2]["achse_von"] == "3F"
|
||||
|
||||
|
||||
def test_sivas_4403_zaehlt_beruehrungen():
|
||||
_, counters = export_sivas.process_blocks([], anzahl_weichen_ils=10)
|
||||
assert counters["anzahl_weichen_ils"] == 10
|
||||
_, counters = export_sivas.process_blocks([])
|
||||
assert counters["anzahl_weichen_ils"] == 0
|
||||
|
||||
|
||||
def test_sivas_6216_summenzeile():
|
||||
"""Eine Zeile 6216, je Beruehrpunkt 1x aktiv (3371) + 1x passiv (3372)."""
|
||||
items, _ = export_sivas.process_blocks([], anzahl_weichen_ils=10)
|
||||
weichen = [i for i in items if i["sivasnr"] == "6216"]
|
||||
assert len(weichen) == 1
|
||||
w = weichen[0]
|
||||
assert w["teileart"] == "ILS 2.0 Weiche"
|
||||
assert w["anzahl"] == 1
|
||||
assert w["details"] == {"3371": "10", "3372": "10"}
|
||||
# CSV-Zeile laesst sich formatieren
|
||||
assert ';"6216";' in export_sivas.format_csv_line(w)
|
||||
|
||||
|
||||
def test_sivas_6216_ohne_weichen_keine_zeile():
|
||||
items, _ = export_sivas.process_blocks([])
|
||||
assert not [i for i in items if i["sivasnr"] == "6216"]
|
||||
+94
-1
@@ -756,6 +756,99 @@
|
||||
)
|
||||
|
||||
|
||||
;; ------------------------------------------------------------
|
||||
;; TESTS: KreiselInsert.lsp - Beruehrpunkte/Weichen (kreisel-bp-*)
|
||||
;; ------------------------------------------------------------
|
||||
;; Element-Record kurz: (typ x y z rot abstand id)
|
||||
(defun tu-bp-el (typ x y z rot abstand id)
|
||||
(kreisel-bp-element typ (list x y) z rot abstand 400.0 id id id)
|
||||
)
|
||||
|
||||
(defun tu-bp-arten (treffer)
|
||||
(mapcar '(lambda (tr) (cdr (assoc "art" tr))) treffer)
|
||||
)
|
||||
|
||||
(defun tu-tests-kreisel-bp ( / _els _erg _ber _kol)
|
||||
(princ "\n[KreiselInsert/Beruehrpunkte]")
|
||||
|
||||
;; Hilfs-Kerne
|
||||
(tu-eqf "kreisel-bp-abstand/attribut" 7715.0 (kreisel-bp-abstand "7715" "KREISEL_1_STANDARD_7715"))
|
||||
(tu-eqf "kreisel-bp-abstand/blockname" 3469.0 (kreisel-bp-abstand nil "KREISEL_3_STANDARD_3469"))
|
||||
(tu-eqf "kreisel-bp-naechste-punkte/kreuz"
|
||||
'((5.0 0.0) (5.0 0.0))
|
||||
(kreisel-bp-naechste-punkte '(0.0 0.0) '(10.0 0.0) '(5.0 -5.0) '(5.0 5.0)))
|
||||
|
||||
;; Die 11 Einfuegungen aus tests/testdata/schnittspunkte_kreisel.dxf
|
||||
(setq _els
|
||||
(list
|
||||
(tu-bp-el "ECKRAD" 22405.42028816571 -4021.762548616969 5000.0 270.0 0.0 "E1")
|
||||
(tu-bp-el "KREISEL" 20971.14247926632 -3221.762548616969 5000.0 0.0 7715.0 "K1")
|
||||
(tu-bp-el "KREISEL" 22503.49142858727 -2821.762548616969 5000.0 90.0 9020.0 "K2")
|
||||
(tu-bp-el "KREISEL" 27253.08134883916 -3621.762548616969 5000.0 270.0 3469.0 "K3")
|
||||
(tu-bp-el "KREISEL" 22503.49142858727 6998.075803812235 5000.0 90.0 4746.0 "K4")
|
||||
(tu-bp-el "KREISEL" 22405.42028816571 -4421.762548616969 5000.0 270.0 6147.0 "K5")
|
||||
(tu-bp-el "KREISEL" 26853.08134883916 -6582.442351476258 5000.0 180.0 3248.0 "K6")
|
||||
(tu-bp-el "KREISEL" 32541.84792939903 -5752.219206460449 2000.0 270.0 9200.0 "K7")
|
||||
(tu-bp-el "KREISEL" 32941.84792939903 -7662.266486416901 2000.0 0.0 3637.0 "K8a")
|
||||
(tu-bp-el "KREISEL" 32941.84792939903 -11185.64734962363 2000.0 0.0 3637.0 "K8b")
|
||||
(tu-bp-el "ECKRAD" 20571.14247926632 -3221.762548616969 5000.0 270.0 0.0 "E1b")))
|
||||
(setq _erg (kreisel-bp-berechnen _els 1.0 1.0)
|
||||
_ber (car _erg)
|
||||
_kol (cadr _erg))
|
||||
(tu-eq "kreisel-bp/dxf-beruehrungen" 10 (length _ber))
|
||||
(tu-eq "kreisel-bp/dxf-kollisionen" 0 (length _kol))
|
||||
(tu-eq "kreisel-bp/dxf-kreis-kreis" 3
|
||||
(length (vl-remove-if-not '(lambda (a) (= a "Kreis/Kreis")) (tu-bp-arten _ber))))
|
||||
(tu-eq "kreisel-bp/dxf-paare"
|
||||
'(("E1" "K1") ("E1" "K5") ("K1" "K2") ("K1" "K3") ("K1" "E1b") ("K2" "K4")
|
||||
("K3" "K6") ("K5" "K6") ("K7" "K8a") ("K7" "K8b"))
|
||||
(mapcar '(lambda (tr) (list (cdr (assoc "id" (cdr (assoc "a" tr))))
|
||||
(cdr (assoc "id" (cdr (assoc "b" tr))))))
|
||||
_ber))
|
||||
;; K2 (AN8) steht auf dem oberen Laufprofil von K1
|
||||
(tu-eqf "kreisel-bp/dxf-punkt-k1-k2"
|
||||
(list 22503.49142858727 -2821.762548616969)
|
||||
(cdr (assoc "p" (nth 2 _ber))))
|
||||
(tu-eq "kreisel-bp/dxf-achse-von-k1-k2" "K2" (cdr (assoc "achse_von" (nth 2 _ber))))
|
||||
|
||||
;; Unterschiedliche Hoehe -> kein Kontakt
|
||||
(tu-eq "kreisel-bp/hoehe"
|
||||
'(nil nil)
|
||||
(kreisel-bp-berechnen (list (tu-bp-el "ECKRAD" 0.0 0.0 0.0 0.0 0.0 "A")
|
||||
(tu-bp-el "ECKRAD" 800.0 0.0 500.0 0.0 0.0 "B"))
|
||||
1.0 1.0))
|
||||
;; Zwei Eckraeder Rad an Rad -> eine Weiche in der Mitte
|
||||
(setq _ber (car (kreisel-bp-berechnen (list (tu-bp-el "ECKRAD" 0.0 0.0 0.0 0.0 0.0 "A")
|
||||
(tu-bp-el "ECKRAD" 800.0 0.0 0.0 0.0 0.0 "B"))
|
||||
1.0 1.0)))
|
||||
(tu-eq "kreisel-bp/eckraeder-art" '("Kreis/Kreis") (tu-bp-arten _ber))
|
||||
(tu-eqf "kreisel-bp/eckraeder-punkt" '(400.0 0.0) (cdr (assoc "p" (car _ber))))
|
||||
;; Spalt groesser als Toleranz -> nichts
|
||||
(tu-eq "kreisel-bp/spalt"
|
||||
'(nil nil)
|
||||
(kreisel-bp-berechnen (list (tu-bp-el "ECKRAD" 0.0 0.0 0.0 0.0 0.0 "A")
|
||||
(tu-bp-el "ECKRAD" 805.0 0.0 0.0 0.0 0.0 "B"))
|
||||
1.0 1.0))
|
||||
;; Laufprofile kreuzen sich -> Kollision, keine Weiche
|
||||
(setq _erg (kreisel-bp-berechnen (list (tu-bp-el "KREISEL" 0.0 0.0 0.0 0.0 2000.0 "A")
|
||||
(tu-bp-el "KREISEL" 1000.0 -1500.0 0.0 90.0 2000.0 "B"))
|
||||
1.0 1.0))
|
||||
(tu-nil "kreisel-bp/kreuzung-keine-weiche" (car _erg))
|
||||
(tu-eq "kreisel-bp/kreuzung-kollision" '("Ueberschneidung") (tu-bp-arten (cadr _erg)))
|
||||
;; Kreisel Seite an Seite (Profile aufeinander) -> Kollision, keine Weiche
|
||||
(setq _erg (kreisel-bp-berechnen (list (tu-bp-el "KREISEL" 0.0 0.0 0.0 0.0 2000.0 "A")
|
||||
(tu-bp-el "KREISEL" 500.0 800.0 0.0 0.0 2000.0 "B"))
|
||||
1.0 1.0))
|
||||
(tu-nil "kreisel-bp/parallel-keine-weiche" (car _erg))
|
||||
(tu-eq "kreisel-bp/parallel-kollision" '("Tangente/Tangente") (tu-bp-arten (cadr _erg)))
|
||||
;; Eckrad an der Flanke eines Kreiselrades -> Weiche (freie Seite)
|
||||
(setq _ber (car (kreisel-bp-berechnen (list (tu-bp-el "KREISEL" 0.0 0.0 0.0 0.0 2000.0 "A")
|
||||
(tu-bp-el "ECKRAD" 400.0 800.0 0.0 0.0 0.0 "B"))
|
||||
1.0 1.0)))
|
||||
(tu-eq "kreisel-bp/flanke-eckrad" 1 (length _ber))
|
||||
)
|
||||
|
||||
|
||||
;; ------------------------------------------------------------
|
||||
;; TESTS: ssg_ks_insert.lsp - Sepliste-Serialisierung
|
||||
;; ------------------------------------------------------------
|
||||
@@ -2046,7 +2139,7 @@
|
||||
|
||||
(foreach fn '("tu-tests-core" "tu-tests-lang" "tu-tests-id" "tu-tests-vfcore"
|
||||
"tu-tests-etage"
|
||||
"tu-tests-export" "tu-tests-hoehen" "tu-tests-gf" "tu-tests-omni" "tu-tests-kreisel"
|
||||
"tu-tests-export" "tu-tests-hoehen" "tu-tests-gf" "tu-tests-omni" "tu-tests-kreisel" "tu-tests-kreisel-bp"
|
||||
"tu-tests-sepliste" "tu-tests-json" "tu-tests-geruest"
|
||||
"tu-tests-sepscan" "tu-tests-vfl-segs" "tu-tests-vfl-abbruch"
|
||||
"tu-tests-werkzeuge")
|
||||
|
||||
Reference in New Issue
Block a user