1 package org.opentrafficsim.road.network.lane;
2
3 import java.util.LinkedHashMap;
4 import java.util.LinkedHashSet;
5 import java.util.List;
6 import java.util.Map;
7 import java.util.Set;
8 import java.util.UUID;
9
10 import org.djunits.value.vdouble.scalar.Length;
11 import org.djutils.exceptions.Throw;
12 import org.opentrafficsim.core.geometry.OtsGeometryException;
13 import org.opentrafficsim.core.gtu.GtuType;
14 import org.opentrafficsim.core.network.LateralDirectionality;
15 import org.opentrafficsim.core.network.NetworkException;
16
17 /**
18 * <p>
19 * Copyright (c) 2013-2023 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
20 * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
21 * </p>
22 * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
23 * @author <a href="https://tudelft.nl/staff/p.knoppers-1">Peter Knoppers</a>
24 * @author <a href="https://dittlab.tudelft.nl">Wouter Schakel</a>
25 */
26 public class Stripe extends CrossSectionElement
27 {
28 /** */
29 private static final long serialVersionUID = 20141025L;
30
31 /** Type of the stripe, defining default permeability. */
32 private final Type type;
33
34 /** Type to overrule the normal type, e.g. rush-hour lanes without changing the appearance of the stripe. */
35 private Type overruleType;
36
37 /** Lateral permeability per GTU type and direction. */
38 private final Map<GtuType, Set<LateralDirectionality>> permeabilityMap = new LinkedHashMap<>();
39
40 /**
41 * Constructor allowing difference at start at end.
42 * @param type Type; strip type defining appearance and default permeability.
43 * @param parentLink CrossSectionLink; Cross Section Link to which the element belongs.
44 * @param startCenterPosition Length; the lateral start position compared to the linear geometry of the Cross Section Link
45 * at the start of the road marker.
46 * @param endCenterPosition Length; the lateral end position compared to the linear geometry of the Cross Section Link at
47 * the end of the road marker.
48 * @param beginWidth Length; start width, positioned <i>symmetrically around</i> the lateral start position.
49 * @param endWidth Length; end width, positioned <i>symmetrically around</i> the lateral end position.
50 * @param fixGradualLateralOffset boolean; true if gradualLateralOffset needs to be fixed
51 * @throws OtsGeometryException when creation of the center line or contour geometry fails
52 * @throws NetworkException when id equal to null or not unique
53 */
54 public Stripe(final Type type, final CrossSectionLink parentLink, final Length startCenterPosition,
55 final Length endCenterPosition, final Length beginWidth, final Length endWidth,
56 final boolean fixGradualLateralOffset) throws OtsGeometryException, NetworkException
57 {
58 super(parentLink, UUID.randomUUID().toString(), startCenterPosition, endCenterPosition, beginWidth, endWidth,
59 fixGradualLateralOffset);
60 Throw.whenNull(type, "Type may not be null.");
61 this.type = type;
62 }
63
64 /**
65 * Constructor for constant properties along the length.
66 * @param type Type; strip type defining appearance and default permeability.
67 * @param parentLink CrossSectionLink; Cross Section Link to which the element belongs.
68 * @param lateralCenterPosition Length; the lateral start position compared to the linear geometry of the Cross Section
69 * Link.
70 * @param width Length; start width, positioned <i>symmetrically around</i> the lateral start position.
71 * @throws OtsGeometryException when creation of the center line or contour geometry fails
72 * @throws NetworkException when id equal to null or not unique
73 */
74 public Stripe(final Type type, final CrossSectionLink parentLink, final Length lateralCenterPosition, final Length width)
75 throws OtsGeometryException, NetworkException
76 {
77 this(type, parentLink, lateralCenterPosition, lateralCenterPosition, width, width, false);
78 }
79
80 /**
81 * Constructor for elaborate longitudinal property changes.
82 * @param type Type; strip type defining appearance and default permeability.
83 * @param parentLink CrossSectionLink; Cross Section Link to which the element belongs.
84 * @param crossSectionSlices List<CrossSectionSlice>; The offsets and widths at positions along the line, relative to
85 * the design line of the parent link. If there is just one with and offset, there should just be one element in
86 * the list with Length = 0. If there are more slices, the last one should be at the length of the design line.
87 * If not, a NetworkException is thrown.
88 * @throws OtsGeometryException when creation of the center line or contour geometry fails
89 * @throws NetworkException when id equal to null or not unique
90 */
91 public Stripe(final Type type, final CrossSectionLink parentLink, final List<CrossSectionSlice> crossSectionSlices)
92 throws OtsGeometryException, NetworkException
93 {
94 super(parentLink, UUID.randomUUID().toString(), crossSectionSlices);
95 Throw.whenNull(type, "Type may not be null.");
96 this.type = type;
97 }
98
99 /**
100 * Returns the stripe type.
101 * @return Type; stripe type.
102 */
103 public Type getType()
104 {
105 return this.type;
106 }
107
108 /**
109 * Sets an overruling stripe type. This can be used for e.g. rush-hour lanes, without changing the appearance of the stripe.
110 * Note that custom set permeabilities (addPermeability()) remain active.
111 * @param overruleType Type; overruling stripe type.
112 */
113 public void setOverruleType(final Type overruleType)
114 {
115 this.overruleType = overruleType;
116 }
117
118 /**
119 * Clears the overrule type, after which the normal type will hold.
120 */
121 public void clearOverruleType()
122 {
123 this.overruleType = null;
124 }
125
126 /**
127 * Returns the currently active stripe type.
128 * @return Type; the currently active stripe type.
129 */
130 private Type activeType()
131 {
132 return this.overruleType == null ? this.type : this.overruleType;
133 }
134
135 /** {@inheritDoc} */
136 @Override
137 public final double getZ()
138 {
139 return -0.0002;
140 }
141
142 /**
143 * Add lateral permeability for a GTU type in the direction of the design line of the overarching CrossSectionLink. Add NONE
144 * to prevent lane changes relative to the stripe type. Add LEFT or RIGHT, or both in two calls, to enable lane changes
145 * relative to the stripe type.
146 * @param gtuType GtuType; GTU type to add permeability for.
147 * @param lateralDirection LateralDirectionality; direction to add compared to the direction of the design line.
148 */
149 public void addPermeability(final GtuType gtuType, final LateralDirectionality lateralDirection)
150 {
151 if (!this.permeabilityMap.containsKey(gtuType))
152 {
153 this.permeabilityMap.put(gtuType, new LinkedHashSet<LateralDirectionality>(2));
154 }
155 this.permeabilityMap.get(gtuType).add(lateralDirection);
156 }
157
158 /**
159 * Returns whether the given GTU type is allowed to cross the line in the given lateral direction.
160 * @param gtuType GtuType; GTU type to look for.
161 * @param lateralDirection LateralDirectionality; direction to look for (LEFT or RIGHT) compared to the direction of the
162 * design line.
163 * @return whether the road marker is permeable for the GTU type.
164 */
165 public final boolean isPermeable(final GtuType gtuType, final LateralDirectionality lateralDirection)
166 {
167 Throw.when(lateralDirection.isNone(), RuntimeException.class,
168 "May not request NONE lateral direction for permeability.");
169 for (GtuType testGtuType = gtuType; null != testGtuType; testGtuType = testGtuType.getParent())
170 {
171 Set<LateralDirectionality> set = this.permeabilityMap.get(testGtuType);
172 if (null != set)
173 {
174 return set.contains(lateralDirection);
175 }
176 }
177 return lateralDirection.isLeft() ? activeType().left() : activeType().right;
178 }
179
180 /**
181 * Defines the visible type of the stripe, and the standard permeability that pertains to it.
182 * <p>
183 * Copyright (c) 2022-2023 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
184 * <br>
185 * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
186 * </p>
187 * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
188 * @author <a href="https://tudelft.nl/staff/p.knoppers-1">Peter Knoppers</a>
189 * @author <a href="https://dittlab.tudelft.nl">Wouter Schakel</a>
190 */
191 public enum Type
192 {
193 /** Single solid line. */
194 SOLID(false, false),
195
196 /** Line |¦ allow to go to left, but not to right. */
197 LEFT(true, false),
198
199 /** Line ¦| allow to go to right, but not to left. */
200 RIGHT(false, true),
201
202 /** Dashes ¦ allow to cross in both directions. */
203 DASHED(true, true),
204
205 /** Double solid line ||, don't cross. */
206 DOUBLE(false, false),
207
208 /** Block : allow to cross in both directions. */
209 BLOCK(true, true);
210
211 /** Left permeable. */
212 private final boolean left;
213
214 /** Right permeable. */
215 private final boolean right;
216
217 /**
218 * Constructor setting permeability.
219 * @param left boolean; left permeability.
220 * @param right boolean; right permeability.
221 */
222 Type(final boolean left, final boolean right)
223 {
224 this.left = left;
225 this.right = right;
226 }
227
228 /**
229 * Returns the left permeability.
230 * @return boolean; left permeability.
231 */
232 public boolean left()
233 {
234 return this.left;
235 }
236
237 /**
238 * Returns the right permeability.
239 * @return boolean; right permeability.
240 */
241 public boolean right()
242 {
243 return this.right;
244 }
245 }
246
247 }