View Javadoc
1   package org.opentrafficsim.road.network.lane.object;
2   
3   import java.util.LinkedHashSet;
4   import java.util.List;
5   import java.util.Set;
6   
7   import org.djunits.value.vdouble.scalar.Length;
8   import org.djutils.immutablecollections.Immutable;
9   import org.djutils.immutablecollections.ImmutableHashSet;
10  import org.djutils.immutablecollections.ImmutableMap;
11  import org.djutils.immutablecollections.ImmutableSet;
12  import org.opentrafficsim.core.gtu.GTUDirectionality;
13  import org.opentrafficsim.core.gtu.GTUType;
14  import org.opentrafficsim.core.network.LongitudinalDirectionality;
15  import org.opentrafficsim.core.network.NetworkException;
16  import org.opentrafficsim.road.network.lane.CrossSectionElement;
17  import org.opentrafficsim.road.network.lane.Lane;
18  import org.opentrafficsim.road.network.lane.conflict.BusStopConflictRule;
19  import org.opentrafficsim.road.network.lane.conflict.Conflict;
20  
21  import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
22  
23  /**
24   * A bus stop is a location on a lane. The stop has a name, and a set of lines. At a single stop in reality, there may be
25   * different locations where busses stop for different lines. A {@code BusStop} pertains to only one such location. The bus stop
26   * in reality is represented by a shared name over a few {@code BusStop}'s, with different lines. As lines may also be set
27   * dynamically, the name and lines are insufficient to identify a specific {@code BusStop}. Hence there is a fixed unique id per
28   * {@code BusStop}.
29   * <p>
30   * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
31   * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
32   * <p>
33   * @version $Revision$, $LastChangedDate$, by $Author$, initial version 24 jan. 2017 <br>
34   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
35   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
36   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
37   */
38  public class BusStop extends AbstractLaneBasedObject
39  {
40  
41      /** */
42      private static final long serialVersionUID = 20170124L;
43  
44      /** Line numbers. */
45      private final Set<String> lines = new LinkedHashSet<>();
46  
47      /** Stop name. */
48      private final String name;
49  
50      /** Stored conflicts downstream. */
51      private Set<Conflict> conflicts = null;
52  
53      /**
54       * @param id String; id
55       * @param lane Lane; lane
56       * @param longitudinalPosition Length; position
57       * @param name String; name of stop
58       * @param simulator SimulatorInterface.TimeDoubleUnit; the simulator to schedule on
59       * @throws NetworkException when the position on the lane is out of bounds
60       */
61      public BusStop(final String id, final Lane lane, final Length longitudinalPosition, final String name,
62              final SimulatorInterface.TimeDoubleUnit simulator) throws NetworkException
63      {
64          super(id, lane, LongitudinalDirectionality.DIR_PLUS, longitudinalPosition,
65                  LaneBasedObject.makeGeometry(lane, longitudinalPosition), Length.ZERO);
66          this.name = name;
67          
68          init();
69      }
70  
71      /**
72       * Sets the lines.
73       * @param lines Set&lt;String&gt;; lines that stop at this location
74       */
75      public final void setLines(final Set<String> lines)
76      {
77          this.lines.clear();
78          this.lines.addAll(lines);
79      }
80  
81      /**
82       * Returns the lines set.
83       * @return whether the lines belongs to this stop
84       */
85      public final ImmutableSet<String> getLines()
86      {
87          return new ImmutableHashSet<>(this.lines, Immutable.COPY);
88      }
89  
90      /**
91       * Returns the downstream conflicts of the bus stop. Search is only performed over links with BUS_STOP priority.
92       * @return downstream conflicts of the given conflict
93       */
94      public final Set<Conflict> getConflicts()
95      {
96          if (this.conflicts == null)
97          {
98              this.conflicts = new LinkedHashSet<>();
99              Lane lane = getLane();
100             // conflict forces only plus or minus as direction
101             GTUDirectionality dir = getDirection().isForward() ? GTUDirectionality.DIR_PLUS : GTUDirectionality.DIR_MINUS;
102             Length position = getLongitudinalPosition();
103             while (lane != null)
104             {
105                 List<LaneBasedObject> objects = lane.getObjectAhead(position, dir);
106                 while (objects != null)
107                 {
108                     for (LaneBasedObject object : objects)
109                     {
110                         if (object instanceof Conflict)
111                         {
112                             Conflict./../../../../org/opentrafficsim/road/network/lane/conflict/Conflict.html#Conflict">Conflict conflict = (Conflict) object;
113                             if (conflict.getConflictRule() instanceof BusStopConflictRule)
114                             {
115                                 this.conflicts.add(conflict);
116                             }
117                         }
118                     }
119                     objects = lane.getObjectAhead(objects.get(0).getLongitudinalPosition(), dir);
120                 }
121                 ImmutableMap<Lane, GTUDirectionality> downstreamLanes =
122                         lane.downstreamLanes(dir, lane.getNetwork().getGtuType(GTUType.DEFAULTS.BUS));
123                 int numLanes = 0;
124                 for (Lane nextLane : downstreamLanes.keySet())
125                 {
126                     if (nextLane.getParentLink().getPriority().isBusStop())
127                     {
128                         numLanes++;
129                         lane = nextLane;
130                         dir = downstreamLanes.get(lane);
131                         position = dir.isPlus() ? Length.ZERO : lane.getLength();
132                     }
133                 }
134                 if (numLanes != 1)
135                 {
136                     lane = null;
137                 }
138             }
139         }
140         return this.conflicts;
141     }
142 
143     /** {@inheritDoc} */
144     @Override
145     public final int hashCode()
146     {
147         final int prime = 31;
148         int result = 1;
149         result = prime * result + this.getId().hashCode();
150         return result;
151     }
152 
153     /** {@inheritDoc} */
154     @Override
155     public final boolean equals(final Object obj)
156     {
157         if (this == obj)
158         {
159             return true;
160         }
161         if (obj == null)
162         {
163             return false;
164         }
165         if (getClass() != obj.getClass())
166         {
167             return false;
168         }
169         BusStop../../../../../../org/opentrafficsim/road/network/lane/object/BusStop.html#BusStop">BusStop other = (BusStop) obj;
170         if (!this.getId().equals(other.getId()))
171         {
172             return false;
173         }
174         return true;
175     }
176 
177     /** {@inheritDoc} */
178     @Override
179     public final String toString()
180     {
181         String out = "BusStop [id=" + getId() + ", lines=";
182         String delim = "";
183         for (String line : this.lines)
184         {
185             out = out + delim + line;
186             delim = "/";
187         }
188         return out + "]";
189     }
190 
191     /** {@inheritDoc} */
192     @Override
193     public final AbstractLaneBasedObject clone(final CrossSectionElement newCSE,
194             final SimulatorInterface.TimeDoubleUnit newSimulator) throws NetworkException
195     {
196         BusStopnetwork/lane/object/BusStop.html#BusStop">BusStop busStop = new BusStop(getId(), (Lane) newCSE, getLongitudinalPosition(), this.name, newSimulator);
197         busStop.setLines(this.lines);
198         return busStop;
199     }
200 
201 }