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
15
16
17
18
19
20
21
22
23 public class SpeedContourPlot extends ContourPlot
24 {
25
26 private static final long serialVersionUID = 20140729L;
27
28
29
30
31
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
41 private ArrayList<MutableDoubleVector.Abs<TimeUnit>> cumulativeTimes;
42
43
44 private ArrayList<MutableDoubleVector.Abs<LengthUnit>> cumulativeLengths;
45
46
47 @Override
48 public final Comparable<String> getSeriesKey(final int series)
49 {
50 return "speed";
51 }
52
53
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
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
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 }