View Javadoc
1   package org.opentrafficsim.draw.graphs;
2   
3   import static org.junit.Assert.assertEquals;
4   import static org.junit.Assert.assertNull;
5   import static org.junit.Assert.assertTrue;
6   import static org.junit.Assert.fail;
7   
8   import java.awt.event.ActionEvent;
9   import java.util.ArrayList;
10  import java.util.HashSet;
11  import java.util.LinkedHashSet;
12  import java.util.List;
13  import java.util.Set;
14  
15  import javax.naming.NamingException;
16  import javax.swing.JOptionPane;
17  
18  import org.djunits.unit.AccelerationUnit;
19  import org.djunits.unit.TimeUnit;
20  import org.djunits.unit.util.UNITS;
21  import org.djunits.value.vdouble.scalar.Acceleration;
22  import org.djunits.value.vdouble.scalar.Direction;
23  import org.djunits.value.vdouble.scalar.Duration;
24  import org.djunits.value.vdouble.scalar.Length;
25  import org.djunits.value.vdouble.scalar.Speed;
26  import org.djunits.value.vdouble.scalar.Time;
27  import org.djutils.immutablecollections.ImmutableArrayList;
28  import org.jfree.data.DomainOrder;
29  import org.junit.Test;
30  import org.mockito.ArgumentMatchers;
31  import org.mockito.Mockito;
32  import org.mockito.invocation.InvocationOnMock;
33  import org.mockito.stubbing.Answer;
34  import org.opentrafficsim.core.dsol.OTSSimulator;
35  import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
36  import org.opentrafficsim.core.geometry.OTSGeometryException;
37  import org.opentrafficsim.core.geometry.OTSPoint3D;
38  import org.opentrafficsim.core.gtu.GTUDirectionality;
39  import org.opentrafficsim.core.gtu.GTUException;
40  import org.opentrafficsim.core.gtu.GTUType;
41  import org.opentrafficsim.core.network.NetworkException;
42  import org.opentrafficsim.draw.graphs.GraphPath.Section;
43  import org.opentrafficsim.draw.graphs.road.GraphLaneUtil;
44  import org.opentrafficsim.kpi.interfaces.LaneDataInterface;
45  import org.opentrafficsim.kpi.sampling.KpiLaneDirection;
46  import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU;
47  import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedCFLCTacticalPlanner;
48  import org.opentrafficsim.road.gtu.lane.tactical.following.FixedAccelerationModel;
49  import org.opentrafficsim.road.gtu.lane.tactical.following.GTUFollowingModelOld;
50  import org.opentrafficsim.road.gtu.lane.tactical.following.SequentialFixedAccelerationModel;
51  import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.Egoistic;
52  import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.LaneChangeModel;
53  import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
54  import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlanner;
55  import org.opentrafficsim.road.network.OTSRoadNetwork;
56  import org.opentrafficsim.road.network.factory.LaneFactory;
57  import org.opentrafficsim.road.network.lane.DirectedLanePosition;
58  import org.opentrafficsim.road.network.lane.Lane;
59  import org.opentrafficsim.road.network.lane.LaneDirection;
60  import org.opentrafficsim.road.network.lane.LaneType;
61  import org.opentrafficsim.road.network.lane.OTSRoadNode;
62  import org.opentrafficsim.road.network.sampling.RoadSampler;
63  
64  import nl.tudelft.simulation.dsol.SimRuntimeException;
65  import nl.tudelft.simulation.dsol.formalisms.eventscheduling.SimEvent;
66  import nl.tudelft.simulation.dsol.formalisms.eventscheduling.SimEventInterface;
67  import nl.tudelft.simulation.dsol.simtime.SimTimeDoubleUnit;
68  
69  /**
70   * Test the non-GUI part of the ContourPlot class.
71   * <p>
72   * Copyright (c) 2013-2018 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
73   * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
74   * <p>
75   * $LastChangedDate: 2015-09-14 01:33:02 +0200 (Mon, 14 Sep 2015) $, @version $Revision: 1401 $, by $Author: averbraeck $,
76   * initial version Aug 21, 2014 <br>
77   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
78   */
79  public class ContourPlotTest implements UNITS
80  {
81  
82      /** Mocked GraphPath. */
83      @SuppressWarnings("unchecked")
84      GraphPath<KpiLaneDirection> mockedPath = Mockito.mock(GraphPath.class);
85  
86      Section<KpiLaneDirection> section0 = Mockito.mock(Section.class);
87  
88      Section<KpiLaneDirection> section1 = Mockito.mock(Section.class);
89  
90      KpiLaneDirection direction0 = Mockito.mock(KpiLaneDirection.class);
91  
92      KpiLaneDirection direction1 = Mockito.mock(KpiLaneDirection.class);
93  
94      LaneDataInterface mockedLane0 = Mockito.mock(LaneDataInterface.class);
95  
96      LaneDataInterface mockedLane1 = Mockito.mock(LaneDataInterface.class);
97  
98      RoadSampler mockedRoadSampler = Mockito.mock(RoadSampler.class);
99  
100     OTSSimulatorInterface mockedSimulator = Mockito.mock(OTSSimulatorInterface.class);
101 
102     SimEventInterface<SimTimeDoubleUnit> lastScheduledEvent = null;
103 
104     /**
105      * Create a network and a path for the tests.
106      * @param simulator OTSSimulatorInterface; the simulator
107      * @param network OTSRoadNetwork; the network
108      * @return GraphPath&lt;KpiLaneDirection&gt;; the dummy path
109      * @throws Exception when something goes wrong (should not happen)
110      */
111     private GraphPath<KpiLaneDirection> dummyPath(final OTSSimulatorInterface simulator, final OTSRoadNetwork network)
112             throws Exception
113     {
114         LaneType laneType = network.getLaneType(LaneType.DEFAULTS.TWO_WAY_LANE);
115         OTSRoadNode b = new OTSRoadNode(network, "B", new OTSPoint3D(12345, 0, 0), Direction.ZERO);
116         ArrayList<Lane> result = new ArrayList<Lane>();
117         Lane[] lanes = LaneFactory.makeMultiLane(network, "AtoB",
118                 new OTSRoadNode(network, "A", new OTSPoint3D(1234, 0, 0), Direction.ZERO), b, null, 1, laneType,
119                 new Speed(100, KM_PER_HOUR), simulator);
120         result.add(lanes[0]);
121         // Make a continuation lane to prevent errors when the operational plan exceeds the available remaining length
122         lanes = LaneFactory.makeMultiLane(network, "BtoC", b,
123                 new OTSRoadNode(network, "C", new OTSPoint3D(99999, 0, 0), Direction.ZERO), null, 1, laneType,
124                 new Speed(100, KM_PER_HOUR), null);
125         return GraphLaneUtil.createPath("AtoB", new LaneDirection(lanes[0], GTUDirectionality.DIR_PLUS));
126     }
127 
128     /**
129      * Code common to all contour plot tests.
130      * @throws SimRuntimeException if that happens uncaught; this test has failed
131      */
132     public final void setUp() throws SimRuntimeException
133     {
134         Mockito.when(this.mockedPath.getTotalLength()).thenReturn(Length.valueOf("2000m"));
135         Mockito.when(this.mockedPath.getNumberOfSeries()).thenReturn(2);
136         Mockito.when(this.mockedPath.get(0)).thenReturn(this.section0);
137         Mockito.when(this.mockedPath.get(1)).thenReturn(this.section1);
138         Mockito.when(this.mockedPath.getStartDistance(this.section0)).thenReturn(Length.ZERO);
139         Mockito.when(this.mockedPath.getStartDistance(this.section1)).thenReturn(Length.valueOf("1234m"));
140         Mockito.when(this.mockedPath.getSpeedLimit()).thenReturn(Speed.valueOf("100 km/h"));
141         List<Section<KpiLaneDirection>> sectionList = new ArrayList<>();
142         sectionList.add(this.section0);
143         sectionList.add(this.section1);
144         Mockito.when(this.mockedLane0.getLength()).thenReturn(Length.valueOf("1234m"));
145         Mockito.when(this.mockedLane1.getLength()).thenReturn(Length.valueOf("766m"));
146         Mockito.when(this.direction0.getLaneData()).thenReturn(this.mockedLane0);
147         Mockito.when(this.direction1.getLaneData()).thenReturn(this.mockedLane1);
148         Set<KpiLaneDirection> set0 = new HashSet<>();
149         set0.add(this.direction0);
150         Mockito.when(this.section0.iterator()).thenReturn(set0.iterator());
151         Set<KpiLaneDirection> set1 = new HashSet<>();
152         set1.add(this.direction1);
153         Mockito.when(this.section0.iterator()).thenReturn(set0.iterator());
154         Mockito.when(this.section1.iterator()).thenReturn(set1.iterator());
155         Mockito.when(this.mockedPath.getSections()).thenReturn(new ImmutableArrayList<>(sectionList));
156         Mockito.when(this.section0.getLength()).thenReturn(Length.valueOf("1234m"));
157         Mockito.when(this.section1.getLength()).thenReturn(Length.valueOf("766m"));
158         Mockito.when(this.mockedSimulator.scheduleEventAbs(ArgumentMatchers.any(Time.class), ArgumentMatchers.any(),
159                 ArgumentMatchers.any(), ArgumentMatchers.anyString(), ArgumentMatchers.isNull()))
160                 .thenAnswer(new Answer<SimEventInterface<SimTimeDoubleUnit>>()
161                 {
162                     @Override
163                     public SimEventInterface<SimTimeDoubleUnit> answer(final InvocationOnMock invocation) throws Throwable
164                     {
165                         ContourPlotTest.this.lastScheduledEvent = new SimEvent.TimeDoubleUnit(invocation.getArgument(0),
166                                 invocation.getArgument(1), invocation.getArgument(2), "update", null);
167                         return ContourPlotTest.this.lastScheduledEvent;
168                     }
169                 });
170         Mockito.when(this.mockedSimulator.getSimulatorTime()).thenReturn(Time.ZERO);
171     }
172 
173     /**
174      * Test the ContourPlotAcceleration.
175      * @throws Exception when something goes wrong (should not happen)
176      */
177     @Test
178     public final void accelerationContourTest() throws Exception
179     {
180         setUp();
181         ContourDataSource<?> dataPool = new ContourDataSource<>(this.mockedRoadSampler, this.mockedPath);
182         ContourPlotAcceleration acp = new ContourPlotAcceleration("acceleration", this.mockedSimulator, dataPool);
183         assertTrue("newly created AccelerationContourPlot should not be null", null != acp);
184         assertEquals("SeriesKey should be \"acceleration\"", "acceleration", acp.getSeriesKey(0));
185         standardContourTests(this.mockedSimulator, acp, this.mockedPath, Double.NaN, 0);
186     }
187 
188     /**
189      * Test the ContourPlotDensity.
190      * @throws Exception when something goes wrong (should not happen)
191      */
192     @Test
193     public final void densityContourTest() throws Exception
194     {
195         OTSRoadNetwork network = new OTSRoadNetwork("density contour test network", true);
196         OTSSimulatorInterface simulator = new OTSSimulator();
197         GraphPath<KpiLaneDirection> path = dummyPath(simulator, network);
198         RoadSampler sampler = new RoadSampler(simulator);
199         ContourDataSource<?> dataPool = new ContourDataSource<>(sampler, path);
200         ContourPlotDensity dcp = new ContourPlotDensity("Density", simulator, dataPool);
201         assertTrue("newly created DensityContourPlot should not be null", null != dcp);
202         assertEquals("SeriesKey should be \"density\"", "density", dcp.getSeriesKey(0));
203         GTUType gtuType = network.getGtuType(GTUType.DEFAULTS.CAR);
204         standardContourTests(simulator, dcp, path, 0, Double.NaN);
205     }
206 
207     /**
208      * Test the ContourPlotFlow.
209      * @throws Exception when something goes wrong (should not happen)
210      */
211     @Test
212     public final void flowContourTest() throws Exception
213     {
214         OTSRoadNetwork network = new OTSRoadNetwork("flow contour test network", true);
215         OTSSimulatorInterface simulator = new OTSSimulator();
216         GraphPath<KpiLaneDirection> path = dummyPath(simulator, network);
217         RoadSampler sampler = new RoadSampler(simulator);
218         ContourDataSource<?> dataPool = new ContourDataSource<>(sampler, path);
219         ContourPlotFlow fcp = new ContourPlotFlow("Density", simulator, dataPool);
220         assertTrue("newly created DensityContourPlot should not be null", null != fcp);
221         assertEquals("SeriesKey should be \"flow\"", "flow", fcp.getSeriesKey(0));
222         GTUType gtuType = network.getGtuType(GTUType.DEFAULTS.CAR);
223         standardContourTests(simulator, fcp, path, 0, Double.NaN);
224     }
225 
226     /**
227      * Test the SpeedContourPlot.
228      * @throws Exception when something goes wrong (should not happen)
229      */
230     @Test
231     public final void speedContourTest() throws Exception
232     {
233         OTSRoadNetwork network = new OTSRoadNetwork("flow contour test network", true);
234         OTSSimulatorInterface simulator = new OTSSimulator();
235         GraphPath<KpiLaneDirection> path = dummyPath(simulator, network);
236         RoadSampler sampler = new RoadSampler(simulator);
237         ContourDataSource<?> dataPool = new ContourDataSource<>(sampler, path);
238         ContourPlotSpeed scp = new ContourPlotSpeed("Density", simulator, dataPool);
239         assertTrue("newly created DensityContourPlot should not be null", null != scp);
240         assertEquals("SeriesKey should be \"speed\"", "speed", scp.getSeriesKey(0));
241         GTUType gtuType = network.getGtuType(GTUType.DEFAULTS.CAR);
242         standardContourTests(simulator, scp, path, Double.NaN, 50);
243     }
244 
245     /**
246      * Debugging method.
247      * @param cp AbstractContourPlot&lt;?&gt;; a contour plot
248      * @param fromX int; lower bound of the x coordinate to print (inclusive)
249      * @param toX int; upper bound of the x coordinate to print (inclusive)
250      * @param fromY int; lower bound of the y coordinate to print (inclusive)
251      * @param toY int; upper bound of the y coordinate to print (inclusive)
252      */
253     static void printMatrix(final AbstractContourPlot<?> cp, final int fromX, final int toX, final int fromY, final int toY)
254     {
255         System.out.println("Contour plot data:");
256         int maxItem = cp.getItemCount(0);
257         for (int y = fromY; y <= toY; y++)
258         {
259             System.out.print(String.format("y=%3d ", y));
260             for (int x = fromX; x <= toX; x++)
261             {
262                 // Find the item with the requested x and y
263                 int item;
264                 for (item = 0; item < maxItem; item++)
265                 {
266                     if (cp.getXValue(0, item) == x && cp.getYValue(0, item) == y)
267                     {
268                         break;
269                     }
270                 }
271                 if (item < maxItem)
272                 {
273                     System.out.print(String.format("%10.6f", cp.getZValue(0, item)));
274                 }
275                 else
276                 {
277                     System.out.print(" -------- ");
278                 }
279             }
280             System.out.println("");
281         }
282         System.out.print("");
283     }
284 
285     /**
286      * Test various properties of a ContourPlot that has no observed data added.
287      * @param simulator OTSSimulatorInterface; the simulator
288      * @param cp AbstractContourPlot&lt;?&gt;; the ContourPlot to test
289      * @param path GraphPath&lt;?&gt;; the path
290      * @param expectedZValue double; the value that getZ and getZValue should return for a valid item when no car has passed
291      * @param expectedZValueWithTraffic double; the value that getZ and getZValue should return a valid item where a car has
292      *            traveled at constant speed of 50 km/h. Supply Double.NaN if the value varies but differs from the value
293      *            expected when no car has passed
294      * @throws Exception when something goes wrong (should not happen)
295      */
296     public static void standardContourTests(final OTSSimulatorInterface simulator, final AbstractContourPlot<?> cp,
297             final GraphPath<?> path, final double expectedZValue, final double expectedZValueWithTraffic) throws Exception
298     {
299         assertEquals("seriesCount should be 1", 1, cp.getSeriesCount());
300         assertEquals("domainOrder should be ASCENDING", DomainOrder.ASCENDING, cp.getDomainOrder());
301         assertEquals("indexOf always returns 0", 0, cp.indexOf(0));
302         assertEquals("indexOf always returns 0", 0, cp.indexOf("abc"));
303         assertNull("getGroup always returns null", cp.getGroup());
304         int xBins = cp.getDataPool().timeAxis.getBinCount();
305         int yBins = cp.getDataPool().spaceAxis.getBinCount();
306         int expectedXBins = (int) Math.ceil(((AbstractPlot.DEFAULT_INITIAL_UPPER_TIME_BOUND).getSI())
307                 / ContourDataSource.DEFAULT_TIME_GRANULARITIES[ContourDataSource.DEFAULT_TIME_GRANULARITY_INDEX] 
308                         + (cp.getDataPool().timeAxis.isInterpolate() ? 1 : 0));
309         assertEquals("Initial xBins should be " + expectedXBins, expectedXBins, xBins);
310         int expectedYBins = (int) Math.ceil(path.getTotalLength().getSI()
311                 / ContourDataSource.DEFAULT_SPACE_GRANULARITIES[ContourDataSource.DEFAULT_SPACE_GRANULARITY_INDEX]
312                         + (cp.getDataPool().timeAxis.isInterpolate() ? 1 : 0));
313         assertEquals("yBins should be " + expectedYBins, expectedYBins, yBins);
314         int bins = cp.getItemCount(0);
315         assertEquals("Total bin count is product of xBins * yBins", xBins * yBins, bins);
316         String initialUpperTimeBoundString = AbstractPlot.DEFAULT_INITIAL_UPPER_TIME_BOUND.toString();
317         // Vary the x granularity
318         for (double timeGranularity : ContourDataSource.DEFAULT_TIME_GRANULARITIES)
319         {
320             cp.actionPerformed(new ActionEvent(timeGranularity, 0, "setTimeGranularity"));
321             for (double distanceGranularity : ContourDataSource.DEFAULT_SPACE_GRANULARITIES)
322             {
323                 cp.actionPerformed(new ActionEvent(distanceGranularity, 0, "setSpaceGranularity"));
324                 cp.notifyPlotChange();
325                 expectedXBins = (int) Math.ceil((AbstractPlot.DEFAULT_INITIAL_UPPER_TIME_BOUND.getSI()) / timeGranularity);
326                 xBins = cp.getDataPool().timeAxis.getBinCount();
327                 assertEquals("Modified xBins should be " + expectedXBins, expectedXBins, xBins);
328                 expectedYBins = (int) Math.ceil(path.get(0).getLength().getSI() / distanceGranularity);
329                 yBins = cp.getDataPool().spaceAxis.getBinCount();
330                 assertEquals("Modified yBins should be " + expectedYBins, expectedYBins, yBins);
331                 bins = cp.getItemCount(0);
332                 assertEquals("Total bin count is product of xBins * yBins", xBins * yBins, bins);
333                 for (int item = 0; item < bins; item++)
334                 {
335                     double x = cp.getXValue(0, item);
336                     assertTrue("X should be >= 0", x >= 0);
337                     assertTrue("X should be <= " + initialUpperTimeBoundString,
338                             x <= AbstractPlot.DEFAULT_INITIAL_UPPER_TIME_BOUND.getSI());
339                     Number alternateX = cp.getX(0, item);
340                     assertEquals("getXValue and getX should return things that have the same value", x,
341                             alternateX.doubleValue(), 0.000001);
342                     double y = cp.getYValue(0, item);
343                     Number alternateY = cp.getY(0, item);
344                     assertEquals("getYValue and getY should return things that have the same value", y,
345                             alternateY.doubleValue(), 0.000001);
346                     double z = cp.getZValue(0, item);
347                     if (Double.isNaN(expectedZValue))
348                     {
349                         assertTrue("Z value should be NaN", Double.isNaN(z));
350                     }
351                     else
352                     {
353                         assertEquals("Z value should be " + expectedZValue, expectedZValue, z, 0.0001);
354                     }
355                     Number alternateZ = cp.getZ(0, item);
356                     if (Double.isNaN(expectedZValue))
357                     {
358                         assertTrue("Alternate Z value should be NaN", Double.isNaN(alternateZ.doubleValue()));
359                     }
360                     else
361                     {
362                         assertEquals("Alternate Z value should be " + expectedZValue, expectedZValue, alternateZ.doubleValue(),
363                                 0.0000);
364                     }
365                 }
366                 try
367                 {
368                     cp.getXValue(0, -1);
369                     fail("Should have thrown an Exception");
370                 }
371                 catch (RuntimeException e)
372                 {
373                     // Ignore expected exception
374                 }
375                 try
376                 {
377                     cp.getXValue(0, bins);
378                     fail("Should have thrown an Exception");
379                 }
380                 catch (RuntimeException e)
381                 {
382                     // Ignore expected exception
383                 }
384                 // try
385                 // {
386                 // cp.yAxisBin(-1);
387                 // fail("Should have thrown an Exception");
388                 // }
389                 // catch (RuntimeException e)
390                 // {
391                 // // Ignore expected exception
392                 // }
393                 // try
394                 // {
395                 // cp.yAxisBin(bins);
396                 // fail("Should have thrown an Exception");
397                 // }
398                 // catch (RuntimeException e)
399                 // {
400                 // // Ignore expected exception
401                 // }
402             }
403         }
404         // Test some ActionEvents that ContourPlot can not handle
405         try
406         {
407             cp.actionPerformed(new ActionEvent(cp, 0, "blabla"));
408             fail("Should have thrown an Exception");
409         }
410         catch (RuntimeException e)
411         {
412             // Ignore expected exception
413         }
414         try
415         {
416             cp.actionPerformed(new ActionEvent(cp, 0, "setDistanceGranularity -1"));
417             fail("Should have thrown an Exception");
418         }
419         catch (RuntimeException e)
420         {
421             // Ignore expected exception
422         }
423         try
424         {
425             cp.actionPerformed(new ActionEvent(cp, 0, "setDistanceGranularity abc"));
426             fail("Should have thrown an Exception");
427         }
428         catch (RuntimeException e)
429         {
430             // Ignore expected exception
431         }
432         try
433         {
434             cp.actionPerformed(new ActionEvent(cp, 0, "setDistanceGranularitIE 10")); // typo in the event name
435             fail("Should have thrown an Exception");
436         }
437         catch (RuntimeException e)
438         {
439             // Ignore expected exception
440         }
441         // Make the time granularity a bit more reasonable
442         final double useTimeGranularity = 30; // [s]
443         cp.actionPerformed(new ActionEvent(useTimeGranularity, 0, "setTimeGranularity"));
444         final double useDistanceGranularity =
445                 ContourDataSource.DEFAULT_SPACE_GRANULARITIES[ContourDataSource.DEFAULT_SPACE_GRANULARITIES.length - 1];
446         cp.actionPerformed(new ActionEvent(useDistanceGranularity, 0, "setDistanceGranularity"));
447         cp.notifyPlotChange();
448         bins = cp.getItemCount(0);
449         Time initialTime = new Time(0, TimeUnit.BASE_SECOND);
450         Length initialPosition = new Length(100, METER);
451         Speed initialSpeed = new Speed(50, KM_PER_HOUR);
452         // Create a car running 50 km.h
453         SequentialFixedAccelerationModel gtuFollowingModel =
454                 new SequentialFixedAccelerationModel(simulator, new Acceleration(2.0, AccelerationUnit.METER_PER_SECOND_2));
455         // Make the car run at constant speed for one minute
456         gtuFollowingModel
457                 .addStep(new FixedAccelerationModel(new Acceleration(0, METER_PER_SECOND_2), new Duration(60, SECOND)));
458         // Make the car run at constant speed for another minute
459         gtuFollowingModel
460                 .addStep(new FixedAccelerationModel(new Acceleration(0, METER_PER_SECOND_2), new Duration(600, SECOND)));
461         // Make the car run at constant speed for five more minutes
462         gtuFollowingModel
463                 .addStep(new FixedAccelerationModel(new Acceleration(0, METER_PER_SECOND_2), new Duration(300, SECOND)));
464         LaneChangeModel laneChangeModel = new Egoistic();
465 
466         // Check that the initial data in the graph contains no trace of any car.
467         for (int item = 0; item < bins; item++)
468         {
469             double x = cp.getXValue(0, item);
470             assertTrue("X should be >= 0", x >= 0);
471             assertTrue("X should be <= " + initialUpperTimeBoundString, x <= AbstractPlot.DEFAULT_INITIAL_UPPER_TIME_BOUND.si);
472             Number alternateX = cp.getX(0, item);
473             assertEquals("getXValue and getX should return things that have the same value", x, alternateX.doubleValue(),
474                     0.000001);
475             double y = cp.getYValue(0, item);
476             Number alternateY = cp.getY(0, item);
477             assertEquals("getYValue and getY should return things that have the same value", y, alternateY.doubleValue(),
478                     0.000001);
479             double z = cp.getZValue(0, item);
480             if (Double.isNaN(expectedZValue))
481             {
482                 assertTrue("Z value should be NaN (got " + z + ")", Double.isNaN(z));
483             }
484             else
485             {
486                 assertEquals("Z value should be " + expectedZValue, expectedZValue, z, 0.0001);
487             }
488             Number alternateZ = cp.getZ(0, item);
489             if (Double.isNaN(expectedZValue))
490             {
491                 assertTrue("Alternate Z value should be NaN", Double.isNaN(alternateZ.doubleValue()));
492             }
493             else
494             {
495                 assertEquals("Alternate Z value should be " + expectedZValue, expectedZValue, alternateZ.doubleValue(), 0.0000);
496             }
497         }
498 
499         // LaneBasedIndividualGTU car =
500         // makeReferenceCar("0", gtuType, ((CrossSectionLink) network.getLink("AtoB")).getLanes().get(0), initialPosition,
501         // initialSpeed, simulator, null, laneChangeModel, network);
502         // car.getParameters().setParameter(ParameterTypes.LOOKAHEAD, new Length(10, LengthUnit.KILOMETER));
503         //
504         // // System.out.println("Running simulator from " + simulator.getSimulatorTime() + " to "
505         // // + gtuFollowingModel.timeAfterCompletionOfStep(0));
506         // double stopTime = gtuFollowingModel.timeAfterCompletionOfStep(0).si;
507         // simulator.runUpToAndIncluding(new Time(stopTime, TimeUnit.BASE_SECOND));
508         // while (simulator.isRunning())
509         // {
510         // try
511         // {
512         // Thread.sleep(10);
513         // }
514         // catch (InterruptedException ie)
515         // {
516         // ie = null; // ignore
517         // }
518         // }
519         // // System.out.println("Simulator is now at " + simulator.getSimulatorTime());
520         // // System.out.println("Car at start time " + car.getOperationalPlan().getStartTime() + " is at "
521         // // + car.getPosition(car.getOperationalPlan().getStartTime()));
522         // // System.out.println("At time " + simulator.getSimulator().getSimulatorTime() + " car is at " + car);
523         // for (int item = 0; item < bins; item++)
524         // {
525         // double x = cp.getXValue(0, item);
526         // assertTrue("X should be >= 0", x >= 0);
527         // assertTrue("X should be <= " + initialUpperTimeBoundString, x <= AbstractPlot.DEFAULT_INITIAL_UPPER_TIME_BOUND.si);
528         // Number alternateX = cp.getX(0, item);
529         // assertEquals("getXValue and getX should return things that have the same value", x, alternateX.doubleValue(),
530         // 0.000001);
531         // double y = cp.getYValue(0, item);
532         // Number alternateY = cp.getY(0, item);
533         // assertEquals("getYValue and getY should return things that have the same value", y, alternateY.doubleValue(),
534         // 0.000001);
535         // double z = cp.getZValue(0, item);
536         // // figure out if the car has traveled through this cell
537         // // if (x >= 180)
538         // // System.out.println(String.format("t=%.3f, x=%.3f z=%f, exp=%.3f, carLastEval=%s, carNextEval=%s", x, y, z,
539         // // expectedZValue, car.getOperationalPlan().getStartTime().getSI(), car.getOperationalPlan().getEndTime()
540         // // .getSI()));
541         // boolean hit = false;
542         // if (x + useTimeGranularity >= 0// car.getOperationalPlan().getStartTime().getSI()
543         // && x < 60)// car.getOperationalPlan().getEndTime().getSI())
544         // {
545         // // the car MAY have contributed to this cell
546         // Time cellStartTime =
547         // new Time(Math.max(car.getOperationalPlan().getStartTime().getSI(), x), TimeUnit.BASE_SECOND);
548         // Time cellEndTime = new Time(Math.min(car.getOperationalPlan().getEndTime().getSI(), x + useTimeGranularity),
549         // TimeUnit.BASE_SECOND);
550         // // System.out.println("cellStartTime=" + cellStartTime + ", cellEndTime=" + cellEndTime);
551         // // The next if statement is the problem
552         // // if (cellStartTime.lt(cellEndTime)
553         // // && car.position(lane, car.getRear(), cellStartTime).getSI() <= y + useDistanceGranularity
554         // // && car.position(lane, car.getRear(), cellEndTime).getSI() >= y)
555         // double xAtCellStartTime = initialPosition.si + initialSpeed.si * cellStartTime.si;
556         // double xAtCellEndTime = initialPosition.si + initialSpeed.si * cellEndTime.si;
557         // if (xAtCellStartTime < y + useDistanceGranularity && xAtCellEndTime >= y)
558         // {
559         // hit = true;
560         // }
561         // }
562         // // System.out.println(String.format(
563         // // "hit=%s, t=%.3f, x=%.3f z=%f, exp=%.3f, carLastEval=%s, carNextEval=%s, simulatortime=%s", hit, x, y, z,
564         // // expectedZValue, car.getOperationalPlan().getStartTime().getSI(), car.getOperationalPlan().getEndTime()
565         // // .getSI(), car.getSimulator().getSimulatorTime()));
566         // Number alternateZ = cp.getZ(0, item);
567         // if (hit)
568         // {
569         // if (!Double.isNaN(expectedZValueWithTraffic))
570         // {
571         // if (Double.isNaN(z))
572         // {
573         // printMatrix(cp, 0, 10, 0, 10);
574         // System.out.println("Oops - z is NaN, expected z value with traffic is " + expectedZValueWithTraffic);
575         // }
576         // assertEquals("Z value should be " + expectedZValueWithTraffic, expectedZValueWithTraffic, z, 0.0001);
577         // assertEquals("Z value should be " + expectedZValueWithTraffic, expectedZValueWithTraffic,
578         // alternateZ.doubleValue(), 0.0001);
579         // }
580         // else
581         // {
582         // if (Double.isNaN(expectedZValue))
583         // { // FIXME looks wrong / PK
584         // assertFalse("Z value should not be NaN", Double.isNaN(z));
585         // }
586         // }
587         // }
588         // else
589         // {
590         // if (Double.isNaN(expectedZValue))
591         // {
592         // // if (!Double.isNaN(z))
593         // // {
594         // // System.out.println("Oops");
595         // // Time cellStartTime = new Time(x, SECOND);
596         // // Time cellEndTime =
597         // // new Time(Math.min(car.getOperationalPlan().getEndTime().getSI(), x + useTimeGranularity),
598         // // SECOND);
599         // // double xAtCellStartTime = initialPosition.si + initialSpeed.si * cellStartTime.si;
600         // // double xAtCellEndTime = initialPosition.si + initialSpeed.si * cellEndTime.si;
601         // // System.out.println("cellStartTime=" + cellStartTime + " cellEndTime=" + cellEndTime
602         // // + " xAtCellStartTime=" + xAtCellStartTime + " xAtCellEndTime=" + xAtCellEndTime);
603         // // double cellX = cp.getXValue(0, item);
604         // // double cellY = cp.getYValue(0, item);
605         // // double cellZ = cp.getZValue(0, item);
606         // // System.out.println("cellX=" + cellX + " cellY=" + cellY + " cellZ=" + cellZ + " timeGranularity="
607         // // + useTimeGranularity + " distanceGranularity=" + useDistanceGranularity);
608         // // cp.getZValue(0, item);
609         // // }
610         // assertTrue("Z value should be NaN", Double.isNaN(z));
611         // }
612         // else
613         // {
614         // assertEquals("Z value should be " + expectedZValue, expectedZValue, z, 0.0001);
615         // }
616         // if (Double.isNaN(expectedZValue))
617         // {
618         // assertTrue("Alternate Z value should be NaN", Double.isNaN(alternateZ.doubleValue()));
619         // }
620         // else
621         // {
622         // assertEquals("Alternate Z value should be " + expectedZValue, expectedZValue, alternateZ.doubleValue(),
623         // 0.0000);
624         // }
625         // }
626         // }
627         // // System.out.println("Running simulator from " + simulator.getSimulatorTime() + " to "
628         // // + gtuFollowingModel.timeAfterCompletionOfStep(1));
629         // stopTime = gtuFollowingModel.timeAfterCompletionOfStep(1).si;
630         // simulator.runUpToAndIncluding(new Time(stopTime, TimeUnit.BASE_SECOND));
631         // while (simulator.isRunning())
632         // {
633         // try
634         // {
635         // Thread.sleep(10);
636         // }
637         // catch (InterruptedException ie)
638         // {
639         // ie = null; // ignore
640         // }
641         // }
642         // // System.out.println("Simulator is now at " + simulator.getSimulatorTime());
643         // // Check that the time range has expanded
644         // xBins = cp.getDataPool().timeAxis.getBinCount();
645         // bins = cp.getItemCount(0);
646         // double observedHighestTime = Double.MIN_VALUE;
647         // for (int bin = 0; bin < bins; bin++)
648         // {
649         // double xValue = cp.getXValue(0, bin);
650         // if (xValue > observedHighestTime)
651         // {
652         // observedHighestTime = xValue;
653         // }
654         // }
655         // double expectedHighestTime =
656         // Math.floor((car.getSimulator().getSimulatorTime().si - 0.001) / useTimeGranularity) * useTimeGranularity;
657         // assertEquals("Time range should run up to " + expectedHighestTime, expectedHighestTime, observedHighestTime, 0.0001);
658         // Check the updateHint method in the PointerHandler
659         // First get the panel that stores the result of updateHint (this is ugly)
660         // JLabel hintPanel = null;
661         // ChartPanel chartPanel = null;
662         // for (Component c0 : cp.getComponents())
663         // {
664         // for (Component c1 : ((Container) c0).getComponents())
665         // {
666         // if (c1 instanceof Container)
667         // {
668         // for (Component c2 : ((Container) c1).getComponents())
669         // {
670         // // System.out.println("c2 is " + c2);
671         // if (c2 instanceof Container)
672         // {
673         // for (Component c3 : ((Container) c2).getComponents())
674         // {
675         // // System.out.println("c3 is " + c3);
676         // if (c3 instanceof JLabel)
677         // {
678         // if (null == hintPanel)
679         // {
680         // hintPanel = (JLabel) c3;
681         // }
682         // else
683         // {
684         // fail("There should be only one JPanel in a ContourPlot");
685         // }
686         // }
687         // if (c3 instanceof ChartPanel)
688         // {
689         // if (null == chartPanel)
690         // {
691         // chartPanel = (ChartPanel) c3;
692         // }
693         // else
694         // {
695         // fail("There should be only one ChartPanel in a ContourPlot");
696         // }
697         // }
698         // }
699         // }
700         // }
701         // }
702         // }
703         // }
704         // if (null == hintPanel)
705         // {
706         // fail("Could not find a JLabel in ContourPlot");
707         // }
708         // if (null == chartPanel)
709         // {
710         // fail("Could not find a ChartPanel in ContourPlot");
711         // }
712         // assertEquals("Initially the text should be a single space", " ", hintPanel.getText());
713         // PointerHandler ph = null;
714         // for (MouseListener ml : chartPanel.getMouseListeners())
715         // {
716         // if (ml instanceof PointerHandler)
717         // {
718         // if (null == ph)
719         // {
720         // ph = (PointerHandler) ml;
721         // }
722         // else
723         // {
724         // fail("There should be only one PointerHandler on the chartPanel");
725         // }
726         // }
727         // }
728         // if (null == ph)
729         // {
730         // fail("Could not find the PointerHandler for the chartPanel");
731         // }
732         // ph.updateHint(1, 2);
733         // // System.out.println("Hint text is now " + hintPanel.getText());
734         // assertFalse("Hint should not be a single space", " ".equals(hintPanel.getText()));
735         // ph.updateHint(Double.NaN, Double.NaN);
736         // assertEquals("The text should again be a single space", " ", hintPanel.getText());
737     }
738 
739     /**
740      * Create a new Car.
741      * @param id String; the name (number) of the Car
742      * @param gtuType GTUType; the type of the new car
743      * @param lane Lane; the lane on which the new Car is positioned
744      * @param initialPosition Length; the initial longitudinal position of the new Car
745      * @param initialSpeed Speed; the initial speed
746      * @param simulator OTSDEVVSimulator; the simulator that controls the new Car (and supplies the initial value for
747      *            getLastEvalutionTime())
748      * @param gtuFollowingModel GTUFollowingModel; the GTU following model
749      * @param laneChangeModel LaneChangeModel; the lane change model
750      * @param network the network
751      * @return Car; the new Car
752      * @throws NamingException on network error when making the animation
753      * @throws NetworkException when the GTU cannot be placed on the given lane.
754      * @throws SimRuntimeException when the move method cannot be scheduled.
755      * @throws GTUException when construction of the GTU fails (probably due to an invalid parameter)
756      * @throws OTSGeometryException when the initial path is wrong
757      */
758     private static LaneBasedIndividualGTU makeReferenceCar(final String id, final GTUType gtuType, final Lane lane,
759             final Length initialPosition, final Speed initialSpeed, final OTSSimulatorInterface simulator,
760             final GTUFollowingModelOld gtuFollowingModel, final LaneChangeModel laneChangeModel, final OTSRoadNetwork network)
761             throws NamingException, NetworkException, SimRuntimeException, GTUException, OTSGeometryException
762     {
763         Length length = new Length(5.0, METER);
764         Length width = new Length(2.0, METER);
765         Set<DirectedLanePosition> initialLongitudinalPositions = new LinkedHashSet<>(1);
766         initialLongitudinalPositions.add(new DirectedLanePosition(lane, initialPosition, GTUDirectionality.DIR_PLUS));
767         Speed maxSpeed = new Speed(120, KM_PER_HOUR);
768         LaneBasedIndividualGTU gtu =
769                 new LaneBasedIndividualGTU(id, gtuType, length, width, maxSpeed, length.times(0.5), simulator, network);
770         LaneBasedStrategicalPlanner strategicalPlanner = new LaneBasedStrategicalRoutePlanner(
771                 new LaneBasedCFLCTacticalPlanner(gtuFollowingModel, laneChangeModel, gtu), gtu);
772         gtu.init(strategicalPlanner, initialLongitudinalPositions, initialSpeed);
773 
774         return gtu;
775     }
776 
777     /**
778      * Run the DensityContourPlot stand-alone for profiling.
779      * @param args String[]; the command line arguments (not used)
780      * @throws Exception when something goes wrong (should not happen)
781      */
782     public static void main(final String[] args) throws Exception
783     {
784         ContourPlotTesttourPlotTest.html#ContourPlotTest">ContourPlotTest cpt = new ContourPlotTest();
785         System.out.println("Click the OK button");
786         JOptionPane.showMessageDialog(null, "ContourPlot", "Start experiment", JOptionPane.INFORMATION_MESSAGE);
787         System.out.println("Running ...");
788         cpt.densityContourTest();
789         System.out.println("Finished");
790     }
791 
792 }