From d93eae6985ecbdf30929a525685637958edcaf54 Mon Sep 17 00:00:00 2001 From: dominik-korsa <29484605+dominik-korsa@users.noreply.github.com> Date: Sat, 12 Jul 2025 13:12:27 +0200 Subject: [PATCH] Add slip switch prefab definitions --- src/model/defs/defined-switches.js | 162 +++++------ .../switch-descriptions/switch-prefab.js | 266 +++++++++++++++++- 2 files changed, 337 insertions(+), 91 deletions(-) diff --git a/src/model/defs/defined-switches.js b/src/model/defs/defined-switches.js index e917203..48a2260 100644 --- a/src/model/defs/defined-switches.js +++ b/src/model/defs/defined-switches.js @@ -3,92 +3,94 @@ import SwitchPrefab from "../switch-descriptions/switch-prefab"; const DefinedSwitches = { "Crossing": SwitchPrefab.crossing(33.2294, 9.0), "Crossing4.444": SwitchPrefab.crossing(20.0, 4.444), - // Rkp 60E1-190-1_9 ab - // Rkp 60E1-190-1_9 ba - // Rkpd 60E1-190-1_9 - "Rld 60E1-1200_600-1_15 L": SwitchPrefab.fork(600.0, -1200.0, 39.95566, 0.0), - "Rld 60E1-1200_600-1_15 R": SwitchPrefab.fork(-600.0, 1200.0, 39.95566, 0.0), - "Rld 60E1-1200_900-1_18.5 L": SwitchPrefab.fork(900.0, -1200.0, 48.61317, 0.0), - "Rld 60E1-1200_900-1_18.5 R": SwitchPrefab.fork(-900.0, 1200.0, 48.61317, 0.0), - "Rld 60E1-1800_300-1_9 L": SwitchPrefab.fork(300.0, -1800.0, 33.23108, 0.0), - "Rld 60E1-1800_300-1_9 R": SwitchPrefab.fork(-300.0, 1800.0, 33.23108, 0.0), - "Rld 60E1-1800_600-1_14 L": SwitchPrefab.fork(600.0, -1800.0, 42.80262, 0.0), - "Rld 60E1-1800_600-1_14 R": SwitchPrefab.fork(-600.0, 1800.0, 42.80262, 0.0), - "Rld 60E1-1800_900-1_18.5 L": SwitchPrefab.fork(900.0, -1800.0, 48.61317, 0.0), - "Rld 60E1-1800_900-1_18.5 R": SwitchPrefab.fork(-900.0, 1800.0, 48.61317, 0.0), - "Rld 60E1-2500_1200-1_22 L": SwitchPrefab.fork(1200.0, -2500.0, 54.51731, 0.0), - "Rld 60E1-2500_1200-1_22 R": SwitchPrefab.fork(-1200.0, 2500.0, 54.51731, 0.0), - "Rld 60E1-2500_250-1_8.5 L": SwitchPrefab.fork(250.0, -2500.0, 29.31069, 0.0), - "Rld 60E1-2500_250-1_8.5 R": SwitchPrefab.fork(-250.0, 2500.0, 29.31069, 0.0), - "Rld 60E1-2500_400-1_10.5 L": SwitchPrefab.fork(400.0, -2500.0, 38.00925, 0.0), - "Rld 60E1-2500_400-1_10.5 R": SwitchPrefab.fork(-400.0, 2500.0, 38.00925, 0.0), - "Rld 60E1-2500_600-1_14 L": SwitchPrefab.fork(600.0, -2500.0, 42.80262, 0.0), - "Rld 60E1-2500_600-1_14 R": SwitchPrefab.fork(-600.0, 2500.0, 42.80262, 0.0), - "Rld 60E1-2500_900-1_17 L": SwitchPrefab.fork(900.0, -2500.0, 52.14928, 0.0), - "Rld 60E1-2500_900-1_17 R": SwitchPrefab.fork(-900.0, 2500.0, 52.14928, 0.0), - "Rld 60E1-600_300-1_9 L": SwitchPrefab.fork(300.0, -600.0, 29.92537, 0.0), - "Rld 60E1-600_300-1_9 R": SwitchPrefab.fork(-300.0, 600.0, 29.92537, 0.0), - "Rld 60E1-650_450-1_15 L": SwitchPrefab.fork(450.0, -650.0, 29.96674, 0.0), - "Rld 60E1-650_450-1_15 R": SwitchPrefab.fork(-450.0, 650.0, 29.96674, 0.0), - "Rld 60E1-700_190-1_7.5 L": SwitchPrefab.fork(190.0, -700.0, 25.22173, 0.0), - "Rld 60E1-700_190-1_7.5 R": SwitchPrefab.fork(-190.0, 700.0, 25.22173, 0.0), - "Rld 60E1-700_300-1_10 L": SwitchPrefab.fork(300.0, -700.0, 29.38637, 0.0), - "Rld 60E1-700_300-1_10 R": SwitchPrefab.fork(-300.0, 700.0, 29.38637, 0.0), - "Rld 60E1-700_500-1_14 L": SwitchPrefab.fork(500.0, -700.0, 35.66885, 0.0), - "Rld 60E1-700_500-1_14 R": SwitchPrefab.fork(-500.0, 700.0, 35.66885, 0.0), - "Rld 60E1-900_300-1_9 L": SwitchPrefab.fork(300.0, -900.0, 33.23108, 0.0), - "Rld 60E1-900_300-1_9 R": SwitchPrefab.fork(-300.0, 900.0, 33.23108, 0.0), - "Rld 60E1-900_450-1_12 L": SwitchPrefab.fork(450.0, -900.0, 37.43512, 0.0), - "Rld 60E1-900_450-1_12 R": SwitchPrefab.fork(-450.0, 900.0, 37.43512, 0.0), - "Rld 60E1-900_600-1_15 L": SwitchPrefab.fork(600.0, -900.0, 39.95566, 0.0), - "Rld 60E1-900_600-1_15 R": SwitchPrefab.fork(-600.0, 900.0, 39.95566, 0.0), - "Rlds 60E1-1000-1000-1_23": SwitchPrefab.fork(1000.0, -1000.0, 43.45773, 0.0), - "Rlds 60E1-190-190-1_9": SwitchPrefab.fork(190.0, -190.0, 21.23, 0.0), - "Rlds 60E1-600-600-1_18.5": SwitchPrefab.fork(599.9205, -600.0, 33.22262, 0.0), - "Rlj 60E1-1200_300-1_7 L": SwitchPrefab.fork(300.0, 1200.0, 42.64069, 0.0), - "Rlj 60E1-1200_300-1_7 R": SwitchPrefab.fork(-300.0, -1200.0, 42.64069, 0.0), - "Rlj 60E1-1200_600-1_9 L": SwitchPrefab.fork(600.0, 1200.0, 68.0, 0.0), - "Rlj 60E1-1200_600-1_9 R": SwitchPrefab.fork(-600.0, -1200.0, 68.0, 0.0), - "Rlj 60E1-1500_450-1_9 L": SwitchPrefab.fork(450.0, 1500.0, 49.84663, 0.0), - "Rlj 60E1-1500_450-1_9 R": SwitchPrefab.fork(-450.0, -1500.0, 49.84663, 0.0), - "Rlj 60E1-1800_300-1_7.5 L": SwitchPrefab.fork(300.0, 1800.0, 39.0, 0.0), - "Rlj 60E1-1800_300-1_7.5 R": SwitchPrefab.fork(-300.0, -1800.0, 39.0, 0.0), - "Rlj 60E1-1800_450-1_9 L": SwitchPrefab.fork(450.0, 1800.0, 49.84663, 0.0), - "Rlj 60E1-1800_450-1_9 R": SwitchPrefab.fork(-450.0, -1800.0, 49.84663, 0.0), - "Rlj 60E1-1800_600-1_10 L": SwitchPrefab.fork(599.48096, 1800.0, 59.85075, 0.0), - "Rlj 60E1-1800_600-1_10 R": SwitchPrefab.fork(-599.48096, -1800.0, 59.85075, 0.0), - "Rlj 60E1-600_300-1_6 L": SwitchPrefab.fork(300.0, 600.0, 48.0, 0.0), - "Rlj 60E1-600_300-1_6 R": SwitchPrefab.fork(-300.0, -600.0, 48.0, 0.0), - "Rlj 60E1-650_190-1_20 L": SwitchPrefab.fork(190.0, 650.0, 32.47971, 0.0), - "Rlj 60E1-650_190-1_20 R": SwitchPrefab.fork(-190.0, -650.0, 32.47971, 0.0), - "Rlj 60E1-750_190-1_6 L": SwitchPrefab.fork(190.0, 750.0, 31.44976, 0.0), - "Rlj 60E1-750_190-1_6 R": SwitchPrefab.fork(-190.0, -750.0, 31.44976, 0.0), - "Rlj 60E1-800_250-1_6.5 L": SwitchPrefab.fork(250.0, 800.0, 38.23661, 0.0), - "Rlj 60E1-800_250-1_6.5 R": SwitchPrefab.fork(-250.0, -800.0, 38.23661, 0.0), - "Rlj 60E1-900_300-1_7.5 L": SwitchPrefab.fork(300.0, 900.0, 39.82378, 0.0), - "Rlj 60E1-900_300-1_7.5 R": SwitchPrefab.fork(-300.0, -900.0, 39.82378, 0.0), - "Rlj 60E1-900_300-1_9 L": SwitchPrefab.fork(300.0, 900.0, 49.84663, 0.0), - "Rlj 60E1-900_300-1_9 R": SwitchPrefab.fork(-300.0, -900.0, 49.84663, 0.0), - "Rlj 60E1-900_450-1_7.5 L": SwitchPrefab.fork(450.0, 900.0, 59.0, 0.0), - "Rlj 60E1-900_450-1_7.5 R": SwitchPrefab.fork(-450.0, -900.0, 59.0, 0.0), - "Rz 60E1-1200-1_18.5 L": SwitchPrefab.fork(1200.0, 0.0, 64.81756, 0.0), - "Rz 60E1-1200-1_18.5 R": SwitchPrefab.fork(-1200.0, 0.0, 64.81756, 0.0), - "Rz 60E1-190-1_7.5 L": SwitchPrefab.fork(190.0, 0.0, 25.221731, 0.0), - "Rz 60E1-190-1_7.5 R": SwitchPrefab.fork(-190.0, 0.0, 25.221731, 0.0), + + "Rkp 60E1-190-1_9 ab": SwitchPrefab.slip(33.165, 6.06, 7.461676, 190.0, 9.0, false, true), + "Rkp 60E1-190-1_9 ba": SwitchPrefab.slip(33.165, 6.06, 7.461676, 190.0, 9.0, false, true), + "Rkpd 60E1-190-1_9": SwitchPrefab.slip(33.165, 6.06, 7.461676, 190.0, 9.0, true, true), + + "Rld 60E1-1200_600-1_15 L": SwitchPrefab.fork(600.0, -1200.0, 39.95566), + "Rld 60E1-1200_600-1_15 R": SwitchPrefab.fork(-600.0, 1200.0, 39.95566), + "Rld 60E1-1200_900-1_18.5 L": SwitchPrefab.fork(900.0, -1200.0, 48.61317), + "Rld 60E1-1200_900-1_18.5 R": SwitchPrefab.fork(-900.0, 1200.0, 48.61317), + "Rld 60E1-1800_300-1_9 L": SwitchPrefab.fork(300.0, -1800.0, 33.23108), + "Rld 60E1-1800_300-1_9 R": SwitchPrefab.fork(-300.0, 1800.0, 33.23108), + "Rld 60E1-1800_600-1_14 L": SwitchPrefab.fork(600.0, -1800.0, 42.80262), + "Rld 60E1-1800_600-1_14 R": SwitchPrefab.fork(-600.0, 1800.0, 42.80262), + "Rld 60E1-1800_900-1_18.5 L": SwitchPrefab.fork(900.0, -1800.0, 48.61317), + "Rld 60E1-1800_900-1_18.5 R": SwitchPrefab.fork(-900.0, 1800.0, 48.61317), + "Rld 60E1-2500_1200-1_22 L": SwitchPrefab.fork(1200.0, -2500.0, 54.51731), + "Rld 60E1-2500_1200-1_22 R": SwitchPrefab.fork(-1200.0, 2500.0, 54.51731), + "Rld 60E1-2500_250-1_8.5 L": SwitchPrefab.fork(250.0, -2500.0, 29.31069), + "Rld 60E1-2500_250-1_8.5 R": SwitchPrefab.fork(-250.0, 2500.0, 29.31069), + "Rld 60E1-2500_400-1_10.5 L": SwitchPrefab.fork(400.0, -2500.0, 38.00925), + "Rld 60E1-2500_400-1_10.5 R": SwitchPrefab.fork(-400.0, 2500.0, 38.00925), + "Rld 60E1-2500_600-1_14 L": SwitchPrefab.fork(600.0, -2500.0, 42.80262), + "Rld 60E1-2500_600-1_14 R": SwitchPrefab.fork(-600.0, 2500.0, 42.80262), + "Rld 60E1-2500_900-1_17 L": SwitchPrefab.fork(900.0, -2500.0, 52.14928), + "Rld 60E1-2500_900-1_17 R": SwitchPrefab.fork(-900.0, 2500.0, 52.14928), + "Rld 60E1-600_300-1_9 L": SwitchPrefab.fork(300.0, -600.0, 29.92537), + "Rld 60E1-600_300-1_9 R": SwitchPrefab.fork(-300.0, 600.0, 29.92537), + "Rld 60E1-650_450-1_15 L": SwitchPrefab.fork(450.0, -650.0, 29.96674), + "Rld 60E1-650_450-1_15 R": SwitchPrefab.fork(-450.0, 650.0, 29.96674), + "Rld 60E1-700_190-1_7.5 L": SwitchPrefab.fork(190.0, -700.0, 25.22173), + "Rld 60E1-700_190-1_7.5 R": SwitchPrefab.fork(-190.0, 700.0, 25.22173), + "Rld 60E1-700_300-1_10 L": SwitchPrefab.fork(300.0, -700.0, 29.38637), + "Rld 60E1-700_300-1_10 R": SwitchPrefab.fork(-300.0, 700.0, 29.38637), + "Rld 60E1-700_500-1_14 L": SwitchPrefab.fork(500.0, -700.0, 35.66885), + "Rld 60E1-700_500-1_14 R": SwitchPrefab.fork(-500.0, 700.0, 35.66885), + "Rld 60E1-900_300-1_9 L": SwitchPrefab.fork(300.0, -900.0, 33.23108), + "Rld 60E1-900_300-1_9 R": SwitchPrefab.fork(-300.0, 900.0, 33.23108), + "Rld 60E1-900_450-1_12 L": SwitchPrefab.fork(450.0, -900.0, 37.43512), + "Rld 60E1-900_450-1_12 R": SwitchPrefab.fork(-450.0, 900.0, 37.43512), + "Rld 60E1-900_600-1_15 L": SwitchPrefab.fork(600.0, -900.0, 39.95566), + "Rld 60E1-900_600-1_15 R": SwitchPrefab.fork(-600.0, 900.0, 39.95566), + "Rlds 60E1-1000-1000-1_23": SwitchPrefab.fork(1000.0, -1000.0, 43.45773), + "Rlds 60E1-190-190-1_9": SwitchPrefab.fork(190.0, -190.0, 21.23), + "Rlds 60E1-600-600-1_18.5": SwitchPrefab.fork(599.9205, -600.0, 33.22262), + "Rlj 60E1-1200_300-1_7 L": SwitchPrefab.fork(300.0, 1200.0, 42.64069), + "Rlj 60E1-1200_300-1_7 R": SwitchPrefab.fork(-300.0, -1200.0, 42.64069), + "Rlj 60E1-1200_600-1_9 L": SwitchPrefab.fork(600.0, 1200.0, 68.0), + "Rlj 60E1-1200_600-1_9 R": SwitchPrefab.fork(-600.0, -1200.0, 68.0), + "Rlj 60E1-1500_450-1_9 L": SwitchPrefab.fork(450.0, 1500.0, 49.84663), + "Rlj 60E1-1500_450-1_9 R": SwitchPrefab.fork(-450.0, -1500.0, 49.84663), + "Rlj 60E1-1800_300-1_7.5 L": SwitchPrefab.fork(300.0, 1800.0, 39.0), + "Rlj 60E1-1800_300-1_7.5 R": SwitchPrefab.fork(-300.0, -1800.0, 39.0), + "Rlj 60E1-1800_450-1_9 L": SwitchPrefab.fork(450.0, 1800.0, 49.84663), + "Rlj 60E1-1800_450-1_9 R": SwitchPrefab.fork(-450.0, -1800.0, 49.84663), + "Rlj 60E1-1800_600-1_10 L": SwitchPrefab.fork(599.48096, 1800.0, 59.85075), + "Rlj 60E1-1800_600-1_10 R": SwitchPrefab.fork(-599.48096, -1800.0, 59.85075), + "Rlj 60E1-600_300-1_6 L": SwitchPrefab.fork(300.0, 600.0, 48.0), + "Rlj 60E1-600_300-1_6 R": SwitchPrefab.fork(-300.0, -600.0, 48.0), + "Rlj 60E1-650_190-1_20 L": SwitchPrefab.fork(190.0, 650.0, 32.47971), + "Rlj 60E1-650_190-1_20 R": SwitchPrefab.fork(-190.0, -650.0, 32.47971), + "Rlj 60E1-750_190-1_6 L": SwitchPrefab.fork(190.0, 750.0, 31.44976), + "Rlj 60E1-750_190-1_6 R": SwitchPrefab.fork(-190.0, -750.0, 31.44976), + "Rlj 60E1-800_250-1_6.5 L": SwitchPrefab.fork(250.0, 800.0, 38.23661), + "Rlj 60E1-800_250-1_6.5 R": SwitchPrefab.fork(-250.0, -800.0, 38.23661), + "Rlj 60E1-900_300-1_7.5 L": SwitchPrefab.fork(300.0, 900.0, 39.82378), + "Rlj 60E1-900_300-1_7.5 R": SwitchPrefab.fork(-300.0, -900.0, 39.82378), + "Rlj 60E1-900_300-1_9 L": SwitchPrefab.fork(300.0, 900.0, 49.84663), + "Rlj 60E1-900_300-1_9 R": SwitchPrefab.fork(-300.0, -900.0, 49.84663), + "Rlj 60E1-900_450-1_7.5 L": SwitchPrefab.fork(450.0, 900.0, 59.0), + "Rlj 60E1-900_450-1_7.5 R": SwitchPrefab.fork(-450.0, -900.0, 59.0), + "Rz 60E1-1200-1_18.5 L": SwitchPrefab.fork(1200.0, 0.0, 64.81756), + "Rz 60E1-1200-1_18.5 R": SwitchPrefab.fork(-1200.0, 0.0, 64.81756), + "Rz 60E1-190-1_7.5 L": SwitchPrefab.fork(190.0, 0.0, 25.221731), + "Rz 60E1-190-1_7.5 R": SwitchPrefab.fork(-190.0, 0.0, 25.221731), "Rz 60E1-190-1_9 L": SwitchPrefab.fork(0.0, 190.0, 21.046352, 6.0923653), "Rz 60E1-190-1_9 R": SwitchPrefab.fork(0.0, -190.0, 21.046352, 6.0923653), "Rz 60E1-205-1_9 L": SwitchPrefab.fork(205.0, 0.0, 22.707907, 5.42 /* added manually */), "Rz 60E1-205-1_9 R": SwitchPrefab.fork(-205.0, 0.0, 22.707907, 5.42 /* added manually */), - "Rz 60E1-2500-1_26.5 L": SwitchPrefab.fork(2500.0, 0.0, 94.30607, 0.0), - "Rz 60E1-2500-1_26.5 R": SwitchPrefab.fork(-2500.0, 0.0, 94.30607, 0.0), + "Rz 60E1-2500-1_26.5 L": SwitchPrefab.fork(2500.0, 0.0, 94.30607), + "Rz 60E1-2500-1_26.5 R": SwitchPrefab.fork(-2500.0, 0.0, 94.30607), "Rz 60E1-265-1_10 L": SwitchPrefab.fork(0.0, 265.0, 26.434078, 4.75 /* added manually */), "Rz 60E1-265-1_10 R": SwitchPrefab.fork(0.0, -265.0, 26.434078, 4.75 /* added manually */), - "Rz 60E1-300-1_9 L": SwitchPrefab.fork(300.0, 0.0, 33.231083, 0.0), - "Rz 60E1-300-1_9 R": SwitchPrefab.fork(-300.0, 0.0, 33.231083, 0.0), - "Rz 60E1-500-1_12 L": SwitchPrefab.fork(500.0, 0.0, 41.59458, 0.0), - "Rz 60E1-500-1_12 R": SwitchPrefab.fork(-500.0, 0.0, 41.59458, 0.0), - "Rz 60E1-760-1_14 L": SwitchPrefab.fork(760.0, 0.0, 54.21665, 0.0), - "Rz 60E1-760-1_14 R": SwitchPrefab.fork(-760.0, 0.0, 54.21665, 0.0), + "Rz 60E1-300-1_9 L": SwitchPrefab.fork(300.0, 0.0, 33.231083), + "Rz 60E1-300-1_9 R": SwitchPrefab.fork(-300.0, 0.0, 33.231083), + "Rz 60E1-500-1_12 L": SwitchPrefab.fork(500.0, 0.0, 41.59458), + "Rz 60E1-500-1_12 R": SwitchPrefab.fork(-500.0, 0.0, 41.59458), + "Rz 60E1-760-1_14 L": SwitchPrefab.fork(760.0, 0.0, 54.21665), + "Rz 60E1-760-1_14 R": SwitchPrefab.fork(-760.0, 0.0, 54.21665), }; export default DefinedSwitches; diff --git a/src/model/switch-descriptions/switch-prefab.js b/src/model/switch-descriptions/switch-prefab.js index 4b0ef2e..a6161b3 100644 --- a/src/model/switch-descriptions/switch-prefab.js +++ b/src/model/switch-descriptions/switch-prefab.js @@ -49,7 +49,7 @@ export default class SwitchPrefab { }); } - static fork(radiusA, radiusB, curveLength, addedLength) { + static fork(radiusA, radiusB, curveLength, addedLength = 0.0) { const tracks = { start: new SwitchPrefabTrack( Vector3.zero(), @@ -92,18 +92,20 @@ export default class SwitchPrefab { return new SwitchPrefab(tracks); } - static _createForkSwitchTracks(radius, curveLength, addedLength, side) { - let curveEnd; - let endAngle; + static _calculateCurveEnd(startPos, startAngle, radius, curveLength) { if (radius === 0) { - curveEnd = new Vector3(0, 0, curveLength); - endAngle = 0; - } else { - const circleCenter = new Vector3(-radius, 0, 0); - endAngle = -curveLength / radius; - const centerToEnd = Vector3.fromAngleY(endAngle + Math.sign(radius) * Math.PI / 2, Math.abs(radius)); - curveEnd = circleCenter.add(centerToEnd); + return { endPos: startPos, endAngle: startAngle }; } + const centerToStart = Vector3.fromAngleY(startAngle + Math.sign(radius) * Math.PI / 2, Math.abs(radius)); + const circleCenter = startPos.add(centerToStart.negate()); + const endAngle = startAngle -curveLength / radius; + const centerToEnd = Vector3.fromAngleY(endAngle + Math.sign(radius) * Math.PI / 2, Math.abs(radius)); + const endPos = circleCenter.add(centerToEnd); + return { endPos, endAngle }; + } + + static _createForkSwitchTracks(radius, curveLength, addedLength, side) { + const { endPos: curveEnd, endAngle } = SwitchPrefab._calculateCurveEnd(Vector3.zero(), 0, radius, curveLength); const tracks = { [`curve_${side}`]: new SwitchPrefabTrack( @@ -215,4 +217,246 @@ export default class SwitchPrefab { return new SwitchPrefab(tracks); } + + static slip(totalLength, outerLength, transitionLength, radius, tangentInv, leftSlipEnabled, rightSlipEnabled) { + const aAngle = Math.atan(1 / tangentInv / 2); + const bAngle = -aAngle; + const unitVectorA = Vector3.fromAngleY(aAngle); + const unitVectorB = Vector3.fromAngleY(bAngle); + + const outerStart = totalLength / 2; + const transitionStart = outerStart - outerLength; + const innerStart = transitionStart - transitionLength; + + const makeSlipConfig = (radiusSign, unitVector, startAngle) => { + const startPos = unitVector.multiply(transitionStart); + const slipRadius = radiusSign * radius; + const { endPos } = SwitchPrefab._calculateCurveEnd(startPos, startAngle, slipRadius, transitionLength); + return { + startPos, + slipRadius, + endPos, + }; + }; + const slipPoints = { + a_enter: makeSlipConfig(1, unitVectorA.negate(), aAngle), + a_exit: makeSlipConfig(1, unitVectorA, aAngle + Math.PI), + b_enter: makeSlipConfig(-1, unitVectorB.negate(), bAngle), + b_exit: makeSlipConfig(-1, unitVectorB, bAngle + Math.PI), + }; + + let dataIndex = 0; + const outerTrack = (unitVector, name) => [ + `outer_${name}`, + new SwitchPrefabTrack( + unitVector.multiply(outerStart), + unitVector.multiply(transitionStart), + 0, + dataIndex++, + [ + { + type: SwitchTrackConnectionType.EXTERNAL, + end: TrackConnectionEnd.START, + }, + { + type: SwitchTrackConnectionType.INTERNAL, + end: TrackConnectionEnd.END, + otherEnd: TrackConnectionEnd.START, + internalId: `transition_${name}`, + }, + ], + ), + ]; + const transitionTrack = (unitVector, path, end) => [ + `transition_${path}_${end}`, + new SwitchPrefabTrack( + unitVector.multiply(transitionStart), + unitVector.multiply(innerStart), + 0, + dataIndex++, + [ + { + type: SwitchTrackConnectionType.INTERNAL, + end: TrackConnectionEnd.START, + otherEnd: TrackConnectionEnd.END, + internalId: `outer_${path}_${end}`, + }, + { + type: SwitchTrackConnectionType.INTERNAL, + end: TrackConnectionEnd.END, + otherEnd: end === 'enter' ? TrackConnectionEnd.START : TrackConnectionEnd.END, + internalId: `crossing_${path}`, + }, + ], + ), + ]; + const slipTransitionTrack = (path, side, end) => { + const { startPos, slipRadius, endPos } = slipPoints[`${path}_${end}`]; + return [ + `slip_transition_${path}_${end}`, + new SwitchPrefabTrack( + startPos, + endPos, + slipRadius, + dataIndex++, + [ + { + type: SwitchTrackConnectionType.INTERNAL, + end: TrackConnectionEnd.START, + otherEnd: TrackConnectionEnd.END, + internalId: `outer_${path}_${end}`, + }, + { + type: SwitchTrackConnectionType.INTERNAL, + end: TrackConnectionEnd.END, + otherEnd: end === 'enter' ? TrackConnectionEnd.START : TrackConnectionEnd.END, + internalId: `side_${side}`, + }, + ], + ), + ]; + }; + const crossingTrack = (unitVector, path) => [ + `crossing_${path}`, + new SwitchPrefabTrack( + unitVector.multiply(-innerStart), + unitVector.multiply(innerStart), + 0, + dataIndex++, + [ + { + type: SwitchTrackConnectionType.INTERNAL, + end: TrackConnectionEnd.START, + otherEnd: TrackConnectionEnd.END, + internalId: `transition_${path}_enter`, + }, + { + type: SwitchTrackConnectionType.INTERNAL, + end: TrackConnectionEnd.END, + otherEnd: TrackConnectionEnd.END, + internalId: `transition_${path}_exit`, + }, + ], + ), + ]; + const sideTrack = (unitVectorEnter, unitVectorExit, enterPath, exitPath, side, slipEnabled) => { + if (slipEnabled) { + const enterConfig = slipPoints[`${enterPath}_enter`]; + const exitConfig = slipPoints[`${exitPath}_exit`]; + return [ + `side_${side}`, + new SwitchPrefabTrack( + enterConfig.endPos, + exitConfig.endPos, + enterConfig.slipRadius, + dataIndex++, + [ + { + type: SwitchTrackConnectionType.INTERNAL, + end: TrackConnectionEnd.START, + otherEnd: TrackConnectionEnd.END, + internalId: `slip_transition_${enterPath}_enter`, + }, + { + type: SwitchTrackConnectionType.INTERNAL, + end: TrackConnectionEnd.END, + otherEnd: TrackConnectionEnd.END, + internalId: `slip_transition_${exitPath}_exit`, + }, + ] + ), + ]; + } else { + return [ + `side_${side}`, + new SwitchPrefabTrack( + unitVectorEnter.multiply(innerStart), + unitVectorExit.multiply(innerStart), + 0, + dataIndex++, + [ + { + type: SwitchTrackConnectionType.INTERNAL, + end: TrackConnectionEnd.START, + otherEnd: TrackConnectionEnd.END, + internalId: `transition_${enterPath}_enter`, + }, + { + type: SwitchTrackConnectionType.INTERNAL, + end: TrackConnectionEnd.END, + otherEnd: TrackConnectionEnd.END, + internalId: `transition_${exitPath}_exit`, + }, + ] + ), + ]; + } + }; + + // the order is important, each function call increments dataIndex + const trackList = [ + outerTrack(unitVectorA.negate(), 'a_enter'), + outerTrack(unitVectorB.negate(), 'b_enter'), + outerTrack(unitVectorA, 'a_exit'), + outerTrack(unitVectorB, 'b_exit'), + transitionTrack(unitVectorA.negate(), 'a', 'enter'), + transitionTrack(unitVectorB.negate(), 'b', 'enter'), + ]; + if (leftSlipEnabled) { + trackList.push(slipTransitionTrack('a', 'left', 'enter')); + } + if (rightSlipEnabled) { + trackList.push(slipTransitionTrack('b', 'right', 'enter')); + } + trackList.push( + crossingTrack(unitVectorA, 'a'), + crossingTrack(unitVectorB, 'b'), + sideTrack(unitVectorA.negate(), unitVectorB, 'a', 'b', 'left', leftSlipEnabled), + sideTrack(unitVectorB.negate(), unitVectorA, 'b', 'a', 'right', rightSlipEnabled), + transitionTrack(unitVectorA, 'a', 'exit'), + transitionTrack(unitVectorB, 'b', 'exit'), + ); + if (rightSlipEnabled) { + trackList.push(slipTransitionTrack('a', 'right', 'exit')); + } + if (leftSlipEnabled) { + trackList.push(slipTransitionTrack('b', 'left', 'exit')); + } + + const tracks = Object.fromEntries(trackList); + + const addSideConnection = (side, enter_path, exit_path, slipEnabled) => { + if (slipEnabled) { + tracks[`outer_${enter_path}_enter`].connections.push({ + type: SwitchTrackConnectionType.INTERNAL, + end: TrackConnectionEnd.END, + otherEnd: TrackConnectionEnd.START, + internalId: `slip_transition_${enter_path}_enter`, + }); + tracks[`outer_${exit_path}_exit`].connections.push({ + type: SwitchTrackConnectionType.INTERNAL, + end: TrackConnectionEnd.END, + otherEnd: TrackConnectionEnd.START, + internalId: `slip_transition_${exit_path}_exit`, + }); + } else { + tracks[`transition_${enter_path}_enter`].connections.push({ + type: SwitchTrackConnectionType.INTERNAL, + end: TrackConnectionEnd.END, + otherEnd: TrackConnectionEnd.START, + internalId: `side_${side}`, + }); + tracks[`transition_${exit_path}_exit`].connections.push({ + type: SwitchTrackConnectionType.INTERNAL, + end: TrackConnectionEnd.END, + otherEnd: TrackConnectionEnd.END, + internalId: `side_${side}`, + }); + } + }; + addSideConnection('left', 'a', 'b', leftSlipEnabled); + addSideConnection('right', 'b', 'a', rightSlipEnabled); + + return new SwitchPrefab(tracks); + } }