View Javadoc
1   package org.opentrafficsim.core.network;
2   
3   import java.io.Serializable;
4   import java.util.LinkedHashSet;
5   import java.util.Set;
6   
7   import javax.media.j3d.Bounds;
8   
9   import org.djunits.value.vdouble.scalar.Length;
10  import org.djutils.exceptions.Throw;
11  import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
12  import org.opentrafficsim.core.geometry.OTSLine3D;
13  import org.opentrafficsim.core.gtu.GTU;
14  import org.opentrafficsim.core.gtu.GTUType;
15  
16  import nl.tudelft.simulation.dsol.animation.Locatable;
17  import nl.tudelft.simulation.event.EventProducer;
18  import nl.tudelft.simulation.language.d3.DirectedPoint;
19  
20  /**
21   * A standard implementation of a link between two OTSNodes.
22   * <p>
23   * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
24   * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
25   * <p>
26   * $LastChangedDate: 2019-04-11 12:30:43 +0200 (Thu, 11 Apr 2019) $, @version $Revision: 5255 $, by $Author: pknoppers $,
27   * initial version Aug 19, 2014 <br>
28   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
29   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
30   */
31  public class OTSLink extends EventProducer implements Link, Serializable, Locatable
32  {
33      /** */
34      private static final long serialVersionUID = 20150101L;
35  
36      /** the Network. */
37      private final Network network;
38  
39      /** Link id. */
40      private final String id;
41  
42      /** Start node (directional). */
43      private final Node startNode;
44  
45      /** End node (directional). */
46      private final Node endNode;
47  
48      /** Link type to indicate compatibility with GTU types. */
49      private final LinkType linkType;
50  
51      /** Design line of the link. */
52      private final OTSLine3D designLine;
53  
54      /** The simulator on which events can be scheduled. */
55      private final OTSSimulatorInterface simulator;
56  
57      /** The GTUs on this Link. */
58      private final Set<GTU> gtus = new LinkedHashSet<>();
59  
60      /**
61       * Construct a new link.
62       * @param id String; the link id
63       * @param network Network; the network to which the link belongs
64       * @param startNode Node; start node (directional)
65       * @param endNode Node; end node (directional)
66       * @param linkType LinkType; Link type to indicate compatibility with GTU types
67       * @param designLine OTSLine3D; the OTSLine3D design line of the Link
68       * @param simulator OTSSimulatorInterface; the simulator on which events can be scheduled
69       * @throws NetworkException if link already exists in the network, if name of the link is not unique, or if the start node
70       *             or the end node of the link are not registered in the network.
71       */
72      @SuppressWarnings("checkstyle:parameternumber")
73      public OTSLink(final Network network, final String id, final Node startNode, final Node endNode, final LinkType linkType,
74              final OTSLine3D designLine, final OTSSimulatorInterface simulator) throws NetworkException
75      {
76          Throw.whenNull(network, "network cannot be null");
77          Throw.whenNull(id, "id cannot be null");
78          Throw.whenNull(startNode, "startNode cannot be null (link %s)", id);
79          Throw.whenNull(endNode, "endNode cannot be null (link %s)", id);
80          Throw.whenNull(linkType, "linkType cannot be null (link %s)", id);
81          Throw.whenNull(designLine, "designLine cannot be null (link %s)", id);
82          Throw.whenNull(simulator, "simulator cannot be null");
83  
84          this.network = network;
85          this.id = id;
86          this.startNode = startNode;
87          this.endNode = endNode;
88          this.linkType = linkType;
89          this.startNode.addLink(this);
90          this.endNode.addLink(this);
91          this.designLine = designLine;
92          this.simulator = simulator;
93          this.network.addLink(this);
94      }
95  
96      /**
97       * Clone a link for a new network.
98       * @param newNetwork Network; the new network to which the clone belongs
99       * @param newSimulator OTSSimulatorInterface; the new simulator for this network
100      * @param link OTSLink; the link to clone from
101      * @throws NetworkException if link already exists in the network, if name of the link is not unique, or if the start node
102      *             or the end node of the link are not registered in the network.
103      */
104     protected OTSLink(final Network newNetwork, final OTSSimulatorInterface newSimulator, final OTSLink link)
105             throws NetworkException
106     {
107         this(newNetwork, link.id, newNetwork.getNode(link.startNode.getId()), newNetwork.getNode(link.endNode.getId()),
108                 link.linkType, link.designLine, newSimulator);
109     }
110 
111     /** {@inheritDoc} */
112     @Override
113     public final LongitudinalDirectionality getDirectionality(final GTUType gtuType)
114     {
115         return this.getLinkType().getDirectionality(gtuType, true);
116     }
117 
118     /** {@inheritDoc} */
119     @Override
120     public final void addGTU(final GTU gtu)
121     {
122         if (!this.gtus.contains(gtu))
123         {
124             this.gtus.add(gtu);
125             fireTimedEvent(Link.GTU_ADD_EVENT, new Object[] {gtu.getId(), gtu, this.gtus.size()},
126                     gtu.getSimulator().getSimulatorTime());
127         }
128     }
129 
130     /** {@inheritDoc} */
131     @Override
132     public final void removeGTU(final GTU gtu)
133     {
134         if (this.gtus.contains(gtu))
135         {
136             this.gtus.remove(gtu);
137             fireTimedEvent(Link.GTU_REMOVE_EVENT, new Object[] {gtu.getId(), gtu, this.gtus.size()},
138                     gtu.getSimulator().getSimulatorTime());
139         }
140     }
141 
142     /** {@inheritDoc} */
143     @Override
144     public final Set<GTU> getGTUs()
145     {
146         return new LinkedHashSet<>(this.gtus);
147     }
148 
149     /** {@inheritDoc} */
150     @Override
151     public final int getGTUCount()
152     {
153         return this.gtus.size();
154     }
155 
156     /** {@inheritDoc} */
157     @Override
158     public Network getNetwork()
159     {
160         return this.network;
161     }
162 
163     /** {@inheritDoc} */
164     @Override
165     public final String getId()
166     {
167         return this.id;
168     }
169 
170     /** {@inheritDoc} */
171     @Override
172     public final Node getStartNode()
173     {
174         return this.startNode;
175     }
176 
177     /** {@inheritDoc} */
178     @Override
179     public final Node getEndNode()
180     {
181         return this.endNode;
182     }
183 
184     /** {@inheritDoc} */
185     @Override
186     public final LinkType getLinkType()
187     {
188         return this.linkType;
189     }
190 
191     /** {@inheritDoc} */
192     @Override
193     public final OTSLine3D getDesignLine()
194     {
195         return this.designLine;
196     }
197 
198     /** {@inheritDoc} */
199     @Override
200     public final OTSSimulatorInterface getSimulator()
201     {
202         return this.simulator;
203     }
204 
205     /** {@inheritDoc} */
206     @Override
207     public final Length getLength()
208     {
209         return this.designLine.getLength();
210     }
211 
212     /** the location with 0.01 m extra height. */
213     private DirectedPoint zLocation = null;
214 
215     /** {@inheritDoc} */
216     @Override
217     @SuppressWarnings("checkstyle:designforextension")
218     public DirectedPoint getLocation()
219     {
220         if (this.zLocation == null)
221         {
222             DirectedPoint p = this.designLine.getLocation();
223             this.zLocation = new DirectedPoint(p.x, p.y, p.z + 0.01, p.getRotX(), p.getRotY(), p.getRotZ());
224         }
225         return this.zLocation;
226     }
227 
228     /** {@inheritDoc} */
229     @Override
230     @SuppressWarnings("checkstyle:designforextension")
231     public Bounds getBounds()
232     {
233         return this.designLine.getBounds();
234     }
235 
236     /** {@inheritDoc} */
237     @Override
238     @SuppressWarnings("checkstyle:designforextension")
239     public String toString()
240     {
241         return this.id.toString();
242     }
243 
244     /** {@inheritDoc} */
245     @Override
246     @SuppressWarnings("checkstyle:designforextension")
247     public int hashCode()
248     {
249         final int prime = 31;
250         int result = 1;
251         result = prime * result + ((this.endNode == null) ? 0 : this.endNode.hashCode());
252         result = prime * result + ((this.id == null) ? 0 : this.id.hashCode());
253         result = prime * result + ((this.linkType == null) ? 0 : this.linkType.hashCode());
254         result = prime * result + ((this.startNode == null) ? 0 : this.startNode.hashCode());
255         return result;
256     }
257 
258     /** {@inheritDoc} */
259     @Override
260     @SuppressWarnings({"checkstyle:designforextension", "checkstyle:needbraces"})
261     public boolean equals(final Object obj)
262     {
263         if (this == obj)
264             return true;
265         if (obj == null)
266             return false;
267         if (getClass() != obj.getClass())
268             return false;
269         OTSLink other = (OTSLink) obj;
270         if (this.endNode == null)
271         {
272             if (other.endNode != null)
273                 return false;
274         }
275         else if (!this.endNode.equals(other.endNode))
276             return false;
277         if (this.id == null)
278         {
279             if (other.id != null)
280                 return false;
281         }
282         else if (!this.id.equals(other.id))
283             return false;
284         if (this.linkType == null)
285         {
286             if (other.linkType != null)
287                 return false;
288         }
289         else if (!this.linkType.equals(other.linkType))
290             return false;
291         if (this.startNode == null)
292         {
293             if (other.startNode != null)
294                 return false;
295         }
296         else if (!this.startNode.equals(other.startNode))
297             return false;
298         return true;
299     }
300 
301     /**
302      * Clone the OTSLink for e.g., copying a network.
303      * @param newNetwork Network; the new network to which the clone belongs
304      * @param newSimulator OTSSimulatorInterface; the new simulator for this network
305      * @return a clone of this object
306      * @throws NetworkException in case the cloning fails
307      */
308     @SuppressWarnings("checkstyle:designforextension")
309     public OTSLink clone(final Network newNetwork, final OTSSimulatorInterface newSimulator) throws NetworkException
310     {
311         return new OTSLink(newNetwork, newSimulator, this);
312     }
313 }