1 package org.opentrafficsim.road.network.factory.xml.parser;
2
3 import java.math.BigInteger;
4 import java.util.ArrayList;
5 import java.util.Collections;
6 import java.util.Comparator;
7 import java.util.LinkedHashMap;
8 import java.util.LinkedHashSet;
9 import java.util.List;
10 import java.util.Map;
11 import java.util.Set;
12
13 import org.djunits.value.StorageType;
14 import org.djunits.value.vdouble.scalar.Acceleration;
15 import org.djunits.value.vdouble.scalar.Duration;
16 import org.djunits.value.vdouble.scalar.Frequency;
17 import org.djunits.value.vdouble.scalar.Length;
18 import org.djunits.value.vdouble.scalar.Speed;
19 import org.djunits.value.vdouble.scalar.Time;
20 import org.djunits.value.vdouble.vector.FrequencyVector;
21 import org.djunits.value.vdouble.vector.TimeVector;
22 import org.djutils.exceptions.Throw;
23 import org.djutils.exceptions.Try;
24 import org.opentrafficsim.core.distributions.Generator;
25 import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
26 import org.opentrafficsim.core.gtu.GTUException;
27 import org.opentrafficsim.core.gtu.GTUType;
28 import org.opentrafficsim.core.gtu.NestedCache;
29 import org.opentrafficsim.core.gtu.TemplateGTUType;
30 import org.opentrafficsim.core.idgenerator.IdGenerator;
31 import org.opentrafficsim.core.network.Link;
32 import org.opentrafficsim.core.network.Node;
33 import org.opentrafficsim.core.network.route.Route;
34 import org.opentrafficsim.road.gtu.generator.GeneratorPositions.LaneBias;
35 import org.opentrafficsim.road.gtu.generator.GeneratorPositions.LaneBiases;
36 import org.opentrafficsim.road.gtu.generator.GeneratorPositions.RoadPosition;
37 import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator.RoomChecker;
38 import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator;
39 import org.opentrafficsim.road.gtu.generator.MarkovCorrelation;
40 import org.opentrafficsim.road.gtu.generator.characteristics.LaneBasedGTUCharacteristicsGenerator;
41 import org.opentrafficsim.road.gtu.generator.od.DefaultGTUCharacteristicsGeneratorOD.Factory;
42 import org.opentrafficsim.road.gtu.generator.od.ODApplier.GeneratorObjects;
43 import org.opentrafficsim.road.gtu.generator.od.ODApplier;
44 import org.opentrafficsim.road.gtu.generator.od.ODOptions;
45 import org.opentrafficsim.road.gtu.generator.od.ODOptions.Option;
46 import org.opentrafficsim.road.gtu.generator.od.StrategicalPlannerFactorySupplierOD;
47 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
48 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.DefaultLMRSPerceptionFactory;
49 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRSFactory;
50 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
51 import org.opentrafficsim.road.gtu.strategical.od.Categorization;
52 import org.opentrafficsim.road.gtu.strategical.od.Category;
53 import org.opentrafficsim.road.gtu.strategical.od.Interpolation;
54 import org.opentrafficsim.road.gtu.strategical.od.ODMatrix;
55 import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
56 import org.opentrafficsim.road.gtu.strategical.route.RouteGeneratorOD;
57 import org.opentrafficsim.road.network.OTSRoadNetwork;
58 import org.opentrafficsim.road.network.factory.xml.XmlParserException;
59 import org.opentrafficsim.road.network.factory.xml.utils.ParseDistribution;
60 import org.opentrafficsim.road.network.factory.xml.utils.StreamInformation;
61 import org.opentrafficsim.road.network.factory.xml.utils.Transformer;
62 import org.opentrafficsim.road.network.lane.CrossSectionLink;
63 import org.opentrafficsim.road.network.lane.DirectedLanePosition;
64 import org.opentrafficsim.road.network.lane.Lane;
65 import org.opentrafficsim.xml.generated.CATEGORYTYPE;
66 import org.opentrafficsim.xml.generated.GENERATOR;
67 import org.opentrafficsim.xml.generated.GLOBALTIMETYPE.TIME;
68 import org.opentrafficsim.xml.generated.GTUTEMPLATE;
69 import org.opentrafficsim.xml.generated.GTUTEMPLATEMIX;
70 import org.opentrafficsim.xml.generated.LEVELTIMETYPE;
71 import org.opentrafficsim.xml.generated.LISTGENERATOR;
72 import org.opentrafficsim.xml.generated.NETWORKDEMAND;
73 import org.opentrafficsim.xml.generated.OD;
74 import org.opentrafficsim.xml.generated.OD.DEMAND;
75 import org.opentrafficsim.xml.generated.ODOPTIONS;
76 import org.opentrafficsim.xml.generated.ODOPTIONS.ODOPTIONSITEM;
77 import org.opentrafficsim.xml.generated.ODOPTIONS.ODOPTIONSITEM.DEFAULTMODEL;
78 import org.opentrafficsim.xml.generated.ODOPTIONS.ODOPTIONSITEM.LANEBIASES.LANEBIAS;
79 import org.opentrafficsim.xml.generated.ODOPTIONS.ODOPTIONSITEM.MARKOV.STATE;
80 import org.opentrafficsim.xml.generated.ODOPTIONS.ODOPTIONSITEM.MODEL;
81 import org.opentrafficsim.xml.generated.SINK;
82
83 import nl.tudelft.simulation.jstats.streams.StreamInterface;
84
85
86
87
88
89
90
91
92
93
94
95
96 public class DemandParser
97 {
98
99 private DemandParser()
100 {
101
102 }
103
104
105
106
107
108
109
110
111
112
113
114
115
116 public static List<LaneBasedGTUGenerator> parseDemand(final OTSRoadNetwork otsNetwork,
117 final OTSSimulatorInterface simulator, final List<NETWORKDEMAND> demands,
118 final Map<String, GTUTEMPLATE> gtuTemplates, Map<String, LaneBasedStrategicalPlannerFactory<?>> factories,
119 final Map<String, String> modelIdReferrals, final Map<String, StreamInformation> streamMap)
120 throws XmlParserException
121 {
122 List<LaneBasedGTUGenerator> generators = new ArrayList<>();
123
124 IdGenerator idGenerator = new IdGenerator("");
125
126 int idCounter = 1;
127 for (NETWORKDEMAND subDemand : demands)
128 {
129
130
131 for (GTUTEMPLATEMIX gtuMix : subDemand.getGTUTEMPLATEMIX())
132 {
133
134 }
135
136 for (GENERATOR generator : subDemand.getGENERATOR())
137 {
138 String linkId = generator.getLINK();
139 String laneId = null;
140
141 String id = linkId + "." + laneId + "." + idCounter;
142 Generator<Duration> interarrivelTimeGenerator;
143 RoomChecker roomChecker;
144 LaneBasedGTUCharacteristicsGenerator laneBasedGTUCharacteristicsGenerator;
145
146
147 Link link = otsNetwork.getLink(linkId);
148 Throw.when(!(link instanceof CrossSectionLink), XmlParserException.class,
149 "Generator on link %s can not be added as the link is not a CrossSectionLink.", linkId);
150
151 Set<DirectedLanePosition> positions = new LinkedHashSet<>();
152
153
154
155
156 }
157
158 for (LISTGENERATOR generator : subDemand.getLISTGENERATOR())
159 {
160
161 }
162
163 for (SINK sink : subDemand.getSINK())
164 {
165
166 }
167
168
169 Map<String, ODOPTIONS> odOptionsMap = new LinkedHashMap<>();
170 for (ODOPTIONS odOptions : subDemand.getODOPTIONS())
171 {
172 odOptionsMap.put(odOptions.getID(), odOptions);
173 }
174 List<OD> ods = subDemand.getOD();
175 for (OD od : ods)
176 {
177
178
179 String id = od.getID();
180
181
182 List<Node> origins = new ArrayList<>();
183 List<Node> destinations = new ArrayList<>();
184 for (DEMAND demand : od.getDEMAND())
185 {
186 if (!origins.contains(otsNetwork.getNode(demand.getORIGIN())))
187 {
188 origins.add(otsNetwork.getNode(demand.getORIGIN()));
189 }
190 if (!destinations.contains(otsNetwork.getNode(demand.getDESTINATION())))
191 {
192 destinations.add(otsNetwork.getNode(demand.getDESTINATION()));
193 }
194 }
195
196
197 Categorization categorization;
198 Map<String, Category> categories = new LinkedHashMap<>();
199 Map<String, Double> categoryFactors = new LinkedHashMap<>();
200 if (od.getCATEGORY() == null || od.getCATEGORY().isEmpty())
201 {
202 categorization = Categorization.UNCATEGORIZED;
203 }
204 else
205 {
206 List<Class<?>> categoryClasses = new ArrayList<>();
207 if (od.getCATEGORY().get(0).getGTUTYPE() != null)
208 {
209 categoryClasses.add(GTUType.class);
210 }
211 if (od.getCATEGORY().get(0).getROUTE() != null)
212 {
213 categoryClasses.add(Route.class);
214 }
215 if (od.getCATEGORY().get(0).getLANE() != null)
216 {
217 categoryClasses.add(Lane.class);
218 }
219 if (categoryClasses.isEmpty())
220 {
221
222 categorization = Categorization.UNCATEGORIZED;
223 }
224 else
225 {
226 Class<?> clazz = categoryClasses.get(0);
227 categoryClasses.remove(0);
228 categorization = new Categorization("", clazz, categoryClasses.toArray(new Class[0]));
229 }
230
231 for (CATEGORYTYPE category : od.getCATEGORY())
232 {
233 Throw.when(
234 (categorization.entails(GTUType.class) && category.getGTUTYPE() == null)
235 || (!categorization.entails(GTUType.class) && category.getGTUTYPE() != null),
236 XmlParserException.class, "Categories are inconsistent concerning GTUType.");
237 Throw.when(
238 (categorization.entails(Route.class) && category.getROUTE() == null)
239 || (!categorization.entails(Route.class) && category.getROUTE() != null),
240 XmlParserException.class, "Categories are inconsistent concerning Route.");
241 Throw.when(
242 (categorization.entails(Lane.class) && category.getLANE() == null)
243 || (!categorization.entails(Lane.class) && category.getLANE() != null),
244 XmlParserException.class, "Categories are inconsistent concerning Lane.");
245 List<Object> objects = new ArrayList<>();
246 if (categorization.entails(GTUType.class))
247 {
248 objects.add(otsNetwork.getGtuType(category.getGTUTYPE()));
249 }
250 if (categorization.entails(Route.class))
251 {
252 objects.add(otsNetwork.getRoute(category.getROUTE()));
253 }
254 if (categorization.entails(Lane.class))
255 {
256 CrossSectionLink link = (CrossSectionLink) otsNetwork.getLink(category.getLANE().getLINK());
257 Lane lane = (Lane) link.getCrossSectionElement(category.getLANE().getID());
258 objects.add(lane);
259 }
260 categories.put(category.getID(), new Category(categorization, objects.get(0),
261 objects.subList(1, objects.size()).toArray(new Object[objects.size() - 1])));
262 categoryFactors.put(category.getID(), parsePositiveFactor(category.getFACTOR()));
263 }
264 }
265
266
267 TimeVector globalTimeVector = null;
268 if (od.getGLOBALTIME() != null)
269 {
270 List<Time> timeList = new ArrayList<>();
271 for (TIME time : od.getGLOBALTIME().getTIME())
272 {
273 timeList.add(time.getVALUE());
274 }
275 Collections.sort(timeList);
276 globalTimeVector = Try.assign(() -> new TimeVector(timeList, StorageType.DENSE), XmlParserException.class,
277 "Global time has no values.");
278 }
279
280
281 Interpolation globalInterpolation =
282 od.getGLOBALINTERPOLATION().equals("LINEAR") ? Interpolation.LINEAR : Interpolation.STEPWISE;
283
284
285 double globalFactor = parsePositiveFactor(od.getGLOBALFACTOR());
286
287
288 ODMatrix odMatrix =
289 new ODMatrix(id, origins, destinations, categorization, globalTimeVector, globalInterpolation);
290
291
292 NestedCache<Set<DEMAND>> demandPerOD = new NestedCache<>(Node.class, Node.class);
293 for (DEMAND demand : od.getDEMAND())
294 {
295 Node origin = otsNetwork.getNode(demand.getORIGIN());
296 Node destination = otsNetwork.getNode(demand.getDESTINATION());
297 demandPerOD.getValue(() -> new LinkedHashSet<>(), origin, destination).add(demand);
298 }
299 for (Object o : demandPerOD.getKeys())
300 {
301 NestedCache<Set<DEMAND>> demandPerD = demandPerOD.getChild(o);
302 for (Object d : demandPerD.getKeys())
303 {
304 Set<DEMAND> set = demandPerD.getValue(d);
305 Node origin = (Node) o;
306 Node destination = (Node) d;
307 Throw.when(categorization.equals(Categorization.UNCATEGORIZED) && set.size() > 1,
308 XmlParserException.class,
309 "Multiple DEMAND tags define demand from %s to %s in uncategorized demand.", origin.getId(),
310 destination.getId());
311
312
313 DEMAND main = null;
314 if (!categorization.equals(Categorization.UNCATEGORIZED))
315 {
316 for (DEMAND demand : set)
317 {
318 if (demand.getCATEGORY() == null)
319 {
320 Throw.when(main != null, XmlParserException.class,
321 "Multiple DEMAND tags define main demand from %s to %s.", origin.getId(),
322 destination.getId());
323 Throw.when(set.size() == 1, XmlParserException.class,
324 "Categorized demand from %s to %s has single DEMAND, and without category.",
325 origin.getId(), destination.getId());
326 main = demand;
327 }
328 }
329 }
330
331
332 for (DEMAND demand : set)
333 {
334
335 if (demand.equals(main))
336 {
337 continue;
338 }
339
340
341 List<LEVELTIMETYPE> timeTags =
342 demand.getLEVEL() == null || demand.getLEVEL().get(0).getTIME() == null
343 ? (main == null || main.getLEVEL() == null
344 || main.getLEVEL().get(0).getTIME() == null ? null : main.getLEVEL())
345 : demand.getLEVEL();
346 TimeVector timeVector = timeTags == null ? globalTimeVector : parseTimeVector(timeTags);
347
348
349 String interpolationString = demand.getINTERPOLATION() == null
350 ? (main == null || main.getINTERPOLATION() == null ? null : main.getINTERPOLATION())
351 : demand.getINTERPOLATION();
352 Interpolation interpolation = interpolationString == null ? globalInterpolation
353 : interpolationString.equals("LINEAR") ? Interpolation.LINEAR : Interpolation.STEPWISE;
354
355
356 Category category = categorization.equals(Categorization.UNCATEGORIZED) ? Category.UNCATEGORIZED
357 : categories.get(demand.getCATEGORY());
358
359
360 double factor = globalFactor;
361 factor = main == null ? factor : factor * parsePositiveFactor(main.getFACTOR());
362 factor *= parsePositiveFactor(demand.getFACTOR());
363
364
365 Frequency[] demandRaw = new Frequency[timeVector.size()];
366 List<LEVELTIMETYPE> baseDemand;
367 List<LEVELTIMETYPE> factors = null;
368 if (demand.getLEVEL() == null)
369 {
370
371 baseDemand = main.getLEVEL();
372 }
373 else if (demand.getLEVEL().get(0).getValue().contains("veh"))
374 {
375
376 baseDemand = demand.getLEVEL();
377 }
378 else
379 {
380
381 baseDemand = main.getLEVEL();
382 factors = demand.getLEVEL();
383 }
384
385 sortLevelTime(baseDemand);
386 if (factors != null)
387 {
388 sortLevelTime(factors);
389 }
390
391 for (int i = 0; i < baseDemand.size(); i++)
392 {
393 Throw.when(
394 baseDemand.get(i).getTIME() != null && factors != null
395 && factors.get(i).getTIME() != null
396 && !baseDemand.get(i).getTIME().eq(factors.get(i).getTIME()),
397 XmlParserException.class,
398 "Demand from %s to %s is specified with factors that have different time from the base demand.",
399 origin, destination);
400 demandRaw[i] = parseLevel(baseDemand.get(i).getValue(),
401 factor * (factors == null ? 1.0 : parsePositiveFactor(factors.get(i).getValue())));
402 }
403 FrequencyVector demandVector = Try.assign(() -> new FrequencyVector(demandRaw, StorageType.DENSE),
404 XmlParserException.class, "Unexpected empty demand.");
405
406
407 odMatrix.putDemandVector(origin, destination, category, demandVector, timeVector, interpolation);
408 }
409
410 }
411 }
412
413
414 ODOptions odOptions = new ODOptions().set(ODOptions.GTU_ID, idGenerator);
415
416 Set<TemplateGTUType> templates = new LinkedHashSet<>();
417 for (GTUTEMPLATE template : gtuTemplates.values())
418 {
419 GTUType gtuType = otsNetwork.getGtuType(template.getGTUTYPE());
420 Generator<Length> lengthGenerator = ParseDistribution.parseLengthDist(streamMap, template.getLENGTHDIST());
421 Generator<Length> widthGenerator = ParseDistribution.parseLengthDist(streamMap, template.getWIDTHDIST());
422 Generator<Speed> maximumSpeedGenerator =
423 ParseDistribution.parseSpeedDist(streamMap, template.getMAXSPEEDDIST());
424 if (template.getMAXACCELERATIONDIST() == null || template.getMAXDECELERATIONDIST() == null)
425 {
426 templates.add(new TemplateGTUType(gtuType, lengthGenerator, widthGenerator, maximumSpeedGenerator));
427 }
428 else
429 {
430 Generator<Acceleration> maxAccelerationGenerator =
431 ParseDistribution.parseAccelerationDist(streamMap, template.getMAXACCELERATIONDIST());
432 Generator<Acceleration> maxDecelerationGenerator =
433 ParseDistribution.parseAccelerationDist(streamMap, template.getMAXDECELERATIONDIST());
434 templates.add(new TemplateGTUType(gtuType, lengthGenerator, widthGenerator, maximumSpeedGenerator,
435 maxAccelerationGenerator, maxDecelerationGenerator));
436 }
437 }
438
439 Factory factory = new Factory();
440 factory.setTemplates(templates);
441 odOptions.set(ODOptions.GTU_TYPE, factory.create());
442
443 if (od.getOPTIONS() != null)
444 {
445 Throw.when(!odOptionsMap.containsKey(od.getOPTIONS()), XmlParserException.class,
446 "OD options of id od.getOPTIONS() not defined.");
447 for (ODOPTIONSITEM options : odOptionsMap.get(od.getOPTIONS()).getODOPTIONSITEM())
448 {
449
450
451
452
453
454
455
456
457
458
459 if (options.getDEFAULTMODEL() != null || (options.getMODEL() != null && !options.getMODEL().isEmpty()))
460 {
461 LaneBasedStrategicalPlannerFactory<?> defaultFactory;
462 if (options.getDEFAULTMODEL() != null)
463 {
464
465 String modelId = DemandParser.getModelId(options.getDEFAULTMODEL(), modelIdReferrals);
466 Throw.when(!factories.containsKey(modelId), XmlParserException.class,
467 "OD option DEFAULTMODEL refers to a non-existent model with ID %s.", modelId);
468 defaultFactory = factories.get(modelId);
469 }
470 else
471 {
472 defaultFactory = null;
473 }
474
475 final Map<GTUType, LaneBasedStrategicalPlannerFactory<?>> gtuTypeFactoryMap = new LinkedHashMap<>();
476 if (options.getMODEL() != null)
477 {
478 for (MODEL model : options.getMODEL())
479 {
480 GTUType gtuType = otsNetwork.getGtuType(model.getGTUTYPE());
481 Throw.when(!factories.containsKey(model.getID()), XmlParserException.class,
482 "OD option MODEL refers to a non existent-model with ID %s.", model.getID());
483 gtuTypeFactoryMap.put(gtuType, factories.get(getModelId(model, modelIdReferrals)));
484 }
485 }
486 factory = new Factory();
487 factory.setTemplates(templates);
488 factory.setFactorySupplier(new StrategicalPlannerFactorySupplierOD()
489 {
490
491 @Override
492 public LaneBasedStrategicalPlannerFactory<?> getFactory(final Node origin,
493 final Node destination, final Category category, final StreamInterface randomStream)
494 throws GTUException
495 {
496 if (category.getCategorization().entails(GTUType.class))
497 {
498 LaneBasedStrategicalPlannerFactory<?> strategicalPlannerFactory =
499 gtuTypeFactoryMap.get(category.get(GTUType.class));
500 if (strategicalPlannerFactory != null)
501 {
502
503 return strategicalPlannerFactory;
504 }
505 }
506 if (defaultFactory != null)
507 {
508
509 return defaultFactory;
510 }
511
512
513
514 return new LaneBasedStrategicalRoutePlannerFactory(
515 new LMRSFactory(new IDMPlusFactory(randomStream),
516 new DefaultLMRSPerceptionFactory()),
517 RouteGeneratorOD.getDefaultRouteSupplier(randomStream));
518 }
519 });
520 setOption(odOptions, ODOptions.GTU_TYPE, factory.create(), options, otsNetwork);
521 }
522
523 setOption(odOptions, ODOptions.NO_LC_DIST, options.getNOLANECHANGE(), options, otsNetwork);
524
525 setOption(odOptions, ODOptions.ROOM_CHECKER, Transformer.parseRoomChecker(options.getROOMCHECKER()),
526 options, otsNetwork);
527
528 try
529 {
530 setOption(odOptions, ODOptions.HEADWAY_DIST,
531 Transformer.parseHeadwayDistribution(options.getHEADWAYDIST()), options, otsNetwork);
532 }
533 catch (NoSuchFieldException | IllegalAccessException exception)
534 {
535 throw new XmlParserException(exception);
536 }
537
538 if (options.getMARKOV() != null)
539 {
540 Throw.when(!categorization.entails(GTUType.class), XmlParserException.class,
541 "The OD option MARKOV can only be used if GTUType is in the CATEGORY's.");
542 Throw.when(!categorization.entails(Lane.class) && options.getLANE() != null,
543 XmlParserException.class,
544 "Markov chains at lane level are not used if Lane's are not in the CATEGORY's.");
545 MarkovCorrelation<GTUType, Frequency> markov = new MarkovCorrelation<>();
546 for (STATE state : options.getMARKOV().getSTATE())
547 {
548 GTUType gtuType = otsNetwork.getGtuType(state.getGTUTYPE());
549 double correlation = state.getCORRELATION();
550 if (state.getPARENT() == null)
551 {
552 markov.addState(gtuType, correlation);
553 }
554 else
555 {
556 GTUType parentType = otsNetwork.getGtuType(state.getPARENT());
557 markov.addState(parentType, gtuType, correlation);
558 }
559 }
560 setOption(odOptions, ODOptions.MARKOV, markov, options, otsNetwork);
561 }
562
563 if (options.getLANEBIASES() != null)
564 {
565 LaneBiases laneBiases = new LaneBiases();
566 for (LANEBIAS laneBias : options.getLANEBIASES().getLANEBIAS())
567 {
568 GTUType gtuType = otsNetwork.getGtuType(laneBias.getGTUTYPE());
569 double bias = laneBias.getBIAS();
570 int stickyLanes;
571 if (laneBias.getSTICKYLANES() == null)
572 {
573 stickyLanes = Integer.MAX_VALUE;
574 }
575 else
576 {
577 if (laneBias.getSTICKYLANES().compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0)
578 {
579 stickyLanes = Integer.MAX_VALUE;
580 }
581 else
582 {
583 stickyLanes = laneBias.getSTICKYLANES().intValue();
584 }
585 }
586 RoadPosition roadPosition;
587 if (laneBias.getFROMRIGHT() != null)
588 {
589 roadPosition = new RoadPosition.ByValue(laneBias.getFROMRIGHT());
590 }
591 else if (laneBias.getFROMLEFT() != null)
592 {
593 roadPosition = new RoadPosition.ByValue(1.0 - laneBias.getFROMLEFT());
594 }
595 else
596 {
597 roadPosition = new RoadPosition.BySpeed(laneBias.getLEFTSPEED(), laneBias.getRIGHTSPEED());
598 }
599 laneBiases.addBias(gtuType, new LaneBias(roadPosition, bias, stickyLanes));
600 }
601 setOption(odOptions, ODOptions.getLaneBiasOption(otsNetwork), laneBiases, options, otsNetwork);
602 }
603 }
604 }
605
606
607 Map<String, GeneratorObjects> output =
608 Try.assign(() -> ODApplier.applyOD(otsNetwork, odMatrix, simulator, odOptions),
609 XmlParserException.class, "Simulator time should be zero when parsing an OD.");
610
611
612 for (GeneratorObjects generatorObject : output.values())
613 {
614 generators.add(generatorObject.getGenerator());
615 }
616 }
617 }
618
619 return generators;
620 }
621
622
623
624
625
626
627
628 private static Frequency parseLevel(final String string, double factor)
629 {
630 return Frequency.valueOf(string.replace("veh", "")).multiplyBy(factor);
631 }
632
633
634
635
636
637 private static void sortLevelTime(final List<LEVELTIMETYPE> levelTime)
638 {
639 Collections.sort(levelTime, new Comparator<LEVELTIMETYPE>()
640 {
641
642 @Override
643 public int compare(final LEVELTIMETYPE o1, final LEVELTIMETYPE o2)
644 {
645 if (o1.getTIME() == null && o2.getTIME() == null)
646 {
647 return 0;
648 }
649 if (o1.getTIME() == null)
650 {
651 return -1;
652 }
653 if (o2.getTIME() == null)
654 {
655 return 1;
656 }
657 return o1.getTIME().compareTo(o2.getTIME());
658 }
659 });
660 }
661
662
663
664
665
666
667
668 private final static TimeVector parseTimeVector(final List<LEVELTIMETYPE> list) throws XmlParserException
669 {
670 List<Time> timeList = new ArrayList<>();
671 for (LEVELTIMETYPE time : list)
672 {
673 timeList.add(time.getTIME());
674 }
675 Collections.sort(timeList);
676 return Try.assign(() -> new TimeVector(timeList, StorageType.DENSE), XmlParserException.class,
677 "Global time has no values.");
678 }
679
680
681
682
683
684
685
686 private final static double parsePositiveFactor(final String factor) throws XmlParserException
687 {
688 double factorValue;
689 if (factor.endsWith("%"))
690 {
691 factorValue = Double.parseDouble(factor.substring(0, factor.length() - 1)) / 100.0;
692 }
693 factorValue = Double.parseDouble(factor);
694 Throw.when(factorValue < 0.0, XmlParserException.class, "Factor %d is not positive.", factorValue);
695 return factorValue;
696 }
697
698
699
700
701
702
703
704
705
706
707 private static <T> void setOption(final ODOptions odOptions, final Option<T> option, final T value,
708 final ODOPTIONSITEM options, final OTSRoadNetwork otsNetwork)
709 {
710 if (value != null)
711 {
712 if (options.getLINKTYPE() != null)
713 {
714 odOptions.set(otsNetwork.getLinkType(options.getLINKTYPE().getVALUE()), option, value);
715 }
716 else if (options.getORIGIN() != null)
717 {
718 odOptions.set(otsNetwork.getNode(options.getORIGIN().getVALUE()), option, value);
719 }
720 else if (options.getLANE() != null)
721 {
722 CrossSectionLink link = (CrossSectionLink) otsNetwork.getLink(options.getLANE().getLINK());
723 odOptions.set((Lane) link.getCrossSectionElement(options.getLANE().getID()), option, value);
724 }
725 else
726 {
727 odOptions.set(option, value);
728 }
729 }
730 }
731
732
733
734
735
736
737
738 private static String getModelId(final DEFAULTMODEL model, final Map<String, String> modelIdReferrals)
739 {
740 if (model.getMODELIDREFERRAL() != null)
741 {
742 return modelIdReferrals.get(model.getMODELIDREFERRAL());
743 }
744 return model.getID();
745 }
746
747
748
749
750
751
752
753 private static String getModelId(final MODEL model, final Map<String, String> modelIdReferrals)
754 {
755 if (model.getMODELIDREFERRAL() != null)
756 {
757 return modelIdReferrals.get(model.getMODELIDREFERRAL());
758 }
759 return model.getID();
760 }
761
762 }