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-2017 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<GTUType, LongitudinalDirectionality>; 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<CrossSectionElement>; 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<Lane>; 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-2017 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 /** Priority at bus stop, i.e. bus has right of way if it wants to leave the bus stop. */
280 BUS_STOP;
281
282 /**
283 * Returns whether this is priority.
284 * @return whether this is priority
285 */
286 public boolean isPriority()
287 {
288 return this.equals(PRIORITY);
289 }
290
291 /**
292 * Returns whether this is none.
293 * @return whether this is none
294 */
295 public boolean isNone()
296 {
297 return this.equals(NONE);
298 }
299
300 /**
301 * Returns whether this is stop.
302 * @return whether this is stop
303 */
304 public boolean isStop()
305 {
306 return this.equals(STOP);
307 }
308
309 /**
310 * Returns whether this is all-stop.
311 * @return whether this is all-stop
312 */
313 public boolean isAllStop()
314 {
315 return this.equals(ALL_STOP);
316 }
317
318 /**
319 * Returns whether this is bus stop.
320 * @return whether this is bus stop
321 */
322 public boolean isBusStop()
323 {
324 return this.equals(BUS_STOP);
325 }
326
327 }
328
329 }