1 package org.opentrafficsim.road.gtu.generator.od;
2
3 import java.util.HashMap;
4 import java.util.Map;
5
6 import org.djunits.value.vdouble.scalar.Frequency;
7 import org.djunits.value.vdouble.scalar.Length;
8 import org.opentrafficsim.core.gtu.GTUType;
9 import org.opentrafficsim.core.gtu.animation.GTUColorer;
10 import org.opentrafficsim.core.idgenerator.IdGenerator;
11 import org.opentrafficsim.core.network.LinkType;
12 import org.opentrafficsim.core.network.Node;
13 import org.opentrafficsim.road.gtu.animation.DefaultSwitchableGTUColorer;
14 import org.opentrafficsim.road.gtu.generator.CFBARoomChecker;
15 import org.opentrafficsim.road.gtu.generator.GeneratorPositions.LaneBias;
16 import org.opentrafficsim.road.gtu.generator.GeneratorPositions.LaneBiases;
17 import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator.RoomChecker;
18 import org.opentrafficsim.road.gtu.generator.MarkovCorrelation;
19 import org.opentrafficsim.road.gtu.generator.headway.ArrivalsHeadwayGenerator.HeadwayDistribution;
20 import org.opentrafficsim.road.network.lane.Lane;
21
22 import nl.tudelft.simulation.language.Throw;
23
24 /**
25 * Options for vehicle generation based on an OD matrix.
26 * <p>
27 * Copyright (c) 2013-2018 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
28 * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
29 * <p>
30 * @version $Revision$, $LastChangedDate$, by $Author$, initial version 6 dec. 2017 <br>
31 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
32 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
33 * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
34 */
35 public class ODOptions
36 {
37
38 /** Headway randomization option. */
39 public static final Option<HeadwayDistribution> HEADWAY_DIST =
40 new Option<>("headway distribution", HeadwayDistribution.EXPONENTIAL);
41
42 /** ID generator option. */
43 public static final Option<IdGenerator> GTU_ID = new Option<>("gtu id", new IdGenerator(""));
44
45 /** GTU colorer option. */
46 public static final Option<GTUColorer> GTU_COLORER = new Option<>("gtu colorer", new DefaultSwitchableGTUColorer());
47
48 /** GTU characteristics generator option. */
49 public static final Option<GTUCharacteristicsGeneratorOD> GTU_TYPE =
50 new Option<>("gtu type", new DefaultGTUCharacteristicsGeneratorOD());
51
52 /** Room checker option. */
53 public static final Option<RoomChecker> ROOM_CHECKER = new Option<>("room checker", new CFBARoomChecker());
54
55 /** Markov chain for GTU type option. */
56 public static final Option<MarkovCorrelation<GTUType, Frequency>> MARKOV = new Option<>("markov", null);
57
58 /** Lane bias. Default is Truck: truck right (strong right, max 2 lanes), Vehicle (other): weak left. */
59 public static final Option<LaneBiases> LANE_BIAS = new Option<>("lane bias",
60 new LaneBiases().addBias(GTUType.TRUCK, LaneBias.TRUCK_RIGHT).addBias(GTUType.VEHICLE, LaneBias.WEAK_LEFT));
61
62 /** Initial distance over which lane changes shouldn't be performed option. */
63 public static final Option<Length> NO_LC_DIST = new Option<>("no lc distance", null);
64
65 /** Show generator animation option. */
66 public static final Option<Boolean> ANIMATION = new Option<>("show generator animation", false);
67
68 /** Options overall. */
69 private OptionSet<Void> options = new OptionSet<>();
70
71 /** Options per lane. */
72 private OptionSet<Lane> laneOptions = new OptionSet<>();
73
74 /** Options per node. */
75 private OptionSet<Node> nodeOptions = new OptionSet<>();
76
77 /** Options per road type. */
78 private OptionSet<LinkType> linkTypeOptions = new OptionSet<>();
79
80 /**
81 * Set option value.
82 * @param option Option<K>; option
83 * @param value K; option value
84 * @param <K> value type
85 * @return this option set
86 */
87 public final <K> ODOptions set(final Option<K> option, final K value)
88 {
89 this.options.set(null, option, value);
90 return this;
91 }
92
93 /**
94 * Set option value for lane.
95 * @param lane Lane; lane
96 * @param option Option<K>; option
97 * @param value K; option value
98 * @param <K> value type
99 * @return this option set
100 */
101 public final <K> ODOptions set(final Lane lane, final Option<K> option, final K value)
102 {
103 this.laneOptions.set(lane, option, value);
104 return this;
105 }
106
107 /**
108 * Set option value for node.
109 * @param node Node; node
110 * @param option Option<K>; option
111 * @param value K; option value
112 * @param <K> value type
113 * @return this option set
114 */
115 public final <K> ODOptions set(final Node node, final Option<K> option, final K value)
116 {
117 this.nodeOptions.set(node, option, value);
118 return this;
119 }
120
121 /**
122 * Set option value for link type.
123 * @param linkType LinkType; link type
124 * @param option Option<K>; option
125 * @param value K; option value
126 * @param <K> value type
127 * @return this option set
128 */
129 public final <K> ODOptions set(final LinkType linkType, final Option<K> option, final K value)
130 {
131 this.linkTypeOptions.set(linkType, option, value);
132 return this;
133 }
134
135 /**
136 * Get option value. If a value is specified for a specific category, it is returned. The following order is used:
137 * <ul>
138 * <li>{@code Lane}</li>
139 * <li>{@code Node} (origin)</li>
140 * <li>{@code LinkType}</li>
141 * <li>None (global option value)</li>
142 * <li>Default option value</li>
143 * </ul>
144 * @param option Option<K>; option
145 * @param lane Lane; lane to obtain specific option value, may be null
146 * @param node Node; node to obtain specific option value, may be null
147 * @param linkType LinkType; link type to obtain specific option value, may be null
148 * @param <K> value type
149 * @return K; option value
150 */
151 public final <K> K get(final Option<K> option, final Lane lane, final Node node, final LinkType linkType)
152 {
153 Throw.whenNull(option, "Option may not be null.");
154 K value = this.laneOptions.get(lane, option);
155 if (value != null)
156 {
157 return value;
158 }
159 value = this.nodeOptions.get(node, option);
160 if (value != null)
161 {
162 return value;
163 }
164 value = this.linkTypeOptions.get(linkType, option);
165 if (value != null)
166 {
167 return value;
168 }
169 value = this.options.get(null, option);
170 if (value != null)
171 {
172 return value;
173 }
174 return option.getDefaultValue();
175 }
176
177 /**
178 * Utility class to store options.
179 * <p>
180 * Copyright (c) 2013-2018 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
181 * <br>
182 * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
183 * <p>
184 * @version $Revision$, $LastChangedDate$, by $Author$, initial version 6 dec. 2017 <br>
185 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
186 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
187 * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
188 * @param <K> option value type
189 */
190 private static final class Option<K>
191 {
192
193 /** Id. */
194 private final String id;
195
196 /** Default value. */
197 private final K defaultValue;
198
199 /**
200 * Constructor.
201 * @param id String; id
202 * @param defaultValue K; default value
203 */
204 Option(final String id, final K defaultValue)
205 {
206 this.id = id;
207 this.defaultValue = defaultValue;
208 }
209
210 /**
211 * Returns the default value.
212 * @return default value
213 */
214 public K getDefaultValue()
215 {
216 return this.defaultValue;
217 }
218
219 /** {@inheritDoc} */
220 @Override
221 public int hashCode()
222 {
223 final int prime = 31;
224 int result = 1;
225 result = prime * result + ((this.id == null) ? 0 : this.id.hashCode());
226 return result;
227 }
228
229 /** {@inheritDoc} */
230 @Override
231 public boolean equals(final Object obj)
232 {
233 if (this == obj)
234 {
235 return true;
236 }
237 if (obj == null)
238 {
239 return false;
240 }
241 if (getClass() != obj.getClass())
242 {
243 return false;
244 }
245 Option<?> other = (Option<?>) obj;
246 if (this.id == null)
247 {
248 if (other.id != null)
249 {
250 return false;
251 }
252 }
253 else if (!this.id.equals(other.id))
254 {
255 return false;
256 }
257 return true;
258 }
259
260 /** {@inheritDoc} */
261 @Override
262 public String toString()
263 {
264 return "Option [id=" + this.id + "]";
265 }
266
267 }
268
269 /**
270 * Single set of options for a certain category, i.e. lane, node, link type or null (i.e. global).
271 * <p>
272 * Copyright (c) 2013-2018 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
273 * <br>
274 * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
275 * <p>
276 * @version $Revision$, $LastChangedDate$, by $Author$, initial version 11 jan. 2018 <br>
277 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
278 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
279 * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
280 * @param <C> category type, i.e. {@code Lane}, {@code Node}, {@code LinkType} or {@code Void} (i.e. global).
281 */
282 private class OptionSet<C>
283 {
284
285 /** Options. */
286 private Map<C, Map<Option<?>, Object>> optionsSet = new HashMap<>();
287
288 /**
289 * Constructor.
290 */
291 OptionSet()
292 {
293 //
294 }
295
296 /**
297 * Set value in option set.
298 * @param category C; category
299 * @param option Option<K>; option
300 * @param value K; value
301 * @param <K> option value type
302 */
303 public <K> void set(final C category, final Option<K> option, final K value)
304 {
305 Map<Option<?>, Object> map = this.optionsSet.get(category);
306 if (map == null)
307 {
308 map = new HashMap<>();
309 this.optionsSet.put(category, map);
310 }
311 map.put(option, value);
312 }
313
314 /**
315 * Returns the option value for the category.
316 * @param category C; category
317 * @param option Option<K>; option
318 * @return option value for the category
319 * @param <K> value type
320 */
321 @SuppressWarnings("unchecked")
322 public <K> K get(final C category, final Option<K> option)
323 {
324 if (!this.optionsSet.containsKey(category))
325 {
326 return null;
327 }
328 return (K) this.optionsSet.get(category).get(option);
329 }
330
331 }
332
333 }