lsa-planer

LSA-Planer Professional – Planungssoftware für Lichtsignalanlagen nach RiLSA 2015 und § 45 StVO. EUPL-1.2.

/ tests domain planungsgrundlage.test.ts

5,4 KB Rohdatei
tests/domain/planungsgrundlage.test.ts — 160 Zeilen
1 import { describe, expect, it } from 'vitest';
2 import {
3 LEERER_LAGEPLAN,
4 planungsgrundlage,
5 type Lageplan,
6 type Planlinie,
7 } from '@/domain/geometrie/lageplan';
8 import { REGELBREITE } from '@/domain/geometrie/vermessung';
9
10 /**
11 * Nachweis der Planungsgrundlage.
12 *
13 * Geprueft wird die Frage, die ein Pruefer an die Unterlagen stellt: Worauf
14 * beruhen die Raeum- und Einfahrwege? Die Funktion buendelt die Antwort; sie
15 * rechnet dabei Massstab und Kantenlaenge aus und darf keinen Wert erfinden,
16 * wenn die Grundlage fehlt.
17 */
18
19 const GELADEN_AM = '2026-03-04T09:15:00.000Z';
20
21 /** Fahrlinie mit zwei Punkten - genug, um ableitbar zu sein. */
22 function fahrlinie(id: string): Planlinie {
23 return {
24 id,
25 name: id,
26 mode: 'kfz',
27 movement: 'geradeaus',
28 breiteMeter: REGELBREITE.kfz,
29 punkte: [
30 { x: 10, y: 10 },
31 { x: 10, y: 90 },
32 ],
33 haltlinieId: null,
34 startT: 0.5,
35 signalGroupId: null,
36 };
37 }
38
39 /**
40 * Luftbild 800 mal 600 Bildpunkte, Massstab 0,5 m je Bildpunkt.
41 * Die Bezugsstrecke ist 100 Bildpunkte lang und misst 50 m.
42 */
43 function luftbild(herkunft: 'gemessen' | 'georeferenziert'): Lageplan {
44 return {
45 arbeitsbereiche: [],
46 signalgeber: [],
47 bild: {
48 datenUrl: 'data:image/png;base64,AAAA',
49 breite: 800,
50 hoehe: 600,
51 herkunft: 'Luftbild NRW · Land NRW · Kante 400 m',
52 geladenAm: GELADEN_AM,
53 },
54 kalibrierung: {
55 von: { x: 100, y: 200 },
56 bis: { x: 200, y: 200 },
57 laengeMeter: 50,
58 herkunft,
59 },
60 haltlinien: [],
61 linien: [fahrlinie('l1'), fahrlinie('l2')],
62 };
63 }
64
65 describe('Planungsgrundlage', () => {
66 it('meldet einen leeren Lageplan als Unterlage ohne Bild', () => {
67 const grundlage = planungsgrundlage(LEERER_LAGEPLAN);
68
69 expect(grundlage.hatBild).toBe(false);
70 expect(grundlage.herkunft).toBe('');
71 expect(grundlage.geladenAm).toBe('');
72 expect(grundlage.ladedatumBekannt).toBe(false);
73 expect(grundlage.breiteBildpunkte).toBe(0);
74 expect(grundlage.hoeheBildpunkte).toBe(0);
75 expect(grundlage.auswertbar).toBe(false);
76 });
77
78 it('gibt ohne Kalibrierung keinen Massstab und keine Kantenlaenge an', () => {
79 // Ein eingelesenes Bild ohne festgelegten Massstab. Eine Kantenlaenge waere
80 // hier frei erfunden - der Ausdruck darf sie nicht behaupten.
81 const ohneMassstab: Lageplan = { ...luftbild('gemessen'), kalibrierung: null };
82 const grundlage = planungsgrundlage(ohneMassstab);
83
84 expect(grundlage.hatBild).toBe(true);
85 expect(grundlage.massstabHerkunft).toBeNull();
86 expect(grundlage.meterJeBildpunkt).toBeNull();
87 expect(grundlage.bezugslaengeMeter).toBeNull();
88 expect(grundlage.bezugslaengeBildpunkte).toBeNull();
89 expect(grundlage.kantenlaengeMeter).toBeNull();
90 expect(grundlage.auswertbar).toBe(false);
91 });
92
93 it('rechnet Massstab und Kantenlaenge am Boden aus der Bezugsstrecke', () => {
94 const grundlage = planungsgrundlage(luftbild('gemessen'));
95
96 // 50 m auf 100 Bildpunkten sind 0,5 m je Bildpunkt.
97 expect(grundlage.bezugslaengeMeter).toBe(50);
98 expect(grundlage.bezugslaengeBildpunkte).toBeCloseTo(100, 9);
99 expect(grundlage.meterJeBildpunkt).toBeCloseTo(0.5, 9);
100 // 800 Bildpunkte Bildbreite mal 0,5 m sind 400 m Kantenlaenge.
101 expect(grundlage.kantenlaengeMeter).toBeCloseTo(400, 9);
102 expect(grundlage.massstabHerkunft).toBe('gemessen');
103 });
104
105 it('unterscheidet den georeferenzierten Ausschnitt vom nachgemessenen', () => {
106 expect(planungsgrundlage(luftbild('georeferenziert')).massstabHerkunft).toBe('georeferenziert');
107 expect(planungsgrundlage(luftbild('gemessen')).massstabHerkunft).toBe('gemessen');
108 });
109
110 it('reicht Herkunft, Ladedatum und Bildgroesse unveraendert durch', () => {
111 const grundlage = planungsgrundlage(luftbild('georeferenziert'));
112
113 expect(grundlage.herkunft).toBe('Luftbild NRW · Land NRW · Kante 400 m');
114 expect(grundlage.geladenAm).toBe(GELADEN_AM);
115 expect(grundlage.ladedatumBekannt).toBe(true);
116 expect(grundlage.breiteBildpunkte).toBe(800);
117 expect(grundlage.hoeheBildpunkte).toBe(600);
118 });
119
120 it('erkennt ein fehlendes Ladedatum, statt den 1.1.1970 auszuweisen', () => {
121 const plan = luftbild('gemessen');
122 const ohneDatum: Lageplan = { ...plan, bild: { ...plan.bild!, geladenAm: '' } };
123 const epoche: Lageplan = {
124 ...plan,
125 bild: { ...plan.bild!, geladenAm: '1970-01-01T00:00:00.000Z' },
126 };
127
128 expect(planungsgrundlage(ohneDatum).ladedatumBekannt).toBe(false);
129 expect(planungsgrundlage(epoche).ladedatumBekannt).toBe(false);
130 });
131
132 it('zaehlt Haltlinien und Fahrlinien und meldet die Auswertbarkeit', () => {
133 const plan = luftbild('georeferenziert');
134 const grundlage = planungsgrundlage({
135 ...plan,
136 haltlinien: [
137 {
138 id: 'hl1',
139 name: 'Nord',
140 art: 'zufahrt',
141 armId: null,
142 von: { x: 0, y: 0 },
143 bis: { x: 20, y: 0 },
144 },
145 ],
146 });
147
148 expect(grundlage.anzahlHaltlinien).toBe(1);
149 expect(grundlage.anzahlFahrlinien).toBe(2);
150 expect(grundlage.auswertbar).toBe(true);
151 });
152
153 it('ist ohne gezeichnete Fahrlinien nicht auswertbar, auch mit Massstab', () => {
154 // Massstab allein genuegt nicht: Ohne Fahrlinien ist nichts zu vermessen.
155 const grundlage = planungsgrundlage({ ...luftbild('gemessen'), linien: [] });
156
157 expect(grundlage.meterJeBildpunkt).toBeCloseTo(0.5, 9);
158 expect(grundlage.auswertbar).toBe(false);
159 });
160 });