1 package org.opentrafficsim.road.od;
2
3 import java.util.LinkedHashMap;
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.djutils.exceptions.Throw;
9 import org.opentrafficsim.core.gtu.GtuErrorHandler;
10 import org.opentrafficsim.core.gtu.GtuType;
11 import org.opentrafficsim.core.idgenerator.IdSupplier;
12 import org.opentrafficsim.core.network.LinkType;
13 import org.opentrafficsim.core.network.Node;
14 import org.opentrafficsim.road.gtu.generator.CfBaRoomChecker;
15 import org.opentrafficsim.road.gtu.generator.GeneratorPositions.LaneBiases;
16 import org.opentrafficsim.road.gtu.generator.LaneBasedGtuGenerator.RoomChecker;
17 import org.opentrafficsim.road.gtu.generator.MarkovCorrelation;
18 import org.opentrafficsim.road.gtu.generator.characteristics.LaneBasedGtuCharacteristicsGeneratorOd;
19 import org.opentrafficsim.road.gtu.generator.headway.ArrivalsHeadwayGenerator.HeadwayDistribution;
20 import org.opentrafficsim.road.gtu.lane.LaneBookkeeping;
21 import org.opentrafficsim.road.network.lane.Lane;
22
23 /**
24 * Options for vehicle generation based on an OD matrix.
25 * <p>
26 * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
27 * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
28 * </p>
29 * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
30 * @author <a href="https://github.com/peter-knoppers">Peter Knoppers</a>
31 * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
32 */
33 public class OdOptions
34 {
35 /** Headway randomization option. */
36 public static final Option<HeadwayDistribution> HEADWAY_DIST =
37 new Option<>("headway distribution", HeadwayDistribution.EXPONENTIAL);
38
39 /** ID generator option. */
40 public static final Option<IdSupplier> GTU_ID = new Option<>("gtu id", new IdSupplier(""));
41
42 /** GTU characteristics generator option. */
43 public static final Option<LaneBasedGtuCharacteristicsGeneratorOd> GTU_TYPE = new Option<>("gtu type", null);
44
45 /** Room checker option. */
46 public static final Option<RoomChecker> ROOM_CHECKER = new Option<>("room checker", new CfBaRoomChecker());
47
48 /** Markov chain for GTU type option. */
49 public static final Option<MarkovCorrelation<GtuType, Frequency>> MARKOV = new Option<>("markov", null);
50
51 /** Initial distance over which lane changes shouldn't be performed option. */
52 public static final Option<Length> NO_LC_DIST = new Option<>("no lc distance", null);
53
54 /** Lane bookkeeping. */
55 public static final Option<LaneBookkeeping> BOOKKEEPING = new Option<>("bookkeeping", LaneBookkeeping.EDGE);
56
57 /** Error handler when GTU exceptions occur. */
58 public static final Option<GtuErrorHandler> ERROR_HANDLER = new Option<>("error handler", GtuErrorHandler.THROW);
59
60 /** Lane bias. Default is none, i.e. uniform distribution over lanes for all GTU types. */
61 public static final Option<LaneBiases> LANE_BIAS = new Option<>("lane bias", new LaneBiases());
62
63 /** Options overall. */
64 private OptionSet<Void> options = new OptionSet<>();
65
66 /** Options per lane. */
67 private OptionSet<Lane> laneOptions = new OptionSet<>();
68
69 /** Options per node. */
70 private OptionSet<Node> nodeOptions = new OptionSet<>();
71
72 /** Options per road type. */
73 private OptionSet<LinkType> linkTypeOptions = new OptionSet<>();
74
75 /**
76 * Constructor.
77 */
78 public OdOptions()
79 {
80 //
81 }
82
83 /**
84 * Set option value.
85 * @param option option
86 * @param value option value
87 * @param <K> value type
88 * @return this option set
89 */
90 public final <K> OdOptions set(final Option<K> option, final K value)
91 {
92 this.options.set(null, option, value);
93 return this;
94 }
95
96 /**
97 * Set option value for lane.
98 * @param lane lane
99 * @param option option
100 * @param value option value
101 * @param <K> value type
102 * @return this option set
103 */
104 public final <K> OdOptions set(final Lane lane, final Option<K> option, final K value)
105 {
106 this.laneOptions.set(lane, option, value);
107 return this;
108 }
109
110 /**
111 * Set option value for node.
112 * @param node node
113 * @param option option
114 * @param value option value
115 * @param <K> value type
116 * @return this option set
117 */
118 public final <K> OdOptions set(final Node node, final Option<K> option, final K value)
119 {
120 this.nodeOptions.set(node, option, value);
121 return this;
122 }
123
124 /**
125 * Set option value for link type.
126 * @param linkType link type
127 * @param option option
128 * @param value option value
129 * @param <K> value type
130 * @return this option set
131 */
132 public final <K> OdOptions set(final LinkType linkType, final Option<K> option, final K value)
133 {
134 this.linkTypeOptions.set(linkType, option, value);
135 return this;
136 }
137
138 /**
139 * Get option value. If a value is specified for a specific category, it is returned. The following order is used:
140 * <ul>
141 * <li>{@code Lane}</li>
142 * <li>{@code Node} (origin)</li>
143 * <li>{@code LinkType}</li>
144 * <li>None (global option value)</li>
145 * <li>Default option value</li>
146 * </ul>
147 * @param option option
148 * @param lane lane to obtain specific option value, may be null
149 * @param node node to obtain specific option value, may be null
150 * @param linkType link type to obtain specific option value, may be null
151 * @param <K> value type
152 * @return option value
153 */
154 public final <K> K get(final Option<K> option, final Lane lane, final Node node, final LinkType linkType)
155 {
156 Throw.whenNull(option, "Option may not be null.");
157 K value = this.laneOptions.get(lane, option);
158 if (value != null)
159 {
160 return value;
161 }
162 value = this.nodeOptions.get(node, option);
163 if (value != null)
164 {
165 return value;
166 }
167 value = this.linkTypeOptions.get(linkType, option);
168 if (value != null)
169 {
170 return value;
171 }
172 value = this.options.get(null, option);
173 if (value != null)
174 {
175 return value;
176 }
177 return option.getDefaultValue();
178 }
179
180 /**
181 * Utility class to store options.
182 * <p>
183 * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
184 * <br>
185 * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
186 * </p>
187 * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
188 * @author <a href="https://github.com/peter-knoppers">Peter Knoppers</a>
189 * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
190 * @param <K> option value type
191 */
192 public static final class Option<K>
193 {
194
195 /** Id. */
196 private final String id;
197
198 /** Default value. */
199 private final K defaultValue;
200
201 /**
202 * Constructor.
203 * @param id id
204 * @param defaultValue default value
205 */
206 Option(final String id, final K defaultValue)
207 {
208 this.id = id;
209 this.defaultValue = defaultValue;
210 }
211
212 /**
213 * Returns the default value.
214 * @return default value
215 */
216 public K getDefaultValue()
217 {
218 return this.defaultValue;
219 }
220
221 @Override
222 public int hashCode()
223 {
224 final int prime = 31;
225 int result = 1;
226 result = prime * result + ((this.id == null) ? 0 : this.id.hashCode());
227 return result;
228 }
229
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 @Override
261 public String toString()
262 {
263 return "Option [id=" + this.id + "]";
264 }
265
266 }
267
268 /**
269 * Single set of options for a certain category, i.e. lane, node, link type or null (i.e. global).
270 * <p>
271 * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
272 * <br>
273 * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
274 * </p>
275 * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
276 * @author <a href="https://github.com/peter-knoppers">Peter Knoppers</a>
277 * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
278 * @param <C> category type, i.e. {@code Lane}, {@code Node}, {@code LinkType} or {@code Void} (i.e. global).
279 */
280 private class OptionSet<C>
281 {
282
283 /** Options. */
284 private Map<C, Map<Option<?>, Object>> optionsSet = new LinkedHashMap<>();
285
286 /**
287 * Constructor.
288 */
289 OptionSet()
290 {
291 //
292 }
293
294 /**
295 * Set value in option set.
296 * @param category category
297 * @param option option
298 * @param value value
299 * @param <K> option value type
300 */
301 public <K> void set(final C category, final Option<K> option, final K value)
302 {
303 Map<Option<?>, Object> map = this.optionsSet.get(category);
304 if (map == null)
305 {
306 map = new LinkedHashMap<>();
307 this.optionsSet.put(category, map);
308 }
309 map.put(option, value);
310 }
311
312 /**
313 * Returns the option value for the category.
314 * @param category category
315 * @param option option
316 * @return option value for the category
317 * @param <K> value type
318 */
319 @SuppressWarnings("unchecked")
320 public <K> K get(final C category, final Option<K> option)
321 {
322 if (!this.optionsSet.containsKey(category))
323 {
324 return null;
325 }
326 return (K) this.optionsSet.get(category).get(option);
327 }
328
329 }
330
331 }