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 this.trajectories.add(trajectory);
84 }
85
86
87
88
89 public final Time getStartTime()
90 {
91 return this.startTime;
92 }
93
94
95
96
97 public final Length getLength()
98 {
99 return this.endPosition.minus(this.startPosition);
100 }
101
102
103
104
105
106
107
108 public final boolean contains(final Trajectory<?> trajectory)
109 {
110 return this.trajectories.contains(trajectory);
111 }
112
113
114
115
116
117 public final int size()
118 {
119 return this.trajectories.size();
120 }
121
122
123
124
125
126 public final List<Trajectory<G>> getTrajectories()
127 {
128 return new ArrayList<>(this.trajectories);
129 }
130
131
132
133
134
135
136
137 public final synchronized TrajectoryGroup<G> getTrajectoryGroup(final Length x0, final Length x1)
138 {
139 Length minLenght = Length.max(x0, this.startPosition);
140 Length maxLenght = Length.min(x1, this.endPosition);
141 TrajectoryGroup<G> out = new TrajectoryGroup<>(this.startTime, minLenght, maxLenght, this.laneDirection);
142 for (Trajectory<G> trajectory : this.trajectories)
143 {
144 out.addTrajectory(trajectory.subSet(x0, x1));
145 }
146 return out;
147 }
148
149
150
151
152
153
154
155 public final synchronized TrajectoryGroup<G> getTrajectoryGroup(final Time t0, final Time t1)
156 {
157 TrajectoryGroup<G> out = new TrajectoryGroup<>(this.startTime.lt(t0) ? t0 : this.startTime, this.laneDirection);
158 for (Trajectory<G> trajectory : this.trajectories)
159 {
160 out.addTrajectory(trajectory.subSet(t0, t1));
161 }
162 return out;
163 }
164
165
166
167
168
169
170
171
172
173 public final synchronized TrajectoryGroup<G> getTrajectoryGroup(final Length x0, final Length x1, final Time t0,
174 final Time t1)
175 {
176 TrajectoryGroup<G> out = new TrajectoryGroup<>(this.startTime.lt(t0) ? t0 : this.startTime, this.laneDirection);
177 for (Trajectory<G> trajectory : this.trajectories)
178 {
179 out.addTrajectory(trajectory.subSet(x0, x1, t0, t1));
180 }
181 return out;
182 }
183
184
185
186
187
188 public final KpiLaneDirection getLaneDirection()
189 {
190 return this.laneDirection;
191 }
192
193
194 @Override
195 public final int hashCode()
196 {
197 final int prime = 31;
198 int result = 1;
199 result = prime * result + ((this.laneDirection == null) ? 0 : this.laneDirection.hashCode());
200 result = prime * result + ((this.endPosition == null) ? 0 : this.endPosition.hashCode());
201 result = prime * result + ((this.startPosition == null) ? 0 : this.startPosition.hashCode());
202 result = prime * result + ((this.startTime == null) ? 0 : this.startTime.hashCode());
203 result = prime * result + ((this.trajectories == null) ? 0 : this.trajectories.hashCode());
204 return result;
205 }
206
207
208 @Override
209 public final boolean equals(final Object obj)
210 {
211 if (this == obj)
212 {
213 return true;
214 }
215 if (obj == null)
216 {
217 return false;
218 }
219 if (getClass() != obj.getClass())
220 {
221 return false;
222 }
223 TrajectoryGroup<?> other = (TrajectoryGroup<?>) obj;
224 if (this.laneDirection == null)
225 {
226 if (other.laneDirection != null)
227 {
228 return false;
229 }
230 }
231 else if (!this.laneDirection.equals(other.laneDirection))
232 {
233 return false;
234 }
235 if (this.endPosition == null)
236 {
237 if (other.endPosition != null)
238 {
239 return false;
240 }
241 }
242 else if (!this.endPosition.equals(other.endPosition))
243 {
244 return false;
245 }
246 if (this.startPosition == null)
247 {
248 if (other.startPosition != null)
249 {
250 return false;
251 }
252 }
253 else if (!this.startPosition.equals(other.startPosition))
254 {
255 return false;
256 }
257 if (this.startTime == null)
258 {
259 if (other.startTime != null)
260 {
261 return false;
262 }
263 }
264 else if (!this.startTime.equals(other.startTime))
265 {
266 return false;
267 }
268 if (this.trajectories == null)
269 {
270 if (other.trajectories != null)
271 {
272 return false;
273 }
274 }
275 else if (!this.trajectories.equals(other.trajectories))
276 {
277 return false;
278 }
279 return true;
280 }
281
282
283 @Override
284 public final String toString()
285 {
286 return "TrajectoryGroup [startTime=" + this.startTime + ", minLength=" + this.startPosition + ", maxLength="
287 + this.endPosition + ", laneDirection=" + this.laneDirection + "]";
288 }
289
290
291 @Override
292 public Iterator<Trajectory<G>> iterator()
293 {
294 return this.trajectories.iterator();
295 }
296
297 }