fix: Z-Versatz bei GF/VF behoben (OSMODE=0 im Wrap ssg-block-wrap-welt); gepickte Hoehe als Einfuegehoehe im GF-Dialog

This commit is contained in:
2026-07-21 14:05:13 +02:00
parent d99bdb10d5
commit 5bb6bb8241
4 changed files with 111 additions and 28 deletions
+55 -16
View File
@@ -1438,7 +1438,7 @@
startpunkt last-ent nach-aus-pt entry-hz L-first-seg startpunkt last-ent nach-aus-pt entry-hz L-first-seg
es-seite / es-seite /
gf-bname gf-ss ent gf-insert typ-str anzahl-gf gf-bname gf-ss ent gf-insert typ-str anzahl-gf
gf-winkel-str i) gf-winkel-str i gf-g10z gf-korr-dz gf-osmode-alt)
;; Beschriftung: Mitte der ersten Geraden, 400mm senkrecht versetzt ;; Beschriftung: Mitte der ersten Geraden, 400mm senkrecht versetzt
(gf-make-label gf-nummer hoehe-von hoehe-bis deltaH deltaL (gf-make-label gf-nummer hoehe-von hoehe-bis deltaH deltaL
L-gf-str winkel n-separator nach-aus-pt entry-hz L-first-seg) L-gf-str winkel n-separator nach-aus-pt entry-hz L-first-seg)
@@ -1479,15 +1479,26 @@
(ssadd ent gf-ss) (ssadd ent gf-ss)
(setq ent (entnext ent)) (setq ent (entnext ent))
) )
;; Block definieren und einfuegen (ATTREQ/ATTDIA=0: keine interaktive Abfrage) ;; Block definieren und einfuegen. ssg-block-wrap-welt schaltet dabei den
(setvar "ATTREQ" 0) ;; Objektfang (OSMODE=0), die Elevation (0) und das BKS (Welt) sauber ab -
(setvar "ATTDIA" 0) ;; sonst wird der uebergebene Einfuegepunkt umgefangen bzw. der OCS-Skew der
(command "_.-BLOCK" gf-bname startpunkt gf-ss "") ;; gekippten Elemente schlaegt durch (Ursache des Z-Versatz-Bugs).
(command "_.INSERT" gf-bname startpunkt 1.0 1.0 0.0) (ssg-block-wrap-welt gf-bname startpunkt gf-ss)
(setvar "ATTREQ" 1)
;; Attribute auf das eingefuegte INSERT-Objekt setzen (volle Werteliste; ;; Attribute auf das eingefuegte INSERT-Objekt setzen (volle Werteliste;
;; nicht vorhandene Tags ignoriert ssg-attrib-set-on -> reduzierter Satz ok). ;; nicht vorhandene Tags ignoriert ssg-attrib-set-on -> reduzierter Satz ok).
(setq gf-insert (entlast)) (setq gf-insert (entlast))
;; Kette wurde bei Z=0 gebaut; der OSMODE=0-Wrap loest den OCS-Skew der
;; gekippten Elemente sauber zur logischen Position (Z=0) auf. Den fertigen
;; GF_n-Block daher nur noch senkrecht auf die Zielhoehe heben (OSMODE=0,
;; sonst faengt _.MOVE die Punkte auf Objekte um). gf-g10z faengt einen
;; evtl. Rest-Z im Einfuegepunkt ab.
(setq gf-g10z (cadddr (assoc 10 (entget gf-insert))))
(setq gf-korr-dz (- hoehe-von gf-g10z))
(setq gf-osmode-alt (getvar "OSMODE"))
(setvar "OSMODE" 0)
(if (> (abs gf-korr-dz) 1e-6)
(command "_.MOVE" gf-insert "" (list 0.0 0.0 0.0) (list 0.0 0.0 gf-korr-dz)))
(setvar "OSMODE" gf-osmode-alt)
(ssg-attrib-set-on gf-insert (ssg-attrib-set-on gf-insert
(list (list
(cons "Bezeichnung" gf-bname) (cons "Bezeichnung" gf-bname)
@@ -1533,9 +1544,22 @@
ein-hz rad-ein xu-ein ein-hz rad-ein xu-ein
startframe aktuell-frame startframe aktuell-frame
stau-endpunkt sep-endpunkt sep-frame stau-endpunkt sep-endpunkt sep-frame
gf-deltaH L-gf-str nach-aus-pt gf-insert) gf-deltaH L-gf-str nach-aus-pt gf-insert
ziel-hoehe alt-elev)
(if (null as-winkel) (setq as-winkel "90")) (if (null as-winkel) (setq as-winkel "90"))
(if (null es-winkel) (setq es-winkel "90")) (if (null es-winkel) (setq es-winkel "90"))
;; Gesamte Operation mit ELEVATION=0 fahren. Fing man den Startpunkt auf
;; einen hohen Punkt, kann ELEVATION != 0 sein und veraendert, wie die
;; gekippten Elemente gezeichnet werden (OCS-Skew wird sonst inkonsistent
;; absorbiert -> Rest-Versatz). Mit ELEVATION=0 ist der Skew immer 31.945.
(setq alt-elev (getvar "ELEVATION"))
(setvar "ELEVATION" 0.0)
;; Gepickte Zielhoehe merken und die Kette intern bei Z=0 aufbauen. Das
;; entkoppelt den (hoehenunabhaengigen) OCS-Skew der gekippten Elemente von
;; der Zielhoehe: Elemente immer bei 0 platzieren, den fertigen (nicht
;; gekippten) GF_n-Block danach in gf-block-erstellen auf ziel-hoehe heben.
(setq ziel-hoehe (caddr startpunkt))
(setq startpunkt (list (car startpunkt) (cadr startpunkt) 0.0))
(setq as-block (strcat "AS_Element_" as-winkel "_" as-seite)) (setq as-block (strcat "AS_Element_" as-winkel "_" as-seite))
(setq es-block (strcat "ES_Element_" es-winkel "_" es-seite)) (setq es-block (strcat "ES_Element_" es-winkel "_" es-seite))
(if (not *lib-initialized*) (gf-init-bibliothek)) (if (not *lib-initialized*) (gf-init-bibliothek))
@@ -1601,8 +1625,11 @@
(setq gf-insert (setq gf-insert
(gf-block-erstellen (gf-block-erstellen
"standard" as-seite gf-nummer "standard" as-seite gf-nummer
(caddr startpunkt) ;; hoehe-von = Zielhoehe; hoehe-bis = Zielhoehe + (relative Endhoehe der
(caddr endpunkt) ;; bei Z=0 gebauten Kette). So sind die Hoehen-Attribute korrekt, obwohl
;; die Kette intern bei 0 liegt (der GF_n-Block wird spaeter angehoben).
ziel-hoehe
(+ ziel-hoehe (caddr endpunkt))
gf-deltaH gf-deltaH
(float deltaL-total) (float deltaL-total)
L-gf-str L-gf-str
@@ -1616,11 +1643,13 @@
;; auf das GF_N-INSERT schreiben, damit GEFAELLESTRECKE_EDIT die Strecke ;; auf das GF_N-INSERT schreiben, damit GEFAELLESTRECKE_EDIT die Strecke
;; verlustfrei nachbauen kann. Nicht Teil des Sivas-Attributsatzes. ;; verlustfrei nachbauen kann. Nicht Teil des Sivas-Attributsatzes.
(gf-xdata-schreiben gf-insert hz winkel as-winkel es-winkel (gf-xdata-schreiben gf-insert hz winkel as-winkel es-winkel
(caddr startpunkt) deltaL-total) ziel-hoehe deltaL-total)
(princ "\n\n=========================================") (princ "\n\n=========================================")
(princ (ssg-text "gf-status-erfolgreich-eingefuegt")) (princ (ssg-text "gf-status-erfolgreich-eingefuegt"))
(princ "\n=========================================") (princ "\n=========================================")
;; ELEVATION wiederherstellen (Nutzer-Umgebung nicht dauerhaft veraendern).
(setvar "ELEVATION" alt-elev)
;; Rueckgabe: (ename echtes-deltaH echtes-deltaL) - volle Fliesskomma- ;; Rueckgabe: (ename echtes-deltaH echtes-deltaL) - volle Fliesskomma-
;; Genauigkeit, unabhaengig von der auf ganze mm gerundeten HOEHE_VON/ ;; Genauigkeit, unabhaengig von der auf ganze mm gerundeten HOEHE_VON/
;; HOEHE_BIS-Attribut-Darstellung im GF_N-Block. ;; HOEHE_BIS-Attribut-Darstellung im GF_N-Block.
@@ -1640,7 +1669,7 @@
;; Rueckgabe: (deltaL winkel hz-winkel as-seite es-seite einfuegehoehe ;; Rueckgabe: (deltaL winkel hz-winkel as-seite es-seite einfuegehoehe
;; as-winkel es-winkel) ;; as-winkel es-winkel)
;; oder nil bei Abbruch / fehlendem Dialog. ;; oder nil bei Abbruch / fehlendem Dialog.
(defun gf-dialog-eingabe ( prefill / dcl-pfad dat ergebnis (defun gf-dialog-eingabe ( prefill hoehe-vorbelegung / dcl-pfad dat ergebnis
dlg-deltal dlg-hoehe dlg-winkel dlg-deltal dlg-hoehe dlg-winkel
dlg-richtung dlg-aus dlg-ein dlg-richtung dlg-aus dlg-ein
dlg-aus-winkel dlg-ein-winkel dlg-aus-winkel dlg-ein-winkel
@@ -1658,8 +1687,12 @@
(set_tile "deltal" (set_tile "deltal"
(if prefill (rtos (cdr (assoc "deltaL" prefill)) 2 0) (if prefill (rtos (cdr (assoc "deltaL" prefill)) 2 0)
(rtos (ssg-cfg-or "gefaelle" "default_delta_l" 5000.0) 2 0))) (rtos (ssg-cfg-or "gefaelle" "default_delta_l" 5000.0) 2 0)))
;; Einfuegehoehe: 1) explizite Vorbelegung (gepickte Punkthoehe, Modus 1),
;; 2) prefill (Edit), 3) Default "0".
(set_tile "einfuegehoehe" (set_tile "einfuegehoehe"
(if prefill (rtos (cdr (assoc "einfuegehoehe" prefill)) 2 1) "0")) (cond (hoehe-vorbelegung (rtos hoehe-vorbelegung 2 1))
(prefill (rtos (cdr (assoc "einfuegehoehe" prefill)) 2 1))
(t "0")))
(set_tile "winkel" (set_tile "winkel"
(if prefill (rtos (cdr (assoc "winkel" prefill)) 2 1) (if prefill (rtos (cdr (assoc "winkel" prefill)) 2 1)
(rtos (ssg-cfg-or "gefaelle" "default_winkel" 3.0) 2 1))) (rtos (ssg-cfg-or "gefaelle" "default_winkel" 3.0) 2 1)))
@@ -1966,12 +1999,14 @@
;; Modus 1: Manuelle Eingabe via DCL-Dialog ;; Modus 1: Manuelle Eingabe via DCL-Dialog
(t (t
(princ (ssg-text "gf-modus1-header")) (princ (ssg-text "gf-modus1-header"))
;; Startpunkt (X/Y) in der Zeichnung waehlen; Z kommt aus dem Dialog ;; Startpunkt (X/Y/Z) in der Zeichnung waehlen. Faengt man einen Punkt mit
;; Hoehe (z.B. Basispunkt Z=12000), wird diese als Einfuegehoehe in den
;; Dialog vorbelegt - der Nutzer kann sie dort bestaetigen oder aendern.
(setq startpunkt-fuer-einfuegen (setq startpunkt-fuer-einfuegen
(getpoint (ssg-text "gf-prompt-startpunkt-aus"))) (getpoint (ssg-text "gf-prompt-startpunkt-aus")))
(if (null startpunkt-fuer-einfuegen) (if (null startpunkt-fuer-einfuegen)
(setq startpunkt-fuer-einfuegen '(0 0 0))) (setq startpunkt-fuer-einfuegen '(0 0 0)))
(setq dlg-werte (gf-dialog-eingabe nil)) (setq dlg-werte (gf-dialog-eingabe nil (caddr startpunkt-fuer-einfuegen)))
(if (null dlg-werte) (if (null dlg-werte)
(princ (ssg-text "gf-status-abgebrochen")) (princ (ssg-text "gf-status-abgebrochen"))
(progn (progn
@@ -1982,7 +2017,11 @@
es-seite (nth 4 dlg-werte) es-seite (nth 4 dlg-werte)
gf-as-winkel (nth 6 dlg-werte) gf-as-winkel (nth 6 dlg-werte)
gf-es-winkel (nth 7 dlg-werte)) gf-es-winkel (nth 7 dlg-werte))
;; Einfuegehoehe (Z) aus Dialog auf gewaehlten Startpunkt anwenden ;; Einfuegehoehe = Dialogwert (nth 5), der mit der gepickten Hoehe
;; vorbelegt wurde. So gewinnt die gepickte Hoehe standardmaessig,
;; bleibt aber im Dialog editierbar. Nur diese Z-Hoehe zaehlt (X/Y
;; vom gefangenen Punkt) -> geht als ziel-hoehe in die Attribute und
;; als finale Hoehe in den GF_n-Move (gf-block-erstellen).
(setq startpunkt-fuer-einfuegen (setq startpunkt-fuer-einfuegen
(list (car startpunkt-fuer-einfuegen) (list (car startpunkt-fuer-einfuegen)
(cadr startpunkt-fuer-einfuegen) (cadr startpunkt-fuer-einfuegen)
+46
View File
@@ -73,6 +73,52 @@
) )
;; ------------------------------------------------------------
;; BLOCK-WRAP MIT GARANTIERT WELTPARALLELEM BKS
;; ------------------------------------------------------------
;; Fasst die Entities in ss zu einem Block bname zusammen und fuegt ihn am
;; Welt-Punkt basispkt-welt wieder ein. Setzt das BKS dazu temporaer hart
;; auf Welt und stellt es danach wieder her.
;;
;; Hintergrund (31.95mm-Z-Versatz-Bug): (command "_.-BLOCK"/"_.INSERT" ...)
;; rechnet Punktargumente im AKTUELLEN BKS. Bei einem vom Welt-KS
;; abweichenden BKS ging der korrekt via (trans ...) umgerechnete Z-Wert
;; beim _.-BLOCK -> _.INSERT-Rundlauf verloren, sodass der fertige Block
;; um die BKS-Hoehe (z.B. 31.95mm) in Z verschoben wurde - obwohl die
;; ELEVATION-Systemvariable 0 war. Bei BKS=Welt liegen Objekte, Basispunkt
;; und Einfuegepunkt alle bei WCS-Z ohne jede Umrechnungs-Mehrdeutigkeit;
;; ein bei WCS-Z=0 platziertes Element bleibt garantiert bei Z=0.
;;
;; Rueckgabe: das eingefuegte INSERT-Objekt (entlast).
(defun ssg-block-wrap-welt (bname basispkt-welt ss / alt-attreq alt-attdia alt-elev alt-osmode)
(setq alt-attreq (getvar "ATTREQ")
alt-attdia (getvar "ATTDIA")
alt-elev (getvar "ELEVATION")
alt-osmode (getvar "OSMODE"))
(setvar "ATTREQ" 0)
(setvar "ATTDIA" 0)
;; OSMODE=0: laufenden Objektfang abschalten. Sonst kann _.INSERT den
;; explizit uebergebenen Einfuegepunkt (X,Y,0) auf ein an derselben X/Y-Stelle
;; liegendes Objekt umfangen - z.B. den gefangenen Basispunkt bei Z=12000 ->
;; der Block landet auf 12000 statt 0 (12000er-Bug).
(setvar "OSMODE" 0)
;; ELEVATION=0: sonst kann _.INSERT die Z-Hoehe aus der aktuellen Elevation
;; statt aus dem uebergebenen Punkt ziehen.
(setvar "ELEVATION" 0.0)
;; BKS temporaer auf Welt; _Previous stellt danach das vorige BKS wieder her.
(command "_.UCS" "_World")
;; basispkt-welt ist ein Welt-Punkt; bei BKS=Welt ist er zugleich BKS-Punkt.
(command "_.-BLOCK" bname basispkt-welt ss "")
(command "_.INSERT" bname basispkt-welt 1.0 1.0 0.0)
(command "_.UCS" "_Previous")
(setvar "OSMODE" alt-osmode)
(setvar "ELEVATION" alt-elev)
(setvar "ATTREQ" alt-attreq)
(setvar "ATTDIA" alt-attdia)
(entlast)
)
;; ------------------------------------------------------------ ;; ------------------------------------------------------------
;; BENUTZER-ABFRAGEN ;; BENUTZER-ABFRAGEN
;; ------------------------------------------------------------ ;; ------------------------------------------------------------
+5 -6
View File
@@ -1104,12 +1104,11 @@
(setq vf-bname (strcat "VF_" (itoa vf-nummer))) (setq vf-bname (strcat "VF_" (itoa vf-nummer)))
(if (> (sslength vf-ss) 0) (if (> (sslength vf-ss) 0)
(progn (progn
(setvar "ATTREQ" 0) ;; Block definieren und einfuegen mit garantiert weltparallelem BKS.
(setvar "ATTDIA" 0) ;; startpunkt ist ein Welt-Punkt; ssg-block-wrap-welt setzt das BKS
(command "_.-BLOCK" vf-bname startpunkt vf-ss "") ;; temporaer auf Welt (verhindert den 31.95mm-Z-Versatz bei
(command "_.INSERT" vf-bname startpunkt 1.0 1.0 0.0) ;; abweichendem BKS) und stellt es danach wieder her.
(setvar "ATTREQ" 1) (setq vf-insert (ssg-block-wrap-welt vf-bname startpunkt vf-ss))
(setq vf-insert (entlast))
(setq montagehoehe-m (/ (+ hoehe-von hoehe-bis) 2000.0)) (setq montagehoehe-m (/ (+ hoehe-von hoehe-bis) 2000.0))
;; L_GF_m: kommagetrennte Segmentlaengen in Metern (vorne,hinten), ;; L_GF_m: kommagetrennte Segmentlaengen in Metern (vorne,hinten),
;; analog L_GF_m in Gefaellestrecke.lsp. ;; analog L_GF_m in Gefaellestrecke.lsp.
+5 -6
View File
@@ -821,12 +821,11 @@
(ssadd ent vfl-ss) (ssadd ent vfl-ss)
(setq ent (entnext ent)) (setq ent (entnext ent))
) )
(setvar "ATTREQ" 0) ;; Block definieren und einfuegen mit garantiert weltparallelem BKS.
(setvar "ATTDIA" 0) ;; startpunkt ist ein Welt-Punkt; ssg-block-wrap-welt setzt das BKS
(command "_.-BLOCK" vfl-bname startpunkt vfl-ss "") ;; temporaer auf Welt (verhindert den 31.95mm-Z-Versatz bei abweichendem
(command "_.INSERT" vfl-bname startpunkt 1.0 1.0 0.0) ;; BKS, siehe Kommentar dort) und stellt es danach wieder her.
(setvar "ATTREQ" 1) (setq vfl-insert (ssg-block-wrap-welt vfl-bname startpunkt vfl-ss))
(setq vfl-insert (entlast))
;; Werte (volle Liste; nicht vorhandene Tags ignoriert ssg-attrib-set-on) ;; Werte (volle Liste; nicht vorhandene Tags ignoriert ssg-attrib-set-on)
(ssg-attrib-set-on vfl-insert (ssg-attrib-set-on vfl-insert
(list (list