View Javadoc
1   package org.opentrafficsim.road.gtu.lane.perception;
2   
3   import java.util.Iterator;
4   import java.util.function.Function;
5   import java.util.function.Supplier;
6   
7   import org.djunits.value.vdouble.scalar.Length;
8   import org.opentrafficsim.road.gtu.lane.perception.headway.Headway;
9   
10  /**
11   * Iterable that additionally provides support for PerceptionCollectors. These gather raw data, to only 'perceive' the result.
12   * <p>
13   * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
14   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
15   * </p>
16   * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
17   * @author <a href="https://github.com/peter-knoppers">Peter Knoppers</a>
18   * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
19   * @param <H> headway type
20   * @param <U> underlying object type
21   */
22  public interface PerceptionCollectable<H extends Headway, U> extends PerceptionIterable<H>
23  {
24  
25      /**
26       * Collect the underlying objects in to a perceived result. This methodology is loosely based on Stream.collect().
27       * @param collector collector
28       * @param <C> collection result type
29       * @param <I> intermediate type
30       * @return collection result
31       */
32      default <C, I> C collect(final PerceptionCollector<C, ? super U, I> collector)
33      {
34          return collect(collector.getIdentity(), collector.getAccumulator(), collector.getFinalizer());
35      }
36  
37      /**
38       * Collect the underlying objects in to a perceived result. This methodology is loosely based on Stream.collect().
39       * @param identity the initial intermediate result value
40       * @param accumulator accumulator
41       * @param finalizer finalizer
42       * @param <C> collection result type
43       * @param <I> intermediate type
44       * @return collection result
45       */
46      <C, I> C collect(Supplier<I> identity, PerceptionAccumulator<? super U, I> accumulator, Function<I, C> finalizer);
47  
48      /**
49       * Returns an iterator over the underlying objects.
50       * @return iterator
51       */
52      Iterator<U> underlying();
53  
54      /**
55       * Returns an iterator over the underlying objects coupled with the distance.
56       * @return iterator
57       */
58      Iterator<UnderlyingDistance<U>> underlyingWithDistance();
59  
60      /**
61       * Combination of an accumulator and a finalizer.
62       * @param <C> collection result type
63       * @param <U> underlying object type
64       * @param <I> intermediate result type
65       */
66      interface PerceptionCollector<C, U, I>
67      {
68          /**
69           * Returns the identity value, the initial intermediate value.
70           * @return identity value, the initial intermediate value
71           */
72          Supplier<I> getIdentity();
73  
74          /**
75           * Returns the accumulator.
76           * @return accumulator
77           */
78          PerceptionAccumulator<U, I> getAccumulator();
79  
80          /**
81           * Returns the finalizer.
82           * @return finalizer
83           */
84          Function<I, C> getFinalizer();
85      }
86  
87      /**
88       * Accumulates an object one at a time in to an accumulating intermediate result.
89       * @param <U> underlying object type
90       * @param <I> intermediate result type
91       */
92      interface PerceptionAccumulator<U, I>
93      {
94          /**
95           * Accumulate the next object to intermediate result.
96           * @param intermediate intermediate result before accumulation of object
97           * @param object next object to include
98           * @param distance distance to the considered object
99           * @return intermediate result after accumulation of object
100          */
101         Intermediate<I> accumulate(Intermediate<I> intermediate, U object, Length distance);
102     }
103 
104     /**
105      * Wrapper of intermediate result with info for the iterator algorithm.
106      * @param <I> intermediate result type
107      */
108     class Intermediate<I>
109     {
110         /** Number of underlying object being iterated. */
111         private int number = 0;
112 
113         /** Intermediate object. */
114         private I object;
115 
116         /** Whether to stop accumulating. */
117         private boolean stop = false;
118 
119         /**
120          * Constructor.
121          * @param object identity value
122          */
123         public Intermediate(final I object)
124         {
125             this.object = object;
126         }
127 
128         /**
129          * Get intermediate object.
130          * @return intermediate object
131          */
132         public I getObject()
133         {
134             return this.object;
135         }
136 
137         /**
138          * Set intermediate object.
139          * @param object intermediate object
140          */
141         public void setObject(final I object)
142         {
143             this.object = object;
144         }
145 
146         /**
147          * Returns the number of the underlying object currently being accumulated, starts at 0 for the first.
148          * @return number of the underlying object currently being accumulated
149          */
150         public int getNumber()
151         {
152             return this.number;
153         }
154 
155         /**
156          * Method for the iterator to increase the underlying object number.
157          */
158         public void step()
159         {
160             this.number++;
161         }
162 
163         /**
164          * Method for the accumulator to indicate the iterator can stop.
165          */
166         public void stop()
167         {
168             this.stop = true;
169         }
170 
171         /**
172          * Method for the iterator to check if it can stop.
173          * @return whether the iterator can stop
174          */
175         public boolean isStop()
176         {
177             return this.stop;
178         }
179     }
180 
181     /**
182      * Wrapper for object and its distance.
183      * @param object underlying object
184      * @param distance distance to object
185      * @param <U> underlying object type
186      */
187     record UnderlyingDistance<U>(U object, Length distance) implements Comparable<UnderlyingDistance<U>>
188     {
189         @Override
190         public int compareTo(final UnderlyingDistance<U> o)
191         {
192             int out = this.distance.compareTo(o.distance);
193             if (out != 0)
194             {
195                 return out;
196             }
197             if (this.object == null)
198             {
199                 if (o.object == null)
200                 {
201                     return 0;
202                 }
203                 return -1;
204             }
205             if (o.object == null)
206             {
207                 return 1;
208             }
209             return Integer.compare(this.object.hashCode(), o.object.hashCode());
210         }
211     }
212 
213 }