1 package org.opentrafficsim.road.network;
2
3 import java.util.Map;
4 import java.util.Optional;
5 import java.util.Set;
6
7 import org.djunits.value.vdouble.scalar.Duration;
8 import org.djutils.exceptions.Throw;
9 import org.opentrafficsim.core.gtu.GtuType;
10 import org.opentrafficsim.core.network.LateralDirectionality;
11 import org.opentrafficsim.road.network.speed.LaneSpeedLimits;
12 import org.opentrafficsim.road.network.speed.SpeedLimit;
13 import org.opentrafficsim.road.network.speed.SpeedLimits;
14
15
16
17
18
19
20
21
22
23
24 public class Shoulder extends Lane
25 {
26
27
28 private Lane lane;
29
30
31
32
33
34
35
36
37 public Shoulder(final CrossSectionLink link, final String id, final CrossSectionGeometry geometry, final LaneType laneType)
38 {
39 super(link, id, geometry, laneType, new LaneSpeedLimits(Map.of()));
40 }
41
42
43
44
45
46
47
48 @Override
49 public Optional<Lane> getAdjacentLane(final LateralDirectionality laneChangeDirection, final GtuType gtuType)
50 {
51 Set<Lane> adjLanes = accessibleAdjacentLanesPhysical(laneChangeDirection, gtuType);
52 if (!adjLanes.isEmpty())
53 {
54 return Optional.of(adjLanes.iterator().next());
55 }
56 return Optional.empty();
57 }
58
59 @Override
60 public double getZ()
61 {
62 return -0.00005;
63 }
64
65 @Override
66 public SpeedLimits getSpeedLimits(final GtuType gtuType)
67 {
68 return getLane().getSpeedLimits(gtuType);
69 }
70
71 @Override
72 public SpeedLimits getSpeedLimits(final GtuType gtuType, final Duration timeOfDay)
73 {
74 return getLane().getSpeedLimits(gtuType, timeOfDay);
75 }
76
77 @Override
78 public Optional<SpeedLimit> getSpeedLimit()
79 {
80 return getLane().getSpeedLimit();
81 }
82
83 @Override
84 public Optional<SpeedLimit> getSpeedLimit(final Duration timeOfDay)
85 {
86 return getLane().getSpeedLimit(timeOfDay);
87 }
88
89
90
91
92
93 private Lane getLane()
94 {
95 if (this.lane == null)
96 {
97 double minDist = Double.POSITIVE_INFINITY;
98 for (Lane laneInLink : getLink().getLanes())
99 {
100 double dist = laneInLink.getCenterLine().getFirst().distance(getCenterLine().getFirst());
101 if (dist < minDist)
102 {
103 this.lane = laneInLink;
104 minDist = dist;
105 }
106 }
107 Throw.when(this.lane == null, IllegalStateException.class, "Shoulder is on a link without any lane.");
108 }
109 return this.lane;
110 }
111
112 }