1 package org.opentrafficsim.road.network.factory.xml.old;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.io.Serializable;
6 import java.net.URL;
7 import java.rmi.RemoteException;
8 import java.util.ArrayList;
9 import java.util.HashMap;
10 import java.util.HashSet;
11 import java.util.LinkedHashSet;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.Set;
15
16 import javax.naming.NamingException;
17 import javax.xml.parsers.DocumentBuilder;
18 import javax.xml.parsers.DocumentBuilderFactory;
19 import javax.xml.parsers.ParserConfigurationException;
20
21 import org.djunits.unit.FrequencyUnit;
22 import org.djunits.unit.TimeUnit;
23 import org.djunits.value.StorageType;
24 import org.djunits.value.ValueException;
25 import org.djunits.value.vdouble.vector.FrequencyVector;
26 import org.djunits.value.vdouble.vector.TimeVector;
27 import org.djutils.immutablecollections.Immutable;
28 import org.djutils.immutablecollections.ImmutableArrayList;
29 import org.djutils.immutablecollections.ImmutableList;
30 import org.opentrafficsim.base.parameters.ParameterException;
31 import org.opentrafficsim.core.animation.gtu.colorer.GTUColorer;
32 import org.opentrafficsim.core.animation.network.NetworkAnimation;
33 import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
34 import org.opentrafficsim.core.geometry.OTSGeometryException;
35 import org.opentrafficsim.core.geometry.OTSLine3D;
36 import org.opentrafficsim.core.geometry.OTSPoint3D;
37 import org.opentrafficsim.core.gtu.GTUException;
38 import org.opentrafficsim.core.gtu.GTUType;
39 import org.opentrafficsim.core.gtu.TemplateGTUType;
40 import org.opentrafficsim.core.network.Link;
41 import org.opentrafficsim.core.network.LinkType;
42 import org.opentrafficsim.core.network.NetworkException;
43 import org.opentrafficsim.core.network.OTSNode;
44 import org.opentrafficsim.road.gtu.generator.od.DefaultGTUCharacteristicsGeneratorOD;
45 import org.opentrafficsim.road.gtu.generator.od.GTUCharacteristicsGeneratorOD;
46 import org.opentrafficsim.road.gtu.generator.od.ODOptions;
47 import org.opentrafficsim.road.gtu.strategical.od.Categorization;
48 import org.opentrafficsim.road.gtu.strategical.od.Category;
49 import org.opentrafficsim.road.gtu.strategical.od.Interpolation;
50 import org.opentrafficsim.road.gtu.strategical.od.ODMatrix;
51 import org.opentrafficsim.road.network.OTSRoadNetwork;
52 import org.opentrafficsim.road.network.factory.xml.XmlParserException;
53 import org.opentrafficsim.road.network.factory.xml.demand.XmlOdParser;
54 import org.opentrafficsim.road.network.lane.CrossSectionLink;
55 import org.opentrafficsim.road.network.lane.LaneType;
56 import org.opentrafficsim.road.network.lane.changing.LaneKeepingPolicy;
57 import org.w3c.dom.Comment;
58 import org.w3c.dom.Document;
59 import org.w3c.dom.Node;
60 import org.w3c.dom.NodeList;
61 import org.xml.sax.SAXException;
62
63 import nl.tudelft.simulation.dsol.SimRuntimeException;
64
65
66
67
68
69
70
71
72
73
74 public class XmlNetworkLaneParserOld implements Serializable
75 {
76
77 private static final long serialVersionUID = 20150723L;
78
79
80 @SuppressWarnings("visibilitymodifier")
81 protected GlobalTag globalTag;
82
83
84 @SuppressWarnings("visibilitymodifier")
85 protected Map<String, NodeTag> nodeTags = new HashMap<>();
86
87
88 @SuppressWarnings("visibilitymodifier")
89 protected Map<String, ConnectorTag> connectorTags = new HashMap<>();
90
91
92 @SuppressWarnings("visibilitymodifier")
93 protected Map<String, LinkTag> linkTags = new HashMap<>();
94
95
96 @SuppressWarnings("visibilitymodifier")
97 public Map<String, GTUTag> gtuTags = new HashMap<>();
98
99
100 @SuppressWarnings("visibilitymodifier")
101 protected Map<String, GTUMixTag> gtuMixTags = new HashMap<>();
102
103
104 @SuppressWarnings("visibilitymodifier")
105 protected Map<String, RouteTag> routeTags = new HashMap<>();
106
107
108 @SuppressWarnings("visibilitymodifier")
109 protected Map<String, RouteMixTag> routeMixTags = new HashMap<>();
110
111
112 @SuppressWarnings("visibilitymodifier")
113 protected Map<String, ShortestRouteTag> shortestRouteTags = new HashMap<>();
114
115
116 @SuppressWarnings("visibilitymodifier")
117 protected Map<String, ShortestRouteMixTag> shortestRouteMixTags = new HashMap<>();
118
119
120 @SuppressWarnings("visibilitymodifier")
121 protected Map<String, RoadTypeTag> roadTypeTags = new HashMap<>();
122
123
124 @SuppressWarnings("visibilitymodifier")
125 protected Map<String, RoadLayoutTag> roadLayoutTags = new HashMap<>();
126
127
128 @SuppressWarnings("visibilitymodifier")
129 public Map<String, GTUType> gtuTypes = new HashMap<>();
130
131
132 @SuppressWarnings("visibilitymodifier")
133 protected Map<String, LaneTypeTag> laneTypeTags = new HashMap<>();
134
135
136 @SuppressWarnings("visibilitymodifier")
137 protected Map<String, LaneType> laneTypes = new HashMap<>();
138
139
140 @SuppressWarnings("visibilitymodifier")
141 protected OTSSimulatorInterface simulator;
142
143
144 @SuppressWarnings("visibilitymodifier")
145 protected OTSRoadNetwork network;
146
147
148 @SuppressWarnings("visibilitymodifier")
149 protected NetworkAnimation networkAnimation;
150
151
152 List<String> xmlComments = new ArrayList<>();
153
154
155
156
157 public XmlNetworkLaneParserOld(final OTSSimulatorInterface simulator)
158 {
159 this.simulator = simulator;
160 LaneTypeTag laneTypeTagNoTraffic = new LaneTypeTag();
161 laneTypeTagNoTraffic.name = "NOTRAFFIC";
162 this.laneTypeTags.put(laneTypeTagNoTraffic.name, laneTypeTagNoTraffic);
163 }
164
165
166
167
168
169 public XmlNetworkLaneParserOld(final OTSSimulatorInterface simulator, final GTUColorer colorer)
170 {
171 this.simulator = simulator;
172 GTUColorerTag.defaultColorer = colorer;
173 LaneTypeTag laneTypeTagNoTraffic = new LaneTypeTag();
174 laneTypeTagNoTraffic.name = "NOTRAFFIC";
175 this.laneTypeTags.put(laneTypeTagNoTraffic.name, laneTypeTagNoTraffic);
176 }
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194 @SuppressWarnings("checkstyle:needbraces")
195 public final OTSRoadNetwork build(final URL url, boolean interpretXMLComments)
196 throws NetworkException, ParserConfigurationException, SAXException, IOException, NamingException, GTUException,
197 OTSGeometryException, SimRuntimeException, ValueException, ParameterException
198 {
199 return build(url, new OTSRoadNetwork(url.toString(), true), interpretXMLComments);
200 }
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218 @SuppressWarnings("checkstyle:needbraces")
219 public final OTSRoadNetwork build(final InputStream stream, boolean interpretXMLComments)
220 throws NetworkException, ParserConfigurationException, SAXException, IOException, NamingException, GTUException,
221 OTSGeometryException, SimRuntimeException, ValueException, ParameterException
222 {
223 return build(stream, new OTSRoadNetwork(stream.toString(), true), interpretXMLComments);
224 }
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243 @SuppressWarnings("checkstyle:needbraces")
244 public final OTSRoadNetwork build(final URL url, final OTSRoadNetwork otsNetwork, boolean interpretXMLComments)
245 throws NetworkException, ParserConfigurationException, SAXException, IOException, NamingException, GTUException,
246 OTSGeometryException, SimRuntimeException, ValueException, ParameterException
247 {
248 return build(url.openStream(), otsNetwork, interpretXMLComments);
249 }
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268 @SuppressWarnings("checkstyle:needbraces")
269 public final OTSRoadNetwork build(final InputStream stream, final OTSRoadNetwork otsNetwork, boolean interpretXMLComments)
270 throws NetworkException, ParserConfigurationException, SAXException, IOException, NamingException, GTUException,
271 OTSGeometryException, SimRuntimeException, ValueException, ParameterException
272 {
273
274
275
276
277
278
279
280
281
282
283 this.network = otsNetwork;
284 this.networkAnimation = new NetworkAnimation(this.network);
285 this.xmlComments.clear();
286
287 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
288 factory.setNamespaceAware(true);
289 factory.setXIncludeAware(true);
290 DocumentBuilder builder = factory.newDocumentBuilder();
291 Document document = builder.parse(stream);
292 NodeList networkNodeList = document.getDocumentElement().getChildNodes();
293
294 for (int i = 0; i < networkNodeList.getLength(); i++)
295 {
296 Node node = networkNodeList.item(i);
297 if (node instanceof Comment)
298 {
299 this.xmlComments.add(node.getTextContent());
300 }
301 }
302
303 if (!document.getDocumentElement().getNodeName().equals("NETWORK"))
304 throw new SAXException("XmlNetworkLaneParser.build: XML document does not start with an NETWORK tag, found "
305 + document.getDocumentElement().getNodeName() + " instead");
306
307
308 List<Node> definitionNodes = XMLParser.getNodes(networkNodeList, "DEFINITIONS");
309
310 if (definitionNodes.size() == 0)
311 throw new SAXException("XmlNetworkLaneParser.build: XML document does not have a DEFINITIONS tag");
312
313
314 this.gtuTypes.put("ALL", otsNetwork.getGtuType(GTUType.DEFAULTS.VEHICLE));
315
316
317
318 for (Node definitionNode : definitionNodes)
319 GlobalTag.parseGlobal(definitionNode.getChildNodes(), this);
320 for (Node definitionNode : definitionNodes)
321 GTUTypeTag.parseGTUTypes(definitionNode.getChildNodes(), this);
322 for (Node definitionNode : definitionNodes)
323 GTUTag.parseGTUs(definitionNode.getChildNodes(), this);
324 for (Node definitionNode : definitionNodes)
325 GTUMixTag.parseGTUMix(definitionNode.getChildNodes(), this);
326 for (Node definitionNode : definitionNodes)
327 RoadTypeTag.parseRoadTypes(definitionNode.getChildNodes(), this);
328 for (Node definitionNode : definitionNodes)
329 LaneTypeTag.parseLaneTypes(definitionNode.getChildNodes(), this);
330 for (Node definitionNode : definitionNodes)
331 RoadLayoutTag.parseRoadTypes(definitionNode.getChildNodes(), this);
332
333
334 NodeTag.parseNodes(networkNodeList, this);
335 RouteTag.parseRoutes(networkNodeList, this);
336 ShortestRouteTag.parseShortestRoutes(networkNodeList, this);
337 RouteMixTag.parseRouteMix(networkNodeList, this);
338 ShortestRouteMixTag.parseShortestRouteMix(networkNodeList, this);
339 ConnectorTag.parseConnectors(networkNodeList, this);
340 LinkTag.parseLinks(networkNodeList, this);
341
342
343 for (LinkTag linkTag : this.linkTags.values())
344 Links.calculateNodeAngles(linkTag);
345 for (ConnectorTag connectorTag : this.connectorTags.values())
346 Links.buildConnector(connectorTag, this, this.simulator);
347 for (LinkTag linkTag : this.linkTags.values())
348 Links.buildLink(linkTag, this, this.simulator);
349 for (LinkTag linkTag : this.linkTags.values())
350 Links.applyRoadTypeToLink(linkTag, this, this.simulator);
351
352
353 for (RouteTag routeTag : this.routeTags.values())
354 routeTag.makeRoute();
355
356
357
358 makeNetwork();
359 if (interpretXMLComments)
360 {
361
362 }
363
364 List<Node> od = XMLParser.getNodes(networkNodeList, "OD");
365 if (od.size() == 1)
366 {
367 Set<TemplateGTUType> templates = new LinkedHashSet<>();
368 for (String gtuType : this.gtuTags.keySet())
369 {
370 GTUTag gtuTag = this.gtuTags.get(gtuType);
371 templates.add(new TemplateGTUType(this.gtuTypes.get(gtuType), gtuTag.lengthDist, gtuTag.widthDist,
372 gtuTag.maxSpeedDist));
373 }
374 GTUCharacteristicsGeneratorOD gtuTypeGenerator = new DefaultGTUCharacteristicsGeneratorOD(templates);
375 ODOptions odOptions = new ODOptions().set(ODOptions.GTU_TYPE, gtuTypeGenerator);
376
377 XmlOdParser xmlOdParser =
378 new XmlOdParser(this.simulator, this.network, new LinkedHashSet<>(this.gtuTypes.values()));
379 try
380 {
381 xmlOdParser.apply(od.get(0), odOptions);
382 }
383 catch (XmlParserException exception)
384 {
385 throw new SAXException("Exception while applying OD.", exception);
386 }
387 }
388 else if (od.size() > 1)
389 {
390 throw new SAXException("XmlNetworkLaneParser.build: XML document contains multiple OD tags");
391 }
392 return this.network;
393 }
394
395
396
397
398
399
400
401
402
403
404
405
406 private void fixOD(final OTSRoadNetwork otsNetwork) throws NetworkException, OTSGeometryException, RemoteException,
407 NamingException, ValueException, ParameterException, SimRuntimeException
408 {
409
410 Map<String, Map<String, String>> odInfo = new HashMap<>();
411 for (String comment : getXMLComments())
412 {
413 if (comment.startsWith("OD "))
414 {
415 String odText = comment.substring(3);
416 odInfo.put(odText, parseODLine(odText));
417 }
418 }
419 System.out.println("There are " + odInfo.size() + " OD comments");
420
421 List<GTUType> odGTUTypes = new ArrayList<>(this.gtuTypes.values());
422 for (GTUType gtuType : odGTUTypes)
423 {
424 if (otsNetwork.getGtuType(GTUType.DEFAULTS.VEHICLE).equals(gtuType))
425 {
426 odGTUTypes.remove(gtuType);
427 break;
428 }
429 }
430 double startTime = Double.NaN;
431
432 for (Map<String, String> map : odInfo.values())
433 {
434 String startTimeString = map.get("simulationStartTime");
435 if (null != startTimeString)
436 {
437 startTime = Double.parseDouble(startTimeString);
438 }
439 }
440 if (Double.isNaN(startTime))
441 {
442 throw new NetworkException("Cannot find start time XML comment");
443 }
444
445 Set<org.opentrafficsim.core.network.Node> origins = new HashSet<>();
446 Set<org.opentrafficsim.core.network.Node> destinations = new HashSet<>();
447 Set<String> startTimeStrings = new HashSet<>();
448 Map<String, String> durations = new HashMap<>();
449 for (Map<String, String> map : odInfo.values())
450 {
451 String od = map.get("od");
452 if (null == od)
453 {
454 continue;
455 }
456 String startTimeString = map.get("startTime");
457 if (null != startTimeString)
458 {
459 startTimeStrings.add(startTimeString);
460 String durationString = map.get("duration");
461 if (null == durationString)
462 {
463 throw new NetworkException("No duration specified");
464 }
465 String old = durations.get(startTimeString);
466 if (null != old && (!durationString.equals(old)))
467 {
468 throw new NetworkException("Duration for period starting at " + startTimeString + " changed from " + old
469 + " to " + durationString);
470 }
471 else
472 {
473 durations.put(startTimeString, durationString);
474 }
475 }
476 String centroidName = map.get("centroid");
477 String[] coordinates = map.get("centroidLocation").split(",");
478 OTSPoint3D centroidPoint = new OTSPoint3D(Double.parseDouble(coordinates[0]), Double.parseDouble(coordinates[1]));
479 org.opentrafficsim.core.network.Node centroidNode = otsNetwork.getNode(centroidName);
480 if (null == centroidNode)
481 {
482 centroidNode = new OTSNode(otsNetwork, centroidName, centroidPoint);
483 }
484 String linkId = map.get("link");
485 Link link = otsNetwork.getLink(linkId);
486 if (null == link)
487 {
488 throw new NetworkException("Cannot find link with id \"" + linkId + "\"");
489 }
490 org.opentrafficsim.core.network.Node from = null;
491 org.opentrafficsim.core.network.Node to = null;
492 if ("attracts".equals(od))
493 {
494 destinations.add(centroidNode);
495 from = link.getEndNode();
496 to = centroidNode;
497
498 }
499 else if ("generates".equals(od))
500 {
501 origins.add(centroidNode);
502 from = centroidNode;
503 to = link.getStartNode();
504 }
505 OTSLine3D designLine = new OTSLine3D(from.getPoint(), to.getPoint());
506 String linkName = String.format("connector_from_%s_to_%s", from.getId(), to.getId());
507 Link connectorLink = otsNetwork.getLink(linkName);
508 if (null == connectorLink)
509 {
510 System.out.println("Constructing connector link " + linkName);
511 connectorLink = new CrossSectionLink(otsNetwork, linkName, from, to,
512 otsNetwork.getLinkType(LinkType.DEFAULTS.CONNECTOR), designLine, this.simulator,
513 LaneKeepingPolicy.KEEPRIGHT);
514 }
515 }
516 if (startTimeStrings.size() > 1)
517 {
518 throw new NetworkException("Cannot handle multiple start times - yet");
519 }
520 if (startTimeStrings.size() == 0)
521 {
522 throw new NetworkException("Missing start time XML comment");
523 }
524 String startTimeString = startTimeStrings.iterator().next();
525 double start = Double.parseDouble(startTimeString);
526 start = 0;
527 double duration = Double.parseDouble(durations.get(startTimeString));
528 TimeVector tv = new TimeVector(new double[] {start, start + duration}, TimeUnit.BASE, StorageType.DENSE);
529
530 Categorization categorization = new Categorization("AimsunOTSExport", GTUType.class);
531 ODMatrix od = new ODMatrix("ODExample", new ArrayList<>(origins), new ArrayList<>(destinations), categorization, tv,
532 Interpolation.STEPWISE);
533 for (Map<String, String> map : odInfo.values())
534 {
535 String flow = map.get("flow");
536 if (null == flow)
537 {
538 continue;
539 }
540 String vehicleClassName = map.get("vehicleClass");
541 GTUType gtuType = null;
542 for (GTUType gt : odGTUTypes)
543 {
544 if (gt.getId().equals(vehicleClassName))
545 {
546 gtuType = gt;
547 }
548 }
549 if (null == gtuType)
550 {
551 throw new NetworkException("Can not find GTUType with name " + vehicleClassName);
552 }
553 Category category = new Category(categorization, gtuType);
554 org.opentrafficsim.core.network.Node from = otsNetwork.getNode(map.get("origin"));
555 org.opentrafficsim.core.network.Node to = otsNetwork.getNode(map.get("destination"));
556 FrequencyVector demand = new FrequencyVector(new double[] {Double.parseDouble(map.get("flow")), 0},
557 FrequencyUnit.PER_HOUR, StorageType.DENSE);
558 od.putDemandVector(from, to, category, demand);
559 System.out.println(
560 "Adding demand from " + from.getId() + " to " + to.getId() + " category " + category + ": " + demand);
561 }
562 Set<TemplateGTUType> templates = new HashSet<>();
563 for (GTUType gtuType : odGTUTypes)
564 {
565 GTUTag gtuTag = this.gtuTags.get(gtuType.getId());
566 templates.add(new TemplateGTUType(gtuType, gtuTag.lengthDist, gtuTag.widthDist, gtuTag.maxSpeedDist));
567 }
568 od.print();
569 }
570
571
572
573
574
575
576 private Map<String, String> parseODLine(final String line)
577 {
578 Map<String, String> result = new HashMap<>();
579
580 for (String pair : line.split(" "))
581 {
582 String[] fields = pair.split("=");
583
584 for (int index = fields.length; --index >= 2;)
585 {
586 fields[index - 1] += "=" + fields[index];
587 }
588 if (fields.length < 2)
589 {
590 throw new IndexOutOfBoundsException("can not find equals sign in \"" + pair + "\"");
591 }
592 if (fields[1].startsWith("\"") && fields[1].endsWith("\"") && fields[1].length() >= 2)
593 {
594 fields[1] = fields[1].substring(1, fields[1].length() - 1);
595 }
596 result.put(fields[0], fields[1]);
597 }
598 return result;
599 }
600
601
602
603
604
605 private void makeNetwork() throws NetworkException
606 {
607 for (RouteTag routeTag : this.routeTags.values())
608 {
609
610
611 this.network.addRoute(this.network.getGtuType(GTUType.DEFAULTS.VEHICLE), routeTag.route);
612 }
613 }
614
615
616
617
618
619 public ImmutableList<String> getXMLComments()
620 {
621 return new ImmutableArrayList<>(this.xmlComments, Immutable.COPY);
622 }
623
624
625
626
627 public final NetworkAnimation getNetworkAnimation()
628 {
629 return this.networkAnimation;
630 }
631
632
633 @Override
634 public String toString()
635 {
636 return "XmlNetworkLaneParser [globalTag=" + this.globalTag + ", nodeTags.size=" + this.nodeTags.size()
637 + ", linkTags.size=" + this.linkTags.size() + ", gtuTags.size=" + this.gtuTags.size() + ", gtuMixTags.size="
638 + this.gtuMixTags.size() + ", routeTags.size=" + this.routeTags.size() + ", routeMixTags.size="
639 + this.routeMixTags.size() + ", shortestRouteTagssize.=" + this.shortestRouteTags.size()
640 + ", shortestRouteMixTags.size=" + this.shortestRouteMixTags.size() + ", roadTypeTags.size="
641 + this.roadTypeTags.size() + ", gtuTypes.size=" + this.gtuTypes.size() + ", laneTypes.size="
642 + this.laneTypeTags.size() + "]";
643 }
644
645 }