VissimNetworkLaneParser.java

  1. package org.opentrafficsim.road.network.factory.vissim;

  2. import java.io.File;
  3. import java.io.IOException;
  4. import java.io.Serializable;
  5. import java.net.URL;
  6. import java.util.HashMap;
  7. import java.util.LinkedHashMap;
  8. import java.util.Map;
  9. import java.util.Map.Entry;

  10. import javax.naming.NamingException;
  11. import javax.xml.parsers.DocumentBuilder;
  12. import javax.xml.parsers.DocumentBuilderFactory;
  13. import javax.xml.parsers.ParserConfigurationException;

  14. import org.locationtech.jts.geom.LineString;
  15. import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
  16. import org.opentrafficsim.core.geometry.OTSGeometryException;
  17. import org.opentrafficsim.core.geometry.OTSLine3D;
  18. import org.opentrafficsim.core.gtu.GTUException;
  19. import org.opentrafficsim.core.gtu.GTUType;
  20. import org.opentrafficsim.core.network.NetworkException;
  21. import org.opentrafficsim.road.network.OTSRoadNetwork;
  22. import org.opentrafficsim.road.network.lane.LaneType;
  23. import org.w3c.dom.Document;
  24. import org.w3c.dom.NodeList;
  25. import org.xml.sax.SAXException;

  26. import nl.tudelft.simulation.dsol.SimRuntimeException;
  27. import nl.tudelft.simulation.dsol.simulators.DEVSSimulatorInterface;

  28. /**
  29.  * <p>
  30.  * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
  31.  * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
  32.  * <p>
  33.  * $LastChangedDate: 2015-07-24 02:58:59 +0200 (Fri, 24 Jul 2015) $, @version $Revision: 1147 $, by $Author: averbraeck $,
  34.  * initial version Jul 23, 2015 <br>
  35.  * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
  36.  */
  37. public class VissimNetworkLaneParser implements Serializable
  38. {
  39.     /** */
  40.     private static final long serialVersionUID = 20150723L;

  41.     /** Global values from the GLOBAL tag. */
  42.     private GlobalTag globalTag;

  43.     /** The UNprocessed links for further reference. */
  44.     private Map<String, NodeTag> nodeTags = new LinkedHashMap<>();

  45.     /** The UNprocessed links for further reference. */
  46.     private Map<String, LinkTag> linkTags = new LinkedHashMap<>();

  47.     /** The UNprocessed links for further reference. */
  48.     private Map<String, LinkTag> connectorTags = new LinkedHashMap<>();

  49.     /** The UNprocessed links for further reference. */
  50.     private Map<String, LinkTag> realLinkTags = new LinkedHashMap<>();

  51.     /** The UNprocessed links for further reference. */
  52.     private Map<String, SignalHeadTag> signalHeadTags = new LinkedHashMap<>();

  53.     /** The UNprocessed links for further reference. */
  54.     private Map<String, SensorTag> sensorTags = new LinkedHashMap<>();

  55.     /** The gtu tags for further reference. */
  56.     private Map<String, GTUTag> gtuTags = new LinkedHashMap<>();

  57.     /** The gtumix tags for further reference. */
  58.     private Map<String, GTUMixTag> gtuMixTags = new LinkedHashMap<>();

  59.     /** The road type tags for further reference. */
  60.     private Map<String, RoadTypeTag> roadTypeTags = new LinkedHashMap<>();

  61.     /** The GTUTypes that have been created. public to make it accessible from LaneAttributes. */
  62.     private Map<String, GTUType> gtuTypes = new LinkedHashMap<>();

  63.     /** The LaneType tags that have been created. */
  64.     private Map<String, LaneTypeTag> laneTypeTags = new LinkedHashMap<>();

  65.     /** The LaneType tags that have been created. */
  66.     private Map<String, RoadLayoutTag> roadLayoutTags = new LinkedHashMap<>();

  67.     /** The RouteMix tags that have been created. */
  68.     private Map<String, RouteMixTag> routeMixTags = new LinkedHashMap<>();

  69.     /** The RouteMix tags that have been created. */
  70.     private Map<String, ShortestRouteMixTag> shortestRouteMixTags = new LinkedHashMap<>();

  71.     /** The RouteMix tags that have been created. */
  72.     private Map<String, ShortestRouteTag> shortestRouteTags = new LinkedHashMap<>();

  73.     /** The RouteMix tags that have been created. */
  74.     private Map<String, RouteTag> routeTags = new LinkedHashMap<>();

  75.     /** The LaneTypes that have been created. */
  76.     private Map<String, LaneType> laneTypes = new LinkedHashMap<>();

  77.     /** The simulator for creating the animation. Null if no animation needed. */
  78.     private OTSSimulatorInterface simulator;

  79.     /** The network to register the GTUs in. */
  80.     @SuppressWarnings("visibilitymodifier")
  81.     protected OTSRoadNetwork network;

  82.     /*****
  83.      * Variables, typically for Vissim network import
  84.      */

  85.     /** the node number is automatically generated and increases with every additional node. */
  86.     private int upperNodeNr = 1;

  87.     /** the node number is automatically generated and increases with every additional node. */
  88.     private int upperLinkNr = 1;

  89.     /**
  90.      * @param simulator OTSSimulatorInterface; the simulator for creating the animation. Null if no animation needed.
  91.      */
  92.     public VissimNetworkLaneParser(final OTSSimulatorInterface simulator)
  93.     {
  94.         this.simulator = simulator;
  95.     }

  96.     /**
  97.      * @param inputUrl URL; input
  98.      * @param outputFile File; output file
  99.      * @param network OTSRoadNetwork; network
  100.      * @param sinkKillClassName String; name of the sink-sensor class
  101.      * @param sensorClassName String; name of the sensor class
  102.      * @param trafficLightName String; name of the trafficLight class
  103.      * @return the network with Nodes, Links, and Lanes.
  104.      * @throws NetworkException in case of parsing problems.
  105.      * @throws SAXException in case of parsing problems.
  106.      * @throws ParserConfigurationException in case of parsing problems.
  107.      * @throws IOException in case of file reading problems.
  108.      * @throws NamingException in case the animation context cannot be found
  109.      * @throws GTUException in case of a problem with creating the LaneBlock (which is a GTU right now)
  110.      * @throws OTSGeometryException when construction of a lane contour or offset design line fails
  111.      * @throws SimRuntimeException when simulator cannot be used to schedule GTU generation
  112.      */
  113.     @SuppressWarnings("checkstyle:needbraces")
  114.     public OTSRoadNetwork build(final URL inputUrl, final File outputFile, final OTSRoadNetwork network,
  115.             final String sinkKillClassName, final String sensorClassName, final String trafficLightName)
  116.             throws NetworkException, ParserConfigurationException, SAXException, IOException, NamingException, GTUException,
  117.             OTSGeometryException, SimRuntimeException
  118.     {
  119.         if (inputUrl.getFile().length() > 0 && !(new File(inputUrl.getFile()).exists()))
  120.         {
  121.             throw new SAXException("XmlNetworkLaneParser.build: File url.getFile() does not exist");
  122.         }

  123.         // starts with the creation of an empty network
  124.         this.network = network;

  125.         // prepare for reading the XML document
  126.         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  127.         factory.setNamespaceAware(true);
  128.         factory.setXIncludeAware(true);
  129.         DocumentBuilder builder = factory.newDocumentBuilder();
  130.         Document document = builder.parse(inputUrl.openStream());
  131.         NodeList networkXMLNodeList = document.getDocumentElement().getChildNodes();

  132.         // Is it a Vissim network?
  133.         if (!document.getDocumentElement().getNodeName().equals("network"))
  134.         {
  135.             throw new SAXException("XmlNetworkLaneParser.build: XML document does not start with an NETWORK tag, found "
  136.                     + document.getDocumentElement().getNodeName() + " instead");
  137.         }

  138.         // make the GTUTypes ALL and NONE to get started
  139.         this.gtuTypes.put("ALL", network.getGtuType(GTUType.DEFAULTS.VEHICLE));
  140.         // this.gtuTypes.put("NONE", GTUType.NONE);

  141.         // Read the link (and connector) tags and ...
  142.         // Construct the nodes as Vissim does not use Nodes!!
  143.         LinkTag.parseLinks(networkXMLNodeList, this);

  144.         // the signal heads are stored separately. Read them first, connect to links later on
  145.         SignalHeadTag.parseSignalHead(networkXMLNodeList, this);

  146.         // the sensor are defined separate also. Read them first, connect to links later on
  147.         SensorTag.parseSensor(networkXMLNodeList, this);

  148.         // add the signalHeads to the links
  149.         LinkTag.addSignalHeads(this);

  150.         // add the detectors to the links
  151.         LinkTag.addDetectors(this);

  152.         // create a subset of connector links
  153.         for (LinkTag linkTag : this.linkTags.values())
  154.         {
  155.             if (linkTag.connector)
  156.             {
  157.                 this.connectorTags.put(linkTag.name, linkTag);
  158.             }
  159.             else
  160.             {
  161.                 this.realLinkTags.put(linkTag.name, linkTag);
  162.             }
  163.         }

  164.         // removes all duplicate nodes, both in Link and Node lists
  165.         NodeTag.removeDuplicateNodes(this);
  166.         // Split links where appropriate
  167.         // Step 1: split links, where a connector intersects a link
  168.         // loops through all connectors
  169.         // a link gets split if the connector is more than a "margin" number of meters from the start or end of a link
  170.         Double margin = 5.0;
  171.         splitLinksIntersectedByConnector(margin);

  172.         // create space between connectors and links, in order to make bezier curved links between connectors and links
  173.         // action: the connectors become shorter than they were
  174.         // LinkTag.shortenConnectors(this);

  175.         // Create links to connect the shortened connectors and links by means of bezier curved links
  176.         createLinkBetweenConnectorAndLink(this);

  177.         // Step 2: split links directly behind a signal head, assuming such a link enters a signalized junction
  178.         //
  179.         Double splitMetersAfterSignalHead = 1.5;
  180.         margin = 4.0;
  181.         splitLinkAtSignalAndDetector(this.linkTags, margin, splitMetersAfterSignalHead);

  182.         // remove double links with the same start and end node
  183.         LinkedHashMap<String, LinkTag> removeConnectorTags = new LinkedHashMap<>();
  184.         removeDoubleConnectors(removeConnectorTags);

  185.         // build links
  186.         for (LinkTag linkTag : this.linkTags.values())
  187.         {
  188.             Links.buildLink(linkTag, this, this.simulator);
  189.         }

  190.         // Generate the real links
  191.         for (LinkTag realLinkTag : this.linkTags.values())
  192.         {
  193.             Links.applyRoadTypeToLink(realLinkTag, this, this.simulator);
  194.         }

  195.         // Generate sink/kill sensors at the links that have no further connections (dead-walking)
  196.         for (LinkTag realLinkTag : this.linkTags.values())
  197.         {
  198.             Links.createSinkSensor(realLinkTag, this, this.simulator);
  199.         }

  200.         // generate the connector links
  201.         for (LinkTag connectorTag : this.linkTags.values())
  202.         {
  203.             Links.applyRoadTypeToConnector(connectorTag, this, this.simulator);
  204.         }

  205.         NodeTag.removeRedundantNodeTags(this);

  206.         // process the routes
  207.         // for (RouteTag routeTag : this.routeTags.values())
  208.         // routeTag.makeRoute();
  209.         // TODO shortestRoute, routeMix, ShortestRouteMix

  210.         // store the structure information in the network
  211.         XMLNetworkWriter.writeToXML(outputFile, linkTags, nodeTags, sinkKillClassName, sensorClassName, trafficLightName);

  212.         return makeNetwork();
  213.     }

  214.     private void removeDoubleConnectors(HashMap<String, LinkTag> removeConnectorTags)
  215.     {
  216.         for (LinkTag linkTag : this.connectorTags.values())
  217.         {
  218.             for (LinkTag linkTag2 : this.connectorTags.values())
  219.             {
  220.                 if (linkTag.nodeStartTag.name.equals(linkTag2.nodeStartTag.name)
  221.                         && linkTag.nodeEndTag.name.equals(linkTag2.nodeEndTag.name) && !linkTag.equals(linkTag2))
  222.                 {
  223.                     removeConnectorTags.put(linkTag.nodeStartTag.name + linkTag.nodeEndTag.name, linkTag);
  224.                 }
  225.             }
  226.         }
  227.         for (Entry<String, LinkTag> entry : removeConnectorTags.entrySet())
  228.         {
  229.             connectorTags.remove(entry.getValue().name);
  230.             linkTags.remove(entry.getValue().name);
  231.         }
  232.     }

  233.     /**
  234.      * @param parser VissimNetworkLaneParser;
  235.      * @throws OTSGeometryException
  236.      */
  237.     private void createLinkBetweenConnectorAndLink(final VissimNetworkLaneParser parser) throws OTSGeometryException
  238.     {
  239.         // loop through all connector links
  240.         for (LinkTag connectorLinkTag : this.connectorTags.values())
  241.         {

  242.             OTSLine3D designLineOTS = LinkTag.createLineString(connectorLinkTag);
  243.             LineString designLine = designLineOTS.getLineString();
  244.             Double length = designLine.getLength();
  245.             // default: we replace the connector link by a bezier curved link
  246.             if (length < 999995)
  247.             {
  248.                 connectorLinkTag.nodeStartTag = parser.nodeTags.get(connectorLinkTag.connectorTag.fromNodeName);
  249.                 connectorLinkTag.nodeEndTag = parser.nodeTags.get(connectorLinkTag.connectorTag.toNodeName);
  250.                 connectorLinkTag.bezierTag = new BezierTag();
  251.                 if (connectorLinkTag.nodeStartTag.name.equals(connectorLinkTag.nodeEndTag.name))
  252.                 {
  253.                     this.linkTags.remove(connectorLinkTag.name);
  254.                     // this.connectorTags.remove(connectorLinkTag.name);
  255.                 }
  256.                 if (connectorLinkTag.polyLineTag != null)
  257.                 {
  258.                     connectorLinkTag.polyLineTag = null;
  259.                 }
  260.                 if (connectorLinkTag.straightTag != null)
  261.                 {
  262.                     connectorLinkTag.straightTag = null;
  263.                 }
  264.             }
  265.             // if the link is quite long....we could split it but we don't do this now
  266.             // so the next block is inactive!!!
  267.             else
  268.             {
  269.                 // get the from link
  270.                 LinkTag pasteLinkFromTag = new LinkTag(connectorLinkTag);
  271.                 // add a unique name
  272.                 String linkName = "" + parser.upperLinkNr;
  273.                 parser.upperLinkNr++;
  274.                 pasteLinkFromTag.name = linkName;
  275.                 pasteLinkFromTag.nodeStartTag = parser.nodeTags.get(connectorLinkTag.connectorTag.fromNodeName);
  276.                 pasteLinkFromTag.nodeEndTag = connectorLinkTag.nodeStartTag;
  277.                 pasteLinkFromTag.bezierTag = new BezierTag();
  278.                 if (pasteLinkFromTag.polyLineTag != null)
  279.                 {
  280.                     pasteLinkFromTag.polyLineTag = null;
  281.                 }
  282.                 if (pasteLinkFromTag.straightTag != null)
  283.                 {
  284.                     pasteLinkFromTag.straightTag = null;
  285.                 }
  286.                 // this.linkTags.put(pasteLinkFromTag.name, pasteLinkFromTag);

  287.                 // get the To link
  288.                 LinkTag pasteLinkToTag = new LinkTag(connectorLinkTag);
  289.                 linkName = "" + parser.upperLinkNr;
  290.                 parser.upperLinkNr++;
  291.                 pasteLinkToTag.name = linkName;
  292.                 pasteLinkToTag.nodeStartTag = connectorLinkTag.nodeEndTag;
  293.                 pasteLinkToTag.nodeEndTag = parser.nodeTags.get(connectorLinkTag.connectorTag.toNodeName);

  294.                 pasteLinkToTag.bezierTag = new BezierTag();
  295.                 if (pasteLinkToTag.polyLineTag != null)
  296.                 {
  297.                     pasteLinkToTag.polyLineTag = null;
  298.                 }
  299.                 if (pasteLinkToTag.straightTag != null)
  300.                 {
  301.                     pasteLinkToTag.straightTag = null;
  302.                 }
  303.                 // this.linkTags.put(pasteLinkToTag.name, pasteLinkToTag);

  304.             }
  305.             // }
  306.         }
  307.     }

  308.     private void splitLinkAtSignalAndDetector(Map<String, LinkTag> inputLinkTags, Double margin,
  309.             Double splitMetersAfterSignalHead) throws OTSGeometryException, NetworkException
  310.     {

  311.         Map<String, LinkTag> newLinkTags = new LinkedHashMap<>();
  312.         // Loops through all links
  313.         splitLinksAtSignal(margin, splitMetersAfterSignalHead, inputLinkTags, newLinkTags);

  314.     }

  315.     private void splitLinksAtSignal(Double margin, Double splitMetersAfterSignalHead, Map<String, LinkTag> inputLinkTags,
  316.             Map<String, LinkTag> newLinkTags) throws OTSGeometryException, NetworkException
  317.     {
  318.         for (LinkTag linkTag : inputLinkTags.values())
  319.         {
  320.             for (SignalHeadTag signalHeadTag : linkTag.signalHeads)
  321.             {
  322.                 Double position = Double.parseDouble(signalHeadTag.positionStr);
  323.                 Double splitPosition = position + splitMetersAfterSignalHead;
  324.                 // A new node has to be created
  325.                 NodeTag newNodeTag = NodeTag.createNewNodeAtLinkPosition(linkTag, this, splitPosition);
  326.                 // split the link and connect the new node after the position of the signalhead\
  327.                 Map<String, LinkTag> newLinks = LinkTag.splitLink(newNodeTag, linkTag, this, splitPosition, margin, false);
  328.                 if (newLinks != null)
  329.                 {
  330.                     newLinkTags.putAll(newLinks);
  331.                 }
  332.             }
  333.             linkTag.signalHeads.removeAll(linkTag.signalHeadsToRemove);
  334.             linkTag.sensors.removeAll(linkTag.sensorTagsToRemove);
  335.             // relocate the signalHeads and detectors afterwards!
  336.         }
  337.         if (!newLinkTags.isEmpty())
  338.         {
  339.             this.linkTags.putAll(newLinkTags);
  340.         }

  341.         // run again for the newly created linkTags
  342.         Map<String, LinkTag> new2LinkTags = new LinkedHashMap<>();
  343.         if (newLinkTags.size() > 0)
  344.         {
  345.             splitLinksAtSignal(margin, splitMetersAfterSignalHead, newLinkTags, new2LinkTags);
  346.         }
  347.     }

  348.     private void splitLinksIntersectedByConnector(Double margin) throws OTSGeometryException, NetworkException
  349.     {
  350.         // loop through all connector links
  351.         for (LinkTag connectorLinkTag : this.connectorTags.values())
  352.         {
  353.             // ***********************
  354.             // 1: connector meets link:
  355.             // get the position where this connector intersects the Link. Here the link will be split
  356.             Double position = Double.parseDouble(connectorLinkTag.connectorTag.toPositionStr);

  357.             // get the meeting link
  358.             LinkTag linkToTag = this.realLinkTags.get(connectorLinkTag.connectorTag.toLinkNo);
  359.             boolean isConnectorToLink = true;

  360.             // create a new node at the split position of the "meeting" Link
  361.             NodeTag newSplitNodeTag = NodeTag.createNewNodeAtLinkPosition(linkToTag, this, position);

  362.             // split the link
  363.             Map<String, LinkTag> newLinkToTags =
  364.                     LinkTag.splitLink(newSplitNodeTag, linkToTag, this, position, margin, isConnectorToLink);
  365.             linkToTag.signalHeads.removeAll(linkToTag.signalHeadsToRemove);
  366.             linkToTag.sensors.removeAll(linkToTag.sensorTagsToRemove);

  367.             if (newLinkToTags != null)
  368.             {
  369.                 // only add if a link is split
  370.                 connectorLinkTag.connectorTag.toNodeName = newSplitNodeTag.name;
  371.                 this.nodeTags.put(newSplitNodeTag.name, newSplitNodeTag);
  372.                 // adjust the connection of other Connector links
  373.                 for (LinkTag connectorLinkTag2 : this.connectorTags.values())
  374.                 {

  375.                     if (connectorLinkTag2 != connectorLinkTag
  376.                             && connectorLinkTag2.connectorTag.toLinkNo.equals(connectorLinkTag.connectorTag.toLinkNo))
  377.                     {

  378.                         Double position2 = Double.parseDouble(connectorLinkTag2.connectorTag.toPositionStr);
  379.                         if (position2 > position)
  380.                         {
  381.                             connectorLinkTag2.connectorTag.toLinkNo = newLinkToTags.values().iterator().next().name;
  382.                             Double newPosition = position2 - position;
  383.                             connectorLinkTag2.connectorTag.toPositionStr = newPosition.toString();
  384.                         }
  385.                     }
  386.                     if (connectorLinkTag2 != connectorLinkTag
  387.                             && connectorLinkTag2.connectorTag.fromLinkNo.equals(connectorLinkTag.connectorTag.toLinkNo))
  388.                     {

  389.                         Double position2 = Double.parseDouble(connectorLinkTag2.connectorTag.fromPositionStr);
  390.                         if (position2 > position)
  391.                         {
  392.                             connectorLinkTag2.connectorTag.fromLinkNo = newLinkToTags.values().iterator().next().name;
  393.                             Double newPosition = position2 - position;
  394.                             connectorLinkTag2.connectorTag.fromPositionStr = newPosition.toString();
  395.                         }
  396.                     }
  397.                 }
  398.                 // connectorTag.connectorTag.toLinkNo = newLinkToTags.values().iterator().next().name;
  399.                 this.linkTags.putAll(newLinkToTags);
  400.                 this.realLinkTags.putAll(newLinkToTags);
  401.             }
  402.             else
  403.             {

  404.                 // from connector to next link
  405.                 if (position < margin)
  406.                 {
  407.                     this.nodeTags.remove(connectorLinkTag.connectorTag.toNodeName);
  408.                     connectorLinkTag.connectorTag.toNodeName = linkToTag.nodeStartTag.name;
  409.                 }
  410.                 // from link to connector
  411.                 else
  412.                 {
  413.                     this.nodeTags.remove(connectorLinkTag.connectorTag.toNodeName);
  414.                     connectorLinkTag.connectorTag.toNodeName = linkToTag.nodeEndTag.name;
  415.                 }
  416.             }

  417.             // ******************************
  418.             // 2: connector exits from a link:
  419.             position = Double.parseDouble(connectorLinkTag.connectorTag.fromPositionStr);
  420.             LinkTag linkFromTag = this.realLinkTags.get(connectorLinkTag.connectorTag.fromLinkNo);
  421.             isConnectorToLink = false;
  422.             NodeTag newSplitNodeTag2 = NodeTag.createNewNodeAtLinkPosition(linkFromTag, this, position);

  423.             Map<String, LinkTag> newLinkFromTags =
  424.                     LinkTag.splitLink(newSplitNodeTag2, linkFromTag, this, position, margin, isConnectorToLink);
  425.             linkFromTag.signalHeads.removeAll(linkFromTag.signalHeadsToRemove);
  426.             linkFromTag.sensors.removeAll(linkFromTag.sensorTagsToRemove);

  427.             if (newLinkFromTags != null)
  428.             {
  429.                 // only add if a link is split
  430.                 connectorLinkTag.connectorTag.fromNodeName = newSplitNodeTag2.name;
  431.                 this.nodeTags.put(newSplitNodeTag2.name, newSplitNodeTag2);
  432.                 // adjust the connection of other Connector links
  433.                 for (LinkTag connectorLinkTag2 : this.connectorTags.values())
  434.                 {
  435.                     if (connectorLinkTag2 != connectorLinkTag
  436.                             && connectorLinkTag2.connectorTag.fromLinkNo.equals(connectorLinkTag.connectorTag.fromLinkNo))
  437.                     {

  438.                         Double position2 = Double.parseDouble(connectorLinkTag2.connectorTag.fromPositionStr);
  439.                         if (position2 > position)
  440.                         {
  441.                             connectorLinkTag2.connectorTag.fromLinkNo = newLinkFromTags.values().iterator().next().name;
  442.                             Double newPosition = position2 - position;
  443.                             connectorLinkTag2.connectorTag.fromPositionStr = newPosition.toString();
  444.                         }
  445.                     }
  446.                     if (connectorLinkTag2 != connectorLinkTag
  447.                             && connectorLinkTag2.connectorTag.toLinkNo.equals(connectorLinkTag.connectorTag.fromLinkNo))
  448.                     {

  449.                         Double position2 = Double.parseDouble(connectorLinkTag2.connectorTag.toPositionStr);
  450.                         if (position2 > position)
  451.                         {
  452.                             connectorLinkTag2.connectorTag.toLinkNo = newLinkFromTags.values().iterator().next().name;
  453.                             Double newPosition = position2 - position;
  454.                             connectorLinkTag2.connectorTag.toPositionStr = newPosition.toString();
  455.                         }
  456.                     }
  457.                 }
  458.                 // connectorTag.connectorTag.fromLinkNo = newLinkFromTags.values().iterator().next().name;
  459.                 this.linkTags.putAll(newLinkFromTags);
  460.                 this.realLinkTags.putAll(newLinkFromTags);
  461.             }
  462.             else
  463.             {
  464.                 // from connector to next link
  465.                 if (position < margin)
  466.                 {
  467.                     this.nodeTags.remove(connectorLinkTag.connectorTag.fromNodeName);
  468.                     connectorLinkTag.connectorTag.fromNodeName = linkFromTag.nodeStartTag.name;
  469.                 }
  470.                 // from link to connector
  471.                 else
  472.                 {
  473.                     this.nodeTags.remove(connectorLinkTag.connectorTag.fromNodeName);
  474.                     connectorLinkTag.connectorTag.fromNodeName = linkFromTag.nodeEndTag.name;
  475.                 }
  476.             }
  477.         }
  478.     }

  479.     /**
  480.      * @return the OTSRoadNetwork with the static information about the network
  481.      * @throws NetworkException if items cannot be added to the Network
  482.      */
  483.     private OTSRoadNetwork makeNetwork() throws NetworkException
  484.     {
  485.         // for (RouteTag routeTag : this.routeTags.values()) {
  486.         // // TODO Make routes GTU specific. See what to do with GTUType.ALL for routes
  487.         // // TODO Automate addition of Routes to network
  488.         // this.network.addRoute(GTUType.ALL, routeTag.route);
  489.         // }
  490.         return this.network;
  491.     }

  492.     /** {@inheritDoc} */
  493.     @Override
  494.     public final String toString()
  495.     {
  496.         return "VissimANMNetworkLaneParser [gtuTypes=" + this.gtuTypes + ", laneTypes=" + this.laneTypes + "]";
  497.     }

  498.     public GlobalTag getGlobalTag()
  499.     {
  500.         return globalTag;
  501.     }

  502.     public void setGlobalTag(GlobalTag globalTag)
  503.     {
  504.         this.globalTag = globalTag;
  505.     }

  506.     public Map<String, NodeTag> getNodeTags()
  507.     {
  508.         return nodeTags;
  509.     }

  510.     public void setNodeTags(Map<String, NodeTag> nodeTags)
  511.     {
  512.         this.nodeTags = nodeTags;
  513.     }

  514.     public Map<String, LinkTag> getLinkTags()
  515.     {
  516.         return linkTags;
  517.     }

  518.     public void setLinkTags(Map<String, LinkTag> linkTags)
  519.     {
  520.         this.linkTags = linkTags;
  521.     }

  522.     public Map<String, LinkTag> getConnectorTags()
  523.     {
  524.         return connectorTags;
  525.     }

  526.     public void setConnectorTags(Map<String, LinkTag> connectorTags)
  527.     {
  528.         this.connectorTags = connectorTags;
  529.     }

  530.     public Map<String, LinkTag> getRealLinkTags()
  531.     {
  532.         return realLinkTags;
  533.     }

  534.     public void setRealLinkTags(Map<String, LinkTag> realLinkTags)
  535.     {
  536.         this.realLinkTags = realLinkTags;
  537.     }

  538.     public Map<String, SignalHeadTag> getSignalHeadTags()
  539.     {
  540.         return signalHeadTags;
  541.     }

  542.     public void setSignalHeadTags(Map<String, SignalHeadTag> signalHeadTags)
  543.     {
  544.         this.signalHeadTags = signalHeadTags;
  545.     }

  546.     public Map<String, SensorTag> getSensorTags()
  547.     {
  548.         return sensorTags;
  549.     }

  550.     public void setSensorTags(Map<String, SensorTag> sensorTags)
  551.     {
  552.         this.sensorTags = sensorTags;
  553.     }

  554.     public Map<String, GTUTag> getGtuTags()
  555.     {
  556.         return gtuTags;
  557.     }

  558.     public void setGtuTags(Map<String, GTUTag> gtuTags)
  559.     {
  560.         this.gtuTags = gtuTags;
  561.     }

  562.     public Map<String, GTUMixTag> getGtuMixTags()
  563.     {
  564.         return gtuMixTags;
  565.     }

  566.     public void setGtuMixTags(Map<String, GTUMixTag> gtuMixTags)
  567.     {
  568.         this.gtuMixTags = gtuMixTags;
  569.     }

  570.     public Map<String, RoadTypeTag> getRoadTypeTags()
  571.     {
  572.         return roadTypeTags;
  573.     }

  574.     public void setRoadTypeTags(Map<String, RoadTypeTag> roadTypeTags)
  575.     {
  576.         this.roadTypeTags = roadTypeTags;
  577.     }

  578.     public Map<String, GTUType> getGtuTypes()
  579.     {
  580.         return gtuTypes;
  581.     }

  582.     public void setGtuTypes(Map<String, GTUType> gtuTypes)
  583.     {
  584.         this.gtuTypes = gtuTypes;
  585.     }

  586.     public Map<String, LaneTypeTag> getLaneTypeTags()
  587.     {
  588.         return laneTypeTags;
  589.     }

  590.     public void setLaneTypeTags(Map<String, LaneTypeTag> laneTypeTags)
  591.     {
  592.         this.laneTypeTags = laneTypeTags;
  593.     }

  594.     public Map<String, RoadLayoutTag> getRoadLayoutTags()
  595.     {
  596.         return roadLayoutTags;
  597.     }

  598.     public void setRoadLayoutTags(Map<String, RoadLayoutTag> roadLayoutTags)
  599.     {
  600.         this.roadLayoutTags = roadLayoutTags;
  601.     }

  602.     public Map<String, RouteMixTag> getRouteMixTags()
  603.     {
  604.         return routeMixTags;
  605.     }

  606.     public void setRouteMixTags(Map<String, RouteMixTag> routeMixTags)
  607.     {
  608.         this.routeMixTags = routeMixTags;
  609.     }

  610.     public Map<String, ShortestRouteMixTag> getShortestRouteMixTags()
  611.     {
  612.         return shortestRouteMixTags;
  613.     }

  614.     public void setShortestRouteMixTags(Map<String, ShortestRouteMixTag> shortestRouteMixTags)
  615.     {
  616.         this.shortestRouteMixTags = shortestRouteMixTags;
  617.     }

  618.     public Map<String, ShortestRouteTag> getShortestRouteTags()
  619.     {
  620.         return shortestRouteTags;
  621.     }

  622.     public void setShortestRouteTags(Map<String, ShortestRouteTag> shortestRouteTags)
  623.     {
  624.         this.shortestRouteTags = shortestRouteTags;
  625.     }

  626.     public Map<String, RouteTag> getRouteTags()
  627.     {
  628.         return routeTags;
  629.     }

  630.     public void setRouteTags(Map<String, RouteTag> routeTags)
  631.     {
  632.         this.routeTags = routeTags;
  633.     }

  634.     public Map<String, LaneType> getLaneTypes()
  635.     {
  636.         return laneTypes;
  637.     }

  638.     public void setLaneTypes(Map<String, LaneType> laneTypes)
  639.     {
  640.         this.laneTypes = laneTypes;
  641.     }

  642.     public DEVSSimulatorInterface.TimeDoubleUnit getSimulator()
  643.     {
  644.         return simulator;
  645.     }

  646.     public void setSimulator(OTSSimulatorInterface simulator)
  647.     {
  648.         this.simulator = simulator;
  649.     }

  650.     public OTSRoadNetwork getNetwork()
  651.     {
  652.         return network;
  653.     }

  654.     public void setNetwork(OTSRoadNetwork network)
  655.     {
  656.         this.network = network;
  657.     }

  658.     public int getUpperNodeNr()
  659.     {
  660.         return upperNodeNr;
  661.     }

  662.     public void setUpperNodeNr(int upperNodeNr)
  663.     {
  664.         this.upperNodeNr = upperNodeNr;
  665.     }

  666.     public int getUpperLinkNr()
  667.     {
  668.         return upperLinkNr;
  669.     }

  670.     public void setUpperLinkNr(int upperLinkNr)
  671.     {
  672.         this.upperLinkNr = upperLinkNr;
  673.     }
  674. }