Files
dxfmakros/doc/todo/modus2-achsenweise-bilanz.md
T
y.wang 35ebee1e88 fix: Laengenbilanz des gefalteten Modus-2-Laufs (U-Form)
Gefaltete VF-Laeufe wurden zu kurz gebaut, weil der Solver Posten dem
falschen Schenkel zurechnete. Vier Aenderungen, alle nach demselben
Leitsatz: die letzten freien Groessen folgen der GEMESSENEN Ist-Lage,
nicht einer vorab verteilten Gesamtplanung.

1. vfl-zsolve-schluss-ziel (neu): endet der Lauf auf einem flachen
   Fueller, werden RICHTUNG und LAENGE gemeinsam gegen den Zielpunkt
   geloest statt nur die Laenge. Geschlossene Loesung ueber
   A = sqrt(|D|^2 - P^2), hz = Winkel(D) - atan2(P, A); C und P sind
   von hz unabhaengig, daher ohne Iteration. Bisher uebernahm der
   Solve die Richtung aus dem gezeichneten Pfad - ein Querversatz der
   realen Eck-Bauteile war damit prinzipiell unerreichbar, weil eine
   Laenge die Kette nur entlang ihrer Achse verschiebt.

2. Eingangs-Hardware bei gefaltetem Lauf: Umlenkstation + Separator
   stehen auf dem Eingangs-Schenkel und verbrauchen die Kletterspanne
   nicht; ihr Laengenanteil wird der Spanne wieder zugeschlagen.
   feste-vf bleibt unveraendert - sein sin3-Hoehenanteil ist real.

3. kletter-ende-fp: endet der Lauf auf einem KLETTERER, gibt es keinen
   Schluss-Fueller, der Motorstation + Separator + ES abzieht - sie
   standen in keinem Budget. Nur bei flacher Zone, Pfadende und
   vorhandenem ES, sonst sind sie bereits anderweitig verbucht.

4. Nachrechner wieder aktiv (8 statt 4 Runden): GF1 steht im Budget,
   aber im Eingangs-Schenkel. Die Kollision mit filler-A-len, wegen
   der er abgeschaltet war, ist entfallen.

3 und 4 wirken NUR gemeinsam - die Betraege heben sich teilweise auf,
eine einzeln eingebaute Korrektur verschiebt den Fehler bloss in die
andere Richtung (GF1 1636.9 - (Motor+Sep+ES) 1235.1 = 401.8 mm).

Gemessen am selben Pfad: 9 Grad 0.56 mm, 12 Grad 0.7 mm quer (vorher
1424 bzw. 934 mm), dZ 0.1 mm. Beide Modus-2-Regressionsketten weiter
OK; TEST_UNIT 904/904 mit 7 neuen file-freien Tests.

doc/todo.md: Punkt "Modus-2-Solver: achsenweise Laengen-Bilanz" ist
damit erledigt. Die Detaildatei bleibt liegen, weil vier Kommentare in
vf_linienzug.lsp auf ihren Pfad verweisen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-29 12:14:13 +01:00

18 KiB

Modus-2-Solver: achsenweise Laengen-Bilanz

Status: ERLEDIGT 2026-10-29. Gefaltete Laeufe (U-Form) werden gebaut; am selben Pfad gemessen 0.56 mm (9 Grad) und 0.7 mm (12 Grad) quer, beide Regressionsketten weiter OK. Der Abschnitt "Stand 2026-10-29" und der "Nachtrag 2026-10-29" am Ende beschreiben Loesung und Herleitung.

Die Datei bleibt BEWUSST liegen, obwohl der Auftrag abgeschlossen ist: vier Kommentare in Lisp/vf_linienzug.lsp verweisen auf diesen Pfad (Suche nach modus2-achsenweise-bilanz). Sie dokumentiert damit nicht mehr einen Plan, sondern WARUM der Solver so bilanziert, wie er es tut - einschliesslich der fehlgeschlagenen Versuche, damit sie niemand ein zweites Mal unternimmt.

Alles unterhalb dieser Zeile ist der urspruengliche Plan von 2026-09-18 und seine Zwischenstaende. Die dort genannten Zeilennummern sind veraltet; Phase B von vf-linienzug-modus2 findet man per Suche nach climber-span. Die damals vorgeschlagene Zwischenloesung (gefaltete Laeufe mit Meldung abweisen) wurde NICHT umgesetzt und ist gegenstandslos - solche Laeufe funktionieren jetzt.

Kurzfassung

Der Modus-2-Solver (vf-linienzug-modus2, Phase B, Lisp/vf_linienzug.lsp ca. Zeile 9915-10145) modelliert den VarioFoerderer-Lauf als EINE gerade Bruecke. Bei einer gefalteten Kette (U-Form: hoch, quer, runter) zieht er die festen Fussabdruecke aus der falschen Achse ab: die erste GF wird zu lang, die Kletterstrecke zu kurz, Motor/ES landen falsch bzw. fehlen. Der Fix: Laengen pro Schenkelrichtung bilanzieren statt als eine skalare Spanne.

Das ist ein dokumentiertes v1-Naeherungs-Limit, kein Regressionsfehler - die Umbauten SEGS/Alert-Box/Mini-Filter haben Phase B nicht angefasst.

Symptom (echter Testfall: results/test_modus2.dxf, logs/vfl_modus2.dbg)

U-Form-Kette, 6 Segmente, EIN VF-Lauf (Seg 2-6; die zwei Vario-Kurven zaehlen als VF-Mitglieder):

   ^  Seg2 VF (1500 mm)
   |  Seg1 GF (2500 mm)
 start                    Seg4 VF (2257 mm)
   |                +-----------------------+
   |           Seg3 Kurve              Seg5 Kurve
   |                                        |
   |                                   Seg6 VF (3800 mm)
   +                                        v
                                        Ziel (3520, 180)

Ergebnis: SOLL-ENDE=(3520, 180, 2000), IST-ENDE=(3333, 2825, 2080) -> dY=+2645 mm, dZ=+80 mm. Die erste GF wird zu lang erzeugt; die Kletterstrecke (Seg 6) endet ~2645 mm zu frueh; Motorstation, das VF-Kurven-Zwischenstueck und das ES-Element sitzen falsch bzw. fehlen.

Ursache, praezise lokalisiert

Der Solver waehlt die laengste VF-Gerade (Seg 6, 3800) als Kletterer, der die ganze Hoehe traegt, und rechnet die geneigte Laenge skalar:

;; vf_linienzug.lsp:9990 - Solver bekommt die SKALARE Spanne
(setq wahl3 (vfl-zsolve-winkel-waehlen climber-span dH-adj feste-vf))
;; feste-vf = Umlenk + Separator (+ Motor) -- ein fester Fussabdruck

;; vf_linienzug.lsp:10070 - Kletterer bekommt br-lvf proportional
(setq this-lvf (max clamp (* br-lvf (/ (caddr seg) climber-span))))
;;   br-lvf = climber-span MINUS feste-vf
;;   ABER: Umlenk/GF1/Motor sitzen physisch in ANDEREN Schenkeln
;;   (GF1+Umlenk am Eingang entlang hz=90, nicht in Seg6/hz=-90)

Der Modellbruch: br-lvf = climber-span minus die festen Fussabdruecke (Umlenk 500 + Separator 300 + GF1 gf-total + Motor). Diese Teile liegen aber in den ANDEREN U-Schenkeln - nicht in Seg 6. Der Solver zieht sie trotzdem von Seg 6s 3800er-Spanne ab. Weil GF1 = "alles am Einlauf" gewaehlt war, ist gf-total gross -> Seg 6 wird um genau diese Summe (~2645 mm) zu kurz. Bei einer GERADEN Bruecke liegen alle Teile auf derselben Achse - dann stimmt die skalare Rechnung. Bei der U-Form nicht.

Zusaetzlich: die flache Zone nimmt GENAU EIN Uebergangspaar an (hor-pairs = 1, Zeile 9950), obwohl die U-Form zwei 90-Grad-Kurven plus Kletterstrecke mischt -> daraus die Rest-dZ von +80 mm.

Beleg: dokumentiertes Limit, kein Regressionsfehler

Kommentar-Fundstelle Aussage
vf_linienzug.lsp:9073-9075 "v1-Naeherung Laenge ... feinere Laengen-Reservierung -> spaeter"
vf_linienzug.lsp:9923-9926 Modell explizit "EIN Vario mit Horizontal-Mitte" - eine gerade Bruecke ist die Design-Annahme
vf_linienzug.lsp:9948-9950 "flache Zone hat GENAU EIN Uebergangspaar ... unabhaengig von der Zahl der Fueller/Kurven"

Verifiziert: SEGS-Umbau, Alert-Box und Mini-Filter haben Phase B (den Solver) nachweislich nicht veraendert. Die Abweichung ist vorbestehend.

Vorgeschlagener Umbau in sicheren Etappen

Nach jeder Etappe eine BricsCAD-Sichtpruefung (Geometrie ist nur interaktiv pruefbar).

  1. Regressionsnetz zuerst. Eine bekannt-gute GERADE Modus-2-Kette (GF...VF...GF, eine Achse) bauen und mit lib/dxf_vf_abbild.py --schreibe-referenz als Referenz einfrieren. Schuetzt den funktionierenden Normalfall, bevor die Bilanz umgebaut wird.
  2. Schenkel erkennen. Den VF-Lauf (Seg vf-start..vf-ende) an den Vario-Kurven in Schenkel aufteilen - jeder Schenkel eine Fahrtrichtung (hz). Pro Schenkel: Summe der VF-Geraden-Laengen, welche festen Teile darin liegen. Neue Datenstruktur statt der skalaren climber-span. (ersetzt die climber/nonclimber-Schleife 9935-9947)
  3. Fussabdruecke dem richtigen Schenkel zuordnen (Risiko-Kern). Umlenk/GF1 nur vom Eingangs-Schenkel abziehen, Motor/GF2/ES nur vom Ausgangs-Schenkel - nicht pauschal von der Kletterstrecke. Reicht ein Schenkel nicht, verteilt sich die Restneigung auf weitere Schenkel. (feste-vf/dH-adj 9978-9989, this-lvf 10070, fill-len 10094-10104)
  4. Uebergangspaare pro Kurve statt pauschal eins. hor-pairs aus der tatsaechlichen Schenkel-/Kurvenzahl ableiten - behebt die dZ-Restabweichung. (9950, dH-adj-Bildung 9982-9989)
  5. Verifikation. Regressionsnetz aus Schritt 1 muss gruen bleiben (gerader Fall unveraendert). U-Form interaktiv: erste GF korrekt kurz, Kletterstrecke trifft den Zielpunkt, Motor + Kurven-Zwischenstueck + ES an der richtigen Stelle. SEGS-Journal bleibt formgleich.

Risiko-Einschaetzung

  • Der GERADE Fall funktioniert heute - er ist der Normalfall, fuer den der Solver gebaut ist. Ein Umbau der Kern-Bilanz kann ihn brechen -> Schritt 1 (Referenznetz) ist nicht optional.
  • Geometrie nur interaktiv in BricsCAD pruefbar -> mehrere Runden noetig.
  • Gut eingegrenzt: der Umbau bleibt in Phase B von vf-linienzug-modus2 (~9915-10145). Klassifizierung, SEGS-Journal, Doppelklick-Replay und die anderen Modi bleiben unberuehrt.

Zwischenloesung (falls der Umbau nicht sofort kommt)

Gefaltete VF-Laeufe (mehr als eine Achsenrichtung im VF-Bereich, z.B. U-Form) erkennen und mit klarer Meldung abweisen, statt still falsche Geometrie zu bauen - analog zur bereits vorhandenen "nur EIN VF-Lauf"-Abweisung (vfl-m3-vf-lauf-alert). Macht das Limit ehrlich sichtbar, kleiner Eingriff.


Stand 2026-10-27 (nach Commit ce4ad0f)

Teilweise entschaerft, Kern bleibt offen.

Die Budget-Arbeit vom 26./27.10. hat genau das Prinzip eingefuehrt, das dieses Dokument fordert - aber nur fuer DREI Posten. Sie werden jetzt dem Segment zugeschlagen, auf dem sie physisch stehen, statt skalar von der Gesamtspanne abgezogen zu werden:

Posten wie Stelle
AS-Element gemessener Fussabdruck, nur vf-start as-along-fix
Abschlussbogen + Motorstation nur vf-ende abschluss-fp
Eck-Differenz (gezeichneter Bogen gegen Bauteil) Alist je Segmentindex vfl-eck-korrekturen / vfl-eck-extra

vfl-eck-extra ist dabei bereits die hier geforderte Form: ein Zuschlag je Segment, nicht ein Skalar fuer den ganzen Lauf. Er fliesst in alle vier Budgets (Spannweite, Kletterer, Fueller, Rueckanker).

Skalar geblieben sind genau die zwei Posten, die den U-Form-Fehler verursachen:

  • feste-vf (Umlenkstation 500 + Separator 300, ggf. + Motor) - wird in vfl-zsolve-winkel-waehlen als EIN Wert uebergeben
  • gf-total (GF1) - bei "alles am Einlauf" gross, und genau diese Summe fehlt dem Kletterer im anderen Schenkel

Das oben beschriebene Symptom (dY = +2645 mm) bleibt daher bestehen. Der naechste Schritt waere, diese beiden ebenfalls dem Segment zuzuordnen, auf dem sie stehen - also dieselbe Umstellung wie bei AS und Motorstation, nur fuer den Lauf-EINGANG.

Hinweis zur Fehlersuche: Seit ce4ad0f meldet die Konsole jeden Zuschlag namentlich (AS-Fussabdruck ... von Segment N abgezogen, Abschluss-Fussabdruck ..., Eck-Korrektur ... auf Segment N). Eine FEHLENDE Zeile ist das Warnsignal - so wurde ein 2,4-mm-Rest gefunden. Fuer die U-Form-Diagnose sind diese Zeilen der schnellste Einstieg.


Stand 2026-10-28: Fueller-Seite geloest, Solver-Seite offen

Geloest und gemessen

vfl-m2-eingang-fp: GF1 + Separator + Umlenkstation + Uebergangsbogen stehen auf dem Segment vf-start. Ist dieses Segment ein FUELLER (der Kletterer liegt hinter einer Kurve), bekam der Fueller bisher die volle Restlaenge, als staende dort nichts. Jetzt werden sie abgezogen.

Ist das Eingangs-Segment selbst der Kletterer - der gerade Normalfall -, gibt die Funktion hart 0.0 zurueck; der funktionierende Fall kann sich also nicht aendern. Gemessen am U-Form-Testfall: Querabweichung 8005 -> 1424 mm, Segment 1 danach auf 0,2 mm genau belegt.

Noch offen: der Solver rechnet GF und Stationen gegen die falsche Achse

Rest 1424 mm. Segment 5 (Kletterer) legt 6475,5 mm zurueck, verfuegbar waeren 7899,8 - der Solver reserviert dort Platz fuer Umlenkstation, Separator und den GF1-Anteil, die auf Segment 1 stehen.

Fehlgeschlagene Versuche (nicht wiederholen)

Drei Anlaeufe am 2026-10-27/28, jeder an einer anderen Kopplung gescheitert:

  1. feste-vf kleiner uebergeben. Geht nicht: feste-hz fliesst in vf-winkel-AB (vf_standard.lsp:241/245) sowohl als feste*cos3 in die LAENGE als auch als feste*sin3 in die HOEHE. Die Hoehe ist real - die Teile senken die Kette ab, egal auf welchem Schenkel sie stehen. Nur der Laengenanteil darf verschoben werden.
  2. Spanne vorab korrigieren und iterieren. Geht nicht direkt: vfl-zsolve-winkel-waehlen enthaelt die WINKELFRAGE an den Nutzer - eine Iteration wuerde mehrfach fragen. Und die Korrektur ist pro Winkel verschieden, weil jeder Winkel ein anderes L_GF ergibt.
  3. Stiller Nachrechner nach der GF-Verteilungsfrage (Code vorhanden, per (setq nachrechnen-k 4) deaktiviert). Technisch sauber: kein Dialog, Fragenfolge und Journal unveraendert, Konvergenz in 4 Runden (3278 -> 4372 -> 4737 -> 4859 -> 4899 mm). ABER er kollidiert mit filler-A-len: dieser Fueller belegt im Kletter-Segment genau den Platz, den das halbe GF1 dort frei laesst. Nimmt man GF1 aus der Kletterer-Spanne heraus, wird Fueller-A trotzdem gebaut - zusaetzlich zum echten GF1 auf demselben Segment. Gemessen: Fueller nach der Umlenkstation -369 mm (auf 100 geklemmt), Kette 746 mm daneben. Kleinerer Endfehler, aber entartete Geometrie - deshalb zurueckgenommen.

Daraus fuer den naechsten Anlauf

Der Nachrechner ist vermutlich der richtige Weg, aber filler-A-len muss mitbehandelt werden: er gehoert zur Annahme "GF1 liegt im Kletter-Segment" und darf bei gefaltetem Lauf nicht mehr entstehen. Wer das angeht, sollte beide Mechanismen zusammen betrachten, nicht nacheinander.

Testfall vorhanden: U-Form 5855 / 270 / 7806 mm (Kletterer hinter zwei 90-Grad-Kurven), Soll-Querabweichung ~0, Stand heute 1424 mm. Die beiden geraden Referenzketten in c:TEST_LINIENZUG_MODUS2 schuetzen den Normalfall.


Stand 2026-10-29: Eingangs-Segment exakt, Kletterer-Segment offen

Zusaetzlich geloest (gegenueber dem Stand vom 2026-10-28)

Fueller-A entfaellt bei gefaltetem Lauf, und vfl-m2-eingang-fp zieht seitdem br-gf1 ab statt gf-total. Beides gehoert zusammen:

filler-A-len fuellt den Platz, den ein halbiertes GF1 auf DERSELBEN Achse frei laesst - er gehoert zur Annahme "GF1 und GF2 liegen auf einer Geraden". Bei gefaltetem Lauf wurde er auf dem Eingangs-Segment ZUSAETZLICH zu GF1 gebaut; zusammen mit GF2 im Kletterer-Schenkel entstanden damit 1.5 x gf-total Gefaellestrecke bei einem Budget von gf-total.

Ergebnis, am U-Form-Testfall nachgerechnet (9 Grad, Verteilung 1/2+1/2):

Segment 1: AS 425,8 + GF1 1370,3 + Sep 299,6 + Umlenk 499,3
           + Bogen 199,9 + Fueller 3153,7           = 5948,6 mm
Budget:    5855 + 93,8 (Eck-Korrektur)              = 5948,8 mm

Das Eingangs-Segment ist damit auf 0,2 mm exakt belegt, und im Protokoll steht nur noch EIN Fueller statt zwei.

Was offen bleibt

Das KLETTERER-Segment. Gemessen im selben Lauf: Segment 5 belegt 6965,8 mm, verfuegbar waeren 7899,8 - es fehlen 934 mm, exakt die Endabweichung.

Der Solver bekommt als Spanne 7704,16 mm und verplant darin u.a. GF1 (1370,3) sowie Umlenkstation + Separator (798,9) - Teile, die auf Segment 1 stehen. Umgekehrt enthaelt seine Spanne NICHT den Abschluss-Fussabdruck (ab_3 + Motorstation, 695 mm), weil dieser nur von FUELLER-Segmenten abgezogen wird (fill-len) und das Kletterer-Segment keines ist.

Der Restfehler skaliert mit L_GF und damit mit dem gewaehlten Winkel - unabhaengig bestaetigt durch zwei Laeufe auf demselben Pfad:

Winkel L_GF Querabweichung
6 Grad 1093 90 mm
9 Grad 2744 934 mm

Praktische Folge: Mit flachem Winkel ist der gefaltete Lauf heute brauchbar, mit steilem nicht.

Hinweis zur Methodik fuer den naechsten Anlauf

Zwei Laeufe sind nur vergleichbar, wenn Winkel UND GF-Verteilung gleich sind. Mehrere Messreihen dieser Sitzung waren nicht deutbar, weil sich zwischendurch der Winkel geaendert hatte und der Restfehler mit L_GF skaliert. Vor einer Aenderung also eine feste Kombination festlegen (Vorschlag: 12 Grad, Verteilung 1/2+1/2) und nur die vergleichen.


Nachtrag 2026-10-29: Loesungsansatz vom Nutzer

Der Abschnitt darueber beschreibt den Stand VOR dem folgenden Umbau; er bleibt als Herleitung stehen.

Nutzer-Vorgabe: "nach der zweiten VF-Kurve den passenden Winkel neu aus dem KS_AUS der Kurve und dem Zielpunkt rechnen" und "da GF2 feststeht, steht auch die fuer Auf/Ab verbleibende Laenge fest - passender Winkel plus eine ausgleichende GF".

Das ist die Umkehrung der bisherigen Logik und trifft den Kern: bisher wurde ALLES vorab global verplant und der aufgelaufene Fehler landete am Kettenende. Richtig ist, die letzten freien Groessen aus der GEMESSENEN Ist-Lage zu bestimmen. Je nachdem, was das letzte Segment ist, sind das verschiedene Groessen:

Letztes Segment feste Groesse freie Groessen
flacher Fueller - Richtung + Fuellerlaenge
Auf/Ab-Koerper (U-Form) Laenge (aus dem Pfad) Winkel (diskret) + GF-Ausgleich

Umgesetzt

1. Flacher Fueller als Schlussstueck - neue Funktion vfl-zsolve-schluss-ziel. Bisher loeste vfl-zsolve-es-fueller nur die LAENGE und uebernahm die Richtung aus dem gezeichneten Pfad. Eine Laenge verschiebt die Kette aber nur ENTLANG ihrer Achse - steht der reale Kurvenausgang seitlich NEBEN der gezeichneten Geraden, laeuft die gebaute Achse parallel zur Zielachse und der Querversatz ist unerreichbar. Gibt man die Richtung mit frei, stehen zwei Unbekannte zwei Gleichungen (X und Y) gegenueber, geschlossen loesbar:

D    = Ziel - KS_AUS(letzte Kurve)
A    = sqrt(|D|^2 - P^2)      ; P = Querversatz des ES-Fussabdrucks
fill = A - C
hz   = Winkel(D) - atan2(P, A)

C und P sind von hz unabhaengig, weil vfl-zsolve-es-vektor Vektor und Bezugsrahmen um denselben Winkel dreht - deshalb ist keine Iteration noetig. Scheitert der Solve (Ziel naeher als P), bleibt der bisherige Weg. Unit-Tests: tu-tests-vfl-schluss (file-frei ueber es-block = nil).

2. Eingangs-Hardware bei gefaltetem Lauf - der am 2026-10-28 zurueck- genommene Spannen-Zuschlag ist wieder da. Begruendung fuer die Ruecknahme war die Kollision mit filler-A-len; dieser Blocker ist entfallen, seit Fueller-A bei gefaltetem Lauf gar nicht mehr entsteht. Zugeschlagen wird weiterhin NUR der Laengenanteil (entry-fixed * cos3), nie feste-vf selbst - dessen sin3-Hoehenanteil ist real.

3. Abschluss-Hardware auf dem Kletterer (kletter-ende-fp) - endet der Lauf auf einem FUELLER, zieht vfl-zsolve-es-fueller Motorstation + Separator + ES beim Loesen der Fuellerlaenge selbst ab. Endet er auf einem KLETTERER, gibt es diesen Fueller nicht: die drei Teile werden dort gebaut, standen aber in keinem Budget. Abgezogen wird dasselbe wie in dessen Konstante cc, OHNE den ab_3-Bogen (der steckt in diesem Fall schon in uebergang-fp).

4. GF1-Fremdanteil (Nachrechner wieder aktiv, 8 statt 4 Runden) - gf-total ist ein ERGEBNIS des Winkel-Solves, sein auf dem Eingangs-Schenkel stehender Teil laesst sich dort noch nicht abziehen (Henne-Ei). Der Nachrechner loest bei UNVERAENDERTEM Winkel neu und konvergiert mit Faktor ~1/3.

Der entscheidende Punkt: 3 und 4 wirken nur GEMEINSAM

Posten im Budget des Solvers steht real auf dem Kletterer
GF1 ja nein - liegt im Eingangs-Schenkel
Motor + Separator + ES nein ja

Die beiden Betraege heben sich TEILWEISE auf. Wer nur einen davon korrigiert, verschiebt den Fehler bloss in die andere Richtung - genau das war der 746-mm-Befund vom 2026-10-28, der damals wie eine Verschlechterung aussah. Gemessen am 9-Grad-Lauf: GF1 1636.9 - (Motor+Sep+ES) 1235.1 = 401.8 mm, exakt die damalige Restabweichung von 401.7 mm.

Messergebnis

Lauf vorher nachher
U-Form 9 Grad 1424 -> 934 mm 0.56 mm
U-Form 12 Grad - 0.7 mm
Variante A (Vario-Kurve) OK OK
Variante B (GF-Bogen) OK OK

Zwei verschiedene Winkel auf demselben Pfad - der Restfehler skaliert also nicht mehr mit L_GF, die Bilanz selbst stimmt.

Regression auf dem Weg dorthin (Lehrstueck)

kletter-ende-fp schlug zunaechst auch in Variante B zu und verkuerzte deren Segment 1 um 798.9 mm. Dort ist vf-start = vf-ende = 0: der VF-Lauf besteht aus EINEM Segment, die Segmente 2..5 sind Back-Lauf. Damit ist der Kletterer zugleich Laufende, der Abzug griff - obwohl ohne flache Zone die Motorstation bereits in feste-vf steckt und Separator + ES vom Back-Lauf reserviert werden. Die drei Bedingungen am if (hor-pairs > 0, vf-ende = n-1, es-vorhanden) sind deshalb keine Vorsichtsmassnahme, sondern benennen genau die Faelle, in denen sonst doppelt gebucht wird.

Auffindbar war die Ursache nur, weil Segment 1 von Variante B bei hz=0 liegt: eine Verkuerzung dieses Segments uebersetzt sich 1:1 in dX, und IST - SOLL = (-799.11 | -104.68) aus logs/vfl_modus2.dbg zeigte die reine X-Verschiebung.