-
Notifications
You must be signed in to change notification settings - Fork 4
/
EEP_Gleisplan.html
7490 lines (6542 loc) · 278 KB
/
EEP_Gleisplan.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="de">
<!-- https://www.w3.org/International/questions/qa-html-language-declarations -->
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<META http-equiv="Content-Script-Type" content="text/javascript">
<title>Interaktive Anzeige des Gleisplans zu einer EEP-Anlage-Datei (.anl3)</title>
<meta name="description" content="Dieses Programm nutzt die Javascript-Funktion DOMParser um eine .anl3-Datei von EEP, die aus XML aufgebaut ist, zu interpretieren und in das Document Object Model (DOM) umzuwandeln. Anschließend wird dynamisch mit Javascript die Graphik des Gleisplanes mit SVG-Befehlen aufgebaut. Die Formatierung der graphischen Elemente erfolgt getrennt von der Definition der Graphik mit der SVG-Variante von CSS. Der Browser kann solche SVG-Graphiken direkt anzeigen. Zusätzlich werden die Bibliotheken svg-pan-zoom zum Verschieben und Zoomen und toolwindow zur Anzeige von Popups verwendet.">
<meta name="author" content="Frank Buchholz">
<meta name="keywords" content="EEP,.anl3,Gleisplan" />
<meta name="language" content="de" />
<!-- <link rel="icon" href="https://www.eepforum.de/images/favicon.ico" type="image/x-icon"> -->
<link rel="icon" href="images/favicon.ico" type="image/x-icon">
<script type="text/javascript" src="js/EEP_Texts.js"></script> <!-- Load texts and translations -->
<link rel="stylesheet" href="css/EEP_Texts.css">
<script type="text/javascript"> // Experiment to load scripts dynamically either from relative path or from fixed URL - not used yet
"use strict";
/* Interface
required standard objects:
document
public api:
loadScript
*/
(function(api) {
// public api
api.loadScript = loadScript;
/* Source: https://humanwhocodes.com/blog/2009/07/28/the-best-way-to-load-external-javascript/
Usage:
<s.cript type="text/javascript">
loadScript("http://your.cdn.com/script.js", function(){
//initialization code
});
</s.cript>
*/
function loadScript(url, callback){
const script = document.createElement("script");
script.type = "text/javascript";
script.onload = function(){ // IE would require different calls
callback();
};
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
}
})(this); // end module
</script>
<style> /* html page */
/* <![CDATA[ */
html, body { /* deactivate default settings */
margin: 0;
padding: 0;
}
body {
--header-background-color: STEELBLUE; /* ThreeDHighlight; */
--header-text-color: WHITE; /* CaptionText; */
--body-background-color: WhiteSmoke; /* AZURE; Window; */
--body-text-color: BLACK; /* WindowText; */
--footer-background-color: CADETBLUE; /* ButtonFace; */
--footer-text-color: WHITE; /* ButtonText; */
}
.hidden {
display: none;
}
/* no select/copy to clipboard. Firefox prevents selection even in case of Ctrl-A, but with Chrome it's not reliably. */
.no-select,
fieldset,
select,
input,
button {
user-select: none;
-webkit-user-select: none; /* WebKit-specific values */
}
/* ]]> */
</style>
</head>
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<body>
<section id="fileselector"> <!-- Selection screen -->
<header class="flexRow"> <!-- Show heading and language selection buttons, see EEP_Texts.css -->
<div> <!-- left part -->
<h3><span lang="de">EEP-Gleisplan</span><span lang="en">EEP Track plan</span><span lang="fr">EEP Plan des voies</span></h3>
</div>
<div> <!-- right part -->
<label for="german" class="langBtn">Deutsch</label>
<label for="english" class="langBtn">English</label>
<label for="french" class="langBtn">Français</label>
</div>
</header>
<article>
<form action="#" onsubmit="return false;"> <!-- better not to use inline listener, explicit register is better -->
<label for="fileinput">
<span lang="de">Wähle (auch mit Drag&Drop möglich) und lade eine EEP-Anlage-Datei (.anl3).</span>
<span lang="en">Select (or use Drag&Drop) and load an EEP file (.anl3).</span>
<span lang="fr">Sélectionnez un réseau EEP (nom_du_réseau.anl3) ou utilisez la fonction glisser-déposer.</span>
</label>
<input type="file" id="fileinput" accept=".anl3" onchange="loadFile(this.files && this.files[0])" />
<!-- An extra button is not necessary -->
<!-- <input type="button" id="btnLoad" value="Load" onclick="loadFile();"> -->
</form>
<p lang="de"> <!-- Mausfunktionen -->
<small><strong>Mausfunktionen</strong><br>
Verschieben: Klick+Halten+Bewegen<br>
An der Stelle des Cursors hineinzoomen: Doppelklick<br>
Herauszoomen: <kbd>⇧ Shift</kbd>+Doppelklick<br>
Details anzeigen: Klick auf Gleis, Symbol oder Text<br>
<span class="li">wenn zusammen mit <kbd>⇧ Shift</kbd>, dann wird jeweils ein neues Popup geöffnet</span>
<span class="li">wenn zusammen mit <kbd>alt</kbd>, dann wird zusätzlich der Code aus der Anlage-Datei für dieses Objekt angezeigt</span>
</small></p>
<p lang="en">
<small><strong>Mouse functions</strong><br>
Move: Click+Hold+Move<br>
Zoom in at position of the cursor: Double click<br>
Zoom out: <kbd>⇧ Shift</kbd>+Double click<br>
Show details: Click on track, symbol or text<br>
<span class="li">if together with <kbd>⇧ Shift</kbd>, then you get another new popup window</span>
<span class="li">if together with <kbd>alt</kbd>, then you will get the code from the file for this object, too</span>
</small></p>
<p lang="fr">
<small><strong>Fonctions de la souris</strong><br>
Déplacer: Clic+Tenir+Mouvoir<br>
Zoomer à l‘endroit précis du curseur: double-clic<br>
Dézoomer: <kbd>⇧ Shift</kbd>+double-clic<br>
Afficher les détails: Cliquer sur voie, symbole ou texte<br>
<span class="li">en appuyant simultanément également sur <kbd>⇧ Shift</kbd>, un nouveau pop-up s‘ouvrira</span>
<span class="li">en appuyant simultanément également sur <kbd>alt</kbd>, tout le code du fichier *.anl3 correspondant à cet objet s‘affichera</span>
</small></p>
<p lang="de"> <!-- Tastaturfunktionen -->
<small><strong>Tastaturfunktionen</strong><br>
<kbd>←</kbd> <kbd>↑</kbd> <kbd>→</kbd> <kbd>↓</kbd> : Verschieben der Graphik (wenn zusammen mit <kbd>⇧ Shift</kbd>, dann jeweils um eine halbe Seite)<br>
<kbd>+</kbd> <kbd>-</kbd> : Zoomen</small></p>
<p lang="en">
<small><strong>Key functions</strong><br>
<kbd>←</kbd> <kbd>↑</kbd> <kbd>→</kbd> <kbd>↓</kbd> : Move graphic (if together with <kbd>⇧ Shift</kbd>, then you move it by half of a page)<br>
<kbd>+</kbd> <kbd>-</kbd> : Zoom</small></p>
<p lang="fr">
<small><strong>Fonctions du clavier</strong><br>
<kbd>←</kbd> <kbd>↑</kbd> <kbd>→</kbd> <kbd>↓</kbd> : Déplacer le graphique (ensemble avec la touche <kbd>⇧ Shift</kbd>, alors d‘une demi-page à la fois)<br>
<kbd>+</kbd> <kbd>-</kbd> : Zoomer</small></p>
<p lang="de"> <!-- Interaktive Funktionen -->
<small><strong>Interaktive Funktionen</strong><br>
Wechsel zwischen vertikaler und horizontaler Ausrichtung (Fullscreen mit <kbd>F11</kbd>)<br>
Zoom-in, -out, -reset<br>
Auswahl der anzuzeigenden Gleissysteme<br>
Auswahl der anzuzeigenden Informationen (GleisID, Kurventyp, Gleisstil, Höhe, Weichen, Signale, Kontakte, Marker, Gleisobjekte, Kamera, Rahmen)<br>
Auswahl der anzuzeigenden Gleise (aktive/inaktive Gleise mit/ohne Rollmaterialien, sichtbare/unsichtbare Gleise, virtuelle Verbindungen)<br>
Anzeige der Fahrstraßen (alle bzw. von bestimmten Start-Signalen oder zu bestimmten Ende-Signalen)<br>
Aktuelle Darstellung als Bild (png/jpg/svg) speichern<br>
Gleisplan auf bestimmtes Gleis, bzw. das Gleis eines Signals oder Weiche positionieren<br>
Die Positionierung ist auch über das <a href="EEP_Inventar.html" target="_blank">Inventar</a>-Programm möglich!<br>
Einstellung der Linienbreite und der Schriftgröße<br>
Auswahl der Gleise mit minimalem und maximalen Höhenfilter<br>
Farben der Gleissysteme anpassen
</small></p>
<p lang="en">
<small><strong>Interactive functions</strong><br>
Switch between vertical and horizontal alignment (Full screen using <kbd>F11</kbd>)<br>
Zoom-in, -out, -reset<br>
Choose displayed track systems<br>
Choose displayed information (TrackID, curve type, track style, height, switches, signals, contacts, marker, track objects, cameras, border)<br>
Choose displayed tracks (active/inactive tracks with/without rolling stocks, visible/invisible tracks, virtual connections)<br>
Display of predefined lines (all or from certain start signals or to certain end signals)<br>
Store current view as picture (png/jpg/svg)<br>
Position track plan at specific track, respective track of a signal or switch<br>
You can use the <a href="EEP_Inventar.html" target="_blank">inventory</a> program as well to position the view!<br>
Define line thickness and font size<br>
Filter tracks by min./max. height<br>
Define colors of the track systems
</small></p>
<p lang="fr">
<small><strong>Fonctions interactives</strong><br>
Alterner la position de la barre entre horizontale et verticale (<kbd>F11</kbd> pour plein écran)<br>
Zoom-in, -out, -reset<br>
Sélection des systèmes de voies<br>
Sélection des informations à visualiser (ID voie, variante de voie, style de voie, hauteur, aiguillages, signaux, contacts,marqueurs,objets de voie, caméras, cadre)<br>
Sélection des voies à visualiser (voies actives/inactives. avec/sansmatériels roulants, connexion virtuelle)<br>
Affichage des parcours prédéfini (tous ou à partir de certains signaux de démarrage ou vers certains signaux de fin)<br>
Mémoriser l‘image actuelle au format (png/jpg/svg)<br>
Concentrer la vue sur une voie déterminée, resp. sur la voie d‘un signal ou d‘un aiguillage<br>
Le postionnement est également possible par le programme <a href="EEP_Inventar.html" target="_blank">Inventaire</a>!<br>
Réglage de la largeur des lignes et des textes<br>
Sélection des voies à l‘aide du filtre de hauteur minimale et maximale<br>
Adapter les couleurs des systèmes de voie
</small></p>
<p lang="de"> <!-- Referenzen / verwandte Programme -->
<small><strong>Referenzen / verwandte Programme</strong><br>
Diskussionsbeitrag im <a href="https://www.eepforum.de/forum/thread/26770-eep-gleisplan-im-browser-anzeigen-javascript-projekt" target="_blank">EEP-Forum</a><br>
Entwicklungsprojekt auf <a href="https://github.com/FrankBuchholz/EEP_convert_anl3_file" target="_blank">GitHub</a><br>
Anzeige einer <a href="https://frankbuchholz.github.io/EEP_convert_anl3_file/EEP_Inventar.html" target="_blank">Inventarliste</a> zu einer EEP-Anlage<br>
Übersicht zu den <a href="https://frankbuchholz.github.io/EEP_convert_anl3_file/EEP_Signale.html" target="_blank">Signalstellungen</a> anhand der extrahierten .ini-Dateien zu Signalen (siehe EEP → Extras → Ressourcen-Extraktor)</small></p>
<p lang="en">
<small><strong>References / related programs</strong><br>
Thread in the <a href="https://www.eepforum.de/forum/thread/26770-eep-gleisplan-im-browser-anzeigen-javascript-projekt" target="_blank">EEP Forum</a><br>
Development project at <a href="https://github.com/FrankBuchholz/EEP_convert_anl3_file" target="_blank">GitHub</a><br>
Show <a href="https://frankbuchholz.github.io/EEP_convert_anl3_file/EEP_Inventar.html" target="_blank">inventory list</a> of an EEP file<br>
Overview about <a href="https://frankbuchholz.github.io/EEP_convert_anl3_file/EEP_Signale.html" target="_blank">signal positions</a> according to the extracted data from the .ini files of signals (see EEP → Extras → Ressourcen-Extraktor)</small></p>
<p lang="fr">
<small><strong>Références / Programmes associés</strong><br>
Discussions dans le <a href="https://www.eepforum.de/forum/thread/26770-eep-gleisplan-im-browser-anzeigen-javascript-projekt" target="_blank">EEP-Forum</a><br>
Projet de développement sur <a href="https://github.com/FrankBuchholz/EEP_convert_anl3_file" target="_blank">GitHub</a><br>
Afficher une <a href="https://frankbuchholz.github.io/EEP_convert_anl3_file/EEP_Inventar.html" target="_blank">liste de l‘inventaire</a> d‘un réseau EEP<br>
Aperçu des <a href="https://frankbuchholz.github.io/EEP_convert_anl3_file/EEP_Signale.html" target="_blank">positions de signaux</a> à l‘aide des données extraites des fichiers *.ini des signaux (voir EEP → Extras → Ressourcen-Extraktor)</small></p>
<p lang="de"> <!-- Technische Beschreibung -->
<small><strong>Technische Beschreibung</strong><br>
Dieses Programm nutzt die Javascript-Funktion <a href="https://www.w3schools.com/xml/xml_parser.asp" target="_blank">DOMParser</a> um eine <i>.anl3</i>-Datei von EEP, die aus <a href="https://www.w3schools.com/xml/xml_tree.asp" target="_blank">XML</a> aufgebaut ist, zu interpretieren und in das <a href="https://www.w3schools.com/xml/xml_dom.asp" target="_blank">Document Object Model (DOM)</a> umzuwandeln.<br>
Anschließend wird dynamisch mit Javascript die Graphik des Gleisplanes mit <a href="https://www.w3schools.com/html/html5_svg.asp" target="_blank">SVG</a>-Befehlen aufgebaut. Die Formatierung der graphischen Elemente erfolgt getrennt von der Definition der Graphik mit der SVG-Variante von <a href="https://www.w3schools.com/html/html_css.asp" target="_blank">CSS</a>.<br>
Der Browser kann solche SVG-Graphiken direkt anzeigen. Zusätzlich werden die Bibliotheken <a href="https://github.com/bumbu/svg-pan-zoom" target="_blank">svg-pan-zoom</a> zum Verschieben und Zoomen und <a href="https://github.com/fluffynuts/toolwindow" target="_blank">toolwindow</a> zur Anzeige von Popups verwendet.<br>
Das Programm läuft in aktuellen Versionen von Google Chrome, Firefox oder MS Edge, nicht jedoch im Internet Explorer.</small></p>
<p lang="en">
<small><strong>Technical description</strong><br>
This program uses the Javascript function <a href="https://www.w3schools.com/xml/xml_parser.asp" target="_blank">DOMParser</a> to analyse an <i>.anl3</i> file of EEP, which contains <a href="https://www.w3schools.com/xml/xml_tree.asp" target="_blank">XML</a> structured data, and to transform it into the <a href="https://www.w3schools.com/xml/xml_dom.asp" target="_blank">Document Object Model (DOM)</a>.<br>
Then it dynamically creates the graphic of the track plan using Javascript using <a href="https://www.w3schools.com/html/html5_svg.asp" target="_blank">SVG</a> commands. The formatting of the graphical elements using the SVG variant of <a href="https://www.w3schools.com/html/html_css.asp" target="_blank">CSS</a> is separated from the definition of the graphic.<br>
The Browser shows such SVG graphics directly. The programs uses the libraries <a href="https://github.com/bumbu/svg-pan-zoom" target="_blank">svg-pan-zoom</a> for pan and zoom and <a href="https://github.com/fluffynuts/toolwindow" target="_blank">toolwindow</a> to show popup windows.<br>
The program runs with current versions of Google Chrome, Firefox or MS Edge, but not with Internet Explorer.</small></p>
<p lang="fr">
<small><strong>Description technique</strong><br>
Ce programme utilise la fonction javascript <a href="https://www.w3schools.com/xml/xml_parser.asp" target="_blank">DOMParser</a> pour interpréter un fichier <i>.anl3</i> de EEP conçu en <a href="https://www.w3schools.com/xml/xml_tree.asp" target="_blank">XML</a>, pour le transformer au format <a href="https://www.w3schools.com/xml/xml_dom.asp" target="_blank">Document Object Model (DOM)</a>.<br>
Ensuite le graphique du plan de voies est reconstitué dynamiquement en javascript avec des instructions <a href="https://www.w3schools.com/html/html5_svg.asp" target="_blank">SVG</a>. Le formatage des éléments graphiques s‘effectue séparément de la définition du graphique avec la variante SVG de <a href="https://www.w3schools.com/html/html_css.asp" target="_blank">CSS</a>.<br>
Le navigateur est capable d‘afficher directement les graphiques SVG. En plus celui-ci utilise les bibliothèques <a href="https://github.com/bumbu/svg-pan-zoom" target="_blank">svg-pan-zoom</a> pour les déplacements et le zooming, ainsi que <a href="https://github.com/fluffynuts/toolwindow" target="_blank">toolwindow</a> pour visualiser les pop-ups.<br>
Le programme fonctionne correctement avec les versions actuelles de Google Chrome, Firefox et MS Edge. Internet Explorer n‘est plus supporté.</small></p>
</article>
<footer>
<hr>
<p lang="de">
<small>(c) Frank Buchholz, 2021, mit Unterstützung von <a href="https://github.com/campersau" target="_blank">campersau</a> und <a href="https://github.com/EEP-Benny" target="_blank">Benny</a> sowie <a href="https://www.eepforum.de/user/6-michael89/" target="_blank">Michael89</a> (EEP 16 Anlagen), <a href="https://www.eepforum.de/user/3932-messina/" target="_blank">Messina</a> (französische Übersetzung) und <a href="https://www.eepforum.de/user/6783-hstoni54/" target="_blank">HStoni54</a> (Berechnung von Helix-Gleisen)</small></p>
<p lang="en">
<small>(c) Frank Buchholz, 2021, with support by <a href="https://github.com/campersau" target="_blank">campersau</a> and <a href="https://github.com/EEP-Benny" target="_blank">Benny</a> as well as <a href="https://www.eepforum.de/user/6-michael89/" target="_blank">Michael89</a> (EEP 16 track plans), <a href="https://www.eepforum.de/user/3932-messina/" target="_blank">Messina</a> (French translation) and <a href="https://www.eepforum.de/user/6783-hstoni54/" target="_blank">HStoni54</a> (Calculation of helix tracks)</small></p>
<p lang="fr">
<small>(c) Frank Buchholz, 2021, avec le soutien de <a href="https://github.com/campersau" target="_blank">campersau</a> et <a href="https://github.com/EEP-Benny" target="_blank">Benny</a> aussi <a href="https://www.eepforum.de/user/6-michael89/" target="_blank">Michael89</a> (EEP 16 Plan des voies), <a href="https://www.eepforum.de/user/3932-messina/" target="_blank">Messina</a> (traduction en français) et <a href="https://www.eepforum.de/user/6783-hstoni54/" target="_blank">HStoni54</a> (Calcul de voies d'hélice)</small></p>
</footer>
<style> /* Selection screen */
/* <![CDATA[ */
#fileselector {
margin: 15px;
}
#fileselector span.li {
display: list-item;
padding-top: 0.2em;
margin-left: 2em;
}
/* ]]> */
</style>
<script type="text/javascript" src="js/matrix.js"></script> <!-- Matrix operations optimized for this program -->
<script type="text/javascript" src="js/bezier_curve_arc_length.js"></script> <!-- getArcLength of Bezier Curve -->
<script type="text/javascript" src="js/convexhull.js"></script> <!-- Convex hull algorithm -->
<script type="text/javascript"> // Load and process file
"use strict";
/* Interface
required standard objects:
DOMParser
Event
FileReader
Promise
console
document
localStorage
requestAnimationFrame
window
required global data:
EEP_Texts
required functions:
_
SvgPanZoom
changefontSize
createSVG
loadColors
public data:
global
public api:
loadFile
*/
(function(api) {
// public api
api.loadFile = loadFile;
// public data
const global = {}; // Collection of all global variables
api.global = global;
function loadFile(file) {
let fr; // upvalue for function processFile
if (typeof window.FileReader !== "function") {
bodyAppend("p", _("err", "001")); // The file API isn't supported on this browser yet.
return;
}
if (!file) {
bodyAppend("p", EEP_Texts.getText("err", "002")); // Please select a file before clicking 'Load'
return;
} else {
global.timestamp = {};
global.timestamp.start = Date.now();
fr = { FileReader: new FileReader() }; // strict mode does not allow to unset read-only property 'result' directly, therfore we have to put the FileReader into an object
fr.FileReader.onload = processFile;
fr.FileReader.readAsText(file);
}
// process file (local function to get access to local variable fr)
function processFile() {
global.timestamp.fileLoaded = Date.now();
console.log('load file:' + (global.timestamp.fileLoaded - global.timestamp.start) / 1000 + 'sec');
updateUi(function() {
// Hide file selector
document.getElementById("fileselector").classList.add("hidden");
// Show loading
document.getElementById("loading").classList.remove("hidden");
}).then(function() {
// Create parser
const parser = new DOMParser();
// Parse xml into DOM
const xmlDoc = parser.parseFromString(fr.FileReader.result, "text/xml");
//fr.FileReader.result = null; // we do not need the file content anymore, but in strict mode we cannot unset the property directly
delete fr.FileReader; // however, we can remove the whole thing (see http://perfectionkills.com/understanding-delete/ )
global.timestamp.fileParsed = Date.now();
console.log('parse file:' + (global.timestamp.fileParsed - global.timestamp.fileLoaded) / 1000 + 'sec');
return xmlDoc;
}).then(function(xmlDoc) {
let progress = document.getElementById("progress");
// Process root node (documentElement always represents the root node)
const sutrackp = xmlDoc.documentElement;
global.sutrackp = sutrackp;
return createSVG(sutrackp, initProgress, incrementProgress);
function initProgress(progressMax) {
return updateUi(function() {
progress.max = progressMax;
progress.value = 0;
progress.classList.remove("hidden");
});
}
function incrementProgress() {
return updateUi(function() {
progress.value++;
});
}
}).then(function() {
// Hide loading
document.getElementById("loading").classList.add("hidden");
// Show main area
document.getElementById("main").classList.remove("hidden");
// Show file name
const filename = file.name.substring(0, file.name.length -1 -1 -3);
document.getElementById("filename").textContent = filename;
document.getElementById("svgTitle").textContent = filename;
// Read settings from localStorage
const strokeWidth = localStorage.getItem("strokeWidth") || document.getElementById("strokeWidth").value;
document.getElementById("strokeWidth").value = strokeWidth;
const fontSize = localStorage.getItem("fontSize") || document.getElementById("fontSize").value;
document.getElementById("fontSize").value = fontSize;
// Checkboxes require spectial treatment
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (key.indexOf("checkbox_") === 0) { // Read checkbox settings
const checkbox = document.querySelector(`input[type="checkbox"][name="${key.substring(9)}"]`);
if (checkbox) {
const value = localStorage.getItem(key) === "true";
if (checkbox.checked !== value) {
checkbox.checked = value;
checkbox.dispatchEvent(new Event("change"));
}
}
} else {
}
}
loadColors();
// Activate Pan and Zoom
global.SvgPanZoom = SvgPanZoom();
changefontSize(fontSize);
return;
}, function(err) {
// `</pre>` confuses syntax detection within Notepad++, therefore I've to use "</pre>"
document.getElementById("loading").innerHTML =
EEP_Texts.getText("err", "003") // Fehler beim Lesen der Datei
+ `:<br>${err.name}: "${err.message}"`
+ EEP_Texts.getText("err", "003a") // in line
+ `${err.lineNumber}<br><pre>${err.stack}` + "</pre>";
console.log(err);
});
}
// helper method which waits some time to let the browser update the ui
function updateUi(fn) {
return new Promise(function(resolve) {
requestAnimationFrame(function() {
const result = fn();
requestAnimationFrame(function() {
resolve(result);
});
});
});
}
function bodyAppend(tagName, innerHTML) {
var elm = document.createElement(tagName);
elm.textContent = innerHTML;
document.body.appendChild(elm);
}
} // loadFile
})(this); // end module
</script>
<script type="text/javascript"> // DOM2SVG
"use strict";
/* Interface
required standard objects:
console
document
required global data:
matrix
global
required functions:
_
convexhull
getKontaktIcon
public api:
TrackSystemText
createSVG
loadStaticTexts
public data:
GebaeudesammlungText
GleisDataText
Gleisart
TrackSystemCode
TrackSystemTexts
WeichenstellungText
unsichtbar
*/
/* [Access to public data does not work this way.]
(function(api) {
// public api
api.TrackSystemText = TrackSystemText;
api.createSVG = createSVG;
api.loadStaticTexts = loadStaticTexts;
// public data
*/
let GebaeudesammlungText, GleisDataText, Gleisart, TrackSystemCode, TrackSystemTexts, WeichenstellungText, unsichtbar;
/*
api.GebaeudesammlungText = GebaeudesammlungText;
api.GleisDataText = GleisDataText;
api.Gleisart = Gleisart;
api.TrackSystemCode = TrackSystemCode;
api.TrackSystemTexts = TrackSystemTexts;
api.WeichenstellungText = WeichenstellungText;
api.unsichtbar = unsichtbar;
*/
// Process root node (sutrackp)
// EEP: Static texts
function TrackSystemText(GleissystemID) {
return TrackSystemTexts[global.TrackSystem[GleissystemID]];
}
function loadStaticTexts() {
TrackSystemTexts = { // per TrackSystemNumber 1-6 (caution: GleissystemID could show other numbers, too)
1 : _('Eisenbahn'),
2 : _('Strassenbahn'),
3 : _('Strasse'),
4 : _('Wasserwege'),
5 : _('Steuerstrecken'), // nicht in EEP 9
6 : _('GBS'), // nicht in EEP 9
};
Gleisart = { // clsid
"2E25C8E2-ADCD-469A-942E-7484556FF932" : _('Normal'),
"C889EADB-63B5-44A2-AAB9-457424CFF15F" : _('Weiche'),
"B0818DD8-5DFD-409F-8022-993FD3C90759" : _('3-Weg-Weiche'),
"06D80C90-4E4B-469B-BFE0-509A573EBC99" : _('Prellbock'),
};
// GleisData
GleisDataText = {
1 : _('Oberleitung'),
2 : _('Weichenlaterne verstecken'),
3 : _('Oberleitung') + ', ' + _('Weichenlaterne verstecken'),
4 : _('Weichenlaterne rechts'),
5 : _('Oberleitung') + ', ' + _('Weichenlaterne rechts'),
8 : _('Weichenlaterne links'),
9 : _('Oberleitung') + ', ' + _('Weichenlaterne links'),
16 : _('Weichenlaterne als Immobilie/Straßen-T-Kreuzung'),
18 : _('Doppelkreuzungsweiche'),
19 : _('Oberleitung') + ', ' + _('Doppelkreuzungsweiche'),
20 : _('Straßen-T-Kreuzung'),
};
// Weichenstellung
WeichenstellungText = {
1 : _('Durchfahrt'),
2 : _('Abzweig'),
3 : _('KoAbzweig'),
5 : _('Spezial'),
};
GebaeudesammlungText = { // GebaeudesammlungID : Text,
1 : _('Eisenbahn'),
2 : _('Strassenbahn'),
3 : _('Straße'),
4 : _('Immobilien'),
5 : _('Landschaftselemente'),
6 : _('Sonstiges'), // (Wasserwege)
};
} // end function loadStaticTexts
TrackSystemCode = { // TracksystemID : Code,
1 : "Eisenbahn",
2 : "Strassenbahn",
3 : "Strasse",
4 : "Wasserwege",
5 : "Steuerstrecken", // nicht in EEP 9
6 : "GBS", // nicht in EEP 9
};
/* Gleisstile:
http://up.picr.de/33875489iu.pdf
http://bahn.hersacher.de/splinekatalog/spkat_intro.htm
*/
unsichtbar = [ // unsichtbare Gleisstile
17, // \Gleisstile\Sonstiges\Wasserweg_unsichtbar.3dm
28, // Gleis
35, // Straßenbahn
34, // \Gleisstile\Sonstiges\Wasserweg_unsichtbar.3dm
36, // \Gleisstile\Strassen\unsichtbar.3dm
562, // Gleis
1309, // \Gleisstile\Gleise\Unsichtbar_LW1.3dm
1346, // Gleis
2052, // \Gleisstile\Gleise\Unsichtbares_Gleis_m_OL_UB3.3dm
3425, // \Gleisstile\Strassen\1Spur_unsichtbar_AS3.3dm
5100, // \Gleisstile\Gleise\Unsichtbar_RB2.3dm
100000, // Kamerafahrweg
/*
18, // \Gleisstile\Sonstiges\telegraph.3dm
70, // \Gleisstile\Sonstiges\Stuetzmauer_Lauscha.3dm
85, // \Gleisstile\Strassen\Leitplanke.3dm
92, // \Gleisstile\Gleise\Bahnsteig.3dm
102, // \Gleisstile\Sonstiges\Gitterzaun.3dm
134, // \Gleisstile\Gleise\Bahnsteig_KoelnHbf.3dm
184, // \Gleisstile\Sonstiges\Gelaender.3dm
264, // \Gleisstile\Gleise\Bahnsteig_Hohenfels.3dm
731, // \Gleisstile\Gleise\Bhst900_Kreihnsdoerp.3dm
732, // \Gleisstile\Gleise\Bhst1350_Kreihnsdoerp.def
851, // \Gleisstile\Sonstiges\851_Gelaender_mit_Stuetze_AF1.3dm
927, // \Gleisstile\Sonstiges\Schallschutzwand.3dm
1246, // \Gleisstile\Sonstiges\Sicherheitszaun.3dm
1307, // \Gleisstile\Sonstiges\Gleis_Abdeckung_C_LW1.3dm
1380, // \Gleisstile\Sonstiges\Fuehrungsschiene_R_LW1.3dm
1381, // \Gleisstile\Sonstiges\Nur Fahrdraht_MM_LW1.3dm
1393, // \Gleisstile\Sonstiges\LW1_Gleis_Fahrdraht_mitte.3dm
1399, // \Gleisstile\Sonstiges\LW1_Gleis_Fahrdraht_ende.3dm
1401, // \Gleisstile\Sonstiges\LW1_Gleis_Quertraeger_unten.3dm
1402, // \Gleisstile\Sonstiges\LW1_Gleis_Quertraeger_oben.3dm
1412, // \Gleisstile\Sonstiges\LW1_Gleis_Fahrdraht_anf.3dm
1414, // \Gleisstile\Sonstiges\LW1_Gleis_Fahrdraht_spann.3dm
1445, // \Gleisstile\Sonstiges\LW1_Gleis_Quertraeger_Stahl_LW1.3dm
1448, // \Gleisstile\Sonstiges\LW1_Gleis_Quertraeger_leer.3dm
1449, // \Gleisstile\Sonstiges\LW1_Gleis_Schallschutz_Stuetzmauer_LW1.3dm
1450, // \Gleisstile\Sonstiges\LW1_Gleis_Spannungsver_A.3dm
1601, // \Gleisstile\Sonstiges\1601_Gelaender_mit_Stuetze_AF1.3dm
1738, // \Gleisstile\Sonstiges\Kabelkanal1_MA1.3dm
1958, // \Gleisstile\Sonstiges\3DVersion\Lattenzaun-3D_SM1.3dm
1959, // \Gleisstile\Sonstiges\3DVersion\Jaegerzaun-3D_SM1.3dm
1974, // \Gleisstile\Sonstiges\Steinmauer3_SM1.3dm
1978, // \Gleisstile\Sonstiges\Arkadenmauer-2gl_SM1.3dm
1979, // \Gleisstile\Sonstiges\Arkadenmauer-4gl_SM1.3dm
1982, // \Gleisstile\Sonstiges\3DVersion\Arkadenmauer-einseitig-3D_SM1.3dm
1995, // \Gleisstile\Sonstiges\Schutzmauer_2_MA1.3dm
2304, // \Gleisstile\Sonstiges\DB-Gelaender_SB3.3dm
2381, // \Gleisstile\Sonstiges\DB-Gelaender_10_SB3.3dm
2386, // \Gleisstile\Sonstiges\Schallschutzwand_grau_SB3.3dm
2387, // \Gleisstile\Sonstiges\Schallschutzwand_gruen_SB3.3dm
2581, // \Gleisstile\Sonstiges\BMauer_eben_0_HW1.3dm
5008, // \Gleisstile\Sonstiges\3DVersion\Sicherheitszaun_mit_Stacheldragt_3D.3dm
5085, // \Gleisstile\Sonstiges\3DVersion\Hedge_1m_Cypress.3dm
5138, // \Gleisstile\Sonstiges\3DVersion\ParkHotel_Harz_Zaun.3dm
5145, 5146, 5147, // Farm track
5213, // \Gleisstile\Sonstiges\3DVersion\Ebrzgl.3dm
5261, // \Gleisstile\Sonstiges\3DVersion\Schutzplanke_einfach_MA1.3dm
5262, // \Gleisstile\Sonstiges\3DVersion\Schutzplanke_zweifach_MA1.3dm
5263, // \Gleisstile\Sonstiges\3DVersion\Schutzplanke_doppel_MA1.3dm
5271, // \Gleisstile\Sonstiges\IndZaun_Zaun_AE1.3dm
5272, // \Gleisstile\Sonstiges\IndZaun_Zaun_TT1_AE1.3dm
5274, // \Gleisstile\Sonstiges\IndZaun_Zaun_TT3_AE1.3dm
5602, // Fence
7411, // \Gleisstile\Strassen\Leitpl_3D_mit_Pf_UFS_DH1.3dm
7412, // \Gleisstile\Sonstiges\Doppel_T_Trg_30x30_blau_DH1.3dm
*/
];
function createSVG(sutrackp, initProgress, incrementProgress) {
loadStaticTexts();
const Gleissysteme = prepareGleissysteme(sutrackp);
// Append new svg elements to this root node which we append to the svg node later
const SVGfragment = document.createDocumentFragment();
return initProgress(Gleissysteme.length).then(function() {
let promise = null;
for (const Gleissystem of Gleissysteme) {
if (promise === null) {
createSVGforGleissystem(Gleissystem, SVGfragment);
promise = incrementProgress();
} else {
promise = promise.then(function() {
createSVGforGleissystem(Gleissystem, SVGfragment);
return incrementProgress();
});
}
}
return promise;
}).then(function() {
createSVGfinalize(SVGfragment);
return;
});
function prepareGleissysteme(sutrackp) {
// Verwendeter Bereich der Anlage
global.usedArea = {
min : {x : 0, y : 0, z : 0},
max : {x : 0, y : 0, z : 0},
};
const Version = sutrackp.getElementsByTagName("Version")[0];
if (Version) {
global.EEPversion = Version.getAttribute("EEP");
if (global.EEPversion >= 16) {
document.getElementById("CheckboxCurveType").classList.remove("hidden");
}
}
// Collections for direct access
global.Gleissysteme = {}; // Verwendung: Gleis = global.Gleissysteme[GleissystemID][GleisID];
global.Meldungen = {};
global.waitingTrains = [], // ID (des Zugverbandes), speed
global.Weichen = {};
global.Kontakte = {};
global.KontaktZiele = {};
global.EndRouteSignals = {}; // Start-route-signals of end-route-signals
global.KameraSet = {}; // Verwendung: Kamera = global.KameraSet[index];
global.Zugverband = {}; // Verwendung: Train = global.Zugverband[GleissystemID][trainName];
global.Gleisobjekte = {};
global.Routen = {};
global.Sounds = {};
// Schaltverbindungen zwischen Signalen und/oder Weichen
global.Couplings = {}; // SignalData, Schaltverbindung zu einem anderen Signal bzw. Weiche
// <Options RouteItems="5" SndId_0="6" SndName_0="ZIEGEN.WAV" SoundItems="1" RouteId_0="1" RouteName_0="Nahverkehr" RouteId_1="2" RouteName_1="Schnellzug" RouteId_2="3" RouteName_2="Gueter" RouteId_3="4" RouteName_3="Nebenbahn" RouteId_4="5" RouteName_4="Sonderzug"/>
const Options = sutrackp.getElementsByTagName("Options")[0];
const RouteItems = +Options.getAttribute("RouteItems");
for (let i = 0; i < RouteItems; i++) {
const RouteID = Options.getAttribute("RouteId_" + i);
const RouteName = Options.getAttribute("RouteName_" + i);
global.Routen[RouteID] = RouteName;
}
const SoundItems = +Options.getAttribute("SoundItems");
for (let i = 0; i < SoundItems; i++) {
const SoundID = Options.getAttribute("SndId_" + i);
const SoundName = Options.getAttribute("SndName_" + i);
global.Sounds[SoundID] = SoundName;
}
// Preparation: Collect "active" tracks
const activeTracks = []; // Gleise, auf denen Züge stehen oder die Kontakte enthalten (Signale werden ignoriert)
// oder die mit solchen Gleisen verbunden sind
// Preparation: Collect connected tracks
const trackConnections = []; // Gleisverbindungen
// Preparation: Collect signals on tracks
const trackSignals = []; // Vor- und Hauptsignale
// Start-route-signals of end-route-signals
const Gleissysteme = sutrackp.getElementsByTagName("Gleissystem");
for (const Gleissystem of Gleissysteme) {
// Use both attributes GleissystemID and TrackSystemNumber if available
let GleissystemID = Gleissystem.getAttribute('GleissystemID');
let TrackSystemNumber = Gleissystem.getAttribute('TrackSystemNumber');
if (GleissystemID && !TrackSystemNumber) {
TrackSystemNumber = GleissystemID;
} else if (!GleissystemID && TrackSystemNumber) {
GleissystemID = TrackSystemNumber;
}
// Store relationship between GleissystemID and TrackSystemNumber
if (!global.TrackSystem) {
global.TrackSystem = {};
}
if (!global.TrackSystem[GleissystemID]) {
global.TrackSystem[GleissystemID] = TrackSystemNumber;
}
global.Gleissysteme[GleissystemID] = {};
activeTracks[GleissystemID] = [];
trackSignals[GleissystemID] = [];
const Gleise = Gleissystem.getElementsByTagName("Gleis");
for (const Gleis of Gleise) {
const GleisID = Gleis.getAttribute("GleisID");
Gleis.GleissystemID = GleissystemID;
global.Gleissysteme[GleissystemID][GleisID] = Gleis;
// Weichen
const WeicheID = Number(Gleis.getAttribute("Key_Id"));
if (WeicheID > 0) {
Gleis.WeicheID = WeicheID;
global.Weichen[WeicheID] = Gleis;
//console.log("global.Weichen["+WeicheID+"] on "+GleissystemID+"-"+GleisID)
// Schaltverbindung zu einem anderen Signal bzw. Weiche
collectCouplings( Gleis, WeicheID );
}
// Weichen mit KontaktZiel
const KontaktZielEntry = Gleis.getElementsByTagName("KontaktZiel")[0];
if (KontaktZielEntry) {
const KontaktZiel = KontaktZielEntry.textContent;
if (KontaktZiel != null && KontaktZiel != 0) {
global.KontaktZiele[KontaktZiel] = {
Typ : _('Weiche'), // 1st letter is used to show an svg text.
ID : WeicheID,
GleissystemID : GleissystemID,
GleisID : GleisID,
};
}
}
// Collect Meldungen to be able to create individual symbols for Vor- and Hauptsignal
for (const Meldung of Gleis.getElementsByTagName("Meldung")) {
const SignalID = Number(Meldung.getAttribute("Key_Id"));
Meldung.GleissystemID = GleissystemID;
Meldung.GleisID = GleisID;
global.Meldungen[SignalID] = Meldung;
if (!trackSignals[GleissystemID][GleisID]) {
trackSignals[GleissystemID][GleisID] = [];
}
trackSignals[GleissystemID][GleisID].push({Meldung : Meldung});
// Signale mit wartenden Zügen
for (const Wartender of Meldung.getElementsByTagName('Wartender')) {
const ZugID = Wartender.getAttribute('zugverbandID');
const targetSpeed = +Wartender.getAttribute('sollgeschwindigkeit') * 3600 / 1000; // km/h
global.waitingTrains[ZugID] = {
SignalID : SignalID,
targetSpeed : targetSpeed,
};
}
// Signale mit KontaktZiel
const KontaktZielEntry = Meldung.getElementsByTagName("KontaktZiel")[0];
if (KontaktZielEntry) {
const KontaktZiel = KontaktZielEntry.textContent;
if (KontaktZiel != null && KontaktZiel != 0) {
global.KontaktZiele[KontaktZiel] = {
Typ : _('Signal'), // 1st letter is used to show an svg text.
ID : SignalID,
GleissystemID : GleissystemID,
GleisID : GleisID,
};
}
}
// Signale für Fahrstraßen: Suche Start-Signale zu Ende-Signalen
const Routes = Meldung.getAttribute('Routes');
const RouteList = Meldung.getElementsByTagName("Route");
let RoutesText = '';
for (const Route of RouteList) {
const Target = Route.getAttribute('Target');
const Color = Route.getAttribute('Color');
if (!global.EndRouteSignals[Target]) {
global.EndRouteSignals[Target] = [];
}
global.EndRouteSignals[Target].push({
GleissystemID : GleissystemID,
StartSignal : SignalID,
Color : Color,
Route : Route,
});
}
// Schaltverbindung zu einem anderen Signal bzw. Weiche
const Signal = Meldung.getElementsByTagName('Signal')[0];
collectCouplings( Signal, SignalID );
}
// Signale, die nur zur Anzeige dienen und keine Züge beeinflussen sollen werden gerne auf "inaktive" Gleise gesetzt.
// Alternativ könnte man nicht-verbundene Einzelgleise als "inaktive" interpretieren.
// A track having a Signal is an "active" track
/*
for (const Meldung of Gleis.getElementsByTagName("Meldung")) {
if (!activeTracks[GleissystemID].includes(GleisID)) {
activeTracks[GleissystemID].push(GleisID);
}
}
*/
// Kontakte
// A track having a Kontakt is an "active" track
for (const Kontakt of Gleis.getElementsByTagName("Kontakt")) {
if (!activeTracks[GleissystemID].includes(GleisID)) {
activeTracks[GleissystemID].push(GleisID);
}
}
} // Gleise
// Gleisverbindungen
trackConnections[GleissystemID] = [];
const Gleisverbindungen = Gleissystem.getElementsByTagName("Gleisverbindung");
for (const Gleisverbindung of Gleisverbindungen) {
// <Gleisverbindung GleisID1="1" Anschluss1="Anfang" GleisID2="5" Anschluss2="Anfang" Flags="1"/>
// Verwendung:
// prevGleisID = trackConnections[GleissystemID][GleisID].Anfang.GleisID
// prevGleisAnschluss = trackConnections[GleissystemID][GleisID].Anfang.Anschluss
// nextGleisID = trackConnections[GleissystemID][GleisID].Ende.GleisID
// nextGleisAnschluss = trackConnections[GleissystemID][GleisID].Ende.Anschluss
// ..
const GleisID1 = Gleisverbindung.getAttribute("GleisID1");
const Anschluss1 = Gleisverbindung.getAttribute("Anschluss1");
const GleisID2 = Gleisverbindung.getAttribute("GleisID2");
const Anschluss2 = Gleisverbindung.getAttribute("Anschluss2");
const Flags = Gleisverbindung.getAttribute("Flags"); // undefined: normal connection, 1: virtual connection
// Store relation GleisID1 -> GleisID2
if (!trackConnections[GleissystemID][GleisID1]) {
trackConnections[GleissystemID][GleisID1] = {};
}
trackConnections[GleissystemID][GleisID1][Anschluss1] = { GleisID : GleisID2, Anschluss : Anschluss2, Flags : Flags, Direction : 1 };
// Store relation GleisID2 -> GleisID1
if (!trackConnections[GleissystemID][GleisID2]) {
trackConnections[GleissystemID][GleisID2] = {};
}
trackConnections[GleissystemID][GleisID2][Anschluss2] = { GleisID : GleisID1, Anschluss : Anschluss1, Flags : Flags, Direction : 2 };
}
}
// Now we are able to show connections on detail popups
global.trackConnections = trackConnections;
// Meldungen analysieren um Fahrstraßen sowie Vor- zu Hauptsignele zu separieren
for (const GleissystemID in trackSignals) {
for (const GleisID in trackSignals[GleissystemID]) {
for (const entry of trackSignals[GleissystemID][GleisID]) {
if (entry.signalType) { continue; } // we have added the entry during the loop, however, for..of does not process new entries anyway
let currentGleisID = GleisID; // Let's start with the current track
const SignalID = entry.Meldung.getAttribute("Key_Id");
let Position = entry.Meldung.getAttribute("Position") / 100; // Wert zwischen 0 und Gleis.Laenge
let ParaOderAnti = entry.Meldung.getAttribute("ParaOderAnti"); //Gleisrichtung: 0 = Ende -> Anfang, 1 = Anfang -> Ende
const Distanz = entry.Meldung.getElementsByTagName("Signal")[0].getAttribute("wirkungsdistanz") / 100; // immmer positiv
const Name = entry.Meldung.getAttribute("name"); // Fahrstraßen: name = "system\Route_SignalS.3ds" bzw. "system\Route_SignalZ.3ds"
const Routes = entry.Meldung.getAttribute("Routes"); // Fahrstraßen Start: Routes > 0
// Store signal data
entry.SignalID = SignalID;
entry.Position = Position;
entry.ParaOderAnti = ParaOderAnti;
// Für Fahrstraßen gilt: name="system\Route_SignalS.3ds" für den Start bzw. name="system\Route_SignalZ.3ds" für das Ziel
// (Außerdem besitzt die Meldung zu Beginn einer Fahrstraße weitere Elemente <Route> usw.
if (Name === "system\\Route_SignalS.3ds") {
entry.signalType = "FStart"; // Fahrstraße Start
continue;
} else if (Name === "system\\Route_SignalZ.3ds") {
entry.signalType = "FZiel"; // Fahrstraße Ziel
continue;
} else if (Distanz === 0) {
entry.signalType = "single"; // Einzel-Signal
continue;
}
// Store Vorsignal
entry.signalType = "pre"; // Vorsignal
// Now we can follow the tracks to find the position of the main signal on the track
let Gleis = global.Gleissysteme[GleissystemID][currentGleisID]; // current track
let Laenge, near, far; //###
if (global.EEPversion && global.EEPversion >= 16) { /* EEP 16 */
const Interval = Gleis.getElementsByTagName("Interval")[0];
near = +Interval.getAttribute("near");
far = +Interval.getAttribute("far");
Laenge = Math.abs( far - near );
} else { /* EEP 15 */
const Charakteristik = Gleis.getElementsByTagName("Charakteristik")[0];
Laenge = +Charakteristik.getAttribute("Laenge") / 100;
}
// Do we find the main signal on the same track?
Position = Position + Distanz * (ParaOderAnti == 1 ? 1 : -1) * (near > far ? -1 : 1); //###
if (Position >= 0 && Position <= Laenge) {
// The main signal is on the same track
trackSignals[GleissystemID][currentGleisID].push({
Meldung : entry.Meldung,
SignalID : SignalID,
signalType : "main",
Position : Position,
ParaOderAnti : ParaOderAnti,
});
continue;
}
if (Position > Laenge) { // look forward
Position = Position - Laenge; // remaining position on next track
} else { // look backward
Position = -Position; // remaining position on previous track
}
// The main signal is on a different track
while (Position > 0) {
let nextGleisID, Anschluss;
if (!trackConnections[GleissystemID][currentGleisID]) { // should not happen
console.log(`Error: Signal ${SignalID} no connected track for ${TrackSystemText(GleissystemID)} ${currentGleisID}`);
break;
}
if (ParaOderAnti == 1) { // look forward
if (trackConnections[GleissystemID][currentGleisID].Ende) {
nextGleisID = trackConnections[GleissystemID][currentGleisID].Ende.GleisID;
Anschluss = trackConnections[GleissystemID][currentGleisID].Ende.Anschluss;
ParaOderAnti = (Anschluss === "Anfang" ? ParaOderAnti : 1-ParaOderAnti);
} else if (trackConnections[GleissystemID][currentGleisID].EndeAbzweig) { // should not happen
console.log(`Error: no connected track for ${TrackSystemText(GleissystemID)} ${currentGleisID}.Ende`);
nextGleisID = trackConnections[GleissystemID][currentGleisID].EndeAbzweig.GleisID;
Anschluss = trackConnections[GleissystemID][currentGleisID].EndeAbzweig.Anschluss;
ParaOderAnti = (Anschluss === "Anfang" ? ParaOderAnti : 1-ParaOderAnti);
} else {
console.log(`Error: no connected track for ${TrackSystemText(GleissystemID)} ${currentGleisID}.EndeAbzweig`);
break;
}
} else { // look backward
if (!trackConnections[GleissystemID][currentGleisID].Anfang) { // should not happen
console.log(`Error: Signal ${SignalID} no connected track for ${TrackSystemText(GleissystemID)} ${currentGleisID}.Anfang`);
break;
}
nextGleisID = trackConnections[GleissystemID][currentGleisID].Anfang.GleisID;