1 package org.opentrafficsim.kpi.sampling;
2
3 import java.io.BufferedWriter;
4 import java.io.IOException;
5 import java.util.ArrayList;
6 import java.util.Collection;
7 import java.util.Iterator;
8 import java.util.LinkedHashMap;
9 import java.util.LinkedHashSet;
10 import java.util.List;
11 import java.util.Map;
12 import java.util.Set;
13 import java.util.function.BiFunction;
14 import java.util.function.Function;
15
16 import org.djunits.value.vdouble.scalar.Length;
17 import org.djunits.value.vdouble.scalar.Time;
18 import org.opentrafficsim.base.CompressedFileWriter;
19 import org.opentrafficsim.kpi.interfaces.GtuDataInterface;
20 import org.opentrafficsim.kpi.interfaces.GtuTypeDataInterface;
21 import org.opentrafficsim.kpi.interfaces.LaneDataInterface;
22 import org.opentrafficsim.kpi.interfaces.LinkDataInterface;
23 import org.opentrafficsim.kpi.interfaces.NodeDataInterface;
24 import org.opentrafficsim.kpi.interfaces.RouteDataInterface;
25 import org.opentrafficsim.kpi.sampling.ListTable.ListRecord;
26 import org.opentrafficsim.kpi.sampling.data.ExtendedDataType;
27 import org.opentrafficsim.kpi.sampling.meta.FilterDataType;
28
29 /**
30 * SamplerData is a storage for trajectory data. Adding trajectory groups can only be done by subclasses. This is however not a
31 * guaranteed read-only class. Any type can obtain the lane directions and with those the coupled trajectory groups.
32 * Trajectories can be added to these trajectory groups. Data can also be added to the trajectories themselves.
33 * <p>
34 * Copyright (c) 2020-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
35 * BSD-style license. See <a href="https://opentrafficsim.org/docs/current/license.html">OpenTrafficSim License</a>.
36 * </p>
37 * @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a>
38 * @author <a href="https://www.tudelft.nl/pknoppers">Peter Knoppers</a>
39 * @author <a href="https://www.transport.citg.tudelft.nl">Wouter Schakel</a>
40 * @param <G> gtu data type
41 */
42 // TODO: extending list table requires us to know the columns beforehand, create a view asTable()?
43 public class SamplerData<G extends GtuDataInterface> extends AbstractTable
44 {
45
46 /**
47 * Constructor.
48 * @param columns Collection<Column<?>>; columns
49 */
50 public SamplerData(final Collection<Column<?>> columns)
51 {
52 super("sampler", "Trajectory data", columns);
53 }
54
55 /** Map with all sampling data. */
56 private final Map<KpiLaneDirection, TrajectoryGroup<G>> trajectories = new LinkedHashMap<>();
57
58 /**
59 * Stores a trajectory group with the lane direction.
60 * @param kpiLaneDirection KpiLaneDirection; lane direction
61 * @param trajectoryGroup trajectory group for given lane direction
62 */
63 protected final void putTrajectoryGroup(final KpiLaneDirection kpiLaneDirection, final TrajectoryGroup<G> trajectoryGroup)
64 {
65 this.trajectories.put(kpiLaneDirection, trajectoryGroup);
66 }
67
68 /**
69 * Returns the set of lane directions.
70 * @return Set<KpiLaneDirection>; lane directions
71 */
72 public final Set<KpiLaneDirection> getLaneDirections()
73 {
74 return this.trajectories.keySet();
75 }
76
77 /**
78 * Returns whether there is data for the give lane direction.
79 * @param kpiLaneDirection KpiLaneDirection; lane direction
80 * @return whether there is data for the give lane direction
81 */
82 public final boolean contains(final KpiLaneDirection kpiLaneDirection)
83 {
84 return this.trajectories.containsKey(kpiLaneDirection);
85 }
86
87 /**
88 * Returns the trajectory group of given lane direction.
89 * @param kpiLaneDirection KpiLaneDirection; lane direction
90 * @return trajectory group of given lane direction, {@code null} if none
91 */
92 public final TrajectoryGroup<G> getTrajectoryGroup(final KpiLaneDirection kpiLaneDirection)
93 {
94 return this.trajectories.get(kpiLaneDirection);
95 }
96
97 /**
98 * Write the contents of the sampler in to a file. By default this is zipped and numeric data is formated %.3f.
99 * @param file String; file
100 */
101 public final void writeToFile(final String file)
102 {
103 writeToFile(file, "%.3f", CompressionMethod.ZIP);
104 }
105
106 /**
107 * Write the contents of the sampler in to a file.
108 * @param file String; file
109 * @param format String; number format, as used in {@code String.format()}
110 * @param compression CompressionMethod; how to compress the data
111 */
112 public final void writeToFile(final String file, final String format, final CompressionMethod compression)
113 {
114 int counter = 0;
115 BufferedWriter bw = CompressedFileWriter.create(file, compression.equals(CompressionMethod.ZIP));
116
117 // TODO: Sampler used this to cut-off space if SpaceTimeRegion's did not cover complete lanes. Trajectories are however
118 // recorded over the complete length.
119
120 /*
121 * // create Query, as this class is designed to filter for space-time regions Query<G> query = new Query<>(this, "",
122 * new MetaDataSet()); for (SpaceTimeRegion str : this.spaceTimeRegions) {
123 * query.addSpaceTimeRegion(str.getLaneDirection(), str.getStartPosition(), str.getEndPosition(), str.getStartTime(),
124 * str.getEndTime()); } List<TrajectoryGroup<G>> groups =
125 * query.getTrajectoryGroups(Time.instantiateSI(Double.POSITIVE_INFINITY));
126 */
127
128 Collection<TrajectoryGroup<G>> groups = this.trajectories.values();
129 try
130 {
131 // gather all filter data types for the header line
132 List<FilterDataType<?>> allFilterDataTypes = new ArrayList<>();
133 for (TrajectoryGroup<G> group : groups)
134 {
135 for (Trajectory<G> trajectory : group.getTrajectories())
136 {
137 for (FilterDataType<?> filterDataType : trajectory.getFilterDataTypes())
138 {
139 if (!allFilterDataTypes.contains(filterDataType))
140 {
141 allFilterDataTypes.add(filterDataType);
142 }
143 }
144 }
145 }
146 // gather all extended data types for the header line
147 List<ExtendedDataType<?, ?, ?, ?>> allExtendedDataTypes = new ArrayList<>();
148 for (TrajectoryGroup<G> group : groups)
149 {
150 for (Trajectory<?> trajectory : group.getTrajectories())
151 {
152 for (ExtendedDataType<?, ?, ?, ?> extendedDataType : trajectory.getExtendedDataTypes())
153 {
154 if (!allExtendedDataTypes.contains(extendedDataType))
155 {
156 allExtendedDataTypes.add(extendedDataType);
157 }
158 }
159 }
160 }
161 // create header line
162 StringBuilder str = new StringBuilder();
163 str.append("traj#,linkId,laneId&dir,gtuId,t,x,v,a");
164 for (FilterDataType<?> metaDataType : allFilterDataTypes)
165 {
166 str.append(",");
167 str.append(metaDataType.getId());
168 }
169 for (ExtendedDataType<?, ?, ?, ?> extendedDataType : allExtendedDataTypes)
170 {
171 str.append(",");
172 str.append(extendedDataType.getId());
173 }
174 bw.write(str.toString());
175 bw.newLine();
176 for (TrajectoryGroup<G> group : groups)
177 {
178 for (Trajectory<G> trajectory : group.getTrajectories())
179 {
180 counter++;
181 float[] t = trajectory.getT();
182 float[] x = trajectory.getX();
183 float[] v = trajectory.getV();
184 float[] a = trajectory.getA();
185 Map<ExtendedDataType<?, ?, ?, ?>, Object> extendedData = new LinkedHashMap<>();
186 for (ExtendedDataType<?, ?, ?, ?> extendedDataType : allExtendedDataTypes)
187 {
188 if (trajectory.contains(extendedDataType))
189 {
190 try
191 {
192 extendedData.put(extendedDataType, trajectory.getExtendedData(extendedDataType));
193 }
194 catch (SamplingException exception)
195 {
196 // should not occur, we obtain the extended data types from the trajectory
197 throw new RuntimeException("Error while loading extended data type.", exception);
198 }
199 }
200 }
201 for (int i = 0; i < t.length; i++)
202 {
203 // TODO: values can contain ","; use csv writer
204 str = new StringBuilder();
205 str.append(counter);
206 str.append(",");
207 if (!compression.equals(CompressionMethod.OMIT_DUPLICATE_INFO) || i == 0)
208 {
209 str.append(group.getLaneDirection().getLaneData().getLinkData().getId());
210 str.append(",");
211 str.append(group.getLaneDirection().getLaneData().getId());
212 str.append(group.getLaneDirection().getKpiDirection().isPlus() ? "+" : "-");
213 str.append(",");
214 str.append(trajectory.getGtuId());
215 str.append(",");
216 }
217 else
218 {
219 // one trajectory is on the same lane and pertains to the same GTU, no need to repeat data
220 str.append(",,,");
221 }
222 str.append(String.format(format, t[i]));
223 str.append(",");
224 str.append(String.format(format, x[i]));
225 str.append(",");
226 str.append(String.format(format, v[i]));
227 str.append(",");
228 str.append(String.format(format, a[i]));
229 for (FilterDataType<?> metaDataType : allFilterDataTypes)
230 {
231 str.append(",");
232 if (i == 0 && trajectory.contains(metaDataType))
233 {
234 // no need to repeat meta data
235 str.append(metaDataType.formatValue(format, castValue(trajectory.getMetaData(metaDataType))));
236 }
237 }
238 for (ExtendedDataType<?, ?, ?, ?> extendedDataType : allExtendedDataTypes)
239 {
240 str.append(",");
241 if (trajectory.contains(extendedDataType))
242 {
243 try
244 {
245 str.append(extendedDataType.formatValue(format, castValue(extendedData, extendedDataType,
246 i)));
247 }
248 catch (SamplingException exception)
249 {
250 // should not occur, we obtain the extended data types from the trajectory
251 throw new RuntimeException("Error while loading extended data type.", exception);
252 }
253 }
254 }
255 bw.write(str.toString());
256 bw.newLine();
257 }
258 }
259 }
260 }
261 catch (IOException exception)
262 {
263 throw new RuntimeException("Could not write to file.", exception);
264 }
265 // close file on fail
266 finally
267 {
268 try
269 {
270 if (bw != null)
271 {
272 bw.close();
273 }
274 }
275 catch (IOException ex)
276 {
277 ex.printStackTrace();
278 }
279 }
280 }
281
282 /**
283 * Cast value to type for meta data.
284 * @param value Object; value object to cast
285 * @return cast value
286 * @param <T> type of value
287 */
288 @SuppressWarnings("unchecked")
289 private <T> T castValue(final Object value)
290 {
291 return (T) value;
292 }
293
294 /**
295 * Cast value to type for extended data.
296 * @param extendedData Map<ExtendedDataType<?,?,?,?>,Object>; extended data of trajectory in output form
297 * @param extendedDataType ExtendedDataType<?,?,?,?>; extended data type
298 * @param i int; index of value to return
299 * @return cast value
300 * @throws SamplingException when the found index is out of bounds
301 * @param <T> type of value
302 * @param <O> output type
303 * @param <S> storage type
304 */
305 @SuppressWarnings("unchecked")
306 private <T, O, S> T castValue(final Map<ExtendedDataType<?, ?, ?, ?>, Object> extendedData, final ExtendedDataType<?, ?, ?,
307 ?> extendedDataType, final int i) throws SamplingException
308 {
309 // is only called on value directly taken from an ExtendedDataType within range of trajectory
310 ExtendedDataType<T, O, S, ?> edt = (ExtendedDataType<T, O, S, ?>) extendedDataType;
311 return edt.getOutputValue((O) extendedData.get(edt), i);
312 }
313
314 /**
315 * Defines the compression method for stored data.
316 * <p>
317 * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
318 * <br>
319 * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
320 * <p>
321 * @version $Revision$, $LastChangedDate$, by $Author$, initial version 3 mei 2017 <br>
322 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
323 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
324 * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
325 */
326 public enum CompressionMethod
327 {
328 /** No compression. */
329 NONE,
330
331 /** Duplicate info per trajectory is only stored at the first sample, and empty for other samples. */
332 OMIT_DUPLICATE_INFO,
333
334 /** Zip compression. */
335 ZIP,
336 }
337
338 /**
339 * Loads sampler data from a file. There are a few limitations with respect to live sampled data:
340 * <ol>
341 * <li>The number of decimals in numeric data is equal to the stored format.</li>
342 * <li>All extended data types are stored as {@code String}.</li>
343 * <li>Meta data types are not recognized, and hence stored as extended data types. Values are always stored as
344 * {@code String}.</li>
345 * </ol>
346 * @param file String; file
347 * @return Sampler data from file
348 */
349 public static SamplerData<?> loadFromFile(final String file)
350 {
351 return loadFromFile(file, new LinkedHashSet<ExtendedDataType<?, ?, ?, ?>>(), new LinkedHashSet<FilterDataType<?>>());
352 }
353
354 /**
355 * Loads sampler data from a file. There are a few limitations with respect to live sampled data:
356 * <ol>
357 * <li>The number of decimals in numeric data is equal to the stored format.</li>
358 * <li>All extended data types are stored as {@code String}, unless recognized by id as provided.</li>
359 * <li>Meta data types are not recognized, and hence stored as extended data types, unless recognized by id as provided.
360 * Values are always stored as {@code String}.</li>
361 * </ol>
362 * @param file String; file
363 * @param extendedDataTypes Set<ExtendedDataType<?, ?, ?, ?>>; extended data types
364 * @param metaDataTypes Set<MetaDataType<?>>; meta data types
365 * @return Sampler data from file
366 */
367 @SuppressWarnings("unchecked")
368 public static SamplerData<?> loadFromFile(final String file, final Set<ExtendedDataType<?, ?, ?, ?>> extendedDataTypes,
369 final Set<FilterDataType<?>> metaDataTypes)
370 {
371 /*
372 @SuppressWarnings("rawtypes")
373 SamplerData samplerData = new SamplerData();
374
375 // "traj#,linkId,laneId&dir,gtuId,t,x,v,a" meta data types, extended data types
376
377 // we can use the default meta data types: cross section, destination, origin, route and GTU type
378
379 Getter<NodeData> nodes = new Getter<NodeData>((id) -> new NodeData(id));
380 Getter<GtuTypeData> gtuTypes = new Getter<GtuTypeData>((id) -> new GtuTypeData(id));
381 Getter<RouteData> routes = new Getter<RouteData>((id) -> new RouteData(id));
382 Getter<LinkData> links = new Getter<LinkData>((id) -> new LinkData(id));
383 BiGetter<LinkData, LaneData> lanes = new BiGetter<LinkData, LaneData>((id, link) -> new LaneData(id, link));
384 BiGetter<LaneData, KpiLaneDirection> laneDirections = new BiGetter<LaneData, KpiLaneDirection>((dir,
385 lane) -> new KpiLaneDirection(lane, dir.equals("+") ? KpiGtuDirectionality.DIR_PLUS
386 : KpiGtuDirectionality.DIR_MINUS));
387 @SuppressWarnings("rawtypes")
388 Function<KpiLaneDirection, TrajectoryGroup> groupFunction = (laneDir) -> new TrajectoryGroup(Time.ZERO, laneDir);
389
390 String id = null;
391 if (!gtus.containsKey(id))
392 {
393 // NOTE: USE SEPARATE IDS HERE
394 gtus.put(id, new GtuData(id, nodeSupplier.apply(id), nodeSupplier.apply(id), gtuTypeSupplier.apply(id),
395 routeSupplier.apply(id)));
396 }
397 GtuData gtuData = gtus.get(id);
398
399 Trajectory<?> trajectory = new Trajectory(gtuData, metaData, extendedDataTypes, kpiLaneDirection);
400
401 // TODO: set data from outside
402 trajectory.add(position, speed, acceleration, time, gtu);
403
404 KpiLaneDirection laneDir = null;
405 ((TrajectoryGroup) samplerData.trajectories.computeIfAbsent(laneDir, groupFunction)).addTrajectory(trajectory);
406
407 return samplerData;
408 */
409 return null;
410 }
411
412 /**
413 * Returns a value from the map. Creates a value if needed.
414 * @param id String; id of object (key in map)
415 * @param map Map<String, T>; stored values
416 * @param producer Supplier<TT>; producer used if no value exists in the map
417 * @param <T> type
418 * @return value for the id
419 */
420 private final <T> T getOrCreate(final String id, final Map<String, T> map, final Function<String, T> producer)
421 {
422 if (!map.containsKey(id))
423 {
424 map.put(id, producer.apply(id));
425 }
426 return map.get(id);
427 }
428
429 // TABLE METHODS
430
431 /** {@inheritDoc} */
432 @Override
433 public Iterator<Record> iterator()
434 {
435 // TODO: local iterator over this.trajectories, trajectories per group, and length of each trajectory
436
437 // TODO: gathering the extended and filter data types should be done here, these are within the trajectories, and upon
438 // file loading, this should be mimicked
439
440 Iterator<KpiLaneDirection> laneIterator = this.trajectories.keySet().iterator();
441
442 return new Iterator<Record>()
443 {
444 private Iterator<Trajectory<G>> trajectoryIterator = laneIterator.hasNext() ? SamplerData.this.trajectories.get(
445 laneIterator.next()).iterator() : null;
446
447 private Trajectory<G> trajectory = this.trajectoryIterator != null && this.trajectoryIterator.hasNext()
448 ? this.trajectoryIterator.next() : null;
449
450 private Trajectory<G> currentTrajectory;
451
452 private int index;
453
454 @Override
455 public boolean hasNext()
456 {
457 if (this.index == this.currentTrajectory.size())
458 {
459 // get next trajectory
460
461 }
462 return true;
463 }
464
465 @Override
466 public Record next()
467 {
468 Recording/Record.html#Record">Record record = new Record()
469 {
470 @Override
471 public <T> T getValue(final Column<T> column)
472 {
473 return null;
474 }
475
476 @Override
477 public Object getValue(final String id)
478 {
479 return null;
480 }
481 };
482 this.index++;
483 return record;
484 }
485 };
486 }
487
488 /** {@inheritDoc} */
489 @Override
490 public boolean isEmpty()
491 {
492 for (TrajectoryGroup<G> group : this.trajectories.values())
493 {
494 for (Trajectory<G> trajectory : group.getTrajectories())
495 {
496 if (trajectory.size() > 0)
497 {
498 return false;
499 }
500 }
501 }
502 return true;
503 }
504
505 // LOCAL HELPER CLASSES TO IMPLEMENT INTERFACES //
506
507 /**
508 * Getter for single {@code String} input.
509 * @param <T> output value type
510 */
511 private static class Getter<T>
512 {
513
514 /** Map with cached values. */
515 private final Map<String, T> map = new LinkedHashMap<>();
516
517 /** Provider function. */
518 private Function<String, T> function;
519
520 /**
521 * Constructor.
522 * @param function Function<String, T>; provider function
523 */
524 Getter(final Function<String, T> function)
525 {
526 this.function = function;
527 }
528
529 /**
530 * Get value, from cache or provider function.
531 * @param id String; id
532 * @return T; value, from cache or provider function
533 */
534 public T get(final String id)
535 {
536 T t;
537 if (!this.map.containsKey(id))
538 {
539 t = this.function.apply(id);
540 this.map.put(id, t);
541 }
542 else
543 {
544 t = this.map.get(id);
545 }
546 return t;
547 }
548 }
549
550 /**
551 * Getter for dual {@code String} and {@code O} input.
552 * @param <O> type of second input (besides the first being {@code String})
553 * @param <T> output value type
554 */
555 private static class BiGetter<O, T>
556 {
557
558 /** Map with cached values. */
559 private final Map<String, T> map = new LinkedHashMap<>();
560
561 /** Provider function. */
562 private BiFunction<String, O, T> function;
563
564 /**
565 * Constructor.
566 * @param function BiFunction<String, T>; provider function
567 */
568 BiGetter(final BiFunction<String, O, T> function)
569 {
570 this.function = function;
571 }
572
573 /**
574 * Get value, from cache or provider function.
575 * @param id String; id
576 * @param o O; other object
577 * @return T; value, from cache or provider function
578 */
579 public T get(final String id, final O o)
580 {
581 T t;
582 if (!this.map.containsKey(id))
583 {
584 t = this.function.apply(id, o);
585 this.map.put(id, t);
586 }
587 else
588 {
589 t = this.map.get(id);
590 }
591 return t;
592 }
593 }
594
595 /** Helper class LinkData. */
596 private static class LinkData implements LinkDataInterface
597 {
598
599 /** Length ({@code null} always). */
600 private final Length length = null; // unknown in this context
601
602 /** Id. */
603 private final String id;
604
605 /** Lanes. */
606 private final List<LaneData> lanes = new ArrayList<>();
607
608 /**
609 * @param id String; id
610 */
611 LinkData(final String id)
612 {
613 this.id = id;
614 }
615
616 /** {@inheritDoc} */
617 @Override
618 public Length getLength()
619 {
620 return this.length;
621 }
622
623 /** {@inheritDoc} */
624 @Override
625 public List<? extends LaneDataInterface> getLaneDatas()
626 {
627 return this.lanes;
628 }
629
630 /** {@inheritDoc} */
631 @Override
632 public String getId()
633 {
634 return this.id;
635 }
636
637 }
638
639 /** Helper class LaneData. */
640 private static class LaneData implements LaneDataInterface
641 {
642
643 /** Length ({@code null} always). */
644 private final Length length = null; // unknown in this context
645
646 /** Id. */
647 private final String id;
648
649 /** Link. */
650 private final LinkData link;
651
652 /**
653 * Constructor.
654 * @param id String; id
655 * @param link LinkData; link
656 */
657 @SuppressWarnings("synthetic-access")
658 LaneData(final String id, final LinkData link)
659 {
660 this.id = id;
661 this.link = link;
662 link.lanes.add(this);
663 }
664
665 /** {@inheritDoc} */
666 @Override
667 public Length getLength()
668 {
669 return this.length;
670 }
671
672 /** {@inheritDoc} */
673 @Override
674 public LinkData getLinkData()
675 {
676 return this.link;
677 }
678
679 /** {@inheritDoc} */
680 @Override
681 public String getId()
682 {
683 return this.id;
684 }
685
686 }
687
688 /** Helper class NodeData. */
689 private static class NodeData implements NodeDataInterface
690 {
691
692 /** Node id. */
693 private String id;
694
695 /**
696 * Constructor.
697 * @param id String; id
698 */
699 NodeData(final String id)
700 {
701 this.id = id;
702 }
703
704 /** {@inheritDoc} */
705 @Override
706 public String getId()
707 {
708 return null;
709 }
710
711 }
712
713 /** Helper class GtuTypeData. */
714 private static class GtuTypeData implements GtuTypeDataInterface
715 {
716
717 /** Node id. */
718 private String id;
719
720 /**
721 * Constructor.
722 * @param id String; id
723 */
724 GtuTypeData(final String id)
725 {
726 this.id = id;
727 }
728
729 /** {@inheritDoc} */
730 @Override
731 public String getId()
732 {
733 return null;
734 }
735
736 }
737
738 /** Helper class RouteData. */
739 private static class RouteData implements RouteDataInterface
740 {
741
742 /** Node id. */
743 private String id;
744
745 /**
746 * Constructor.
747 * @param id String; id
748 */
749 RouteData(final String id)
750 {
751 this.id = id;
752 }
753
754 /** {@inheritDoc} */
755 @Override
756 public String getId()
757 {
758 return null;
759 }
760
761 }
762
763 /** Helper class GtuData. */
764 private static class GtuData implements GtuDataInterface
765 {
766
767 /** Id. */
768 private final String id;
769
770 /** Origin. */
771 private final NodeData origin;
772
773 /** Destination. */
774 private final NodeData destination;
775
776 /** GTU type. */
777 private final GtuTypeData gtuType;
778
779 /** Route. */
780 private final RouteData route;
781
782 /**
783 * @param id String; id
784 * @param origin NodeData; origin
785 * @param destination NodeData; destination
786 * @param gtuType GtuTypeData; GTU type
787 * @param route RouteData; route
788 */
789 GtuData(final String id, final NodeData origin, final NodeData destination, final GtuTypeData gtuType,
790 final RouteData route)
791 {
792 this.id = id;
793 this.origin = origin;
794 this.destination = destination;
795 this.gtuType = gtuType;
796 this.route = route;
797 }
798
799 /** {@inheritDoc} */
800 @Override
801 public String getId()
802 {
803 return this.id;
804 }
805
806 /** {@inheritDoc} */
807 @Override
808 public NodeDataInterface getOriginNodeData()
809 {
810 return this.origin;
811 }
812
813 /** {@inheritDoc} */
814 @Override
815 public NodeDataInterface getDestinationNodeData()
816 {
817 return this.destination;
818 }
819
820 /** {@inheritDoc} */
821 @Override
822 public GtuTypeDataInterface getGtuTypeData()
823 {
824 return this.gtuType;
825 }
826
827 /** {@inheritDoc} */
828 @Override
829 public RouteDataInterface getRouteData()
830 {
831 return this.route;
832 }
833
834 }
835
836 }