bool GeoConvHelper::init(OptionsCont& oc) { std::string proj = "!"; // the default double scale = oc.getFloat("proj.scale"); double rot = oc.getFloat("proj.rotate"); Position offset = Position(oc.getFloat("offset.x"), oc.getFloat("offset.y")); bool inverse = oc.exists("proj.inverse") && oc.getBool("proj.inverse"); bool flatten = oc.exists("flatten") && oc.getBool("flatten"); if (oc.getBool("simple-projection")) { proj = "-"; } #ifdef PROJ_API_FILE if (oc.getBool("proj.inverse") && oc.getString("proj") == "!") { WRITE_ERROR("Inverse projection works only with explicit proj parameters."); return false; } unsigned numProjections = oc.getBool("simple-projection") + oc.getBool("proj.utm") + oc.getBool("proj.dhdn") + oc.getBool("proj.dhdnutm") + (oc.getString("proj").length() > 1); if (numProjections > 1) { WRITE_ERROR("The projection method needs to be uniquely defined."); return false; } if (oc.getBool("proj.utm")) { proj = "UTM"; } else if (oc.getBool("proj.dhdn")) { proj = "DHDN"; } else if (oc.getBool("proj.dhdnutm")) { proj = "DHDN_UTM"; } else if (!oc.isDefault("proj")) { proj = oc.getString("proj"); } #endif myProcessing = GeoConvHelper(proj, offset, Boundary(), Boundary(), scale, rot, inverse, flatten); myFinal = myProcessing; return true; }
// =========================================================================== // 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(); } }
void NBNetBuilder::compute(OptionsCont& oc, const std::set<std::string>& explicitTurnarounds, bool removeElements) { GeoConvHelper& geoConvHelper = GeoConvHelper::getProcessing(); const bool lefthand = oc.getBool("lefthand"); if (lefthand) { mirrorX(); }; // MODIFYING THE SETS OF NODES AND EDGES // Removes edges that are connecting the same node long before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Removing self-loops"); myNodeCont.removeSelfLoops(myDistrictCont, myEdgeCont, myTLLCont); PROGRESS_TIME_MESSAGE(before); // if (oc.exists("remove-edges.isolated") && oc.getBool("remove-edges.isolated")) { before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Finding isolated roads"); myNodeCont.removeIsolatedRoads(myDistrictCont, myEdgeCont, myTLLCont); PROGRESS_TIME_MESSAGE(before); } // if (oc.exists("keep-edges.postload") && oc.getBool("keep-edges.postload")) { if (oc.isSet("keep-edges.explicit") || oc.isSet("keep-edges.input-file")) { before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Removing unwished edges"); myEdgeCont.removeUnwishedEdges(myDistrictCont); PROGRESS_TIME_MESSAGE(before); } } if (oc.getBool("junctions.join") || (oc.exists("ramps.guess") && oc.getBool("ramps.guess"))) { // preliminary geometry computations to determine the length of edges // This depends on turning directions and sorting of edge list // in case junctions are joined geometry computations have to be repeated // preliminary roundabout computations to avoid damaging roundabouts via junctions.join or ramps.guess NBTurningDirectionsComputer::computeTurnDirections(myNodeCont, false); NBNodesEdgesSorter::sortNodesEdges(myNodeCont); myEdgeCont.computeLaneShapes(); myNodeCont.computeNodeShapes(); myEdgeCont.computeEdgeShapes(); if (oc.getBool("roundabouts.guess")) { myEdgeCont.guessRoundabouts(); } const std::set<EdgeSet>& roundabouts = myEdgeCont.getRoundabouts(); for (std::set<EdgeSet>::const_iterator it_round = roundabouts.begin(); it_round != roundabouts.end(); ++it_round) { std::vector<std::string> nodeIDs; for (EdgeSet::const_iterator it_edge = it_round->begin(); it_edge != it_round->end(); ++it_edge) { nodeIDs.push_back((*it_edge)->getToNode()->getID()); } myNodeCont.addJoinExclusion(nodeIDs); } } // join junctions (may create new "geometry"-nodes so it needs to come before removing these if (oc.exists("junctions.join-exclude") && oc.isSet("junctions.join-exclude")) { myNodeCont.addJoinExclusion(oc.getStringVector("junctions.join-exclude")); } unsigned int numJoined = myNodeCont.joinLoadedClusters(myDistrictCont, myEdgeCont, myTLLCont); if (oc.getBool("junctions.join")) { before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Joining junction clusters"); numJoined += myNodeCont.joinJunctions(oc.getFloat("junctions.join-dist"), myDistrictCont, myEdgeCont, myTLLCont); PROGRESS_TIME_MESSAGE(before); } if (oc.getBool("junctions.join") || (oc.exists("ramps.guess") && oc.getBool("ramps.guess"))) { // reset geometry to avoid influencing subsequent steps (ramps.guess) myEdgeCont.computeLaneShapes(); } if (numJoined > 0) { // bit of a misnomer since we're already done WRITE_MESSAGE(" Joined " + toString(numJoined) + " junction cluster(s)."); } // if (removeElements) { unsigned int no = 0; const bool removeGeometryNodes = oc.exists("geometry.remove") && oc.getBool("geometry.remove"); before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Removing empty nodes" + std::string(removeGeometryNodes ? " and geometry nodes" : "")); // removeUnwishedNodes needs turnDirections. @todo: try to call this less often NBTurningDirectionsComputer::computeTurnDirections(myNodeCont, false); no = myNodeCont.removeUnwishedNodes(myDistrictCont, myEdgeCont, myTLLCont, removeGeometryNodes); PROGRESS_TIME_MESSAGE(before); WRITE_MESSAGE(" " + toString(no) + " nodes removed."); } // MOVE TO ORIGIN // compute new boundary after network modifications have taken place Boundary boundary; for (std::map<std::string, NBNode*>::const_iterator it = myNodeCont.begin(); it != myNodeCont.end(); ++it) { boundary.add(it->second->getPosition()); } for (std::map<std::string, NBEdge*>::const_iterator it = myEdgeCont.begin(); it != myEdgeCont.end(); ++it) { boundary.add(it->second->getGeometry().getBoxBoundary()); } geoConvHelper.setConvBoundary(boundary); if (!oc.getBool("offset.disable-normalization") && oc.isDefault("offset.x") && oc.isDefault("offset.y")) { moveToOrigin(geoConvHelper, lefthand); } geoConvHelper.computeFinal(lefthand); // information needed for location element fixed at this point if (oc.exists("geometry.min-dist") && oc.isSet("geometry.min-dist")) { before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Reducing geometries"); myEdgeCont.reduceGeometries(oc.getFloat("geometry.min-dist")); PROGRESS_TIME_MESSAGE(before); } // @note: removing geometry can create similar edges so joinSimilarEdges must come afterwards // @note: likewise splitting can destroy similarities so joinSimilarEdges must come before if (removeElements && oc.getBool("edges.join")) { before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Joining similar edges"); myNodeCont.joinSimilarEdges(myDistrictCont, myEdgeCont, myTLLCont); PROGRESS_TIME_MESSAGE(before); } if (oc.getBool("opposites.guess")) { PROGRESS_BEGIN_MESSAGE("guessing opposite direction edges"); myEdgeCont.guessOpposites(); PROGRESS_DONE_MESSAGE(); } // if (oc.exists("geometry.split") && oc.getBool("geometry.split")) { before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Splitting geometry edges"); myEdgeCont.splitGeometry(myNodeCont); PROGRESS_TIME_MESSAGE(before); } // turning direction before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Computing turning directions"); NBTurningDirectionsComputer::computeTurnDirections(myNodeCont); PROGRESS_TIME_MESSAGE(before); // correct edge geometries to avoid overlap myNodeCont.avoidOverlap(); // guess ramps if ((oc.exists("ramps.guess") && oc.getBool("ramps.guess")) || (oc.exists("ramps.set") && oc.isSet("ramps.set"))) { before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Guessing and setting on-/off-ramps"); NBNodesEdgesSorter::sortNodesEdges(myNodeCont); NBRampsComputer::computeRamps(*this, oc); PROGRESS_TIME_MESSAGE(before); } // guess sidewalks if (oc.getBool("sidewalks.guess") || oc.getBool("sidewalks.guess.from-permissions")) { const int sidewalks = myEdgeCont.guessSidewalks(oc.getFloat("default.sidewalk-width"), oc.getFloat("sidewalks.guess.min-speed"), oc.getFloat("sidewalks.guess.max-speed"), oc.getBool("sidewalks.guess.from-permissions")); WRITE_MESSAGE("Guessed " + toString(sidewalks) + " sidewalks."); } // check whether any not previously setable connections may be set now myEdgeCont.recheckPostProcessConnections(); // remap ids if wished if (oc.getBool("numerical-ids")) { int numChangedEdges = myEdgeCont.mapToNumericalIDs(); int numChangedNodes = myNodeCont.mapToNumericalIDs(); if (numChangedEdges + numChangedNodes > 0) { WRITE_MESSAGE("Remapped " + toString(numChangedEdges) + " edge IDs and " + toString(numChangedNodes) + " node IDs."); } } // if (oc.exists("geometry.max-angle")) { myEdgeCont.checkGeometries( DEG2RAD(oc.getFloat("geometry.max-angle")), oc.getFloat("geometry.min-radius"), oc.getBool("geometry.min-radius.fix")); } // GEOMETRY COMPUTATION // before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Sorting nodes' edges"); NBNodesEdgesSorter::sortNodesEdges(myNodeCont); PROGRESS_TIME_MESSAGE(before); myEdgeCont.computeLaneShapes(); // before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Computing node shapes"); if (oc.exists("geometry.junction-mismatch-threshold")) { myNodeCont.computeNodeShapes(oc.getFloat("geometry.junction-mismatch-threshold")); } else { myNodeCont.computeNodeShapes(); } PROGRESS_TIME_MESSAGE(before); // before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Computing edge shapes"); myEdgeCont.computeEdgeShapes(); PROGRESS_TIME_MESSAGE(before); // resort edges based on the node and edge shapes NBNodesEdgesSorter::sortNodesEdges(myNodeCont, true); NBTurningDirectionsComputer::computeTurnDirections(myNodeCont, false); // APPLY SPEED MODIFICATIONS if (oc.exists("speed.offset")) { const SUMOReal speedOffset = oc.getFloat("speed.offset"); const SUMOReal speedFactor = oc.getFloat("speed.factor"); if (speedOffset != 0 || speedFactor != 1 || oc.isSet("speed.minimum")) { const SUMOReal speedMin = oc.isSet("speed.minimum") ? oc.getFloat("speed.minimum") : -std::numeric_limits<SUMOReal>::infinity(); before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Applying speed modifications"); for (std::map<std::string, NBEdge*>::const_iterator i = myEdgeCont.begin(); i != myEdgeCont.end(); ++i) { (*i).second->setSpeed(-1, MAX2((*i).second->getSpeed() * speedFactor + speedOffset, speedMin)); } PROGRESS_TIME_MESSAGE(before); } } // CONNECTIONS COMPUTATION // before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Computing node types"); NBNodeTypeComputer::computeNodeTypes(myNodeCont); PROGRESS_TIME_MESSAGE(before); // bool haveCrossings = false; if (oc.getBool("crossings.guess")) { haveCrossings = true; int crossings = 0; for (std::map<std::string, NBNode*>::const_iterator i = myNodeCont.begin(); i != myNodeCont.end(); ++i) { crossings += (*i).second->guessCrossings(); } WRITE_MESSAGE("Guessed " + toString(crossings) + " pedestrian crossings."); } if (!haveCrossings) { // recheck whether we had crossings in the input for (std::map<std::string, NBNode*>::const_iterator i = myNodeCont.begin(); i != myNodeCont.end(); ++i) { if (i->second->getCrossings().size() > 0) { haveCrossings = true; break; } } } if (oc.isDefault("no-internal-links") && !haveCrossings && myHaveLoadedNetworkWithoutInternalEdges) { oc.set("no-internal-links", "true"); } // before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Computing priorities"); NBEdgePriorityComputer::computeEdgePriorities(myNodeCont); PROGRESS_TIME_MESSAGE(before); // before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Computing approached edges"); myEdgeCont.computeEdge2Edges(oc.getBool("no-left-connections")); PROGRESS_TIME_MESSAGE(before); // if (oc.getBool("roundabouts.guess")) { before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Guessing and setting roundabouts"); const int numGuessed = myEdgeCont.guessRoundabouts(); if (numGuessed > 0) { WRITE_MESSAGE(" Guessed " + toString(numGuessed) + " roundabout(s)."); } PROGRESS_TIME_MESSAGE(before); } myEdgeCont.markRoundabouts(); // before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Computing approaching lanes"); myEdgeCont.computeLanes2Edges(); PROGRESS_TIME_MESSAGE(before); // before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Dividing of lanes on approached lanes"); myNodeCont.computeLanes2Lanes(); myEdgeCont.sortOutgoingLanesConnections(); PROGRESS_TIME_MESSAGE(before); // before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Processing turnarounds"); if (!oc.getBool("no-turnarounds")) { myEdgeCont.appendTurnarounds(oc.getBool("no-turnarounds.tls")); } else { myEdgeCont.appendTurnarounds(explicitTurnarounds, oc.getBool("no-turnarounds.tls")); } PROGRESS_TIME_MESSAGE(before); // before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Rechecking of lane endings"); myEdgeCont.recheckLanes(); PROGRESS_TIME_MESSAGE(before); if (haveCrossings && !oc.getBool("no-internal-links")) { for (std::map<std::string, NBNode*>::const_iterator i = myNodeCont.begin(); i != myNodeCont.end(); ++i) { i->second->buildCrossingsAndWalkingAreas(); } } // GUESS TLS POSITIONS before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Assigning nodes to traffic lights"); if (oc.isSet("tls.set")) { std::vector<std::string> tlControlledNodes = oc.getStringVector("tls.set"); TrafficLightType type = SUMOXMLDefinitions::TrafficLightTypes.get(oc.getString("tls.default-type")); for (std::vector<std::string>::const_iterator i = tlControlledNodes.begin(); i != tlControlledNodes.end(); ++i) { NBNode* node = myNodeCont.retrieve(*i); if (node == 0) { WRITE_WARNING("Building a tl-logic for junction '" + *i + "' is not possible." + "\n The junction '" + *i + "' is not known."); } else { myNodeCont.setAsTLControlled(node, myTLLCont, type); } } } myNodeCont.guessTLs(oc, myTLLCont); PROGRESS_TIME_MESSAGE(before); // if (oc.getBool("tls.join")) { before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Joining traffic light nodes"); myNodeCont.joinTLS(myTLLCont, oc.getFloat("tls.join-dist")); PROGRESS_TIME_MESSAGE(before); } // COMPUTING RIGHT-OF-WAY AND TRAFFIC LIGHT PROGRAMS // before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Computing traffic light control information"); myTLLCont.setTLControllingInformation(myEdgeCont, myNodeCont); PROGRESS_TIME_MESSAGE(before); // before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Computing node logics"); myNodeCont.computeLogics(myEdgeCont, oc); PROGRESS_TIME_MESSAGE(before); // before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Computing traffic light logics"); std::pair<unsigned int, unsigned int> numbers = myTLLCont.computeLogics(oc); PROGRESS_TIME_MESSAGE(before); std::string progCount = ""; if (numbers.first != numbers.second) { progCount = "(" + toString(numbers.second) + " programs) "; } WRITE_MESSAGE(" " + toString(numbers.first) + " traffic light(s) " + progCount + "computed."); // if (oc.isSet("street-sign-output")) { before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Generating street signs"); myEdgeCont.generateStreetSigns(); PROGRESS_TIME_MESSAGE(before); } // FINISHING INNER EDGES if (!oc.getBool("no-internal-links")) { before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Building inner edges"); for (std::map<std::string, NBEdge*>::const_iterator i = myEdgeCont.begin(); i != myEdgeCont.end(); ++i) { (*i).second->sortOutgoingConnectionsByIndex(); } // walking areas shall only be built if crossings are wished as well for (std::map<std::string, NBNode*>::const_iterator i = myNodeCont.begin(); i != myNodeCont.end(); ++i) { (*i).second->buildInnerEdges(); } PROGRESS_TIME_MESSAGE(before); } if (lefthand) { mirrorX(); }; // report WRITE_MESSAGE("-----------------------------------------------------"); WRITE_MESSAGE("Summary:"); myNodeCont.printBuiltNodesStatistics(); WRITE_MESSAGE(" Network boundaries:"); WRITE_MESSAGE(" Original boundary : " + toString(geoConvHelper.getOrigBoundary())); WRITE_MESSAGE(" Applied offset : " + toString(geoConvHelper.getOffsetBase())); WRITE_MESSAGE(" Converted boundary : " + toString(geoConvHelper.getConvBoundary())); WRITE_MESSAGE("-----------------------------------------------------"); NBRequest::reportWarnings(); // report on very large networks if (MAX2(geoConvHelper.getConvBoundary().xmax(), geoConvHelper.getConvBoundary().ymax()) > 1000000 || MIN2(geoConvHelper.getConvBoundary().xmin(), geoConvHelper.getConvBoundary().ymin()) < -1000000) { WRITE_WARNING("Network contains very large coordinates and will probably flicker in the GUI. Check for outlying nodes and make sure the network is shifted to the coordinate origin"); } }
void NIImporter_SUMO::_loadNetwork(OptionsCont& oc) { // check whether the option is set (properly) if (!oc.isUsableFileList("sumo-net-file")) { return; } // parse file(s) std::vector<std::string> files = oc.getStringVector("sumo-net-file"); for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) { if (!FileHelpers::isReadable(*file)) { WRITE_ERROR("Could not open sumo-net-file '" + *file + "'."); return; } setFileName(*file); PROGRESS_BEGIN_MESSAGE("Parsing sumo-net from '" + *file + "'"); XMLSubSys::runParser(*this, *file, true); PROGRESS_DONE_MESSAGE(); } // build edges for (std::map<std::string, EdgeAttrs*>::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) { EdgeAttrs* ed = (*i).second; // skip internal edges if (ed->func == EDGEFUNC_INTERNAL || ed->func == EDGEFUNC_CROSSING || ed->func == EDGEFUNC_WALKINGAREA) { continue; } // get and check the nodes NBNode* from = myNodeCont.retrieve(ed->fromNode); NBNode* to = myNodeCont.retrieve(ed->toNode); if (from == 0) { WRITE_ERROR("Edge's '" + ed->id + "' from-node '" + ed->fromNode + "' is not known."); continue; } if (to == 0) { WRITE_ERROR("Edge's '" + ed->id + "' to-node '" + ed->toNode + "' is not known."); continue; } // edge shape PositionVector geom; if (ed->shape.size() > 0) { geom = ed->shape; } else { // either the edge has default shape consisting only of the two node // positions or we have a legacy network geom = reconstructEdgeShape(ed, from->getPosition(), to->getPosition()); } // build and insert the edge NBEdge* e = new NBEdge(ed->id, from, to, ed->type, ed->maxSpeed, (unsigned int) ed->lanes.size(), ed->priority, NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET, geom, ed->streetName, "", ed->lsf, true); // always use tryIgnoreNodePositions to keep original shape e->setLoadedLength(ed->length); if (!myNetBuilder.getEdgeCont().insert(e)) { WRITE_ERROR("Could not insert edge '" + ed->id + "'."); delete e; continue; } ed->builtEdge = myNetBuilder.getEdgeCont().retrieve(ed->id); } // assign further lane attributes (edges are built) for (std::map<std::string, EdgeAttrs*>::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) { EdgeAttrs* ed = (*i).second; NBEdge* nbe = ed->builtEdge; if (nbe == 0) { // inner edge or removed by explicit list, vclass, ... continue; } for (unsigned int fromLaneIndex = 0; fromLaneIndex < (unsigned int) ed->lanes.size(); ++fromLaneIndex) { LaneAttrs* lane = ed->lanes[fromLaneIndex]; // connections const std::vector<Connection>& connections = lane->connections; for (std::vector<Connection>::const_iterator c_it = connections.begin(); c_it != connections.end(); c_it++) { const Connection& c = *c_it; if (myEdges.count(c.toEdgeID) == 0) { WRITE_ERROR("Unknown edge '" + c.toEdgeID + "' given in connection."); continue; } NBEdge* toEdge = myEdges[c.toEdgeID]->builtEdge; if (toEdge == 0) { // removed by explicit list, vclass, ... continue; } if (nbe->hasConnectionTo(toEdge, c.toLaneIdx)) { WRITE_WARNING("Target lane '" + toEdge->getLaneID(c.toLaneIdx) + "' has multiple connections from '" + nbe->getID() + "'."); } nbe->addLane2LaneConnection( fromLaneIndex, toEdge, c.toLaneIdx, NBEdge::L2L_VALIDATED, true, c.mayDefinitelyPass, c.keepClear, c.contPos); // maybe we have a tls-controlled connection if (c.tlID != "" && myRailSignals.count(c.tlID) == 0) { const std::map<std::string, NBTrafficLightDefinition*>& programs = myTLLCont.getPrograms(c.tlID); if (programs.size() > 0) { std::map<std::string, NBTrafficLightDefinition*>::const_iterator it; for (it = programs.begin(); it != programs.end(); it++) { NBLoadedSUMOTLDef* tlDef = dynamic_cast<NBLoadedSUMOTLDef*>(it->second); if (tlDef) { tlDef->addConnection(nbe, toEdge, fromLaneIndex, c.toLaneIdx, c.tlLinkNo); } else { throw ProcessError("Corrupt traffic light definition '" + c.tlID + "' (program '" + it->first + "')"); } } } else { WRITE_ERROR("The traffic light '" + c.tlID + "' is not known."); } } } // allow/disallow XXX preferred nbe->setPermissions(parseVehicleClasses(lane->allow, lane->disallow), fromLaneIndex); // width, offset nbe->setLaneWidth(fromLaneIndex, lane->width); nbe->setEndOffset(fromLaneIndex, lane->endOffset); nbe->setSpeed(fromLaneIndex, lane->maxSpeed); } nbe->declareConnectionsAsLoaded(); if (!nbe->hasLaneSpecificWidth() && nbe->getLanes()[0].width != NBEdge::UNSPECIFIED_WIDTH) { nbe->setLaneWidth(-1, nbe->getLaneWidth(0)); } if (!nbe->hasLaneSpecificEndOffset() && nbe->getEndOffset(0) != NBEdge::UNSPECIFIED_OFFSET) { nbe->setEndOffset(-1, nbe->getEndOffset(0)); } } // insert loaded prohibitions for (std::vector<Prohibition>::const_iterator it = myProhibitions.begin(); it != myProhibitions.end(); it++) { NBEdge* prohibitedFrom = myEdges[it->prohibitedFrom]->builtEdge; NBEdge* prohibitedTo = myEdges[it->prohibitedTo]->builtEdge; NBEdge* prohibitorFrom = myEdges[it->prohibitorFrom]->builtEdge; NBEdge* prohibitorTo = myEdges[it->prohibitorTo]->builtEdge; if (prohibitedFrom == 0) { WRITE_WARNING("Edge '" + it->prohibitedFrom + "' in prohibition was not built"); } else if (prohibitedTo == 0) { WRITE_WARNING("Edge '" + it->prohibitedTo + "' in prohibition was not built"); } else if (prohibitorFrom == 0) { WRITE_WARNING("Edge '" + it->prohibitorFrom + "' in prohibition was not built"); } else if (prohibitorTo == 0) { WRITE_WARNING("Edge '" + it->prohibitorTo + "' in prohibition was not built"); } else { NBNode* n = prohibitedFrom->getToNode(); n->addSortedLinkFoes( NBConnection(prohibitorFrom, prohibitorTo), NBConnection(prohibitedFrom, prohibitedTo)); } } if (!myHaveSeenInternalEdge) { myNetBuilder.haveLoadedNetworkWithoutInternalEdges(); } if (oc.isDefault("lefthand")) { oc.set("lefthand", toString(myAmLefthand)); } if (oc.isDefault("junctions.corner-detail")) { oc.set("junctions.corner-detail", toString(myCornerDetail)); } if (oc.isDefault("junctions.internal-link-detail") && myLinkDetail > 0) { oc.set("junctions.internal-link-detail", toString(myLinkDetail)); } if (!deprecatedVehicleClassesSeen.empty()) { WRITE_WARNING("Deprecated vehicle class(es) '" + toString(deprecatedVehicleClassesSeen) + "' in input network."); deprecatedVehicleClassesSeen.clear(); } // add loaded crossings if (!oc.getBool("no-internal-links")) { for (std::map<std::string, std::vector<Crossing> >::const_iterator it = myPedestrianCrossings.begin(); it != myPedestrianCrossings.end(); ++it) { NBNode* node = myNodeCont.retrieve((*it).first); for (std::vector<Crossing>::const_iterator it_c = (*it).second.begin(); it_c != (*it).second.end(); ++it_c) { const Crossing& crossing = (*it_c); EdgeVector edges; for (std::vector<std::string>::const_iterator it_e = crossing.crossingEdges.begin(); it_e != crossing.crossingEdges.end(); ++it_e) { NBEdge* edge = myNetBuilder.getEdgeCont().retrieve(*it_e); // edge might have been removed due to options if (edge != 0) { edges.push_back(edge); } } if (edges.size() > 0) { node->addCrossing(edges, crossing.width, crossing.priority, true); } } } } // add roundabouts for (std::vector<std::vector<std::string> >::const_iterator it = myRoundabouts.begin(); it != myRoundabouts.end(); ++it) { EdgeSet roundabout; for (std::vector<std::string>::const_iterator it_r = it->begin(); it_r != it->end(); ++it_r) { NBEdge* edge = myNetBuilder.getEdgeCont().retrieve(*it_r); if (edge == 0) { if (!myNetBuilder.getEdgeCont().wasIgnored(*it_r)) { WRITE_ERROR("Unknown edge '" + (*it_r) + "' in roundabout"); } } else { roundabout.insert(edge); } } myNetBuilder.getEdgeCont().addRoundabout(roundabout); } }
// =========================================================================== // 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(); }