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