1 package org.opentrafficsim.draw.graphs;
2
3 import static org.junit.jupiter.api.Assertions.assertEquals;
4 import static org.junit.jupiter.api.Assertions.assertNull;
5 import static org.junit.jupiter.api.Assertions.assertTrue;
6 import static org.junit.jupiter.api.Assertions.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.draw.point.Point2d;
28 import org.djutils.immutablecollections.ImmutableArrayList;
29 import org.jfree.data.DomainOrder;
30 import org.junit.jupiter.api.Test;
31 import org.mockito.ArgumentMatchers;
32 import org.mockito.Mockito;
33 import org.mockito.invocation.InvocationOnMock;
34 import org.mockito.stubbing.Answer;
35 import org.opentrafficsim.animation.GraphLaneUtil;
36 import org.opentrafficsim.core.definitions.DefaultsNl;
37 import org.opentrafficsim.core.dsol.OtsModelInterface;
38 import org.opentrafficsim.core.dsol.OtsReplication;
39 import org.opentrafficsim.core.dsol.OtsSimulatorInterface;
40 import org.opentrafficsim.core.geometry.OtsGeometryException;
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.core.network.Node;
45 import org.opentrafficsim.draw.graphs.GraphPath.Section;
46 import org.opentrafficsim.kpi.interfaces.LaneData;
47 import org.opentrafficsim.kpi.sampling.SamplerData;
48 import org.opentrafficsim.road.definitions.DefaultsRoadNl;
49 import org.opentrafficsim.road.gtu.lane.LaneBasedGtu;
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.LaneBasedStrategicalRoutePlanner;
58 import org.opentrafficsim.road.network.RoadNetwork;
59 import org.opentrafficsim.road.network.factory.LaneFactory;
60 import org.opentrafficsim.road.network.lane.Lane;
61 import org.opentrafficsim.road.network.lane.LanePosition;
62 import org.opentrafficsim.road.network.lane.LaneType;
63 import org.opentrafficsim.road.network.sampling.LaneDataRoad;
64 import org.opentrafficsim.road.network.sampling.RoadSampler;
65
66 import nl.tudelft.simulation.dsol.SimRuntimeException;
67 import nl.tudelft.simulation.dsol.formalisms.eventscheduling.SimEvent;
68 import nl.tudelft.simulation.dsol.formalisms.eventscheduling.SimEventInterface;
69
70
71
72
73
74
75
76
77
78 public class ContourPlotTest implements UNITS
79 {
80
81
82 @SuppressWarnings("unchecked")
83 GraphPath<LaneData<?>> mockedPath = Mockito.mock(GraphPath.class);
84
85 Section<LaneData<?>> section0 = Mockito.mock(Section.class);
86
87 Section<LaneData<?>> section1 = Mockito.mock(Section.class);
88
89 LaneData<?> mockedLane0 = Mockito.mock(LaneData.class);
90
91 LaneData<?> mockedLane1 = Mockito.mock(LaneData.class);
92
93 SamplerData mockedSamplerData = Mockito.mock(SamplerData.class);
94
95 OtsSimulatorInterface mockedSimulator = Mockito.mock(OtsSimulatorInterface.class);
96
97 PlotScheduler mockedScheduler = Mockito.mock(PlotScheduler.class);
98
99 SimEventInterface<Duration> lastScheduledEvent = null;
100
101
102
103
104
105
106
107
108 private GraphPath<LaneDataRoad> dummyPath(final OtsSimulatorInterface simulator, final RoadNetwork network) throws Exception
109 {
110 LaneType laneType = DefaultsRoadNl.TWO_WAY_LANE;
111 Node b = new Node(network, "B", new Point2d(12345, 0), Direction.ZERO);
112 ArrayList<Lane> result = new ArrayList<Lane>();
113 Lane[] lanes = LaneFactory.makeMultiLane(network, "AtoB", new Node(network, "A", new Point2d(1234, 0), Direction.ZERO),
114 b, null, 1, laneType, new Speed(100, KM_PER_HOUR), simulator, DefaultsNl.VEHICLE);
115 result.add(lanes[0]);
116
117 lanes = LaneFactory.makeMultiLane(network, "BtoC", b, new Node(network, "C", new Point2d(99999, 0), Direction.ZERO),
118 null, 1, laneType, new Speed(100, KM_PER_HOUR), null, DefaultsNl.VEHICLE);
119 return GraphLaneUtil.createPath("AtoB", lanes[0]);
120 }
121
122
123
124
125
126
127 public final void setUp() throws SimRuntimeException, NamingException
128 {
129 Mockito.when(this.mockedPath.getTotalLength()).thenReturn(Length.valueOf("2000m"));
130 Mockito.when(this.mockedPath.getNumberOfSeries()).thenReturn(2);
131 Mockito.when(this.mockedPath.get(0)).thenReturn(this.section0);
132 Mockito.when(this.mockedPath.get(1)).thenReturn(this.section1);
133 Mockito.when(this.mockedPath.getStartDistance(this.section0)).thenReturn(Length.ZERO);
134 Mockito.when(this.mockedPath.getStartDistance(this.section1)).thenReturn(Length.valueOf("1234m"));
135 Mockito.when(this.mockedPath.getSpeedLimit()).thenReturn(Speed.valueOf("100 km/h"));
136 List<Section<LaneData<?>>> sectionList = new ArrayList<>();
137 sectionList.add(this.section0);
138 sectionList.add(this.section1);
139 Mockito.when(this.mockedLane0.getLength()).thenReturn(Length.valueOf("1234m"));
140 Mockito.when(this.mockedLane1.getLength()).thenReturn(Length.valueOf("766m"));
141 Set<LaneData<?>> set0 = new HashSet<>();
142 set0.add(this.mockedLane0);
143 Mockito.when(this.section0.iterator()).thenReturn(set0.iterator());
144 Set<LaneData<?>> set1 = new HashSet<>();
145 set1.add(this.mockedLane1);
146 Mockito.when(this.section0.iterator()).thenReturn(set0.iterator());
147 Mockito.when(this.section1.iterator()).thenReturn(set1.iterator());
148 Mockito.when(this.mockedPath.getSections()).thenReturn(new ImmutableArrayList<>(sectionList));
149 Mockito.when(this.section0.length()).thenReturn(Length.valueOf("2000m"));
150 Mockito.when(this.section1.length()).thenReturn(Length.valueOf("766m"));
151 Mockito.when(this.mockedSimulator.scheduleEventAbsTime(ArgumentMatchers.any(Time.class), ArgumentMatchers.any(),
152 ArgumentMatchers.anyString(), ArgumentMatchers.isNull())).thenAnswer(new Answer<SimEventInterface<Duration>>()
153 {
154 @Override
155 public SimEventInterface<Duration> answer(final InvocationOnMock invocation) throws Throwable
156 {
157 ContourPlotTest.this.lastScheduledEvent = new SimEvent<Duration>(
158 ((Time) invocation.getArgument(0)).minus(Time.ZERO), invocation.getArgument(2), "update", null);
159 return ContourPlotTest.this.lastScheduledEvent;
160 }
161 });
162 Mockito.when(this.mockedSimulator.getSimulatorAbsTime()).thenReturn(Time.ZERO);
163 Mockito.when(this.mockedSimulator.getSimulatorTime()).thenReturn(Duration.ZERO);
164 OtsModelInterface model = Mockito.mock(OtsModelInterface.class);
165 OtsReplication replication = new OtsReplication("test", Time.ZERO, Duration.ZERO, Duration.instantiateSI(3600.0));
166 Mockito.when(this.mockedSimulator.getReplication()).thenReturn(replication);
167 Mockito.when(this.mockedScheduler.getTime()).thenReturn(Time.ZERO);
168 }
169
170
171
172
173
174 @Test
175 public final void accelerationContourTest() throws Exception
176 {
177 setUp();
178 ContourDataSource dataPool = new ContourDataSource(this.mockedSamplerData, this.mockedPath);
179 ContourPlotAcceleration acp = new ContourPlotAcceleration("acceleration", this.mockedScheduler, dataPool);
180 assertEquals("acceleration", acp.getSeriesKey(0), "SeriesKey should be \"acceleration\"");
181 standardContourTests(this.mockedSimulator, acp, this.mockedPath, Double.NaN, 0);
182 }
183
184
185
186
187
188 @Test
189 public final void densityContourTest() throws Exception
190 {
191 setUp();
192 OtsSimulatorInterface simulator = this.mockedSimulator;
193 RoadNetwork network = new RoadNetwork("density contour test network", simulator);
194 GraphPath<LaneDataRoad> path = dummyPath(simulator, network);
195 RoadSampler sampler = new RoadSampler(network);
196 ContourDataSource dataPool = new ContourDataSource(sampler.getSamplerData(), path);
197 ContourPlotDensity dcp = new ContourPlotDensity("density", this.mockedScheduler, dataPool);
198 assertTrue(null != dcp, "newly created DensityContourPlot should not be null");
199 assertEquals("density", dcp.getSeriesKey(0), "SeriesKey should be \"density\"");
200 standardContourTests(simulator, dcp, path, Double.NaN, Double.NaN);
201 }
202
203
204
205
206
207 @Test
208 public final void flowContourTest() throws Exception
209 {
210 setUp();
211 OtsSimulatorInterface simulator = this.mockedSimulator;
212 RoadNetwork network = new RoadNetwork("flow contour test network", simulator);
213 GraphPath<LaneDataRoad> path = dummyPath(simulator, network);
214 RoadSampler sampler = new RoadSampler(network);
215 ContourDataSource dataPool = new ContourDataSource(sampler.getSamplerData(), path);
216 ContourPlotFlow fcp = new ContourPlotFlow("flow", this.mockedScheduler, dataPool);
217 assertTrue(null != fcp, "newly created DensityContourPlot should not be null");
218 assertEquals("flow", fcp.getSeriesKey(0), "SeriesKey should be \"flow\"");
219 standardContourTests(simulator, fcp, path, Double.NaN, Double.NaN);
220 }
221
222
223
224
225
226 @Test
227 public final void speedContourTest() throws Exception
228 {
229 setUp();
230 OtsSimulatorInterface simulator = this.mockedSimulator;
231 RoadNetwork network = new RoadNetwork("flow contour test network", simulator);
232 GraphPath<LaneDataRoad> path = dummyPath(simulator, network);
233 RoadSampler sampler = new RoadSampler(network);
234 ContourDataSource dataPool = new ContourDataSource(sampler.getSamplerData(), path);
235 ContourPlotSpeed scp = new ContourPlotSpeed("speed", this.mockedScheduler, dataPool);
236 assertTrue(null != scp, "newly created DensityContourPlot should not be null");
237 assertEquals("speed", scp.getSeriesKey(0), "SeriesKey should be \"speed\"");
238 standardContourTests(simulator, scp, path, Double.NaN, 50);
239 }
240
241
242
243
244
245
246
247
248
249 static void printMatrix(final AbstractContourPlot<?> cp, final int fromX, final int toX, final int fromY, final int toY)
250 {
251 System.out.println("Contour plot data:");
252 int maxItem = cp.getItemCount(0);
253 for (int y = fromY; y <= toY; y++)
254 {
255 System.out.print(String.format("y=%3d ", y));
256 for (int x = fromX; x <= toX; x++)
257 {
258
259 int item;
260 for (item = 0; item < maxItem; item++)
261 {
262 if (cp.getXValue(0, item) == x && cp.getYValue(0, item) == y)
263 {
264 break;
265 }
266 }
267 if (item < maxItem)
268 {
269 System.out.print(String.format("%10.6f", cp.getZValue(0, item)));
270 }
271 else
272 {
273 System.out.print(" -------- ");
274 }
275 }
276 System.out.println("");
277 }
278 System.out.print("");
279 }
280
281
282
283
284
285
286
287
288
289
290
291
292 public static void standardContourTests(final OtsSimulatorInterface simulator, final AbstractContourPlot<?> cp,
293 final GraphPath<?> path, final double expectedZValue, final double expectedZValueWithTraffic) throws Exception
294 {
295 assertEquals(1, cp.getSeriesCount(), "seriesCount should be 1");
296 assertEquals(DomainOrder.ASCENDING, cp.getDomainOrder(), "domainOrder should be ASCENDING");
297 assertEquals(0, cp.indexOf(0), "indexOf always returns 0");
298 assertEquals(0, cp.indexOf("abc"), "indexOf always returns 0");
299 assertNull(cp.getGroup(), "getGroup always returns null");
300 int xBins = cp.getDataPool().timeAxis.getBinCount();
301 int yBins = cp.getDataPool().spaceAxis.getBinCount();
302 int expectedXBins = (int) Math.ceil(((AbstractPlot.DEFAULT_INITIAL_UPPER_TIME_BOUND).getSI())
303 / ContourDataSource.DEFAULT_TIME_GRANULARITIES[ContourDataSource.DEFAULT_TIME_GRANULARITY_INDEX]
304 + (cp.getDataPool().timeAxis.isInterpolate() ? 1 : 0));
305 assertEquals(expectedXBins, xBins, "Initial xBins should be " + expectedXBins);
306 int expectedYBins = (int) Math.ceil(path.getTotalLength().getSI()
307 / ContourDataSource.DEFAULT_SPACE_GRANULARITIES[ContourDataSource.DEFAULT_SPACE_GRANULARITY_INDEX]
308 + (cp.getDataPool().timeAxis.isInterpolate() ? 1 : 0));
309 assertEquals(expectedYBins, yBins, "yBins should be " + expectedYBins);
310 int bins = cp.getItemCount(0);
311 assertEquals(xBins * yBins, bins, "Total bin count is product of xBins * yBins");
312 String initialUpperTimeBoundString = AbstractPlot.DEFAULT_INITIAL_UPPER_TIME_BOUND.toString();
313
314 for (double timeGranularity : ContourDataSource.DEFAULT_TIME_GRANULARITIES)
315 {
316 cp.actionPerformed(new ActionEvent(timeGranularity, 0, "setTimeGranularity"));
317
318 for (double distanceGranularity : ContourDataSource.DEFAULT_SPACE_GRANULARITIES)
319 {
320 cp.actionPerformed(new ActionEvent(distanceGranularity, 0, "setSpaceGranularity"));
321 cp.notifyPlotChange();
322 expectedXBins = (int) Math.ceil((AbstractPlot.DEFAULT_INITIAL_UPPER_TIME_BOUND.getSI()) / timeGranularity)
323 + (cp.getDataPool().timeAxis.isInterpolate() ? 1 : 0);
324 xBins = cp.getDataPool().timeAxis.getBinCount();
325 assertEquals(expectedXBins, xBins, "Modified xBins should be " + expectedXBins);
326 expectedYBins = (int) Math.ceil(path.get(0).length().getSI() / distanceGranularity)
327 + (cp.getDataPool().spaceAxis.isInterpolate() ? 1 : 0);
328 yBins = cp.getDataPool().spaceAxis.getBinCount();
329
330
331
332 assertEquals(expectedYBins, yBins, "Modified yBins should be " + expectedYBins);
333 bins = cp.getItemCount(0);
334 assertEquals(xBins * yBins, bins, "Total bin count is product of xBins * yBins");
335 for (int item = 0; item < bins; item++)
336 {
337 double x = cp.getXValue(0, item);
338
339 assertTrue(x >= -timeGranularity / 2, "X should be >= -granularity / 2");
340 assertTrue(x <= AbstractPlot.DEFAULT_INITIAL_UPPER_TIME_BOUND.getSI(),
341 "X should be <= " + initialUpperTimeBoundString);
342 Number alternateX = cp.getX(0, item);
343 assertEquals(x, alternateX.doubleValue(), 0.000001,
344 "getXValue and getX should return things that have the same value");
345 double y = cp.getYValue(0, item);
346 Number alternateY = cp.getY(0, item);
347 assertEquals(y, alternateY.doubleValue(), 0.000001,
348 "getYValue and getY should return things that have the same value");
349 double z = cp.getZValue(0, item);
350 if (Double.isNaN(expectedZValue))
351 {
352 assertTrue(Double.isNaN(z), "Z value should be NaN");
353 }
354 else
355 {
356 assertEquals(expectedZValue, z, 0.0001, "Z value should be " + expectedZValue);
357 }
358 Number alternateZ = cp.getZ(0, item);
359 if (Double.isNaN(expectedZValue))
360 {
361 assertTrue(Double.isNaN(alternateZ.doubleValue()), "Alternate Z value should be NaN");
362 }
363 else
364 {
365 assertEquals(expectedZValue, alternateZ.doubleValue(), 0.0000,
366 "Alternate Z value should be " + expectedZValue);
367 }
368 }
369 try
370 {
371 cp.getXValue(0, -1);
372 fail("Should have thrown an Exception");
373 }
374 catch (RuntimeException e)
375 {
376
377 }
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405 }
406 }
407
408 try
409 {
410 cp.actionPerformed(new ActionEvent(cp, 0, "blabla"));
411 fail("Should have thrown an Exception");
412 }
413 catch (RuntimeException e)
414 {
415
416 }
417 try
418 {
419 cp.actionPerformed(new ActionEvent(cp, 0, "setDistanceGranularity -1"));
420 fail("Should have thrown an Exception");
421 }
422 catch (RuntimeException e)
423 {
424
425 }
426 try
427 {
428 cp.actionPerformed(new ActionEvent(cp, 0, "setDistanceGranularity abc"));
429 fail("Should have thrown an Exception");
430 }
431 catch (RuntimeException e)
432 {
433
434 }
435 try
436 {
437 cp.actionPerformed(new ActionEvent(cp, 0, "setDistanceGranularitIE 10"));
438 fail("Should have thrown an Exception");
439 }
440 catch (RuntimeException e)
441 {
442
443 }
444
445 final double useTimeGranularity = 30;
446 cp.actionPerformed(new ActionEvent(useTimeGranularity, 0, "setTimeGranularity"));
447 final double useDistanceGranularity =
448 ContourDataSource.DEFAULT_SPACE_GRANULARITIES[ContourDataSource.DEFAULT_SPACE_GRANULARITIES.length - 1];
449 cp.actionPerformed(new ActionEvent(useDistanceGranularity, 0, "setSpaceGranularity"));
450 cp.notifyPlotChange();
451 bins = cp.getItemCount(0);
452 Time initialTime = new Time(0, TimeUnit.BASE_SECOND);
453 Length initialPosition = new Length(100, METER);
454 Speed initialSpeed = new Speed(50, KM_PER_HOUR);
455
456 SequentialFixedAccelerationModel gtuFollowingModel =
457 new SequentialFixedAccelerationModel(simulator, new Acceleration(2.0, AccelerationUnit.METER_PER_SECOND_2));
458
459 gtuFollowingModel
460 .addStep(new FixedAccelerationModel(new Acceleration(0, METER_PER_SECOND_2), new Duration(60, SECOND)));
461
462 gtuFollowingModel
463 .addStep(new FixedAccelerationModel(new Acceleration(0, METER_PER_SECOND_2), new Duration(600, SECOND)));
464
465 gtuFollowingModel
466 .addStep(new FixedAccelerationModel(new Acceleration(0, METER_PER_SECOND_2), new Duration(300, SECOND)));
467 LaneChangeModel laneChangeModel = new Egoistic();
468
469
470 for (int item = 0; item < bins; item++)
471 {
472 double x = cp.getXValue(0, item);
473
474
475 assertTrue(x >= -cp.getTimeGranularity() / 2, "X should be >= -timeGranularity / 2");
476 assertTrue(x <= AbstractPlot.DEFAULT_INITIAL_UPPER_TIME_BOUND.si, "X should be <= " + initialUpperTimeBoundString);
477 Number alternateX = cp.getX(0, item);
478 assertEquals(x, alternateX.doubleValue(), 0.000001,
479 "getXValue and getX should return things that have the same value");
480 double y = cp.getYValue(0, item);
481 Number alternateY = cp.getY(0, item);
482 assertEquals(y, alternateY.doubleValue(), 0.000001,
483 "getYValue and getY should return things that have the same value");
484 double z = cp.getZValue(0, item);
485 if (Double.isNaN(expectedZValue))
486 {
487 assertTrue(Double.isNaN(z), "Z value should be NaN (got " + z + ")");
488 }
489 else
490 {
491 assertEquals(expectedZValue, z, 0.0001, "Z value should be " + expectedZValue);
492 }
493 Number alternateZ = cp.getZ(0, item);
494 if (Double.isNaN(expectedZValue))
495 {
496 assertTrue(Double.isNaN(alternateZ.doubleValue()), "Alternate Z value should be NaN");
497 }
498 else
499 {
500 assertEquals(expectedZValue, alternateZ.doubleValue(), 0.0000, "Alternate Z value should be " + expectedZValue);
501 }
502 }
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742 }
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763 private static LaneBasedGtu makeReferenceCar(final String id, final GtuType gtuType, final Lane lane,
764 final Length initialPosition, final Speed initialSpeed, final OtsSimulatorInterface simulator,
765 final GtuFollowingModelOld gtuFollowingModel, final LaneChangeModel laneChangeModel, final RoadNetwork network)
766 throws NamingException, NetworkException, SimRuntimeException, GtuException, OtsGeometryException
767 {
768
769 Length length = new Length(5.0, METER);
770 Length width = new Length(2.0, METER);
771 Speed maxSpeed = new Speed(120, KM_PER_HOUR);
772 LaneBasedGtu gtu = new LaneBasedGtu(id, gtuType, length, width, maxSpeed, length.times(0.5), network);
773 LaneBasedStrategicalPlanner strategicalPlanner = new LaneBasedStrategicalRoutePlanner(
774 new LaneBasedCfLcTacticalPlanner(gtuFollowingModel, laneChangeModel, gtu), gtu);
775 gtu.init(strategicalPlanner, new LanePosition(lane, initialPosition), initialSpeed);
776
777 return gtu;
778 }
779
780
781
782
783
784
785 public static void main(final String[] args) throws Exception
786 {
787 ContourPlotTest cpt = new ContourPlotTest();
788 System.out.println("Click the OK button");
789 JOptionPane.showMessageDialog(null, "ContourPlot", "Start experiment", JOptionPane.INFORMATION_MESSAGE);
790 System.out.println("Running ...");
791 cpt.densityContourTest();
792 System.out.println("Finished");
793 }
794
795 }