// =========================================================================== // method definitions // =========================================================================== // --------------------------------------------------------------------------- // NBRampsComputer // --------------------------------------------------------------------------- void NBRampsComputer::computeRamps(NBNetBuilder& nb, OptionsCont& oc) { SUMOReal minHighwaySpeed = oc.getFloat("ramps.min-highway-speed"); SUMOReal maxRampSpeed = oc.getFloat("ramps.max-ramp-speed"); SUMOReal rampLength = oc.getFloat("ramps.ramp-length"); bool dontSplit = oc.getBool("ramps.no-split"); std::set<NBEdge*> incremented; // check whether on-off ramps shall be guessed if (oc.getBool("ramps.guess")) { NBNodeCont& nc = nb.getNodeCont(); NBEdgeCont& ec = nb.getEdgeCont(); NBDistrictCont& dc = nb.getDistrictCont(); std::set<NBNode*> potOnRamps; std::set<NBNode*> potOffRamps; for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NBNode* cur = (*i).second; if (mayNeedOnRamp(cur, minHighwaySpeed, maxRampSpeed)) { potOnRamps.insert(cur); } if (mayNeedOffRamp(cur, minHighwaySpeed, maxRampSpeed)) { potOffRamps.insert(cur); } } for (std::set<NBNode*>::const_iterator i = potOnRamps.begin(); i != potOnRamps.end(); ++i) { buildOnRamp(*i, nc, ec, dc, rampLength, dontSplit, incremented); } for (std::set<NBNode*>::const_iterator i = potOffRamps.begin(); i != potOffRamps.end(); ++i) { buildOffRamp(*i, nc, ec, dc, rampLength, dontSplit, incremented); } } // check whether on-off ramps shall be guessed if (oc.isSet("ramps.set")) { std::vector<std::string> edges = oc.getStringVector("ramps.set"); NBNodeCont& nc = nb.getNodeCont(); NBEdgeCont& ec = nb.getEdgeCont(); NBDistrictCont& dc = nb.getDistrictCont(); for (std::vector<std::string>::iterator i = edges.begin(); i != edges.end(); ++i) { NBEdge* e = ec.retrieve(*i); if (e == 0) { WRITE_WARNING("Can not build on ramp on edge '" + *i + "' - the edge is not known."); continue; } NBNode* from = e->getFromNode(); if (from->getIncomingEdges().size() == 2 && from->getOutgoingEdges().size() == 1) { buildOnRamp(from, nc, ec, dc, rampLength, dontSplit, incremented); } // load edge again to check offramps e = ec.retrieve(*i); if (e == 0) { WRITE_WARNING("Can not build off ramp on edge '" + *i + "' - the edge is not known."); continue; } NBNode* to = e->getToNode(); if (to->getIncomingEdges().size() == 1 && to->getOutgoingEdges().size() == 2) { buildOffRamp(to, nc, ec, dc, rampLength, dontSplit, incremented); } } } }
// --------------------------------------------------------------------------- // static methods // --------------------------------------------------------------------------- void NWWriter_DlrNavteq::writeNetwork(const OptionsCont& oc, NBNetBuilder& nb) { // check whether a matsim-file shall be generated if (!oc.isSet("dlr-navteq-output")) { return; } writeNodesUnsplitted(oc, nb.getNodeCont(), nb.getEdgeCont()); writeLinksUnsplitted(oc, nb.getEdgeCont()); }
// --------------------------------------------------------------------------- // static methods // --------------------------------------------------------------------------- void NWWriter_DlrNavteq::writeNetwork(const OptionsCont& oc, NBNetBuilder& nb) { // check whether a matsim-file shall be generated if (!oc.isSet("dlr-navteq-output")) { return; } std::map<NBEdge*, std::string> internalNodes; writeNodesUnsplitted(oc, nb.getNodeCont(), nb.getEdgeCont(), internalNodes); writeLinksUnsplitted(oc, nb.getEdgeCont(), internalNodes); writeTrafficSignals(oc, nb.getNodeCont()); writeProhibitedManoeuvres(oc, nb.getNodeCont(), nb.getEdgeCont()); writeConnectedLanes(oc, nb.getNodeCont()); }
// =========================================================================== // method definitions // =========================================================================== // --------------------------------------------------------------------------- // static methods // --------------------------------------------------------------------------- void NWWriter_XML::writeNetwork(const OptionsCont& oc, NBNetBuilder& nb) { // check whether plain-output files shall be generated if (oc.isSet("plain-output-prefix")) { writeNodes(oc, nb.getNodeCont()); writeEdgesAndConnections(oc, nb.getNodeCont(), nb.getEdgeCont()); writeTrafficLights(oc, nb.getTLLogicCont(), nb.getEdgeCont()); } if (oc.isSet("junctions.join-output")) { writeJoinedJunctions(oc, nb.getNodeCont()); } if (oc.isSet("street-sign-output")) { writeStreetSigns(oc, nb.getEdgeCont()); } }
// =========================================================================== // method definitions // =========================================================================== // --------------------------------------------------------------------------- // static methods (interface in this case) // --------------------------------------------------------------------------- void NIImporter_RobocupRescue::loadNetwork(const OptionsCont& oc, NBNetBuilder& nb) { // check whether the option is set (properly) if (!oc.isSet("robocup-dir")) { return; } // build the handler NIImporter_RobocupRescue handler(nb.getNodeCont(), nb.getEdgeCont()); // parse file(s) std::vector<std::string> files = oc.getStringVector("robocup-dir"); for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) { // nodes std::string nodesName = (*file) + "/node.bin"; if (!FileHelpers::exists(nodesName)) { WRITE_ERROR("Could not open robocup-node-file '" + nodesName + "'."); return; } PROGRESS_BEGIN_MESSAGE("Parsing robocup-nodes from '" + nodesName + "'"); handler.loadNodes(nodesName); PROGRESS_DONE_MESSAGE(); // edges std::string edgesName = (*file) + "/road.bin"; if (!FileHelpers::exists(edgesName)) { WRITE_ERROR("Could not open robocup-road-file '" + edgesName + "'."); return; } PROGRESS_BEGIN_MESSAGE("Parsing robocup-roads from '" + edgesName + "'"); handler.loadEdges(edgesName); PROGRESS_DONE_MESSAGE(); } }
// =========================================================================== // method definitions // =========================================================================== // --------------------------------------------------------------------------- // static methods (interface in this case) // --------------------------------------------------------------------------- void NIImporter_ArcView::loadNetwork(const OptionsCont& oc, NBNetBuilder& nb) { if (!oc.isSet("shapefile-prefix")) { return; } // check whether the correct set of entries is given // and compute both file names std::string dbf_file = oc.getString("shapefile-prefix") + ".dbf"; std::string shp_file = oc.getString("shapefile-prefix") + ".shp"; std::string shx_file = oc.getString("shapefile-prefix") + ".shx"; // check whether the files do exist if (!FileHelpers::isReadable(dbf_file)) { WRITE_ERROR("File not accessible: " + dbf_file); } if (!FileHelpers::isReadable(shp_file)) { WRITE_ERROR("File not accessible: " + shp_file); } if (!FileHelpers::isReadable(shx_file)) { WRITE_ERROR("File not accessible: " + shx_file); } if (MsgHandler::getErrorInstance()->wasInformed()) { return; } // load the arcview files NIImporter_ArcView loader(oc, nb.getNodeCont(), nb.getEdgeCont(), nb.getTypeCont(), dbf_file, shp_file, oc.getBool("speed-in-kmh")); loader.load(); }
// =========================================================================== // method definitions // =========================================================================== // --------------------------------------------------------------------------- // static methods // --------------------------------------------------------------------------- void NIImporter_MATSim::loadNetwork(const OptionsCont& oc, NBNetBuilder& nb) { // check whether the option is set (properly) if (!oc.isSet("matsim-files")) { return; } /* Parse file(s) * Each file is parsed twice: first for nodes, second for edges. */ std::vector<std::string> files = oc.getStringVector("matsim-files"); // load nodes, first NodesHandler nodesHandler(nb.getNodeCont()); for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) { // nodes if (!FileHelpers::isReadable(*file)) { WRITE_ERROR("Could not open matsim-file '" + *file + "'."); return; } nodesHandler.setFileName(*file); PROGRESS_BEGIN_MESSAGE("Parsing nodes from matsim-file '" + *file + "'"); if (!XMLSubSys::runParser(nodesHandler, *file)) { return; } PROGRESS_DONE_MESSAGE(); } // load edges, then EdgesHandler edgesHandler(nb.getNodeCont(), nb.getEdgeCont(), oc.getBool("matsim.keep-length"), oc.getBool("matsim.lanes-from-capacity"), NBCapacity2Lanes(oc.getFloat("lanes-from-capacity.norm"))); for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) { // edges edgesHandler.setFileName(*file); PROGRESS_BEGIN_MESSAGE("Parsing edges from matsim-file '" + *file + "'"); XMLSubSys::runParser(edgesHandler, *file); PROGRESS_DONE_MESSAGE(); } }
int main(int argc, char** argv) { OptionsCont& oc = OptionsCont::getOptions(); // give some application descriptions oc.setApplicationDescription("Road network generator for the microscopic road traffic simulation SUMO."); oc.setApplicationName("netgen", "SUMO netgen Version " + (std::string)VERSION_STRING); int ret = 0; try { // initialise the application system (messaging, xml, options) XMLSubSys::init(false); fillOptions(); OptionsIO::getOptions(true, argc, argv); if (oc.processMetaOptions(argc < 2)) { SystemFrame::close(); return 0; } MsgHandler::initOutputOptions(); if (!checkOptions()) { throw ProcessError(); } RandHelper::initRandGlobal(); NBNetBuilder nb; nb.applyOptions(oc); // build the netgen-network description NGNet* net = buildNetwork(nb); // ... and we have to do this... oc.resetWritable(); // transfer to the netbuilding structures net->toNB(); delete net; // report generated structures WRITE_MESSAGE(" Generation done;"); WRITE_MESSAGE(" " + toString<int>(nb.getNodeCont().size()) + " nodes generated."); WRITE_MESSAGE(" " + toString<int>(nb.getEdgeCont().size()) + " edges generated."); nb.compute(oc); NWFrame::writeNetwork(oc, nb); } catch (ProcessError& e) { if (std::string(e.what()) != std::string("Process Error") && std::string(e.what()) != std::string("")) { WRITE_ERROR(e.what()); } MsgHandler::getErrorInstance()->inform("Quitting (on error).", false); ret = 1; #ifndef _DEBUG } catch (...) { MsgHandler::getErrorInstance()->inform("Quitting (on unknown error).", false); ret = 1; #endif } OutputDevice::closeAll(); SystemFrame::close(); if (ret == 0) { std::cout << "Success." << std::endl; } return ret; }
// =========================================================================== // method definitions // =========================================================================== // --------------------------------------------------------------------------- // static methods // --------------------------------------------------------------------------- void NWWriter_MATSim::writeNetwork(const OptionsCont& oc, NBNetBuilder& nb) { // check whether a matsim-file shall be generated if (!oc.isSet("matsim-output")) { return; } OutputDevice& device = OutputDevice::getDevice(oc.getString("matsim-output")); device << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; device << "<!DOCTYPE network SYSTEM \"http://www.matsim.org/files/dtd/network_v1.dtd\">\n\n"; device << "<network name=\"NAME\">\n"; // !!! name // write nodes device << " <nodes>\n"; NBNodeCont& nc = nb.getNodeCont(); for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { device << " <node id=\"" << (*i).first << "\" x=\"" << (*i).second->getPosition().x() << "\" y=\"" << (*i).second->getPosition().y() << "\"/>\n"; } device << " </nodes>\n"; // write edges device << " <links capperiod=\"01:00:00\">\n"; NBEdgeCont& ec = nb.getEdgeCont(); for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) { device << " <link id=\"" << (*i).first << "\" from=\"" << (*i).second->getFromNode()->getID() << "\" to=\"" << (*i).second->getToNode()->getID() << "\" length=\"" << (*i).second->getLoadedLength() << "\" capacity=\"" << (oc.getFloat("lanes-from-capacity.norm") * (*i).second->getNumLanes()) << "\" freespeed=\"" << (*i).second->getSpeed() << "\" permlanes=\"" << (*i).second->getNumLanes() << "\"/>\n"; } device << " </links>\n"; // device << "</network>\n"; // !!! name device.close(); }
// =========================================================================== // method definitions // =========================================================================== // --------------------------------------------------------------------------- // static methods // --------------------------------------------------------------------------- void NWWriter_OpenDrive::writeNetwork(const OptionsCont& oc, NBNetBuilder& nb) { // check whether an opendrive-file shall be generated if (!oc.isSet("opendrive-output")) { return; } const NBNodeCont& nc = nb.getNodeCont(); const NBEdgeCont& ec = nb.getEdgeCont(); const bool origNames = oc.getBool("output.original-names"); const bool lefthand = oc.getBool("lefthand"); const double straightThresh = DEG2RAD(oc.getFloat("opendrive-output.straight-threshold")); // some internal mapping containers int nodeID = 1; int edgeID = nc.size() * 10; // distinct from node ids StringBijection<int> edgeMap; StringBijection<int> nodeMap; // OutputDevice& device = OutputDevice::getDevice(oc.getString("opendrive-output")); device << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; device.openTag("OpenDRIVE"); time_t now = time(0); std::string dstr(ctime(&now)); const Boundary& b = GeoConvHelper::getFinal().getConvBoundary(); // write header device.openTag("header"); device.writeAttr("revMajor", "1"); device.writeAttr("revMinor", "4"); device.writeAttr("name", ""); device.writeAttr("version", "1.00"); device.writeAttr("date", dstr.substr(0, dstr.length() - 1)); device.writeAttr("north", b.ymax()); device.writeAttr("south", b.ymin()); device.writeAttr("east", b.xmax()); device.writeAttr("west", b.xmin()); /* @note obsolete in 1.4 device.writeAttr("maxRoad", ec.size()); device.writeAttr("maxJunc", nc.size()); device.writeAttr("maxPrg", 0); */ device.closeTag(); // write optional geo reference const GeoConvHelper& gch = GeoConvHelper::getFinal(); if (gch.usingGeoProjection()) { if (gch.getOffsetBase() == Position(0,0)) { device.openTag("geoReference"); device.writePreformattedTag(" <![CDATA[\n " + gch.getProjString() + "\n]]>\n"); device.closeTag(); } else { WRITE_WARNING("Could not write OpenDRIVE geoReference. Only unshifted Coordinate systems are supported (offset=" + toString(gch.getOffsetBase()) + ")"); } } // write normal edges (road) for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) { const NBEdge* e = (*i).second; const int fromNodeID = e->getIncomingEdges().size() > 0 ? getID(e->getFromNode()->getID(), nodeMap, nodeID) : INVALID_ID; const int toNodeID = e->getConnections().size() > 0 ? getID(e->getToNode()->getID(), nodeMap, nodeID) : INVALID_ID; writeNormalEdge(device, e, getID(e->getID(), edgeMap, edgeID), fromNodeID, toNodeID, origNames, straightThresh); } device.lf(); // write junction-internal edges (road). In OpenDRIVE these are called 'paths' or 'connecting roads' OutputDevice_String junctionOSS(false, 3); for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NBNode* n = (*i).second; int connectionID = 0; // unique within a junction const int nID = getID(n->getID(), nodeMap, nodeID); if (n->numNormalConnections() > 0) { junctionOSS << " <junction name=\"" << n->getID() << "\" id=\"" << nID << "\">\n"; } std::vector<NBEdge*> incoming = (*i).second->getIncomingEdges(); if (lefthand) { std::reverse(incoming.begin(), incoming.end()); } for (NBEdge* inEdge : incoming) { std::string centerMark = "none"; const int inEdgeID = getID(inEdge->getID(), edgeMap, edgeID); // group parallel edges const NBEdge* outEdge = 0; bool isOuterEdge = true; // determine where a solid outer border should be drawn int lastFromLane = -1; std::vector<NBEdge::Connection> parallel; std::vector<NBEdge::Connection> connections = inEdge->getConnections(); if (lefthand) { std::reverse(connections.begin(), connections.end()); } for (const NBEdge::Connection& c : connections) { assert(c.toEdge != 0); if (outEdge != c.toEdge || c.fromLane == lastFromLane) { if (outEdge != 0) { if (isOuterEdge) { addPedestrianConnection(inEdge, outEdge, parallel); } connectionID = writeInternalEdge(device, junctionOSS, inEdge, nID, getID(parallel.back().getInternalLaneID(), edgeMap, edgeID), inEdgeID, getID(outEdge->getID(), edgeMap, edgeID), connectionID, parallel, isOuterEdge, straightThresh, centerMark); parallel.clear(); isOuterEdge = false; } outEdge = c.toEdge; } lastFromLane = c.fromLane; parallel.push_back(c); } if (isOuterEdge) { addPedestrianConnection(inEdge, outEdge, parallel); } if (!parallel.empty()) { if (!lefthand && (n->geometryLike() || inEdge->isTurningDirectionAt(outEdge))) { centerMark = "solid"; } connectionID = writeInternalEdge(device, junctionOSS, inEdge, nID, getID(parallel.back().getInternalLaneID(), edgeMap, edgeID), inEdgeID, getID(outEdge->getID(), edgeMap, edgeID), connectionID, parallel, isOuterEdge, straightThresh, centerMark); parallel.clear(); } } if (n->numNormalConnections() > 0) { junctionOSS << " </junction>\n"; } } device.lf(); // write junctions (junction) device << junctionOSS.getString(); for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NBNode* n = (*i).second; const std::vector<NBEdge*>& incoming = n->getIncomingEdges(); // check if any connections must be written int numConnections = 0; for (std::vector<NBEdge*>::const_iterator j = incoming.begin(); j != incoming.end(); ++j) { numConnections += (int)((*j)->getConnections().size()); } if (numConnections == 0) { continue; } for (std::vector<NBEdge*>::const_iterator j = incoming.begin(); j != incoming.end(); ++j) { const NBEdge* inEdge = *j; const std::vector<NBEdge::Connection>& elv = inEdge->getConnections(); for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) { const NBEdge::Connection& c = *k; const NBEdge* outEdge = c.toEdge; if (outEdge == 0) { continue; } } } } device.closeTag(); device.close(); }
// =========================================================================== // method definitions // =========================================================================== // --------------------------------------------------------------------------- // static methods (interface in this case) // --------------------------------------------------------------------------- void NIImporter_OpenDrive::loadNetwork(const OptionsCont &oc, NBNetBuilder &nb) { // check whether the option is set (properly) if (!oc.isUsableFileList("opendrive")) { return; } // build the handler std::vector<OpenDriveEdge> innerEdges, outerEdges; NIImporter_OpenDrive handler(nb.getNodeCont(), innerEdges, outerEdges); // parse file(s) std::vector<std::string> files = oc.getStringVector("opendrive"); for (std::vector<std::string>::const_iterator file=files.begin(); file!=files.end(); ++file) { if (!FileHelpers::exists(*file)) { MsgHandler::getErrorInstance()->inform("Could not open opendrive file '" + *file + "'."); return; } handler.setFileName(*file); MsgHandler::getMessageInstance()->beginProcessMsg("Parsing opendrive from '" + *file + "'..."); XMLSubSys::runParser(handler, *file); MsgHandler::getMessageInstance()->endProcessMsg("done."); } // convert geometries into a discretised representation computeShapes(innerEdges); computeShapes(outerEdges); // ------------------------- // node building // ------------------------- // build nodes#1 // look at all links which belong to a node, collect their bounding boxes // and place the node in the middle of this bounding box std::map<std::string, Boundary> posMap; std::map<std::string, std::string> edge2junction; // compute node positions for (std::vector<OpenDriveEdge>::iterator i=innerEdges.begin(); i!=innerEdges.end(); ++i) { OpenDriveEdge &e = *i; assert(e.junction!="-1" && e.junction!=""); edge2junction[e.id] = e.junction; if (posMap.find(e.junction)==posMap.end()) { posMap[e.junction] = Boundary(); } posMap[e.junction].add(e.geom.getBoxBoundary()); } // build nodes for (std::map<std::string, Boundary>::iterator i=posMap.begin(); i!=posMap.end(); ++i) { if (!nb.getNodeCont().insert((*i).first, (*i).second.getCenter())) { throw ProcessError("Could not add node '" + (*i).first + "'."); } } // assign built nodes for (std::vector<OpenDriveEdge>::iterator i=outerEdges.begin(); i!=outerEdges.end(); ++i) { OpenDriveEdge &e = *i; for (std::vector<OpenDriveLink>::iterator j=e.links.begin(); j!=e.links.end(); ++j) { OpenDriveLink &l = *j; if (l.elementType!=OPENDRIVE_ET_ROAD) { // set node information setNodeSecure(nb.getNodeCont(), e, l.elementID, l.linkType); continue; } if (edge2junction.find(l.elementID)!=edge2junction.end()) { // set node information of an internal road setNodeSecure(nb.getNodeCont(), e, edge2junction[l.elementID], l.linkType); continue; } } } // we should now have all nodes set for links which are not outer edge-to-outer edge links // build nodes#2 // build nodes for all outer edge-to-outer edge connections for (std::vector<OpenDriveEdge>::iterator i=outerEdges.begin(); i!=outerEdges.end(); ++i) { OpenDriveEdge &e = *i; for (std::vector<OpenDriveLink>::iterator j=e.links.begin(); j!=e.links.end(); ++j) { OpenDriveLink &l = *j; if (l.elementType!=OPENDRIVE_ET_ROAD || edge2junction.find(l.elementID)!=edge2junction.end()) { // is a connection to an internal edge, or a node, skip continue; } // we have a direct connection between to external edges std::string id1 = e.id; std::string id2 = l.elementID; if (id1<id2) { std::swap(id1, id2); } std::string nid = id1+"."+id2; if (nb.getNodeCont().retrieve(nid)==0) { // not yet seen, build Position2D pos = l.linkType==OPENDRIVE_LT_SUCCESSOR ? e.geom[(int)e.geom.size()-1] : e.geom[0]; if (!nb.getNodeCont().insert(nid, pos)) { throw ProcessError("Could not build node '" + nid + "'."); } } /* debug-stuff else { Position2D pos = l.linkType==OPENDRIVE_LT_SUCCESSOR ? e.geom[e.geom.size()-1] : e.geom[0]; cout << nid << " " << pos << " " << nb.getNodeCont().retrieve(nid)->getPosition() << endl; } */ setNodeSecure(nb.getNodeCont(), e, nid, l.linkType); } } // we should now have start/end nodes for all outer edge-to-outer edge connections // build nodes#3 // assign further nodes generated from inner-edges // these nodes have not been assigned earlier, because the connectiosn are referenced in inner-edges for (std::vector<OpenDriveEdge>::iterator i=outerEdges.begin(); i!=outerEdges.end(); ++i) { OpenDriveEdge &e = *i; if (e.to!=0&&e.from!=0) { continue; } for (std::vector<OpenDriveEdge>::iterator j=innerEdges.begin(); j!=innerEdges.end(); ++j) { OpenDriveEdge &ie = *j; for (std::vector<OpenDriveLink>::iterator k=ie.links.begin(); k!=ie.links.end(); ++k) { OpenDriveLink &il = *k; if (il.elementType!=OPENDRIVE_ET_ROAD || il.elementID!=e.id) { // not conneted to the currently investigated outer edge continue; } std::string nid = edge2junction[ie.id]; if (il.contactPoint==OPENDRIVE_CP_START) { setNodeSecure(nb.getNodeCont(), e, nid, OPENDRIVE_LT_PREDECESSOR); } else { setNodeSecure(nb.getNodeCont(), e, nid, OPENDRIVE_LT_SUCCESSOR); } } } } // // build start/end nodes which were not defined previously for (std::vector<OpenDriveEdge>::iterator i=outerEdges.begin(); i!=outerEdges.end(); ++i) { OpenDriveEdge &e = *i; if (e.from==0) { std::string nid = e.id + ".begin"; Position2D pos(e.geometries[0].x, e.geometries[0].y); e.from = getOrBuildNode(nid, e.geom[0], nb.getNodeCont()); } if (e.to==0) { std::string nid = e.id + ".end"; Position2D pos(e.geometries[e.geometries.size()-1].x, e.geometries[e.geometries.size()-1].y); e.to = getOrBuildNode(nid, e.geom[(int)e.geom.size()-1], nb.getNodeCont()); } } // ------------------------- // edge building // ------------------------- std::map<NBEdge*, std::map<int, int> > fromLaneMap; std::map<NBEdge*, std::map<int, int> > toLaneMap; // build edges for (std::vector<OpenDriveEdge>::iterator i=outerEdges.begin(); i!=outerEdges.end(); ++i) { OpenDriveEdge &e = *i; SUMOReal speed = nb.getTypeCont().getDefaultSpeed(); int priority = nb.getTypeCont().getDefaultPriority(); unsigned int nolanes = e.getMaxLaneNumber(SUMO_TAG_OPENDRIVE_RIGHT); if (nolanes>0) { NBEdge *nbe = new NBEdge("-" + e.id, e.from, e.to, "", speed, nolanes, priority, e.geom, NBEdge::LANESPREAD_RIGHT, true); if (!nb.getEdgeCont().insert(nbe)) { throw ProcessError("Could not add edge '" + std::string("-") + e.id + "'."); } fromLaneMap[nbe] = e.laneSections.back().buildLaneMapping(SUMO_TAG_OPENDRIVE_RIGHT); toLaneMap[nbe] = e.laneSections[0].buildLaneMapping(SUMO_TAG_OPENDRIVE_RIGHT); } nolanes = e.getMaxLaneNumber(SUMO_TAG_OPENDRIVE_LEFT); if (nolanes>0) { NBEdge *nbe = new NBEdge(e.id, e.to, e.from, "", speed, nolanes, priority, e.geom.reverse(), NBEdge::LANESPREAD_RIGHT, true); if (!nb.getEdgeCont().insert(nbe)) { throw ProcessError("Could not add edge '" + e.id + "'."); } fromLaneMap[nbe] = e.laneSections[0].buildLaneMapping(SUMO_TAG_OPENDRIVE_LEFT); toLaneMap[nbe] = e.laneSections.back().buildLaneMapping(SUMO_TAG_OPENDRIVE_LEFT); } } // ------------------------- // connections building // ------------------------- std::vector<Connection> connections; // connections#1 // build connections between outer-edges for (std::vector<OpenDriveEdge>::iterator i=outerEdges.begin(); i!=outerEdges.end(); ++i) { OpenDriveEdge &e = *i; for (std::vector<OpenDriveLink>::iterator j=e.links.begin(); j!=e.links.end(); ++j) { OpenDriveLink &l = *j; if (l.elementType!=OPENDRIVE_ET_ROAD) { // we are not interested in connections to nodes continue; } if (edge2junction.find(l.elementID)!=edge2junction.end()) { // connection via an inner-road addViaConnectionSecure(nb.getEdgeCont(), nb.getNodeCont().retrieve(edge2junction[l.elementID]), e, l.linkType, l.elementID, connections); } else { // connection between two outer-edges; can be used directly std::vector<OpenDriveEdge>::iterator p = std::find_if(outerEdges.begin(), outerEdges.end(), edge_by_id_finder(l.elementID)); if (p==outerEdges.end()) { throw ProcessError("Could not find connection edge."); } std::string id1 = e.id; std::string id2 = (*p).id; if (id1<id2) { std::swap(id1, id2); } std::string nid = id1+"."+id2; if (l.linkType==OPENDRIVE_LT_PREDECESSOR) { addE2EConnectionsSecure(nb.getEdgeCont(), nb.getNodeCont().retrieve(nid), *p, e, connections); } else { addE2EConnectionsSecure(nb.getEdgeCont(), nb.getNodeCont().retrieve(nid), e, *p, connections); } } } } /* for (std::vector<OpenDriveEdge>::iterator i=innerEdges.begin(); i!=innerEdges.end(); ++i) { OpenDriveEdge &e = *i; std::string pred, succ; ContactPoint predC, succC; for (std::vector<OpenDriveLink>::iterator j=e.links.begin(); j!=e.links.end(); ++j) { OpenDriveLink &l = *j; if (l.elementType!=OPENDRIVE_ET_ROAD) { // we are not interested in connections to nodes cout << "unsupported" << endl; continue; } if(edge2junction.find(l.elementID)!=edge2junction.end()) { // not supported cout << "unsupported" << endl; continue; } if(l.linkType==OPENDRIVE_LT_SUCCESSOR) { if(succ!="") { cout << "double succ" << endl; } succ = l.elementID; succC = l.contactPoint; } else { if(pred!="") { cout << "double pred" << endl; } pred = l.elementID; predC = l.contactPoint; } } if(e.getMaxLaneNumber(SUMO_TAG_OPENDRIVE_LEFT)!=0&&e.getMaxLaneNumber(SUMO_TAG_OPENDRIVE_RIGHT)!=0) { cout << "Both dirs given!" << endl; } bool isReversed = false; if(e.getMaxLaneNumber(SUMO_TAG_OPENDRIVE_LEFT)!=0) { // std::swap(pred, succ); //std::swap(predC, succC); isReversed = true; } if(succ==""||pred=="") { cout << "Missing edge." << endl; continue; // yes, occurs } NBNode *n = nb.getNodeCont().retrieve(edge2junction[e.id]); std::vector<OpenDriveEdge>::iterator predEdge = std::find_if(outerEdges.begin(), outerEdges.end(), edge_by_id_finder(pred)); if(predEdge==outerEdges.end()) { throw ProcessError("Could not find connection edge."); } std::vector<OpenDriveEdge>::iterator succEdge = std::find_if(outerEdges.begin(), outerEdges.end(), edge_by_id_finder(succ)); if(succEdge==outerEdges.end()) { throw ProcessError("Could not find connection edge."); } NBEdge *fromEdge, *toEdge; if(!isReversed) { fromEdge = predC==OPENDRIVE_CP_END ? nb.getEdgeCont().retrieve("-" + pred) : nb.getEdgeCont().retrieve(pred); toEdge = succC==OPENDRIVE_CP_START ? nb.getEdgeCont().retrieve("-" + succ) : nb.getEdgeCont().retrieve(succ); } else { fromEdge = predC!=OPENDRIVE_CP_END ? nb.getEdgeCont().retrieve("-" + pred) : nb.getEdgeCont().retrieve(pred); toEdge = succC!=OPENDRIVE_CP_START ? nb.getEdgeCont().retrieve("-" + succ) : nb.getEdgeCont().retrieve(succ); } /* Connection c( n->hasIncoming(nb.getEdgeCont().retrieve("-" + pred)) ? nb.getEdgeCont().retrieve("-" + pred) : nb.getEdgeCont().retrieve(pred), e.id, n->hasOutgoing(nb.getEdgeCont().retrieve("-" + succ)) ? nb.getEdgeCont().retrieve("-" + succ) : nb.getEdgeCont().retrieve(succ)); / Connection c(fromEdge, e.id, toEdge); if(c.from==0||c.to==0||c.from==c.to) { throw ProcessError("Something's false"); } setLaneConnections(c, *predEdge, c.from->getID()[0]!='-', c.from->getID()[0]=='-' ? SUMO_TAG_OPENDRIVE_RIGHT : SUMO_TAG_OPENDRIVE_LEFT, e, isReversed, !isReversed ? SUMO_TAG_OPENDRIVE_RIGHT : SUMO_TAG_OPENDRIVE_LEFT, *succEdge, c.to->getID()[0]!='-', c.to->getID()[0]=='-' ? SUMO_TAG_OPENDRIVE_RIGHT : SUMO_TAG_OPENDRIVE_LEFT); connections.push_back(c); } */ for (std::vector<Connection>::const_iterator i=connections.begin(); i!=connections.end(); ++i) { if ((*i).from==0 || (*i).to==0) { std::cout << "Nope." << std::endl; continue; } (*i).from->addEdge2EdgeConnection((*i).to); std::map<int, int> fromMap = fromLaneMap[(*i).from]; std::map<int, int> toMap = fromLaneMap[(*i).to]; for (std::vector<std::pair<int, int> >::const_iterator j=(*i).lanes.begin(); j!=(*i).lanes.end(); ++j) { int fromLane = fromMap[(*j).first]; int toLane = toMap[(*j).second]; if (static_cast<unsigned int>(fromLane)>=(*i).from->getNoLanes()||fromLane<0) { std::cout << "False " << std::endl; } if (static_cast<unsigned int>(toLane)>=(*i).to->getNoLanes()||toLane<0) { std::cout << "False " << std::endl; } (*i).from->addLane2LaneConnection(fromLane, (*i).to, toLane, NBEdge::L2L_VALIDATED, true); } } }
void NIImporter_OpenStreetMap::_loadNetwork(const OptionsCont& oc, NBNetBuilder& nb) { // check whether the option is set (properly) if (!oc.isSet("osm-files")) { return; } // preset types // for highways NBTypeCont& tc = nb.getTypeCont(); SUMOReal const WIDTH = NBEdge::UNSPECIFIED_WIDTH; tc.insert("highway.motorway", 3, (SUMOReal)(160./ 3.6), 13, WIDTH, SVC_UNKNOWN, true); tc.insert("highway.motorway_link", 1, (SUMOReal)(80. / 3.6), 12, WIDTH, SVC_UNKNOWN, true); tc.insert("highway.trunk", 2, (SUMOReal)(100./ 3.6), 11, WIDTH); // !!! 130km/h? tc.insert("highway.trunk_link", 1, (SUMOReal)(80. / 3.6), 10, WIDTH); tc.insert("highway.primary", 2, (SUMOReal)(100./ 3.6), 9, WIDTH); tc.insert("highway.primary_link", 1, (SUMOReal)(80. / 3.6), 8, WIDTH); tc.insert("highway.secondary", 2, (SUMOReal)(100./ 3.6), 7, WIDTH); tc.insert("highway.secondary_link",1, (SUMOReal)(80. / 3.6), 6, WIDTH); tc.insert("highway.tertiary", 1, (SUMOReal)(80. / 3.6), 6, WIDTH); tc.insert("highway.tertiary_link", 1, (SUMOReal)(80. / 3.6), 5, WIDTH); tc.insert("highway.unclassified", 1, (SUMOReal)(80. / 3.6), 5, WIDTH); tc.insert("highway.residential", 1, (SUMOReal)(50. / 3.6), 4, WIDTH); // actually, maybe one lane for parking would be nice... tc.insert("highway.living_street", 1, (SUMOReal)(10. / 3.6), 3, WIDTH); tc.insert("highway.service", 1, (SUMOReal)(20. / 3.6), 2, WIDTH, SVC_DELIVERY); tc.insert("highway.track", 1, (SUMOReal)(20. / 3.6), 1, WIDTH); tc.insert("highway.services", 1, (SUMOReal)(30. / 3.6), 1, WIDTH); tc.insert("highway.unsurfaced", 1, (SUMOReal)(30. / 3.6), 1, WIDTH); // unofficial value, used outside germany tc.insert("highway.footway", 1, (SUMOReal)(30. / 3.6), 1, WIDTH, SVC_PEDESTRIAN); tc.insert("highway.pedestrian", 1, (SUMOReal)(30. / 3.6), 1, WIDTH, SVC_PEDESTRIAN); tc.insert("highway.path", 1, (SUMOReal)(10. / 3.6), 1, WIDTH, SVC_PEDESTRIAN); tc.insert("highway.bridleway", 1, (SUMOReal)(10. / 3.6), 1, WIDTH, SVC_BICYCLE); // no horse stuff tc.insert("highway.cycleway", 1, (SUMOReal)(20. / 3.6), 1, WIDTH, SVC_BICYCLE); tc.insert("highway.footway", 1, (SUMOReal)(10. / 3.6), 1, WIDTH, SVC_PEDESTRIAN); tc.insert("highway.step", 1, (SUMOReal)(5. / 3.6), 1, WIDTH, SVC_PEDESTRIAN); // additional tc.insert("highway.steps", 1, (SUMOReal)(5. / 3.6), 1, WIDTH, SVC_PEDESTRIAN); // :-) do not run too fast tc.insert("highway.stairs", 1, (SUMOReal)(5. / 3.6), 1, WIDTH, SVC_PEDESTRIAN); // additional tc.insert("highway.bus_guideway", 1, (SUMOReal)(30. / 3.6), 1, WIDTH, SVC_BUS); tc.insert("highway.raceway", 2, (SUMOReal)(300./ 3.6), 14, WIDTH, SVC_VIP); tc.insert("highway.ford", 1, (SUMOReal)(10. / 3.6), 1, WIDTH, SVC_PUBLIC_ARMY); // for railways tc.insert("railway.rail", 1, (SUMOReal)(30. / 3.6), 1, WIDTH, SVC_RAIL_FAST); tc.insert("railway.tram", 1, (SUMOReal)(30. / 3.6), 1, WIDTH, SVC_CITYRAIL); tc.insert("railway.light_rail", 1, (SUMOReal)(30. / 3.6), 1, WIDTH, SVC_LIGHTRAIL); tc.insert("railway.subway", 1, (SUMOReal)(30. / 3.6), 1, WIDTH, SVC_CITYRAIL); tc.insert("railway.preserved", 1, (SUMOReal)(30. / 3.6), 1, WIDTH, SVC_LIGHTRAIL); tc.insert("railway.monorail", 1, (SUMOReal)(30. / 3.6), 1, WIDTH, SVC_LIGHTRAIL); // rail stuff has to be discussed /* Parse file(s) * Each file is parsed twice: first for nodes, second for edges. */ std::vector<std::string> files = oc.getStringVector("osm-files"); // load nodes, first NodesHandler nodesHandler(myOSMNodes, myUniqueNodes); for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) { // nodes if (!FileHelpers::exists(*file)) { WRITE_ERROR("Could not open osm-file '" + *file + "'."); return; } nodesHandler.setFileName(*file); PROGRESS_BEGIN_MESSAGE("Parsing nodes from osm-file '" + *file + "'"); if (!XMLSubSys::runParser(nodesHandler, *file)) { return; } PROGRESS_DONE_MESSAGE(); } // load edges, then EdgesHandler edgesHandler(myOSMNodes, myEdges); for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) { // edges edgesHandler.setFileName(*file); PROGRESS_BEGIN_MESSAGE("Parsing edges from osm-file '" + *file + "'"); XMLSubSys::runParser(edgesHandler, *file); PROGRESS_DONE_MESSAGE(); } /* Remove duplicate edges with the same shape and attributes */ if (!OptionsCont::getOptions().getBool("osm.skip-duplicates-check")) { PROGRESS_BEGIN_MESSAGE("Removing duplicate edges"); if (myEdges.size() > 1) { std::set<const Edge*, CompareEdges> dupsFinder; for (std::map<std::string, Edge*>::iterator it = myEdges.begin(); it != myEdges.end();) { if (dupsFinder.count(it->second) > 0) { WRITE_MESSAGE("Found duplicate edges. Removing " + it->first); delete it->second; myEdges.erase(it++); } else { dupsFinder.insert(it->second); it++; } } } PROGRESS_DONE_MESSAGE(); } /* Mark which nodes are used (by edges or traffic lights). * This is necessary to detect which OpenStreetMap nodes are for * geometry only */ std::map<int, int> nodeUsage; // Mark which nodes are used by edges (begin and end) for (std::map<std::string, Edge*>::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) { Edge* e = (*i).second; assert(e->myCurrentIsRoad); for (std::vector<int>::const_iterator j = e->myCurrentNodes.begin(); j != e->myCurrentNodes.end(); ++j) { if (nodeUsage.find(*j) == nodeUsage.end()) { nodeUsage[*j] = 0; } nodeUsage[*j] = nodeUsage[*j] + 1; } } // Mark which nodes are used by traffic lights for (std::map<int, NIOSMNode*>::const_iterator nodesIt = myOSMNodes.begin(); nodesIt != myOSMNodes.end(); ++nodesIt) { if (nodesIt->second->tlsControlled) { // If the key is not found in the map, the value is automatically // initialized with 0. nodeUsage[nodesIt->first] += 1; } } /* Instantiate edges * Only those nodes in the middle of an edge which are used by more than * one edge are instantiated. Other nodes are considered as geometry nodes. */ NBNodeCont& nc = nb.getNodeCont(); NBEdgeCont& ec = nb.getEdgeCont(); NBTrafficLightLogicCont& tlsc = nb.getTLLogicCont(); for (std::map<std::string, Edge*>::iterator i = myEdges.begin(); i != myEdges.end(); ++i) { Edge* e = (*i).second; assert(e->myCurrentIsRoad); // build nodes; // the from- and to-nodes must be built in any case // the geometry nodes are only built if more than one edge references them NBNode* currentFrom = insertNodeChecking(*e->myCurrentNodes.begin(), nc, tlsc); NBNode* last = insertNodeChecking(*(e->myCurrentNodes.end() - 1), nc, tlsc); int running = 0; std::vector<int> passed; for (std::vector<int>::iterator j = e->myCurrentNodes.begin(); j != e->myCurrentNodes.end(); ++j) { passed.push_back(*j); if (nodeUsage[*j] > 1 && j != e->myCurrentNodes.end() - 1 && j != e->myCurrentNodes.begin()) { NBNode* currentTo = insertNodeChecking(*j, nc, tlsc); insertEdge(e, running, currentFrom, currentTo, passed, ec, tc); currentFrom = currentTo; running++; passed.clear(); } } if (running == 0) { running = -1; } insertEdge(e, running, currentFrom, last, passed, ec, tc); } }
// =========================================================================== // method definitions // =========================================================================== // --------------------------------------------------------------------------- // static methods // --------------------------------------------------------------------------- void NWWriter_SUMO::writeNetwork(const OptionsCont& oc, NBNetBuilder& nb) { // check whether a sumo net-file shall be generated if (!oc.isSet("output-file")) { return; } OutputDevice& device = OutputDevice::getDevice(oc.getString("output-file")); const std::string lefthand = oc.getBool("lefthand") ? " " + toString(SUMO_ATTR_LEFTHAND) + "=\"true\"" : ""; const int cornerDetail = oc.getInt("junctions.corner-detail"); const int linkDetail = oc.getInt("junctions.internal-link-detail"); const std::string junctionCornerDetail = (cornerDetail > 0 ? " " + toString(SUMO_ATTR_CORNERDETAIL) + "=\"" + toString(cornerDetail) + "\"" : ""); const std::string junctionLinkDetail = (oc.isDefault("junctions.internal-link-detail") ? "" : " " + toString(SUMO_ATTR_LINKDETAIL) + "=\"" + toString(linkDetail) + "\""); device.writeXMLHeader("net", NWFrame::MAJOR_VERSION + lefthand + junctionCornerDetail + junctionLinkDetail + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo.dlr.de/xsd/net_file.xsd\""); // street names may contain non-ascii chars device.lf(); // get involved container const NBNodeCont& nc = nb.getNodeCont(); const NBEdgeCont& ec = nb.getEdgeCont(); const NBDistrictCont& dc = nb.getDistrictCont(); // write network offsets and projection GeoConvHelper::writeLocation(device); // write edge types and restrictions nb.getTypeCont().writeTypes(device); // write inner lanes bool origNames = oc.getBool("output.original-names"); if (!oc.getBool("no-internal-links")) { bool hadAny = false; for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { hadAny |= writeInternalEdges(device, *(*i).second, origNames); } if (hadAny) { device.lf(); } } // write edges with lanes and connected edges bool noNames = !oc.getBool("output.street-names"); for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) { writeEdge(device, *(*i).second, noNames, origNames); } device.lf(); // write tls logics writeTrafficLights(device, nb.getTLLogicCont()); // write the nodes (junctions) std::set<NBNode*> roundaboutNodes; const bool checkLaneFoesAll = oc.getBool("check-lane-foes.all"); const bool checkLaneFoesRoundabout = !checkLaneFoesAll && oc.getBool("check-lane-foes.roundabout"); if (checkLaneFoesRoundabout) { const std::set<EdgeSet>& roundabouts = ec.getRoundabouts(); for (std::set<EdgeSet>::const_iterator i = roundabouts.begin(); i != roundabouts.end(); ++i) { for (EdgeSet::const_iterator j = (*i).begin(); j != (*i).end(); ++j) { roundaboutNodes.insert((*j)->getToNode()); } } } for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { const bool checkLaneFoes = checkLaneFoesAll || (checkLaneFoesRoundabout && roundaboutNodes.count((*i).second) > 0); writeJunction(device, *(*i).second, checkLaneFoes); } device.lf(); const bool includeInternal = !oc.getBool("no-internal-links"); if (includeInternal) { // ... internal nodes if not unwanted bool hadAny = false; for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { hadAny |= writeInternalNodes(device, *(*i).second); } if (hadAny) { device.lf(); } } // write the successors of lanes unsigned int numConnections = 0; for (std::map<std::string, NBEdge*>::const_iterator it_edge = ec.begin(); it_edge != ec.end(); it_edge++) { NBEdge* from = it_edge->second; from->sortOutgoingConnectionsByIndex(); const std::vector<NBEdge::Connection> connections = from->getConnections(); numConnections += (unsigned int)connections.size(); for (std::vector<NBEdge::Connection>::const_iterator it_c = connections.begin(); it_c != connections.end(); it_c++) { writeConnection(device, *from, *it_c, includeInternal); } } if (numConnections > 0) { device.lf(); } if (includeInternal) { // ... internal successors if not unwanted bool hadAny = false; for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { hadAny |= writeInternalConnections(device, *(*i).second); } if (hadAny) { device.lf(); } } for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NBNode* node = (*i).second; // write connections from pedestrian crossings const std::vector<NBNode::Crossing>& crossings = node->getCrossings(); for (std::vector<NBNode::Crossing>::const_iterator it = crossings.begin(); it != crossings.end(); it++) { NWWriter_SUMO::writeInternalConnection(device, (*it).id, (*it).nextWalkingArea, 0, 0, ""); } // write connections from pedestrian walking areas const std::vector<NBNode::WalkingArea>& WalkingAreas = node->getWalkingAreas(); for (std::vector<NBNode::WalkingArea>::const_iterator it = WalkingAreas.begin(); it != WalkingAreas.end(); it++) { if ((*it).nextCrossing != "") { const NBNode::Crossing& nextCrossing = node->getCrossing((*it).nextCrossing); // connection to next crossing (may be tls-controlled) device.openTag(SUMO_TAG_CONNECTION); device.writeAttr(SUMO_ATTR_FROM, (*it).id); device.writeAttr(SUMO_ATTR_TO, (*it).nextCrossing); device.writeAttr(SUMO_ATTR_FROM_LANE, 0); device.writeAttr(SUMO_ATTR_TO_LANE, 0); if (node->isTLControlled()) { device.writeAttr(SUMO_ATTR_TLID, (*node->getControllingTLS().begin())->getID()); assert(nextCrossing.tlLinkNo >= 0); device.writeAttr(SUMO_ATTR_TLLINKINDEX, nextCrossing.tlLinkNo); } device.writeAttr(SUMO_ATTR_DIR, LINKDIR_STRAIGHT); device.writeAttr(SUMO_ATTR_STATE, nextCrossing.priority ? LINKSTATE_MAJOR : LINKSTATE_MINOR); device.closeTag(); } // optional connections from/to sidewalk for (std::vector<std::string>::const_iterator it_sw = (*it).nextSidewalks.begin(); it_sw != (*it).nextSidewalks.end(); ++it_sw) { NWWriter_SUMO::writeInternalConnection(device, (*it).id, (*it_sw), 0, 0, ""); } for (std::vector<std::string>::const_iterator it_sw = (*it).prevSidewalks.begin(); it_sw != (*it).prevSidewalks.end(); ++it_sw) { NWWriter_SUMO::writeInternalConnection(device, (*it_sw), (*it).id, 0, 0, ""); } } } // write loaded prohibitions for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { writeProhibitions(device, i->second->getProhibitions()); } // write roundabout information writeRoundabouts(device, ec.getRoundabouts(), ec); // write the districts for (std::map<std::string, NBDistrict*>::const_iterator i = dc.begin(); i != dc.end(); i++) { writeDistrict(device, *(*i).second); } if (dc.size() != 0) { device.lf(); } device.close(); }
// =========================================================================== // method definitions // =========================================================================== // --------------------------------------------------------------------------- // static methods // --------------------------------------------------------------------------- void NWWriter_OpenDrive::writeNetwork(const OptionsCont& oc, NBNetBuilder& nb) { // check whether an opendrive-file shall be generated if (!oc.isSet("opendrive-output")) { return; } const NBNodeCont& nc = nb.getNodeCont(); const NBEdgeCont& ec = nb.getEdgeCont(); const bool origNames = oc.getBool("output.original-names"); const SUMOReal straightThresh = DEG2RAD(oc.getFloat("opendrive-output.straight-threshold")); // some internal mapping containers int nodeID = 1; int edgeID = nc.size() * 10; // distinct from node ids StringBijection<int> edgeMap; StringBijection<int> nodeMap; // OutputDevice& device = OutputDevice::getDevice(oc.getString("opendrive-output")); device << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; device.openTag("OpenDRIVE"); time_t now = time(0); std::string dstr(ctime(&now)); const Boundary& b = GeoConvHelper::getFinal().getConvBoundary(); // write header device.openTag("header"); device.writeAttr("revMajor", "1"); device.writeAttr("revMinor", "4"); device.writeAttr("name", ""); device.writeAttr("version", "1.00"); device.writeAttr("date", dstr.substr(0, dstr.length() - 1)); device.writeAttr("north", b.ymax()); device.writeAttr("south", b.ymin()); device.writeAttr("east", b.xmax()); device.writeAttr("west", b.xmin()); /* @note obsolete in 1.4 device.writeAttr("maxRoad", ec.size()); device.writeAttr("maxJunc", nc.size()); device.writeAttr("maxPrg", 0); */ device.closeTag(); // write normal edges (road) for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) { const NBEdge* e = (*i).second; // buffer output because some fields are computed out of order OutputDevice_String elevationOSS(false, 3); elevationOSS.setPrecision(8); OutputDevice_String planViewOSS(false, 2); planViewOSS.setPrecision(8); SUMOReal length = 0; planViewOSS.openTag("planView"); planViewOSS.setPrecision(8); // geometry hdg requires higher precision // for the shape we need to use the leftmost border of the leftmost lane const std::vector<NBEdge::Lane>& lanes = e->getLanes(); PositionVector ls = getLeftLaneBorder(e); #ifdef DEBUG_SMOOTH_GEOM if (DEBUGCOND) { std::cout << "write planview for edge " << e->getID() << "\n"; } #endif if (ls.size() == 2 || e->getPermissions() == SVC_PEDESTRIAN) { // foot paths may contain sharp angles length = writeGeomLines(ls, planViewOSS, elevationOSS); } else { bool ok = writeGeomSmooth(ls, e->getSpeed(), planViewOSS, elevationOSS, straightThresh, length); if (!ok) { WRITE_WARNING("Could not compute smooth shape for edge '" + e->getID() + "'."); } } planViewOSS.closeTag(); device.openTag("road"); device.writeAttr("name", StringUtils::escapeXML(e->getStreetName())); device.setPrecision(8); // length requires higher precision device.writeAttr("length", MAX2(POSITION_EPS, length)); device.setPrecision(OUTPUT_ACCURACY); device.writeAttr("id", getID(e->getID(), edgeMap, edgeID)); device.writeAttr("junction", -1); const bool hasSucc = e->getConnections().size() > 0; const bool hasPred = e->getIncomingEdges().size() > 0; if (hasPred || hasSucc) { device.openTag("link"); if (hasPred) { device.openTag("predecessor"); device.writeAttr("elementType", "junction"); device.writeAttr("elementId", getID(e->getFromNode()->getID(), nodeMap, nodeID)); device.closeTag(); } if (hasSucc) { device.openTag("successor"); device.writeAttr("elementType", "junction"); device.writeAttr("elementId", getID(e->getToNode()->getID(), nodeMap, nodeID)); device.closeTag(); } device.closeTag(); } device.openTag("type").writeAttr("s", 0).writeAttr("type", "town").closeTag(); device << planViewOSS.getString(); writeElevationProfile(ls, device, elevationOSS); device << " <lateralProfile/>\n"; device << " <lanes>\n"; device << " <laneSection s=\"0\">\n"; writeEmptyCenterLane(device, "solid", 0.13); device << " <right>\n"; for (int j = e->getNumLanes(); --j >= 0;) { device << " <lane id=\"-" << e->getNumLanes() - j << "\" type=\"" << getLaneType(e->getPermissions(j)) << "\" level=\"true\">\n"; device << " <link/>\n"; // this could be used for geometry-link junctions without u-turn, // predecessor and sucessors would be lane indices, // road predecessor / succesfors would be of type 'road' rather than // 'junction' //device << " <predecessor id=\"-1\"/>\n"; //device << " <successor id=\"-1\"/>\n"; //device << " </link>\n"; device << " <width sOffset=\"0\" a=\"" << e->getLaneWidth(j) << "\" b=\"0\" c=\"0\" d=\"0\"/>\n"; std::string markType = "broken"; if (j == 0) { markType = "solid"; } device << " <roadMark sOffset=\"0\" type=\"" << markType << "\" weight=\"standard\" color=\"standard\" width=\"0.13\"/>\n"; device << " <speed sOffset=\"0\" max=\"" << lanes[j].speed << "\"/>\n"; device << " </lane>\n"; } device << " </right>\n"; device << " </laneSection>\n"; device << " </lanes>\n"; device << " <objects/>\n"; device << " <signals/>\n"; if (origNames) { device << " <userData code=\"sumoId\" value=\"" << e->getID() << "\"/>\n"; } device.closeTag(); checkLaneGeometries(e); } device.lf(); // write junction-internal edges (road). In OpenDRIVE these are called 'paths' or 'connecting roads' for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NBNode* n = (*i).second; const std::vector<NBEdge*>& incoming = (*i).second->getIncomingEdges(); for (std::vector<NBEdge*>::const_iterator j = incoming.begin(); j != incoming.end(); ++j) { const NBEdge* inEdge = *j; const std::vector<NBEdge::Connection>& elv = inEdge->getConnections(); for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) { const NBEdge::Connection& c = *k; const NBEdge* outEdge = c.toEdge; if (outEdge == 0) { continue; } const SUMOReal width = c.toEdge->getLaneWidth(c.toLane); const PositionVector begShape = getLeftLaneBorder(inEdge, c.fromLane); const PositionVector endShape = getLeftLaneBorder(outEdge, c.toLane); //std::cout << "computing reference line for internal lane " << c.getInternalLaneID() << " begLane=" << inEdge->getLaneShape(c.fromLane) << " endLane=" << outEdge->getLaneShape(c.toLane) << "\n"; SUMOReal length; PositionVector fallBackShape; fallBackShape.push_back(begShape.back()); fallBackShape.push_back(endShape.front()); const bool turnaround = inEdge->isTurningDirectionAt(outEdge); bool ok = true; PositionVector init = NBNode::bezierControlPoints(begShape, endShape, turnaround, 25, 25, ok, 0, straightThresh); if (init.size() == 0) { length = fallBackShape.length2D(); // problem with turnarounds is known, method currently returns 'ok' (#2539) if (!ok) { WRITE_WARNING("Could not compute smooth shape from lane '" + inEdge->getLaneID(c.fromLane) + "' to lane '" + outEdge->getLaneID(c.toLane) + "'. Use option 'junctions.scurve-stretch' or increase radius of junction '" + inEdge->getToNode()->getID() + "' to fix this."); } } else { length = bezier(init, 12).length2D(); } device.openTag("road"); device.writeAttr("name", c.getInternalLaneID()); device.setPrecision(8); // length requires higher precision device.writeAttr("length", MAX2(POSITION_EPS, length)); device.setPrecision(OUTPUT_ACCURACY); device.writeAttr("id", getID(c.getInternalLaneID(), edgeMap, edgeID)); device.writeAttr("junction", getID(n->getID(), nodeMap, nodeID)); device.openTag("link"); device.openTag("predecessor"); device.writeAttr("elementType", "road"); device.writeAttr("elementId", getID(inEdge->getID(), edgeMap, edgeID)); device.writeAttr("contactPoint", "end"); device.closeTag(); device.openTag("successor"); device.writeAttr("elementType", "road"); device.writeAttr("elementId", getID(outEdge->getID(), edgeMap, edgeID)); device.writeAttr("contactPoint", "start"); device.closeTag(); device.closeTag(); device.openTag("type").writeAttr("s", 0).writeAttr("type", "town").closeTag(); device.openTag("planView"); device.setPrecision(8); // geometry hdg requires higher precision OutputDevice_String elevationOSS(false, 3); #ifdef DEBUG_SMOOTH_GEOM if (DEBUGCOND) { std::cout << "write planview for internal edge " << c.getInternalLaneID() << " init=" << init << " fallback=" << fallBackShape << "\n"; } #endif if (init.size() == 0) { writeGeomLines(fallBackShape, device, elevationOSS); } else { writeGeomPP3(device, elevationOSS, init, length); } device.setPrecision(OUTPUT_ACCURACY); device.closeTag(); writeElevationProfile(fallBackShape, device, elevationOSS); device << " <lateralProfile/>\n"; device << " <lanes>\n"; device << " <laneSection s=\"0\">\n"; writeEmptyCenterLane(device, "none", 0); device << " <right>\n"; device << " <lane id=\"-1\" type=\"" << getLaneType(outEdge->getPermissions(c.toLane)) << "\" level=\"true\">\n"; device << " <link>\n"; device << " <predecessor id=\"-" << inEdge->getNumLanes() - c.fromLane << "\"/>\n"; device << " <successor id=\"-" << outEdge->getNumLanes() - c.toLane << "\"/>\n"; device << " </link>\n"; device << " <width sOffset=\"0\" a=\"" << width << "\" b=\"0\" c=\"0\" d=\"0\"/>\n"; device << " <roadMark sOffset=\"0\" type=\"none\" weight=\"standard\" color=\"standard\" width=\"0.13\"/>\n"; device << " </lane>\n"; device << " </right>\n"; device << " </laneSection>\n"; device << " </lanes>\n"; device << " <objects/>\n"; device << " <signals/>\n"; device.closeTag(); } } } // write junctions (junction) for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NBNode* n = (*i).second; const std::vector<NBEdge*>& incoming = n->getIncomingEdges(); // check if any connections must be written int numConnections = 0; for (std::vector<NBEdge*>::const_iterator j = incoming.begin(); j != incoming.end(); ++j) { numConnections += (int)((*j)->getConnections().size()); } if (numConnections == 0) { continue; } device << " <junction name=\"" << n->getID() << "\" id=\"" << getID(n->getID(), nodeMap, nodeID) << "\">\n"; int index = 0; for (std::vector<NBEdge*>::const_iterator j = incoming.begin(); j != incoming.end(); ++j) { const NBEdge* inEdge = *j; const std::vector<NBEdge::Connection>& elv = inEdge->getConnections(); for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) { const NBEdge::Connection& c = *k; const NBEdge* outEdge = c.toEdge; if (outEdge == 0) { continue; } device << " <connection id=\"" << index << "\" incomingRoad=\"" << getID(inEdge->getID(), edgeMap, edgeID) << "\" connectingRoad=\"" << getID(c.getInternalLaneID(), edgeMap, edgeID) << "\" contactPoint=\"start\">\n"; device << " <laneLink from=\"-" << inEdge->getNumLanes() - c.fromLane << "\" to=\"-1" // every connection has its own edge << "\"/>\n"; device << " </connection>\n"; ++index; } } device << " </junction>\n"; } device.closeTag(); device.close(); }
// =========================================================================== // method definitions // =========================================================================== // --------------------------------------------------------------------------- // static methods // --------------------------------------------------------------------------- void NWWriter_Amitran::writeNetwork(const OptionsCont& oc, NBNetBuilder& nb) { // check whether an amitran-file shall be generated if (!oc.isSet("amitran-output")) { return; } OutputDevice& device = OutputDevice::getDevice(oc.getString("amitran-output")); device << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; device << "<network xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo-sim.org/xsd/amitran/network.xsd\">\n"; // write nodes int index = 0; NBNodeCont& nc = nb.getNodeCont(); std::set<NBNode*> singleRoundaboutNodes; std::set<NBNode*> multiRoundaboutNodes; const std::vector<EdgeVector>& roundabouts = nb.getRoundabouts(); for (std::vector<EdgeVector>::const_iterator i = roundabouts.begin(); i != roundabouts.end(); ++i) { for (EdgeVector::const_iterator j = (*i).begin(); j != (*i).end(); ++j) { if ((*j)->getNumLanes() > 1) { multiRoundaboutNodes.insert((*j)->getFromNode()); } else { singleRoundaboutNodes.insert((*j)->getFromNode()); } } } std::map<NBNode*, int> nodeIds; for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { device << " <node id=\"" << index; nodeIds[i->second] = index++; if (singleRoundaboutNodes.count(i->second) > 0) { device << "\" type=\"roundaboutSingle\"/>\n"; continue; } if (multiRoundaboutNodes.count(i->second) > 0) { device << "\" type=\"roundaboutMulti\"/>\n"; continue; } switch (i->second->getType()) { case NODETYPE_TRAFFIC_LIGHT: case NODETYPE_TRAFFIC_LIGHT_NOJUNCTION: device << "\" type=\"trafficLight"; break; case NODETYPE_PRIORITY: device << "\" type=\"priority"; break; case NODETYPE_PRIORITY_STOP: device << "\" type=\"priorityStop"; break; case NODETYPE_RIGHT_BEFORE_LEFT: device << "\" type=\"rightBeforeLeft"; break; case NODETYPE_ALLWAY_STOP: device << "\" type=\"allwayStop"; break; case NODETYPE_DEAD_END: case NODETYPE_DEAD_END_DEPRECATED: device << "\" type=\"deadEnd"; break; case NODETYPE_DISTRICT: case NODETYPE_NOJUNCTION: case NODETYPE_INTERNAL: case NODETYPE_UNKNOWN: break; } device << "\"/>\n"; } // write edges index = 0; NBEdgeCont& ec = nb.getEdgeCont(); for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) { device << " <link id=\"" << index++ << "\" from=\"" << nodeIds[i->second->getFromNode()] << "\" to=\"" << nodeIds[i->second->getToNode()] << "\" roadClass=\"" << NWWriter_DlrNavteq::getRoadClass((*i).second) << "\" length=\"" << int(1000 * i->second->getLoadedLength()) << "\" speedLimitKmh=\"" << int(3.6 * (*i).second->getSpeed() + 0.5) << "\" laneNr=\"" << (*i).second->getNumLanes() << "\"/>\n"; } device << "</network>\n"; device.close(); }
// =========================================================================== // method definitions // =========================================================================== // --------------------------------------------------------------------------- // static methods // --------------------------------------------------------------------------- void NWWriter_SUMO::writeNetwork(const OptionsCont& oc, NBNetBuilder& nb) { // check whether a sumo net-file shall be generated if (!oc.isSet("output-file")) { return; } OutputDevice& device = OutputDevice::getDevice(oc.getString("output-file")); device.writeXMLHeader("net", NWFrame::MAJOR_VERSION + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo.sf.net/xsd/net_file.xsd\""); // street names may contain non-ascii chars device.lf(); // get involved container const NBNodeCont& nc = nb.getNodeCont(); const NBEdgeCont& ec = nb.getEdgeCont(); const NBDistrictCont& dc = nb.getDistrictCont(); // write network offsets and projection writeLocation(device); // write inner lanes bool origNames = oc.getBool("output.original-names"); if (!oc.getBool("no-internal-links")) { bool hadAny = false; for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { hadAny |= writeInternalEdges(device, *(*i).second, origNames); } if (hadAny) { device.lf(); } } // write edges with lanes and connected edges bool noNames = !oc.getBool("output.street-names"); for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) { writeEdge(device, *(*i).second, noNames, origNames); } device.lf(); // write tls logics writeTrafficLights(device, nb.getTLLogicCont()); // write the nodes (junctions) for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { writeJunction(device, *(*i).second); } device.lf(); const bool includeInternal = !oc.getBool("no-internal-links"); if (includeInternal) { // ... internal nodes if not unwanted bool hadAny = false; for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { hadAny |= writeInternalNodes(device, *(*i).second); } if (hadAny) { device.lf(); } } // write the successors of lanes unsigned int numConnections = 0; for (std::map<std::string, NBEdge*>::const_iterator it_edge = ec.begin(); it_edge != ec.end(); it_edge++) { NBEdge* from = it_edge->second; from->sortOutgoingConnectionsByIndex(); const std::vector<NBEdge::Connection> connections = from->getConnections(); numConnections += (unsigned int)connections.size(); for (std::vector<NBEdge::Connection>::const_iterator it_c = connections.begin(); it_c != connections.end(); it_c++) { writeConnection(device, *from, *it_c, includeInternal); } } if (numConnections > 0) { device.lf(); } if (includeInternal) { // ... internal successors if not unwanted bool hadAny = false; for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { hadAny |= writeInternalConnections(device, *(*i).second); } if (hadAny) { device.lf(); } } // write loaded prohibitions for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { writeProhibitions(device, i->second->getProhibitions()); } // write roundabout information const std::vector<EdgeVector>& roundabouts = nb.getRoundabouts(); for (std::vector<EdgeVector>::const_iterator i = roundabouts.begin(); i != roundabouts.end(); ++i) { writeRoundabout(device, *i); } if (roundabouts.size() != 0) { device.lf(); } // write the districts for (std::map<std::string, NBDistrict*>::const_iterator i = dc.begin(); i != dc.end(); i++) { writeDistrict(device, *(*i).second); } if (dc.size() != 0) { device.lf(); } device.close(); }
// =========================================================================== // method definitions // =========================================================================== // --------------------------------------------------------------------------- // static methods // --------------------------------------------------------------------------- void NIImporter_DlrNavteq::loadNetwork(const OptionsCont& oc, NBNetBuilder& nb) { // check whether the option is set (properly) if (!oc.isSet("dlr-navteq-prefix")) { return; } time_t csTime; time(&csTime); // parse file(s) LineReader lr; // load nodes std::map<std::string, PositionVector> myGeoms; PROGRESS_BEGIN_MESSAGE("Loading nodes"); std::string file = oc.getString("dlr-navteq-prefix") + "_nodes_unsplitted.txt"; NodesHandler handler1(nb.getNodeCont(), file, myGeoms); if (!lr.setFile(file)) { throw ProcessError("The file '" + file + "' could not be opened."); } lr.readAll(handler1); PROGRESS_DONE_MESSAGE(); // load street names if given and wished std::map<std::string, std::string> streetNames; // nameID : name if (oc.getBool("output.street-names")) { file = oc.getString("dlr-navteq-prefix") + "_names.txt"; if (lr.setFile(file)) { PROGRESS_BEGIN_MESSAGE("Loading Street Names"); NamesHandler handler4(file, streetNames); lr.readAll(handler4); PROGRESS_DONE_MESSAGE(); } else { WRITE_WARNING("Output will not contain street names because the file '" + file + "' was not found"); } } // load edges PROGRESS_BEGIN_MESSAGE("Loading edges"); file = oc.getString("dlr-navteq-prefix") + "_links_unsplitted.txt"; // parse the file EdgesHandler handler2(nb.getNodeCont(), nb.getEdgeCont(), nb.getTypeCont(), file, myGeoms, streetNames); if (!lr.setFile(file)) { throw ProcessError("The file '" + file + "' could not be opened."); } lr.readAll(handler2); nb.getEdgeCont().recheckLaneSpread(); PROGRESS_DONE_MESSAGE(); // load traffic lights if given file = oc.getString("dlr-navteq-prefix") + "_traffic_signals.txt"; if (lr.setFile(file)) { PROGRESS_BEGIN_MESSAGE("Loading traffic lights"); TrafficlightsHandler handler3(nb.getNodeCont(), nb.getTLLogicCont(), nb.getEdgeCont(), file); lr.readAll(handler3); PROGRESS_DONE_MESSAGE(); } // load prohibited manoeuvres if given file = oc.getString("dlr-navteq-prefix") + "_prohibited_manoeuvres.txt"; if (lr.setFile(file)) { PROGRESS_BEGIN_MESSAGE("Loading prohibited manoeuvres"); ProhibitionHandler handler6(nb.getEdgeCont(), file, csTime); lr.readAll(handler6); PROGRESS_DONE_MESSAGE(); } // load connected lanes if given file = oc.getString("dlr-navteq-prefix") + "_connected_lanes.txt"; if (lr.setFile(file)) { PROGRESS_BEGIN_MESSAGE("Loading connected lanes"); ConnectedLanesHandler handler7(nb.getEdgeCont()); lr.readAll(handler7); PROGRESS_DONE_MESSAGE(); } // load time restrictions if given file = oc.getString("dlr-navteq-prefix") + "_links_timerestrictions.txt"; if (lr.setFile(file)) { PROGRESS_BEGIN_MESSAGE("Loading time restrictions"); if (!oc.isDefault("construction-date")) { csTime = readDate(oc.getString("construction-date")); } TimeRestrictionsHandler handler5(nb.getEdgeCont(), nb.getDistrictCont(), csTime); lr.readAll(handler5); handler5.printSummary(); PROGRESS_DONE_MESSAGE(); } }
// =========================================================================== // method definitions // =========================================================================== // --------------------------------------------------------------------------- // static methods (interface in this case) // --------------------------------------------------------------------------- void NIImporter_SUMO::loadNetwork(const OptionsCont &oc, NBNetBuilder &nb) { // check whether the option is set (properly) if (!oc.isUsableFileList("sumo-net")) { return; } // build the handler NIImporter_SUMO handler(nb.getNodeCont()); // parse file(s) std::vector<std::string> files = oc.getStringVector("sumo-net"); for (std::vector<std::string>::const_iterator file=files.begin(); file!=files.end(); ++file) { if (!FileHelpers::exists(*file)) { MsgHandler::getErrorInstance()->inform("Could not open sumo-net-file '" + *file + "'."); return; } handler.setFileName(*file); MsgHandler::getMessageInstance()->beginProcessMsg("Parsing sumo-net from '" + *file + "'..."); XMLSubSys::runParser(handler, *file); MsgHandler::getMessageInstance()->endProcessMsg("done."); } // build edges std::map<std::string, EdgeAttrs*> &loadedEdges = handler.myEdges; NBNodeCont &nodesCont = nb.getNodeCont(); NBEdgeCont &edgesCont = nb.getEdgeCont(); for (std::map<std::string, EdgeAttrs*>::const_iterator i=loadedEdges.begin(); i!=loadedEdges.end(); ++i) { EdgeAttrs *ed = (*i).second; // get and check the nodes NBNode *from = nodesCont.retrieve(ed->fromNode); NBNode *to = nodesCont.retrieve(ed->toNode); if (from==0) { MsgHandler::getErrorInstance()->inform("Edge's '" + ed->id + "' from-node '" + ed->fromNode + "' is not known."); continue; } if (to==0) { MsgHandler::getErrorInstance()->inform("Edge's '" + ed->id + "' to-node '" + ed->toNode + "' is not known."); continue; } // build and insert the edge NBEdge *e = new NBEdge(ed->id, from, to, ed->type, ed->maxSpeed, (unsigned int) ed->lanes.size(), ed->priority); if (!edgesCont.insert(e)) { MsgHandler::getErrorInstance()->inform("Could not insert edge '" + ed->id + "'."); delete e; continue; } ed->builtEdge = edgesCont.retrieve(ed->id); } // assign lane attributes (edges are built) for (std::map<std::string, EdgeAttrs*>::const_iterator i=loadedEdges.begin(); i!=loadedEdges.end(); ++i) { EdgeAttrs *ed = (*i).second; if (ed->builtEdge==0) { // earlier errors continue; } for (unsigned int j=0; j<(unsigned int) ed->lanes.size(); ++j) { const std::vector<EdgeLane> &connections = ed->lanes[j]->connections; for (std::vector<EdgeLane>::const_iterator k=connections.begin(); k!=connections.end(); ++k) { if ((*k).lane!="SUMO_NO_DESTINATION") { std::string lane = (*k).lane; std::string edge = lane.substr(0, lane.find('_')); int index = TplConvert<char>::_2int(lane.substr(lane.find('_')+1).c_str()); if (loadedEdges.find(edge)==loadedEdges.end()) { MsgHandler::getErrorInstance()->inform("Unknown edge given in succlane (for lane '" + lane + "')."); continue; } NBEdge *ce = loadedEdges.find(edge)->second->builtEdge; if (ce==0) { // earlier error or edge removal continue; } ed->builtEdge->addLane2LaneConnection(j, ce, index, NBEdge::L2L_VALIDATED); } } } } // clean up for (std::map<std::string, EdgeAttrs*>::const_iterator i=loadedEdges.begin(); i!=loadedEdges.end(); ++i) { EdgeAttrs *ed = (*i).second; for (std::vector<LaneAttrs*>::const_iterator j=ed->lanes.begin(); j!=ed->lanes.end(); ++j) { delete *j; } delete ed; } }