1 package org.opentrafficsim.draw.graphs.road;
2
3 import java.awt.Color;
4 import java.util.List;
5
6 import org.djunits.unit.DurationUnit;
7 import org.djunits.unit.LinearDensityUnit;
8 import org.djunits.value.StorageType;
9 import org.djunits.value.ValueException;
10 import org.djunits.value.vdouble.matrix.DurationMatrix;
11 import org.djunits.value.vdouble.scalar.Duration;
12 import org.djunits.value.vdouble.scalar.Length;
13 import org.djunits.value.vdouble.scalar.Time;
14 import org.djunits.value.vfloat.vector.FloatSpeedVector;
15 import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
16 import org.opentrafficsim.core.egtf.Converter;
17 import org.opentrafficsim.core.egtf.Quantity;
18 import org.opentrafficsim.draw.core.BoundsPaintScale;
19 import org.opentrafficsim.draw.graphs.AbstractContourPlot;
20 import org.opentrafficsim.draw.graphs.ContourDataSource;
21 import org.opentrafficsim.draw.graphs.ContourDataSource.ContourDataType;
22 import org.opentrafficsim.draw.graphs.GraphType;
23 import org.opentrafficsim.draw.graphs.GraphUtil;
24 import org.opentrafficsim.kpi.sampling.SamplingException;
25 import org.opentrafficsim.kpi.sampling.Trajectory;
26 import org.opentrafficsim.kpi.sampling.TrajectoryGroup;
27 import org.opentrafficsim.road.network.sampling.GtuData;
28 import org.opentrafficsim.road.network.sampling.data.ReferenceSpeed;
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 public class ContourPlotDelay extends AbstractContourPlot<Duration>
49 {
50
51
52 private static final long serialVersionUID = 20181010L;
53
54
55 private static final Quantity<Duration, DurationMatrix> QUANTITY = new Quantity<>("delay", new Converter<DurationMatrix>()
56 {
57
58 @Override
59 public DurationMatrix convert(final double[][] filteredData)
60 {
61 try
62 {
63 return new DurationMatrix(filteredData, DurationUnit.SI, StorageType.DENSE);
64 }
65 catch (ValueException exception)
66 {
67
68 throw new RuntimeException("Unexpected exception while converting duration to output format.", exception);
69 }
70 }
71 });
72
73
74 private static final ContourDataType<Duration, Duration> CONTOUR_DATA_TYPE = new ContourDataType<Duration, Duration>()
75 {
76
77 @Override
78 public Duration identity()
79 {
80 return Duration.ZERO;
81 }
82
83
84 @Override
85 public Duration processSeries(final Duration intermediate, final List<TrajectoryGroup<?>> trajectories,
86 final List<Length> xFrom, final List<Length> xTo, final Time tFrom, final Time tTo)
87 {
88 double sumActualTime = 0.0;
89 double sumRefTime = 0.0;
90 for (int i = 0; i < trajectories.size(); i++)
91 {
92 TrajectoryGroup<?> trajectoryGroup = trajectories.get(i);
93 for (Trajectory<?> trajectory : trajectoryGroup.getTrajectories())
94 {
95 if (GraphUtil.considerTrajectory(trajectory, tFrom, tTo))
96 {
97 trajectory = trajectory.subSet(xFrom.get(i), xTo.get(i), tFrom, tTo);
98 try
99 {
100 FloatSpeedVector ref = trajectory.getExtendedData(ReferenceSpeed.INSTANCE);
101 float[] v = trajectory.getV();
102 float[] x = trajectory.getX();
103 for (int j = 0; j < v.length - 1; j++)
104 {
105 sumRefTime += (x[j + 1] - x[j]) / ref.get(j).si;
106 }
107 }
108 catch (SamplingException | ValueException exception)
109 {
110 throw new RuntimeException("Unexpected exception while calculating delay.", exception);
111 }
112 sumActualTime += trajectory.getTotalDuration().si;
113 }
114 }
115 }
116 return Duration.createSI(intermediate.si + sumActualTime - sumRefTime);
117 }
118
119
120 @Override
121 public Duration finalize(final Duration intermediate)
122 {
123 return intermediate;
124 }
125
126
127 @SuppressWarnings("synthetic-access")
128 @Override
129 public Quantity<Duration, ?> getQuantity()
130 {
131 return QUANTITY;
132 }
133
134 };
135
136
137
138
139
140
141
142 public ContourPlotDelay(final String caption, final OTSSimulatorInterface simulator,
143 final ContourDataSource<GtuData> dataPool)
144 {
145 super(caption, simulator, dataPool, createPaintScale(), new Duration(0.05, DurationUnit.SI), "%.1f/km",
146 "delay %.1f /km");
147 dataPool.getSampler().registerExtendedDataType(ReferenceSpeed.INSTANCE);
148 }
149
150
151
152
153
154 private static BoundsPaintScale createPaintScale()
155 {
156 double[] boundaries = { 0.0, 0.05, 0.2 };
157 Color[] colorValues = BoundsPaintScale.GREEN_RED;
158 return new BoundsPaintScale(boundaries, colorValues);
159 }
160
161
162 @Override
163 public GraphType getGraphType()
164 {
165 return GraphType.DELAY_CONTOUR;
166 }
167
168
169 @Override
170 protected double scale(final double si)
171 {
172 return LinearDensityUnit.PER_KILOMETER.getScale().fromStandardUnit(si);
173 }
174
175
176 @Override
177 protected double getValue(final int item, final double cellLength, final double cellSpan)
178 {
179 return getDataPool().get(item, CONTOUR_DATA_TYPE) / (cellLength * cellSpan);
180 }
181
182
183 @Override
184 protected ContourDataType<Duration, Duration> getContourDataType()
185 {
186 return CONTOUR_DATA_TYPE;
187 }
188
189 }