This commit is contained in:
2026-07-21 09:11:21 +02:00
24 changed files with 1630 additions and 277 deletions
+401 -99
View File
@@ -1611,6 +1611,12 @@
startpunkt last-ent nach-aus-pt (float hz) (float L_stau)
es-seite))
;; Edit-Metadaten (Fahrtrichtung, Gefaellewinkel, Element-Winkel) als XDATA
;; auf das GF_N-INSERT schreiben, damit GEFAELLESTRECKE_EDIT die Strecke
;; verlustfrei nachbauen kann. Nicht Teil des Sivas-Attributsatzes.
(gf-xdata-schreiben gf-insert hz winkel as-winkel es-winkel
(caddr startpunkt) deltaL-total)
(princ "\n\n=========================================")
(princ (ssg-text "gf-status-erfolgreich-eingefuegt"))
(princ "\n=========================================")
@@ -1620,14 +1626,246 @@
(list gf-insert gf-deltaH (float deltaL-total))
)
;; ============================================================
;; TEIL 5b: DCL-DIALOG (Modus 1 - parametrische Eingabe)
;; ============================================================
;; Parametrische Eingabe fuer Modus 1 / Edit ueber DCL-Dialog
;; (dcl/gefaellestrecke.dcl). Analog zum Kreisel-Dialog, ergaenzt
;; um die Angabe der Einfuegehoehe (Z).
;; prefill: Assoziationsliste zur Vorbelegung (fuer GEFAELLESTRECKE_EDIT) mit
;; Schluesseln "deltaL" "winkel" "hz" "as-seite" "es-seite" "einfuegehoehe"
;; "as-winkel" "es-winkel" - oder nil fuer Neuanlage (Modus 1) mit Defaults.
;; Rueckgabe: (deltaL winkel hz-winkel as-seite es-seite einfuegehoehe
;; as-winkel es-winkel)
;; oder nil bei Abbruch / fehlendem Dialog.
(defun gf-dialog-eingabe ( prefill / dcl-pfad dat ergebnis
dlg-deltal dlg-hoehe dlg-winkel
dlg-richtung dlg-aus dlg-ein
dlg-aus-winkel dlg-ein-winkel
hz-winkel as-seite es-seite as-winkel es-winkel)
(setq dcl-pfad (strcat (getenv "DXFM_DCL") "/gefaellestrecke.dcl"))
(setq dat (load_dialog dcl-pfad))
(if (not (new_dialog "gefaellestrecke" dat))
(progn
(if (>= dat 0) (unload_dialog dat))
(alert (ssg-textf "gf-alert-dialog-fehlt" (list dcl-pfad)))
nil
)
(progn
;; Vorbelegung: aus prefill (Edit) oder Defaults (Neuanlage)
(set_tile "deltal"
(if prefill (rtos (cdr (assoc "deltaL" prefill)) 2 0)
(rtos (ssg-cfg-or "gefaelle" "default_delta_l" 5000.0) 2 0)))
(set_tile "einfuegehoehe"
(if prefill (rtos (cdr (assoc "einfuegehoehe" prefill)) 2 1) "0"))
(set_tile "winkel"
(if prefill (rtos (cdr (assoc "winkel" prefill)) 2 1)
(rtos (ssg-cfg-or "gefaelle" "default_winkel" 3.0) 2 1)))
;; Fahrtrichtung
(start_list "fahrtrichtung")
(add_list (ssg-textf "gf-dlg-richtung-0" (list grad-zeichen)))
(add_list (ssg-textf "gf-dlg-richtung-90" (list grad-zeichen)))
(add_list (ssg-textf "gf-dlg-richtung-180" (list grad-zeichen)))
(add_list (ssg-textf "gf-dlg-richtung-270" (list grad-zeichen)))
(end_list)
(set_tile "fahrtrichtung"
(if prefill
(cond ((equal (cdr (assoc "hz" prefill)) 90.0 0.1) "1")
((equal (cdr (assoc "hz" prefill)) 180.0 0.1) "2")
((equal (cdr (assoc "hz" prefill)) 270.0 0.1) "3")
(t "0"))
"0"))
;; AUS-Element: Winkel (90/30) + Seite
(start_list "aus_winkel")
(add_list "90")
(add_list "30")
(end_list)
(set_tile "aus_winkel"
(if (and prefill (equal (cdr (assoc "as-winkel" prefill)) "30")) "1" "0"))
(start_list "aus_seite")
(add_list (ssg-text "gf-dlg-links"))
(add_list (ssg-text "gf-dlg-rechts"))
(end_list)
(set_tile "aus_seite"
(if (and prefill (equal (cdr (assoc "as-seite" prefill)) "rechts")) "1" "0"))
;; EIN-Element: Winkel (90/30) + Seite
(start_list "ein_winkel")
(add_list "90")
(add_list "30")
(end_list)
(set_tile "ein_winkel"
(if (and prefill (equal (cdr (assoc "es-winkel" prefill)) "30")) "1" "0"))
(start_list "ein_seite")
(add_list (ssg-text "gf-dlg-links"))
(add_list (ssg-text "gf-dlg-rechts"))
(end_list)
(set_tile "ein_seite"
(if (and prefill (equal (cdr (assoc "es-seite" prefill)) "rechts")) "1" "0"))
;; Actions
(action_tile "accept"
(strcat
"(setq dlg-deltal (get_tile \"deltal\"))"
"(setq dlg-hoehe (get_tile \"einfuegehoehe\"))"
"(setq dlg-winkel (get_tile \"winkel\"))"
"(setq dlg-richtung (get_tile \"fahrtrichtung\"))"
"(setq dlg-aus-winkel (get_tile \"aus_winkel\"))"
"(setq dlg-aus (get_tile \"aus_seite\"))"
"(setq dlg-ein-winkel (get_tile \"ein_winkel\"))"
"(setq dlg-ein (get_tile \"ein_seite\"))"
"(done_dialog 1)"
)
)
(action_tile "cancel" "(done_dialog 0)")
(setq ergebnis (start_dialog))
(unload_dialog dat)
(if (= ergebnis 1)
(progn
(setq hz-winkel
(cond ((= dlg-richtung "1") 90.0)
((= dlg-richtung "2") 180.0)
((= dlg-richtung "3") 270.0)
(t 0.0)))
(setq as-seite (if (= dlg-aus "1") "rechts" "links"))
(setq es-seite (if (= dlg-ein "1") "rechts" "links"))
(setq as-winkel (if (= dlg-aus-winkel "1") "30" "90"))
(setq es-winkel (if (= dlg-ein-winkel "1") "30" "90"))
(list
(atof dlg-deltal)
(atof dlg-winkel)
hz-winkel
as-seite
es-seite
(atof dlg-hoehe)
as-winkel
es-winkel)
)
nil
)
)
)
)
;; Gemeinsamer Abschluss fuer Modus 1 + 2: Laengenberechnung,
;; Zusammenfassung, Bestaetigung und Einfuegen.
;; startpunkt: Einfuegepunkt AUS-Element (inkl. Z aus Einfuegehoehe)
;; as-winkel/es-winkel: "30" oder "90" (Element-Variante)
(defun gf-modus12-abschluss (deltaL winkel hz-winkel as-seite es-seite startpunkt
as-winkel es-winkel /
rad sep-x L_stau antwort)
(if (null as-winkel) (setq as-winkel "90"))
(if (null es-winkel) (setq es-winkel "90"))
(setq winkel (float winkel))
(setq rad (* winkel (/ pi 180.0)))
(princ (ssg-textf "gf-status-winkel" (list (rtos winkel 2 1) grad-zeichen)))
;; AS-/ES-Masse fuer die gewaehlte Winkel-/Seiten-Variante setzen
;; (aktualisiert aus-dx/ein-dx vor der Laengenberechnung)
(vf-set-as-masse as-winkel as-seite)
(vf-set-es-masse es-winkel es-seite)
;; Laengenberechnung
;; deltaL = aus_dx + L_stau*cos(rad) + sep*cos(rad) + ein_dx
(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)))
;; Validierung
(if (<= L_stau 0.1)
(progn
(alert (ssg-textf "gf-alert-staustrecke-ungueltig" (list (rtos L_stau 2 2))))
(exit)
)
)
;; Zusammenfassung
(princ "\n\n=========================================")
(princ (ssg-textf "gf-status-fahrtrichtung" (list (rtos hz-winkel 2 1) grad-zeichen)))
(princ (ssg-textf "gf-status-zus2-winkel" (list (rtos winkel 2 1) grad-zeichen)))
(princ (ssg-textf "gf-status-zus2-aus-seite" (list as-seite)))
(princ (ssg-textf "gf-status-zus2-ein-seite" (list es-seite)))
(princ (ssg-textf "gf-status-zus2-lstau" (list (rtos L_stau 2 2))))
(princ "\n=========================================")
;; Bestaetigung
(setq antwort (getstring (ssg-text "gf-prompt-einfuegen")))
(if (not (= antwort "2"))
(gefaellestrecke-einfuegen L_stau (fix winkel) startpunkt as-seite es-seite hz-winkel deltaL as-winkel es-winkel)
(princ (ssg-text "gf-status-abgebrochen"))
)
)
;; Nicht-interaktiver Neuaufbau (fuer GEFAELLESTRECKE_EDIT): Element-Masse
;; setzen, L_stau berechnen und einfuegen - ohne Zusammenfassung/Rueckfrage.
;; Rueckgabe: (ename deltaH deltaL) von gefaellestrecke-einfuegen oder nil.
(defun gf-rebuild (deltaL winkel hz-winkel as-seite es-seite startpunkt
as-winkel es-winkel /
rad sep-x L_stau)
(if (null as-winkel) (setq as-winkel "90"))
(if (null es-winkel) (setq es-winkel "90"))
(setq winkel (float winkel))
(setq rad (* winkel (/ pi 180.0)))
(vf-set-as-masse as-winkel as-seite)
(vf-set-es-masse es-winkel es-seite)
(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)))
(if (<= L_stau 0.1)
(progn
(alert (ssg-textf "gf-alert-staustrecke-ungueltig" (list (rtos L_stau 2 2))))
nil
)
(gefaellestrecke-einfuegen
L_stau (fix winkel) startpunkt as-seite es-seite hz-winkel deltaL as-winkel es-winkel)
)
)
;; ============================================================
;; XDATA-Metadaten fuer den Edit-Nachbau (App "SSG_GF_EDIT").
;; Bewusst NICHT im Sivas-Attributsatz, damit der Export unveraendert bleibt.
;; ============================================================
(if (null *gf-xdata-app*) (setq *gf-xdata-app* "SSG_GF_EDIT"))
;; Fahrtrichtung/Winkel/Element-Varianten als XDATA auf das GF_N-INSERT schreiben.
(defun gf-xdata-schreiben (ent hz winkel as-winkel es-winkel z-start deltaL /)
(regapp *gf-xdata-app*)
(entmod
(append (entget ent)
(list
(list -3
(list *gf-xdata-app*
(cons 1000 (rtos (float hz) 2 4))
(cons 1000 (rtos (float winkel) 2 4))
(cons 1000 (if as-winkel as-winkel "90"))
(cons 1000 (if es-winkel es-winkel "90"))
(cons 1000 (rtos (float z-start) 2 4))
(cons 1000 (rtos (float deltaL) 2 4)))))))
ent
)
;; XDATA lesen -> (hz-str winkel-str as-winkel es-winkel z-str deltaL-str) oder nil.
(defun gf-xdata-lesen (ent / xd app-data)
(setq xd (entget ent (list *gf-xdata-app*)))
(setq app-data (cdr (assoc -3 xd)))
(if app-data
(mapcar 'cdr (cdr (car app-data)))
nil
)
)
;; ============================================================
;; TEIL 6: HAUPTBEFEHL
;; ============================================================
(defun c:GEFAELLESTRECKE ( / antwort eingabe-modus deltaL winkel rad L_stau sep-x
(defun c:GEFAELLESTRECKE ( / antwort deltaL winkel
as-seite es-seite gf-as-winkel gf-es-winkel
line-points startpunkt endpunkt differenz
deltaX deltaY startpunkt-fuer-einfuegen hz-winkel)
deltaX deltaY startpunkt-fuer-einfuegen hz-winkel
dlg-werte)
(princ "\n=========================================")
(princ (ssg-text "gf-banner-titel"))
@@ -1655,95 +1893,52 @@
(gf-linienzug-modus)
)
;; Modus 1+2: einfache Gefaellestrecke
(t
(if (= antwort "2")
(setq eingabe-modus "Linie")
(setq eingabe-modus "Manuell")
;; Modus 2: 3D-Linie (Konsoleneingabe)
((= antwort "2")
(princ (ssg-text "gf-modus2-header"))
(command "BKS" "W")
(princ (ssg-text "gf-status-bks-welt"))
(setq line-points
(get-line-start-end-points
(ssg-text "gf-prompt-3dlinie-richtung")))
(if (null line-points)
(progn (alert (ssg-text "gf-alert-keine-linie")) (exit))
)
;; Modus 1: Manuelle Eingabe
(if (= eingabe-modus "Manuell")
(progn
(princ (ssg-text "gf-modus1-header"))
(setq startpunkt-fuer-einfuegen
(getpoint (ssg-text "gf-prompt-startpunkt-aus")))
(if (null startpunkt-fuer-einfuegen)
(setq startpunkt-fuer-einfuegen '(0 0 0)))
(setq deltaL (getreal (ssg-textf "gf-prompt-deltal-abstand" (list delta-sym))))
(if (or (null deltaL) (<= deltaL 0))
(setq deltaL (ssg-cfg-or "gefaelle" "default_delta_l" 5000.0)))
)
;; Modus 2: 3D-Linie
(progn
(princ (ssg-text "gf-modus2-header"))
(command "BKS" "W")
(princ (ssg-text "gf-status-bks-welt"))
(setq line-points
(get-line-start-end-points
(ssg-text "gf-prompt-3dlinie-richtung")))
(if (null line-points)
(progn (alert (ssg-text "gf-alert-keine-linie")) (exit))
)
(setq startpunkt (car line-points)
endpunkt (cadr line-points))
(setq differenz (punkt-differenz startpunkt endpunkt))
(setq deltaX (car differenz)
deltaY (cadr differenz))
;; deltaL: horizontale 2D-Projektion entlang Fahrtrichtung
(setq deltaL (sqrt (+ (* deltaX deltaX) (* deltaY deltaY))))
;; hz-Winkel: Fahrtrichtung aus Linienpunkten (in Grad, 0=Ost)
(setq hz-winkel (* (angle '(0.0 0.0) (list deltaX deltaY)) (/ 180.0 pi)))
(princ (ssg-textf "gf-status-fahrtrichtung-linie" (list (rtos hz-winkel 2 1) grad-zeichen)))
(princ (ssg-textf "gf-status-deltal-mm" (list delta-sym (rtos deltaL 2 2))))
;; Startpunkt separat waehlen (unabhaengig von Linie)
(setq startpunkt-fuer-einfuegen
(getpoint (ssg-text "gf-prompt-startpunkt-aus")))
(if (null startpunkt-fuer-einfuegen)
(progn (princ (ssg-text "gf-fehler-kein-startpunkt")) (exit))
)
)
(setq startpunkt (car line-points)
endpunkt (cadr line-points))
(setq differenz (punkt-differenz startpunkt endpunkt))
(setq deltaX (car differenz)
deltaY (cadr differenz))
;; deltaL: horizontale 2D-Projektion entlang Fahrtrichtung
(setq deltaL (sqrt (+ (* deltaX deltaX) (* deltaY deltaY))))
;; hz-Winkel: Fahrtrichtung aus Linienpunkten (in Grad, 0=Ost)
(setq hz-winkel (* (angle '(0.0 0.0) (list deltaX deltaY)) (/ 180.0 pi)))
(princ (ssg-textf "gf-status-fahrtrichtung-linie" (list (rtos hz-winkel 2 1) grad-zeichen)))
(princ (ssg-textf "gf-status-deltal-mm" (list delta-sym (rtos deltaL 2 2))))
;; Startpunkt separat waehlen (unabhaengig von Linie)
(setq startpunkt-fuer-einfuegen
(getpoint (ssg-text "gf-prompt-startpunkt-aus")))
(if (null startpunkt-fuer-einfuegen)
(progn (princ (ssg-text "gf-fehler-kein-startpunkt")) (exit))
)
(princ "\n\n=========================================")
(princ (ssg-textf "gf-status-deltal-mm" (list delta-sym (rtos deltaL 2 2))))
(princ "\n=========================================")
;; Winkelabfrage (beide Modi: manuell)
;; Winkelabfrage
(setq winkel (getreal (ssg-text "gf-prompt-gefaellewinkel-def3")))
(if (or (null winkel) (<= winkel 0))
(setq winkel (ssg-cfg-or "gefaelle" "default_winkel" 3.0)))
(setq winkel (float winkel))
(setq rad (* winkel (/ pi 180.0)))
(princ (ssg-textf "gf-status-winkel" (list (rtos winkel 2 1) grad-zeichen)))
;; Fahrtrichtung waehlen (nur Modus 1; Modus 2 berechnet hz aus Linie)
(if (= eingabe-modus "Manuell")
(progn
(princ (ssg-text "vfc-fahrtrichtung-header"))
(princ (ssg-textf "vfc-fahrtrichtung-0" (list grad-zeichen)))
(princ (ssg-textf "vfc-fahrtrichtung-90" (list grad-zeichen)))
(princ (ssg-textf "vfc-fahrtrichtung-180" (list grad-zeichen)))
(princ (ssg-textf "vfc-fahrtrichtung-270" (list grad-zeichen)))
(setq antwort (getstring (ssg-text "prompt-wahl-1-2-3-4")))
(cond
((= antwort "2") (setq hz-winkel 90.0))
((= antwort "3") (setq hz-winkel 180.0))
((= antwort "4") (setq hz-winkel 270.0))
(t (setq hz-winkel 0.0))
)
(princ (ssg-textf "gf-status-fahrtrichtung" (list (rtos hz-winkel 2 1) grad-zeichen)))
)
)
;; AUS-Element: 30/90 (vor Seite) + Seite, dann Masse fuer Variante setzen
;; AUS-Element: 30/90 + Seite
(setq gf-as-winkel (vf-frage-element-winkel "vf-winkel-aus-header"))
(princ (ssg-text "gf-seite-aus-header"))
(princ (ssg-text "gf-seite-links"))
(princ (ssg-text "gf-seite-rechts"))
(setq antwort (getstring (ssg-text "prompt-wahl-1-2")))
(setq as-seite (if (= antwort "2") "rechts" "links"))
(vf-set-as-masse gf-as-winkel as-seite)
;; EIN-Element: 30/90 + Seite
(setq gf-es-winkel (vf-frage-element-winkel "vf-winkel-ein-header"))
@@ -1752,41 +1947,148 @@
(princ (ssg-text "gf-seite-rechts"))
(setq antwort (getstring (ssg-text "prompt-wahl-1-2")))
(setq es-seite (if (= antwort "2") "rechts" "links"))
(vf-set-es-masse gf-es-winkel es-seite)
;; Laengenberechnung (aus-dx/ein-dx jetzt fuer die gewaehlte Variante)
;; deltaL = aus_dx + L_stau*cos(rad) + sep*cos(rad) + ein_dx
(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)))
;; Gemeinsamer Abschluss (Masse, Laenge, Zusammenfassung, Einfuegen)
(gf-modus12-abschluss deltaL winkel hz-winkel as-seite es-seite
startpunkt-fuer-einfuegen gf-as-winkel gf-es-winkel)
)
;; Validierung
(if (<= L_stau 0.1)
(progn
(alert (ssg-textf "gf-alert-staustrecke-ungueltig" (list (rtos L_stau 2 2))))
(exit)
)
)
;; Zusammenfassung
(princ "\n\n=========================================")
(princ (ssg-textf "gf-status-fahrtrichtung" (list (rtos hz-winkel 2 1) grad-zeichen)))
(princ (ssg-textf "gf-status-zus2-winkel" (list (rtos winkel 2 1) grad-zeichen)))
(princ (ssg-textf "gf-status-zus2-aus-seite" (list as-seite)))
(princ (ssg-textf "gf-status-zus2-ein-seite" (list es-seite)))
(princ (ssg-textf "gf-status-zus2-lstau" (list (rtos L_stau 2 2))))
(princ "\n=========================================")
;; Bestaetigung
(setq antwort (getstring (ssg-text "gf-prompt-einfuegen")))
(if (not (= antwort "2"))
(gefaellestrecke-einfuegen L_stau (fix winkel) startpunkt-fuer-einfuegen as-seite es-seite hz-winkel deltaL gf-as-winkel gf-es-winkel)
;; Modus 1: Manuelle Eingabe via DCL-Dialog
(t
(princ (ssg-text "gf-modus1-header"))
;; Startpunkt (X/Y) in der Zeichnung waehlen; Z kommt aus dem Dialog
(setq startpunkt-fuer-einfuegen
(getpoint (ssg-text "gf-prompt-startpunkt-aus")))
(if (null startpunkt-fuer-einfuegen)
(setq startpunkt-fuer-einfuegen '(0 0 0)))
(setq dlg-werte (gf-dialog-eingabe nil))
(if (null dlg-werte)
(princ (ssg-text "gf-status-abgebrochen"))
(progn
(setq deltaL (nth 0 dlg-werte)
winkel (nth 1 dlg-werte)
hz-winkel (nth 2 dlg-werte)
as-seite (nth 3 dlg-werte)
es-seite (nth 4 dlg-werte)
gf-as-winkel (nth 6 dlg-werte)
gf-es-winkel (nth 7 dlg-werte))
;; Einfuegehoehe (Z) aus Dialog auf gewaehlten Startpunkt anwenden
(setq startpunkt-fuer-einfuegen
(list (car startpunkt-fuer-einfuegen)
(cadr startpunkt-fuer-einfuegen)
(nth 5 dlg-werte)))
(if (or (null deltaL) (<= deltaL 0))
(setq deltaL (ssg-cfg-or "gefaelle" "default_delta_l" 5000.0)))
(if (or (null winkel) (<= winkel 0))
(setq winkel (ssg-cfg-or "gefaelle" "default_winkel" 3.0)))
(gf-modus12-abschluss deltaL winkel hz-winkel as-seite es-seite
startpunkt-fuer-einfuegen gf-as-winkel gf-es-winkel)
)
)
)
)
nil
)
;; ============================================================
;; TEIL 7: GEFAELLESTRECKE_EDIT - Doppelklick/Kontextmenue-Bearbeitung
;; ============================================================
;; Bearbeitet eine bestehende Gefaellestrecke (GF_n-Block) ueber den
;; DCL-Dialog: liest die aktuellen Parameter (XDATA, sonst Attribute),
;; zeigt sie vorbelegt im Dialog und baut die Strecke bei OK am selben
;; Startpunkt neu auf. Wird vom Doppelklick-Dispatcher SSG_BLOCKEDIT
;; fuer Blocknamen "GF_*" aufgerufen.
(defun c:GEFAELLESTRECKE_EDIT ( / ss ent ed bname startpunkt attribs xd
hz winkel as-winkel es-winkel z-start deltaL
prefill dlg-werte)
;; Implied Selection VOR ssg-start pruefen (ssg-start hebt Selektion auf)
(setq ss (ssget "I"))
(if (and ss (= (sslength ss) 1)
(= (cdr (assoc 0 (entget (ssname ss 0)))) "INSERT"))
(setq ent (ssname ss 0))
)
(ssg-start "GEFAELLESTRECKE_EDIT" '(("OSMODE") ("ATTREQ") ("ATTDIA")))
(setvar "OSMODE" 0)
;; Block auswaehlen (falls nicht vorselektiert)
(if (null ent)
(progn
(setq ss (ssget ":S" '((0 . "INSERT"))))
(if ss (setq ent (ssname ss 0)))
)
)
(if (null ent) (progn (ssg-end) (exit)))
(setq ed (entget ent))
(setq bname (cdr (assoc 2 ed)))
(if (not (wcmatch bname "GF_*"))
(progn (alert (ssg-textf "gf-edit-kein-gf" (list bname))) (ssg-end) (exit)))
(setq startpunkt (cdr (assoc 10 ed)))
(setq attribs (ssg-attrib-read ent))
;; Nur einfache Gefaellestrecken (TYP "Gefaellestrecke") lassen sich ueber den
;; Dialog verlustfrei nachbauen. Streckengruppen (mit Bogen / Linienzug / VF)
;; wuerden beim Neuaufbau ihre Bogengeometrie verlieren -> abbrechen.
(if (/= (cond ((cdr (assoc "TYP" attribs))) ("")) "Gefaellestrecke")
(progn
(alert (ssg-textf "gf-edit-nur-einfach"
(list (cond ((cdr (assoc "TYP" attribs))) ("?")))))
(ssg-end)
(exit)
)
)
;; Parameter bestimmen: bevorzugt aus XDATA (verlustfrei), sonst aus Attributen.
;; Aus Attributen sind Fahrtrichtung (hz) und Element-Winkel nicht ableitbar
;; -> Default 0 Grad / 90 Grad; der Nutzer kann sie im Dialog korrigieren.
(setq xd (gf-xdata-lesen ent))
(if xd
(setq hz (atof (nth 0 xd))
winkel (atof (nth 1 xd))
as-winkel (nth 2 xd)
es-winkel (nth 3 xd)
z-start (atof (nth 4 xd))
deltaL (atof (nth 5 xd)))
(setq hz 0.0
winkel (atof (cond ((cdr (assoc "GF_WINKEL" attribs))) ("3.0")))
as-winkel "90"
es-winkel "90"
z-start (atof (cond ((cdr (assoc "HOEHE_VON_mm" attribs))) ("0")))
deltaL (atof (cond ((cdr (assoc "DELTA_L_mm" attribs))) ("0"))))
)
(setq prefill
(list (cons "deltaL" deltaL)
(cons "winkel" winkel)
(cons "hz" hz)
(cons "as-seite" (cond ((cdr (assoc "SEITE_AS" attribs))) ("links")))
(cons "es-seite" (cond ((cdr (assoc "SEITE_ES" attribs))) ("links")))
(cons "einfuegehoehe" z-start)
(cons "as-winkel" as-winkel)
(cons "es-winkel" es-winkel)))
(setq dlg-werte (gf-dialog-eingabe prefill))
(if (null dlg-werte)
(princ (ssg-text "gf-status-abgebrochen"))
(progn
;; Alten GF-Verbund loeschen und am selben Startpunkt (X/Y) mit der
;; im Dialog gewaehlten Einfuegehoehe (Z) neu aufbauen.
(entdel ent)
(gf-rebuild
(nth 0 dlg-werte) (nth 1 dlg-werte) (nth 2 dlg-werte)
(nth 3 dlg-werte) (nth 4 dlg-werte)
(list (car startpunkt) (cadr startpunkt) (nth 5 dlg-werte))
(nth 6 dlg-werte) (nth 7 dlg-werte))
(princ (ssg-textf "gf-edit-neu-aufgebaut" (list bname)))
)
)
(ssg-end)
(princ)
)
;; ============================================================
;; START
;; ============================================================
+8 -8
View File
@@ -72,7 +72,7 @@
;; Attribut-Definitionen: ((TAG DEFAULT) ...)
(setq *kreisel-attrib-defs*
'(("NAME" "")
'(("Bezeichnung" "")
("DREHRICHTUNG" "UZS")
("ANZAHL_SEPARATOR" "2")
("KREISELART" "STANDARD")
@@ -90,7 +90,7 @@
;; Eckrad Attribut-Definitionen: ((TAG DEFAULT) ...)
(setq *eckrad-attrib-defs*
'(("NAME" "")
'(("Bezeichnung" "")
("DREHRICHTUNG" "UZS")
("DREHUNG" "0")
("NUMMER" "0")
@@ -325,9 +325,9 @@
)
)
;; NAME automatisch setzen: "KreiselN"
(setq attribs (subst (cons "NAME" (strcat "Kreisel" (itoa kreisel-nummer)))
(assoc "NAME" attribs) attribs))
;; Bezeichnung automatisch setzen: "KreiselN"
(setq attribs (subst (cons "Bezeichnung" (strcat "Kreisel" (itoa kreisel-nummer)))
(assoc "Bezeichnung" attribs) attribs))
;; --- HÖHE BESTIMMEN ---
;; Priorität 1: Aus basePoint (wenn 3D Punkt mit Z > 0)
@@ -928,7 +928,7 @@
)
;; Tiles initialisieren
(set_tile "name" (cdr (assoc "NAME" attribs)))
(set_tile "name" (cdr (assoc "Bezeichnung" attribs)))
(set_tile "abstand" (cdr (assoc "ABSTAND" attribs)))
(set_tile "hoehe" (cdr (assoc "HOEHE" attribs)))
@@ -976,8 +976,8 @@
(setq newRotation (kreisel-idx-to-rotation (atoi dlg-ausrichtung)))
;; Attribute aktualisieren
(setq attribs (subst (cons "NAME" dlg-name)
(assoc "NAME" attribs) attribs))
(setq attribs (subst (cons "Bezeichnung" dlg-name)
(assoc "Bezeichnung" attribs) attribs))
(setq attribs (subst (cons "HOEHE" dlg-hoehe)
(assoc "HOEHE" attribs) attribs))
(setq attribs (subst (cons "KREISELART"
+52 -5
View File
@@ -233,9 +233,30 @@ Lädt alle Module in der richtigen Reihenfolge. Ermittelt den Pfad automatisch
### `VarioFoerderer.lsp` Vario-Förderer
Parametrischer Generator für ILS Vario-Förderanlagen. Liest Block-Geometrie aus einer DWG-Bibliothek (`DXFM_BLOCKS`). Alle Konstanten (Abstände, Winkel, Skalierung) werden via `ssg-cfg-or` aus `component_defaults.json` (Sektion `vario`) gelesen.
Kompatibilitäts-Wrapper, der `vf_core.lsp` lädt (Plugin-Dispatcher-Architektur; lädt seinerseits `vf_standard.lsp`, `vf_etage.lsp`, `vf_linienzug.lsp`). Parametrischer Generator für ILS Vario-Förderanlagen. Liest Block-Geometrie aus einer DWG-Bibliothek (`DXFM_BLOCKS`). Alle Konstanten (Abstände, Winkel, Skalierung) werden via `ssg-cfg-or` aus `component_defaults.json` (Sektion `vario`) gelesen.
**Befehl:** `c:FOERDERANLAGE`
**Befehl:** `c:FOERDERANLAGE` / `c:VarioFoerderer` wählt zuerst den Anlagen-Typ (Standard/Etage/Linienzug):
- **Typ „standard“ + Werteingabe:** läuft über den DCL-Dialog
[`dcl/variofoerderer.dcl`](../dcl/variofoerderer.dcl) (zwei Dialoge, `vfs-standard-dialog-ablauf`
in `vf_standard.lsp`): Dialog 1 (`vfs-dialog-eingabe-basis`) erfasst deltaL, deltaH,
Förderrichtung (Auf/Ab), Einfügehöhe, Fahrtrichtung und Seite; anschließend berechnet
`berechne-standard` die gültigen Winkel-Varianten, und Dialog 2
(`vfs-dialog-winkel-verteilung`) lässt Winkel und L_GF-Verteilung (vorne/hinten) wählen.
Startpunkt (X/Y) wird wie bei der Gefällestrecke vorher in der Zeichnung gepickt.
- **Typ „standard“ + 3D-Linie**, sowie **Typ „etage“** und **„linienzug“** bleiben
vollständig interaktiv (Kommandozeile), unverändert gegenüber dem bisherigen Ablauf.
**Bearbeiten (`c:VARIOFOERDERER_EDIT`):** Doppelklick auf einen `VF_n`-Block bzw.
Rechtsklick-Kontextmenü/`SSG_BLOCKEDIT` öffnet dieselben Dialoge, vorbelegt mit den
aktuellen Parametern, und baut die Strecke bei OK am selben Startpunkt neu auf (neue
`VF_n`-Nummer). Da `VF_n`-Blöcke auch von Etage- und Linienzug-Anlagen erzeugt werden
(deren komplexere Geometrie ein einfacher Neuaufbau zerstören würde), markiert
`vfs-xdata-schreiben` nur per Standard-Dialog erstellte Blöcke mit XDATA (App
`SSG_VF_EDIT`, Fahrtrichtung `hz`); Blöcke ohne diese Markierung weist
`c:VARIOFOERDERER_EDIT` mit einer Meldung ab, statt sie zu verändern. Winkel und L_GF1
werden aus den Sivas-Attributen (`VF_WINKEL`, `L_GF_m`) vorbelegt (Verteilung stets als
„Eigene Werte“ mit dem exakten aktuellen L_GF1).
**Wichtige interne Funktionen** (werden auch von `Gefaellestrecke.lsp` genutzt):
@@ -260,10 +281,36 @@ Setzt `VarioFoerderer.lsp` voraus (nutzt dessen `init-bibliothek`, `insert-block
**Befehl:** `c:GEFAELLESTRECKE`
Zwei Modi:
Drei Modi:
- **Modus 1:** Startpunkt + ΔL (Horizontalabstand) interaktiv abfragen
- **Modus 2:** Bestehende 3D-Linie wählen (ΔL und Winkel werden daraus berechnet)
- **Modus 1:** Startpunkt (X/Y) picken, restliche Parameter über den DCL-Dialog
[`dcl/gefaellestrecke.dcl`](../dcl/gefaellestrecke.dcl) eingeben (ΔL, Einfügehöhe Z,
Gefällewinkel, Fahrtrichtung, AUS-/EIN-Element je Winkel 30/90 und Seite links/rechts).
Die Einfügehöhe aus dem Dialog setzt die Z-Koordinate des Startpunkts.
- **Modus 2:** Bestehende 3D-Linie wählen (ΔL und Fahrtrichtung werden daraus berechnet),
restliche Parameter interaktiv über die Kommandozeile.
- **Modus 3:** Linienzug aus LINE-/ARC-Objekten; ARC-Segmente werden durch
Gefällebogen-Blöcke ersetzt, Winkel aus ΔH und Geometrie berechnet.
**Dialog-Hilfsfunktionen:** `gf-dialog-eingabe` (lädt/liest den DCL-Dialog, liefert
`(deltaL winkel hz-winkel as-seite es-seite einfuegehoehe as-winkel es-winkel)` oder `nil`
bei Abbruch) und `gf-modus12-abschluss` (gemeinsamer Abschluss für Modus 1+2: setzt die
Element-Masse per `vf-set-as-masse`/`vf-set-es-masse`, berechnet die Staustreckenlänge,
zeigt die Zusammenfassung und ruft `gefaellestrecke-einfuegen`).
Die AUS-/EIN-Element-Varianten (30/90 Grad, links/rechts) liegen als DWG-Blöcke
`AS_Element_<30|90>_<links|rechts>` bzw. `ES_Element_…` in `data/ils/2D|3D/`; ihre Maße
werden direkt aus dem Block gemessen (`vf-element-masse`), es gibt dafür keine JSON-Tabelle.
**Bearbeiten (`c:GEFAELLESTRECKE_EDIT`):** Doppelklick auf einen Gefällestrecken-Block
(`GF_n`) bzw. Rechtsklick-Kontextmenü/`SSG_BLOCKEDIT` öffnet denselben DCL-Dialog,
vorbelegt mit den aktuellen Parametern, und baut die Strecke bei OK am selben Startpunkt
neu auf. Damit Fahrtrichtung und Element-Winkel (30/90) verlustfrei rekonstruiert werden,
schreibt `gefaellestrecke-einfuegen` diese beim Erstellen als XDATA (App `SSG_GF_EDIT`,
Helfer `gf-xdata-schreiben`/`gf-xdata-lesen`) auf das `GF_n`-INSERT bewusst **nicht** in
den Sivas-Attributsatz, damit der Export unverändert bleibt. Ältere Blöcke ohne XDATA
werden aus den Attributen vorbelegt (Fahrtrichtung 0°, Element-Winkel 90° als Vorgabe).
Der Neuaufbau läuft über `gf-rebuild` (nicht-interaktiv, ohne Konsolen-Rückfrage).
---
+63
View File
@@ -15,6 +15,55 @@
(princ)
)
;; --- ILS / Zusatzmodul: Sensoren (Scanner / Separator) einfuegen ---
;; Ermittelt den Pfad zu einer Sensor-Blockdatei. Die Sensor-Bloecke
;; werden fest aus data/ils/3D geladen (unabhaengig von der
;; 2D/3D-Umschaltung).
(defun ils-sensor-pfad (fname / p)
(setq p (strcat (getenv "DXFMAKRO") "\\data\\ils\\3D\\" fname ".dwg"))
(if (findfile p) p nil)
)
;; Fuegt einen Sensor-Block wiederholt ein, bis der Benutzer mit
;; ENTER oder ESC abbricht. Rotation je Einfuegung interaktiv.
(defun ils-insert-sensor (fname / pfad pt oldattreq n res)
(setq pfad (ils-sensor-pfad fname))
(if (null pfad)
(princ (strcat "\n>>> FEHLER: Blockdatei '" fname ".dwg' nicht gefunden."
" (in data/ils/3D pruefen)"))
(progn
(setq oldattreq (getvar "ATTREQ"))
(setvar "ATTREQ" 0)
(setq n 0)
;; Punkt abfragen; ENTER liefert nil, ESC einen abgefangenen Fehler -
;; beides beendet die Schleife sauber (ATTREQ wird wiederhergestellt).
(while
(progn
(setq res (vl-catch-all-apply
'getpoint
(list (strcat "\nEinfuegepunkt fuer " fname " [ENTER=Ende]: "))))
(and (not (vl-catch-all-error-p res)) res)
)
(setq pt res)
(command "_.INSERT" pfad pt "" "" pause)
(setq n (1+ n))
)
(setvar "ATTREQ" oldattreq)
(princ (strcat "\n>>> " (itoa n) " x " fname " eingefuegt."))
)
)
(princ)
)
(defun c:ILS_SCANNER_INSERT ()
(ils-insert-sensor "Scanner")
)
(defun c:ILS_SEPARATOR_INSERT ()
(ils-insert-sensor "Separator_SP")
)
;; --- ILS / Foerderer ---
(defun c:ILS_TEF_Strecke ()
(princ "\n[DUMMY] ILS_TEF_Strecke aufgerufen")
@@ -219,6 +268,20 @@
(command "_.BEDIT" bname)
)
;; Gefaellestrecke-Bloecke (GF_n) -> GEFAELLESTRECKE_EDIT (DCL-Dialog)
((wcmatch bname "GF_*")
(princ (ssg-textf "cmd-gefaelle-bearbeiten" (list bname)))
(c:GEFAELLESTRECKE_EDIT)
)
;; VarioFoerderer-Bloecke (VF_n) -> VARIOFOERDERER_EDIT (DCL-Dialog);
;; weist Bloecke ohne SSG_VF_EDIT-XDATA (Etage/Linienzug/Altbestand)
;; intern selbst ab, siehe c:VARIOFOERDERER_EDIT in vf_standard.lsp.
((wcmatch bname "VF_*")
(princ (ssg-textf "cmd-variofoerderer-bearbeiten" (list bname)))
(c:VARIOFOERDERER_EDIT)
)
;; Omniflo-Bloecke -> OMNI_EDIT
;; Erkennung: TEILEART-Attribut vorhanden, AP110-Blockname oder rein numerisch
((progn
+24 -15
View File
@@ -6,11 +6,14 @@
;;; Gefaellestrecke) und schreibt die Anzahlen in die Attribute
;;; des jeweiligen ILS-Blocks. Anschliessend QSAVE.
;;;
;;; Zuordnung eines Sensors zu einem ILS-Block:
;;; - Der geometrische Mittelpunkt (X/Y) des Sensors (Zentrum
;;; seiner eigenen Bounding-Box, unabhaengig vom $INSBASE)
;;; muss in der achsparallelen Bounding-Box des ILS-Blocks
;;; liegen (Z wird ignoriert).
;;; Zuordnung eines Sensors zu einem ILS-Block (Z wird ignoriert):
;;; - Scanner: der Einfuegepunkt (X/Y) muss in der Bounding-Box
;;; des ILS-Blocks liegen. Die 3D-Geometrie des Scanners kann
;;; weit vom Einfuegepunkt entfernt sein, daher zaehlt hier der
;;; Einfuegepunkt (dort klickt der Benutzer auf den Block).
;;; - Separator: der geometrische Mittelpunkt (Zentrum der eigenen
;;; Bounding-Box, unabhaengig vom $INSBASE) muss in der
;;; Bounding-Box des ILS-Blocks liegen.
;;; - Liegt der Punkt in mehreren Boxen (Ueberlappung), wird
;;; der ILS-Block mit dem naechstgelegenen Box-Zentrum gewaehlt.
;;; - Ein optionaler Toleranzrand (*senstol*) vergroessert die
@@ -112,17 +115,23 @@
)
;;; ------------------------------------------------------------
;;; Referenzpunkt eines Sensors: geometrischer Mittelpunkt seiner
;;; eigenen Bounding-Box (X/Y). Unabhaengig vom $INSBASE der
;;; Sensor-DWG. Fallback auf den Einfuegepunkt, falls die Box
;;; nicht ermittelbar ist.
;;; Referenzpunkt eines Sensors (X/Y), je nach Typ:
;;; - Scanner : Einfuegepunkt (DXF-Gruppe 10).
;;; - Separator : geometrischer Mittelpunkt seiner eigenen
;;; Bounding-Box (unabhaengig vom $INSBASE),
;;; Fallback auf den Einfuegepunkt.
;;; ------------------------------------------------------------
(defun cs-sensor-point (ent ed / bb)
(setq bb (cs-bbox ent))
(if bb
(list (/ (+ (nth 0 bb) (nth 2 bb)) 2.0)
(/ (+ (nth 1 bb) (nth 3 bb)) 2.0))
(defun cs-sensor-point (ent ed kind / bb)
(if (eq kind 'scanner)
(cdr (assoc 10 ed))
(progn
(setq bb (cs-bbox ent))
(if bb
(list (/ (+ (nth 0 bb) (nth 2 bb)) 2.0)
(/ (+ (nth 1 bb) (nth 3 bb)) 2.0))
(cdr (assoc 10 ed))
)
)
)
)
@@ -271,7 +280,7 @@
(setq kind (cs-sensor-kind nm))
(if kind
(progn
(setq pt (cs-sensor-point ent ed))
(setq pt (cs-sensor-point ent ed kind))
(if (eq kind 'scanner)
(setq scanpts (cons pt scanpts))
(setq seppts (cons pt seppts)))))
+26 -5
View File
@@ -1151,8 +1151,9 @@
(if (car (atoms-family 1 '("SSG-ID-GENERATE")))
(ssg-id-generate vf-insert))
(princ (ssg-textf "vfc-block-erstellt-eingefuegt" (list vf-bname)))
vf-insert
)
(princ (ssg-text "vfc-fehler-keine-entities"))
(progn (princ (ssg-text "vfc-fehler-keine-entities")) nil)
)
)
@@ -1247,10 +1248,10 @@
(princ "\n 3 - 3D-Objekte stueckweise (Vorwaerts-Nachbau, in Arbeit)")
(setq wahl (getint "\nIhre Wahl (1/2/3) [1]: "))
;; Konsolen-Nummer -> interne Funktion:
;; 2 = fertiger Ziel-Hoehe-Modus (intern vf-linienzug-modus3)
;; 3 = alter Vorwaerts-Nachbau (intern vf-linienzug-modus2, wird umgebaut)
(cond ((= wahl 2) (vf-linienzug-modus3))
((= wahl 3) (vf-linienzug-modus2))
;; 2 = fertiger Ziel-Hoehe-Modus (intern vf-linienzug-modus2)
;; 3 = alter Vorwaerts-Nachbau (intern vf-linienzug-modus3, wird umgebaut)
(cond ((= wahl 2) (vf-linienzug-modus2))
((= wahl 3) (vf-linienzug-modus3))
(t (vf-linienzug-modus)))
(exit)
)
@@ -1260,6 +1261,26 @@
(setq vf-nummer (vf-next-number))
(princ (ssg-textf "vfc-naechste-vf-nummer" (list (itoa vf-nummer))))
;; 2b. Standardfall (anlage-typ "standard") + Werteingabe -> DCL-Dialog
;; (dcl/variofoerderer.dcl, siehe vf_standard.lsp: vfs-standard-dialog-ablauf).
;; 3D-Linie-Eingabe und alle anderen Anlagen-Typen (Etage, Linienzug) bleiben
;; unveraendert interaktiv (fallen unten in den bestehenden Konsolen-Ablauf,
;; der die Eingabemodus-Frage dabei erneut stellt - siehe vf-eingabe-abfragen).
(if (= anlage-typ "standard")
(progn
(princ (ssg-text "vfc-eingabemodus-header"))
(princ (ssg-text "vfc-eingabemodus-3dlinie"))
(princ (ssg-text "vfc-eingabemodus-werte"))
(setq antwort (getstring (ssg-text "vfc-prompt-wahl-1-2-ohne-default")))
(if (= antwort "2")
(progn
(vfs-standard-dialog-ablauf vf-nummer)
(exit)
)
)
)
)
;; 3. Gemeinsame Eingabe (deltaL, deltaH, richtung, startpunkt) - richtung
;; steht bei beiden Eingabemodi (Werteingabe UND 3D-Linie) bereits fest.
(setq eingabe (vf-eingabe-abfragen))
+94 -89
View File
@@ -1386,7 +1386,7 @@
(foreach x liste (setq d (abs (- x w))) (if (< d bd) (setq bd d best x)))
best)
(defun vf-linienzug-modus2 ( / ss k obj-liste startpunkt start-hoehe as-seite
(defun vf-linienzug-modus3 ( / ss k obj-liste startpunkt start-hoehe as-seite
es-seite kette segmente n i seg typ hz laenge
bwinkel bseite frame antwort winkel deltaL
anzahl-gf anzahl-vf vfl-nummer lastEnt hoehe-bis
@@ -1770,7 +1770,7 @@
(- (/ (- ep-na (* perp-es np-na)) dp-na) cc)
100.0))))
(defun vf-linienzug-modus3 ( / ss k obj-liste startpunkt start-hoehe as-seite
(defun vf-linienzug-modus2 ( / ss k obj-liste startpunkt start-hoehe as-seite
endpunkt end-hoehe es-seite kette segmente n i seg
typ hz laenge bwinkel bseite antwort winkel klass
plan e ecke-bad vf-start vf-ende dz z-front
@@ -1791,57 +1791,60 @@
rad3v feste-vf dH-adj dir-x dir-y fill-D end-hz
gf-total br-gf-mode br-gf2-exp filler-A-len filler-a-done)
(princ "\n\n=========================================")
(princ "\n VF-LINIENZUG - Modus 2: Pfad + Ziel-Hoehe (fertig; Anker + Solver + Bau)")
(princ (ssg-text "vfl-m3-titel"))
(princ "\n=========================================")
;; Abhaengigkeit Gefaellestrecke-Modul
(if (null (car (atoms-family 1 '("GF-INSERT-HZ-INCL-SCALED"))))
(progn (alert "Gefaellestrecke-Modul nicht geladen!") (exit)))
(progn (alert (ssg-text "vfl-m3-alert-gf-modul")) (exit)))
(if (or (not *lib-initialized*) (null bogen-auf)) (init-bibliothek))
;; --- 1. Pfad-Objekte waehlen ---
(princ "\n\nPfad-Objekte waehlen (Linien/Boegen):")
(princ (ssg-text "vfl-m3-pfad-waehlen"))
(setq ss (ssget '((0 . "LINE,ARC"))))
(if (null ss) (progn (princ "\nKeine Objekte gewaehlt - Abbruch.") (exit)))
(if (null ss) (progn (princ (ssg-text "vfl-m3-keine-objekte")) (exit)))
(setq obj-liste '() k 0)
(repeat (sslength ss)
(setq obj-liste (cons (vlax-ename->vla-object (ssname ss k)) obj-liste))
(setq k (1+ k)))
;; --- 2. Startpunkt + Z + AS-Seite ---
(setq startpunkt (vfl-getpoint nil "\n\nStartpunkt der Kette (hoehere Seite) waehlen: "))
(if (null startpunkt) (progn (princ "\nAbgebrochen.") (exit)))
(setq start-hoehe (getreal (strcat "\nHoehe (Z) des Startpunkts ["
(rtos (caddr startpunkt) 2 1) "]: ")))
(setq startpunkt (vfl-getpoint nil (ssg-text "vfl-m3-prompt-startpunkt")))
(if (null startpunkt) (progn (princ (ssg-text "gf-status-abgebrochen")) (exit)))
(setq start-hoehe (getreal (ssg-textf "vfl-prompt-hoehe-startpunkt"
(list (rtos (caddr startpunkt) 2 1)))))
(if (null start-hoehe) (setq start-hoehe (caddr startpunkt)))
(setq startpunkt (list (car startpunkt) (cadr startpunkt) start-hoehe))
(setq *vfl-as-winkel* (vf-frage-element-winkel "vf-winkel-aus-header")) ; 30/90 vor Seite
(princ "\n\nAUS-Element - Seite waehlen:\n 1 - Links\n 2 - Rechts")
(setq as-seite (if (= (getstring "\nIhre Wahl (1/2) [1]: ") "2") "rechts" "links"))
(princ (ssg-text "gf-seite-aus-header"))
(princ (ssg-text "gf-seite-links"))
(princ (ssg-text "gf-seite-rechts"))
(setq as-seite (if (= (getstring (ssg-text "prompt-wahl-1-2")) "2") "rechts" "links"))
(vf-set-as-masse *vfl-as-winkel* as-seite) ; Masse fuer Variante
;; --- 3. Endpunkt + Z + ES-Seite (NEU in Modus 3) ---
(setq endpunkt (vfl-getpoint nil "\n\nEndpunkt der Kette (Ziel) waehlen: "))
(if (null endpunkt) (progn (princ "\nAbgebrochen.") (exit)))
(setq end-hoehe (getreal (strcat "\nZiel-Hoehe (Z) des Endpunkts ["
(rtos (caddr endpunkt) 2 1) "]: ")))
(setq endpunkt (vfl-getpoint nil (ssg-text "vfl-m3-prompt-endpunkt")))
(if (null endpunkt) (progn (princ (ssg-text "gf-status-abgebrochen")) (exit)))
(setq end-hoehe (getreal (ssg-textf "vfl-m3-prompt-zielhoehe"
(list (rtos (caddr endpunkt) 2 1)))))
(if (null end-hoehe) (setq end-hoehe (caddr endpunkt)))
(setq endpunkt (list (car endpunkt) (cadr endpunkt) end-hoehe))
(setq *vfl-es-winkel* (vf-frage-element-winkel "vf-winkel-ein-header")) ; 30/90 vor Seite
(princ "\n\nEIN-Element (ES) - Seite waehlen:\n 1 - Links\n 2 - Rechts")
(setq es-seite (if (= (getstring "\nIhre Wahl (1/2) [1]: ") "2") "rechts" "links"))
(princ (ssg-text "gf-seite-ein-header"))
(princ (ssg-text "gf-seite-links"))
(princ (ssg-text "gf-seite-rechts"))
(setq es-seite (if (= (getstring (ssg-text "prompt-wahl-1-2")) "2") "rechts" "links"))
(vf-set-es-masse *vfl-es-winkel* es-seite) ; Masse fuer Variante
;; --- 4. Sortieren + Analysieren + Eck-Vorpruefung ---
(setq kette (gf-sortiere-objekte obj-liste startpunkt))
(if (null kette)
(progn (princ "\nFEHLER: Pfad nicht sortierbar (haengt er lueckenlos zusammen?).") (exit)))
(progn (princ (ssg-text "vfl-m3-fehler-nicht-sortierbar")) (exit)))
(setq segmente (gf-analysiere-kette kette))
(setq ecke-bad (vfl2-pruefe-eckwinkel kette 5.0))
(if ecke-bad
(progn
(alert (strcat "Kein passender Bogen: Eck-Winkel " (rtos ecke-bad 2 1)
" Grad ist nicht ~30/60/90.\nBitte die Winkel anpassen."))
(alert (ssg-textf "vfl-m3-alert-eckwinkel" (list (rtos ecke-bad 2 1))))
(exit)))
;; --- 5. Klassifizierung (Phase A: nur speichern, nichts bauen) ---
@@ -1852,36 +1855,36 @@
(setq seg (nth i segmente) typ (car seg) hz (cadr seg) laenge (caddr seg))
(cond
((= typ "Linie")
(princ (strcat "\n\nSegment " (itoa (1+ i)) "/" (itoa n)
": Gerade L=" (rtos laenge 2 0) " mm hz=" (rtos hz 2 1)))
(princ (ssg-textf "vfl-m3-seg-gerade"
(list (itoa (1+ i)) (itoa n) (rtos laenge 2 0) (rtos hz 2 1))))
(cond
;; Direkt nach einer Vario-Kurve: automatisch VF (keine Abfrage) -
;; die Kurve sitzt mitten in der VF-Einheit, es MUSS VF folgen.
(nach-kurve
(princ "\n (automatisch VF - Segment folgt direkt auf eine Vario-Kurve)")
(princ (ssg-text "vfl-m3-auto-vf"))
(setq plan (cons (list "Linie" hz laenge "VF" nil) plan))
(setq nach-kurve nil))
(t
(princ "\n Typ? 1 = GF (Eingabe-Winkel) 2 = VF (Bruecke)")
(setq antwort (getstring "\nIhre Wahl (1/2) [1]: "))
(princ (ssg-text "vfl-m3-typ-gerade"))
(setq antwort (getstring (ssg-text "prompt-wahl-1-2")))
(if (= antwort "2")
(setq plan (cons (list "Linie" hz laenge "VF" nil) plan))
(progn
(setq winkel (getreal "\n GF-Neigung in Grad [3]: "))
(setq winkel (getreal (ssg-text "vfl-m3-prompt-gf-neigung")))
(if (null winkel) (setq winkel 3.0))
(if (> winkel 3.0)
(progn (princ "\n Hinweis: GF max. 3 Grad - auf 3 begrenzt.") (setq winkel 3.0)))
(progn (princ (ssg-text "vfl-m3-hinweis-gf-max")) (setq winkel 3.0)))
(setq plan (cons (list "Linie" hz laenge "GF" winkel) plan)))))))
((= typ "Bogen")
(setq bwinkel (nth 3 seg) bseite (nth 4 seg))
(princ (strcat "\n\nSegment " (itoa (1+ i)) "/" (itoa n)
": Eck/Bogen " (itoa bwinkel) " Grad " bseite))
(princ "\n Typ? 1 = GF-Bogen 2 = Vario-Kurve")
(setq antwort (getstring "\nIhre Wahl (1/2) [1]: "))
(princ (ssg-textf "vfl-m3-seg-bogen"
(list (itoa (1+ i)) (itoa n) (itoa bwinkel) bseite)))
(princ (ssg-text "vfl-m3-typ-bogen"))
(setq antwort (getstring (ssg-text "prompt-wahl-1-2")))
(if (= antwort "2")
(progn
(princ "\n Vario-Kurve - Variante? 1 = Aussen 2 = Innen")
(setq kv-variante (if (= (getstring "\nIhre Wahl (1/2) [2]: ") "1") "aussen" "innen"))
(princ (ssg-text "vfl-m3-variante-frage"))
(setq kv-variante (if (= (getstring (ssg-text "vfl-prompt-wahl-1-2-def2")) "1") "aussen" "innen"))
(setq plan (cons (list "Bogen" hz laenge bwinkel bseite "Vario-Kurve" kv-variante) plan))
(setq nach-kurve t)) ; naechste Gerade automatisch VF
(progn
@@ -1905,9 +1908,9 @@
(if (/= vf-count 1)
(progn
(princ (strcat "\n\n[M3a] Gefundene VF-Laeufe: " (itoa vf-count)))
(princ "\n[M3a] Genau EIN VF-Lauf noetig (GF...VF...GF; Vario-Kurven duerfen im Lauf liegen).")
(princ "\n[M3a] Mehrere/keine VF-Laeufe -> M3b spaeter.")
(princ (ssg-textf "vfl-m3-vf-laeufe" (list (itoa vf-count))))
(princ (ssg-text "vfl-m3-vf-lauf-noetig"))
(princ (ssg-text "vfl-m3-vf-lauf-m3b"))
(exit)))
;; Traeger-Stueck = laengste VF-Gerade im Lauf (traegt die ganze Hoehe).
(setq carrier-idx -1 i vf-start)
@@ -1918,7 +1921,7 @@
(setq carrier-idx i)))
(setq i (1+ i)))
(if (< carrier-idx 0)
(progn (princ "\n[M3a] VF-Lauf ohne VF-Gerade - Abbruch.") (exit)))
(progn (princ (ssg-text "vfl-m3-vf-lauf-ohne-gerade")) (exit)))
;; --- 7. Anker rechnen ---
;; Vorwaerts: Start-Z durch alle Front-Segmente (Index < vf-start).
@@ -1947,31 +1950,30 @@
;; --- 8. Anker-Report (noch kein Bauen) ---
(princ "\n\n=========================================")
(princ "\n M3a ANKER-VORSCHAU (grob geschaetzt; exakte Werte beim Bau)")
(princ (ssg-text "vfl-m3-anker-vorschau-header"))
(princ "\n=========================================")
(princ (strcat "\n Start-Hoehe Z: " (rtos (float start-hoehe) 2 1) " mm"))
(princ (strcat "\n Ziel-Hoehe Z: " (rtos (float end-hoehe) 2 1) " mm"))
(princ (strcat "\n delta-H gesamt: " (rtos dH-gesamt 2 1) " mm (positiv = Abfall)"))
(princ (strcat "\n VF-Lauf: Segment " (itoa (1+ vf-start)) ".." (itoa (1+ vf-ende))))
(princ (strcat "\n Front-Anker Z: " (rtos z-front 2 1) " mm (vorwaerts von AS)"))
(princ (strcat "\n Junction-Anker Z: " (rtos z-junction 2 1) " mm (rueckwaerts von ES)"))
(princ (ssg-textf "vfl-m3-start-hoehe" (list (rtos (float start-hoehe) 2 1))))
(princ (ssg-textf "vfl-m3-ziel-hoehe" (list (rtos (float end-hoehe) 2 1))))
(princ (ssg-textf "vfl-m3-delta-h-gesamt" (list (rtos dH-gesamt 2 1))))
(princ (ssg-textf "vfl-m3-vf-lauf-segmente" (list (itoa (1+ vf-start)) (itoa (1+ vf-ende)))))
(princ (ssg-textf "vfl-m3-front-anker-vorschau" (list (rtos z-front 2 1))))
(princ (ssg-textf "vfl-m3-junction-anker-vorschau" (list (rtos z-junction 2 1))))
;; Vorzeichen = Richtung (VF ist angetrieben, kann steigen UND fallen).
(setq richtn (cond ((< dH-bruecke -0.1) "Auf (steigt)")
((> dH-bruecke 0.1) "Ab (faellt)")
(t "horizontal")))
(setq richtn (cond ((< dH-bruecke -0.1) (ssg-text "vfl-m3-richtung-auf"))
((> dH-bruecke 0.1) (ssg-text "vfl-m3-richtung-ab"))
(t (ssg-text "vfl-m3-richtung-horizontal"))))
(setq req-w (if (> span-bruecke 1.0)
(* (atan (/ (abs dH-bruecke) span-bruecke)) (/ 180.0 pi))
0.0))
(princ (strcat "\n --> Bruecke: delta-H = " (rtos dH-bruecke 2 1)
" mm ueber Spannweite " (rtos span-bruecke 2 0) " mm"))
(princ (strcat "\n Richtung: VF-" richtn))
(princ "\n (VF ist angetrieben - kann STEIGEN und FALLEN; Vorzeichen = nur Auf/Ab)")
(princ (strcat "\n grobe mittlere Neigung ueber Spannweite: ~" (rtos req-w 2 1) " Grad"))
(princ (ssg-textf "vfl-m3-bruecke-dh" (list (rtos dH-bruecke 2 1) (rtos span-bruecke 2 0))))
(princ (ssg-textf "vfl-m3-bruecke-richtung" (list richtn)))
(princ (ssg-text "vfl-m3-vf-angetrieben"))
(princ (ssg-textf "vfl-m3-mittlere-neigung" (list (rtos req-w 2 1))))
(if (> req-w 51.0)
(princ "\n WARNUNG: ~Neigung > 51 Grad -> zu steil fuer Vario (Magnitude infeasibel).")
(princ "\n -> innerhalb Vario-Bereich (3..51 Grad), grobe Orientierung."))
(princ (ssg-text "vfl-m3-warnung-zu-steil"))
(princ (ssg-text "vfl-m3-vario-bereich-ok")))
(princ "\n (Anker oben = grobe Vorschau; exakte Werte werden beim Bau GEMESSEN)")
(princ (ssg-text "vfl-m3-anker-hinweis"))
(princ "\n=========================================")
;; ================= PHASE B: BAUEN (messen statt schaetzen) =================
@@ -1990,7 +1992,7 @@
(setq i (1+ i)))
;; --- B1: FRONT-Lauf bauen (Segmente 0 .. vf-start-1) -> Front-Anker MESSEN ---
(princ "\n\n>>> Phase B1: Front-Lauf (AS + GF) bauen ...")
(princ (ssg-text "vfl-m3-phase-b1"))
(setq i 0)
(while (< i vf-start)
(setq seg (nth i plan) typ (car seg) hz (cadr seg))
@@ -2016,9 +2018,9 @@
(if (= klass "GF-Bogen")
(progn
(if (null frame)
(progn (alert "Kette beginnt mit einem Bogen - bitte erst eine Gerade.") (exit)))
(progn (alert (ssg-text "vfl-m3-alert-beginnt-bogen")) (exit)))
(setq frame (vfl-insert-gf-bogen-block frame bwinkel bseite)))
(princ "\n >>> [M3a] Vario-Kurve im Front-Lauf - uebersprungen."))))
(princ (ssg-text "vfl-m3-kurve-front-uebersprungen")))))
(setq i (1+ i)))
;; Front-Anker (gemessen). Falls die VF-Bruecke ganz vorne liegt: AS jetzt setzen.
@@ -2066,11 +2068,11 @@
;; Kletter-Segment als Standard-Vario loesen; GF wird BERECHNET (L_GF) und der
;; Winkel WAEHLBAR (mehrere gueltige -> Nutzer waehlt). feste = 800 (Umlenk+Sep;
;; Motor sitzt am Kettenende). Die flache Zone gleicht danach die Laenge aus.
(princ "\n\n --- STANDARD-VARIO (Kletter-Segment) + flache Zone ---")
(princ (strcat "\n Front-Anker (gemessen): " (rtos z-front 2 1) " mm"))
(princ (strcat "\n Junction (exakt): " (rtos z-junction 2 1) " mm"))
(princ (strcat "\n Kletterhoehe " (rtos target-climb 2 1) " mm | Kletterer "
(itoa n-climb) " | Kurven " (itoa nkurve) " | kurze VF " (itoa nonclimber-cnt)))
(princ (ssg-text "vfl-m3-standard-vario-header"))
(princ (ssg-textf "vfl-m3-front-anker-gemessen" (list (rtos z-front 2 1))))
(princ (ssg-textf "vfl-m3-junction-exakt" (list (rtos z-junction 2 1))))
(princ (ssg-textf "vfl-m3-kletter-info"
(list (rtos target-climb 2 1) (itoa n-climb) (itoa nkurve) (itoa nonclimber-cnt))))
;; feste-Horizontal + Hoehen-Anpassung fuer den Solver:
;; - Mit flacher Zone: Motor sitzt am Kettenende (nicht im Kletter-Segment) ->
;; feste = 800 (Umlenk+Sep). berechne rechnet Motor-/Uebergangs-Abstieg NICHT,
@@ -2083,24 +2085,28 @@
(setq feste-vf 1300.0 dH-adj dH-bruecke))
(setq wahl3 (vfl3-waehle-winkel climber-span dH-adj feste-vf))
(if (null wahl3)
(progn (princ "\n KEIN passender Vario-Winkel -> infeasibel (Front bereits gebaut).")
(progn (princ (ssg-text "vfl-m3-kein-winkel"))
(princ) (exit)))
(setq br-winkel (car wahl3) gf-total (cadr wahl3) br-lvf (caddr wahl3) br-richtn (cadddr wahl3))
;; GF-Verteilung: 1 = alles am Einlauf (GF1); 2 = 1/2 GF1 + 1/2 GF2. Bei 1/2/1/2
;; wird der im Kletter-Segment durch das halbe GF1 frei werdende Platz mit einem
;; horizontalen Fueller-A gefuellt; GF2 (~1/2 L_GF) sitzt hinter dem Motor, der
;; ES-Laengen-Abschluss zieht seinen Fussabdruck ab (Fueller-B wird kuerzer).
(princ "\n\n GF-Verteilung: 1 - alles am Einlauf (GF1) 2 - 1/2 GF1 + 1/2 GF2")
(setq br-gf-mode (if (= (getstring "\n Ihre Wahl (1/2) [1]: ") "2") 2 1))
(princ (ssg-text "vfl-m3-gf-verteilung"))
(setq br-gf-mode (if (= (getstring (ssg-text "prompt-wahl-1-2")) "2") 2 1))
(if (= br-gf-mode 2)
(setq br-gf1 (/ gf-total 2.0) br-gf2-exp (/ gf-total 2.0)
filler-A-len (* (/ gf-total 2.0) (cos rad3v)))
(setq br-gf1 gf-total br-gf2-exp 0.0 filler-A-len 0.0))
(setq filler-a-done nil)
(princ (strcat "\n -> Vario " (itoa br-winkel) " (" br-richtn "), L_VF " (rtos br-lvf 2 0)
" mm, GF gesamt " (rtos gf-total 2 0) " mm, Verteilung "
(if (= br-gf-mode 2) "1/2 GF1 + 1/2 GF2" "alles GF1")
" (GF2-Rest = Mess-Feinkorrektur)"))
(princ (ssg-textf "vfl-m3-vario-ergebnis"
(list (itoa br-winkel)
(if (= br-richtn "Auf") (ssg-text "vfl-m3-richtung-auf-kurz")
(ssg-text "vfl-m3-richtung-ab-kurz"))
(rtos br-lvf 2 0)
(rtos gf-total 2 0)
(if (= br-gf-mode 2) (ssg-text "vfl-m3-vert-halb")
(ssg-text "vfl-m3-vert-ganz")))))
;; --- B3: Standard-Vario (Klettern, 3-Grad-Basis) + flache Zone (0 Grad) ---
;; Die flache Zone (Vario-Kurve + horizontaler Fueller) haengt EINMAL ueber auf_3
@@ -2171,13 +2177,12 @@
(setq gf2-drop (- z-aftermotor z-junction))
(if (< gf2-drop 0.0)
(progn
(princ (strcat "\n WARNUNG: Koerper klettert zu wenig - GF2<0 (fehlen "
(rtos (- gf2-drop) 2 1) " mm). Winkel zu flach; dZ nicht exakt."))
(princ (ssg-textf "vfl-m3-warnung-gf2-negativ" (list (rtos (- gf2-drop) 2 1))))
(setq gf2-drop 0.0)))
(setq gf2-planar (/ gf2-drop (/ (sin (* 3.0 (/ pi 180.0))) (cos (* 3.0 (/ pi 180.0))))))
(if (> gf2-planar 0.1)
(progn
(princ (strcat "\n GF2 (gemessener Ausgleich): L=" (rtos gf2-planar 2 1) " mm"))
(princ (ssg-textf "vfl-m3-gf2-ausgleich" (list (rtos gf2-planar 2 1))))
(setq frame (vfl-insert-gf-segment pt letzt-koerper-hz gf2-planar 3))
(vfl-acc-gf-seg (/ gf2-planar (cos (* 3.0 (/ pi 180.0)))) 3))
(setq frame (vfl-frame-3grad pt letzt-koerper-hz)))
@@ -2199,11 +2204,11 @@
(setq bwinkel (nth 3 seg) bseite (nth 4 seg) klass (nth 5 seg))
(if (= klass "GF-Bogen")
(setq frame (vfl-insert-gf-bogen-block frame bwinkel bseite))
(princ "\n >>> [M3a] Vario-Kurve im Back-Lauf - uebersprungen."))))
(princ (ssg-text "vfl-m3-kurve-back-uebersprungen")))))
(setq i (1+ i)))
;; --- B5: Kettenende Separator + ES ---
(if (null frame) (progn (princ "\nNichts gebaut - Abbruch.") (exit)))
(if (null frame) (progn (princ (ssg-text "vfl-m3-nichts-gebaut")) (exit)))
(setq frame (vfl-insert-es-element "GF" frame (car (frame->hz-winkel frame))
(if letzt-winkel letzt-winkel 3.0) (caddr (car frame)) es-seite))
@@ -2213,25 +2218,25 @@
(vfl-planar-dist startpunkt (car frame)) as-seite es-seite startpunkt lastEnt)
(setq soll-ende endpunkt ist-ende (car frame))
(princ "\n\n=========================================")
(princ "\n>>> VF-Linienzug (Modus 3, M3a) gebaut! <<<")
(princ (strcat "\n Ziel (Soll): X=" (rtos (car soll-ende) 2 1)
" Y=" (rtos (cadr soll-ende) 2 1) " Z=" (rtos (caddr soll-ende) 2 1)))
(princ (strcat "\n ES (Ist): X=" (rtos (car ist-ende) 2 1)
" Y=" (rtos (cadr ist-ende) 2 1) " Z=" (rtos (caddr ist-ende) 2 1)))
(princ (strcat "\n Abweichung: dX=" (rtos (- (car ist-ende) (car soll-ende)) 2 1)
" dY=" (rtos (- (cadr ist-ende) (cadr soll-ende)) 2 1)
" dZ=" (rtos (- (caddr ist-ende) (caddr soll-ende)) 2 1) " mm"))
(princ (ssg-text "vfl-m3-fertig-header"))
(princ (ssg-textf "vfl-m3-ziel-soll"
(list (rtos (car soll-ende) 2 1) (rtos (cadr soll-ende) 2 1) (rtos (caddr soll-ende) 2 1))))
(princ (ssg-textf "vfl-m3-es-ist"
(list (rtos (car ist-ende) 2 1) (rtos (cadr ist-ende) 2 1) (rtos (caddr ist-ende) 2 1))))
(princ (ssg-textf "vfl-m3-abweichung"
(list (rtos (- (car ist-ende) (car soll-ende)) 2 1)
(rtos (- (cadr ist-ende) (cadr soll-ende)) 2 1)
(rtos (- (caddr ist-ende) (caddr soll-ende)) 2 1))))
;; Zerlegung bezogen auf die ES-KS_AUS-ACHSE: Quer (senkrecht zur Achse) soll
;; ~0 sein (Endpunkt liegt auf der KS_AUS-Achse), Laengs = ES-Ausladung.
(setq end-hz (car (frame->hz-winkel frame))) ; KS_AUS-Achsrichtung
(setq dir-x (cos (* end-hz (/ pi 180.0))) dir-y (sin (* end-hz (/ pi 180.0))))
(princ (strcat "\n Laengs KS_AUS-Achse: "
(rtos (+ (* (- (car ist-ende) (car soll-ende)) dir-x)
(princ (ssg-textf "vfl-m3-laengs-quer"
(list (rtos (+ (* (- (car ist-ende) (car soll-ende)) dir-x)
(* (- (cadr ist-ende) (cadr soll-ende)) dir-y)) 2 1)
" mm | Quer zur Achse (soll ~0): "
(rtos (+ (* (- (car ist-ende) (car soll-ende)) (- dir-y))
(* (- (cadr ist-ende) (cadr soll-ende)) dir-x)) 2 1) " mm"))
(princ "\n (dZ=Ziel-Hoehe; Quer zur KS_AUS-Achse ~0 => Endpunkt liegt auf der Achse)")
(* (- (cadr ist-ende) (cadr soll-ende)) dir-x)) 2 1))))
(princ (ssg-text "vfl-m3-achse-hinweis"))
(princ "\n=========================================")
(princ)
)
+421
View File
@@ -699,6 +699,427 @@
endpunkt
)
;; ============================================================
;; DCL-DIALOG (Standardfall) - dcl/variofoerderer.dcl
;; Ersetzt die interaktive Werteingabe aus vf-eingabe-abfragen
;; (Konsolen-Modus "Werteingabe") fuer anlage-typ "standard" durch
;; zwei DCL-Dialoge: Basis-Eingabe und Winkel/Verteilung. Die
;; 3D-Linie-Eingabe sowie die Typen "etage"/"linienzug" bleiben
;; unveraendert interaktiv (siehe Verzweigung in c:VarioFoerderer).
;; ============================================================
;; Basis-Eingabe (Dialog 1): deltaL, deltaH, Richtung, Einfuegehoehe,
;; Fahrtrichtung, Seite.
;; prefill: Assoziationsliste zur Vorbelegung (fuer VARIOFOERDERER_EDIT) mit
;; Schluesseln "deltaL" "deltaH" "richtung" "einfuegehoehe" "hz" "seite"
;; - oder nil fuer Neuanlage mit Defaults.
;; Rueckgabe: (deltaL deltaH richtung einfuegehoehe hz seite) oder nil bei Abbruch.
(defun vfs-dialog-eingabe-basis (prefill / dcl-pfad dat ergebnis
dlg-deltal dlg-deltah dlg-richtung dlg-hoehe
dlg-fahrtrichtung dlg-seite
deltaL deltaH richtung hz seite z-start)
(setq dcl-pfad (strcat (getenv "DXFM_DCL") "/variofoerderer.dcl"))
(setq dat (load_dialog dcl-pfad))
(if (not (new_dialog "variofoerderer_basis" dat))
(progn
(if (>= dat 0) (unload_dialog dat))
(alert (ssg-textf "gf-alert-dialog-fehlt" (list dcl-pfad)))
nil
)
(progn
;; Vorbelegung: aus prefill (Edit) oder Defaults (Neuanlage)
(set_tile "deltal"
(if prefill (rtos (cdr (assoc "deltaL" prefill)) 2 0) "15000"))
(set_tile "deltah"
(if prefill (rtos (cdr (assoc "deltaH" prefill)) 2 0) "3000"))
(set_tile "einfuegehoehe"
(if prefill (rtos (cdr (assoc "einfuegehoehe" prefill)) 2 1) "0"))
(start_list "richtung")
(add_list (ssg-text "vfs-dlg-richtung-auf"))
(add_list (ssg-text "vfs-dlg-richtung-ab"))
(end_list)
(set_tile "richtung"
(if (and prefill (equal (cdr (assoc "richtung" prefill)) "Ab")) "1" "0"))
(start_list "fahrtrichtung")
(add_list (ssg-textf "gf-dlg-richtung-0" (list grad-zeichen)))
(add_list (ssg-textf "gf-dlg-richtung-90" (list grad-zeichen)))
(add_list (ssg-textf "gf-dlg-richtung-180" (list grad-zeichen)))
(add_list (ssg-textf "gf-dlg-richtung-270" (list grad-zeichen)))
(end_list)
(set_tile "fahrtrichtung"
(if prefill
(cond ((equal (cdr (assoc "hz" prefill)) 90.0 0.1) "1")
((equal (cdr (assoc "hz" prefill)) 180.0 0.1) "2")
((equal (cdr (assoc "hz" prefill)) 270.0 0.1) "3")
(t "0"))
"0"))
(start_list "seite")
(add_list (ssg-text "gf-dlg-rechts"))
(add_list (ssg-text "gf-dlg-links"))
(end_list)
(set_tile "seite"
(if (and prefill (equal (cdr (assoc "seite" prefill)) "links")) "1" "0"))
;; Actions
(action_tile "accept"
(strcat
"(setq dlg-deltal (get_tile \"deltal\"))"
"(setq dlg-deltah (get_tile \"deltah\"))"
"(setq dlg-richtung (get_tile \"richtung\"))"
"(setq dlg-hoehe (get_tile \"einfuegehoehe\"))"
"(setq dlg-fahrtrichtung (get_tile \"fahrtrichtung\"))"
"(setq dlg-seite (get_tile \"seite\"))"
"(done_dialog 1)"
)
)
(action_tile "cancel" "(done_dialog 0)")
(setq ergebnis (start_dialog))
(unload_dialog dat)
(if (= ergebnis 1)
(progn
(setq deltaL (atof dlg-deltal))
(setq deltaH (atof dlg-deltah))
(setq richtung (if (= dlg-richtung "1") "Ab" "Auf"))
(setq z-start (atof dlg-hoehe))
(setq hz
(cond ((= dlg-fahrtrichtung "1") 90.0)
((= dlg-fahrtrichtung "2") 180.0)
((= dlg-fahrtrichtung "3") 270.0)
(t 0.0)))
(setq seite (if (= dlg-seite "1") "links" "rechts"))
(list deltaL deltaH richtung z-start hz seite)
)
nil
)
)
)
)
;; Winkel/Verteilung-Eingabe (Dialog 2): Winkel-Popup aus den vorher
;; berechneten gueltigen Varianten (gueltige-winkel/ergebnis-liste, siehe
;; berechne-alle-winkel), plus L_GF-Verteilung vorne/hinten (analog Schritt
;; 8+9 in c:VarioFoerderer).
;; prefill: Assoziationsliste ("winkel" . best-winkel) ("verteilung-idx" . "0".."3")
;; ("lgf1" . mm) - oder nil fuer Vorbelegung mit dem kleinsten gueltigen Winkel.
;; Rueckgabe: (best-winkel L_GF L_VF L_GF1 L_GF2 verteilung-modus) oder nil bei Abbruch.
(defun vfs-dialog-winkel-verteilung (gueltige-winkel ergebnis-liste staustrecke-basis prefill /
dcl-pfad dat ergebnis w eintrag idx sel-idx init-verteilung
dlg-winkel dlg-verteilung dlg-lgf1
best-winkel L_GF L_VF verteilung-modus L_GF1 L_GF2)
(setq dcl-pfad (strcat (getenv "DXFM_DCL") "/variofoerderer.dcl"))
(setq dat (load_dialog dcl-pfad))
(if (not (new_dialog "variofoerderer_winkel" dat))
(progn
(if (>= dat 0) (unload_dialog dat))
(alert (ssg-textf "gf-alert-dialog-fehlt" (list dcl-pfad)))
nil
)
(progn
;; Winkel-Popup aus den gueltigen Varianten aufbauen
(start_list "winkel")
(foreach w gueltige-winkel
(setq eintrag (assoc w ergebnis-liste))
(if (= w 0)
(add_list (ssg-textf "vfs-dlg-winkel-horizontal"
(list (rtos (nth 1 eintrag) 2 1) (rtos (nth 2 eintrag) 2 1))))
(add_list (ssg-textf "vfs-dlg-winkel-option"
(list (itoa w) grad-zeichen (rtos (nth 1 eintrag) 2 1) (rtos (nth 2 eintrag) 2 1))))
)
)
(end_list)
;; Vorbelegung: Winkel aus prefill (falls noch gueltig), sonst erster
;; (kleinster) gueltiger Winkel - analog der automatischen Konsolen-Wahl.
(setq sel-idx 0 idx 0)
(if prefill
(foreach w gueltige-winkel
(if (equal w (cdr (assoc "winkel" prefill))) (setq sel-idx idx))
(setq idx (1+ idx))
)
)
(set_tile "winkel" (itoa sel-idx))
;; Verteilung: Popup + manuelles L_GF1-Feld (nur bei "Eigene Werte" aktiv)
(start_list "verteilung")
(add_list (ssg-text "vfs-dlg-verteilung-1"))
(add_list (ssg-text "vfs-dlg-verteilung-2"))
(add_list (ssg-text "vfs-dlg-verteilung-3"))
(add_list (ssg-text "vfs-dlg-verteilung-4"))
(end_list)
(setq init-verteilung (if prefill (cdr (assoc "verteilung-idx" prefill)) "0"))
(set_tile "verteilung" init-verteilung)
(set_tile "lgf1_manuell"
(if (and prefill (cdr (assoc "lgf1" prefill)))
(rtos (cdr (assoc "lgf1" prefill)) 2 1) "0"))
(mode_tile "lgf1_manuell" (if (= init-verteilung "3") 0 1))
(action_tile "verteilung"
"(mode_tile \"lgf1_manuell\" (if (= (get_tile \"verteilung\") \"3\") 0 1))")
(action_tile "accept"
(strcat
"(setq dlg-winkel (get_tile \"winkel\"))"
"(setq dlg-verteilung (get_tile \"verteilung\"))"
"(setq dlg-lgf1 (get_tile \"lgf1_manuell\"))"
"(done_dialog 1)"
)
)
(action_tile "cancel" "(done_dialog 0)")
(setq ergebnis (start_dialog))
(unload_dialog dat)
(if (= ergebnis 1)
(progn
(setq best-winkel (nth (atoi dlg-winkel) gueltige-winkel))
(setq eintrag (assoc best-winkel ergebnis-liste))
(setq L_GF (nth 1 eintrag) L_VF (nth 2 eintrag))
(setq verteilung-modus dlg-verteilung)
(cond
((= verteilung-modus "0")
(setq L_GF1 (/ L_GF 2.0) L_GF2 (/ L_GF 2.0)))
((= verteilung-modus "1")
(setq L_GF1 (float staustrecke-basis))
(setq L_GF2 (max 0.0 (- L_GF (float staustrecke-basis)))))
((= verteilung-modus "2")
(setq L_GF2 (float staustrecke-basis))
(setq L_GF1 (max 0.0 (- L_GF (float staustrecke-basis)))))
((= verteilung-modus "3")
(setq L_GF1 (atof dlg-lgf1))
(if (or (null L_GF1) (< L_GF1 0)) (setq L_GF1 (/ L_GF 2.0)))
(if (> L_GF1 L_GF) (setq L_GF1 L_GF))
(setq L_GF2 (max 0.0 (- L_GF L_GF1))))
(t (setq L_GF1 (/ L_GF 2.0) L_GF2 (/ L_GF 2.0)))
)
(list best-winkel L_GF L_VF L_GF1 L_GF2 verteilung-modus)
)
nil
)
)
)
)
;; ============================================================
;; XDATA-Metadaten fuer den Edit-Nachbau (App "SSG_VF_EDIT").
;; Markiert ein VF_n-INSERT als "mit dem Standard-Dialog erstellt" und
;; speichert die Fahrtrichtung (hz) - der einzige Wert, der sich nicht aus
;; den Sivas-Attributen rekonstruieren laesst (ANTRIEBFAHRTRICHTUNG, SEITE_AS,
;; VF_WINKEL, L_GF_m stehen dort bereits). Bewusst NICHT im Sivas-Attributsatz.
;; Ohne diese Markierung (z.B. Etage-, Linienzug- oder Altbestand-Bloecke)
;; verweigert c:VARIOFOERDERER_EDIT die Bearbeitung, um deren komplexere
;; Geometrie nicht versehentlich durch einen einfachen Neuaufbau zu ersetzen.
;; ============================================================
(if (null *vf-xdata-app*) (setq *vf-xdata-app* "SSG_VF_EDIT"))
(defun vfs-xdata-schreiben (ent hz /)
(regapp *vf-xdata-app*)
(entmod
(append (entget ent)
(list
(list -3
(list *vf-xdata-app*
(cons 1000 "standard")
(cons 1000 (rtos (float hz) 2 4)))))))
ent
)
;; XDATA lesen -> (typ-marker hz-str) oder nil.
(defun vfs-xdata-lesen (ent / xd app-data)
(setq xd (entget ent (list *vf-xdata-app*)))
(setq app-data (cdr (assoc -3 xd)))
(if app-data
(mapcar 'cdr (cdr (car app-data)))
nil
)
)
;; ============================================================
;; Gemeinsame Berechnung + Winkel/Verteilung-Dialog + Einfuegung.
;; Wird sowohl von der Neuanlage (vfs-standard-dialog-ablauf) als auch vom
;; Edit-Befehl (c:VARIOFOERDERER_EDIT) verwendet.
;; winkel-prefill: Vorbelegung fuer vfs-dialog-winkel-verteilung oder nil.
;; ============================================================
(defun vfs-standard-dialog-berechnen-einfuegen (vf-nummer deltaL deltaH richtung startpunkt hz seite
winkel-prefill /
ergebnis ergebnis-liste gueltige-winkel horizontal-info
winkelwahl best-winkel L_GF L_VF L_GF1 L_GF2 verteilung-modus
n-scanner hoehe-von hoehe-bis lastEnt vf-insert staustrecke-basis)
(setq ergebnis (berechne-standard deltaL deltaH richtung seite))
(setq ergebnis-liste (cadddr ergebnis))
(setq staustrecke-basis (ssg-cfg-or "vario" "staustrecke_basis" 1000))
;; Horizontale Zwischenstrecke als Zusatzoption (nur bei "Ab" erreichbar,
;; siehe Kommentar in c:VarioFoerderer Schritt 5b).
(setq horizontal-info nil)
(if (= richtung "Ab")
(progn
(setq horizontal-info (berechne-horizontale-mitte deltaL deltaH "Ab"))
(if (and horizontal-info (caddr horizontal-info))
(setq ergebnis-liste
(append ergebnis-liste (list (list 0 (car horizontal-info) (cadr horizontal-info) T))))
(setq horizontal-info nil)
)
)
)
(setq gueltige-winkel
(mapcar 'car
(vl-remove-if-not
(function (lambda (e) (and (nth 3 e) (numberp (nth 1 e)) (numberp (nth 2 e))
(>= (nth 1 e) 0) (>= (nth 2 e) 0))))
ergebnis-liste)))
(if (null gueltige-winkel)
(alert (ssg-textf "vfc-alert-kein-winkel"
(list (chr 916) (rtos deltaL 2 0) (rtos deltaH 2 0) richtung)))
(progn
(setq winkelwahl (vfs-dialog-winkel-verteilung gueltige-winkel ergebnis-liste staustrecke-basis winkel-prefill))
(if (null winkelwahl)
(princ (ssg-text "vfc-vorgang-abgebrochen"))
(progn
(setq best-winkel (nth 0 winkelwahl)
L_GF (nth 1 winkelwahl)
L_VF (nth 2 winkelwahl)
L_GF1 (nth 3 winkelwahl)
L_GF2 (nth 4 winkelwahl)
verteilung-modus (nth 5 winkelwahl))
(setq n-scanner 0)
(setq hoehe-von (caddr startpunkt))
(setq hoehe-bis
(cond ((= richtung "Auf") (+ hoehe-von deltaH))
((= richtung "Ab") (- hoehe-von deltaH))
(t hoehe-von)))
(setq lastEnt (vf-lastent-ohne-attribute))
(variofoerderer-einfuegen deltaL deltaH richtung best-winkel L_GF1 L_GF2 L_VF startpunkt seite hz)
(setq vf-insert
(vf-block-erstellen "standard" seite vf-nummer n-scanner
hoehe-von hoehe-bis deltaH deltaL L_VF L_GF1 L_GF2
richtung best-winkel startpunkt lastEnt hz))
(if vf-insert (vfs-xdata-schreiben vf-insert hz))
(princ "\n=========================================")
)
)
)
)
)
;; Neuanlage (Menue/Konsole -> Dialog): Startpunkt (X/Y) picken, Basis-Dialog,
;; dann gemeinsame Berechnung/Winkel-Dialog/Einfuegung.
(defun vfs-standard-dialog-ablauf (vf-nummer / eingabe deltaL deltaH richtung
z-start hz seite startpunkt startpunkt-xy)
(setq startpunkt-xy (getpoint (ssg-text "vfc-prompt-startpunkt-aus")))
(if (null startpunkt-xy) (setq startpunkt-xy '(0 0 0)))
(setq eingabe (vfs-dialog-eingabe-basis nil))
(if (null eingabe)
(princ (ssg-text "vfc-vorgang-abgebrochen"))
(progn
(setq deltaL (nth 0 eingabe)
deltaH (nth 1 eingabe)
richtung (nth 2 eingabe)
z-start (nth 3 eingabe)
hz (nth 4 eingabe)
seite (nth 5 eingabe))
(setq startpunkt (list (car startpunkt-xy) (cadr startpunkt-xy) z-start))
(vfs-standard-dialog-berechnen-einfuegen vf-nummer deltaL deltaH richtung startpunkt hz seite nil)
)
)
)
;; ============================================================
;; VARIOFOERDERER_EDIT - Doppelklick/Kontextmenue-Bearbeitung
;; ============================================================
;; Bearbeitet einen bestehenden Standard-VarioFoerderer (VF_n-Block, mit
;; SSG_VF_EDIT-XDATA) ueber die DCL-Dialoge: liest die aktuellen Parameter,
;; zeigt sie vorbelegt und baut die Strecke bei OK am selben Startpunkt neu
;; auf. Wird vom Doppelklick-Dispatcher SSG_BLOCKEDIT fuer Blocknamen "VF_*"
;; aufgerufen. Bloecke ohne SSG_VF_EDIT-XDATA (Etage, Linienzug, Altbestand)
;; werden abgewiesen, da ihre Geometrie sich nicht verlustfrei aus dem
;; einfachen Standard-Schema rekonstruieren laesst.
(defun c:VARIOFOERDERER_EDIT ( / ss ent ed bname startpunkt attribs xd
deltaL deltaH richtung z-start hz seite
eingabe vf-nummer best-winkel-attr L_GF_m-teile
prefill-basis prefill-winkel)
;; Implied Selection VOR ssg-start pruefen (ssg-start hebt Selektion auf)
(setq ss (ssget "I"))
(if (and ss (= (sslength ss) 1)
(= (cdr (assoc 0 (entget (ssname ss 0)))) "INSERT"))
(setq ent (ssname ss 0))
)
(ssg-start "VARIOFOERDERER_EDIT" '(("OSMODE") ("ATTREQ") ("ATTDIA")))
(setvar "OSMODE" 0)
(if (null ent)
(progn
(setq ss (ssget ":S" '((0 . "INSERT"))))
(if ss (setq ent (ssname ss 0)))
)
)
(if (null ent) (progn (ssg-end) (exit)))
(setq ed (entget ent))
(setq bname (cdr (assoc 2 ed)))
(if (not (wcmatch bname "VF_*"))
(progn (alert (ssg-textf "vfs-edit-kein-vf" (list bname))) (ssg-end) (exit)))
(setq xd (vfs-xdata-lesen ent))
(if (or (null xd) (/= (car xd) "standard"))
(progn (alert (ssg-textf "vfs-edit-keine-xdata" (list bname))) (ssg-end) (exit)))
(setq startpunkt (cdr (assoc 10 ed)))
(setq attribs (ssg-attrib-read ent))
(setq hz (atof (nth 1 xd)))
(setq deltaL (atof (cond ((cdr (assoc "DELTA_L_mm" attribs))) ("15000"))))
(setq deltaH (atof (cond ((cdr (assoc "DELTA_H_mm" attribs))) ("3000"))))
(setq richtung (cond ((cdr (assoc "ANTRIEBFAHRTRICHTUNG" attribs))) ("Auf")))
(setq seite (cond ((cdr (assoc "SEITE_AS" attribs))) ("rechts")))
(setq z-start (caddr startpunkt))
(setq prefill-basis
(list (cons "deltaL" deltaL) (cons "deltaH" deltaH) (cons "richtung" richtung)
(cons "einfuegehoehe" z-start) (cons "hz" hz) (cons "seite" seite)))
(setq eingabe (vfs-dialog-eingabe-basis prefill-basis))
(if (null eingabe)
(princ (ssg-text "vfc-vorgang-abgebrochen"))
(progn
(setq deltaL (nth 0 eingabe)
deltaH (nth 1 eingabe)
richtung (nth 2 eingabe)
z-start (nth 3 eingabe)
hz (nth 4 eingabe)
seite (nth 5 eingabe))
(setq startpunkt (list (car startpunkt) (cadr startpunkt) z-start))
;; Vorbelegung Winkel/Verteilung: bestehenden Winkel vorschlagen, L_GF-
;; Verteilung als "Eigene Werte" mit dem aktuellen L_GF1 (aus L_GF_m) -
;; das ist unabhaengig vom urspruenglichen Verteilungsmodus immer exakt.
(setq best-winkel-attr (atoi (cond ((cdr (assoc "VF_WINKEL" attribs))) ("0"))))
(setq L_GF_m-teile (ssg-cfg-split-comma (cond ((cdr (assoc "L_GF_m" attribs))) ("0.0,0.0"))))
(setq prefill-winkel
(list (cons "winkel" best-winkel-attr)
(cons "verteilung-idx" "3")
(cons "lgf1" (* 1000.0 (atof (car L_GF_m-teile))))))
(entdel ent)
(setq vf-nummer (vf-next-number))
(vfs-standard-dialog-berechnen-einfuegen vf-nummer deltaL deltaH richtung
startpunkt hz seite prefill-winkel)
(princ (ssg-textf "vfs-edit-neu-aufgebaut" (list bname)))
)
)
(ssg-end)
(princ)
)
;; ============================================================
;; REGISTRIERUNG
;; ============================================================