1 package org.opentrafficsim.kpi.sampling;
2
3 import java.util.ArrayList;
4 import java.util.Iterator;
5 import java.util.List;
6
7 import org.djunits.value.vdouble.scalar.Length;
8 import org.djunits.value.vdouble.scalar.Time;
9 import org.djutils.exceptions.Throw;
10 import org.opentrafficsim.kpi.interfaces.GtuDataInterface;
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 public class TrajectoryGroup<G extends GtuDataInterface> implements Iterable<Trajectory<G>>
26 {
27
28
29 private final Time startTime;
30
31
32 private final Length startPosition;
33
34
35 private final Length endPosition;
36
37
38 private final KpiLaneDirection laneDirection;
39
40
41 private final List<Trajectory<G>> trajectories = new ArrayList<>();
42
43
44
45
46
47
48 public TrajectoryGroup(final Time startTime, final KpiLaneDirection laneDirection)
49 {
50 this(startTime, Length.ZERO, laneDirection == null ? null : laneDirection.getLaneData().getLength(), laneDirection);
51 }
52
53
54
55
56
57
58
59 public TrajectoryGroup(final Time startTime, final Length startPosition, final Length endPosition,
60 final KpiLaneDirection laneDirection)
61 {
62 Throw.whenNull(startTime, "Start time may not be null.");
63
64 Throw.whenNull(laneDirection, "Lane direction time may not be null.");
65 Throw.whenNull(startPosition, "Start position may not be null");
66 Throw.whenNull(endPosition, "End position may not be null");
67 Length length0 = laneDirection.getPositionInDirection(startPosition);
68 Length length1 = laneDirection.getPositionInDirection(endPosition);
69 Throw.when(length0.gt(length1), IllegalArgumentException.class,
70 "Start position should be smaller than end position in the direction of travel");
71 this.startTime = startTime;
72 this.startPosition = startPosition;
73 this.endPosition = endPosition;
74 this.laneDirection = laneDirection;
75 }
76
77
78
79
80
81 public final synchronized void addTrajectory(final Trajectory<G> trajectory)
82 {
83
84 this.trajectories.add(trajectory);
85 }
86
87
88
89
90 public final Time getStartTime()
91 {
92 return this.startTime;
93 }
94
95
96
97
98 public final Length getLength()
99 {
100 return this.endPosition.minus(this.startPosition);
101 }
102
103
104
105
106
107
108
109 public final boolean contains(final Trajectory<?> trajectory)
110 {
111 return this.trajectories.contains(trajectory);
112 }
113
114
115
116
117
118 public final int size()
119 {
120 return this.trajectories.size();
121 }
122
123
124
125
126
127 public final List<Trajectory<G>> getTrajectories()
128 {
129 return new ArrayList<>(this.trajectories);
130 }
131
132
133
134
135
136
137
138 public final synchronized TrajectoryGroup<G> getTrajectoryGroup(final Length x0, final Length x1)
139 {
140 Length minLenght = Length.max(x0, this.startPosition);
141 Length maxLenght = Length.min(x1, this.endPosition);
142 TrajectoryGroup<G> out = new TrajectoryGroup<>(this.startTime, minLenght, maxLenght, this.laneDirection);
143 for (Trajectory<G> trajectory : this.trajectories)
144 {
145 out.addTrajectory(trajectory.subSet(x0, x1));
146 }
147 return out;
148 }
149
150
151
152
153
154
155
156 public final synchronized TrajectoryGroup<G> getTrajectoryGroup(final Time t0, final Time t1)
157 {
158 TrajectoryGroup<G> out = new TrajectoryGroup<>(this.startTime.lt(t0) ? t0 : this.startTime, this.laneDirection);
159 for (Trajectory<G> trajectory : this.trajectories)
160 {
161 out.addTrajectory(trajectory.subSet(t0, t1));
162 }
163 return out;
164 }
165
166
167
168
169
170
171
172
173
174 public final synchronized TrajectoryGroup<G> getTrajectoryGroup(final Length x0, final Length x1, final Time t0,
175 final Time t1)
176 {
177 TrajectoryGroup<G> out = new TrajectoryGroup<>(this.startTime.lt(t0) ? t0 : this.startTime, this.laneDirection);
178 for (Trajectory<G> trajectory : this.trajectories)
179 {
180 out.addTrajectory(trajectory.subSet(x0, x1, t0, t1));
181 }
182 return out;
183 }
184
185
186
187
188
189 public final KpiLaneDirection getLaneDirection()
190 {
191 return this.laneDirection;
192 }
193
194
195 @Override
196 public final int hashCode()
197 {
198 final int prime = 31;
199 int result = 1;
200 result = prime * result + ((this.laneDirection == null) ? 0 : this.laneDirection.hashCode());
201 result = prime * result + ((this.endPosition == null) ? 0 : this.endPosition.hashCode());
202 result = prime * result + ((this.startPosition == null) ? 0 : this.startPosition.hashCode());
203 result = prime * result + ((this.startTime == null) ? 0 : this.startTime.hashCode());
204 result = prime * result + ((this.trajectories == null) ? 0 : this.trajectories.hashCode());
205 return result;
206 }
207
208
209 @Override
210 public final boolean equals(final Object obj)
211 {
212 if (this == obj)
213 {
214 return true;
215 }
216 if (obj == null)
217 {
218 return false;
219 }
220 if (getClass() != obj.getClass())
221 {
222 return false;
223 }
224 TrajectoryGroup<?> other = (TrajectoryGroup<?>) obj;
225 if (this.laneDirection == null)
226 {
227 if (other.laneDirection != null)
228 {
229 return false;
230 }
231 }
232 else if (!this.laneDirection.equals(other.laneDirection))
233 {
234 return false;
235 }
236 if (this.endPosition == null)
237 {
238 if (other.endPosition != null)
239 {
240 return false;
241 }
242 }
243 else if (!this.endPosition.equals(other.endPosition))
244 {
245 return false;
246 }
247 if (this.startPosition == null)
248 {
249 if (other.startPosition != null)
250 {
251 return false;
252 }
253 }
254 else if (!this.startPosition.equals(other.startPosition))
255 {
256 return false;
257 }
258 if (this.startTime == null)
259 {
260 if (other.startTime != null)
261 {
262 return false;
263 }
264 }
265 else if (!this.startTime.equals(other.startTime))
266 {
267 return false;
268 }
269 if (this.trajectories == null)
270 {
271 if (other.trajectories != null)
272 {
273 return false;
274 }
275 }
276 else if (!this.trajectories.equals(other.trajectories))
277 {
278 return false;
279 }
280 return true;
281 }
282
283
284 @Override
285 public final String toString()
286 {
287 return "TrajectoryGroup [startTime=" + this.startTime + ", minLength=" + this.startPosition + ", maxLength="
288 + this.endPosition + ", laneDirection=" + this.laneDirection + ", collected "
289 + (this.trajectories == null ? "null" : this.trajectories.size()) + " trajectories]";
290 }
291
292
293 @Override
294 public Iterator<Trajectory<G>> iterator()
295 {
296 return this.trajectories.iterator();
297 }
298
299 }