1 package org.opentrafficsim.graphs;
2
3 import static org.junit.Assert.assertEquals;
4 import static org.junit.Assert.assertFalse;
5 import static org.junit.Assert.assertTrue;
6 import static org.junit.Assert.fail;
7 import static org.opentrafficsim.core.gtu.GTUType.CAR;
8
9 import java.awt.Component;
10 import java.awt.Container;
11 import java.awt.event.ActionEvent;
12 import java.awt.event.MouseListener;
13 import java.util.ArrayList;
14 import java.util.List;
15
16 import javax.swing.JLabel;
17 import javax.swing.JOptionPane;
18
19 import org.djunits.unit.AccelerationUnit;
20 import org.djunits.unit.LengthUnit;
21 import org.djunits.unit.TimeUnit;
22 import org.djunits.unit.UNITS;
23 import org.djunits.value.vdouble.scalar.Acceleration;
24 import org.djunits.value.vdouble.scalar.DoubleScalar;
25 import org.djunits.value.vdouble.scalar.Duration;
26 import org.djunits.value.vdouble.scalar.Length;
27 import org.djunits.value.vdouble.scalar.Speed;
28 import org.djunits.value.vdouble.scalar.Time;
29 import org.jfree.chart.ChartPanel;
30 import org.jfree.data.DomainOrder;
31 import org.opentrafficsim.base.parameters.ParameterTypes;
32 import org.opentrafficsim.core.dsol.OTSModelInterface;
33 import org.opentrafficsim.core.geometry.OTSPoint3D;
34 import org.opentrafficsim.core.gtu.GTUType;
35 import org.opentrafficsim.core.network.Network;
36 import org.opentrafficsim.core.network.OTSNetwork;
37 import org.opentrafficsim.core.network.OTSNode;
38 import org.opentrafficsim.road.car.CarTest;
39 import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU;
40 import org.opentrafficsim.road.gtu.lane.tactical.following.FixedAccelerationModel;
41 import org.opentrafficsim.road.gtu.lane.tactical.following.SequentialFixedAccelerationModel;
42 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.Egoistic;
43 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.LaneChangeModel;
44 import org.opentrafficsim.road.network.factory.LaneFactory;
45 import org.opentrafficsim.road.network.lane.Lane;
46 import org.opentrafficsim.road.network.lane.LaneType;
47 import org.opentrafficsim.simulationengine.SimpleSimulator;
48
49 import nl.tudelft.simulation.dsol.SimRuntimeException;
50 import nl.tudelft.simulation.dsol.simtime.SimTimeDoubleUnit;
51 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
52
53
54
55
56
57
58
59
60
61
62
63 public class ContourPlotTest implements UNITS
64 {
65
66
67
68
69
70
71
72
73 private List<Lane> dummyPath(final Network network, final LaneType laneType, final GTUType gtuType) throws Exception
74 {
75 OTSNode b = new OTSNode(network, "B", new OTSPoint3D(12345, 0, 0));
76 ArrayList<Lane> result = new ArrayList<Lane>();
77 Lane[] lanes = LaneFactory.makeMultiLane(network, "AtoB", new OTSNode(network, "A", new OTSPoint3D(1234, 0, 0)), b,
78 null, 1, laneType, new Speed(100, KM_PER_HOUR), null);
79 result.add(lanes[0]);
80
81 lanes = LaneFactory.makeMultiLane(network, "BtoC", b, new OTSNode(network, "C", new OTSPoint3D(99999, 0, 0)), null, 1,
82 laneType, new Speed(100, KM_PER_HOUR), null);
83
84
85 return result;
86 }
87
88
89
90
91
92 @SuppressWarnings("static-method")
93
94 public final void accelerationContourTest() throws Exception
95 {
96 Network network = new OTSNetwork("contour test network");
97 GTUType gtuType = CAR;
98 LaneType laneType = LaneType.TWO_WAY_LANE;
99 List<Lane> path = dummyPath(network, laneType, gtuType);
100 AccelerationContourPlot acp = new AccelerationContourPlot("Acceleration", path);
101 assertTrue("newly created AccelerationContourPlot should not be null", null != acp);
102 assertEquals("SeriesKey should be \"acceleration\"", "acceleration", acp.getSeriesKey(0));
103 standardContourTests(acp, path.get(0), gtuType, Double.NaN, 0);
104 }
105
106
107
108
109
110 @SuppressWarnings("static-method")
111
112 public final void densityContourTest() throws Exception
113 {
114 Network network = new OTSNetwork("contour test network");
115 GTUType gtuType = CAR;
116 LaneType laneType = LaneType.TWO_WAY_LANE;
117 List<Lane> path = dummyPath(network, laneType, gtuType);
118 DensityContourPlot dcp = new DensityContourPlot("Density", path);
119 assertTrue("newly created DensityContourPlot should not be null", null != dcp);
120 assertEquals("SeriesKey should be \"density\"", "density", dcp.getSeriesKey(0));
121 standardContourTests(dcp, path.get(0), gtuType, 0, Double.NaN);
122 }
123
124
125
126
127
128
129
130
131
132 static void printMatrix(final ContourPlot cp, final int fromX, final int toX, final int fromY, final int toY)
133 {
134 System.out.println("Contour plot data:");
135 int maxItem = cp.getItemCount(0);
136 for (int y = fromY; y <= toY; y++)
137 {
138 System.out.print(String.format("y=%3d ", y));
139 for (int x = fromX; x <= toX; x++)
140 {
141
142 int item;
143 for (item = 0; item < maxItem; item++)
144 {
145 if (cp.getXValue(0, item) == x && cp.getYValue(0, item) == y)
146 {
147 break;
148 }
149 }
150 if (item < maxItem)
151 {
152 System.out.print(String.format("%10.6f", cp.getZValue(0, item)));
153 }
154 else
155 {
156 System.out.print(" -------- ");
157 }
158 }
159 System.out.println("");
160 }
161 System.out.print("");
162 }
163
164
165
166
167
168 @SuppressWarnings("static-method")
169
170 public final void flowContourTest() throws Exception
171 {
172 Network network = new OTSNetwork("contour test network");
173 GTUType gtuType = CAR;
174 LaneType laneType = LaneType.TWO_WAY_LANE;
175 List<Lane> path = dummyPath(network, laneType, gtuType);
176 FlowContourPlot fcp = new FlowContourPlot("Density", path);
177 assertTrue("newly created DensityContourPlot should not be null", null != fcp);
178 assertEquals("SeriesKey should be \"flow\"", "flow", fcp.getSeriesKey(0));
179 standardContourTests(fcp, path.get(0), gtuType, 0, Double.NaN);
180 }
181
182
183
184
185
186 @SuppressWarnings("static-method")
187
188 public final void speedContourTest() throws Exception
189 {
190 Network network = new OTSNetwork("contour test network");
191 GTUType gtuType = CAR;
192 LaneType laneType = LaneType.TWO_WAY_LANE;
193 List<Lane> path = dummyPath(network, laneType, gtuType);
194 SpeedContourPlot scp = new SpeedContourPlot("Density", path);
195 assertTrue("newly created DensityContourPlot should not be null", null != scp);
196 assertEquals("SeriesKey should be \"speed\"", "speed", scp.getSeriesKey(0));
197 standardContourTests(scp, path.get(0), gtuType, Double.NaN, 50);
198 }
199
200
201
202
203
204
205
206
207
208
209
210
211 public static void standardContourTests(final ContourPlot cp, final Lane lane, final GTUType gtuType,
212 final double expectedZValue, final double expectedZValueWithTraffic) throws Exception
213 {
214 assertEquals("seriesCount should be 1", 1, cp.getSeriesCount());
215 assertEquals("domainOrder should be ASCENDING", DomainOrder.ASCENDING, cp.getDomainOrder());
216 assertEquals("indexOf always returns 0", 0, cp.indexOf(0));
217 assertEquals("indexOf always returns 0", 0, cp.indexOf("abc"));
218 assertEquals("getGroup always returns null", null, cp.getGroup());
219 int xBins = cp.xAxisBins();
220 int yBins = cp.yAxisBins();
221 int expectedXBins = (int) Math
222 .ceil((DoubleScalar.minus(ContourPlot.INITIALUPPERTIMEBOUND, ContourPlot.INITIALLOWERTIMEBOUND).getSI())
223 / ContourPlot.STANDARDTIMEGRANULARITIES[ContourPlot.STANDARDINITIALTIMEGRANULARITYINDEX]);
224 assertEquals("Initial xBins should be " + expectedXBins, expectedXBins, xBins);
225 int expectedYBins = (int) Math.ceil(lane.getLength().getSI()
226 / ContourPlot.STANDARDDISTANCEGRANULARITIES[ContourPlot.STANDARDINITIALDISTANCEGRANULARITYINDEX]);
227 assertEquals("yBins should be " + expectedYBins, expectedYBins, yBins);
228 int bins = cp.getItemCount(0);
229 assertEquals("Total bin count is product of xBins * yBins", xBins * yBins, bins);
230
231
232 String initialLowerTimeBoundString = ContourPlot.INITIALLOWERTIMEBOUND.toString();
233 String initialUpperTimeBoundString = ContourPlot.INITIALUPPERTIMEBOUND.toString();
234
235 for (double timeGranularity : ContourPlot.STANDARDTIMEGRANULARITIES)
236 {
237 cp.actionPerformed(new ActionEvent(cp, 0, "setTimeGranularity " + timeGranularity));
238 for (double distanceGranularity : ContourPlot.STANDARDDISTANCEGRANULARITIES)
239 {
240 cp.actionPerformed(new ActionEvent(cp, 0, "setDistanceGranularity " + distanceGranularity));
241 cp.reGraph();
242 expectedXBins = (int) Math
243 .ceil((DoubleScalar.minus(ContourPlot.INITIALUPPERTIMEBOUND, ContourPlot.INITIALLOWERTIMEBOUND).getSI())
244 / timeGranularity);
245 xBins = cp.xAxisBins();
246 assertEquals("Modified xBins should be " + expectedXBins, expectedXBins, xBins);
247 expectedYBins = (int) Math.ceil(lane.getLength().getSI() / distanceGranularity);
248 yBins = cp.yAxisBins();
249 assertEquals("Modified yBins should be " + expectedYBins, expectedYBins, yBins);
250 bins = cp.getItemCount(0);
251 assertEquals("Total bin count is product of xBins * yBins", xBins * yBins, bins);
252 for (int item = 0; item < bins; item++)
253 {
254 double x = cp.getXValue(0, item);
255 assertTrue("X should be >= " + initialLowerTimeBoundString, x >= ContourPlot.INITIALLOWERTIMEBOUND.getSI());
256 assertTrue("X should be <= " + initialUpperTimeBoundString, x <= ContourPlot.INITIALUPPERTIMEBOUND.getSI());
257 Number alternateX = cp.getX(0, item);
258 assertEquals("getXValue and getX should return things that have the same value", x,
259 alternateX.doubleValue(), 0.000001);
260 double y = cp.getYValue(0, item);
261 Number alternateY = cp.getY(0, item);
262 assertEquals("getYValue and getY should return things that have the same value", y,
263 alternateY.doubleValue(), 0.000001);
264 double z = cp.getZValue(0, item);
265 if (Double.isNaN(expectedZValue))
266 {
267 assertTrue("Z value should be NaN", Double.isNaN(z));
268 }
269 else
270 {
271 assertEquals("Z value should be " + expectedZValue, expectedZValue, z, 0.0001);
272 }
273 Number alternateZ = cp.getZ(0, item);
274 if (Double.isNaN(expectedZValue))
275 {
276 assertTrue("Alternate Z value should be NaN", Double.isNaN(alternateZ.doubleValue()));
277 }
278 else
279 {
280 assertEquals("Alternate Z value should be " + expectedZValue, expectedZValue, alternateZ.doubleValue(),
281 0.0000);
282 }
283 }
284 try
285 {
286 cp.getXValue(0, -1);
287 fail("Should have thrown an Exception");
288 }
289 catch (RuntimeException e)
290 {
291
292 }
293 try
294 {
295 cp.getXValue(0, bins);
296 fail("Should have thrown an Exception");
297 }
298 catch (RuntimeException e)
299 {
300
301 }
302 try
303 {
304 cp.yAxisBin(-1);
305 fail("Should have thrown an Exception");
306 }
307 catch (RuntimeException e)
308 {
309
310 }
311 try
312 {
313 cp.yAxisBin(bins);
314 fail("Should have thrown an Exception");
315 }
316 catch (RuntimeException e)
317 {
318
319 }
320 }
321 }
322
323 try
324 {
325 cp.actionPerformed(new ActionEvent(cp, 0, "blabla"));
326 fail("Should have thrown an Exception");
327 }
328 catch (RuntimeException e)
329 {
330
331 }
332 try
333 {
334 cp.actionPerformed(new ActionEvent(cp, 0, "setDistanceGranularity -1"));
335 fail("Should have thrown an Exception");
336 }
337 catch (RuntimeException e)
338 {
339
340 }
341 try
342 {
343 cp.actionPerformed(new ActionEvent(cp, 0, "setDistanceGranularity abc"));
344 fail("Should have thrown an Exception");
345 }
346 catch (RuntimeException e)
347 {
348
349 }
350 try
351 {
352 cp.actionPerformed(new ActionEvent(cp, 0, "setDistanceGranularitIE 10"));
353 fail("Should have thrown an Exception");
354 }
355 catch (RuntimeException e)
356 {
357
358 }
359
360 final double useTimeGranularity = 30;
361 cp.actionPerformed(new ActionEvent(cp, 0, "setTimeGranularity " + useTimeGranularity));
362 final double useDistanceGranularity =
363 ContourPlot.STANDARDDISTANCEGRANULARITIES[ContourPlot.STANDARDDISTANCEGRANULARITIES.length - 1];
364 cp.actionPerformed(new ActionEvent(cp, 0, "setDistanceGranularity " + useDistanceGranularity));
365 cp.reGraph();
366 bins = cp.getItemCount(0);
367 Time initialTime = new Time(0, TimeUnit.BASE_SECOND);
368 Length initialPosition = new Length(100, METER);
369 Speed initialSpeed = new Speed(50, KM_PER_HOUR);
370 ContourPlotModel model = new ContourPlotModel();
371 SimpleSimulator simulator =
372 new SimpleSimulator(initialTime, new Duration(0, SECOND), new Duration(1800, SECOND), model);
373
374 SequentialFixedAccelerationModel gtuFollowingModel =
375 new SequentialFixedAccelerationModel(simulator, new Acceleration(2.0, AccelerationUnit.METER_PER_SECOND_2));
376
377 gtuFollowingModel
378 .addStep(new FixedAccelerationModel(new Acceleration(0, METER_PER_SECOND_2), new Duration(60, SECOND)));
379
380 gtuFollowingModel
381 .addStep(new FixedAccelerationModel(new Acceleration(0, METER_PER_SECOND_2), new Duration(600, SECOND)));
382
383 gtuFollowingModel
384 .addStep(new FixedAccelerationModel(new Acceleration(0, METER_PER_SECOND_2), new Duration(300, SECOND)));
385 LaneChangeModel laneChangeModel = new Egoistic();
386 OTSNetwork network = new OTSNetwork("network");
387
388
389 for (int item = 0; item < bins; item++)
390 {
391 double x = cp.getXValue(0, item);
392 assertTrue("X should be >= " + ContourPlot.INITIALLOWERTIMEBOUND, x >= ContourPlot.INITIALLOWERTIMEBOUND.getSI());
393 assertTrue("X should be <= " + ContourPlot.INITIALUPPERTIMEBOUND, x <= ContourPlot.INITIALUPPERTIMEBOUND.getSI());
394 Number alternateX = cp.getX(0, item);
395 assertEquals("getXValue and getX should return things that have the same value", x, alternateX.doubleValue(),
396 0.000001);
397 double y = cp.getYValue(0, item);
398 Number alternateY = cp.getY(0, item);
399 assertEquals("getYValue and getY should return things that have the same value", y, alternateY.doubleValue(),
400 0.000001);
401 double z = cp.getZValue(0, item);
402 if (Double.isNaN(expectedZValue))
403 {
404 assertTrue("Z value should be NaN (got " + z + ")", Double.isNaN(z));
405 }
406 else
407 {
408 assertEquals("Z value should be " + expectedZValue, expectedZValue, z, 0.0001);
409 }
410 Number alternateZ = cp.getZ(0, item);
411 if (Double.isNaN(expectedZValue))
412 {
413 assertTrue("Alternate Z value should be NaN", Double.isNaN(alternateZ.doubleValue()));
414 }
415 else
416 {
417 assertEquals("Alternate Z value should be " + expectedZValue, expectedZValue, alternateZ.doubleValue(), 0.0000);
418 }
419 }
420
421 LaneBasedIndividualGTU car = CarTest.makeReferenceCar("0", gtuType, lane, initialPosition, initialSpeed, simulator,
422 gtuFollowingModel, laneChangeModel, network);
423 car.getParameters().setParameter(ParameterTypes.LOOKAHEAD, new Length(10, LengthUnit.KILOMETER));
424
425
426
427 double stopTime = gtuFollowingModel.timeAfterCompletionOfStep(0).si;
428 simulator.runUpToAndIncluding(new Time(stopTime, TimeUnit.BASE_SECOND));
429 while (simulator.isRunning())
430 {
431 try
432 {
433 Thread.sleep(10);
434 }
435 catch (InterruptedException ie)
436 {
437 ie = null;
438 }
439 }
440
441
442
443
444 for (int item = 0; item < bins; item++)
445 {
446 double x = cp.getXValue(0, item);
447 assertTrue("X should be >= " + ContourPlot.INITIALLOWERTIMEBOUND, x >= ContourPlot.INITIALLOWERTIMEBOUND.getSI());
448 assertTrue("X should be <= " + ContourPlot.INITIALUPPERTIMEBOUND, x <= ContourPlot.INITIALUPPERTIMEBOUND.getSI());
449 Number alternateX = cp.getX(0, item);
450 assertEquals("getXValue and getX should return things that have the same value", x, alternateX.doubleValue(),
451 0.000001);
452 double y = cp.getYValue(0, item);
453 Number alternateY = cp.getY(0, item);
454 assertEquals("getYValue and getY should return things that have the same value", y, alternateY.doubleValue(),
455 0.000001);
456 double z = cp.getZValue(0, item);
457
458
459
460
461
462 boolean hit = false;
463 if (x + useTimeGranularity >= 0
464 && x < 60)
465 {
466
467 Time cellStartTime =
468 new Time(Math.max(car.getOperationalPlan().getStartTime().getSI(), x), TimeUnit.BASE_SECOND);
469 Time cellEndTime = new Time(Math.min(car.getOperationalPlan().getEndTime().getSI(), x + useTimeGranularity),
470 TimeUnit.BASE_SECOND);
471
472
473
474
475
476 double xAtCellStartTime = initialPosition.si + initialSpeed.si * cellStartTime.si;
477 double xAtCellEndTime = initialPosition.si + initialSpeed.si * cellEndTime.si;
478 if (xAtCellStartTime < y + useDistanceGranularity && xAtCellEndTime >= y)
479 {
480 hit = true;
481 }
482 }
483
484
485
486
487 Number alternateZ = cp.getZ(0, item);
488 if (hit)
489 {
490 if (!Double.isNaN(expectedZValueWithTraffic))
491 {
492 if (Double.isNaN(z))
493 {
494 printMatrix(cp, 0, 10, 0, 10);
495 System.out.println("Oops - z is NaN, expected z value with traffic is " + expectedZValueWithTraffic);
496 }
497 assertEquals("Z value should be " + expectedZValueWithTraffic, expectedZValueWithTraffic, z, 0.0001);
498 assertEquals("Z value should be " + expectedZValueWithTraffic, expectedZValueWithTraffic,
499 alternateZ.doubleValue(), 0.0001);
500 }
501 else
502 {
503 if (Double.isNaN(expectedZValue))
504 {
505 assertFalse("Z value should not be NaN", Double.isNaN(z));
506 }
507 }
508 }
509 else
510 {
511 if (Double.isNaN(expectedZValue))
512 {
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531 assertTrue("Z value should be NaN", Double.isNaN(z));
532 }
533 else
534 {
535 assertEquals("Z value should be " + expectedZValue, expectedZValue, z, 0.0001);
536 }
537 if (Double.isNaN(expectedZValue))
538 {
539 assertTrue("Alternate Z value should be NaN", Double.isNaN(alternateZ.doubleValue()));
540 }
541 else
542 {
543 assertEquals("Alternate Z value should be " + expectedZValue, expectedZValue, alternateZ.doubleValue(),
544 0.0000);
545 }
546 }
547 }
548
549
550 stopTime = gtuFollowingModel.timeAfterCompletionOfStep(1).si;
551 simulator.runUpToAndIncluding(new Time(stopTime, TimeUnit.BASE_SECOND));
552 while (simulator.isRunning())
553 {
554 try
555 {
556 Thread.sleep(10);
557 }
558 catch (InterruptedException ie)
559 {
560 ie = null;
561 }
562 }
563
564
565 xBins = cp.xAxisBins();
566 bins = cp.getItemCount(0);
567 double observedHighestTime = Double.MIN_VALUE;
568 for (int bin = 0; bin < bins; bin++)
569 {
570 double xValue = cp.getXValue(0, bin);
571 if (xValue > observedHighestTime)
572 {
573 observedHighestTime = xValue;
574 }
575 }
576 double expectedHighestTime =
577 Math.floor((car.getSimulator().getSimulatorTime().si - 0.001) / useTimeGranularity) * useTimeGranularity;
578 assertEquals("Time range should run up to " + expectedHighestTime, expectedHighestTime, observedHighestTime, 0.0001);
579
580
581 JLabel hintPanel = null;
582 ChartPanel chartPanel = null;
583 for (Component c0 : cp.getComponents())
584 {
585 for (Component c1 : ((Container) c0).getComponents())
586 {
587 if (c1 instanceof Container)
588 {
589 for (Component c2 : ((Container) c1).getComponents())
590 {
591
592 if (c2 instanceof Container)
593 {
594 for (Component c3 : ((Container) c2).getComponents())
595 {
596
597 if (c3 instanceof JLabel)
598 {
599 if (null == hintPanel)
600 {
601 hintPanel = (JLabel) c3;
602 }
603 else
604 {
605 fail("There should be only one JPanel in a ContourPlot");
606 }
607 }
608 if (c3 instanceof ChartPanel)
609 {
610 if (null == chartPanel)
611 {
612 chartPanel = (ChartPanel) c3;
613 }
614 else
615 {
616 fail("There should be only one ChartPanel in a ContourPlot");
617 }
618 }
619 }
620 }
621 }
622 }
623 }
624 }
625 if (null == hintPanel)
626 {
627 fail("Could not find a JLabel in ContourPlot");
628 }
629 if (null == chartPanel)
630 {
631 fail("Could not find a ChartPanel in ContourPlot");
632 }
633 assertEquals("Initially the text should be a single space", " ", hintPanel.getText());
634 PointerHandler ph = null;
635 for (MouseListener ml : chartPanel.getMouseListeners())
636 {
637 if (ml instanceof PointerHandler)
638 {
639 if (null == ph)
640 {
641 ph = (PointerHandler) ml;
642 }
643 else
644 {
645 fail("There should be only one PointerHandler on the chartPanel");
646 }
647 }
648 }
649 if (null == ph)
650 {
651 fail("Could not find the PointerHandler for the chartPanel");
652 }
653 ph.updateHint(1, 2);
654
655 assertFalse("Hint should not be a single space", " ".equals(hintPanel.getText()));
656 ph.updateHint(Double.NaN, Double.NaN);
657 assertEquals("The text should again be a single space", " ", hintPanel.getText());
658 }
659
660
661
662
663
664
665 public static void main(final String[] args) throws Exception
666 {
667 ContourPlotTest cpt = new ContourPlotTest();
668 System.out.println("Click the OK button");
669 JOptionPane.showMessageDialog(null, "ContourPlot", "Start experiment", JOptionPane.INFORMATION_MESSAGE);
670 System.out.println("Running ...");
671 cpt.densityContourTest();
672 System.out.println("Finished");
673 }
674
675 }
676
677
678
679
680
681
682
683
684
685
686 class ContourPlotModel implements OTSModelInterface
687 {
688
689
690 private static final long serialVersionUID = 20150209L;
691
692
693 @Override
694 public void constructModel(final SimulatorInterface<Time, Duration, SimTimeDoubleUnit> simulator) throws SimRuntimeException
695 {
696
697 }
698
699
700 @Override
701 public SimulatorInterface<Time, Duration, SimTimeDoubleUnit> getSimulator()
702
703 {
704 return null;
705 }
706
707
708 @Override
709 public OTSNetwork getNetwork()
710 {
711 return null;
712 }
713
714 }