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      /** Stripe data. */
30      private final StripeData data;
31  
32      /** Longitudinal offset of dashes. */
33      private Length dashOffset = Length.ZERO;
34  
35      /** Link reference line. */
36      private PolyLine2d linkReferenceLine = null;
37  
38      /**
39       * Constructor specifying geometry. Permeability is set according to the stripe type default.
40       * @param id id
41       * @param data stripe data, including permeability, stripe elements and dash synchronization
42       * @param link link
43       * @param geometry geometry
44       */
45      public Stripe(final String id, final StripeData data, final CrossSectionLink link, final CrossSectionGeometry geometry)
46      {
47          super(link, id, geometry);
48          Throw.whenNull(data, "Type may not be null.");
49          this.data = data;
50      }
51  
52      /**
53       * Add lateral permeability for a GTU type. This overrules overall stripe permeability. Add NONE to prevent lane changes.
54       * Add both LEFT and RIGHT in two calls, to enable lane changes. Add LEFT or RIGHT to enable one direction while prohibiting
55       * the other.
56       * @param gtuType GTU type to add permeability for
57       * @param lateralDirection direction to add compared to the direction of the design line
58       */
59      public void addPermeability(final GtuType gtuType, final LateralDirectionality lateralDirection)
60      {
61          this.data.addPermeability(gtuType, lateralDirection);
62      }
63  
64      /**
65       * Returns whether the given GTU type is allowed to cross the line in the given lateral direction.
66       * @param gtuType GTU type to look for.
67       * @param lateralDirection direction to look for (LEFT or RIGHT) compared to the direction of the design line.
68       * @return whether the road marker is permeable for the GTU type.
69       */
70      public final boolean isPermeable(final GtuType gtuType, final LateralDirectionality lateralDirection)
71      {
72          return this.data.isPermeable(gtuType, lateralDirection);
73      }
74  
75      /**
76       * Returns the elements.
77       * @return elements
78       */
79      public List<StripeElement> getElements()
80      {
81          return this.data.getElements();
82      }
83  
84      /**
85       * Sets the dash offset.
86       * @param dashOffset dash offset
87       */
88      public void setDashOffset(final Length dashOffset)
89      {
90          this.dashOffset = dashOffset;
91      }
92  
93      /**
94       * Returns the dash offset.
95       * @return dash offset
96       */
97      public Length getDashOffset()
98      {
99          return this.dashOffset;
100     }
101 
102     /**
103      * Sets the lateral synchronization.
104      * @param lateralSync lateral synchronization
105      */
106     public void setLateralSync(final StripeLateralSync lateralSync)
107     {
108         this.data.setLateralSync(lateralSync);
109     }
110 
111     /**
112      * Returns the lateral synchronization.
113      * @return lateral synchronization
114      */
115     public StripeLateralSync getLateralSync()
116     {
117         return this.data.getLateralSync();
118     }
119 
120     /**
121      * Sets the phase synchronization.
122      * @param phaseSync phase synchronization
123      */
124     public void setPhaseSync(final StripePhaseSync phaseSync)
125     {
126         this.data.setPhaseSync(phaseSync);
127     }
128 
129     /**
130      * Returns the phase synchronization.
131      * @return phase synchronization
132      */
133     public StripePhaseSync getPhaseSync()
134     {
135         return this.data.getPhaseSync();
136     }
137 
138     /**
139      * Returns the period of the common dash pattern.
140      * @return period of the common dash pattern
141      */
142     public double getPeriod()
143     {
144         return this.data.getPeriod();
145     }
146 
147     /**
148      * Return link reference line, which is the line halfway between the left-most and right-most stripes.
149      * @return link reference line
150      */
151     public PolyLine2d getLinkReferenceLine()
152     {
153         if (this.linkReferenceLine == null)
154         {
155             PolyLine2d linkLine = getLink().getDesignLine();
156             double offsetMin0 = Double.POSITIVE_INFINITY;
157             double offsetMax0 = Double.NEGATIVE_INFINITY;
158             double offsetMin1 = Double.POSITIVE_INFINITY;
159             double offsetMax1 = Double.NEGATIVE_INFINITY;
160             for (CrossSectionElement element : getLink().getCrossSectionElementList())
161             {
162                 if (element instanceof Stripe)
163                 {
164                     offsetMin0 = Math.min(offsetMin0, element.getOffsetAtBegin().si);
165                     offsetMax0 = Math.max(offsetMax0, element.getOffsetAtBegin().si);
166                     offsetMin1 = Math.min(offsetMin1, element.getOffsetAtEnd().si);
167                     offsetMax1 = Math.max(offsetMax1, element.getOffsetAtEnd().si);
168                 }
169             }
170             DirectionalPolyLine directionalLine = new DirectionalPolyLine(linkLine, getLink().getStartNode().getHeading(),
171                     getLink().getEndNode().getHeading());
172             PolyLine2d start = directionalLine.directionalOffsetLine(.5 * (offsetMin0 + offsetMax0));
173             PolyLine2d end = directionalLine.directionalOffsetLine(.5 * (offsetMin1 + offsetMax1));
174             this.linkReferenceLine = start.transitionLine(end, (f) -> f);
175         }
176         return this.linkReferenceLine;
177     }
178 
179     @Override
180     public String toString()
181     {
182         return "Stripe [id=" + this.getFullId() + "]";
183     }
184 
185 }