package roadnetwork; import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.List; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import shapes.Point2DExt; /** * Class for parsing a SUMO .net.ml road network file * */ public class RoadNetworkParser { /** * Method that parses a SUMO road network xml file. * * @param roadNetworkXMLDocument * The xml document containing the network * @return The road network * @throws Exception * if anything goes wrong */ public RoadNetwork ParseXMLNetFile(Document roadNetworkXMLDocument) throws Exception { // Create a new network RoadNetwork net = new RoadNetwork(); Element docel = roadNetworkXMLDocument.getDocumentElement(); // Get all edge elements NodeList edges = docel.getElementsByTagName("edge"); // Parse the edge elements List<Edge> parsedEdges = ParseEdges(edges); // Parse the connections between the edges/lanes NodeList successors = docel.getElementsByTagName("succ"); ParseDeprecatedSuccessors(successors, parsedEdges); NodeList successors2 = docel.getElementsByTagName("connection"); ParseNewSuccessors(successors, parsedEdges); // Add the parsed edges to the network net.AddElements(parsedEdges); // Get all junction elements NodeList junctions = docel.getElementsByTagName("junction"); // Parse the junction elements List<Junction> parsedJunctions = ParseJunctions(junctions); // Add the parsed junctions to the network net.AddElements(parsedJunctions); return net; } /** * Method that creates {@link Edge} objects from the xml elements * * @param xmlEdgeNodes * @return a list of created edges */ private List<Edge> ParseEdges(NodeList xmlEdgeNodes) { List<Edge> parsedEdges = new ArrayList<Edge>(); int totalEdges = xmlEdgeNodes.getLength(); // Loop through all the edge xml elements for (int i = 0; i < totalEdges; i++) { Node edge = xmlEdgeNodes.item(i); // Get the xml attributes NamedNodeMap edgeAttributes = edge.getAttributes(); // Continue only if this is a normal edge Node function = edgeAttributes.getNamedItem("function"); if (function==null || function.getNodeValue().equals("normal")) { // Create a new edge Edge e = new Edge(); // Set its properties e.setId(edgeAttributes.getNamedItem("id").getNodeValue()); e.setFrom(edgeAttributes.getNamedItem("from").getNodeValue()); e.setTo(edgeAttributes.getNamedItem("to").getNodeValue()); Node prio = edgeAttributes.getNamedItem("priority"); if(prio!=null) { e.setPriority(Integer.parseInt(prio.getNodeValue())); } else { e.setPriority(-1); } // Get the edge's lanes NodeList lanes = ((Element) edge).getElementsByTagName("lane"); // Parse the lanes int totalLanes = lanes.getLength(); for (int j = 0; j < totalLanes; j++) { Node lane = lanes.item(j); Lane l = new Lane(); // Get the xml attributes NamedNodeMap laneAttributes = lane.getAttributes(); if (j == 0) { e.setLength(Float.parseFloat(laneAttributes.getNamedItem("length").getNodeValue())); e.setSpeedLimit(Float.parseFloat(laneAttributes.getNamedItem("speed").getNodeValue())); } // Get the lane's id l.setId(laneAttributes.getNamedItem("id").getNodeValue()); // Get the lane's coordinates List<Point2DExt> points = new ArrayList<Point2DExt>(); String[] coords = laneAttributes.getNamedItem("shape").getNodeValue().split(" "); for (String coord : coords) { String[] from = coord.split(","); double fromx = Double.parseDouble(from[0]); double fromy = Double.parseDouble(from[1]); points.add(new Point2DExt(fromx, fromy)); } l.SetShape(points); e.AddLane(l); } // Calculate the edge's shape e.CalculateShape(); // Add the edge to the result list parsedEdges.add(e); } } return parsedEdges; } /** * Reads in the connections between the lanes. It takes the list of succ * elements of the SUMO net file and extracts the successors. These are * filled in the list of each lane. The lanes are taken from the provides * edge list. * * @param succNodes * the XML nodes of type succ in the SUMO net file * @param edges * the edges in which the lane connections are filled */ private void ParseDeprecatedSuccessors(NodeList succNodes, List<Edge> edges) { int numberSuccNodes = succNodes.getLength(); for (int nodeIndex = 0; nodeIndex < numberSuccNodes; ++nodeIndex) { Node succNode = succNodes.item(nodeIndex); // Find the edge of which this node contains the successors NamedNodeMap succAttributes = succNode.getAttributes(); String edgeId = succAttributes.getNamedItem("edge").getNodeValue(); Edge edge = null; for (Edge e : edges) { if (e.getId().equals(edgeId)) { edge = e; } } if (edge == null) { continue; } // Find the lane of which this node contains the successors String laneId = succAttributes.getNamedItem("lane").getNodeValue(); Lane lane = null; for (Lane l : edge.getLanes()) { if (l.getId().equals(laneId)) { lane = l; } } if (lane == null) { System.out.printf("Lane %s not found\n", laneId); continue; } // Fill in the successors NodeList childsOfSuccNode = succNode.getChildNodes(); int numberOfChilds = childsOfSuccNode.getLength(); for (int chidIndex = 0; chidIndex < numberOfChilds; ++chidIndex) { Node child = childsOfSuccNode.item(chidIndex); if (child.getNodeName().equals("succlane")) { // This is a node that contains successors NamedNodeMap childAttributes = child.getAttributes(); String connectedLaneId = childAttributes.getNamedItem( "lane").getNodeValue(); String connectedEdgeId = findEdgeIdToLaneId(connectedLaneId, edges); if (connectedEdgeId != null) { lane.AddConnectedEdge(connectedEdgeId); } } } } } private void ParseNewSuccessors(NodeList connNodes, List<Edge> edges) { int numberConnNodes = connNodes.getLength(); for (int nodeIndex = 0; nodeIndex < numberConnNodes; ++nodeIndex) { Node succNode = connNodes.item(nodeIndex); // Find the edge of which this node contains the successors NamedNodeMap succAttributes = succNode.getAttributes(); String fromId = succAttributes.getNamedItem("from").getNodeValue(); Edge from = null; for (Edge e : edges) { if (e.getId().equals(fromId)) { from = e; } } if (from == null) { continue; } String toId = succAttributes.getNamedItem("to").getNodeValue(); Edge to = null; for (Edge e : edges) { if (e.getId().equals(toId)) { to = e; } } if (to == null) { continue; } // Find the lane of which this node contains the successors String fromLaneId = succAttributes.getNamedItem("fromLane").getNodeValue(); Lane fromLane = from.getLanes().get(Integer.parseInt(fromLaneId)); fromLane.AddConnectedEdge(toId); } } /** Returns the ID of the edge that contains the lane with the given ID. * * @param laneId The ID of the lane to search for * @param edges The list of edges * @return the ID of the found edge or null, if not found */ private String findEdgeIdToLaneId(String laneId, List<Edge> edges) { for (Edge e : edges) { for (Lane l : e.getLanes()) { if (l.getId().equals(laneId)) { return e.getId(); } } } return null; } /** * Method that creates {@link Junction} objects from the xml elements * * @param xmlJunctionNodes * @return a list of created junctions */ private List<Junction> ParseJunctions(NodeList xmlJunctionNodes) { List<Junction> parsedJunctions = new ArrayList<Junction>(); int totalJunctions = xmlJunctionNodes.getLength(); // Loop through all the xml junction elements for (int i = 0; i < totalJunctions; i++) { Node junction = xmlJunctionNodes.item(i); // Get the junction's attributes NamedNodeMap junctionAttributes = junction.getAttributes(); // Continue only if this is a normal junction Node function = junctionAttributes.getNamedItem("type"); if (!function.getNodeValue().equals("internal")) { Junction j = new Junction(); // Set the junction's properties j.setId(junctionAttributes.getNamedItem("id").getNodeValue()); j.setType(junctionAttributes.getNamedItem("type").getNodeValue()); String coordinates = junctionAttributes.getNamedItem("shape").getNodeValue();//((Element) junction).getElementsByTagName("shape").item(0).getTextContent(); if (coordinates.equals("")) { j.SetShape(null); } else { String[] coords = coordinates.split(" "); List<Point2D.Float> points = new ArrayList<Point2D.Float>(); if ((coords.length > 0) && (coords[0] != "")) { // Get the junction's shape points for (String coord : coords) { String[] from = coord.split(","); float fromx = Float.parseFloat(from[0]); float fromy = Float.parseFloat(from[1]); points.add(new Point2D.Float(fromx, fromy)); } } j.SetShape(points); } parsedJunctions.add(j); } } return parsedJunctions; } }