void NBEdgeCont::recheckPostProcessConnections() { for (std::vector<PostProcessConnection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) { NBEdge* from = retrieve((*i).from); NBEdge* to = retrieve((*i).to); if (from != 0 && to != 0) { if (!from->addLane2LaneConnection((*i).fromLane, to, (*i).toLane, NBEdge::L2L_USER, false, (*i).mayDefinitelyPass)) { WRITE_WARNING("Could not insert connection between '" + (*i).from + "' and '" + (*i).to + "' after build."); } } } // during loading we also kept some ambiguous connections in hope they might be valid after processing // we need to make sure that all invalid connections are removed now for (EdgeCont::iterator it = myEdges.begin(); it != myEdges.end(); ++it) { NBEdge* edge = it->second; NBNode* to = edge->getToNode(); // make a copy because we may delete connections std::vector<NBEdge::Connection> connections = edge->getConnections(); for (std::vector<NBEdge::Connection>::iterator it_con = connections.begin(); it_con != connections.end(); ++it_con) { NBEdge::Connection& c = *it_con; if (c.toEdge != 0 && c.toEdge->getFromNode() != to) { WRITE_WARNING("Found and removed invalid connection from " + edge->getID() + " to " + c.toEdge->getID() + " via " + to->getID()); edge->removeFromConnections(c.toEdge); } } } }
bool NIImporter_DlrNavteq::ConnectedLanesHandler::report(const std::string& result) { if (result[0] == '#') { return true; } StringTokenizer st(result, StringTokenizer::TAB); if (st.size() == 1) { return true; // one line with the number of data containing lines in it (also starts with a comment # since ersion 6.5) } assert(st.size() >= 7); const std::string nodeID = st.next(); const std::string vehicleType = st.next(); const std::string fromLaneS = st.next(); const std::string toLaneS = st.next(); const std::string throughTraffic = st.next(); const std::string startEdge = st.next(); const std::string endEdge = st.get(st.size() - 1); NBEdge* from = myEdgeCont.retrieve(startEdge); if (from == nullptr) { WRITE_WARNING("Ignoring prohibition from unknown start edge '" + startEdge + "'"); return true; } NBEdge* to = myEdgeCont.retrieve(endEdge); if (to == nullptr) { WRITE_WARNING("Ignoring prohibition from unknown end edge '" + endEdge + "'"); return true; } int fromLane = StringUtils::toInt(fromLaneS) - 1; // one based if (fromLane < 0 || fromLane >= from->getNumLanes()) { WRITE_WARNING("Ignoring invalid lane index '" + fromLaneS + "' in connection from edge '" + startEdge + "' with " + toString(from->getNumLanes()) + " lanes"); return true; } int toLane = StringUtils::toInt(toLaneS) - 1; // one based if (toLane < 0 || toLane >= to->getNumLanes()) { WRITE_WARNING("Ignoring invalid lane index '" + toLaneS + "' in connection to edge '" + endEdge + "' with " + toString(to->getNumLanes()) + " lanes"); return true; } if (!from->addLane2LaneConnection(fromLane, to, toLane, NBEdge::L2L_USER, true)) { if (OptionsCont::getOptions().getBool("show-errors.connections-first-try")) { WRITE_WARNING("Could not set loaded connection from '" + from->getLaneID(fromLane) + "' to '" + to->getLaneID(toLane) + "'."); } // set as to be re-applied after network processing // if this connection runs across a node cluster it may not be possible to set this const bool warnOnly = st.size() > 7; myEdgeCont.addPostProcessConnection(from->getID(), fromLane, to->getID(), toLane, false, true, NBEdge::UNSPECIFIED_CONTPOS, NBEdge::UNSPECIFIED_VISIBILITY_DISTANCE, NBEdge::UNSPECIFIED_SPEED, PositionVector::EMPTY, false, warnOnly); } // ensure that connections for other lanes are guessed if not specified from->declareConnectionsAsLoaded(NBEdge::INIT); from->getLaneStruct(fromLane).connectionsDone = true; return true; }
unsigned int NIVissimConnection::buildEdgeConnections(NBEdgeCont &ec) { unsigned int unsetConnections = 0; // try to determine the connected edges NBEdge *fromEdge = 0; NBEdge *toEdge = 0; NIVissimEdge *vissimFrom = NIVissimEdge::dictionary(getFromEdgeID()); if (vissimFrom->wasWithinAJunction()) { // this edge was not built, try to get one that approaches it vissimFrom = vissimFrom->getBestIncoming(); if (vissimFrom!=0) { fromEdge = ec.retrievePossiblySplitted(toString(vissimFrom->getID()), toString(getFromEdgeID()), true); } } else { // this edge was built, try to get the proper part fromEdge = ec.retrievePossiblySplitted(toString(getFromEdgeID()), toString(getToEdgeID()), true); } NIVissimEdge *vissimTo = NIVissimEdge::dictionary(getToEdgeID()); if (vissimTo->wasWithinAJunction()) { vissimTo = vissimTo->getBestOutgoing(); if (vissimTo!=0) { toEdge = ec.retrievePossiblySplitted(toString(vissimTo->getID()), toString(getToEdgeID()), true); } } else { toEdge = ec.retrievePossiblySplitted(toString(getToEdgeID()), toString(getFromEdgeID()), false); } // try to get the edges the current connection connects /* NBEdge *fromEdge = ec.retrievePossiblySplitted(toString(getFromEdgeID()), toString(getToEdgeID()), true); NBEdge *toEdge = ec.retrievePossiblySplitted(toString(getToEdgeID()), toString(getFromEdgeID()), false); */ if (fromEdge==0||toEdge==0) { WRITE_WARNING("Could not build connection between '" + toString(getFromEdgeID())+ "' and '" + toString(getToEdgeID())+ "'."); return 1; // !!! actually not 1 } recheckLanes(fromEdge, toEdge); const IntVector &fromLanes = getFromLanes(); const IntVector &toLanes = getToLanes(); if (fromLanes.size()!=toLanes.size()) { MsgHandler::getWarningInstance()->inform("Lane sizes differ for connection '" + toString(getID()) + "'."); } else { for (unsigned int index=0; index<fromLanes.size(); ++index) { if (fromEdge->getNoLanes()<=static_cast<unsigned int>(fromLanes[index])) { MsgHandler::getWarningInstance()->inform("Could not set connection between '" + fromEdge->getID() + "_" + toString(fromLanes[index]) + "' and '" + toEdge->getID() + "_" + toString(toLanes[index]) + "'."); ++unsetConnections; } else if (!fromEdge->addLane2LaneConnection(fromLanes[index], toEdge, toLanes[index], NBEdge::L2L_VALIDATED)) { MsgHandler::getWarningInstance()->inform("Could not set connection between '" + fromEdge->getID() + "_" + toString(fromLanes[index]) + "' and '" + toEdge->getID() + "_" + toString(toLanes[index]) + "'."); ++unsetConnections; } } } return unsetConnections; }
void NIImporter_SUMO::_loadNetwork(const 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::exists(*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); 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 == toString(EDGEFUNC_INTERNAL)) { 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; mySuspectKeepShape = false; // no problem with reconstruction if edge shape is given explicit } 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; } nbe->addLane2LaneConnection( fromLaneIndex, toEdge, c.toLaneIdx, NBEdge::L2L_VALIDATED, false, c.mayDefinitelyPass); // maybe we have a tls-controlled connection if (c.tlID != "") { 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 SUMOVehicleClasses allowed; SUMOVehicleClasses disallowed; parseVehicleClasses(lane->allow, lane->disallow, allowed, disallowed); nbe->setVehicleClasses(allowed, disallowed, fromLaneIndex); // width, offset nbe->setWidth(fromLaneIndex, lane->width); nbe->setOffset(fromLaneIndex, lane->offset); nbe->setSpeed(fromLaneIndex, lane->maxSpeed); } nbe->declareConnectionsAsLoaded(); } // insert loaded prohibitions for (std::vector<Prohibition>::const_iterator it = myProhibitions.begin(); it != myProhibitions.end(); it++) { NBEdge* prohibitedFrom = myEdges[it->prohibitedFrom]->builtEdge; if (prohibitedFrom == 0) { WRITE_ERROR("Edge '" + it->prohibitedFrom + "' in prohibition was not built"); } else { NBNode* n = prohibitedFrom->getToNode(); n->addSortedLinkFoes( NBConnection(myEdges[it->prohibitorFrom]->builtEdge, myEdges[it->prohibitorTo]->builtEdge), NBConnection(prohibitedFrom, myEdges[it->prohibitedTo]->builtEdge)); } } // final warning if (mySuspectKeepShape) { WRITE_WARNING("The input network may have been built using option 'xml.keep-shape'.\n... Accuracy of junction positions cannot be guaranteed."); } }
void NIXMLEdgesHandler::myEndElement(int element) { if (element == SUMO_TAG_EDGE && myCurrentEdge != 0) { if (!myIsUpdate) { try { if (!myEdgeCont.insert(myCurrentEdge)) { WRITE_ERROR("Duplicate edge occured. ID='" + myCurrentID + "'"); delete myCurrentEdge; } } catch (InvalidArgument& e) { WRITE_ERROR(e.what()); throw; } catch (...) { WRITE_ERROR("An important information is missing in edge '" + myCurrentID + "'."); } } if (mySplits.size() != 0) { std::vector<Split>::iterator i; NBEdge* e = myCurrentEdge; sort(mySplits.begin(), mySplits.end(), split_sorter()); unsigned int noLanesMax = e->getNumLanes(); // compute the node positions and sort the lanes for (i = mySplits.begin(); i != mySplits.end(); ++i) { (*i).gpos = e->getGeometry().positionAtLengthPosition((*i).pos); sort((*i).lanes.begin(), (*i).lanes.end()); noLanesMax = MAX2(noLanesMax, (unsigned int)(*i).lanes.size()); } // split the edge std::vector<int> currLanes; for (unsigned int l = 0; l < e->getNumLanes(); ++l) { currLanes.push_back(l); } std::string edgeid = e->getID(); SUMOReal seen = 0; for (i = mySplits.begin(); i != mySplits.end(); ++i) { const Split& exp = *i; assert(exp.lanes.size() != 0); if (exp.pos > 0 && e->getGeometry().length() + seen > exp.pos && exp.pos > seen) { std::string nid = edgeid + "." + toString(exp.nameid); NBNode* rn = new NBNode(nid, exp.gpos); if (myNodeCont.insert(rn)) { // split the edge std::string nid = myCurrentID + "." + toString(exp.nameid); std::string pid = e->getID(); myEdgeCont.splitAt(myDistrictCont, e, exp.pos - seen, rn, pid, nid, e->getNumLanes(), (unsigned int) exp.lanes.size()); seen = exp.pos; std::vector<int> newLanes = exp.lanes; NBEdge* pe = myEdgeCont.retrieve(pid); NBEdge* ne = myEdgeCont.retrieve(nid); // reconnect lanes pe->invalidateConnections(true); // new on right unsigned int rightMostP = currLanes[0]; unsigned int rightMostN = newLanes[0]; for (int l = 0; l < (int) rightMostP - (int) rightMostN; ++l) { pe->addLane2LaneConnection(0, ne, l, NBEdge::L2L_VALIDATED, true); } // new on left unsigned int leftMostP = currLanes.back(); unsigned int leftMostN = newLanes.back(); for (int l = 0; l < (int) leftMostN - (int) leftMostP; ++l) { pe->addLane2LaneConnection(pe->getNumLanes() - 1, ne, leftMostN - l - rightMostN, NBEdge::L2L_VALIDATED, true); } // all other connected for (unsigned int l = 0; l < noLanesMax; ++l) { if (find(currLanes.begin(), currLanes.end(), l) == currLanes.end()) { continue; } if (find(newLanes.begin(), newLanes.end(), l) == newLanes.end()) { continue; } pe->addLane2LaneConnection(l - rightMostP, ne, l - rightMostN, NBEdge::L2L_VALIDATED, true); } // move to next e = ne; currLanes = newLanes; } else { WRITE_WARNING("Error on parsing a split (edge '" + myCurrentID + "')."); } } else if (exp.pos == 0) { if (e->getNumLanes() < exp.lanes.size()) { e->incLaneNo((int) exp.lanes.size() - e->getNumLanes()); } else { e->decLaneNo(e->getNumLanes() - (int) exp.lanes.size()); } currLanes = exp.lanes; } else { WRITE_WARNING("Split at '" + toString(exp.pos) + "' lies beyond the edge's length (edge '" + myCurrentID + "')."); } } // patch lane offsets e = myEdgeCont.retrieve(edgeid); i = mySplits.begin(); if ((*i).pos != 0) { e = e->getToNode()->getOutgoingEdges()[0]; } for (; i != mySplits.end(); ++i) { unsigned int maxLeft = (*i).lanes.back(); SUMOReal offset = 0; if (maxLeft < noLanesMax) { if (e->getLaneSpreadFunction() == LANESPREAD_RIGHT) { offset = SUMO_const_laneWidthAndOffset * (noLanesMax - 1 - maxLeft); } else { offset = SUMO_const_halfLaneAndOffset * (noLanesMax - 1 - maxLeft); } } unsigned int maxRight = (*i).lanes.front(); if (maxRight > 0 && e->getLaneSpreadFunction() == LANESPREAD_CENTER) { offset -= SUMO_const_halfLaneAndOffset * maxRight; } if (offset != 0) { PositionVector g = e->getGeometry(); g.move2side(offset); e->setGeometry(g); } if (e->getToNode()->getOutgoingEdges().size() != 0) { e = e->getToNode()->getOutgoingEdges()[0]; } } } } }
bool NBEdgeCont::splitAt(NBDistrictCont& dc, NBEdge* edge, SUMOReal pos, NBNode* node, const std::string& firstEdgeName, const std::string& secondEdgeName, unsigned int noLanesFirstEdge, unsigned int noLanesSecondEdge) { // build the new edges' geometries std::pair<PositionVector, PositionVector> geoms = edge->getGeometry().splitAt(pos); if (geoms.first[-1] != node->getPosition()) { geoms.first.pop_back(); geoms.first.push_back(node->getPosition()); } if (geoms.second[0] != node->getPosition()) { geoms.second.pop_front(); geoms.second.push_front(node->getPosition()); } // build and insert the edges NBEdge* one = new NBEdge(firstEdgeName, edge->myFrom, node, edge->myType, edge->mySpeed, noLanesFirstEdge, edge->getPriority(), edge->myLaneWidth, 0, geoms.first, edge->getStreetName(), edge->myLaneSpreadFunction, true); for (unsigned int i = 0; i < noLanesFirstEdge && i < edge->getNumLanes(); i++) { one->setSpeed(i, edge->getLaneSpeed(i)); } NBEdge* two = new NBEdge(secondEdgeName, node, edge->myTo, edge->myType, edge->mySpeed, noLanesSecondEdge, edge->getPriority(), edge->myLaneWidth, edge->myOffset, geoms.second, edge->getStreetName(), edge->myLaneSpreadFunction, true); for (unsigned int i = 0; i < noLanesSecondEdge && i < edge->getNumLanes(); i++) { two->setSpeed(i, edge->getLaneSpeed(i)); } two->copyConnectionsFrom(edge); // replace information about this edge within the nodes edge->myFrom->replaceOutgoing(edge, one, 0); edge->myTo->replaceIncoming(edge, two, 0); // the edge is now occuring twice in both nodes... // clean up edge->myFrom->removeDoubleEdges(); edge->myTo->removeDoubleEdges(); // add connections from the first to the second edge // check special case: // one in, one out, the outgoing has one lane more if (noLanesFirstEdge == noLanesSecondEdge - 1) { for (unsigned int i = 0; i < one->getNumLanes(); i++) { if (!one->addLane2LaneConnection(i, two, i + 1, NBEdge::L2L_COMPUTED)) { // !!! Bresenham, here!!! throw ProcessError("Could not set connection!"); } } one->addLane2LaneConnection(0, two, 0, NBEdge::L2L_COMPUTED); } else { for (unsigned int i = 0; i < one->getNumLanes() && i < two->getNumLanes(); i++) { if (!one->addLane2LaneConnection(i, two, i, NBEdge::L2L_COMPUTED)) {// !!! Bresenham, here!!! throw ProcessError("Could not set connection!"); } } } if (myRemoveEdgesAfterJoining) { if (find(myEdges2Keep.begin(), myEdges2Keep.end(), edge->getID()) != myEdges2Keep.end()) { myEdges2Keep.insert(one->getID()); myEdges2Keep.insert(two->getID()); } if (find(myEdges2Remove.begin(), myEdges2Remove.end(), edge->getID()) != myEdges2Remove.end()) { myEdges2Remove.insert(one->getID()); myEdges2Remove.insert(two->getID()); } } // erase the splitted edge erase(dc, edge); insert(one, true); insert(two, true); myEdgesSplit++; return true; }
void NIXMLEdgesHandler::myEndElement(int element) { if (element == SUMO_TAG_EDGE && myCurrentEdge != 0) { // add bike lane, wait until lanes are loaded to avoid building if it already exists if (myBikeLaneWidth != NBEdge::UNSPECIFIED_WIDTH) { myCurrentEdge->addBikeLane(myBikeLaneWidth); } // add sidewalk, wait until lanes are loaded to avoid building if it already exists if (mySidewalkWidth != NBEdge::UNSPECIFIED_WIDTH) { myCurrentEdge->addSidewalk(mySidewalkWidth); } if (!myIsUpdate) { try { if (!myEdgeCont.insert(myCurrentEdge)) { WRITE_ERROR("Duplicate edge occured. ID='" + myCurrentID + "'"); delete myCurrentEdge; } } catch (InvalidArgument& e) { WRITE_ERROR(e.what()); throw; } catch (...) { WRITE_ERROR("An important information is missing in edge '" + myCurrentID + "'."); } } if (mySplits.size() != 0) { std::vector<Split>::iterator i; NBEdge* e = myCurrentEdge; sort(mySplits.begin(), mySplits.end(), split_sorter()); unsigned int noLanesMax = e->getNumLanes(); // compute the node positions and sort the lanes for (i = mySplits.begin(); i != mySplits.end(); ++i) { sort((*i).lanes.begin(), (*i).lanes.end()); noLanesMax = MAX2(noLanesMax, (unsigned int)(*i).lanes.size()); } // split the edge std::vector<int> currLanes; for (unsigned int l = 0; l < e->getNumLanes(); ++l) { currLanes.push_back(l); } if (e->getNumLanes() != mySplits.back().lanes.size()) { // invalidate traffic light definitions loaded from a SUMO network // XXX it would be preferable to reconstruct the phase definitions heuristically e->getToNode()->invalidateTLS(myTLLogicCont); // if the number of lanes changes the connections should be // recomputed e->invalidateConnections(true); } std::string edgeid = e->getID(); SUMOReal seen = 0; for (i = mySplits.begin(); i != mySplits.end(); ++i) { const Split& exp = *i; assert(exp.lanes.size() != 0); if (exp.pos > 0 && e->getGeometry().length() + seen > exp.pos && exp.pos > seen) { if (myNodeCont.insert(exp.node)) { myNodeCont.markAsSplit(exp.node); // split the edge std::string pid = e->getID(); myEdgeCont.splitAt(myDistrictCont, e, exp.pos - seen, exp.node, pid, exp.node->getID(), e->getNumLanes(), (unsigned int) exp.lanes.size(), exp.speed); seen = exp.pos; std::vector<int> newLanes = exp.lanes; NBEdge* pe = myEdgeCont.retrieve(pid); NBEdge* ne = myEdgeCont.retrieve(exp.node->getID()); // reconnect lanes pe->invalidateConnections(true); // new on right unsigned int rightMostP = currLanes[0]; unsigned int rightMostN = newLanes[0]; for (int l = 0; l < (int) rightMostP - (int) rightMostN; ++l) { pe->addLane2LaneConnection(0, ne, l, NBEdge::L2L_VALIDATED, true); } // new on left unsigned int leftMostP = currLanes.back(); unsigned int leftMostN = newLanes.back(); for (int l = 0; l < (int) leftMostN - (int) leftMostP; ++l) { pe->addLane2LaneConnection(pe->getNumLanes() - 1, ne, leftMostN - l - rightMostN, NBEdge::L2L_VALIDATED, true); } // all other connected for (unsigned int l = 0; l < noLanesMax; ++l) { if (find(currLanes.begin(), currLanes.end(), l) == currLanes.end()) { continue; } if (find(newLanes.begin(), newLanes.end(), l) == newLanes.end()) { continue; } pe->addLane2LaneConnection(l - rightMostP, ne, l - rightMostN, NBEdge::L2L_VALIDATED, true); } // move to next e = ne; currLanes = newLanes; } else { WRITE_WARNING("Error on parsing a split (edge '" + myCurrentID + "')."); } } else if (exp.pos == 0) { if (e->getNumLanes() < exp.lanes.size()) { e->incLaneNo((int) exp.lanes.size() - e->getNumLanes()); } else { e->decLaneNo(e->getNumLanes() - (int) exp.lanes.size()); } currLanes = exp.lanes; // invalidate traffic light definition loaded from a SUMO network // XXX it would be preferable to reconstruct the phase definitions heuristically e->getFromNode()->invalidateTLS(myTLLogicCont); } else { WRITE_WARNING("Split at '" + toString(exp.pos) + "' lies beyond the edge's length (edge '" + myCurrentID + "')."); } } // patch lane offsets e = myEdgeCont.retrieve(edgeid); if (mySplits.front().pos != 0) { // add a dummy split at the beginning to ensure correct offset Split start; start.pos = 0; for (int lane = 0; lane < (int)e->getNumLanes(); ++lane) { start.lanes.push_back(lane); } mySplits.insert(mySplits.begin(), start); } i = mySplits.begin(); for (; i != mySplits.end(); ++i) { unsigned int maxLeft = (*i).lanes.back(); SUMOReal offset = 0; if (maxLeft < noLanesMax) { if (e->getLaneSpreadFunction() == LANESPREAD_RIGHT) { offset = SUMO_const_laneWidthAndOffset * (noLanesMax - 1 - maxLeft); } else { offset = SUMO_const_halfLaneAndOffset * (noLanesMax - 1 - maxLeft); } } unsigned int maxRight = (*i).lanes.front(); if (maxRight > 0 && e->getLaneSpreadFunction() == LANESPREAD_CENTER) { offset -= SUMO_const_halfLaneAndOffset * maxRight; } if (offset != 0) { PositionVector g = e->getGeometry(); g.move2side(offset); e->setGeometry(g); } if (e->getToNode()->getOutgoingEdges().size() != 0) { e = e->getToNode()->getOutgoingEdges()[0]; } } } } }
void NIImporter_VISUM::parse_LanesConnections() { // get the node NBNode* node = getNamedNode("KNOTNR", "KNOT"); if (node == 0) { return; } // get the from-edge NBEdge* fromEdge = getNamedEdgeContinuating("VONSTRNR", "VONSTR", node); NBEdge* toEdge = getNamedEdgeContinuating("NACHSTRNR", "NACHSTR", node); if (fromEdge == 0 || toEdge == 0) { return; } int fromLaneOffset = 0; if (!node->hasIncoming(fromEdge)) { fromLaneOffset = fromEdge->getNumLanes(); fromEdge = getReversedContinuating(fromEdge, node); } else { fromEdge = getReversedContinuating(fromEdge, node); NBEdge* tmp = myNetBuilder.getEdgeCont().retrieve(fromEdge->getID().substr(0, fromEdge->getID().find('_'))); fromLaneOffset = tmp->getNumLanes(); } int toLaneOffset = 0; if (!node->hasOutgoing(toEdge)) { toLaneOffset = toEdge->getNumLanes(); toEdge = getReversedContinuating(toEdge, node); } else { NBEdge* tmp = myNetBuilder.getEdgeCont().retrieve(toEdge->getID().substr(0, toEdge->getID().find('_'))); toLaneOffset = tmp->getNumLanes(); } // get the from-lane std::string fromLaneS = NBHelpers::normalIDRepresentation(myLineParser.get("VONFSNR")); int fromLane = -1; try { fromLane = TplConvert::_2int(fromLaneS.c_str()); } catch (NumberFormatException&) { WRITE_ERROR("A from-lane number for edge '" + fromEdge->getID() + "' is not numeric (" + fromLaneS + ")."); return; } fromLane -= 1; if (fromLane < 0) { WRITE_ERROR("A from-lane number for edge '" + fromEdge->getID() + "' is not positive (" + fromLaneS + ")."); return; } // get the from-lane std::string toLaneS = NBHelpers::normalIDRepresentation(myLineParser.get("NACHFSNR")); int toLane = -1; try { toLane = TplConvert::_2int(toLaneS.c_str()); } catch (NumberFormatException&) { WRITE_ERROR("A to-lane number for edge '" + toEdge->getID() + "' is not numeric (" + toLaneS + ")."); return; } toLane -= 1; if (toLane < 0) { WRITE_ERROR("A to-lane number for edge '" + toEdge->getID() + "' is not positive (" + toLaneS + ")."); return; } // !!! the next is probably a hack if (fromLane - fromLaneOffset < 0) { fromLaneOffset = 0; } else { fromLane = fromEdge->getNumLanes() - (fromLane - fromLaneOffset) - 1; } if (toLane - toLaneOffset < 0) { toLaneOffset = 0; } else { toLane = toEdge->getNumLanes() - (toLane - toLaneOffset) - 1; } // if ((int) fromEdge->getNumLanes() <= fromLane) { WRITE_ERROR("A from-lane number for edge '" + fromEdge->getID() + "' is larger than the edge's lane number (" + fromLaneS + ")."); return; } if ((int) toEdge->getNumLanes() <= toLane) { WRITE_ERROR("A to-lane number for edge '" + toEdge->getID() + "' is larger than the edge's lane number (" + toLaneS + ")."); return; } // fromEdge->addLane2LaneConnection(fromLane, toEdge, toLane, NBEdge::L2L_VALIDATED); }
void NBNodeCont::joinNodeClusters(NodeClusters clusters, NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tlc) { for (NodeClusters::iterator i = clusters.begin(); i != clusters.end(); ++i) { std::set<NBNode*> cluster = *i; assert(cluster.size() > 1); Position pos; bool setTL; std::string id; TrafficLightType type; analyzeCluster(cluster, id, pos, setTL, type); if (!insert(id, pos)) { // should not fail WRITE_WARNING("Could not join junctions " + id); continue; } NBNode* newNode = retrieve(id); if (setTL) { NBTrafficLightDefinition* tlDef = new NBOwnTLDef(id, newNode, 0, type); if (!tlc.insert(tlDef)) { // actually, nothing should fail here delete tlDef; throw ProcessError("Could not allocate tls '" + id + "'."); } } // collect edges std::set<NBEdge*> allEdges; for (std::set<NBNode*>::const_iterator j = cluster.begin(); j != cluster.end(); ++j) { const EdgeVector& edges = (*j)->getEdges(); allEdges.insert(edges.begin(), edges.end()); } // remap and remove edges which are completely within the new intersection for (std::set<NBEdge*>::iterator j = allEdges.begin(); j != allEdges.end();) { NBEdge* e = (*j); NBNode* from = e->getFromNode(); NBNode* to = e->getToNode(); if (cluster.count(from) > 0 && cluster.count(to) > 0) { for (std::set<NBEdge*>::iterator l = allEdges.begin(); l != allEdges.end(); ++l) { if (e != *l) { (*l)->replaceInConnections(e, e->getConnections()); } } ec.erase(dc, e); allEdges.erase(j++); // erase does not invalidate the other iterators } else { ++j; } } // remap edges which are incoming / outgoing for (std::set<NBEdge*>::iterator j = allEdges.begin(); j != allEdges.end(); ++j) { NBEdge* e = (*j); std::vector<NBEdge::Connection> conns = e->getConnections(); const bool outgoing = cluster.count(e->getFromNode()) > 0; NBNode* from = outgoing ? newNode : e->getFromNode(); NBNode* to = outgoing ? e->getToNode() : newNode; e->reinitNodes(from, to); // re-add connections which previously existed and may still valid. // connections to removed edges will be ignored for (std::vector<NBEdge::Connection>::iterator k = conns.begin(); k != conns.end(); ++k) { e->addLane2LaneConnection((*k).fromLane, (*k).toEdge, (*k).toLane, NBEdge::L2L_USER, false, (*k).mayDefinitelyPass); } } // remove original nodes registerJoinedCluster(cluster); for (std::set<NBNode*>::const_iterator j = cluster.begin(); j != cluster.end(); ++j) { erase(*j); } } }
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); } }