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 /**
50 * The (regular, not timed) event type for pub/sub indicating the addition of a Lane to a CrossSectionLink. <br>
51 * Payload: Object[] { String networkId, String linkId, String LaneId, Lane lane, int laneNumber } <br>
52 * TODO work in a different way with lane numbers to align to standard lane numbering.
53 */
54 public static final EventType LANE_ADD_EVENT = new EventType("LANE.ADD");
55
56 /**
57 * The (regular, not timed) event type for pub/sub indicating the removal of a Lane from a CrossSectionLink. <br>
58 * Payload: Object[] { String networkId, String linkId, String LaneId } <br>
59 * TODO allow for the removal of a Lane; currently this is not possible.
60 */
61 public static final EventType LANE_REMOVE_EVENT = new EventType("LANE.REMOVE");
62
63 /**
64 * Construction of a cross section link.
65 * @param network Network; the network
66 * @param id String; the link id.
67 * @param startNode OTSNode; the start node (directional).
68 * @param endNode OTSNode; the end node (directional).
69 * @param linkType LinkType; the link type
70 * @param designLine OTSLine3D; the design line of the Link
71 * @param directionalityMap Map<GTUType, LongitudinalDirectionality>; the directions (FORWARD, BACKWARD, BOTH, NONE)
72 * that various GTUtypes can traverse this link
73 * @param laneKeepingPolicy LaneKeepingPolicy; the policy to generally keep left, keep right, or keep lane
74 * @throws NetworkException if link already exists in the network, if name of the link is not unique, or if the start node
75 * or the end node of the link are not registered in the network.
76 */
77 @SuppressWarnings("checkstyle:parameternumber")
78 public CrossSectionLink(final Network network, final String id, final Node startNode, final Node endNode,
79 final LinkType linkType, final OTSLine3D designLine,
80 final Map<GTUType, LongitudinalDirectionality> directionalityMap, final LaneKeepingPolicy laneKeepingPolicy)
81 throws NetworkException
82 {
83 super(network, id, startNode, endNode, linkType, designLine, directionalityMap);
84 this.laneKeepingPolicy = laneKeepingPolicy;
85 }
86
87 /**
88 * Construction of a link, with a general directionality for GTUType.ALL. Other directionalities can be added with the
89 * method addDirectionality(...) later.
90 * @param network Network; the network
91 * @param id String; the link id.
92 * @param startNode OTSnode; the start node (directional).
93 * @param endNode OTSNode; the end node (directional).
94 * @param linkType LinkType; the link type
95 * @param designLine OTSLine3D; the design line of the Link
96 * @param directionality LongitudinalDirectionality; the default directionality for all GTUs
97 * @param laneKeepingPolicy LaneKeepingPolicy; the policy to generally keep left, keep right, or keep lane
98 * @throws NetworkException if link already exists in the network, if name of the link is not unique, or if the start node
99 * or the end node of the link are not registered in the network.
100 */
101 @SuppressWarnings("checkstyle:parameternumber")
102 public CrossSectionLink(final Network network, final String id, final Node startNode, final Node endNode,
103 final LinkType linkType, final OTSLine3D designLine, final LongitudinalDirectionality directionality,
104 final LaneKeepingPolicy laneKeepingPolicy) throws NetworkException
105 {
106 super(network, id, startNode, endNode, linkType, designLine, directionality);
107 this.laneKeepingPolicy = laneKeepingPolicy;
108 }
109
110 /**
111 * Construction of a link, on which no traffic is allowed after construction of the link. Directionality for GTUTypes can be
112 * added with the method addDirectionality(...) later.
113 * @param network Network; the network
114 * @param id String; the link id.
115 * @param startNode OTSNode; the start node (directional).
116 * @param endNode OTSNode; the end node (directional).
117 * @param linkType LinkType; the link type
118 * @param designLine OTSLine3D; the design line of the Link
119 * @param laneKeepingPolicy LaneKeepingPolicy; the policy to generally keep left, keep right, or keep lane
120 * @throws NetworkException if link already exists in the network, if name of the link is not unique, or if the start node
121 * or the end node of the link are not registered in the network.
122 */
123 public CrossSectionLink(final Network network, final String id, final OTSNode startNode, final OTSNode endNode,
124 final LinkType linkType, final OTSLine3D designLine, final LaneKeepingPolicy laneKeepingPolicy)
125 throws NetworkException
126 {
127 this(network, id, startNode, endNode, linkType, designLine, new HashMap<GTUType, LongitudinalDirectionality>(),
128 laneKeepingPolicy);
129 }
130
131 /**
132 * Clone a CrossSectionLink for a new network.
133 * @param newNetwork the new network to which the clone belongs
134 * @param newSimulator the new simulator for this network
135 * @param animation whether to (re)create animation or not
136 * @param link the link to clone from
137 * @throws NetworkException if link already exists in the network, if name of the link is not unique, or if the start node
138 * or the end node of the link are not registered in the network.
139 */
140 protected CrossSectionLink(final Network newNetwork, final OTSSimulatorInterface newSimulator, final boolean animation,
141 final CrossSectionLink link) throws NetworkException
142 {
143 super(newNetwork, newSimulator, animation, link);
144 this.laneKeepingPolicy = link.laneKeepingPolicy;
145 for (CrossSectionElement cse : link.crossSectionElementList)
146 {
147 addCrossSectionElement(cse.clone(this, newSimulator, animation));
148 }
149
150 }
151
152 /**
153 * Add a cross section element at the end of the list. <br>
154 * <b>Note:</b> LEFT is seen as a positive lateral direction, RIGHT as a negative lateral direction.
155 * @param cse CrossSectionElement; the cross section element to add.
156 */
157 protected final void addCrossSectionElement(final CrossSectionElement cse)
158 {
159 this.crossSectionElementList.add(cse);
160 if (cse instanceof Lane)
161 {
162 this.lanes.add((Lane) cse);
163 fireEvent(LANE_ADD_EVENT,
164 new Object[] { getNetwork().getId(), getId(), cse.getId(), (Lane) cse, this.lanes.indexOf(cse) });
165 }
166 }
167
168 /**
169 * Retrieve a safe copy of the cross section element list.
170 * @return List<CrossSectionElement>; the cross section element list.
171 */
172 public final List<CrossSectionElement> getCrossSectionElementList()
173 {
174 return this.crossSectionElementList == null ? new ArrayList<>() : new ArrayList<>(this.crossSectionElementList);
175 }
176
177 /**
178 * Retrieve the lane keeping policy.
179 * @return LaneKeepingPolicy; the lane keeping policy on this CrossSectionLink
180 */
181 public final LaneKeepingPolicy getLaneKeepingPolicy()
182 {
183 return this.laneKeepingPolicy;
184 }
185
186 /**
187 * Find a cross section element with a specified id.
188 * @param id String; the id to search for
189 * @return CrossSectionElement; the cross section element with the given id, or null if not found
190 */
191 public final CrossSectionElement getCrossSectionElement(final String id)
192 {
193 for (CrossSectionElement cse : this.crossSectionElementList)
194 {
195 if (cse.getId().equals(id))
196 {
197 return cse;
198 }
199 }
200 return null;
201 }
202
203 /**
204 * Return a safe copy of the list of lanes of this CrossSectionLink.
205 * @return List<Lane>; the list of lanes.
206 */
207 public final List<Lane> getLanes()
208 {
209 return this.lanes == null ? new ArrayList<>() : new ArrayList<>(this.lanes);
210 }
211
212 /** {@inheritDoc} */
213 @Override
214 public final String toString()
215 {
216 return "CrossSectionLink [crossSectionElementList=" + this.crossSectionElementList + ", lanes=" + this.lanes
217 + ", laneKeepingPolicy=" + this.laneKeepingPolicy + "]";
218 }
219
220 /** {@inheritDoc} */
221 @Override
222 @SuppressWarnings("checkstyle:designforextension")
223 public CrossSectionLink clone(final Network newNetwork, final OTSSimulatorInterface newSimulator, final boolean animation)
224 throws NetworkException
225 {
226 return new CrossSectionLink(newNetwork, newSimulator, animation, this);
227 }
228
229 }