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