void NWWriter_DlrNavteq::writeTrafficSignals(const OptionsCont& oc, NBNodeCont& nc) { OutputDevice& device = OutputDevice::getDevice(oc.getString("dlr-navteq-output") + "_traffic_signals.txt"); writeHeader(device, oc); const GeoConvHelper& gch = GeoConvHelper::getFinal(); const bool haveGeo = gch.usingGeoProjection(); const SUMOReal geoScale = pow(10.0f, haveGeo ? 5 : 2); // see NIImporter_DlrNavteq::GEO_SCALE device.setPrecision(0); // write format specifier device << "#Traffic signal related to LINK_ID and NODE_ID with location relative to driving direction.\n#column format like pointcollection.\n#DESCRIPTION->LOCATION: 1-rechts von LINK; 2-links von LINK; 3-oberhalb LINK -1-keineAngabe\n#RELATREC_ID\tPOICOL_TYPE\tDESCRIPTION\tLONGITUDE\tLATITUDE\tLINK_ID\n"; // write record for every edge incoming to a tls controlled node for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NBNode* n = (*i).second; if (n->isTLControlled()) { Position pos = n->getPosition(); gch.cartesian2geo(pos); pos.mul(geoScale); const EdgeVector& incoming = n->getIncomingEdges(); for (EdgeVector::const_iterator it = incoming.begin(); it != incoming.end(); ++it) { NBEdge* e = *it; device << e->getID() << "\t" << "12\t" // POICOL_TYPE << "LSA;NODEIDS#" << n->getID() << "#;LOCATION#-1#;\t" << pos.x() << "\t" << pos.y() << "\t" << e->getID() << "\n"; } } } }
void GNEJunction::setLogicValid(bool valid, GNEUndoList* undoList, const std::string& status) { myHasValidLogic = valid; if (!valid) { assert(undoList != 0); assert(undoList->hasCommandGroup()); undoList->add(new GNEChange_Attribute(this, GNE_ATTR_MODIFICATION_STATUS, status)); // allow edges to recompute their connections NBTurningDirectionsComputer::computeTurnDirectionsForNode(&myNBNode, false); EdgeVector incoming = EdgeVector(myNBNode.getIncomingEdges()); for (EdgeVector::iterator it = incoming.begin(); it != incoming.end(); it++) { NBEdge* srcNBE = *it; NBEdge* turnEdge = srcNBE->getTurnDestination(); GNEEdge* srcEdge = myNet->retrieveEdge(srcNBE->getID()); std::vector<NBEdge::Connection> connections = srcNBE->getConnections(); // make a copy! // delete in reverse so that undoing will add connections in the original order for (std::vector<NBEdge::Connection>::reverse_iterator con_it = connections.rbegin(); con_it != connections.rend(); con_it++) { bool hasTurn = con_it->toEdge == turnEdge; undoList->add(new GNEChange_Connection( srcEdge, con_it->fromLane, con_it->toEdge->getID(), con_it->toLane, con_it->mayDefinitelyPass, false), true); // needs to come after GNEChange_Connection // XXX bug: this code path will not be used on a redo! if (hasTurn) { myNet->addExplicitTurnaround(srcNBE->getID()); } } undoList->add(new GNEChange_Attribute(srcEdge, GNE_ATTR_MODIFICATION_STATUS, status), true); } invalidateTLS(undoList); } else { rebuildCrossings(false); } }
void NWWriter_DlrNavteq::writeLinksUnsplitted(const OptionsCont& oc, NBEdgeCont& ec) { std::map<const std::string, std::string> nameIDs; OutputDevice& device = OutputDevice::getDevice(oc.getString("dlr-navteq-output") + "_links_unsplitted.txt"); writeHeader(device, oc); // write format specifier device << "# LINK_ID\tNODE_ID_FROM\tNODE_ID_TO\tBETWEEN_NODE_ID\tLENGTH\tVEHICLE_TYPE\tFORM_OF_WAY\tBRUNNEL_TYPE\tFUNCTIONAL_ROAD_CLASS\tSPEED_CATEGORY\tNUMBER_OF_LANES\tSPEED_LIMIT\tSPEED_RESTRICTION\tNAME_ID1_REGIONAL\tNAME_ID2_LOCAL\tHOUSENUMBERS_RIGHT\tHOUSENUMBERS_LEFT\tZIP_CODE\tAREA_ID\tSUBAREA_ID\tTHROUGH_TRAFFIC\tSPECIAL_RESTRICTIONS\tEXTENDED_NUMBER_OF_LANES\tISRAMP\tCONNECTION\n"; // write edges for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) { NBEdge* e = (*i).second; const int kph = speedInKph(e->getSpeed()); const std::string& betweenNodeID = (e->getGeometry().size() > 2) ? e->getID() : UNDEFINED; std::string nameID = UNDEFINED; if (oc.getBool("output.street-names")) { const std::string& name = i->second->getStreetName(); if (name != "" && nameIDs.count(name) == 0) { nameID = toString(nameIDs.size()); nameIDs[name] = nameID; } } device << e->getID() << "\t" << e->getFromNode()->getID() << "\t" << e->getToNode()->getID() << "\t" << betweenNodeID << "\t" << getGraphLength(e) << "\t" << getAllowedTypes(e->getPermissions()) << "\t" << "3\t" // Speed Category 1-8 XXX refine this << UNDEFINED << "\t" // no special brunnel type (we don't know yet) << getRoadClass(e) << "\t" << getSpeedCategory(kph) << "\t" << getNavteqLaneCode(e->getNumLanes()) << "\t" << getSpeedCategoryUpperBound(kph) << "\t" << kph << "\t" << nameID << "\t" // NAME_ID1_REGIONAL XXX << UNDEFINED << "\t" // NAME_ID2_LOCAL XXX << UNDEFINED << "\t" // housenumbers_right << UNDEFINED << "\t" // housenumbers_left << UNDEFINED << "\t" // ZIP_CODE << UNDEFINED << "\t" // AREA_ID << UNDEFINED << "\t" // SUBAREA_ID << "1\t" // through_traffic (allowed) << UNDEFINED << "\t" // special_restrictions << UNDEFINED << "\t" // extended_number_of_lanes << UNDEFINED << "\t" // isRamp << "0\t" // connection (between nodes always in order) << "\n"; } if (oc.getBool("output.street-names")) { OutputDevice& namesDevice = OutputDevice::getDevice(oc.getString("dlr-navteq-output") + "_names.txt"); writeHeader(namesDevice, oc); // write format specifier namesDevice << "# NAME_ID\tName\n" << nameIDs.size() << "\n"; for (std::map<const std::string, std::string>::const_iterator i = nameIDs.begin(); i != nameIDs.end(); ++i) { namesDevice << i->second << "\t" << i->first << "\n"; } } }
void NIXMLTrafficLightsHandler::addTlConnection(const SUMOSAXAttributes& attrs) { bool ok = true; // parse identifying attributes NBEdge* from = retrieveEdge(attrs, SUMO_ATTR_FROM, ok); NBEdge* to = retrieveEdge(attrs, SUMO_ATTR_TO, ok); if (!ok) { return; } int fromLane = retrieveLaneIndex(attrs, SUMO_ATTR_FROM_LANE, from, ok); int toLane = retrieveLaneIndex(attrs, SUMO_ATTR_TO_LANE, to, ok); if (!ok) { return; } // retrieve connection const std::vector<NBEdge::Connection>& connections = from->getConnections(); std::vector<NBEdge::Connection>::const_iterator con_it; con_it = find_if(connections.begin(), connections.end(), NBEdge::connections_finder(fromLane, to, toLane)); if (con_it == connections.end()) { WRITE_ERROR("Connection from=" + from->getID() + " to=" + to->getID() + " fromLane=" + toString(fromLane) + " toLane=" + toString(toLane) + " not found"); return; } NBEdge::Connection c = *con_it; // read other attributes std::string tlID = attrs.getOptStringReporting(SUMO_ATTR_TLID, 0, ok, ""); if (tlID == "") { // we are updating an existing tl-controlled connection tlID = c.tlID; assert(tlID != ""); } int tlIndex = attrs.getOptIntReporting(SUMO_ATTR_TLLINKINDEX, 0, ok, -1); if (tlIndex == -1) { // we are updating an existing tl-controlled connection tlIndex = c.tlLinkNo; } // register the connection with all definitions const std::map<std::string, NBTrafficLightDefinition*>& programs = myTLLCont.getPrograms(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(from, c.toEdge, c.fromLane, c.toLane, tlIndex); } else { throw ProcessError("Corrupt traffic light definition '" + tlID + "' (program '" + it->first + "')"); } } } else { WRITE_ERROR("The traffic light '" + tlID + "' is not known."); } }
NBEdge* NIImporter_VISUM::getNamedEdgeContinuating(NBEdge* begin, NBNode* node) { if (begin == 0) { return 0; } NBEdge* ret = begin; std::string edgeID = ret->getID(); // hangle forward while (ret != 0) { // ok, this is the edge we are looking for if (ret->getToNode() == node) { return ret; } const EdgeVector& nedges = ret->getToNode()->getOutgoingEdges(); if (nedges.size() != 1) { // too many edges follow ret = 0; continue; } NBEdge* next = nedges[0]; if (ret->getID().substr(0, edgeID.length()) != next->getID().substr(0, edgeID.length())) { // ok, another edge is next... ret = 0; continue; } if (next->getID().substr(next->getID().length() - node->getID().length()) != node->getID()) { ret = 0; continue; } ret = next; } ret = begin; // hangle backward while (ret != 0) { // ok, this is the edge we are looking for if (ret->getFromNode() == node) { return ret; } const EdgeVector& nedges = ret->getFromNode()->getIncomingEdges(); if (nedges.size() != 1) { // too many edges follow ret = 0; continue; } NBEdge* next = nedges[0]; if (ret->getID().substr(0, edgeID.length()) != next->getID().substr(0, edgeID.length())) { // ok, another edge is next... ret = 0; continue; } if (next->getID().substr(next->getID().length() - node->getID().length()) != node->getID()) { ret = 0; continue; } ret = next; } return 0; }
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.retrievePossiblySplit(toString(vissimFrom->getID()), toString(getFromEdgeID()), true); } } else { // this edge was built, try to get the proper part fromEdge = ec.retrievePossiblySplit(toString(getFromEdgeID()), toString(getToEdgeID()), true); } NIVissimEdge* vissimTo = NIVissimEdge::dictionary(getToEdgeID()); if (vissimTo->wasWithinAJunction()) { vissimTo = vissimTo->getBestOutgoing(); if (vissimTo != 0) { toEdge = ec.retrievePossiblySplit(toString(vissimTo->getID()), toString(getToEdgeID()), true); } } else { toEdge = ec.retrievePossiblySplit(toString(getToEdgeID()), toString(getFromEdgeID()), false); } // try to get the edges the current connection connects /* NBEdge *fromEdge = ec.retrievePossiblySplit(toString(getFromEdgeID()), toString(getToEdgeID()), true); NBEdge *toEdge = ec.retrievePossiblySplit(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 std::vector<int>& fromLanes = getFromLanes(); const std::vector<int>& toLanes = getToLanes(); if (fromLanes.size() != toLanes.size()) { WRITE_WARNING("Lane sizes differ for connection '" + toString(getID()) + "'."); } else { for (unsigned int index = 0; index < fromLanes.size(); ++index) { if (fromEdge->getNumLanes() <= static_cast<unsigned int>(fromLanes[index])) { WRITE_WARNING("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)) { WRITE_WARNING("Could not set connection between '" + fromEdge->getID() + "_" + toString(fromLanes[index]) + "' and '" + toEdge->getID() + "_" + toString(toLanes[index]) + "'."); ++unsetConnections; } } } return unsetConnections; }
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 NBNodeCont::removeUnwishedNodes(NBDistrictCont& dc, NBEdgeCont& ec, NBJoinedEdgesMap& je, NBTrafficLightLogicCont& tlc, bool removeGeometryNodes) { unsigned int no = 0; std::vector<NBNode*> toRemove; for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) { NBNode* current = (*i).second; bool remove = false; std::vector<std::pair<NBEdge*, NBEdge*> > toJoin; // check for completely empty nodes if (current->getOutgoingEdges().size() == 0 && current->getIncomingEdges().size() == 0) { // remove if empty remove = true; } // check for nodes which are only geometry nodes if (removeGeometryNodes) { if ((current->getOutgoingEdges().size() == 1 && current->getIncomingEdges().size() == 1) || (current->getOutgoingEdges().size() == 2 && current->getIncomingEdges().size() == 2)) { // ok, one in, one out or two in, two out // -> ask the node whether to join remove = current->checkIsRemovable(); if (remove) { toJoin = current->getEdgesToJoin(); } } } // remove the node and join the geometries when wished if (!remove) { continue; } for (std::vector<std::pair<NBEdge*, NBEdge*> >::iterator j = toJoin.begin(); j != toJoin.end(); j++) { NBEdge* begin = (*j).first; NBEdge* continuation = (*j).second; begin->append(continuation); continuation->getToNode()->replaceIncoming(continuation, begin, 0); tlc.replaceRemoved(continuation, -1, begin, -1); je.appended(begin->getID(), continuation->getID()); ec.erase(dc, continuation); } toRemove.push_back(current); no++; } // erase all for (std::vector<NBNode*>::iterator j = toRemove.begin(); j != toRemove.end(); ++j) { erase(*j); } return no; }
void NWWriter_SUMO::writeEdge(OutputDevice& into, const NBEdge& e, bool noNames, bool origNames) { // write the edge's begin into.openTag(SUMO_TAG_EDGE).writeAttr(SUMO_ATTR_ID, e.getID()); into.writeAttr(SUMO_ATTR_FROM, e.getFromNode()->getID()); into.writeAttr(SUMO_ATTR_TO, e.getToNode()->getID()); if (!noNames && e.getStreetName() != "") { into.writeAttr(SUMO_ATTR_NAME, StringUtils::escapeXML(e.getStreetName())); } into.writeAttr(SUMO_ATTR_PRIORITY, e.getPriority()); if (e.getTypeID() != "") { into.writeAttr(SUMO_ATTR_TYPE, e.getTypeID()); } if (e.isMacroscopicConnector()) { into.writeAttr(SUMO_ATTR_FUNCTION, EDGEFUNC_CONNECTOR); } // write the spread type if not default ("right") if (e.getLaneSpreadFunction() != LANESPREAD_RIGHT) { into.writeAttr(SUMO_ATTR_SPREADTYPE, e.getLaneSpreadFunction()); } if (e.hasLoadedLength()) { into.writeAttr(SUMO_ATTR_LENGTH, e.getLoadedLength()); } if (!e.hasDefaultGeometry()) { into.writeAttr(SUMO_ATTR_SHAPE, e.getGeometry()); } // write the lanes const std::vector<NBEdge::Lane>& lanes = e.getLanes(); SUMOReal length = e.getLoadedLength(); if (OptionsCont::getOptions().getBool("no-internal-links") && !e.hasLoadedLength()) { // use length to junction center even if a modified geometry was given PositionVector geom = e.cutAtIntersection(e.getGeometry()); geom.push_back_noDoublePos(e.getToNode()->getCenter()); geom.push_front_noDoublePos(e.getFromNode()->getCenter()); length = geom.length(); } if (length <= 0) { length = POSITION_EPS; } for (unsigned int i = 0; i < (unsigned int) lanes.size(); i++) { const NBEdge::Lane& l = lanes[i]; writeLane(into, e.getID(), e.getLaneID(i), l.speed, l.permissions, l.preferred, l.endOffset, l.width, l.shape, l.origID, length, i, origNames); } // close the edge into.closeTag(); }
void NBTrafficLightDefinition::collectEdges() { myIncomingEdges.clear(); myEdgesWithin.clear(); EdgeVector myOutgoing; // collect the edges from the participating nodes for (std::vector<NBNode*>::iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) { const EdgeVector& incoming = (*i)->getIncomingEdges(); copy(incoming.begin(), incoming.end(), back_inserter(myIncomingEdges)); const EdgeVector& outgoing = (*i)->getOutgoingEdges(); copy(outgoing.begin(), outgoing.end(), back_inserter(myOutgoing)); } EdgeVector outer; // check which of the edges are completely within the junction // add them to the list of edges lying within the node for (EdgeVector::iterator j = myIncomingEdges.begin(); j != myIncomingEdges.end(); ++j) { NBEdge* edge = *j; // an edge lies within the logic if it is outgoing as well as incoming EdgeVector::iterator k = find(myOutgoing.begin(), myOutgoing.end(), edge); if (k != myOutgoing.end()) { myEdgesWithin.push_back(edge); } else { outer.push_back(edge); } } // collect edges that are reachable from the outside via controlled connections std::set<NBEdge*> reachable = collectReachable(outer, myEdgesWithin, true); // collect edges that are reachable from the outside regardless of controllability std::set<NBEdge*> reachable2 = collectReachable(outer, myEdgesWithin, false); const bool uncontrolledWithin = OptionsCont::getOptions().getBool("tls.uncontrolled-within"); for (EdgeVector::iterator j = myEdgesWithin.begin(); j != myEdgesWithin.end(); ++j) { NBEdge* edge = *j; // edges that are marked as 'inner' will not get their own phase when // computing traffic light logics (unless they cannot be reached from the outside at all) if (reachable.count(edge) == 1) { edge->setIsInnerEdge(); // legacy behavior if (uncontrolledWithin && myControlledInnerEdges.count(edge->getID()) == 0) { myIncomingEdges.erase(find(myIncomingEdges.begin(), myIncomingEdges.end(), edge)); } } if (reachable2.count(edge) == 0 && edge->getFirstNonPedestrianLaneIndex(NBNode::FORWARD, true) >= 0 && getID() != DummyID) { WRITE_WARNING("Unreachable edge '" + edge->getID() + "' within tlLogic '" + getID() + "'"); } } }
void NWWriter_DlrNavteq::writeConnectedLanes(const OptionsCont& oc, NBNodeCont& nc) { OutputDevice& device = OutputDevice::getDevice(oc.getString("dlr-navteq-output") + "_connected_lanes.txt"); writeHeader(device, oc); // write format specifier device << "#Lane connections related to LINK-IDs and NODE-ID.\n"; device << "#column format like pointcollection.\n"; device << "#NODE-ID\tVEHICLE-TYPE\tFROM_LANE\tTO_LANE\tTHROUGH_TRAFFIC\tLINK_IDs[2..*]\n"; // write record for every connection for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NBNode* n = (*i).second; const EdgeVector& incoming = n->getIncomingEdges(); for (EdgeVector::const_iterator j = incoming.begin(); j != incoming.end(); ++j) { NBEdge* from = *j; const SVCPermissions fromPerm = from->getPermissions(); const std::vector<NBEdge::Connection>& connections = from->getConnections(); for (std::vector<NBEdge::Connection>::const_iterator it_c = connections.begin(); it_c != connections.end(); it_c++) { const NBEdge::Connection& c = *it_c; device << n->getID() << "\t" << getAllowedTypes(fromPerm & c.toEdge->getPermissions()) << "\t" << c.fromLane + 1 << "\t" // one-based << c.toLane + 1 << "\t" // one-based << 1 << "\t" // no information regarding permissibility of through traffic << from->getID() << "\t" << c.toEdge->getID() << "\t" << "\n"; } } } device.close(); }
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); } } } }
void NBTrafficLightDefinition::collectAllLinks() { myControlledLinks.clear(); int tlIndex = 0; // build the list of links which are controled by the traffic light for (EdgeVector::iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) { NBEdge* incoming = *i; unsigned int noLanes = incoming->getNumLanes(); for (unsigned int j = 0; j < noLanes; j++) { std::vector<NBEdge::Connection> connected = incoming->getConnectionsFromLane(j); for (std::vector<NBEdge::Connection>::iterator k = connected.begin(); k != connected.end(); k++) { const NBEdge::Connection& el = *k; if (incoming->mayBeTLSControlled(el.fromLane, el.toEdge, el.toLane)) { if (el.toEdge != 0 && el.toLane >= (int) el.toEdge->getNumLanes()) { throw ProcessError("Connection '" + incoming->getID() + "_" + toString(j) + "->" + el.toEdge->getID() + "_" + toString(el.toLane) + "' yields in a not existing lane."); } if (incoming->getToNode()->getType() != NODETYPE_RAIL_CROSSING || !isRailway(incoming->getPermissions())) { myControlledLinks.push_back(NBConnection(incoming, el.fromLane, el.toEdge, el.toLane, tlIndex++)); } else { myControlledLinks.push_back(NBConnection(incoming, el.fromLane, el.toEdge, el.toLane, -1)); } } } } } }
void NWWriter_SUMO::writeConnection(OutputDevice& into, const NBEdge& from, const NBEdge::Connection& c, bool includeInternal, ConnectionStyle style) { assert(c.toEdge != 0); into.openTag(SUMO_TAG_CONNECTION); into.writeAttr(SUMO_ATTR_FROM, from.getID()); into.writeAttr(SUMO_ATTR_TO, c.toEdge->getID()); into.writeAttr(SUMO_ATTR_FROM_LANE, c.fromLane); into.writeAttr(SUMO_ATTR_TO_LANE, c.toLane); if (c.mayDefinitelyPass) { into.writeAttr(SUMO_ATTR_PASS, c.mayDefinitelyPass); } if (style != PLAIN) { if (includeInternal) { into.writeAttr(SUMO_ATTR_VIA, c.id + "_0"); } // set information about the controlling tl if any if (c.tlID != "") { into.writeAttr(SUMO_ATTR_TLID, c.tlID); into.writeAttr(SUMO_ATTR_TLLINKINDEX, c.tlLinkNo); } if (style == SUMONET) { // write the direction information LinkDirection dir = from.getToNode()->getDirection(&from, c.toEdge); assert(dir != LINKDIR_NODIR); into.writeAttr(SUMO_ATTR_DIR, toString(dir)); // write the state information const LinkState linkState = from.getToNode()->getLinkState( &from, c.toEdge, c.toLane, c.mayDefinitelyPass, c.tlID); into.writeAttr(SUMO_ATTR_STATE, linkState); } } into.closeTag(); }
void NWWriter_DlrNavteq::writeNodesUnsplitted(const OptionsCont& oc, NBNodeCont& nc, NBEdgeCont& ec) { // For "real" nodes we simply use the node id. // For internal nodes (geometry vectors describing edge geometry in the parlance of this format) // we use the id of the edge and do not bother with // compression (each direction gets its own internal node). // XXX add option for generating numerical ids in case the input network has string ids and the target process needs integers OutputDevice& device = OutputDevice::getDevice(oc.getString("dlr-navteq-output") + "_nodes_unsplitted.txt"); writeHeader(device, oc); const GeoConvHelper& gch = GeoConvHelper::getFinal(); const bool haveGeo = gch.usingGeoProjection(); const SUMOReal geoScale = pow(10.0f, haveGeo ? 5 : 2); // see NIImporter_DlrNavteq::GEO_SCALE device.setPrecision(0); if (!haveGeo) { WRITE_WARNING("DlrNavteq node data will be written in (floating point) cartesian coordinates"); } // write format specifier device << "# NODE_ID\tIS_BETWEEN_NODE\tamount_of_geocoordinates\tx1\ty1\t[x2 y2 ... xn yn]\n"; // write normal nodes for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NBNode* n = (*i).second; Position pos = n->getPosition(); gch.cartesian2geo(pos); pos.mul(geoScale); device << n->getID() << "\t0\t1\t" << pos.x() << "\t" << pos.y() << "\n"; } // write "internal" nodes for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) { NBEdge* e = (*i).second; const PositionVector& geom = e->getGeometry(); if (geom.size() > 2) { if (e->getID() == UNDEFINED) { WRITE_WARNING("Edge id '" + UNDEFINED + "' clashes with the magic value for NO_BETWEEN_NODE. Internal geometry for this edge will be lost."); } device << e->getID() << "\t1\t" << geom.size() - 2; for (size_t ii = 1; ii < geom.size() - 1; ++ii) { Position pos = geom[(int)ii]; gch.cartesian2geo(pos); pos.mul(geoScale); device << "\t" << pos.x() << "\t" << pos.y(); } device << "\n"; } } device.close(); }
void NBLoadedSUMOTLDef::collectEdges() { if (myControlledLinks.size() == 0) { NBTrafficLightDefinition::collectEdges(); } myIncomingEdges.clear(); EdgeVector myOutgoing; // collect the edges from the participating nodes for (std::vector<NBNode*>::iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) { const EdgeVector& incoming = (*i)->getIncomingEdges(); copy(incoming.begin(), incoming.end(), back_inserter(myIncomingEdges)); const EdgeVector& outgoing = (*i)->getOutgoingEdges(); copy(outgoing.begin(), outgoing.end(), back_inserter(myOutgoing)); } // check which of the edges are completely within the junction // and which are uncontrolled as well (we already know myControlledLinks) for (EdgeVector::iterator j = myIncomingEdges.begin(); j != myIncomingEdges.end();) { NBEdge* edge = *j; // an edge lies within the logic if it is outgoing as well as incoming EdgeVector::iterator k = find(myOutgoing.begin(), myOutgoing.end(), edge); if (k != myOutgoing.end()) { if (myControlledInnerEdges.count(edge->getID()) == 0) { bool controlled = false; for (NBConnectionVector::iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) { if ((*it).getFrom() == edge) { controlled = true; break; } } if (controlled) { myControlledInnerEdges.insert(edge->getID()); } else { myEdgesWithin.push_back(edge); (*j)->setIsInnerEdge(); ++j; //j = myIncomingEdges.erase(j); continue; } } } ++j; } }
void NWWriter_DlrNavteq::writeProhibitedManoeuvres(const OptionsCont& oc, const NBNodeCont& nc, const NBEdgeCont& ec) { OutputDevice& device = OutputDevice::getDevice(oc.getString("dlr-navteq-output") + "_prohibited_manoeuvres.txt"); writeHeader(device, oc); // need to invent id for relation std::set<std::string> reservedRelIDs; if (oc.isSet("reserved-ids")) { NBHelpers::loadPrefixedIDsFomFile(oc.getString("reserved-ids"), "rel:", reservedRelIDs); } std::vector<std::string> avoid = ec.getAllNames(); // already used for tls RELATREC_ID avoid.insert(avoid.end(), reservedRelIDs.begin(), reservedRelIDs.end()); IDSupplier idSupplier("", avoid); // @note: use a global relRecIDsupplier if this is used more often // write format specifier device << "#No driving allowed from ID1 to ID2 or the complete chain from ID1 to IDn\n"; device << "#RELATREC_ID\tPERMANENT_ID_INFO\tVALIDITY_PERIOD\tTHROUGH_TRAFFIC\tVEHICLE_TYPE\tNAVTEQ_LINK_ID1\t[NAVTEQ_LINK_ID2 ...]\n"; // write record for every pair of incoming/outgoing edge that are not connected despite having common permissions for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NBNode* n = (*i).second; const EdgeVector& incoming = n->getIncomingEdges(); const EdgeVector& outgoing = n->getOutgoingEdges(); for (EdgeVector::const_iterator j = incoming.begin(); j != incoming.end(); ++j) { NBEdge* inEdge = *j; const SVCPermissions inPerm = inEdge->getPermissions(); for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); ++k) { NBEdge* outEdge = *k; const SVCPermissions outPerm = outEdge->getPermissions(); const SVCPermissions commonPerm = inPerm & outPerm; if (commonPerm != 0 && commonPerm != SVC_PEDESTRIAN && !inEdge->isConnectedTo(outEdge)) { device << idSupplier.getNext() << "\t" << 1 << "\t" // permanent id << UNDEFINED << "\t" << 1 << "\t" << getAllowedTypes(SVCAll) << "\t" << inEdge->getID() << "\t" << outEdge->getID() << "\n"; } } } } device.close(); }
void NWWriter_SUMO::writeEdge(OutputDevice& into, const NBEdge& e, bool noNames, bool origNames) { // write the edge's begin into.openTag(SUMO_TAG_EDGE).writeAttr(SUMO_ATTR_ID, e.getID()); into.writeAttr(SUMO_ATTR_FROM, e.getFromNode()->getID()); into.writeAttr(SUMO_ATTR_TO, e.getToNode()->getID()); if (!noNames && e.getStreetName() != "") { into.writeAttr(SUMO_ATTR_NAME, StringUtils::escapeXML(e.getStreetName())); } into.writeAttr(SUMO_ATTR_PRIORITY, e.getPriority()); if (e.getTypeName() != "") { into.writeAttr(SUMO_ATTR_TYPE, e.getTypeName()); } if (e.isMacroscopicConnector()) { into.writeAttr(SUMO_ATTR_FUNCTION, EDGEFUNC_CONNECTOR); } // write the spread type if not default ("right") if (e.getLaneSpreadFunction() != LANESPREAD_RIGHT) { into.writeAttr(SUMO_ATTR_SPREADTYPE, e.getLaneSpreadFunction()); } if (e.hasLoadedLength()) { into.writeAttr(SUMO_ATTR_LENGTH, e.getLoadedLength()); } if (!e.hasDefaultGeometry()) { into.writeAttr(SUMO_ATTR_SHAPE, e.getGeometry()); } // write the lanes const std::vector<NBEdge::Lane>& lanes = e.getLanes(); SUMOReal length = e.getLoadedLength(); if (length <= 0) { length = (SUMOReal) .1; } for (unsigned int i = 0; i < (unsigned int) lanes.size(); i++) { writeLane(into, e.getID(), e.getLaneID(i), lanes[i], length, i, origNames); } // close the edge into.closeTag(); }
// ----- Adapting the input void NBEdgeCont::removeUnwishedEdges(NBDistrictCont& dc) { EdgeVector toRemove; for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) { NBEdge* edge = (*i).second; if (!myEdges2Keep.count(edge->getID())) { edge->getFromNode()->removeEdge(edge); edge->getToNode()->removeEdge(edge); toRemove.push_back(edge); } } for (EdgeVector::iterator j = toRemove.begin(); j != toRemove.end(); ++j) { erase(dc, *j); } }
void NBOwnTLDef::collectLinks() throw(ProcessError) { // build the list of links which are controled by the traffic light for (EdgeVector::iterator i=myIncomingEdges.begin(); i!=myIncomingEdges.end(); i++) { NBEdge *incoming = *i; unsigned int noLanes = incoming->getNoLanes(); for (unsigned int j=0; j<noLanes; j++) { std::vector<NBEdge::Connection> connected = incoming->getConnectionsFromLane(j); for (std::vector<NBEdge::Connection>::iterator k=connected.begin(); k!=connected.end(); k++) { const NBEdge::Connection &el = *k; if (incoming->mayBeTLSControlled(el.fromLane, el.toEdge, el.toLane)) { if (el.toEdge!=0&&el.toLane>=(int) el.toEdge->getNoLanes()) { throw ProcessError("Connection '" + incoming->getID() + "_" + toString(j) + "->" + el.toEdge->getID() + "_" + toString(el.toLane) + "' yields in a not existing lane."); } myControlledLinks.push_back(NBConnection(incoming, j, el.toEdge, el.toLane)); } } } } }
void NWWriter_SUMO::writeConnection(OutputDevice& into, const NBEdge& from, const NBEdge::Connection& c, bool includeInternal, ConnectionStyle style) { assert(c.toEdge != 0); into.openTag(SUMO_TAG_CONNECTION); into.writeAttr(SUMO_ATTR_FROM, from.getID()); into.writeAttr(SUMO_ATTR_TO, c.toEdge->getID()); into.writeAttr(SUMO_ATTR_FROM_LANE, c.fromLane); into.writeAttr(SUMO_ATTR_TO_LANE, c.toLane); if (c.mayDefinitelyPass && style != TLL) { into.writeAttr(SUMO_ATTR_PASS, c.mayDefinitelyPass); } if ((from.getToNode()->getKeepClear() == false || c.keepClear == false) && style != TLL) { into.writeAttr<bool>(SUMO_ATTR_KEEP_CLEAR, false); } if (c.contPos != NBEdge::UNSPECIFIED_CONTPOS && style != TLL) { into.writeAttr(SUMO_ATTR_CONTPOS, c.contPos); } if (style != PLAIN) { if (includeInternal) { into.writeAttr(SUMO_ATTR_VIA, c.getInternalLaneID()); } // set information about the controlling tl if any if (c.tlID != "") { into.writeAttr(SUMO_ATTR_TLID, c.tlID); into.writeAttr(SUMO_ATTR_TLLINKINDEX, c.tlLinkNo); } if (style == SUMONET) { // write the direction information LinkDirection dir = from.getToNode()->getDirection(&from, c.toEdge, OptionsCont::getOptions().getBool("lefthand")); assert(dir != LINKDIR_NODIR); into.writeAttr(SUMO_ATTR_DIR, toString(dir)); // write the state information const LinkState linkState = from.getToNode()->getLinkState( &from, c.toEdge, c.fromLane, c.toLane, c.mayDefinitelyPass, c.tlID); into.writeAttr(SUMO_ATTR_STATE, linkState); } } into.closeTag(); }
void NIImporter_VISUM::parse_Lanes() { // get the node NBNode* node = getNamedNode("KNOTNR"); // get the edge NBEdge* baseEdge = getNamedEdge("STRNR"); NBEdge* edge = getNamedEdgeContinuating("STRNR", node); // check if (node == 0 || edge == 0) { return; } // get the lane std::string laneS = myLineParser.know("FSNR") ? NBHelpers::normalIDRepresentation(myLineParser.get("FSNR")) : NBHelpers::normalIDRepresentation(myLineParser.get("NR")); int lane = -1; try { lane = TplConvert::_2int(laneS.c_str()); } catch (NumberFormatException&) { WRITE_ERROR("A lane number for edge '" + edge->getID() + "' is not numeric (" + laneS + ")."); return; } lane -= 1; if (lane < 0) { WRITE_ERROR("A lane number for edge '" + edge->getID() + "' is not positive (" + laneS + ")."); return; } // get the direction std::string dirS = NBHelpers::normalIDRepresentation(myLineParser.get("RICHTTYP")); int prevLaneNo = baseEdge->getNumLanes(); if ((dirS == "1" && !(node->hasIncoming(edge))) || (dirS == "0" && !(node->hasOutgoing(edge)))) { // get the last part of the turnaround direction edge = getReversedContinuating(edge, node); } // get the length std::string lengthS = NBHelpers::normalIDRepresentation(myLineParser.get("LAENGE")); SUMOReal length = -1; try { length = TplConvert::_2SUMOReal(lengthS.c_str()); } catch (NumberFormatException&) { WRITE_ERROR("A lane length for edge '" + edge->getID() + "' is not numeric (" + lengthS + ")."); return; } if (length < 0) { WRITE_ERROR("A lane length for edge '" + edge->getID() + "' is not positive (" + lengthS + ")."); return; } // if (dirS == "1") { lane -= prevLaneNo; } // if (length == 0) { if ((int) edge->getNumLanes() > lane) { // ok, we know this already... return; } // increment by one edge->incLaneNo(1); } else { // check whether this edge already has been created if (edge->getID().substr(edge->getID().length() - node->getID().length() - 1) == "_" + node->getID()) { if (edge->getID().substr(edge->getID().find('_')) == "_" + toString(length) + "_" + node->getID()) { if ((int) edge->getNumLanes() > lane) { // ok, we know this already... return; } // increment by one edge->incLaneNo(1); return; } } // nope, we have to split the edge... // maybe it is not the proper edge to split - VISUM seems not to sort the splits... bool mustRecheck = true; SUMOReal seenLength = 0; while (mustRecheck) { if (edge->getID().substr(edge->getID().length() - node->getID().length() - 1) == "_" + node->getID()) { // ok, we have a previously created edge here std::string sub = edge->getID(); sub = sub.substr(sub.rfind('_', sub.rfind('_') - 1)); sub = sub.substr(1, sub.find('_', 1) - 1); SUMOReal dist = TplConvert::_2SUMOReal(sub.c_str()); if (dist < length) { seenLength += edge->getLength(); if (dirS == "1") { // incoming -> move back edge = edge->getFromNode()->getIncomingEdges()[0]; } else { // outgoing -> move forward edge = edge->getToNode()->getOutgoingEdges()[0]; } } else { mustRecheck = false; } } else { // we have the center edge - do not continue... mustRecheck = false; } } // compute position Position p; SUMOReal useLength = length - seenLength; useLength = edge->getLength() - useLength; std::string edgeID = edge->getID(); p = edge->getGeometry().positionAtLengthPosition(useLength); if (edgeID.substr(edgeID.length() - node->getID().length() - 1) == "_" + node->getID()) { edgeID = edgeID.substr(0, edgeID.find('_')); } NBNode* rn = new NBNode(edgeID + "_" + toString((size_t) length) + "_" + node->getID(), p); if (!myNetBuilder.getNodeCont().insert(rn)) { throw ProcessError("Ups - could not insert node!"); } std::string nid = edgeID + "_" + toString((size_t) length) + "_" + node->getID(); myNetBuilder.getEdgeCont().splitAt(myNetBuilder.getDistrictCont(), edge, useLength, rn, edge->getID(), nid, edge->getNumLanes() + 0, edge->getNumLanes() + 1); NBEdge* nedge = myNetBuilder.getEdgeCont().retrieve(nid); nedge = nedge->getToNode()->getOutgoingEdges()[0]; while (nedge->getID().substr(nedge->getID().length() - node->getID().length() - 1) == "_" + node->getID()) { assert(nedge->getToNode()->getOutgoingEdges().size() > 0); nedge->incLaneNo(1); nedge = nedge->getToNode()->getOutgoingEdges()[0]; } } }
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]; } } } } }
void NIVissimEdge::buildNBEdge(NBDistrictCont& dc, NBNodeCont& nc, NBEdgeCont& ec, SUMOReal sameNodesOffset) { // build the edge std::pair<NIVissimConnectionCluster*, NBNode*> fromInf, toInf; NBNode* fromNode, *toNode; fromNode = toNode = 0; sort(myConnectionClusters.begin(), myConnectionClusters.end(), connection_cluster_position_sorter(myID)); sort(myDistrictConnections.begin(), myDistrictConnections.end()); ConnectionClusters tmpClusters = myConnectionClusters; if (tmpClusters.size() != 0) { sort(tmpClusters.begin(), tmpClusters.end(), connection_cluster_position_sorter(myID)); // get or build the from-node // A node may have to be build when the edge starts or ends at // a parking place or something like this fromInf = getFromNode(nc, tmpClusters); fromNode = fromInf.second; // get or build the to-node //if(tmpClusters.size()>0) { toInf = getToNode(nc, tmpClusters); toNode = toInf.second; if (fromInf.first != 0 && toNode != 0 && fromInf.first->around(toNode->getPosition())) { WRITE_WARNING("Will not build edge '" + toString(myID) + "'."); myAmWithinJunction = true; return; } //} // if both nodes are the same, resolve the problem otherwise if (fromNode == toNode) { std::pair<NBNode*, NBNode*> tmp = resolveSameNode(nc, sameNodesOffset, fromNode, toNode); if (fromNode != tmp.first) { fromInf.first = 0; } if (toNode != tmp.second) { toInf.first = 0; } fromNode = tmp.first; toNode = tmp.second; } } // if (fromNode == 0) { fromInf.first = 0; Position pos = myGeom[0]; fromNode = new NBNode(toString<int>(myID) + "-SourceNode", pos, NODETYPE_NOJUNCTION); if (!nc.insert(fromNode)) { throw ProcessError("Could not insert node '" + fromNode->getID() + "' to nodes container."); } } if (toNode == 0) { toInf.first = 0; Position pos = myGeom[-1]; toNode = new NBNode(toString<int>(myID) + "-DestinationNode", pos, NODETYPE_NOJUNCTION); if (!nc.insert(toNode)) { throw ProcessError("Could not insert node '" + toNode->getID() + "' to nodes container."); } } // build the edge SUMOReal avgSpeed = 0; int i; for (i = 0; i < (int) myNoLanes; i++) { if (myLaneSpeeds.size() <= (size_t) i || myLaneSpeeds[i] == -1) { myLanesWithMissingSpeeds.push_back(toString(myID) + "_" + toString(i)); avgSpeed += OptionsCont::getOptions().getFloat("vissim.default-speed"); } else { avgSpeed += myLaneSpeeds[i]; } } avgSpeed /= (SUMOReal) myLaneSpeeds.size(); avgSpeed *= OptionsCont::getOptions().getFloat("vissim.speed-norm"); if (fromNode == toNode) { WRITE_WARNING("Could not build edge '" + toString(myID) + "'; would connect same node."); return; } NBEdge* buildEdge = new NBEdge(toString<int>(myID), fromNode, toNode, myType, avgSpeed / (SUMOReal) 3.6, myNoLanes, -1, NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET, myGeom, myName, LANESPREAD_CENTER, true); for (i = 0; i < (int) myNoLanes; i++) { if ((int) myLaneSpeeds.size() <= i || myLaneSpeeds[i] == -1) { buildEdge->setSpeed(i, OptionsCont::getOptions().getFloat("vissim.default-speed") / (SUMOReal) 3.6); } else { buildEdge->setSpeed(i, myLaneSpeeds[i] / (SUMOReal) 3.6); } } ec.insert(buildEdge); // check whether the edge contains any other clusters if (tmpClusters.size() > 0) { bool cont = true; for (ConnectionClusters::iterator j = tmpClusters.begin(); cont && j != tmpClusters.end(); ++j) { // split the edge at the previously build node std::string nextID = buildEdge->getID() + "[1]"; cont = ec.splitAt(dc, buildEdge, (*j)->getNBNode()); // !!! what to do if the edge could not be split? buildEdge = ec.retrieve(nextID); } } }
bool NIVissimDisturbance::addToNode(NBNode* node, NBDistrictCont& dc, NBNodeCont& nc, NBEdgeCont& ec) { myNode = 0; NIVissimConnection* pc = NIVissimConnection::dictionary(myEdge.getEdgeID()); NIVissimConnection* bc = NIVissimConnection::dictionary(myDisturbance.getEdgeID()); if (pc == nullptr && bc == nullptr) { // This has not been tested completely, yet // Both competing abstract edges are normal edges // We have to find a crossing point, build a node here, // split both edges and add the connections NIVissimEdge* e1 = NIVissimEdge::dictionary(myEdge.getEdgeID()); NIVissimEdge* e2 = NIVissimEdge::dictionary(myDisturbance.getEdgeID()); WRITE_WARNING("Ugly split to prohibit '" + toString<int>(e1->getID()) + "' by '" + toString<int>(e2->getID()) + "'."); Position pos = e1->crossesEdgeAtPoint(e2); std::string id1 = toString<int>(e1->getID()) + "x" + toString<int>(e2->getID()); std::string id2 = toString<int>(e2->getID()) + "x" + toString<int>(e1->getID()); NBNode* node1 = nc.retrieve(id1); NBNode* node2 = nc.retrieve(id2); NBNode* node = nullptr; assert(node1 == 0 || node2 == 0); if (node1 == nullptr && node2 == nullptr) { refusedProhibits++; return false; /* node = new NBNode(id1, pos.x(), pos.y(), "priority"); if(!myNodeCont.insert(node)) { "nope, NIVissimDisturbance" << endl; throw 1; }*/ } else { node = node1 == nullptr ? node2 : node1; } ec.splitAt(dc, ec.retrievePossiblySplit(toString<int>(e1->getID()), myEdge.getPosition()), node); ec.splitAt(dc, ec.retrievePossiblySplit(toString<int>(e2->getID()), myDisturbance.getPosition()), node); // !!! in some cases, one of the edges is not being build because it's too short // !!! what to do in these cases? NBEdge* mayDriveFrom = ec.retrieve(toString<int>(e1->getID()) + "[0]"); NBEdge* mayDriveTo = ec.retrieve(toString<int>(e1->getID()) + "[1]"); NBEdge* mustStopFrom = ec.retrieve(toString<int>(e2->getID()) + "[0]"); NBEdge* mustStopTo = ec.retrieve(toString<int>(e2->getID()) + "[1]"); if (mayDriveFrom != nullptr && mayDriveTo != nullptr && mustStopFrom != nullptr && mustStopTo != nullptr) { node->addSortedLinkFoes( NBConnection(mayDriveFrom, mayDriveTo), NBConnection(mayDriveFrom, mayDriveTo)); } else { refusedProhibits++; return false; // !!! warning } // } } else if (pc != nullptr && bc == nullptr) { // The prohibited abstract edge is a connection, the other // is not; // The connection will be prohibitesd by all connections // outgoing from the "real" edge NBEdge* e = ec.retrievePossiblySplit(toString<int>(myDisturbance.getEdgeID()), myDisturbance.getPosition()); if (e == nullptr) { WRITE_WARNING("Could not prohibit '" + toString<int>(myEdge.getEdgeID()) + "' by '" + toString<int>(myDisturbance.getEdgeID()) + "'. Have not found disturbance."); refusedProhibits++; return false; } if (e->getFromNode() == e->getToNode()) { WRITE_WARNING("Could not prohibit '" + toString<int>(myEdge.getEdgeID()) + "' by '" + toString<int>(myDisturbance.getEdgeID()) + "'. Disturbance connects same node."); refusedProhibits++; // What to do with self-looping edges? return false; } // get the begin of the prohibited connection std::string id_pcoe = toString<int>(pc->getFromEdgeID()); std::string id_pcie = toString<int>(pc->getToEdgeID()); NBEdge* pcoe = ec.retrievePossiblySplit(id_pcoe, id_pcie, true); NBEdge* pcie = ec.retrievePossiblySplit(id_pcie, id_pcoe, false); // check whether it's ending node is the node the prohibited // edge end at if (pcoe != nullptr && pcie != nullptr && pcoe->getToNode() == e->getToNode()) { // if so, simply prohibit the connections NBNode* node = e->getToNode(); const EdgeVector& connected = e->getConnectedEdges(); for (EdgeVector::const_iterator i = connected.begin(); i != connected.end(); i++) { node->addSortedLinkFoes( NBConnection(e, *i), NBConnection(pcoe, pcie)); } } else { WRITE_WARNING("Would have to split edge '" + e->getID() + "' to build a prohibition"); refusedProhibits++; // quite ugly - why was it not build? return false; /* std::string nid1 = e->getID() + "[0]"; std::string nid2 = e->getID() + "[1]"; if(ec.splitAt(e, node)) { node->addSortedLinkFoes( NBConnection( ec.retrieve(nid1), ec.retrieve(nid2) ), getConnection(node, myEdge.getEdgeID()) ); } */ } } else if (bc != nullptr && pc == nullptr) { // The prohibiting abstract edge is a connection, the other // is not; // We have to split the other one and add the prohibition // description NBEdge* e = ec.retrievePossiblySplit(toString<int>(myEdge.getEdgeID()), myEdge.getPosition()); if (e == nullptr) { WRITE_WARNING("Could not prohibit '" + toString<int>(myEdge.getEdgeID()) + "' - it was not built."); return false; } std::string nid1 = e->getID() + "[0]"; std::string nid2 = e->getID() + "[1]"; if (e->getFromNode() == e->getToNode()) { WRITE_WARNING("Could not prohibit '" + toString<int>(myEdge.getEdgeID()) + "' by '" + toString<int>(myDisturbance.getEdgeID()) + "'."); refusedProhibits++; // What to do with self-looping edges? return false; } // get the begin of the prohibiting connection std::string id_bcoe = toString<int>(bc->getFromEdgeID()); std::string id_bcie = toString<int>(bc->getToEdgeID()); NBEdge* bcoe = ec.retrievePossiblySplit(id_bcoe, id_bcie, true); NBEdge* bcie = ec.retrievePossiblySplit(id_bcie, id_bcoe, false); // check whether it's ending node is the node the prohibited // edge end at if (bcoe != nullptr && bcie != nullptr && bcoe->getToNode() == e->getToNode()) { // if so, simply prohibit the connections NBNode* node = e->getToNode(); const EdgeVector& connected = e->getConnectedEdges(); for (EdgeVector::const_iterator i = connected.begin(); i != connected.end(); i++) { node->addSortedLinkFoes( NBConnection(bcoe, bcie), NBConnection(e, *i)); } } else { WRITE_WARNING("Would have to split edge '" + e->getID() + "' to build a prohibition"); refusedProhibits++; return false; /* // quite ugly - why was it not build? if(ec.splitAt(e, node)) { node->addSortedLinkFoes( getConnection(node, myDisturbance.getEdgeID()), NBConnection( ec.retrieve(nid1), ec.retrieve(nid2) ) ); } */ } } else { // both the prohibiting and the prohibited abstract edges // are connections // We can retrieve the conected edges and add the desription NBConnection conn1 = getConnection(node, myDisturbance.getEdgeID()); NBConnection conn2 = getConnection(node, myEdge.getEdgeID()); if (!conn1.check(ec) || !conn2.check(ec)) { refusedProhibits++; return false; } node->addSortedLinkFoes(conn1, conn2); } return true; }
void NIXMLConnectionsHandler::myStartElement(int element, const SUMOSAXAttributes& attrs) { if (element == SUMO_TAG_DELETE) { bool ok = true; std::string from = attrs.get<std::string>(SUMO_ATTR_FROM, 0, ok); std::string to = attrs.get<std::string>(SUMO_ATTR_TO, 0, ok); if (!ok) { return; } // these connections were removed when the edge was deleted if (myEdgeCont.wasRemoved(from) || myEdgeCont.wasRemoved(to)) { return; } NBEdge* fromEdge = myEdgeCont.retrieve(from); NBEdge* toEdge = myEdgeCont.retrieve(to); if (fromEdge == 0) { myErrorMsgHandler->inform("The connection-source edge '" + from + "' to reset is not known."); return; } if (toEdge == 0) { myErrorMsgHandler->inform("The connection-destination edge '" + to + "' to reset is not known."); return; } if (!fromEdge->isConnectedTo(toEdge) && fromEdge->getStep() >= NBEdge::EDGE2EDGES) { WRITE_WARNING("Target edge '" + toEdge->getID() + "' is not connected with '" + fromEdge->getID() + "'; the connection cannot be reset."); return; } int fromLane = -1; // Assume all lanes are to be reset. int toLane = -1; if (attrs.hasAttribute(SUMO_ATTR_LANE) || attrs.hasAttribute(SUMO_ATTR_FROM_LANE) || attrs.hasAttribute(SUMO_ATTR_TO_LANE)) { if (!parseLaneInfo(attrs, fromEdge, toEdge, &fromLane, &toLane)) { return; } // we could be trying to reset a connection loaded from a sumo net and which has become obsolete. // In this case it's ok to encounter invalid lance indices if (!fromEdge->hasConnectionTo(toEdge, toLane) && fromEdge->getStep() >= NBEdge::LANES2EDGES) { WRITE_WARNING("Edge '" + fromEdge->getID() + "' has no connection to lane " + toString(toLane) + " of edge '" + toEdge->getID() + "'; the connection cannot be reset."); } } fromEdge->removeFromConnections(toEdge, fromLane, toLane, true); } if (element == SUMO_TAG_CONNECTION) { bool ok = true; std::string from = attrs.get<std::string>(SUMO_ATTR_FROM, "connection", ok); std::string to = attrs.getOpt<std::string>(SUMO_ATTR_TO, "connection", ok, ""); if (!ok || myEdgeCont.wasIgnored(from) || myEdgeCont.wasIgnored(to)) { return; } // extract edges NBEdge* fromEdge = myEdgeCont.retrieve(from); NBEdge* toEdge = to.length() != 0 ? myEdgeCont.retrieve(to) : 0; // check whether they are valid if (fromEdge == 0) { myErrorMsgHandler->inform("The connection-source edge '" + from + "' is not known."); return; } if (toEdge == 0 && to.length() != 0) { myErrorMsgHandler->inform("The connection-destination edge '" + to + "' is not known."); return; } fromEdge->getToNode()->invalidateTLS(myTLLogicCont, true, false); // parse optional lane information if (attrs.hasAttribute(SUMO_ATTR_LANE) || attrs.hasAttribute(SUMO_ATTR_FROM_LANE) || attrs.hasAttribute(SUMO_ATTR_TO_LANE)) { parseLaneBound(attrs, fromEdge, toEdge); } else { fromEdge->addEdge2EdgeConnection(toEdge); } } if (element == SUMO_TAG_PROHIBITION) { bool ok = true; std::string prohibitor = attrs.getOpt<std::string>(SUMO_ATTR_PROHIBITOR, 0, ok, ""); std::string prohibited = attrs.getOpt<std::string>(SUMO_ATTR_PROHIBITED, 0, ok, ""); if (!ok) { return; } NBConnection prohibitorC = parseConnection("prohibitor", prohibitor); NBConnection prohibitedC = parseConnection("prohibited", prohibited); if (prohibitorC == NBConnection::InvalidConnection || prohibitedC == NBConnection::InvalidConnection) { // something failed return; } NBNode* n = prohibitorC.getFrom()->getToNode(); n->addSortedLinkFoes(prohibitorC, prohibitedC); } if (element == SUMO_TAG_CROSSING) { addCrossing(attrs); } if (element == SUMO_TAG_WALKINGAREA) { addWalkingArea(attrs); } }
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 NBRampsComputer::buildOffRamp(NBNode* cur, NBNodeCont& nc, NBEdgeCont& ec, NBDistrictCont& dc, SUMOReal rampLength, bool dontSplit, std::set<NBEdge*>& incremented) { NBEdge* potHighway, *potRamp, *prev; getOffRampEdges(cur, &potHighway, &potRamp, &prev); // compute the number of lanes to append const unsigned int firstLaneNumber = prev->getNumLanes(); int toAdd = (potRamp->getNumLanes() + potHighway->getNumLanes()) - firstLaneNumber; NBEdge* first = prev; NBEdge* last = prev; NBEdge* curr = prev; if (toAdd > 0 && find(incremented.begin(), incremented.end(), prev) == incremented.end()) { SUMOReal currLength = 0; while (curr != 0 && currLength + curr->getGeometry().length() - POSITION_EPS < rampLength) { if (find(incremented.begin(), incremented.end(), curr) == incremented.end()) { curr->incLaneNo(toAdd); curr->invalidateConnections(true); incremented.insert(curr); moveRampRight(curr, toAdd); currLength += curr->getLength(); // !!! loaded length? last = curr; } NBNode* prevN = curr->getFromNode(); if (prevN->getIncomingEdges().size() == 1) { curr = prevN->getIncomingEdges()[0]; if (curr->getNumLanes() != firstLaneNumber) { // the number of lanes changes along the computation; we'll stop... curr = 0; } else if (last->isTurningDirectionAt(curr)) { // turnarounds certainly should not be included in a ramp curr = 0; } else if (curr == potHighway || curr == potRamp) { // circular connectivity. do not split! curr = 0; } } else { // ambigous; and, in fact, what should it be? ...stop curr = 0; } } // check whether a further split is necessary if (curr != 0 && !dontSplit && currLength - POSITION_EPS < rampLength && curr->getNumLanes() == firstLaneNumber && find(incremented.begin(), incremented.end(), curr) == incremented.end()) { // there is enough place to build a ramp; do it bool wasFirst = first == curr; Position pos = curr->getGeometry().positionAtOffset(curr->getGeometry().length() - (rampLength - currLength)); NBNode* rn = new NBNode(curr->getID() + "-AddedOffRampNode", pos); if (!nc.insert(rn)) { throw ProcessError("Ups - could not build on-ramp for edge '" + curr->getID() + "' (node could not be build)!"); } std::string name = curr->getID(); bool ok = ec.splitAt(dc, curr, rn, curr->getID(), curr->getID() + "-AddedOffRampEdge", curr->getNumLanes(), curr->getNumLanes() + toAdd); if (!ok) { WRITE_ERROR("Ups - could not build on-ramp for edge '" + curr->getID() + "'!"); return; } curr = ec.retrieve(name + "-AddedOffRampEdge"); incremented.insert(curr); last = curr; moveRampRight(curr, toAdd); if (wasFirst) { first = curr; } } if (curr == prev && dontSplit) { WRITE_WARNING("Could not build off-ramp for edge '" + curr->getID() + "' due to option '--ramps.no-split'"); return; } } // set connections from added ramp to ramp/highway if (!first->addLane2LaneConnections(potRamp->getNumLanes(), potHighway, 0, MIN2(first->getNumLanes() - 1, potHighway->getNumLanes()), NBEdge::L2L_VALIDATED, true)) { throw ProcessError("Could not set connection!"); } if (!first->addLane2LaneConnections(0, potRamp, 0, potRamp->getNumLanes(), NBEdge::L2L_VALIDATED, false)) { throw ProcessError("Could not set connection!"); } // patch ramp geometry PositionVector p = potRamp->getGeometry(); p.pop_front(); p.push_front(first->getLaneShape(0)[-1]); potRamp->setGeometry(p); }
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 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]; } } } } }