From 01fb2d29f228d056e7e41aa6f6fba01a73998b0f Mon Sep 17 00:00:00 2001 From: Michael Stangl Date: Fri, 9 Oct 2026 13:16:55 +0200 Subject: [PATCH] [CHANGE] GEFAELLESTRECKE_LINIENZUG-Streckengruppen per Doppelklick editierbar machen Bisher brach GEFAELLESTRECKE_EDIT bei jeder Streckengruppe (TYP "Streckengruppe", d.h. mit mindestens einem Bogen) mit "Nur einfache Gefaellestrecken..." ab - Grund war nicht fehlende Technik, sondern dass gf-linienzug-modus schlicht keine Edit-XDATA schrieb (anders als Modus 1/2 ueber SSG_GF_EDIT). Neue XDATA-App SSG_GF_LZ (gf-lz-xdata-schreiben/-lesen in Lisp/Gefaellestrecke.lsp) sichert die Segmentliste (Typ/hz/Laenge/Winkel/Seite je Segment, bereits laengenfertig) + den Baustartpunkt - Serialisierung per gf-segmente->string/gf-string->segmente, Chunking ueber die bestehenden ssg-sepliste-chunk-string/-split-feld/-explode-chars-Helfer aus ssg_ks_insert.lsp (wiederverwendet statt dupliziert). Neue Funktion gf-linienzug-rebuild: baut die Kette am selben Startpunkt neu, AS-/EIN-Element und Gefaellewinkel bleiben ueber dieselben zwei Dialoge wie beim Bauen editierbar (gf-dialog-linienzug-aus-ein/-winkel, jetzt mit prefill-Parameter fuer den Edit-Fall statt Defaults) - die Segmentlaengen/-form selbst nicht (dafuer bleibt GEFAELLESTRECKE_LINIENZUG als Neubau). c:GEFAELLESTRECKE_EDIT dispatcht vor der bisherigen TYP-Sperre: Streckengruppe MIT SSG_GF_LZ-XDATA -> neuer Rebuild-Pfad, Streckengruppe OHNE (Altbestand/VF-Kombi) -> bleibt wie bisher abgewiesen. Alter Block wird erst NACH erfolgreichem Neuaufbau geloescht. doc/variofoerderer.md um den Edit-Ablauf ergaenzt. Manuell in BricsCAD getestet (Doppelklick auf Linienzug-Streckengruppe, beide Dialoge vorbelegt, Neuaufbau, erneuter Doppelklick auf das Ergebnis) - laeuft. Co-Authored-By: Claude Sonnet 5 --- Lisp/Gefaellestrecke.lsp | 425 ++++++++++++++++++++++++++++++++++++--- doc/variofoerderer.md | 19 ++ lang/de_DE.json | 1 + lang/en_GB.json | 1 + 4 files changed, 418 insertions(+), 28 deletions(-) diff --git a/Lisp/Gefaellestrecke.lsp b/Lisp/Gefaellestrecke.lsp index b0fe4e3..83a7871 100644 --- a/Lisp/Gefaellestrecke.lsp +++ b/Lisp/Gefaellestrecke.lsp @@ -719,11 +719,14 @@ ;; EIN-Seite). Muss VOR der Segmentlaengen-Anpassung/Winkelberechnung ;; laufen (die braucht aus-dx/ein-dx aus vf-set-as-masse/-es-masse), darum ;; eigener, frueherer Dialog statt zusammen mit dem Winkel-Vorschlag. +;; prefill: Alist (("as-winkel" . "90"|"30") ("as-seite" . "links"|"rechts") +;; ("es-winkel" . ...) ("es-seite" . ...)) fuer den Edit-Nachbau, oder nil +;; fuer die Defaults (90/links) beim Neu-Bauen. ;; Rueckgabe: (as-winkel as-seite es-winkel es-seite) bei OK, 'ABBRUCH wenn ;; der Nutzer bewusst abbricht (Aufrufer bricht dann den GANZEN Befehl ab, ;; KEIN Rueckfall auf die Konsole), nil wenn der Dialog gar nicht gezeigt ;; werden konnte/durfte (GUI aus) - NUR dann Konsolen-Rueckfall. -(defun gf-dialog-linienzug-aus-ein ( / dcl-pfad dat ergebnis +(defun gf-dialog-linienzug-aus-ein (prefill / dcl-pfad dat ergebnis dlg-aus-winkel dlg-aus dlg-ein-winkel dlg-ein as-seite es-seite as-winkel es-winkel) (if (or (not (car (atoms-family 1 '("SSG-GUI-P")))) (ssg-gui-p)) @@ -740,23 +743,27 @@ (add_list "90") (add_list "30") (end_list) - (set_tile "aus_winkel" "0") + (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" "0") + (set_tile "aus_seite" + (if (and prefill (equal (cdr (assoc "as-seite" prefill)) "rechts")) "1" "0")) (start_list "ein_winkel") (add_list "90") (add_list "30") (end_list) - (set_tile "ein_winkel" "0") + (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" "0") + (set_tile "ein_seite" + (if (and prefill (equal (cdr (assoc "es-seite" prefill)) "rechts")) "1" "0")) (action_tile "accept" (strcat @@ -861,7 +868,7 @@ entry-hz exit-hz first-idx last-idx neu-l aktuell-frame nach-aus-pt - gf-nummer last-ent + gf-nummer last-ent gf-lz-insert L-gf-str delta-l-gf laengen-liste first-l l-item bL90 bL60 bL30 bR90 bR60 bR30 ein-hz-as rad-h-as rad-v-as xu-entry @@ -928,7 +935,7 @@ ;; AUS-/EIN-Element: 30/90 + Seite, in EINEM Dialog (vor Winkelberechnung, ;; da die Laengenanpassung von der AS/ES-Masse abhaengt). Rueckfall auf die ;; alten Konsolenfragen, wenn der Dialog nicht gezeigt werden kann/darf. - (setq dlg-aus-ein (gf-dialog-linienzug-aus-ein)) + (setq dlg-aus-ein (gf-dialog-linienzug-aus-ein nil)) (if (eq dlg-aus-ein 'ABBRUCH) (progn (princ (ssg-text "vfc-vorgang-abgebrochen")) (exit)) ) @@ -1222,24 +1229,30 @@ ;; Block mit allen Attributen erstellen. Geruest fuer Einzelmodul/ ;; Geruestoption sind in diesem Linienzug-Ablauf (Modus 3, keine DCL- ;; Eingabe) nicht abfragbar - bleiben auf Schema-Default. - (gf-block-erstellen - "gruppe" as-seite gf-nummer - (caddr startpunkt) - (caddr endpunkt-ref) - deltaH - delta-l-gf - L-gf-str - grade - ;; n-separator/n-scanner = 0: interne Ketten-Separatoren zaehlen nicht; - ;; die echte Anzahl setzt der Export aus platzierten Symbolen. - 0 - 0 - bL90 bL60 bL30 - bR90 bR60 bR30 - startpunkt last-ent nach-aus-pt entry-hz - (caddr (nth first-idx segmente)) - es-seite "0" "Schoenenberger Geruest" - gf-as-winkel gf-es-winkel) + (setq gf-lz-insert + (gf-block-erstellen + "gruppe" as-seite gf-nummer + (caddr startpunkt) + (caddr endpunkt-ref) + deltaH + delta-l-gf + L-gf-str + grade + ;; n-separator/n-scanner = 0: interne Ketten-Separatoren zaehlen nicht; + ;; die echte Anzahl setzt der Export aus platzierten Symbolen. + 0 + 0 + bL90 bL60 bL30 + bR90 bR60 bR30 + startpunkt last-ent nach-aus-pt entry-hz + (caddr (nth first-idx segmente)) + es-seite "0" "Schoenenberger Geruest" + gf-as-winkel gf-es-winkel)) + + ;; Segmentliste + Startpunkt fuer den Doppelklick-Nachbau sichern (siehe + ;; c:GEFAELLESTRECKE_EDIT) - ohne diese XDATA war eine per Linienzug + ;; gebaute Streckengruppe bisher nicht editierbar. + (gf-lz-xdata-schreiben gf-lz-insert segmente startpunkt) (princ "\n\n=========================================") (princ (ssg-text "gf-status-fertig")) @@ -1249,6 +1262,215 @@ ) ) +;; Doppelklick-Nachbau fuer eine per GEFAELLESTRECKE_LINIENZUG (Modus 3) +;; gebaute Streckengruppe - Gegenstueck zu gf-rebuild (Modus 1/2), aufgerufen +;; aus c:GEFAELLESTRECKE_EDIT. Anders als beim Neu-Bauen (gf-linienzug-modus) +;; sind die Segmentlaengen hier bereits FINAL (AS-/ES-dx und Separator- +;; Abzuege sind laengst eingerechnet, siehe gf-lz-xdata-schreiben) - die +;; Segmentlisten-Anpassungsschleife aus gf-linienzug-modus entfaellt darum +;; komplett, nur AS-/ES-Winkel+Seite und der Gefaellewinkel bleiben ueber +;; dieselben zwei Dialoge editierbar (gf-dialog-linienzug-aus-ein/-winkel, +;; diesmal mit Prefill aus den Block-Attributen). Baut am gleichen +;; startpunkt neu, loescht den alten Block NACH erfolgreichem Neuaufbau. +;; segmente/startpunkt: aus gf-lz-xdata-lesen. alt-ent: der zu ersetzende +;; GF_n-Block. prefill: Alist wie gf-dialog-linienzug-aus-ein (AS/ES aus den +;; aktuellen Attributen des Blocks). +(defun gf-linienzug-rebuild (segmente startpunkt alt-ent prefill / + deltaH entry-hz exit-hz as-seite es-seite + gf-as-winkel gf-es-winkel as-block es-block + dlg-aus-ein dlg-winkel-erg grade + first-idx j seg end-z endpunkt-ref delta-l-gf + aktuell-frame nach-aus-pt ein-hz-as rad-h-as xu-entry + sep-endpunkt rad-h-es rad-v-es xu-exit sep-frame es-aus-frame + gf-nummer last-ent gf-lz-insert + L-gf-str laengen-liste first-l l-item + bL90 bL60 bL30 bR90 bR60 bR30 + rad-v-korr ein-hz-as-k rad-h-as-k xu-as-meas + rad-h-es-k xu-es-meas dz-as-ist dz-es-ist + dH-korr grade-prev iter) + (if (or (null segmente) (< (length segmente) 1)) + (progn (alert (ssg-text "gf-alert-keine-kette")) (exit)) + ) + + (setq entry-hz (cadr (car segmente))) + (setq exit-hz (gf-exit-hz segmente)) + + ;; AUS-/EIN-Element, vorbelegt aus den aktuellen Attributen + (setq dlg-aus-ein (gf-dialog-linienzug-aus-ein prefill)) + (if (eq dlg-aus-ein 'ABBRUCH) + (progn (princ (ssg-text "vfc-vorgang-abgebrochen")) (exit)) + ) + (if (null dlg-aus-ein) + (progn (alert (ssg-text "gf-alert-lz-edit-kein-dialog")) (exit)) + ) + (setq gf-as-winkel (nth 0 dlg-aus-ein) + as-seite (nth 1 dlg-aus-ein) + gf-es-winkel (nth 2 dlg-aus-ein) + es-seite (nth 3 dlg-aus-ein)) + (vf-set-as-masse gf-as-winkel as-seite) + (vf-set-es-masse gf-es-winkel es-seite) + + (setq as-block (strcat "AS_Element_" gf-as-winkel "_" as-seite)) + (setq es-block (strcat "ES_Element_" gf-es-winkel "_" es-seite)) + + ;; Index des ersten "Linie"-Segments (fuer die Label-Laenge) - KEINE + ;; Laengenanpassung, die Segmentlaengen sind bereits final. + (setq first-idx -1 j 0) + (while (and (< j (length segmente)) (< first-idx 0)) + (if (= (car (nth j segmente)) "Linie") (setq first-idx j)) + (setq j (1+ j)) + ) + (if (< first-idx 0) (setq first-idx 0)) + + ;; Ziel-Endhoehe aus dem Z-Attribut HOEHE_BIS_mm des alten Blocks (X/Y des + ;; wirklichen Endpunkts wird erst NACH dem Bau aus der Geometrie selbst + ;; bestimmt, siehe unten - sie ist nicht separat in der XDATA gespeichert + ;; und nur fuer die Zusammenfassung/das Label relevant, nicht fuer den Bau + ;; selbst, der komplett der Segmentliste folgt). + (setq end-z (atof (cond ((cdr (assoc "HOEHE_BIS_mm" (ssg-attrib-read alt-ent)))) ("0")))) + (setq deltaH (abs (- (caddr startpunkt) end-z))) + + (princ (ssg-text "gf-status-berechne-winkel")) + (setq grade (gf-winkel-berechnen segmente deltaH 1)) + + (setq dlg-winkel-erg + (gf-dialog-linienzug-winkel + (list (ssg-textf "gf-status-zus-segmente" (list (length segmente))) + (ssg-textf "gf-status-zus-deltah" (list delta-sym (rtos deltaH 2 2)))) + grade gf-as-winkel as-seite gf-es-winkel es-seite)) + (if (eq dlg-winkel-erg 'ABBRUCH) + (progn (princ (ssg-text "vfc-vorgang-abgebrochen")) (exit)) + ) + (if (null dlg-winkel-erg) + (progn (alert (ssg-text "gf-alert-lz-edit-kein-dialog")) (exit)) + ) + (setq grade (float dlg-winkel-erg)) + + ;; Winkelkorrektur (identisch zu gf-linienzug-modus) + (if (and *gf-L-ohne-as-es* (> *gf-L-ohne-as-es* 0.1)) + (progn + (princ (ssg-text "gf-status-messe-absenkung")) + (setq grade-prev -999.0 iter 0) + (while (and (< iter 4) (> (abs (- grade grade-prev)) 0.001)) + (setq grade-prev grade) + (setq rad-v-korr (* grade (/ pi 180.0))) + (setq ein-hz-as-k (- entry-hz + (vf-element-plan-turn (strcat "AS_Element_" gf-as-winkel "_" as-seite)))) + (setq rad-h-as-k (* (float ein-hz-as-k) (/ pi 180.0))) + (setq xu-as-meas (list (cos rad-h-as-k) (sin rad-h-as-k) 0.0)) + (setq rad-h-es-k (* (float exit-hz) (/ pi 180.0))) + (setq xu-es-meas (list (* (cos rad-h-es-k)(cos rad-v-korr)) + (* (sin rad-h-es-k)(cos rad-v-korr)) + (- (sin rad-v-korr)))) + (setq dz-as-ist (gf-messe-dz-block as-block xu-as-meas)) + (setq dz-es-ist (gf-messe-dz-block es-block xu-es-meas)) + (setq dH-korr (- (float deltaH) dz-as-ist dz-es-ist (float *gf-sum-dz-bogen*))) + (if (and (> dH-korr 0.0) (< (/ dH-korr *gf-L-ohne-as-es*) 1.0)) + (setq grade (* (asin (/ dH-korr *gf-L-ohne-as-es*)) (/ 180.0 pi))) + (progn + (princ (ssg-text "gf-warnung-korrektur-bereich")) + (setq grade-prev grade) + ) + ) + (setq iter (1+ iter)) + ) + (princ (ssg-textf "gf-status-korrigierter-winkel" + (list (rtos grade 2 3) grad-zeichen (itoa iter)))) + ) + ) + ;; Alten Block ERST NACH erfolgreichem Neuaufbau loeschen (siehe unten) - + ;; die GF-Nummer/last-ent-Grenze muss aber VOR dem Neu-Einfuegen stehen. + (setq gf-nummer (gf-next-number)) + (setq last-ent (ssg-lastent-ohne-attribute)) + + (setq ein-hz-as (- entry-hz + (vf-element-plan-turn (strcat "AS_Element_" gf-as-winkel "_" as-seite)))) + (setq rad-h-as (* (float ein-hz-as) (/ pi 180.0))) + (setq xu-entry (list (cos rad-h-as) (sin rad-h-as) 0.0)) + (setq aktuell-frame + (insert-block-mixed-to-ks as-block (make-frame-from-dir startpunkt xu-entry) + (caddr startpunkt) nil "KS_EIN")) + (setq nach-aus-pt (car aktuell-frame)) + + (setq aktuell-frame (gf-linienzug-einfuegen segmente grade aktuell-frame)) + + (setq sep-endpunkt + (gf-insert-hz-with-ks "Staustrecke_Separator_SP_300_mm" + (car aktuell-frame) exit-hz grade 300 0)) + (setq rad-h-es (* (float exit-hz) (/ pi 180.0))) + (setq rad-v-es (* (float grade) (/ pi 180.0))) + (setq xu-exit (list (* (cos rad-h-es)(cos rad-v-es)) + (* (sin rad-h-es)(cos rad-v-es)) + (- (sin rad-v-es)))) + (setq sep-frame (make-frame-from-dir sep-endpunkt xu-exit)) + (setq es-aus-frame + (insert-block-mixed-to-ks es-block sep-frame end-z "KS_EIN" "KS_AUS")) + + ;; Echter Endpunkt (fuer DELTA_L-Attribut/Label) erst jetzt aus der + ;; gebauten Geometrie bekannt - KS_AUS des ES-Elements. + (setq endpunkt-ref (car es-aus-frame)) + (setq delta-l-gf + (sqrt (+ (expt (- (car endpunkt-ref) (car startpunkt)) 2) + (expt (- (cadr endpunkt-ref) (cadr startpunkt)) 2)))) + + (setq laengen-liste '() first-l t) + (foreach seg segmente + (if (= (car seg) "Linie") + (setq laengen-liste + (append laengen-liste (list (rtos (/ (caddr seg) 1000.0) 2 3)))) + ) + ) + (setq L-gf-str "") + (foreach l-item laengen-liste + (if first-l + (progn (setq L-gf-str l-item) (setq first-l nil)) + (setq L-gf-str (strcat L-gf-str "," l-item)) + ) + ) + + (setq bL90 0 bL60 0 bL30 0 bR90 0 bR60 0 bR30 0) + (foreach seg segmente + (if (= (car seg) "Bogen") + (cond + ((and (= (nth 4 seg) "links") (= (nth 3 seg) 90)) (setq bL90 (1+ bL90))) + ((and (= (nth 4 seg) "links") (= (nth 3 seg) 60)) (setq bL60 (1+ bL60))) + ((and (= (nth 4 seg) "links") (= (nth 3 seg) 30)) (setq bL30 (1+ bL30))) + ((and (= (nth 4 seg) "rechts") (= (nth 3 seg) 90)) (setq bR90 (1+ bR90))) + ((and (= (nth 4 seg) "rechts") (= (nth 3 seg) 60)) (setq bR60 (1+ bR60))) + ((and (= (nth 4 seg) "rechts") (= (nth 3 seg) 30)) (setq bR30 (1+ bR30))) + ) + ) + ) + + (setq gf-lz-insert + (gf-block-erstellen + "gruppe" as-seite gf-nummer + (caddr startpunkt) + (caddr endpunkt-ref) + deltaH + delta-l-gf + L-gf-str + grade + 0 0 + bL90 bL60 bL30 + bR90 bR60 bR30 + startpunkt last-ent nach-aus-pt entry-hz + (caddr (nth first-idx segmente)) + es-seite "0" "Schoenenberger Geruest" + gf-as-winkel gf-es-winkel)) + + (gf-lz-xdata-schreiben gf-lz-insert segmente startpunkt) + + ;; Alten Block erst jetzt entfernen - der Neuaufbau ist bereits vollstaendig + ;; abgeschlossen, ein Fehler davor haette ihn stehen gelassen. + (if (and alt-ent (entget alt-ent)) (entdel alt-ent)) + + (princ "\n\n=========================================") + (princ (ssg-text "gf-status-fertig")) + (princ "\n=========================================") + gf-lz-insert +) + ;; ============================================================ ;; TEIL 4.5: GF-BLOCK-SYSTEM (Nummerierung, Label, Attribute) ;; ============================================================ @@ -1871,6 +2093,124 @@ ) ) +;; ============================================================ +;; XDATA fuer den Linienzug-Nachbau (Modus 3, App "SSG_GF_LZ"). +;; Die Segmentliste (gf-analysiere-kette) hat variable Laenge - anders als +;; gf-xdata-schreiben (feste Skalare fuer Modus 1/2) braucht sie ein eigenes +;; String-Format + Chunking (255-Byte-Limit je 1000-Gruppe), analog zur +;; Sepliste-XDATA in ssg_ks_insert.lsp (ssg-sepliste-chunk-string/-split-feld/ +;; -explode-chars werden von dort wiederverwendet statt dupliziert). +;; AS-/ES-Winkel+Seite stehen bereits als Attribute (WINKEL_AS/SEITE_AS/ +;; WINKEL_ES/SEITE_ES) auf dem Block - nur die Segmentliste UND der gebaute +;; Startpunkt (fuer den Neuaufbau-Ursprung) fehlen dort und muessen hier +;; gesichert werden. +;; ============================================================ +(if (null *gf-lz-xdata-app*) (setq *gf-lz-xdata-app* "SSG_GF_LZ")) + +;; Ein Segment "(Typ hz laenge winkel seite)" -> "Typ:hz:laenge:winkel:seite". +(defun gf-segment->string (seg) + (strcat (nth 0 seg) ":" (rtos (float (nth 1 seg)) 2 4) ":" + (rtos (float (nth 2 seg)) 2 4) ":" (itoa (fix (nth 3 seg))) ":" + (nth 4 seg)) +) + +;; Gegenstueck: "Typ:hz:laenge:winkel:seite" -> (Typ hz laenge winkel seite). +(defun gf-string->segment (s / feld) + (setq feld (ssg-sepliste-split-feld s ":")) + (if (= (length feld) 5) + (list (nth 0 feld) (atof (nth 1 feld)) (atof (nth 2 feld)) + (atoi (nth 3 feld)) (nth 4 feld)) + nil + ) +) + +;; Segmentliste -> ein einzelner kommagetrennter String. +(defun gf-segmente->string (segmente / out first) + (setq out "" first t) + (foreach seg segmente + (if first + (progn (setq out (gf-segment->string seg)) (setq first nil)) + (setq out (strcat out "," (gf-segment->string seg))) + ) + ) + out +) + +;; Gegenstueck zu gf-segmente->string - nutzt denselben Zeichen-Explode wie +;; die Sepliste (ssg_ks_insert.lsp), da Segment-Trenner "," mit dem inneren +;; Feld-Trenner ":" nicht kollidiert. +(defun gf-string->segmente (s / out teile eintraege seg) + (setq out '()) + (if (> (strlen s) 0) + (progn + (setq eintraege '() teile "") + (foreach c (ssg-sepliste-explode-chars s) + (if (= c ",") + (progn (setq eintraege (cons teile eintraege)) (setq teile "")) + (setq teile (strcat teile c)) + ) + ) + (setq eintraege (reverse (cons teile eintraege))) + (foreach eintrag eintraege + (if (setq seg (gf-string->segment eintrag)) (setq out (cons seg out))) + ) + ) + ) + (reverse out) +) + +;; Segmentliste + Nachbau-Startpunkt als XDATA schreiben. Marker "linienzug" +;; als erster Wert (Platz fuer kuenftige Varianten, analog SSG_VF_EDIT). +(defun gf-lz-xdata-schreiben (ent segmente startpunkt / chunks appentry) + (if (and ent segmente) + (progn + (regapp *gf-lz-xdata-app*) + (setq chunks + (ssg-sepliste-chunk-string + (strcat (rtos (car startpunkt) 2 4) ";" (rtos (cadr startpunkt) 2 4) ";" + (rtos (caddr startpunkt) 2 4) ";" (gf-segmente->string segmente)) + 250)) + (setq appentry + (cons *gf-lz-xdata-app* + (cons (cons 1000 "linienzug") + (mapcar (function (lambda (c) (cons 1000 c))) chunks)))) + (entmod (append (entget ent) (list (list -3 appentry)))) + ) + ) + ent +) + +;; XDATA lesen -> (startpunkt segmente) oder nil (kein/unbekanntes Linienzug- +;; XDATA am Entity). +(defun gf-lz-xdata-lesen (ent / xd app-data werte roh teile sp-x sp-y sp-z rest) + (setq xd (entget ent (list *gf-lz-xdata-app*))) + (setq app-data (cdr (assoc -3 xd))) + (if app-data + (progn + (setq werte (mapcar 'cdr (cdr (car app-data)))) + (if (and werte (= (car werte) "linienzug")) + (progn + (setq roh (apply 'strcat (cdr werte))) + (setq teile (ssg-sepliste-split-feld roh ";")) + (if (>= (length teile) 4) + (progn + (setq sp-x (atof (nth 0 teile)) sp-y (atof (nth 1 teile)) + sp-z (atof (nth 2 teile))) + ;; Rest nach dem 3. ";" wieder zusammenfuegen (Segmentliste + ;; selbst enthaelt kein ";"). + (setq rest (nth 3 teile)) + (list (list sp-x sp-y sp-z) (gf-string->segmente rest)) + ) + nil + ) + ) + nil + ) + ) + nil + ) +) + ;; ============================================================ ;; TEIL 6: HAUPTBEFEHL ;; ============================================================ @@ -2161,7 +2501,8 @@ (defun c:GEFAELLESTRECKE_EDIT ( / ss ent ed bname startpunkt attribs xd hz winkel as-winkel es-winkel z-start deltaL - as-seite hoehe-bis prefill dlg-werte) + as-seite hoehe-bis prefill dlg-werte + lz-xd lz-segmente lz-startpunkt lz-prefill) ;; Implied Selection VOR ssg-start pruefen (ssg-start hebt Selektion auf) (setq ss (ssget "I")) (if (and ss (= (sslength ss) 1) @@ -2189,9 +2530,37 @@ (setq startpunkt (cdr (assoc 10 ed))) (setq attribs (ssg-attrib-read ent)) + ;; Streckengruppe (mit Bogen) aus GEFAELLESTRECKE_LINIENZUG: eigener + ;; Rebuild-Pfad ueber die Segmentliste in SSG_GF_LZ-XDATA (siehe + ;; gf-linienzug-rebuild), NICHT ueber den einfachen gefaellestrecke-Dialog + ;; unten - der kennt keine Segmentliste/Boegen. Streckengruppe OHNE diese + ;; XDATA (Altbestand/VF-Kombi) bleibt wie bisher nicht editierbar. + (if (= (cond ((cdr (assoc "TYP" attribs))) ("")) "Streckengruppe") + (progn + (setq lz-xd (gf-lz-xdata-lesen ent)) + (cond + (lz-xd + (setq lz-startpunkt (nth 0 lz-xd)) + (setq lz-segmente (nth 1 lz-xd)) + (setq lz-prefill + (list (cons "as-winkel" (cond ((cdr (assoc "WINKEL_AS" attribs))) ("90"))) + (cons "as-seite" (cond ((cdr (assoc "SEITE_AS" attribs))) ("links"))) + (cons "es-winkel" (cond ((cdr (assoc "WINKEL_ES" attribs))) ("90"))) + (cons "es-seite" (cond ((cdr (assoc "SEITE_ES" attribs))) ("links"))))) + (gf-linienzug-rebuild lz-segmente lz-startpunkt ent lz-prefill) + ) + (t + (alert (ssg-textf "gf-edit-nur-einfach" + (list (cond ((cdr (assoc "TYP" attribs))) ("?"))))) + ) + ) + (ssg-end) + (exit) + ) + ) + ;; Nur einfache Gefaellestrecken (TYP "Gefaellestrecke") lassen sich ueber den - ;; Dialog verlustfrei nachbauen. Streckengruppen (mit Bogen / Linienzug / VF) - ;; wuerden beim Neuaufbau ihre Bogengeometrie verlieren -> abbrechen. + ;; Dialog verlustfrei nachbauen. (if (/= (cond ((cdr (assoc "TYP" attribs))) ("")) "Gefaellestrecke") (progn (alert (ssg-textf "gf-edit-nur-einfach" diff --git a/doc/variofoerderer.md b/doc/variofoerderer.md index f4897a6..ad0d2a8 100644 --- a/doc/variofoerderer.md +++ b/doc/variofoerderer.md @@ -280,6 +280,25 @@ Konsole zurueckzufallen. Kontrolle in der Zeichnung stehen: ![GF aus Linienzug - fertige Strecke neben der Ausgangslinie](images/gf-linienzug3.png) +**Bearbeiten (`c:GEFAELLESTRECKE_EDIT`):** Doppelklick auf einen per +Linienzug gebauten `GF_n`-Block (TEILEART `"Streckengruppe"`, enthaelt +mindestens einen Bogen) dispatcht auf `gf-linienzug-rebuild` statt auf den +einfachen Gefaellestrecke-Dialog — der kennt keine Segmentliste/Boegen und +wuerde beim Neuaufbau die Bogengeometrie verlieren. Die Segmentliste +(Typ/Fahrtrichtung/Laenge/Winkel/Seite je Segment, bereits laengenfertig) +UND der Baustartpunkt stehen als eigene XDATA (App `SSG_GF_LZ`, +`gf-lz-xdata-schreiben`/`-lesen`, variable Laenge + Chunking wie die +Sepliste-XDATA in `ssg_ks_insert.lsp`) auf dem Block — ohne sie bleibt eine +Streckengruppe wie zuvor nicht editierbar (Meldung "Nur einfache +Gefaellestrecken..."). Der Edit-Ablauf nutzt dieselben zwei Dialoge wie das +Bauen (`gf-dialog-linienzug-aus-ein`/`-winkel`), diesmal mit den aktuellen +Attributen (`WINKEL_AS`/`SEITE_AS`/`WINKEL_ES`/`SEITE_ES`) vorbelegt statt +mit Defaults — AS-/ES-Element und Gefaellewinkel bleiben damit nachtraeglich +aenderbar, die Segmentlaengen/-form (Geraden, Boegen) selbst nicht (dafuer +muss die Kette per `GEFAELLESTRECKE_LINIENZUG` neu gebaut werden). Baut am +selben Startpunkt neu und loescht den alten Block erst NACH erfolgreichem +Neuaufbau. + --- ## 5. VF Linienzug — Kette (Modus 1, frei zeichnend) diff --git a/lang/de_DE.json b/lang/de_DE.json index 89a83c5..21e5686 100644 --- a/lang/de_DE.json +++ b/lang/de_DE.json @@ -777,6 +777,7 @@ "gf-status-deltah-3dpunkte": "\n %1H aus 3D-Punkten: %2 mm", "gf-status-sortiere-segmente": "\n Sortiere Segmente ...", "gf-alert-keine-kette": "Keine verbundene Kette gefunden!", + "gf-alert-lz-edit-kein-dialog": "Bearbeiten einer Streckengruppe (Linienzug) braucht die GUI - bitte GUI einschalten (ssg-gui-an) und erneut versuchen.", "gf-status-segmente-gefunden": " %1 Segmente gefunden.", "gf-status-segment-analyse-header": "\n\n--- Segment-Analyse (Laengen nach Kuerzung) ---", "gf-status-segment-linie": "\n %1. Linie L=%2 mm hz=%3%4", diff --git a/lang/en_GB.json b/lang/en_GB.json index 1c4e2b9..87733d4 100644 --- a/lang/en_GB.json +++ b/lang/en_GB.json @@ -777,6 +777,7 @@ "gf-status-deltah-3dpunkte": "\n %1H from 3D points: %2 mm", "gf-status-sortiere-segmente": "\n Sorting segments ...", "gf-alert-keine-kette": "No connected chain found!", + "gf-alert-lz-edit-kein-dialog": "Editing a chain group (path-built) requires the GUI - please enable the GUI (ssg-gui-an) and try again.", "gf-status-segmente-gefunden": " %1 segments found.", "gf-status-segment-analyse-header": "\n\n--- Segment analysis (lengths after trimming) ---", "gf-status-segment-linie": "\n %1. Line L=%2 mm hz=%3%4",