View Javadoc
1   package org.opentrafficsim.road.gtu.lane.perception;
2   
3   import java.util.HashMap;
4   import java.util.Iterator;
5   import java.util.Map;
6   import java.util.NoSuchElementException;
7   import java.util.SortedMap;
8   import java.util.TreeMap;
9   
10  import org.djunits.value.vdouble.scalar.Length;
11  import org.opentrafficsim.base.parameters.ParameterException;
12  import org.opentrafficsim.core.gtu.GTUException;
13  import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
14  import org.opentrafficsim.road.gtu.lane.perception.headway.Headway;
15  
16  /**
17   * Iterable class to search over multiple lanes.
18   * <p>
19   * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
20   * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
21   * <p>
22   * @version $Revision$, $LastChangedDate$, by $Author$, initial version 20 feb. 2018 <br>
23   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
24   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
25   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
26   * @param <H> headway type
27   * @param <U> underlying headway type
28   */
29  public class MultiLanePerceptionIterable<H extends Headway, U> extends AbstractPerceptionReiterable<H, U>
30  {
31  
32      /** Set of iterators per lane. */
33      private final Map<RelativeLane, Iterator<PrimaryIteratorEntry>> iterators = new HashMap<>();
34  
35      /** Map of lane per object. */
36      private final Map<U, RelativeLane> laneMap = new HashMap<>();
37  
38      /** Map of iterable per lane. */
39      private final Map<RelativeLane, AbstractPerceptionReiterable<H, U>> iterables = new HashMap<>();
40  
41      /**
42       * Constructor.
43       * @param perceivingGtu LaneBasedGTU; perceiving GTU
44       */
45      public MultiLanePerceptionIterable(final LaneBasedGTU perceivingGtu)
46      {
47          super(perceivingGtu);
48      }
49  
50      /**
51       * Adds an iterable for a lane.
52       * @param lane RelativeLane; lane
53       * @param iterable AbstractPerceptionReiterable&lt;H, U&gt;; iterable
54       */
55      public void addIterable(final RelativeLane lane, final AbstractPerceptionReiterable<H, U> iterable)
56      {
57          this.iterators.put(lane, iterable.getPrimaryIterator());
58          this.iterables.put(lane, iterable);
59      }
60  
61      /** {@inheritDoc} */
62      @Override
63      public Iterator<PrimaryIteratorEntry> primaryIterator()
64      {
65          return new MultiLaneIterator();
66      }
67  
68      /**
69       * Iterator that returns the closest element from a set of lanes.
70       * <p>
71       * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
72       * <br>
73       * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
74       * <p>
75       * @version $Revision$, $LastChangedDate$, by $Author$, initial version 21 feb. 2018 <br>
76       * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
77       * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
78       * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
79       */
80      private class MultiLaneIterator implements Iterator<PrimaryIteratorEntry>
81      {
82  
83          /** Sorted elements per lane. */
84          private SortedMap<PrimaryIteratorEntry, RelativeLane> elements;
85  
86          /** Constructor. */
87          MultiLaneIterator()
88          {
89              //
90          }
91  
92          /** {@inheritDoc} */
93          @Override
94          public boolean hasNext()
95          {
96              assureNext();
97              return !this.elements.isEmpty();
98          }
99  
100         /** {@inheritDoc} */
101         @SuppressWarnings("synthetic-access")
102         @Override
103         public PrimaryIteratorEntry next()
104         {
105             assureNext();
106             if (this.elements.isEmpty())
107             {
108                 throw new NoSuchElementException();
109             }
110 
111             // get and remove next
112             PrimaryIteratorEntry next = this.elements.firstKey();
113             RelativeLane lane = this.elements.get(next);
114             this.elements.remove(next);
115 
116             // prepare next
117             Iterator<PrimaryIteratorEntry> laneIterator = MultiLanePerceptionIterable.this.iterators.get(lane);
118             if (laneIterator != null)
119             {
120                 if (laneIterator.hasNext())
121                 {
122                     this.elements.put(laneIterator.next(), lane);
123                 }
124                 else
125                 {
126                     // remove it, it has no more elements to offer
127                     MultiLanePerceptionIterable.this.iterators.remove(lane);
128                 }
129             }
130 
131             MultiLanePerceptionIterable.this.laneMap.put(next.getObject(), lane);
132             return next;
133         }
134 
135         /**
136          * Starts the process.
137          */
138         @SuppressWarnings("synthetic-access")
139         public void assureNext()
140         {
141             if (this.elements == null)
142             {
143                 this.elements = new TreeMap<>();
144                 for (RelativeLane lane : MultiLanePerceptionIterable.this.iterators.keySet())
145                 {
146                     Iterator<PrimaryIteratorEntry> laneIterator = MultiLanePerceptionIterable.this.iterators.get(lane);
147                     if (laneIterator.hasNext())
148                     {
149                         this.elements.put(laneIterator.next(), lane);
150                     }
151                 }
152             }
153         }
154 
155     }
156 
157     /** {@inheritDoc} */
158     @Override
159     public H perceive(final LaneBasedGTU perceivingGtu, final U object, final Length distance)
160             throws GTUException, ParameterException
161     {
162         return this.iterables.get(this.laneMap.get(object)).perceive(perceivingGtu, object, distance);
163     }
164 }