View Javadoc
1   package org.opentrafficsim.road.network.lane;
2   
3   import java.io.Serializable;
4   import java.util.ArrayList;
5   import java.util.HashMap;
6   import java.util.List;
7   import java.util.Map;
8   
9   import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
10  import org.opentrafficsim.core.geometry.OTSLine3D;
11  import org.opentrafficsim.core.gtu.GTUType;
12  import org.opentrafficsim.core.network.LinkType;
13  import org.opentrafficsim.core.network.LongitudinalDirectionality;
14  import org.opentrafficsim.core.network.Network;
15  import org.opentrafficsim.core.network.NetworkException;
16  import org.opentrafficsim.core.network.Node;
17  import org.opentrafficsim.core.network.OTSLink;
18  import org.opentrafficsim.core.network.OTSNode;
19  import org.opentrafficsim.road.network.lane.changing.LaneKeepingPolicy;
20  
21  import nl.tudelft.simulation.event.EventType;
22  
23  /**
24   * A CrossSectionLink is a link with lanes where GTUs can possibly switch between lanes.
25   * <p>
26   * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
27   * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
28   * <p>
29   * $LastChangedDate: 2015-09-16 19:20:07 +0200 (Wed, 16 Sep 2015) $, @version $Revision: 1405 $, by $Author: averbraeck $,
30   * initial version Aug 19, 2014 <br>
31   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
32   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
33   * @author <a href="http://www.citg.tudelft.nl">Guus Tamminga</a>
34   */
35  public class CrossSectionLink extends OTSLink implements Serializable
36  {
37      /** */
38      private static final long serialVersionUID = 20141015L;
39  
40      /** List of cross-section elements. */
41      private final List<CrossSectionElement> crossSectionElementList = new ArrayList<>();
42  
43      /** List of lanes. */
44      private final List<Lane> lanes = new ArrayList<>();
45  
46      /** The policy to generally keep left, keep right, or keep lane. */
47      private final LaneKeepingPolicy laneKeepingPolicy;
48  
49      /** Priority. */
50      // TODO per GTUDirectionality / LongitudinalDirectionality?
51      private Priority priority = Priority.NONE;
52  
53      /**
54       * The (regular, not timed) event type for pub/sub indicating the addition of a Lane to a CrossSectionLink. <br>
55       * Payload: Object[] { String networkId, String linkId, String LaneId, Lane lane, int laneNumber } <br>
56       * TODO work in a different way with lane numbers to align to standard lane numbering.
57       */
58      public static final EventType LANE_ADD_EVENT = new EventType("LANE.ADD");
59  
60      /**
61       * The (regular, not timed) event type for pub/sub indicating the removal of a Lane from a CrossSectionLink. <br>
62       * Payload: Object[] { String networkId, String linkId, String LaneId } <br>
63       * TODO allow for the removal of a Lane; currently this is not possible.
64       */
65      public static final EventType LANE_REMOVE_EVENT = new EventType("LANE.REMOVE");
66  
67      /**
68       * Construction of a cross section link.
69       * @param network Network; the network
70       * @param id String; the link id.
71       * @param startNode OTSNode; the start node (directional).
72       * @param endNode OTSNode; the end node (directional).
73       * @param linkType LinkType; the link type
74       * @param designLine OTSLine3D; the design line of the Link
75       * @param simulator the simulator on which events can be scheduled
76       * @param directionalityMap Map&lt;GTUType, LongitudinalDirectionality&gt;; the directions (FORWARD, BACKWARD, BOTH, NONE)
77       *            that various GTUtypes can traverse this link
78       * @param laneKeepingPolicy LaneKeepingPolicy; the policy to generally keep left, keep right, or keep lane
79       * @throws NetworkException if link already exists in the network, if name of the link is not unique, or if the start node
80       *             or the end node of the link are not registered in the network.
81       */
82      @SuppressWarnings("checkstyle:parameternumber")
83      public CrossSectionLink(final Network network, final String id, final Node startNode, final Node endNode,
84              final LinkType linkType, final OTSLine3D designLine, final OTSSimulatorInterface simulator,
85              final Map<GTUType, LongitudinalDirectionality> directionalityMap, final LaneKeepingPolicy laneKeepingPolicy)
86              throws NetworkException
87      {
88          super(network, id, startNode, endNode, linkType, designLine, simulator, directionalityMap);
89          this.laneKeepingPolicy = laneKeepingPolicy;
90      }
91  
92      /**
93       * Construction of a link, with a general directionality for GTUType.ALL. Other directionalities can be added with the
94       * method addDirectionality(...) later.
95       * @param network Network; the network
96       * @param id String; the link id.
97       * @param startNode OTSnode; the start node (directional).
98       * @param endNode OTSNode; the end node (directional).
99       * @param linkType LinkType; the link type
100      * @param designLine OTSLine3D; the design line of the Link
101      * @param simulator the simulator on which events can be scheduled
102      * @param directionality LongitudinalDirectionality; the default directionality for all GTUs
103      * @param laneKeepingPolicy LaneKeepingPolicy; the policy to generally keep left, keep right, or keep lane
104      * @throws NetworkException if link already exists in the network, if name of the link is not unique, or if the start node
105      *             or the end node of the link are not registered in the network.
106      */
107     @SuppressWarnings("checkstyle:parameternumber")
108     public CrossSectionLink(final Network network, final String id, final Node startNode, final Node endNode,
109             final LinkType linkType, final OTSLine3D designLine, final OTSSimulatorInterface simulator,
110             final LongitudinalDirectionality directionality, final LaneKeepingPolicy laneKeepingPolicy) throws NetworkException
111     {
112         super(network, id, startNode, endNode, linkType, designLine, simulator, directionality);
113         this.laneKeepingPolicy = laneKeepingPolicy;
114     }
115 
116     /**
117      * Construction of a link, on which no traffic is allowed after construction of the link. Directionality for GTUTypes can be
118      * added with the method addDirectionality(...) later.
119      * @param network Network; the network
120      * @param id String; the link id.
121      * @param startNode OTSNode; the start node (directional).
122      * @param endNode OTSNode; the end node (directional).
123      * @param linkType LinkType; the link type
124      * @param designLine OTSLine3D; the design line of the Link
125      * @param simulator the simulator on which events can be scheduled
126      * @param laneKeepingPolicy LaneKeepingPolicy; the policy to generally keep left, keep right, or keep lane
127      * @throws NetworkException if link already exists in the network, if name of the link is not unique, or if the start node
128      *             or the end node of the link are not registered in the network.
129      */
130     @SuppressWarnings("checkstyle:parameternumber")
131     public CrossSectionLink(final Network network, final String id, final OTSNode startNode, final OTSNode endNode,
132             final LinkType linkType, final OTSLine3D designLine, final OTSSimulatorInterface simulator,
133             final LaneKeepingPolicy laneKeepingPolicy) throws NetworkException
134     {
135         this(network, id, startNode, endNode, linkType, designLine, simulator,
136                 new HashMap<GTUType, LongitudinalDirectionality>(), laneKeepingPolicy);
137     }
138 
139     /**
140      * Clone a CrossSectionLink for a new network.
141      * @param newNetwork the new network to which the clone belongs
142      * @param newSimulator the new simulator for this network
143      * @param animation whether to (re)create animation or not
144      * @param link the link to clone from
145      * @throws NetworkException if link already exists in the network, if name of the link is not unique, or if the start node
146      *             or the end node of the link are not registered in the network.
147      */
148     protected CrossSectionLink(final Network newNetwork, final OTSSimulatorInterface newSimulator, final boolean animation,
149             final CrossSectionLink link) throws NetworkException
150     {
151         super(newNetwork, newSimulator, animation, link);
152         this.laneKeepingPolicy = link.laneKeepingPolicy;
153         for (CrossSectionElement cse : link.crossSectionElementList)
154         {
155             cse.clone(this, newSimulator, animation);
156             // the CrossSectionElement will add itself to the Link (OTS-237)
157         }
158     }
159 
160     /**
161      * Add a cross section element at the end of the list. <br>
162      * <b>Note:</b> LEFT is seen as a positive lateral direction, RIGHT as a negative lateral direction.
163      * @param cse CrossSectionElement; the cross section element to add.
164      */
165     protected final void addCrossSectionElement(final CrossSectionElement cse)
166     {
167         this.crossSectionElementList.add(cse);
168         if (cse instanceof Lane)
169         {
170             this.lanes.add((Lane) cse);
171             fireEvent(LANE_ADD_EVENT,
172                     new Object[] { getNetwork().getId(), getId(), cse.getId(), (Lane) cse, this.lanes.indexOf(cse) });
173         }
174     }
175 
176     /**
177      * Retrieve a safe copy of the cross section element list.
178      * @return List&lt;CrossSectionElement&gt;; the cross section element list.
179      */
180     public final List<CrossSectionElement> getCrossSectionElementList()
181     {
182         return this.crossSectionElementList == null ? new ArrayList<>() : new ArrayList<>(this.crossSectionElementList);
183     }
184 
185     /**
186      * Retrieve the lane keeping policy.
187      * @return LaneKeepingPolicy; the lane keeping policy on this CrossSectionLink
188      */
189     public final LaneKeepingPolicy getLaneKeepingPolicy()
190     {
191         return this.laneKeepingPolicy;
192     }
193 
194     /**
195      * Find a cross section element with a specified id.
196      * @param id String; the id to search for
197      * @return CrossSectionElement; the cross section element with the given id, or null if not found
198      */
199     public final CrossSectionElement getCrossSectionElement(final String id)
200     {
201         for (CrossSectionElement cse : this.crossSectionElementList)
202         {
203             if (cse.getId().equals(id))
204             {
205                 return cse;
206             }
207         }
208         return null;
209     }
210 
211     /**
212      * Return a safe copy of the list of lanes of this CrossSectionLink.
213      * @return List&lt;Lane&gt;; the list of lanes.
214      */
215     public final List<Lane> getLanes()
216     {
217         return this.lanes == null ? new ArrayList<>() : new ArrayList<>(this.lanes);
218     }
219 
220     /**
221      * @return priority.
222      */
223     public final Priority getPriority()
224     {
225         return this.priority;
226     }
227 
228     /**
229      * @param priority set priority.
230      */
231     public final void setPriority(final Priority priority)
232     {
233         this.priority = priority;
234     }
235 
236     /** {@inheritDoc} */
237     @Override
238     public final String toString()
239     {
240         return "CrossSectionLink [crossSectionElementList=" + this.crossSectionElementList + ", lanes=" + this.lanes
241                 + ", laneKeepingPolicy=" + this.laneKeepingPolicy + "]";
242     }
243 
244     /** {@inheritDoc} */
245     @Override
246     @SuppressWarnings("checkstyle:designforextension")
247     public CrossSectionLink clone(final Network newNetwork, final OTSSimulatorInterface newSimulator, final boolean animation)
248             throws NetworkException
249     {
250         return new CrossSectionLink(newNetwork, newSimulator, animation, this);
251     }
252 
253     /**
254      * Priority of a link.
255      * <p>
256      * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
257      * <br>
258      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
259      * <p>
260      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 12 dec. 2016 <br>
261      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
262      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
263      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
264      */
265     public enum Priority
266     {
267         /** Traffic has priority. */
268         PRIORITY,
269 
270         /** No priority. */
271         NONE,
272 
273         /** Need to stop. */
274         STOP,
275 
276         /** Priority according to all-stop rules. */
277         ALL_STOP;
278 
279         /**
280          * Returns whether this is priority.
281          * @return whether this is priority
282          */
283         public boolean isPriority()
284         {
285             return this.equals(PRIORITY);
286         }
287 
288         /**
289          * Returns whether this is none.
290          * @return whether this is none
291          */
292         public boolean isNone()
293         {
294             return this.equals(NONE);
295         }
296 
297         /**
298          * Returns whether this is stop.
299          * @return whether this is stop
300          */
301         public boolean isStop()
302         {
303             return this.equals(STOP);
304         }
305 
306         /**
307          * Returns whether this is all-stop.
308          * @return whether this is all-stop
309          */
310         public boolean isAllStop()
311         {
312             return this.equals(ALL_STOP);
313         }
314 
315     }
316 
317 }