View Javadoc
1   package org.opentrafficsim.kpi.sampling;
2   
3   import java.util.ArrayList;
4   import java.util.List;
5   
6   import org.djunits.value.vdouble.scalar.Length;
7   import org.djunits.value.vdouble.scalar.Time;
8   
9   import nl.tudelft.simulation.language.Throw;
10  
11  /**
12   * Contains all trajectories pertaining to a certain space-time region.
13   * <p>
14   * Copyright (c) 2013-2018 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
15   * BSD-style license. See <a href="http://opentrafficsim.org/docs/current/license.html">OpenTrafficSim License</a>.
16   * </p>
17   * $LastChangedDate: 2015-07-24 02:58:59 +0200 (Fri, 24 Jul 2015) $, @version $Revision: 1147 $, by $Author: averbraeck $,
18   * initial version Sep 21, 2016 <br>
19   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
20   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
21   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
22   */
23  public class TrajectoryGroup
24  {
25  
26      /** Start time of trajectories. */
27      private final Time startTime;
28  
29      /** Start position of the section. */
30      private final Length startPosition;
31  
32      /** End position of the section. */
33      private final Length endPosition;
34  
35      /** Direction for which the trajectories have been sampled. */
36      private final KpiLaneDirection laneDirection;
37  
38      /** Trajectories. */
39      private final List<Trajectory<?>> trajectories = new ArrayList<>();
40  
41      /**
42       * Constructor without length specification. The complete lane will be used.
43       * @param startTime start time of trajectories
44       * @param laneDirection lane direction
45       */
46      public TrajectoryGroup(final Time startTime, final KpiLaneDirection laneDirection)
47      {
48          this(startTime, Length.ZERO, laneDirection == null ? null : laneDirection.getLaneData().getLength(), laneDirection);
49      }
50  
51      /**
52       * @param startTime start time of trajectory group
53       * @param startPosition start position
54       * @param endPosition end position
55       * @param laneDirection lane direction
56       */
57      public TrajectoryGroup(final Time startTime, final Length startPosition, final Length endPosition,
58              final KpiLaneDirection laneDirection)
59      {
60          Throw.whenNull(startTime, "Start time may not be null.");
61          // keep before position check; prevents "End position may not be null" due to missing direction in other constructor
62          Throw.whenNull(laneDirection, "Lane direction time may not be null.");
63          Throw.whenNull(startPosition, "Start position may not be null");
64          Throw.whenNull(endPosition, "End position may not be null");
65          Length length0 = laneDirection.getPositionInDirection(startPosition);
66          Length length1 = laneDirection.getPositionInDirection(endPosition);
67          Throw.when(length0.gt(length1), IllegalArgumentException.class,
68                  "Start position should be smaller than end position in the direction of travel");
69          this.startTime = startTime;
70          this.startPosition = startPosition;
71          this.endPosition = endPosition;
72          this.laneDirection = laneDirection;
73      }
74  
75      /**
76       * Add trajectory.
77       * @param trajectory trajectory to add
78       */
79      public final synchronized void addTrajectory(final Trajectory<?> trajectory)
80      {
81          this.trajectories.add(trajectory);
82      }
83  
84      /**
85       * @return startTime.
86       */
87      public final Time getStartTime()
88      {
89          return this.startTime;
90      }
91  
92      /**
93       * @return length.
94       */
95      public final Length getLength()
96      {
97          return this.endPosition.minus(this.startPosition);
98      }
99  
100     /**
101      * Whether this {@code TrajectoryGroup} holds the given trajectory. Note that this is false if the given trajectory is
102      * derived from a trajectory in this {@code TrajectoryGroup}.
103      * @param trajectory trajectory
104      * @return whether this {@code TrajectoryGroup} holds the given trajectory.
105      */
106     public final boolean contains(final Trajectory<?> trajectory)
107     {
108         return this.trajectories.contains(trajectory);
109     }
110 
111     /**
112      * Returns the number of trajectories in this group.
113      * @return number of trajectories in this group
114      */
115     public final int size()
116     {
117         return this.trajectories.size();
118     }
119 
120     /**
121      * Returns a list of trajectories.
122      * @return list of trajectories
123      */
124     public final List<Trajectory<?>> getTrajectories()
125     {
126         return new ArrayList<>(this.trajectories);
127     }
128 
129     /**
130      * Returns trajectory group between two locations.
131      * @param x0 start length
132      * @param x1 end length
133      * @return list of trajectories
134      */
135     public final synchronized TrajectoryGroup getTrajectoryGroup(final Length x0, final Length x1)
136     {
137         Length minLenght = Length.max(x0, this.startPosition);
138         Length maxLenght = Length.min(x1, this.endPosition);
139         TrajectoryGroup out = new TrajectoryGroup(this.startTime, minLenght, maxLenght, this.laneDirection);
140         for (Trajectory<?> trajectory : this.trajectories)
141         {
142             out.addTrajectory(trajectory.subSet(x0, x1));
143         }
144         return out;
145     }
146 
147     /**
148      * Returns trajectory group between two times.
149      * @param t0 start time
150      * @param t1 end time
151      * @return list of trajectories
152      */
153     public final synchronized TrajectoryGroup getTrajectoryGroup(final Time t0, final Time t1)
154     {
155         TrajectoryGroup out = new TrajectoryGroup(this.startTime.lt(t0) ? t0 : this.startTime, this.laneDirection);
156         for (Trajectory<?> trajectory : this.trajectories)
157         {
158             out.addTrajectory(trajectory.subSet(t0, t1));
159         }
160         return out;
161     }
162 
163     /**
164      * Returns trajectory group between two locations and between two times.
165      * @param x0 start length
166      * @param x1 end length
167      * @param t0 start time
168      * @param t1 end time
169      * @return list of trajectories
170      */
171     public final synchronized TrajectoryGroup getTrajectoryGroup(final Length x0, final Length x1, final Time t0, final Time t1)
172     {
173         TrajectoryGroup out = new TrajectoryGroup(this.startTime.lt(t0) ? t0 : this.startTime, this.laneDirection);
174         for (Trajectory<?> trajectory : this.trajectories)
175         {
176             out.addTrajectory(trajectory.subSet(x0, x1, t0, t1));
177         }
178         return out;
179     }
180 
181     /**
182      * Returns the lane direction.
183      * @return lane direction
184      */
185     public final KpiLaneDirection getLaneDirection()
186     {
187         return this.laneDirection;
188     }
189 
190     /** {@inheritDoc} */
191     @Override
192     public final int hashCode()
193     {
194         final int prime = 31;
195         int result = 1;
196         result = prime * result + ((this.laneDirection == null) ? 0 : this.laneDirection.hashCode());
197         result = prime * result + ((this.endPosition == null) ? 0 : this.endPosition.hashCode());
198         result = prime * result + ((this.startPosition == null) ? 0 : this.startPosition.hashCode());
199         result = prime * result + ((this.startTime == null) ? 0 : this.startTime.hashCode());
200         result = prime * result + ((this.trajectories == null) ? 0 : this.trajectories.hashCode());
201         return result;
202     }
203 
204     /** {@inheritDoc} */
205     @Override
206     public final boolean equals(final Object obj)
207     {
208         if (this == obj)
209         {
210             return true;
211         }
212         if (obj == null)
213         {
214             return false;
215         }
216         if (getClass() != obj.getClass())
217         {
218             return false;
219         }
220         TrajectoryGroup other = (TrajectoryGroup) obj;
221         if (this.laneDirection == null)
222         {
223             if (other.laneDirection != null)
224             {
225                 return false;
226             }
227         }
228         else if (!this.laneDirection.equals(other.laneDirection))
229         {
230             return false;
231         }
232         if (this.endPosition == null)
233         {
234             if (other.endPosition != null)
235             {
236                 return false;
237             }
238         }
239         else if (!this.endPosition.equals(other.endPosition))
240         {
241             return false;
242         }
243         if (this.startPosition == null)
244         {
245             if (other.startPosition != null)
246             {
247                 return false;
248             }
249         }
250         else if (!this.startPosition.equals(other.startPosition))
251         {
252             return false;
253         }
254         if (this.startTime == null)
255         {
256             if (other.startTime != null)
257             {
258                 return false;
259             }
260         }
261         else if (!this.startTime.equals(other.startTime))
262         {
263             return false;
264         }
265         if (this.trajectories == null)
266         {
267             if (other.trajectories != null)
268             {
269                 return false;
270             }
271         }
272         else if (!this.trajectories.equals(other.trajectories))
273         {
274             return false;
275         }
276         return true;
277     }
278 
279     /** {@inheritDoc} */
280     @Override
281     public final String toString()
282     {
283         return "TrajectoryGroup [startTime=" + this.startTime + ", minLength=" + this.startPosition + ", maxLength="
284                 + this.endPosition + ", laneDirection=" + this.laneDirection + "]";
285     }
286 
287 }