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<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-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 }