1   package org.opentrafficsim.road.network.lane.object;
2   
3   import java.util.HashSet;
4   import java.util.LinkedHashSet;
5   import java.util.List;
6   import java.util.Map;
7   import java.util.Set;
8   
9   import org.djunits.value.vdouble.scalar.Length;
10  import org.djutils.immutablecollections.Immutable;
11  import org.djutils.immutablecollections.ImmutableHashSet;
12  import org.djutils.immutablecollections.ImmutableSet;
13  import org.opentrafficsim.core.gtu.GTUDirectionality;
14  import org.opentrafficsim.core.gtu.GTUType;
15  import org.opentrafficsim.core.network.LongitudinalDirectionality;
16  import org.opentrafficsim.core.network.NetworkException;
17  import org.opentrafficsim.road.network.lane.CrossSectionElement;
18  import org.opentrafficsim.road.network.lane.Lane;
19  import org.opentrafficsim.road.network.lane.conflict.BusStopConflictRule;
20  import org.opentrafficsim.road.network.lane.conflict.Conflict;
21  
22  import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  public class BusStop extends AbstractLaneBasedObject
40  {
41  
42      
43      private static final long serialVersionUID = 20170124L;
44  
45      
46      private final Set<String> lines = new HashSet<>();
47  
48      
49      private final String name;
50  
51      
52      private Set<Conflict> conflicts = null;
53  
54      
55  
56  
57  
58  
59  
60  
61  
62      public BusStop(final String id, final Lane lane, final Length longitudinalPosition, final String name,
63              final SimulatorInterface.TimeDoubleUnit simulator) throws NetworkException
64      {
65          super(id, lane, LongitudinalDirectionality.DIR_PLUS, longitudinalPosition,
66                  LaneBasedObject.makeGeometry(lane, longitudinalPosition), Length.ZERO);
67          this.name = name;
68      }
69  
70      
71  
72  
73  
74      public final void setLines(final Set<String> lines)
75      {
76          this.lines.clear();
77          this.lines.addAll(lines);
78      }
79  
80      
81  
82  
83  
84      public final ImmutableSet<String> getLines()
85      {
86          return new ImmutableHashSet<>(this.lines, Immutable.COPY);
87      }
88  
89      
90  
91  
92  
93      public final Set<Conflict> getConflicts()
94      {
95          if (this.conflicts == null)
96          {
97              this.conflicts = new LinkedHashSet<>();
98              Lane lane = getLane();
99              
100             GTUDirectionality dir = getDirection().isForward() ? GTUDirectionality.DIR_PLUS : GTUDirectionality.DIR_MINUS;
101             Length position = getLongitudinalPosition();
102             while (lane != null)
103             {
104                 List<LaneBasedObject> objects = lane.getObjectAhead(position, dir);
105                 while (objects != null)
106                 {
107                     for (LaneBasedObject object : objects)
108                     {
109                         if (object instanceof Conflict)
110                         {
111                             Conflict conflict = (Conflict) object;
112                             if (conflict.getConflictRule() instanceof BusStopConflictRule)
113                             {
114                                 this.conflicts.add(conflict);
115                             }
116                         }
117                     }
118                     objects = lane.getObjectAhead(objects.get(0).getLongitudinalPosition(), dir);
119                 }
120                 Map<Lane, GTUDirectionality> downstreamLanes = lane.downstreamLanes(dir, GTUType.BUS);
121                 int numLanes = 0;
122                 for (Lane nextLane : downstreamLanes.keySet())
123                 {
124                     if (nextLane.getParentLink().getPriority().isBusStop())
125                     {
126                         numLanes++;
127                         lane = nextLane;
128                         dir = downstreamLanes.get(lane);
129                         position = dir.isPlus() ? Length.ZERO : lane.getLength();
130                     }
131                 }
132                 if (numLanes != 1)
133                 {
134                     lane = null;
135                 }
136             }
137         }
138         return this.conflicts;
139     }
140 
141     
142     @Override
143     public final int hashCode()
144     {
145         final int prime = 31;
146         int result = 1;
147         result = prime * result + this.getId().hashCode();
148         return result;
149     }
150 
151     
152     @Override
153     public final boolean equals(final Object obj)
154     {
155         if (this == obj)
156         {
157             return true;
158         }
159         if (obj == null)
160         {
161             return false;
162         }
163         if (getClass() != obj.getClass())
164         {
165             return false;
166         }
167         BusStop other = (BusStop) obj;
168         if (!this.getId().equals(other.getId()))
169         {
170             return false;
171         }
172         return true;
173     }
174 
175     
176     @Override
177     public final String toString()
178     {
179         String out = "BusStop [id=" + getId() + ", lines=";
180         String delim = "";
181         for (String line : this.lines)
182         {
183             out = out + delim + line;
184             delim = "/";
185         }
186         return out + "]";
187     }
188 
189     
190     @Override
191     public final AbstractLaneBasedObject clone(final CrossSectionElement newCSE,
192             final SimulatorInterface.TimeDoubleUnit newSimulator) throws NetworkException
193     {
194         BusStop busStop = new BusStop(getId(), (Lane) newCSE, getLongitudinalPosition(), this.name, newSimulator);
195         busStop.setLines(this.lines);
196         return busStop;
197     }
198 
199 }