View Javadoc
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 &lt;i&gt;symmetrically around&lt;/i&gt; the lateral start position.
49       * @param endWidth Length; end width, positioned &lt;i&gt;symmetrically around&lt;/i&gt; 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 &lt;i&gt;symmetrically around&lt;/i&gt; 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&lt;CrossSectionSlice&gt;; 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 }