View Javadoc
1   package org.opentrafficsim.graphs;
2   
3   import java.util.ArrayList;
4   import java.util.List;
5   
6   import org.djunits.unit.LengthUnit;
7   import org.djunits.unit.TimeUnit;
8   import org.djunits.value.ValueException;
9   import org.djunits.value.vdouble.scalar.DoubleScalar;
10  import org.djunits.value.vdouble.vector.MutableDoubleVector;
11  import org.opentrafficsim.road.network.lane.Lane;
12  
13  /**
14   * Speed contour plot.
15   * <p>
16   * Copyright (c) 2013-2015 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
17   * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
18   * <p>
19   * $LastChangedDate: 2015-09-03 13:38:01 +0200 (Thu, 03 Sep 2015) $, @version $Revision: 1378 $, by $Author: averbraeck $,
20   * initial version Jul 29, 2014 <br>
21   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
22   */
23  public class SpeedContourPlot extends ContourPlot
24  {
25      /** */
26      private static final long serialVersionUID = 20140729L;
27  
28      /**
29       * Create a new SpeedContourPlot.
30       * @param caption String; text to show above the SpeedContourPlot
31       * @param path List&lt;Lane&gt;; the series of Lanes that will provide the data for this TrajectoryPlot
32       */
33      public SpeedContourPlot(final String caption, final List<Lane> path)
34      {
35          super(caption, new Axis(INITIALLOWERTIMEBOUND, INITIALUPPERTIMEBOUND, STANDARDTIMEGRANULARITIES,
36              STANDARDTIMEGRANULARITIES[STANDARDINITIALTIMEGRANULARITYINDEX], "", "Time", "%.0fs"), path, 0d, 40d, 150d,
37              "speed %.1f km/h", "%.1f km/h", 20d);
38      }
39  
40      /** Storage for the total time spent in each cell. */
41      private ArrayList<MutableDoubleVector.Abs<TimeUnit>> cumulativeTimes;
42  
43      /** Storage for the total length traveled in each cell. */
44      private ArrayList<MutableDoubleVector.Abs<LengthUnit>> cumulativeLengths;
45  
46      /** {@inheritDoc} */
47      @Override
48      public final Comparable<String> getSeriesKey(final int series)
49      {
50          return "speed";
51      }
52  
53      /** {@inheritDoc} */
54      @Override
55      public final void extendXRange(final DoubleScalar<?> newUpperLimit)
56      {
57          if (null == this.cumulativeTimes)
58          {
59              this.cumulativeTimes = new ArrayList<MutableDoubleVector.Abs<TimeUnit>>();
60              this.cumulativeLengths = new ArrayList<MutableDoubleVector.Abs<LengthUnit>>();
61          }
62          int highestBinNeeded =
63              (int) Math.floor(this.getXAxis().getRelativeBin(newUpperLimit) * this.getXAxis().getCurrentGranularity()
64                  / this.getXAxis().getGranularities()[0]);
65          while (highestBinNeeded >= this.cumulativeTimes.size())
66          {
67              try
68              {
69                  this.cumulativeTimes.add(new MutableDoubleVector.Abs.Sparse<TimeUnit>(new double[this.getYAxis()
70                      .getBinCount()], SECOND));
71                  this.cumulativeLengths.add(new MutableDoubleVector.Abs.Sparse<LengthUnit>(new double[this.getYAxis()
72                      .getBinCount()], METER));
73              }
74              catch (ValueException exception)
75              {
76                  exception.printStackTrace();
77              }
78          }
79      }
80  
81      /** {@inheritDoc} */
82      @Override
83      public final void incrementBinData(final int timeBin, final int distanceBin, final double duration,
84          final double distanceCovered, final double acceleration)
85      {
86          if (timeBin < 0 || distanceBin < 0 || 0 == duration || distanceBin >= this.getYAxis().getBinCount())
87          {
88              return;
89          }
90          MutableDoubleVector.Abs<TimeUnit> timeValues = this.cumulativeTimes.get(timeBin);
91          MutableDoubleVector.Abs<LengthUnit> lengthValues = this.cumulativeLengths.get(timeBin);
92          try
93          {
94              timeValues.setSI(distanceBin, timeValues.getSI(distanceBin) + duration);
95              lengthValues.setSI(distanceBin, lengthValues.getSI(distanceBin) + distanceCovered);
96          }
97          catch (ValueException exception)
98          {
99              System.err.println("Error in incrementData:");
100             exception.printStackTrace();
101         }
102     }
103 
104     /** {@inheritDoc} */
105     @Override
106     public final double computeZValue(final int firstTimeBin, final int endTimeBin, final int firstDistanceBin,
107         final int endDistanceBin)
108     {
109         double cumulativeTimeInSI = 0;
110         double cumulativeLengthInSI = 0;
111         if (firstTimeBin >= this.cumulativeTimes.size())
112         {
113             return Double.NaN;
114         }
115         try
116         {
117             for (int timeBinIndex = firstTimeBin; timeBinIndex < endTimeBin; timeBinIndex++)
118             {
119                 if (timeBinIndex >= this.cumulativeTimes.size())
120                 {
121                     break;
122                 }
123                 MutableDoubleVector.Abs<TimeUnit> timeValues = this.cumulativeTimes.get(timeBinIndex);
124                 MutableDoubleVector.Abs<LengthUnit> lengthValues = this.cumulativeLengths.get(timeBinIndex);
125                 for (int distanceBinIndex = firstDistanceBin; distanceBinIndex < endDistanceBin; distanceBinIndex++)
126                 {
127                     cumulativeTimeInSI += timeValues.getSI(distanceBinIndex);
128                     cumulativeLengthInSI += lengthValues.getSI(distanceBinIndex);
129                 }
130             }
131         }
132         catch (ValueException exception)
133         {
134             System.err.println(String.format("Error in getZValue(timeBinRange=[%d-%d], distanceBinRange=[%d-%d]",
135                 firstTimeBin, endTimeBin, firstDistanceBin, endDistanceBin));
136             exception.printStackTrace();
137         }
138         if (0 == cumulativeTimeInSI)
139         {
140             return Double.NaN;
141         }
142         return 3600d / 1000 * cumulativeLengthInSI / cumulativeTimeInSI;
143     }
144 
145 }