diff --git a/Lisp/vf_linienzug.lsp b/Lisp/vf_linienzug.lsp index 230c32c..dcba232 100644 --- a/Lisp/vf_linienzug.lsp +++ b/Lisp/vf_linienzug.lsp @@ -3446,6 +3446,48 @@ frame ) +;; Projiziert eine rohe (dx,dz)-Bogenmasse (bei Rotation 0 gemessen, siehe +;; get-bogen-mass) in die Welt, wenn der Bogen bei einer gegebenen Neigung +;; (Grad, gefaelle-winkel-Konvention: positiv=fallend) eingebaut wird - +;; dieselbe Rz(hz)*Ry(rot)-Projektion wie insert-rotated-block-with-ks, hier +;; OHNE Insert (reine Vorausberechnung fuer vfl-gf-auf-ab-solve). Rueckgabe: +;; (welt-dx welt-dz). +(defun vfl-projiziere-neigung (dx dz rot-grad / rad) + (setq rad (* (float rot-grad) (/ pi 180.0))) + (list (+ (* dx (cos rad)) (* dz (sin rad))) + (+ (- (* dx (sin rad))) (* dz (cos rad)))) +) + +;; Rein rechnerisches (KEIN Bau) Pendant zu vfl-gf-bogen-erweitern - fuer +;; Option 4's Formel-basierten Solver (vfl-gf-auf-ab-solve), der die +;; Neigungs-Erweiterung VORAB in die Fixterme einrechnen muss, BEVOR +;; ueberhaupt etwas gebaut wird (Nutzer-Vorgabe 2026-09-14: dieselbe +;; dynamische Winkelwahl wie Option 5, jetzt auch fuer Option 4). Summiert +;; die WELT-(dx,dz) einer Kette aus moeglichst wenigen Bausteinen +;; (moeglichst viele 6-Grad-, ein 3-Grad-Rest-Baustein), exakt in derselben +;; Reihenfolge/Neigungs-Abfolge wie vfl-gf-bogen-erweitern es spaeter ECHT +;; baut - extra-grad=0 liefert (0.0 0.0). Rueckgabe: (welt-dx welt-dz). +(defun vfl-gf-bogen-summe (richtung eingehende-neigung extra-grad / + rest neigung-jetzt m proj sum-dx sum-dz) + (setq sum-dx 0.0 sum-dz 0.0 rest extra-grad neigung-jetzt eingehende-neigung) + (while (>= rest 6) + (setq m (get-bogen-mass (if (= richtung "auf") *gf-bogen-auf* *gf-bogen-ab*) 6)) + (setq proj (vfl-projiziere-neigung (car m) (caddr m) neigung-jetzt)) + (setq sum-dx (+ sum-dx (car proj)) sum-dz (+ sum-dz (cadr proj))) + (setq neigung-jetzt (if (= richtung "auf") (- neigung-jetzt 6) (+ neigung-jetzt 6))) + (setq rest (- rest 6)) + ) + (if (= rest 3) + (progn + (setq m (get-bogen-mass (if (= richtung "auf") *gf-bogen-auf* *gf-bogen-ab*) 3)) + (setq proj (vfl-projiziere-neigung (car m) (caddr m) neigung-jetzt)) + (setq sum-dx (+ sum-dx (car proj))) + (setq sum-dz (+ sum-dz (cadr proj))) + ) + ) + (list sum-dx sum-dz) +) + ;; 2D-Rotation eines LOKALEN (dx,dy)-Versatzes (KS_EIN->KS_AUS eines Blocks ;; bei Rotation 0, siehe vf-element-masse) um einen WELT-Richtungswinkel ;; (Grad) - dieselbe Rz(hz)-Rotationsformel wie in insert-block-ks-to-ks/ @@ -3490,14 +3532,20 @@ ;; 2026-09-12, Geometrie danach nach BricsCAD-Test komplett ueberarbeitet): ;; automatisch berechnete Auf-Ab-GF-Kette, die auf derselben ;; Hoehe endet, auf der sie beginnt - AS -> fallend-GF -> 30-Grad-Bogen -> -;; [fallend-GF -> 6-Grad-Bogen auf -> steigend-GF -> 6-Grad-Bogen ab -> -;; fallend-GF] -> 30-Grad-Bogen (Gegenseite) -> fallend-GF -> ES. Die beiden -;; fallenden Mittelstuecke (vor/nach dem Steig-Stueck) werden als EIN -;; gemeinsamer Unbekannter F_total behandelt (Nutzer-Vorgabe, aufgeteilt -;; nach einem waehlbaren Anteil) - vfl-gf-auf-ab-solve loest F_total und das -;; steigende Mittelstueck S aus der vorgegebenen Mittelteil-Gesamtlaenge und -;; der geforderten Netto-Hoehenaenderung (hier immer 0, da AS/ES auf -;; derselben Hoehe liegen sollen). +;; [fallend-GF -> Bogen auf (6 Grad, ggf. steiler) -> steigend-GF -> Bogen ab +;; (6 Grad, ggf. steiler) -> fallend-GF] -> 30-Grad-Bogen (Gegenseite) -> +;; fallend-GF -> ES. Die beiden fallenden Mittelstuecke (vor/nach dem +;; Steig-Stueck) werden als EIN gemeinsamer Unbekannter F_total behandelt +;; (Nutzer-Vorgabe, aufgeteilt nach einem waehlbaren Anteil) - +;; vfl-gf-auf-ab-solve loest F_total und das steigende Mittelstueck S aus +;; der vorgegebenen Mittelteil-Gesamtlaenge und der geforderten Netto- +;; Hoehenaenderung (hier immer 0, da AS/ES auf derselben Hoehe liegen +;; sollen). S's Neigung wird dabei DYNAMISCH gewaehlt (Nutzer-Vorgabe +;; 2026-09-14, dieselbe Idee wie Option 5): 3 Grad (symmetrischer +;; Grundfall) zuerst, dann 6/9/12/...Grad, bis F_total UND S beide baubar +;; (>=0) sind - der FLACHSTE passende Winkel gewinnt, damit auch kuerzere +;; Mittelteil-Gesamtlaengen noch baubar sind, statt nur bei einem einzigen +;; fest verdrahteten Winkel zu funktionieren. ;; ;; Weltmass-Formel wie insert-rotated-block-with-ks (ssg_ks_insert.lsp): ;; world_dx = dx*cos(rot) + dz*sin(rot) (horizontal, entlang hz) @@ -3506,38 +3554,60 @@ ;; -gefaelle-winkel fuer den "ab"-Bogen (Einstieg steigend) - siehe ;; vfl-gf-bogen-uebergang, das dieselben Tabellen beim tatsaechlichen Bau ;; verwendet. +;; s-winkel (Nutzer-Vorgabe 2026-09-14: dieselbe dynamische Winkelwahl wie +;; Option 5 - "gegebene Laenge -> passenden Winkel waehlen"): die Neigung +;; des steigenden Mittelstuecks S (Grad, STEIGEND-Betrag - F_total bleibt +;; IMMER bei *vfk-gefaelle-winkel*, nur S wird bei Bedarf steiler). Der +;; Aufrufer probiert typischerweise s-winkel=3 (symmetrischer Grundfall), +;; dann 6, 9, ... bis gueltig=T (siehe vfl-qc-linie-mit-gf). ;; Rueckgabe: (f-total s gueltig ziel-laenge-min) - f-total/s als horizontale ;; Laengen (wie deltaL bei vfl-insert-gf-segment), gueltig=nil bei negativem ;; Ergebnis (Mittelteil-Vorgabe geometrisch nicht baubar). ziel-laenge-min ist -;; in diesem Fall die kleinste Gesamtlaenge, mit der f-total UND s beide >= 0 +;; in diesem Fall die kleinste Gesamtlaenge, mit der f-total UND s BEIDE >= 0 ;; wuerden (Nutzer-Vorgabe 2026-09-13: als Vorschlag in der Fehlermeldung -;; ausgeben) - hergeleitet aus a=f-total+s, c=s-f-total (a,c wie unten): damit -;; beide >=0 sind, muss a >= |c| gelten, also ziel-laenge-horiz >= fix-dx+|c|. -(defun vfl-gf-auf-ab-solve (ziel-laenge-horiz ziel-hoehe-delta / - rad3 tan3 m-auf m-ab dx-auf dz-auf dx-ab dz-ab - fix-dx fix-dz a b c f-total s gueltig ziel-laenge-min) +;; ausgeben) - aus F_total+S=a, -F_total*tan3+S*tan(s-winkel)=b (a,b wie +;; unten): S>=0 braucht a>=-b/tan3, F_total>=0 braucht a>=b/tan(s-winkel) - +;; das striktere (groessere) der beiden Minima entscheidet. +(defun vfl-gf-auf-ab-solve (ziel-laenge-horiz ziel-hoehe-delta s-winkel / + rad3 tan3 rad-s tan-s m-auf m-ab proj-auf proj-ab + extra-grad extra-auf extra-ab + fix-dx fix-dz a b f-total s gueltig + a-min-s a-min-ftotal a-min ziel-laenge-min) (vfl-gf-bogen-init) (setq rad3 (* (float (fix *vfk-gefaelle-winkel*)) (/ pi 180.0))) (setq tan3 (/ (sin rad3) (cos rad3))) + (setq rad-s (* (float s-winkel) (/ pi 180.0))) + (setq tan-s (/ (sin rad-s) (cos rad-s))) (setq m-auf (get-bogen-mass *gf-bogen-auf* 6)) (setq m-ab (get-bogen-mass *gf-bogen-ab* 6)) - (setq dx-auf (car m-auf) dz-auf (caddr m-auf)) - (setq dx-ab (car m-ab) dz-ab (caddr m-ab)) - ;; Fixterme: zwei Separatoren (300mm, fallend) + die zwei 6-Grad-Boegen, - ;; jeweils per obiger Rotationsformel ins hz-Frame transformiert. + ;; Basis-Uebergaenge (IMMER vorhanden, wie bisher): auf_6 bei Einstieg + ;; fallend(+3), ab_6 bei Einstieg steigend(-3). + (setq proj-auf (vfl-projiziere-neigung (car m-auf) (caddr m-auf) (fix *vfk-gefaelle-winkel*))) + (setq proj-ab (vfl-projiziere-neigung (car m-ab) (caddr m-ab) (- (fix *vfk-gefaelle-winkel*)))) + ;; Zusaetzliche Erweiterung (nur falls s-winkel > *vfk-gefaelle-winkel*): + ;; "auf"-Kette von -3 weiter auf -s-winkel, "ab"-Kette von -s-winkel + ;; zurueck auf -3 (rein rechnerisch - vfl-gf-bogen-summe, echter Bau folgt + ;; per vfl-gf-bogen-erweitern erst NACH dem Solve). + (setq extra-grad (- s-winkel (fix *vfk-gefaelle-winkel*))) + (setq extra-auf (vfl-gf-bogen-summe "auf" (- (fix *vfk-gefaelle-winkel*)) extra-grad)) + (setq extra-ab (vfl-gf-bogen-summe "ab" (- s-winkel) extra-grad)) + ;; Fixterme: zwei Separatoren (300mm, fallend) + alle Bogen-Beitraege. (setq fix-dx (+ (* 2.0 *vfk-separator-laenge* (cos rad3)) - (* (cos rad3) (+ dx-auf dx-ab)) - (* (sin rad3) (- dz-auf dz-ab)))) + (car proj-auf) (car proj-ab) + (car extra-auf) (car extra-ab))) (setq fix-dz (+ (* -2.0 *vfk-separator-laenge* (sin rad3)) - (* (sin rad3) (- dx-ab dx-auf)) - (* (cos rad3) (+ dz-auf dz-ab)))) + (cadr proj-auf) (cadr proj-ab) + (cadr extra-auf) (cadr extra-ab))) (setq a (- ziel-laenge-horiz fix-dx)) (setq b (- ziel-hoehe-delta fix-dz)) - (setq c (/ b tan3)) - (setq s (/ (+ a c) 2.0)) - (setq f-total (/ (- a c) 2.0)) + ;; F_total+S=a, -F_total*tan3+S*tan-s=b => S=(b+a*tan3)/(tan3+tan-s) + (setq s (/ (+ b (* a tan3)) (+ tan3 tan-s))) + (setq f-total (- a s)) (setq gueltig (and (>= f-total -0.01) (>= s -0.01))) - (setq ziel-laenge-min (+ fix-dx (abs c))) + (setq a-min-s (- (/ b tan3))) + (setq a-min-ftotal (/ b tan-s)) + (setq a-min (if (> a-min-ftotal a-min-s) a-min-ftotal a-min-s)) + (setq ziel-laenge-min (+ fix-dx a-min)) (list f-total s gueltig ziel-laenge-min) ) @@ -3553,6 +3623,7 @@ b-noetig tol hz0 hz1 hz2 e1 e1-brutto e2 anteil ziel-laenge loesung f-total s gueltig fa fb hz-jetzt erg-bogen soll-hoehe ist-hoehe antwort + s-winkel extra-grad rad-s versuche rad3 tan3 p0x p0y px py vx vy esx esy dref-x dref-y hz1-rad hz2-rad zaehler nenner abweichung @@ -3779,14 +3850,28 @@ (- (* e2 tan3)) esz)) ;; --- Solver: F_total/S aus vorgegebener Mittelteil-Gesamtlaenge und - ;; der noch fehlenden Hoehenaenderung (Rest bis Gesamtbilanz=0) --- - (setq loesung (vfl-gf-auf-ab-solve ziel-laenge (- h-aussen-rest))) - (setq f-total (nth 0 loesung) s (nth 1 loesung) gueltig (nth 2 loesung)) + ;; der noch fehlenden Hoehenaenderung (Rest bis Gesamtbilanz=0) - S + ;; beginnt beim symmetrischen Grundfall (3 Grad) und wird in 3-Grad- + ;; Schritten steiler (6, 9, 12, ...) probiert, bis F_total/S beide + ;; baubar sind (>=0) - der FLACHSTE passende Winkel wird automatisch + ;; gewaehlt (Nutzer-Vorgabe 2026-09-14: dieselbe dynamische Winkelwahl + ;; wie Option 5, "gegebene Laenge -> passenden Winkel waehlen"). --- + (setq s-winkel (fix *vfk-gefaelle-winkel*)) + (setq versuche 0 gueltig nil) + (while (and (not gueltig) (< versuche 10)) + (setq loesung (vfl-gf-auf-ab-solve ziel-laenge (- h-aussen-rest) s-winkel)) + (setq f-total (nth 0 loesung) s (nth 1 loesung) gueltig (nth 2 loesung)) + (if (not gueltig) (setq s-winkel (+ s-winkel (fix *vfk-gefaelle-winkel*)))) + (setq versuche (1+ versuche)) + ) + (princ (ssg-textf "vfl-qc-s-winkel-echo" (list (itoa s-winkel)))) (if (not gueltig) (progn (princ (ssg-textf "vfl-qc-nicht-baubar" (list (rtos f-total 2 0) (rtos s 2 0) (rtos (nth 3 loesung) 2 0)))) (vfl-loesche-seit checkpoint)) (progn + (setq extra-grad (- s-winkel (fix *vfk-gefaelle-winkel*))) + (setq rad-s (* (float s-winkel) (/ pi 180.0))) (setq fa (* f-total anteil)) (setq fb (- f-total fa)) ;; --- Rest WIRKLICH bauen (physische Reihenfolge; AS/E1/Sep/1. @@ -3798,10 +3883,15 @@ (setq frame (vfl-insert-separator frame)) (setq erg-bogen (vfl-gf-bogen-uebergang frame (- (fix *vfk-gefaelle-winkel*)))) (setq frame (car erg-bogen)) + ;; --- S bei s-winkel Grad (dynamisch gewaehlt): die zusaetzliche + ;; Neigung wird mit ECHTEN Bausteinen erreicht (vfl-gf-bogen- + ;; erweitern, wie bei Option 5). --- + (setq frame (vfl-gf-bogen-erweitern frame "auf" (- (fix *vfk-gefaelle-winkel*)) extra-grad)) (setq hz-jetzt (car (frame->hz-winkel frame))) - (setq frame (vfl-insert-gf-segment (car frame) hz-jetzt s (- (fix *vfk-gefaelle-winkel*)))) - (vfl-acc-gf-seg (/ s (cos rad3)) (- (fix *vfk-gefaelle-winkel*))) + (setq frame (vfl-insert-gf-segment (car frame) hz-jetzt s (- s-winkel))) + (vfl-acc-gf-seg (/ s (cos rad-s)) (- s-winkel)) (setq anzahl-gf (1+ anzahl-gf)) + (setq frame (vfl-gf-bogen-erweitern frame "ab" (- s-winkel) extra-grad)) (setq erg-bogen (vfl-gf-bogen-uebergang frame (fix *vfk-gefaelle-winkel*))) (setq frame (car erg-bogen)) (setq hz-jetzt (car (frame->hz-winkel frame))) diff --git a/lang/de_DE.json b/lang/de_DE.json index 399d01f..068610a 100644 --- a/lang/de_DE.json +++ b/lang/de_DE.json @@ -62,7 +62,8 @@ "vfl-qc-prompt-e2": "\nLaenge fallend-GF Auslauf nach dem zweiten 30-Grad-Bogen (mm) [%1]: ", "vfl-qc-prompt-gesamtlaenge-mittelteil": "\nGesamtlaenge Mittelteil, ohne Ein-/Auslauf (mm): ", "vfl-qc-prompt-anteil": "\nAnteil 1. Fallend-Stueck an F_total (0.0-1.0) [%1]: ", - "vfl-qc-nicht-baubar": "\nFEHLER: Diese Mittelteil-Laenge ist mit dieser Aufteilung nicht baubar (F_total=%1mm, S=%2mm - negativ). Bitte groessere Gesamtlaenge waehlen (mindestens ca. %3 mm).", + "vfl-qc-s-winkel-echo": "\n>>> S-Neigung automatisch gewaehlt: %1 Grad", + "vfl-qc-nicht-baubar": "\nFEHLER: Diese Mittelteil-Laenge ist mit dieser Aufteilung nicht baubar (F_total=%1mm, S=%2mm - negativ, auch mit steilerem S-Winkel bis 30 Grad probiert). Bitte groessere Gesamtlaenge waehlen (mindestens ca. %3 mm).", "vfl-qc-bogen-nicht-schliessbar": "\nFEHLER: Diese AS-/ES-Winkel-Kombination (AS-Schwenk=%1 Grad, ES-Schwenk=%2 Grad, benoetigter Bogen-Schwenk=%3 Grad) ist weder mit einem 30- noch mit einem 90-Grad-Bogen auf die Ausgangsgerade zurueckzufuehren. Bitte AS-/ES-Winkel anpassen (z.B. beide gleich waehlen).", "vfl-qc-e2-negativ": "\nFEHLER: Die berechnete Laenge zwischen dem 2. Bogen und dem ES-Element ist nicht baubar (%1 mm). Bitte E1, Gesamtlaenge Mittelteil oder Anteil anpassen.", "vfl-qc-erfolg": "\n>>> QC-Kette gebaut. Soll-Hoehe (AS-Austritt)=%1 Ist-Hoehe (ES-Austritt)=%2 Abweichung von der Ausgangsgeraden=%3mm", diff --git a/lang/en_GB.json b/lang/en_GB.json index 5c99e72..49fb868 100644 --- a/lang/en_GB.json +++ b/lang/en_GB.json @@ -62,7 +62,8 @@ "vfl-qc-prompt-e2": "\nLength of descending GF exit after the second 30-degree bend (mm) [%1]: ", "vfl-qc-prompt-gesamtlaenge-mittelteil": "\nTotal middle section length, w/o entry/exit (mm): ", "vfl-qc-prompt-anteil": "\nShare of 1st descending piece of F_total (0.0-1.0) [%1]: ", - "vfl-qc-nicht-baubar": "\nERROR: This middle-section length cannot be built with this split (F_total=%1mm, S=%2mm - negative). Please choose a larger total length (at least approx. %3 mm).", + "vfl-qc-s-winkel-echo": "\n>>> S slope auto-selected: %1 degrees", + "vfl-qc-nicht-baubar": "\nERROR: This middle-section length cannot be built with this split (F_total=%1mm, S=%2mm - negative, even with steeper S angles tried up to 30 degrees). Please choose a larger total length (at least approx. %3 mm).", "vfl-qc-bogen-nicht-schliessbar": "\nERROR: This AS/ES angle combination (AS turn=%1 deg, ES turn=%2 deg, required bend turn=%3 deg) cannot be closed back onto the reference line with either a 30- or a 90-degree bend. Please adjust the AS/ES angles (e.g. choose the same for both).", "vfl-qc-e2-negativ": "\nERROR: The computed length between the 2nd bend and the ES element is not buildable (%1 mm). Please adjust E1, the middle section total length, or the share.", "vfl-qc-erfolg": "\n>>> QC chain built. Target height (AS exit)=%1 Actual height (ES exit)=%2 Deviation from reference line=%3mm",