1 package org.opentrafficsim.road.network.factory.vissim;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.io.Serializable;
6 import java.net.URL;
7 import java.util.HashMap;
8 import java.util.Map;
9 import java.util.Map.Entry;
10
11 import javax.naming.NamingException;
12 import javax.xml.parsers.DocumentBuilder;
13 import javax.xml.parsers.DocumentBuilderFactory;
14 import javax.xml.parsers.ParserConfigurationException;
15
16 import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
17 import org.opentrafficsim.core.geometry.OTSGeometryException;
18 import org.opentrafficsim.core.geometry.OTSLine3D;
19 import org.opentrafficsim.core.gtu.GTUException;
20 import org.opentrafficsim.core.gtu.GTUType;
21 import org.opentrafficsim.core.network.NetworkException;
22 import org.opentrafficsim.core.network.OTSNetwork;
23 import org.opentrafficsim.road.network.lane.LaneType;
24 import org.w3c.dom.Document;
25 import org.w3c.dom.NodeList;
26 import org.xml.sax.SAXException;
27
28 import com.vividsolutions.jts.geom.LineString;
29
30 import nl.tudelft.simulation.dsol.SimRuntimeException;
31
32
33
34
35
36
37
38
39
40
41 public class VissimNetworkLaneParser implements Serializable
42 {
43
44 private static final long serialVersionUID = 20150723L;
45
46
47 private GlobalTag globalTag;
48
49
50 private Map<String, NodeTag> nodeTags = new HashMap<>();
51
52
53 private Map<String, LinkTag> linkTags = new HashMap<>();
54
55
56 private Map<String, LinkTag> connectorTags = new HashMap<>();
57
58
59 private Map<String, LinkTag> realLinkTags = new HashMap<>();
60
61
62 private Map<String, SignalHeadTag> signalHeadTags = new HashMap<>();
63
64
65 private Map<String, SensorTag> sensorTags = new HashMap<>();
66
67
68 private Map<String, GTUTag> gtuTags = new HashMap<>();
69
70
71 private Map<String, GTUMixTag> gtuMixTags = new HashMap<>();
72
73
74 private Map<String, RoadTypeTag> roadTypeTags = new HashMap<>();
75
76
77 private Map<String, GTUType> gtuTypes = new HashMap<>();
78
79
80 private Map<String, LaneTypeTag> laneTypeTags = new HashMap<>();
81
82
83 private Map<String, RoadLayoutTag> roadLayoutTags = new HashMap<>();
84
85
86 private Map<String, RouteMixTag> routeMixTags = new HashMap<>();
87
88
89 private Map<String, ShortestRouteMixTag> shortestRouteMixTags = new HashMap<>();
90
91
92 private Map<String, ShortestRouteTag> shortestRouteTags = new HashMap<>();
93
94
95 private Map<String, RouteTag> routeTags = new HashMap<>();
96
97
98 private Map<String, LaneType> laneTypes = new HashMap<>();
99
100
101 private OTSDEVSSimulatorInterface simulator;
102
103
104 @SuppressWarnings("visibilitymodifier")
105 protected OTSNetwork network;
106
107
108
109
110
111
112 private int upperNodeNr = 1;
113
114
115 private int upperLinkNr = 1;
116
117
118
119
120 public VissimNetworkLaneParser(final OTSDEVSSimulatorInterface simulator)
121 {
122 this.simulator = simulator;
123 }
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142 @SuppressWarnings("checkstyle:needbraces")
143 public OTSNetwork build(final URL inputUrl, final File outputFile, final OTSNetwork network, final String sinkKillClassName,
144 final String sensorClassName, final String trafficLightName) throws NetworkException, ParserConfigurationException,
145 SAXException, IOException, NamingException, GTUException, OTSGeometryException, SimRuntimeException
146 {
147 if (inputUrl.getFile().length() > 0 && !(new File(inputUrl.getFile()).exists()))
148 {
149 throw new SAXException("XmlNetworkLaneParser.build: File url.getFile() does not exist");
150 }
151
152
153 this.network = network;
154
155
156 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
157 factory.setNamespaceAware(true);
158 factory.setXIncludeAware(true);
159 DocumentBuilder builder = factory.newDocumentBuilder();
160 Document document = builder.parse(inputUrl.openStream());
161 NodeList networkXMLNodeList = document.getDocumentElement().getChildNodes();
162
163
164 if (!document.getDocumentElement().getNodeName().equals("network"))
165 {
166 throw new SAXException("XmlNetworkLaneParser.build: XML document does not start with an NETWORK tag, found "
167 + document.getDocumentElement().getNodeName() + " instead");
168 }
169
170
171 this.gtuTypes.put("ALL", GTUType.ALL);
172 this.gtuTypes.put("NONE", GTUType.NONE);
173
174
175
176 LinkTag.parseLinks(networkXMLNodeList, this);
177
178
179 SignalHeadTag.parseSignalHead(networkXMLNodeList, this);
180
181
182 SensorTag.parseSensor(networkXMLNodeList, this);
183
184
185 Links.calculateNodeCoordinates(this);
186
187
188 LinkTag.addSignalHeads(this);
189
190
191 LinkTag.addDetectors(this);
192
193
194 for (LinkTag linkTag : this.linkTags.values())
195 {
196 if (linkTag.connector)
197 {
198 this.connectorTags.put(linkTag.name, linkTag);
199 }
200 else
201 {
202 this.realLinkTags.put(linkTag.name, linkTag);
203 }
204 }
205
206
207 NodeTag.removeDuplicateNodes(this);
208
209
210
211
212 Double margin = 5.0;
213 splitLinksIntersectedByConnector(margin);
214
215
216
217
218
219
220 Links.calculateNodeCoordinates(this);
221
222
223 createLinkBetweenConnectorAndLink(this);
224
225
226
227 Double splitMetersAfterSignalHead = 1.5;
228 margin = 4.0;
229 splitLinkAtSignalAndDetector(this.linkTags, margin, splitMetersAfterSignalHead);
230
231
232 Links.calculateNodeCoordinates(this);
233
234
235 HashMap<String, LinkTag> removeConnectorTags = new HashMap<>();
236 removeDoubleConnectors(removeConnectorTags);
237
238
239 for (LinkTag linkTag : this.linkTags.values())
240 {
241 Links.buildLink(linkTag, this, this.simulator);
242 }
243
244
245 for (LinkTag realLinkTag : this.linkTags.values())
246 {
247 Links.applyRoadTypeToLink(realLinkTag, this, this.simulator);
248 }
249
250
251 for (LinkTag realLinkTag : this.linkTags.values())
252 {
253 Links.createSinkSensor(realLinkTag, this, this.simulator);
254 }
255
256
257 for (LinkTag connectorTag : this.linkTags.values())
258 {
259 Links.applyRoadTypeToConnector(connectorTag, this, this.simulator);
260 }
261
262 NodeTag.removeRedundantNodeTags(this);
263
264
265
266
267
268
269
270 XMLNetworkWriter.writeToXML(outputFile, linkTags, nodeTags, sinkKillClassName, sensorClassName, trafficLightName);
271
272 return makeNetwork();
273 }
274
275 private void removeDoubleConnectors(HashMap<String, LinkTag> removeConnectorTags)
276 {
277 for (LinkTag linkTag : this.connectorTags.values())
278 {
279 for (LinkTag linkTag2 : this.connectorTags.values())
280 {
281 if (linkTag.nodeStartTag.name.equals(linkTag2.nodeStartTag.name)
282 && linkTag.nodeEndTag.name.equals(linkTag2.nodeEndTag.name) && !linkTag.equals(linkTag2))
283 {
284 removeConnectorTags.put(linkTag.nodeStartTag.name + linkTag.nodeEndTag.name, linkTag);
285 }
286 }
287 }
288 for (Entry<String, LinkTag> entry : removeConnectorTags.entrySet())
289 {
290 connectorTags.remove(entry.getValue().name);
291 linkTags.remove(entry.getValue().name);
292 }
293 }
294
295
296
297
298
299 private void createLinkBetweenConnectorAndLink(final VissimNetworkLaneParser parser) throws OTSGeometryException
300 {
301
302 for (LinkTag connectorLinkTag : this.connectorTags.values())
303 {
304
305 OTSLine3D designLineOTS = LinkTag.createLineString(connectorLinkTag);
306 LineString designLine = designLineOTS.getLineString();
307 Double length = designLine.getLength();
308
309 if (length < 999995)
310 {
311 connectorLinkTag.nodeStartTag = parser.nodeTags.get(connectorLinkTag.connectorTag.fromNodeName);
312 connectorLinkTag.nodeEndTag = parser.nodeTags.get(connectorLinkTag.connectorTag.toNodeName);
313 connectorLinkTag.bezierTag = new BezierTag();
314 if (connectorLinkTag.nodeStartTag.name.equals(connectorLinkTag.nodeEndTag.name))
315 {
316 this.linkTags.remove(connectorLinkTag.name);
317
318 }
319 if (connectorLinkTag.polyLineTag != null)
320 {
321 connectorLinkTag.polyLineTag = null;
322 }
323 if (connectorLinkTag.straightTag != null)
324 {
325 connectorLinkTag.straightTag = null;
326 }
327 }
328
329
330 else
331 {
332
333 LinkTag pasteLinkFromTag = new LinkTag(connectorLinkTag);
334
335 String linkName = "" + parser.upperLinkNr;
336 parser.upperLinkNr++;
337 pasteLinkFromTag.name = linkName;
338 pasteLinkFromTag.nodeStartTag = parser.nodeTags.get(connectorLinkTag.connectorTag.fromNodeName);
339 pasteLinkFromTag.nodeEndTag = connectorLinkTag.nodeStartTag;
340 pasteLinkFromTag.bezierTag = new BezierTag();
341 if (pasteLinkFromTag.polyLineTag != null)
342 {
343 pasteLinkFromTag.polyLineTag = null;
344 }
345 if (pasteLinkFromTag.straightTag != null)
346 {
347 pasteLinkFromTag.straightTag = null;
348 }
349
350
351
352 LinkTag pasteLinkToTag = new LinkTag(connectorLinkTag);
353 linkName = "" + parser.upperLinkNr;
354 parser.upperLinkNr++;
355 pasteLinkToTag.name = linkName;
356 pasteLinkToTag.nodeStartTag = connectorLinkTag.nodeEndTag;
357 pasteLinkToTag.nodeEndTag = parser.nodeTags.get(connectorLinkTag.connectorTag.toNodeName);
358
359 pasteLinkToTag.bezierTag = new BezierTag();
360 if (pasteLinkToTag.polyLineTag != null)
361 {
362 pasteLinkToTag.polyLineTag = null;
363 }
364 if (pasteLinkToTag.straightTag != null)
365 {
366 pasteLinkToTag.straightTag = null;
367 }
368
369
370 }
371
372 }
373 }
374
375 private void splitLinkAtSignalAndDetector(Map<String, LinkTag> inputLinkTags, Double margin,
376 Double splitMetersAfterSignalHead) throws OTSGeometryException, NetworkException
377 {
378
379 Map<String, LinkTag> newLinkTags = new HashMap<>();
380
381 splitLinksAtSignal(margin, splitMetersAfterSignalHead, inputLinkTags, newLinkTags);
382
383 }
384
385 private void splitLinksAtSignal(Double margin, Double splitMetersAfterSignalHead, Map<String, LinkTag> inputLinkTags,
386 Map<String, LinkTag> newLinkTags) throws OTSGeometryException, NetworkException
387 {
388 for (LinkTag linkTag : inputLinkTags.values())
389 {
390 for (SignalHeadTag signalHeadTag : linkTag.signalHeads)
391 {
392 Double position = Double.parseDouble(signalHeadTag.positionStr);
393 Double splitPosition = position + splitMetersAfterSignalHead;
394
395 NodeTag newNodeTag = NodeTag.createNewNodeAtLinkPosition(linkTag, this, splitPosition);
396
397 Map<String, LinkTag> newLinks = LinkTag.splitLink(newNodeTag, linkTag, this, splitPosition, margin, false);
398 if (newLinks != null)
399 {
400 newLinkTags.putAll(newLinks);
401 }
402 }
403 linkTag.signalHeads.removeAll(linkTag.signalHeadsToRemove);
404 linkTag.sensors.removeAll(linkTag.sensorTagsToRemove);
405
406 }
407 if (!newLinkTags.isEmpty())
408 {
409 this.linkTags.putAll(newLinkTags);
410 }
411
412
413 Map<String, LinkTag> new2LinkTags = new HashMap<>();
414 if (newLinkTags.size() > 0)
415 {
416 splitLinksAtSignal(margin, splitMetersAfterSignalHead, newLinkTags, new2LinkTags);
417 }
418 }
419
420 private void splitLinksIntersectedByConnector(Double margin) throws OTSGeometryException, NetworkException
421 {
422
423 for (LinkTag connectorLinkTag : this.connectorTags.values())
424 {
425
426
427
428 Double position = Double.parseDouble(connectorLinkTag.connectorTag.toPositionStr);
429
430
431 LinkTag linkToTag = this.realLinkTags.get(connectorLinkTag.connectorTag.toLinkNo);
432 boolean isConnectorToLink = true;
433
434
435 NodeTag newSplitNodeTag = NodeTag.createNewNodeAtLinkPosition(linkToTag, this, position);
436
437
438 Map<String, LinkTag> newLinkToTags =
439 LinkTag.splitLink(newSplitNodeTag, linkToTag, this, position, margin, isConnectorToLink);
440 linkToTag.signalHeads.removeAll(linkToTag.signalHeadsToRemove);
441 linkToTag.sensors.removeAll(linkToTag.sensorTagsToRemove);
442
443 if (newLinkToTags != null)
444 {
445
446 connectorLinkTag.connectorTag.toNodeName = newSplitNodeTag.name;
447 this.nodeTags.put(newSplitNodeTag.name, newSplitNodeTag);
448
449 for (LinkTag connectorLinkTag2 : this.connectorTags.values())
450 {
451
452 if (connectorLinkTag2 != connectorLinkTag
453 && connectorLinkTag2.connectorTag.toLinkNo.equals(connectorLinkTag.connectorTag.toLinkNo))
454 {
455
456 Double position2 = Double.parseDouble(connectorLinkTag2.connectorTag.toPositionStr);
457 if (position2 > position)
458 {
459 connectorLinkTag2.connectorTag.toLinkNo = newLinkToTags.values().iterator().next().name;
460 Double newPosition = position2 - position;
461 connectorLinkTag2.connectorTag.toPositionStr = newPosition.toString();
462 }
463 }
464 if (connectorLinkTag2 != connectorLinkTag
465 && connectorLinkTag2.connectorTag.fromLinkNo.equals(connectorLinkTag.connectorTag.toLinkNo))
466 {
467
468 Double position2 = Double.parseDouble(connectorLinkTag2.connectorTag.fromPositionStr);
469 if (position2 > position)
470 {
471 connectorLinkTag2.connectorTag.fromLinkNo = newLinkToTags.values().iterator().next().name;
472 Double newPosition = position2 - position;
473 connectorLinkTag2.connectorTag.fromPositionStr = newPosition.toString();
474 }
475 }
476 }
477
478 this.linkTags.putAll(newLinkToTags);
479 this.realLinkTags.putAll(newLinkToTags);
480 }
481 else
482 {
483
484
485 if (position < margin)
486 {
487 this.nodeTags.remove(connectorLinkTag.connectorTag.toNodeName);
488 connectorLinkTag.connectorTag.toNodeName = linkToTag.nodeStartTag.name;
489 }
490
491 else
492 {
493 this.nodeTags.remove(connectorLinkTag.connectorTag.toNodeName);
494 connectorLinkTag.connectorTag.toNodeName = linkToTag.nodeEndTag.name;
495 }
496 }
497
498
499
500 position = Double.parseDouble(connectorLinkTag.connectorTag.fromPositionStr);
501 LinkTag linkFromTag = this.realLinkTags.get(connectorLinkTag.connectorTag.fromLinkNo);
502 isConnectorToLink = false;
503 NodeTag newSplitNodeTag2 = NodeTag.createNewNodeAtLinkPosition(linkFromTag, this, position);
504
505 Map<String, LinkTag> newLinkFromTags =
506 LinkTag.splitLink(newSplitNodeTag2, linkFromTag, this, position, margin, isConnectorToLink);
507 linkFromTag.signalHeads.removeAll(linkFromTag.signalHeadsToRemove);
508 linkFromTag.sensors.removeAll(linkFromTag.sensorTagsToRemove);
509
510 if (newLinkFromTags != null)
511 {
512
513 connectorLinkTag.connectorTag.fromNodeName = newSplitNodeTag2.name;
514 this.nodeTags.put(newSplitNodeTag2.name, newSplitNodeTag2);
515
516 for (LinkTag connectorLinkTag2 : this.connectorTags.values())
517 {
518 if (connectorLinkTag2 != connectorLinkTag
519 && connectorLinkTag2.connectorTag.fromLinkNo.equals(connectorLinkTag.connectorTag.fromLinkNo))
520 {
521
522 Double position2 = Double.parseDouble(connectorLinkTag2.connectorTag.fromPositionStr);
523 if (position2 > position)
524 {
525 connectorLinkTag2.connectorTag.fromLinkNo = newLinkFromTags.values().iterator().next().name;
526 Double newPosition = position2 - position;
527 connectorLinkTag2.connectorTag.fromPositionStr = newPosition.toString();
528 }
529 }
530 if (connectorLinkTag2 != connectorLinkTag
531 && connectorLinkTag2.connectorTag.toLinkNo.equals(connectorLinkTag.connectorTag.fromLinkNo))
532 {
533
534 Double position2 = Double.parseDouble(connectorLinkTag2.connectorTag.toPositionStr);
535 if (position2 > position)
536 {
537 connectorLinkTag2.connectorTag.toLinkNo = newLinkFromTags.values().iterator().next().name;
538 Double newPosition = position2 - position;
539 connectorLinkTag2.connectorTag.toPositionStr = newPosition.toString();
540 }
541 }
542 }
543
544 this.linkTags.putAll(newLinkFromTags);
545 this.realLinkTags.putAll(newLinkFromTags);
546 }
547 else
548 {
549
550 if (position < margin)
551 {
552 this.nodeTags.remove(connectorLinkTag.connectorTag.fromNodeName);
553 connectorLinkTag.connectorTag.fromNodeName = linkFromTag.nodeStartTag.name;
554 }
555
556 else
557 {
558 this.nodeTags.remove(connectorLinkTag.connectorTag.fromNodeName);
559 connectorLinkTag.connectorTag.fromNodeName = linkFromTag.nodeEndTag.name;
560 }
561 }
562 }
563 }
564
565
566
567
568
569 private OTSNetwork makeNetwork() throws NetworkException
570 {
571
572
573
574
575
576 return this.network;
577 }
578
579
580 @Override
581 public final String toString()
582 {
583 return "VissimANMNetworkLaneParser [gtuTypes=" + this.gtuTypes + ", laneTypes=" + this.laneTypes + "]";
584 }
585
586 public GlobalTag getGlobalTag()
587 {
588 return globalTag;
589 }
590
591 public void setGlobalTag(GlobalTag globalTag)
592 {
593 this.globalTag = globalTag;
594 }
595
596 public Map<String, NodeTag> getNodeTags()
597 {
598 return nodeTags;
599 }
600
601 public void setNodeTags(Map<String, NodeTag> nodeTags)
602 {
603 this.nodeTags = nodeTags;
604 }
605
606 public Map<String, LinkTag> getLinkTags()
607 {
608 return linkTags;
609 }
610
611 public void setLinkTags(Map<String, LinkTag> linkTags)
612 {
613 this.linkTags = linkTags;
614 }
615
616 public Map<String, LinkTag> getConnectorTags()
617 {
618 return connectorTags;
619 }
620
621 public void setConnectorTags(Map<String, LinkTag> connectorTags)
622 {
623 this.connectorTags = connectorTags;
624 }
625
626 public Map<String, LinkTag> getRealLinkTags()
627 {
628 return realLinkTags;
629 }
630
631 public void setRealLinkTags(Map<String, LinkTag> realLinkTags)
632 {
633 this.realLinkTags = realLinkTags;
634 }
635
636 public Map<String, SignalHeadTag> getSignalHeadTags()
637 {
638 return signalHeadTags;
639 }
640
641 public void setSignalHeadTags(Map<String, SignalHeadTag> signalHeadTags)
642 {
643 this.signalHeadTags = signalHeadTags;
644 }
645
646 public Map<String, SensorTag> getSensorTags()
647 {
648 return sensorTags;
649 }
650
651 public void setSensorTags(Map<String, SensorTag> sensorTags)
652 {
653 this.sensorTags = sensorTags;
654 }
655
656 public Map<String, GTUTag> getGtuTags()
657 {
658 return gtuTags;
659 }
660
661 public void setGtuTags(Map<String, GTUTag> gtuTags)
662 {
663 this.gtuTags = gtuTags;
664 }
665
666 public Map<String, GTUMixTag> getGtuMixTags()
667 {
668 return gtuMixTags;
669 }
670
671 public void setGtuMixTags(Map<String, GTUMixTag> gtuMixTags)
672 {
673 this.gtuMixTags = gtuMixTags;
674 }
675
676 public Map<String, RoadTypeTag> getRoadTypeTags()
677 {
678 return roadTypeTags;
679 }
680
681 public void setRoadTypeTags(Map<String, RoadTypeTag> roadTypeTags)
682 {
683 this.roadTypeTags = roadTypeTags;
684 }
685
686 public Map<String, GTUType> getGtuTypes()
687 {
688 return gtuTypes;
689 }
690
691 public void setGtuTypes(Map<String, GTUType> gtuTypes)
692 {
693 this.gtuTypes = gtuTypes;
694 }
695
696 public Map<String, LaneTypeTag> getLaneTypeTags()
697 {
698 return laneTypeTags;
699 }
700
701 public void setLaneTypeTags(Map<String, LaneTypeTag> laneTypeTags)
702 {
703 this.laneTypeTags = laneTypeTags;
704 }
705
706 public Map<String, RoadLayoutTag> getRoadLayoutTags()
707 {
708 return roadLayoutTags;
709 }
710
711 public void setRoadLayoutTags(Map<String, RoadLayoutTag> roadLayoutTags)
712 {
713 this.roadLayoutTags = roadLayoutTags;
714 }
715
716 public Map<String, RouteMixTag> getRouteMixTags()
717 {
718 return routeMixTags;
719 }
720
721 public void setRouteMixTags(Map<String, RouteMixTag> routeMixTags)
722 {
723 this.routeMixTags = routeMixTags;
724 }
725
726 public Map<String, ShortestRouteMixTag> getShortestRouteMixTags()
727 {
728 return shortestRouteMixTags;
729 }
730
731 public void setShortestRouteMixTags(Map<String, ShortestRouteMixTag> shortestRouteMixTags)
732 {
733 this.shortestRouteMixTags = shortestRouteMixTags;
734 }
735
736 public Map<String, ShortestRouteTag> getShortestRouteTags()
737 {
738 return shortestRouteTags;
739 }
740
741 public void setShortestRouteTags(Map<String, ShortestRouteTag> shortestRouteTags)
742 {
743 this.shortestRouteTags = shortestRouteTags;
744 }
745
746 public Map<String, RouteTag> getRouteTags()
747 {
748 return routeTags;
749 }
750
751 public void setRouteTags(Map<String, RouteTag> routeTags)
752 {
753 this.routeTags = routeTags;
754 }
755
756 public Map<String, LaneType> getLaneTypes()
757 {
758 return laneTypes;
759 }
760
761 public void setLaneTypes(Map<String, LaneType> laneTypes)
762 {
763 this.laneTypes = laneTypes;
764 }
765
766 public OTSDEVSSimulatorInterface getSimulator()
767 {
768 return simulator;
769 }
770
771 public void setSimulator(OTSDEVSSimulatorInterface simulator)
772 {
773 this.simulator = simulator;
774 }
775
776 public OTSNetwork getNetwork()
777 {
778 return network;
779 }
780
781 public void setNetwork(OTSNetwork network)
782 {
783 this.network = network;
784 }
785
786 public int getUpperNodeNr()
787 {
788 return upperNodeNr;
789 }
790
791 public void setUpperNodeNr(int upperNodeNr)
792 {
793 this.upperNodeNr = upperNodeNr;
794 }
795
796 public int getUpperLinkNr()
797 {
798 return upperLinkNr;
799 }
800
801 public void setUpperLinkNr(int upperLinkNr)
802 {
803 this.upperLinkNr = upperLinkNr;
804 }
805 }