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