import { describe, expect, it } from 'vitest'; import { REGELBREITE, konfliktbereich, vermesseWege, type Fahrlinie, } from '@/domain/geometrie/vermessung'; /** * Radweg laengs der Fahrbahn. Haltlinie bei x = -10, Verlauf nach Osten. */ const radweg: Fahrlinie = { id: 'rad', punkte: [ { x: -10, y: 0 }, { x: 50, y: 0 }, ], breite: REGELBREITE.rad, }; /** * Rechtsabbiegender Kfz-Strom: quert den Radweg bei x = 9,43 und faehrt danach * ueber 30 m unmittelbar daneben weiter (Achsabstand 0,3 m bei einem * Grenzabstand von (1,6+3,25)/2 = 2,425 m - die Korridore ueberdecken sich). */ const abbieger: Fahrlinie = { id: 'kfz', punkte: [ { x: 0, y: -5 }, { x: 10, y: 0.3 }, { x: 40, y: 0.3 }, ], breite: REGELBREITE.kfz, }; describe('Konfliktbereich bei Kreuzen und anschliessendem Laengslauf', () => { it('fuehrt den Raeumweg des Radverkehrs bis zum Ende der Ueberlagerung, nicht bis kurz hinter den Schnittpunkt', () => { // Sonst erlebt der Anwender: Der abbiegende Kfz-Strom faehrt noch 27 m im // Korridor des Radwegs, der ausgewiesene Raeumweg endet aber bei 22,90 m - // die Zwischenzeit faellt um rund 6,8 s zu kurz aus. const wege = vermesseWege(radweg, abbieger); expect(wege).not.toBeNull(); expect(wege?.raeumweg).toBeCloseTo(50, 2); }); it('fuehrt auch den Raeumweg des abbiegenden Kfz-Stroms bis zum Ende der Ueberlagerung', () => { const wege = vermesseWege(abbieger, radweg); expect(wege).not.toBeNull(); // 11,318 m bis zum Knick + 30 m Laengslauf. expect(wege?.raeumweg).toBeCloseTo(41.32, 2); }); it('vereinigt Punktschnitt und Ueberlagerung zu einem Bereich', () => { const bereich = konfliktbereich(radweg, abbieger); expect(bereich).not.toBeNull(); // Der Punktschnitt bleibt gezaehlt und bestimmt weiterhin den Beginn. expect(bereich?.schnitte).toBe(1); expect(bereich?.vonA).toBeCloseTo(15.964, 2); expect(bereich?.bisA).toBeCloseTo(50, 3); // Der Einfahrweg des Abbiegers verkuerzt sich auf die vordere Kante des // Punktschnitts - die kleinere und damit sichere Angabe. expect(bereich?.vonB).toBeCloseTo(8.969, 2); expect(bereich?.bisB).toBeCloseTo(41.318, 2); // Das Ende entlang A stammt aus dem Laengslauf; dort gibt es keinen // Schnittwinkel. expect(bereich?.ausUeberlappung).toBe(true); expect(bereich?.winkel).toBe(0); }); it('laesst den reinen Punktschnitt unveraendert', () => { // Gegenprobe: Ohne gleichlaufendes Stueck bleibt es beim bisherigen Wert. const ohneLaengslauf: Fahrlinie = { id: 'kfz-quer', punkte: [ { x: 0, y: -5 }, { x: 10, y: 0.3 }, { x: 20, y: 5.6 }, ], breite: REGELBREITE.kfz, }; const wege = vermesseWege(radweg, ohneLaengslauf); expect(wege?.raeumweg).toBeCloseTo(22.9, 2); expect(wege?.konfliktbereich.ausUeberlappung).toBe(false); }); });