View Javadoc
1   package org.opentrafficsim.road.network.lane;
2   
3   import java.util.List;
4   
5   import org.djunits.value.vdouble.scalar.Length;
6   import org.djutils.draw.line.PolyLine2d;
7   import org.djutils.exceptions.Throw;
8   import org.opentrafficsim.base.StripeElement;
9   import org.opentrafficsim.base.StripeElement.StripeLateralSync;
10  import org.opentrafficsim.base.geometry.DirectionalPolyLine;
11  import org.opentrafficsim.core.gtu.GtuType;
12  import org.opentrafficsim.core.network.LateralDirectionality;
13  import org.opentrafficsim.road.network.lane.StripeData.StripePhaseSync;
14  
15  /**
16   * Stripe road marking. This class only contains functional information. There is no information on how to draw the stripe, i.e.
17   * no color and no information on dashes. The stripe types has information on this, but this only serves as a default towards
18   * classes that do draw a stripe.
19   * <p>
20   * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
21   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
22   * </p>
23   * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
24   * @author <a href="https://github.com/peter-knoppers">Peter Knoppers</a>
25   * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
26   */
27  public class Stripe extends CrossSectionElement
28  {
29      /** */
30      private static final long serialVersionUID = 20141025L;
31  
32      /** Stripe data. */
33      private final StripeData data;
34  
35      /** Longitudinal offset of dashes. */
36      private Length dashOffset = Length.ZERO;
37  
38      /** Link reference line. */
39      private PolyLine2d linkReferenceLine = null;
40  
41      /**
42       * Constructor specifying geometry. Permeability is set according to the stripe type default.
43       * @param id id
44       * @param data stripe data, including permeability, stripe elements and dash synchronization
45       * @param link link
46       * @param geometry geometry
47       */
48      public Stripe(final String id, final StripeData data, final CrossSectionLink link, final CrossSectionGeometry geometry)
49      {
50          super(link, id, geometry);
51          Throw.whenNull(data, "Type may not be null.");
52          this.data = data;
53      }
54  
55      /**
56       * Add lateral permeability for a GTU type. This overrules overall stripe permeability. Add NONE to prevent lane changes.
57       * Add both LEFT and RIGHT in two calls, to enable lane changes. Add LEFT or RIGHT to enable one direction while prohibiting
58       * the other.
59       * @param gtuType GTU type to add permeability for
60       * @param lateralDirection direction to add compared to the direction of the design line
61       */
62      public void addPermeability(final GtuType gtuType, final LateralDirectionality lateralDirection)
63      {
64          this.data.addPermeability(gtuType, lateralDirection);
65      }
66  
67      /**
68       * Returns whether the given GTU type is allowed to cross the line in the given lateral direction.
69       * @param gtuType GTU type to look for.
70       * @param lateralDirection direction to look for (LEFT or RIGHT) compared to the direction of the design line.
71       * @return whether the road marker is permeable for the GTU type.
72       */
73      public final boolean isPermeable(final GtuType gtuType, final LateralDirectionality lateralDirection)
74      {
75          return this.data.isPermeable(gtuType, lateralDirection);
76      }
77  
78      /**
79       * Returns the elements.
80       * @return elements
81       */
82      public List<StripeElement> getElements()
83      {
84          return this.data.getElements();
85      }
86  
87      /**
88       * Sets the dash offset.
89       * @param dashOffset dash offset
90       */
91      public void setDashOffset(final Length dashOffset)
92      {
93          this.dashOffset = dashOffset;
94      }
95  
96      /**
97       * Returns the dash offset.
98       * @return dash offset
99       */
100     public Length getDashOffset()
101     {
102         return this.dashOffset;
103     }
104 
105     /**
106      * Sets the lateral synchronization.
107      * @param lateralSync lateral synchronization
108      */
109     public void setLateralSync(final StripeLateralSync lateralSync)
110     {
111         this.data.setLateralSync(lateralSync);
112     }
113 
114     /**
115      * Returns the lateral synchronization.
116      * @return lateral synchronization
117      */
118     public StripeLateralSync getLateralSync()
119     {
120         return this.data.getLateralSync();
121     }
122 
123     /**
124      * Sets the phase synchronization.
125      * @param phaseSync phase synchronization
126      */
127     public void setPhaseSync(final StripePhaseSync phaseSync)
128     {
129         this.data.setPhaseSync(phaseSync);
130     }
131 
132     /**
133      * Returns the phase synchronization.
134      * @return phase synchronization
135      */
136     public StripePhaseSync getPhaseSync()
137     {
138         return this.data.getPhaseSync();
139     }
140 
141     /**
142      * Returns the period of the common dash pattern.
143      * @return period of the common dash pattern
144      */
145     public double getPeriod()
146     {
147         return this.data.getPeriod();
148     }
149 
150     /**
151      * Return link reference line, which is the line halfway between the left-most and right-most stripes.
152      * @return link reference line
153      */
154     public PolyLine2d getLinkReferenceLine()
155     {
156         if (this.linkReferenceLine == null)
157         {
158             PolyLine2d linkLine = getLink().getDesignLine();
159             double offsetMin0 = Double.POSITIVE_INFINITY;
160             double offsetMax0 = Double.NEGATIVE_INFINITY;
161             double offsetMin1 = Double.POSITIVE_INFINITY;
162             double offsetMax1 = Double.NEGATIVE_INFINITY;
163             for (CrossSectionElement element : getLink().getCrossSectionElementList())
164             {
165                 if (element instanceof Stripe)
166                 {
167                     offsetMin0 = Math.min(offsetMin0, element.getOffsetAtBegin().si);
168                     offsetMax0 = Math.max(offsetMax0, element.getOffsetAtBegin().si);
169                     offsetMin1 = Math.min(offsetMin1, element.getOffsetAtEnd().si);
170                     offsetMax1 = Math.max(offsetMax1, element.getOffsetAtEnd().si);
171                 }
172             }
173             DirectionalPolyLine directionalLine = new DirectionalPolyLine(linkLine, getLink().getStartNode().getHeading(),
174                     getLink().getEndNode().getHeading());
175             PolyLine2d start = directionalLine.directionalOffsetLine(.5 * (offsetMin0 + offsetMax0));
176             PolyLine2d end = directionalLine.directionalOffsetLine(.5 * (offsetMin1 + offsetMax1));
177             this.linkReferenceLine = start.transitionLine(end, (f) -> f);
178         }
179         return this.linkReferenceLine;
180     }
181 
182     @Override
183     public String toString()
184     {
185         return "Stripe [id=" + this.getFullId() + "]";
186     }
187 
188 }