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