void NIImporter_OpenDrive::addViaConnectionSecure(const NBEdgeCont &ec, const NBNode * const node, const OpenDriveEdge &e, LinkType lt, const std::string &via, std::vector<NIImporter_OpenDrive::Connection> &connections) { NBEdge *from = 0; NBEdge *to = 0; if (node==e.to) { // the connection is at the end of the "positive" direction if (lt==OPENDRIVE_LT_PREDECESSOR) { // via -> edge to = ec.retrieve(e.id); } else { // -edge -> via // "ambigous?" from = ec.retrieve("-" + e.id); } } else { // the connection is at the begin of the "positive" direction if (lt==OPENDRIVE_LT_PREDECESSOR) { // via -> -edge to = ec.retrieve("-" + e.id); } else { // edge -> via // "ambigous?" from = ec.retrieve(e.id); } } if (from==0&&to==0) { throw ProcessError("Missing edge"); } Connection c(from, via, to); connections.push_back(c); }
bool NIVissimTL::NIVissimTLSignal::addTo(NBEdgeCont& ec, NBLoadedTLDef* tl) const { NIVissimConnection* c = NIVissimConnection::dictionary(myEdgeID); NBConnectionVector assignedConnections; if (c == 0) { // What to do if on an edge? -> close all outgoing connections NBEdge* edge = ec.retrievePossiblySplit(toString<int>(myEdgeID), myPosition); if (edge == 0) { WRITE_WARNING("Could not set tls signal at edge '" + toString(myEdgeID) + "' - the edge was not built."); return false; } // Check whether it is already known, which edges are approached // by which lanes // check whether to use the original lanes only if (edge->lanesWereAssigned()) { std::vector<NBEdge::Connection> connections = edge->getConnectionsFromLane(myLane - 1); for (std::vector<NBEdge::Connection>::iterator i = connections.begin(); i != connections.end(); i++) { const NBEdge::Connection& conn = *i; assert(myLane - 1 < (int)edge->getNumLanes()); assignedConnections.push_back(NBConnection(edge, myLane - 1, conn.toEdge, conn.toLane)); } } else { WRITE_WARNING("Edge : Lanes were not assigned(!)"); for (unsigned int j = 0; j < edge->getNumLanes(); j++) { std::vector<NBEdge::Connection> connections = edge->getConnectionsFromLane(j); for (std::vector<NBEdge::Connection>::iterator i = connections.begin(); i != connections.end(); i++) { const NBEdge::Connection& conn = *i; assignedConnections.push_back(NBConnection(edge, j, conn.toEdge, conn.toLane)); } } } } else { // get the edges NBEdge* tmpFrom = ec.retrievePossiblySplit(toString<int>(c->getFromEdgeID()), toString<int>(c->getToEdgeID()), true); NBEdge* tmpTo = ec.retrievePossiblySplit(toString<int>(c->getToEdgeID()), toString<int>(c->getFromEdgeID()), false); // check whether the edges are known if (tmpFrom != 0 && tmpTo != 0) { // add connections this signal is responsible for assignedConnections.push_back(NBConnection(tmpFrom, -1, tmpTo, -1)); } else { return false; // !!! one of the edges could not be build } } // add to the group assert(myGroupIDs.size() != 0); // @todo just another hack?! /* if (myGroupIDs.size() == 1) { return tl->addToSignalGroup(toString<int>(*(myGroupIDs.begin())), assignedConnections); } else { // !!! return tl->addToSignalGroup(toString<int>(*(myGroupIDs.begin())), assignedConnections); } */ return tl->addToSignalGroup(toString<int>(myGroupIDs.front()), assignedConnections); }
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"; } } }
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 NBJoinedEdgesMap::init(NBEdgeCont& ec) { const std::vector<std::string> edgeNames = ec.getAllNames(); myMap.clear(); for (std::vector<std::string>::const_iterator i = edgeNames.begin(); i != edgeNames.end(); i++) { MappedEdgesVector e; e.push_back(*i); myMap[*i] = e; myLengths[*i] = ec.retrieve(*i)->getLength(); } }
void NWWriter_XML::writeStreetSigns(const OptionsCont& oc, NBEdgeCont& ec) { OutputDevice& device = OutputDevice::getDevice(oc.getString("street-sign-output")); device.writeXMLHeader("pois", NWFrame::MAJOR_VERSION + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo-sim.org/xsd/poi_file.xsd\""); for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) { NBEdge* e = (*i).second; const std::vector<NBSign>& signs = e->getSigns(); for (std::vector<NBSign>::const_iterator it = signs.begin(); it != signs.end(); ++it) { it->writeAsPOI(device, e); } } device.close(); }
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) { std::string internalNodeID = e->getID(); if (internalNodeID == UNDEFINED || (nc.retrieve(internalNodeID) != 0)) { // need to invent a new name to avoid clashing with the id of a 'real' node or a reserved name internalNodeID += "_geometry"; } device << internalNodeID << "\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 NWWriter_SUMO::writeRoundabout(OutputDevice& into, const std::vector<std::string>& edgeIDs, const NBEdgeCont& ec) { std::vector<std::string> validEdgeIDs; std::vector<std::string> invalidEdgeIDs; std::vector<std::string> nodeIDs; for (std::vector<std::string>::const_iterator i = edgeIDs.begin(); i != edgeIDs.end(); ++i) { const NBEdge* edge = ec.retrieve(*i); if (edge != 0) { nodeIDs.push_back(edge->getToNode()->getID()); validEdgeIDs.push_back(edge->getID()); } else { invalidEdgeIDs.push_back(*i); } } std::sort(nodeIDs.begin(), nodeIDs.end()); if (validEdgeIDs.size() > 0) { into.openTag(SUMO_TAG_ROUNDABOUT); into.writeAttr(SUMO_ATTR_NODES, joinToString(nodeIDs, " ")); into.writeAttr(SUMO_ATTR_EDGES, joinToString(validEdgeIDs, " ")); into.closeTag(); if (invalidEdgeIDs.size() > 0) { WRITE_WARNING("Writing incomplete roundabout. Edges: '" + joinToString(invalidEdgeIDs, " ") + "' no longer exist'"); } } }
void NWWriter_XML::writeTrafficLights(const OptionsCont& oc, NBTrafficLightLogicCont& tc, NBEdgeCont& ec) { OutputDevice& device = OutputDevice::getDevice(oc.getString("plain-output-prefix") + ".tll.xml"); device.writeXMLHeader("tlLogics", NWFrame::MAJOR_VERSION + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo-sim.org/xsd/tllogic_file.xsd\""); NWWriter_SUMO::writeTrafficLights(device, tc); // we also need to remember the associations between tlLogics and connections // since the information in con.xml is insufficient for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) { NBEdge* e = (*i).second; // write this edge's tl-controlled connections const std::vector<NBEdge::Connection> connections = e->getConnections(); for (std::vector<NBEdge::Connection>::const_iterator c = connections.begin(); c != connections.end(); ++c) { if (c->tlID != "") { NWWriter_SUMO::writeConnection(device, *e, *c, false, NWWriter_SUMO::TLL); } } } device.close(); }
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 NBNodeCont::joinSimilarEdges(NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tlc) { // magic values SUMOReal distanceThreshold = 7; // don't merge edges further apart SUMOReal lengthThreshold = 0.05; // don't merge edges with higher relative length-difference for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) { // count the edges to other nodes outgoing from the current node std::map<NBNode*, EdgeVector> connectionCount; const EdgeVector& outgoing = (*i).second->getOutgoingEdges(); for (EdgeVector::const_iterator j = outgoing.begin(); j != outgoing.end(); j++) { NBEdge* e = (*j); NBNode* connected = e->getToNode(); if (connectionCount.find(connected) == connectionCount.end()) { connectionCount[connected] = EdgeVector(); } connectionCount[connected].push_back(e); } // check whether more than a single edge connect another node and join them std::map<NBNode*, EdgeVector>::iterator k; for (k = connectionCount.begin(); k != connectionCount.end(); k++) { // possibly we do not have anything to join... if ((*k).second.size() < 2) { continue; } // for the edges that seem to be a single street, // check whether the geometry is similar const EdgeVector& ev = (*k).second; const NBEdge* const first = ev.front(); EdgeVector::const_iterator jci; // join candidate iterator for (jci = ev.begin() + 1; jci != ev.end(); ++jci) { const SUMOReal relativeLengthDifference = fabs(first->getLoadedLength() - (*jci)->getLoadedLength()) / first->getLoadedLength(); if ((!first->isNearEnough2BeJoined2(*jci, distanceThreshold)) || (relativeLengthDifference > lengthThreshold) || (first->getSpeed() != (*jci)->getSpeed()) // @todo check vclass ) { break; } } // @bug If there are 3 edges of which 2 can be joined, no joining will // take place with the current implementation if (jci == ev.end()) { ec.joinSameNodeConnectingEdges(dc, tlc, ev); } } } }
void NBPTLine::write(OutputDevice& device, NBEdgeCont& ec) { device.openTag(SUMO_TAG_PT_LINE); device.writeAttr(SUMO_ATTR_ID, myPTLineId); if (!myName.empty()) { device.writeAttr(SUMO_ATTR_NAME, StringUtils::escapeXML(myName)); } device.writeAttr(SUMO_ATTR_LINE, StringUtils::escapeXML(myRef)); device.writeAttr(SUMO_ATTR_TYPE, myType); if (myInterval > 0) { // write seconds device.writeAttr(SUMO_ATTR_PERIOD, 60 * myInterval); } if (myNightService != "") { device.writeAttr("nightService", myNightService); } device.writeAttr("completeness", toString((double)myPTStops.size() / (double)myNumOfStops)); std::vector<std::string> validEdgeIDs; // filter out edges that have been removed due to joining junctions // (therest of the route is valid) for (NBEdge* e : myRoute) { if (ec.retrieve(e->getID())) { validEdgeIDs.push_back(e->getID()); } } if (!myRoute.empty()) { device.openTag(SUMO_TAG_ROUTE); device.writeAttr(SUMO_ATTR_EDGES, validEdgeIDs); device.closeTag(); } for (auto& myPTStop : myPTStops) { device.openTag(SUMO_TAG_BUS_STOP); device.writeAttr(SUMO_ATTR_ID, myPTStop->getID()); device.writeAttr(SUMO_ATTR_NAME, StringUtils::escapeXML(myPTStop->getName())); device.closeTag(); } // device.writeAttr(SUMO_ATTR_LANE, myLaneId); // device.writeAttr(SUMO_ATTR_STARTPOS, myStartPos); // device.writeAttr(SUMO_ATTR_ENDPOS, myEndPos); // device.writeAttr(SUMO_ATTR_FRIENDLY_POS, "true"); device.closeTag(); }
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 NIImporter_OpenDrive::addE2EConnectionsSecure(const NBEdgeCont &ec, const NBNode * const node, const NIImporter_OpenDrive::OpenDriveEdge &from, const NIImporter_OpenDrive::OpenDriveEdge &to, std::vector<NIImporter_OpenDrive::Connection> &connections) { // positive direction (from is incoming, to is outgoing) NBEdge *fromEdge = ec.retrieve("-" + from.id); if (fromEdge==0||!node->hasIncoming(fromEdge)) { fromEdge = ec.retrieve(from.id); } NBEdge *toEdge = ec.retrieve("-" + to.id); if (toEdge==0||!node->hasOutgoing(toEdge)) { toEdge = ec.retrieve(to.id); } if (fromEdge!=0&&toEdge!=0) { Connection c(fromEdge, "", toEdge); setLaneConnections(c, from, c.from->getID()[0]!='-', c.from->getID()[0]=='-' ? SUMO_TAG_OPENDRIVE_RIGHT : SUMO_TAG_OPENDRIVE_LEFT, to, c.to->getID()[0]!='-', c.to->getID()[0]=='-' ? SUMO_TAG_OPENDRIVE_RIGHT : SUMO_TAG_OPENDRIVE_LEFT); connections.push_back(c); } // negative direction (to is incoming, from is outgoing) fromEdge = ec.retrieve("-" + from.id); if (fromEdge==0||!node->hasOutgoing(fromEdge)) { fromEdge = ec.retrieve(from.id); } toEdge = ec.retrieve("-" + to.id); if (toEdge==0||!node->hasIncoming(toEdge)) { toEdge = ec.retrieve(to.id); } if (fromEdge!=0&&toEdge!=0) { Connection c(toEdge, "", fromEdge); setLaneConnections(c, to, c.to->getID()[0]!='-', c.to->getID()[0]=='-' ? SUMO_TAG_OPENDRIVE_RIGHT : SUMO_TAG_OPENDRIVE_LEFT, from, c.from->getID()[0]!='-', c.from->getID()[0]=='-' ? SUMO_TAG_OPENDRIVE_RIGHT : SUMO_TAG_OPENDRIVE_LEFT); connections.push_back(c); } }
void NBTrafficLightLogicCont::setTLControllingInformation(const NBEdgeCont& ec, const NBNodeCont& nc) { Definitions definitions = getDefinitions(); // set the information about all participants, first for (Definitions::iterator it = definitions.begin(); it != definitions.end(); it++) { (*it)->setParticipantsInformation(); } // clear previous information because tlDefs may have been removed in NETEDIT ec.clearControllingTLInformation(); // insert the information about the tl-controlling for (Definitions::iterator it = definitions.begin(); it != definitions.end(); it++) { (*it)->setTLControllingInformation(); } // handle rail signals which are not instantiated as normal definitions for (std::map<std::string, NBNode*>::const_iterator it = nc.begin(); it != nc.end(); it ++) { NBNode* n = it->second; if (n->getType() == NODETYPE_RAIL_SIGNAL || n->getType() == NODETYPE_RAIL_CROSSING) { NBOwnTLDef dummy(n->getID(), n, 0, TLTYPE_STATIC); dummy.setParticipantsInformation(); dummy.setTLControllingInformation(); n->removeTrafficLight(&dummy); } } }
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 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 NIVissimDistrictConnection::dict_BuildDistricts(NBDistrictCont& dc, NBEdgeCont& ec, NBNodeCont& nc/*, NBDistribution &distc*/) { // add the sources and sinks // their normalised probability is computed within NBDistrict // to avoid SUMOReal code writing and more securty within the converter // go through the district table for (std::map<int, std::vector<int> >::iterator k = myDistrictsConnections.begin(); k != myDistrictsConnections.end(); k++) { // get the connections const std::vector<int>& connections = (*k).second; // retrieve the current district NBDistrict* district = dc.retrieve(toString<int>((*k).first)); NBNode* districtNode = nc.retrieve("District" + district->getID()); assert(district != 0 && districtNode != 0); for (std::vector<int>::const_iterator l = connections.begin(); l != connections.end(); l++) { NIVissimDistrictConnection* c = dictionary(*l); // get the edge to connect the parking place to NBEdge* e = ec.retrieve(toString<int>(c->myEdgeID)); if (e == 0) { e = ec.retrievePossiblySplit(toString<int>(c->myEdgeID), c->myPosition); } if (e == 0) { WRITE_WARNING("Could not build district '" + toString<int>((*k).first) + "' - edge '" + toString<int>(c->myEdgeID) + "' is missing."); continue; } std::string id = "ParkingPlace" + toString<int>(*l); NBNode* parkingPlace = nc.retrieve(id); if (parkingPlace == 0) { SUMOReal pos = c->getPosition(); if (pos < e->getLength() - pos) { parkingPlace = e->getFromNode(); parkingPlace->invalidateIncomingConnections(); } else { parkingPlace = e->getToNode(); parkingPlace->invalidateOutgoingConnections(); } } assert( e->getToNode() == parkingPlace || e->getFromNode() == parkingPlace); // build the connection to the source if (e->getFromNode() == parkingPlace) { id = "VissimFromParkingplace" + toString<int>((*k).first) + "-" + toString<int>(c->myID); NBEdge* source = new NBEdge(id, districtNode, parkingPlace, "Connection", c->getMeanSpeed(/*distc*/) / (SUMOReal) 3.6, 3, -1, NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET); if (!ec.insert(source)) { // !!! in den Konstruktor throw 1; // !!! } SUMOReal percNormed = c->myPercentages[(*k).first]; if (!district->addSource(source, percNormed)) { throw 1; } } // build the connection to the destination if (e->getToNode() == parkingPlace) { id = "VissimToParkingplace" + toString<int>((*k).first) + "-" + toString<int>(c->myID); NBEdge* destination = new NBEdge(id, parkingPlace, districtNode, "Connection", (SUMOReal) 100 / (SUMOReal) 3.6, 2, -1, NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET); if (!ec.insert(destination)) { // !!! (in den Konstruktor) throw 1; // !!! } SUMOReal percNormed2 = c->myPercentages[(*k).first]; if (!district->addSink(destination, percNormed2)) { throw 1; // !!! } } /* if(e->getToNode()==districtNode) { SUMOReal percNormed = c->myPercentages[(*k).first]; district->addSink(e, percNormed); } if(e->getFromNode()==districtNode) { SUMOReal percNormed = c->myPercentages[(*k).first]; district->addSource(e, percNormed); } */ } /* // add them as sources and sinks to the current district for(std::vector<int>::const_iterator l=connections.begin(); l!=connections.end(); l++) { // get the current connections NIVissimDistrictConnection *c = dictionary(*l); // get the edge to connect the parking place to NBEdge *e = NBEdgeCont::retrieve(toString<int>(c->myEdgeID)); Position edgepos = c->geomPosition(); NBNode *edgeend = e->tryGetNodeAtPosition(c->myPosition, e->getLength()/4.0); if(edgeend==0) { // Edge splitting omitted on build district connections by now assert(false); } // build the district-node if not yet existing std::string id = "VissimParkingplace" + district->getID(); NBNode *districtNode = nc.retrieve(id); assert(districtNode!=0); if(e->getToNode()==edgeend) { // build the connection to the source id = std::string("VissimFromParkingplace") + toString<int>((*k).first) + "-" + toString<int>(c->myID); NBEdge *source = new NBEdge(id, id, districtNode, edgeend, "Connection", 100/3.6, 2, 100, 0, NBEdge::EDGEFUNCTION_SOURCE); NBEdgeCont::insert(source); // !!! (in den Konstruktor) SUMOReal percNormed = c->myPercentages[(*k).first]; district->addSource(source, percNormed); } else { // build the connection to the destination id = std::string("VissimToParkingplace") + toString<int>((*k).first) + "-" + toString<int>(c->myID); NBEdge *destination = new NBEdge(id, id, edgeend, districtNode, "Connection", 100/3.6, 2, 100, 0, NBEdge::EDGEFUNCTION_SINK); NBEdgeCont::insert(destination); // !!! (in den Konstruktor) // add both the source and the sink to the district SUMOReal percNormed = c->myPercentages[(*k).first]; district->addSink(destination, percNormed); } } */ } }
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_OpenStreetMap::insertEdge(Edge* e, int index, NBNode* from, NBNode* to, const std::vector<int> &passed, NBEdgeCont& ec, NBTypeCont& tc) { // patch the id std::string id = e->id; if (index >= 0) { id = id + "#" + toString(index); } // convert the shape PositionVector shape; for (std::vector<int>::const_iterator i = passed.begin(); i != passed.end(); ++i) { NIOSMNode* n = myOSMNodes.find(*i)->second; Position pos(n->lon, n->lat); if (!NILoader::transformCoordinates(pos, true)) { throw ProcessError("Unable to project coordinates for edge " + id + "."); } shape.push_back_noDoublePos(pos); } std::string type = e->myHighWayType; if (!tc.knows(type)) { if (type.find(compoundTypeSeparator) != std::string::npos) { // this edge has a combination type which does not yet exist in the TypeContainer StringTokenizer tok = StringTokenizer(type, compoundTypeSeparator); std::set<std::string> types; while (tok.hasNext()) { std::string t = tok.next(); if (tc.knows(t)) { types.insert(t); } else { WRITE_WARNING("Discarding edge " + id + " with type \"" + type + "\" (unknown compound \"" + t + "\")."); return; } } if (types.size() == 2 && types.count("railway.tram") == 1) { // compound types concern mostly the special case of tram tracks on a normal road. // in this case we simply discard the tram information since the default for road is to allow all vclasses types.erase("railway.tram"); std::string otherCompound = *(types.begin()); // XXX if otherCompound does not allow all vehicles (e.g. SVC_DELIVERY), tram will still not be allowed type = otherCompound; } else { // other cases not implemented yet WRITE_WARNING("Discarding edge " + id + " with unknown type \"" + type + "\"."); return; } } else { // we do not know the type -> something else, ignore //WRITE_WARNING("Discarding edge " + id + " with unknown type \"" + type + "\"."); return; } } // otherwise it is not an edge and will be ignored int noLanes = tc.getNumLanes(type); SUMOReal speed = tc.getSpeed(type); bool defaultsToOneWay = tc.getIsOneWay(type); SUMOVehicleClasses allowedClasses = tc.getAllowedClasses(type); SUMOVehicleClasses disallowedClasses = tc.getDisallowedClasses(type); // check directions bool addSecond = true; if (e->myIsOneWay == "true" || e->myIsOneWay == "yes" || e->myIsOneWay == "1" || (defaultsToOneWay && e->myIsOneWay != "no" && e->myIsOneWay != "false" && e->myIsOneWay != "0")) { addSecond = false; } // if we had been able to extract the number of lanes, override the highway type default if (e->myNoLanes >= 0) { if (!addSecond) { noLanes = e->myNoLanes; } else { noLanes = e->myNoLanes / 2; } } // if we had been able to extract the maximum speed, override the type's default if (e->myMaxSpeed != MAXSPEED_UNGIVEN) { speed = (SUMOReal)(e->myMaxSpeed / 3.6); } if (noLanes != 0 && speed != 0) { if (e->myIsOneWay != "" && e->myIsOneWay != "false" && e->myIsOneWay != "no" && e->myIsOneWay != "true" && e->myIsOneWay != "yes" && e->myIsOneWay != "-1" && e->myIsOneWay != "1") { WRITE_WARNING("New value for oneway found: " + e->myIsOneWay); } LaneSpreadFunction lsf = addSecond ? LANESPREAD_RIGHT : LANESPREAD_CENTER; if (e->myIsOneWay != "-1") { NBEdge* nbe = new NBEdge(id, from, to, type, speed, noLanes, tc.getPriority(type), tc.getWidth(type), NBEdge::UNSPECIFIED_OFFSET, shape, e->streetName, lsf); nbe->setVehicleClasses(allowedClasses, disallowedClasses); if (!ec.insert(nbe)) { delete nbe; throw ProcessError("Could not add edge '" + id + "'."); } } if (addSecond) { if (e->myIsOneWay != "-1") { id = "-" + id; } NBEdge* nbe = new NBEdge(id, to, from, type, speed, noLanes, tc.getPriority(type), tc.getWidth(type), NBEdge::UNSPECIFIED_OFFSET, shape.reverse(), e->streetName, lsf); nbe->setVehicleClasses(allowedClasses, disallowedClasses); if (!ec.insert(nbe)) { delete nbe; throw ProcessError("Could not add edge '-" + id + "'."); } } } }
void NBNodeCont::removeIsolatedRoads(NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tc) { UNUSED_PARAMETER(tc); // Warn of isolated edges, i.e. a single edge with no connection to another edge int edgeCounter = 0; const std::vector<std::string>& edgeNames = ec.getAllNames(); for (std::vector<std::string>::const_iterator it = edgeNames.begin(); it != edgeNames.end(); ++it) { // Test whether this node starts at a dead end, i.e. it has only one adjacent node // to which an edge exists and from which an edge may come. NBEdge* e = ec.retrieve(*it); if (e == 0) { continue; } NBNode* from = e->getFromNode(); const EdgeVector& outgoingEdges = from->getOutgoingEdges(); if (outgoingEdges.size() != 1) { // At this node, several edges or no edge start; so, this node is no dead end. continue; } const EdgeVector& incomingEdges = from->getIncomingEdges(); if (incomingEdges.size() > 1) { // At this node, several edges end; so, this node is no dead end. continue; } else if (incomingEdges.size() == 1) { NBNode* fromNodeOfIncomingEdge = incomingEdges[0]->getFromNode(); NBNode* toNodeOfOutgoingEdge = outgoingEdges[0]->getToNode(); if (fromNodeOfIncomingEdge != toNodeOfOutgoingEdge) { // At this node, an edge ends which is not the inverse direction of // the starting node. continue; } } // Now we know that the edge e starts a dead end. // Next we test if the dead end is isolated, i.e. does not lead to a junction bool hasJunction = false; EdgeVector road; NBEdge* eOld = 0; NBNode* to; std::set<NBNode*> adjacentNodes; do { road.push_back(e); eOld = e; from = e->getFromNode(); to = e->getToNode(); const EdgeVector& outgoingEdgesOfToNode = to->getOutgoingEdges(); const EdgeVector& incomingEdgesOfToNode = to->getIncomingEdges(); adjacentNodes.clear(); for (EdgeVector::const_iterator itOfOutgoings = outgoingEdgesOfToNode.begin(); itOfOutgoings != outgoingEdgesOfToNode.end(); ++itOfOutgoings) { if ((*itOfOutgoings)->getToNode() != from // The back path && (*itOfOutgoings)->getToNode() != to // A loop / dummy edge ) { e = *itOfOutgoings; // Probably the next edge } adjacentNodes.insert((*itOfOutgoings)->getToNode()); } for (EdgeVector::const_iterator itOfIncomings = incomingEdgesOfToNode.begin(); itOfIncomings != incomingEdgesOfToNode.end(); ++itOfIncomings) { adjacentNodes.insert((*itOfIncomings)->getFromNode()); } adjacentNodes.erase(to); // Omit loops if (adjacentNodes.size() > 2) { hasJunction = true; } } while (!hasJunction && eOld != e); if (!hasJunction) { edgeCounter += int(road.size()); std::string warningString = "Removed a road without junctions: "; for (EdgeVector::iterator roadIt = road.begin(); roadIt != road.end(); ++roadIt) { if (roadIt == road.begin()) { warningString += (*roadIt)->getID(); } else { warningString += ", " + (*roadIt)->getID(); } NBNode* fromNode = (*roadIt)->getFromNode(); NBNode* toNode = (*roadIt)->getToNode(); ec.erase(dc, *roadIt); if (fromNode->getIncomingEdges().size() == 0 && fromNode->getOutgoingEdges().size() == 0) { // Node is empty; can be removed erase(fromNode); } if (toNode->getIncomingEdges().size() == 0 && toNode->getOutgoingEdges().size() == 0) { // Node is empty; can be removed erase(toNode); } } WRITE_WARNING(warningString); } } if (edgeCounter > 0 && !OptionsCont::getOptions().getBool("remove-edges.isolated")) { WRITE_WARNING("Detected isolated roads. Use the option --remove-edges.isolated to get a list of all affected edges."); } }
void NBRampsComputer::buildOnRamp(NBNode* cur, NBNodeCont& nc, NBEdgeCont& ec, NBDistrictCont& dc, SUMOReal rampLength, bool dontSplit, std::set<NBEdge*>& incremented) { NBEdge* potHighway, *potRamp, *cont; getOnRampEdges(cur, &potHighway, &potRamp, &cont); // compute the number of lanes to append const unsigned int firstLaneNumber = potHighway->getNumLanes(); int toAdd = (potRamp->getNumLanes() + firstLaneNumber) - cont->getNumLanes(); NBEdge* first = cont; NBEdge* last = cont; NBEdge* curr = cont; if (toAdd > 0 && find(incremented.begin(), incremented.end(), cont) == 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* nextN = curr->getToNode(); if (nextN->getOutgoingEdges().size() == 1) { curr = nextN->getOutgoingEdges()[0]; if (curr->getNumLanes() != firstLaneNumber) { // the number of lanes changes along the computation; we'll stop... 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; NBNode* rn = new NBNode(curr->getID() + "-AddedOnRampNode", curr->getGeometry().positionAtLengthPosition(rampLength - currLength)); 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() + ADDED_ON_RAMP_EDGE, curr->getID(), curr->getNumLanes() + toAdd, curr->getNumLanes()); if (!ok) { WRITE_ERROR("Ups - could not build on-ramp for edge '" + curr->getID() + "'!"); return; } //ec.retrieve(name)->invalidateConnections(); curr = ec.retrieve(name + ADDED_ON_RAMP_EDGE); curr->invalidateConnections(true); incremented.insert(curr); last = curr; moveRampRight(curr, toAdd); if (wasFirst) { first = curr; } } } // set connections from ramp/highway to added ramp if (!potHighway->addLane2LaneConnections(0, first, potRamp->getNumLanes(), MIN2(first->getNumLanes() - potRamp->getNumLanes(), potHighway->getNumLanes()), NBEdge::L2L_VALIDATED, true, true)) { throw ProcessError("Could not set connection!"); } if (!potRamp->addLane2LaneConnections(0, first, 0, potRamp->getNumLanes(), NBEdge::L2L_VALIDATED, true, true)) { throw ProcessError("Could not set connection!"); } // patch ramp geometry PositionVector p = potRamp->getGeometry(); p.pop_back(); p.push_back(first->getLaneShape(0)[0]); potRamp->setGeometry(p); // set connections from added ramp to following highway NBNode* nextN = last->getToNode(); if (nextN->getOutgoingEdges().size() == 1) { NBEdge* next = nextN->getOutgoingEdges()[0];//const EdgeVector& o1 = cont->getToNode()->getOutgoingEdges(); if (next->getNumLanes() < last->getNumLanes()) { last->addLane2LaneConnections(last->getNumLanes() - next->getNumLanes(), next, 0, next->getNumLanes(), NBEdge::L2L_VALIDATED); } } }
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); } } }
void NWWriter_XML::writeEdgesAndConnections(const OptionsCont& oc, NBNodeCont& nc, NBEdgeCont& ec) { const GeoConvHelper& gch = GeoConvHelper::getFinal(); bool useGeo = oc.exists("proj.plain-geo") && oc.getBool("proj.plain-geo"); const bool geoAccuracy = useGeo || gch.usingInverseGeoProjection(); OutputDevice& edevice = OutputDevice::getDevice(oc.getString("plain-output-prefix") + ".edg.xml"); edevice.writeXMLHeader("edges", NWFrame::MAJOR_VERSION + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo-sim.org/xsd/edges_file.xsd\""); OutputDevice& cdevice = OutputDevice::getDevice(oc.getString("plain-output-prefix") + ".con.xml"); cdevice.writeXMLHeader("connections", NWFrame::MAJOR_VERSION + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo-sim.org/xsd/connections_file.xsd\""); bool noNames = !oc.getBool("output.street-names"); for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) { // write the edge itself to the edges-files NBEdge* e = (*i).second; edevice.openTag(SUMO_TAG_EDGE); edevice.writeAttr(SUMO_ATTR_ID, e->getID()); edevice.writeAttr(SUMO_ATTR_FROM, e->getFromNode()->getID()); edevice.writeAttr(SUMO_ATTR_TO, e->getToNode()->getID()); if (!noNames && e->getStreetName() != "") { edevice.writeAttr(SUMO_ATTR_NAME, StringUtils::escapeXML(e->getStreetName())); } edevice.writeAttr(SUMO_ATTR_PRIORITY, e->getPriority()); // write the type if given if (e->getTypeID() != "") { edevice.writeAttr(SUMO_ATTR_TYPE, e->getTypeID()); } edevice.writeAttr(SUMO_ATTR_NUMLANES, e->getNumLanes()); if (!e->hasLaneSpecificSpeed()) { edevice.writeAttr(SUMO_ATTR_SPEED, e->getSpeed()); } // write non-default geometry if (!e->hasDefaultGeometry()) { PositionVector geom = e->getGeometry(); if (useGeo) { for (int i = 0; i < (int) geom.size(); i++) { gch.cartesian2geo(geom[i]); } } if (geoAccuracy) { edevice.setPrecision(GEO_OUTPUT_ACCURACY); } edevice.writeAttr(SUMO_ATTR_SHAPE, geom); if (geoAccuracy) { edevice.setPrecision(); } } // write the spread type if not default ("right") if (e->getLaneSpreadFunction() != LANESPREAD_RIGHT) { edevice.writeAttr(SUMO_ATTR_SPREADTYPE, toString(e->getLaneSpreadFunction())); } // write the length if it was specified if (e->hasLoadedLength()) { edevice.writeAttr(SUMO_ATTR_LENGTH, e->getLoadedLength()); } // some attributes can be set by edge default or per lane. Write as default if possible (efficiency) if (e->getLaneWidth() != NBEdge::UNSPECIFIED_WIDTH && !e->hasLaneSpecificWidth()) { edevice.writeAttr(SUMO_ATTR_WIDTH, e->getLaneWidth()); } if (e->getOffset() != NBEdge::UNSPECIFIED_OFFSET && !e->hasLaneSpecificOffset()) { edevice.writeAttr(SUMO_ATTR_OFFSET, e->getOffset()); } if (!e->needsLaneSpecificOutput()) { edevice.closeTag(); } else { for (unsigned int i = 0; i < e->getLanes().size(); ++i) { const NBEdge::Lane& lane = e->getLanes()[i]; edevice.openTag(SUMO_TAG_LANE); edevice.writeAttr(SUMO_ATTR_INDEX, i); // write allowed lanes NWWriter_SUMO::writePermissions(edevice, lane.permissions); NWWriter_SUMO::writePreferences(edevice, lane.preferred); // write other attributes if (lane.width != NBEdge::UNSPECIFIED_WIDTH && e->hasLaneSpecificWidth()) { edevice.writeAttr(SUMO_ATTR_WIDTH, lane.width); } if (lane.offset != NBEdge::UNSPECIFIED_OFFSET && e->hasLaneSpecificOffset()) { edevice.writeAttr(SUMO_ATTR_OFFSET, lane.offset); } if (e->hasLaneSpecificSpeed()) { edevice.writeAttr(SUMO_ATTR_SPEED, lane.speed); } edevice.closeTag(); } edevice.closeTag(); } // write this edge's connections to the connections-files e->sortOutgoingConnectionsByIndex(); const std::vector<NBEdge::Connection> connections = e->getConnections(); for (std::vector<NBEdge::Connection>::const_iterator c = connections.begin(); c != connections.end(); ++c) { NWWriter_SUMO::writeConnection(cdevice, *e, *c, false, NWWriter_SUMO::PLAIN); } if (connections.size() > 0) { cdevice << "\n"; } } // write loaded prohibitions to the connections-file for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NWWriter_SUMO::writeProhibitions(cdevice, i->second->getProhibitions()); } edevice.close(); cdevice.close(); }
void NWWriter_DlrNavteq::writeNodesUnsplitted(const OptionsCont& oc, NBNodeCont& nc, NBEdgeCont& ec, std::map<NBEdge*, std::string>& internalNodes) { // 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). 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 double geoScale = pow(10.0f, haveGeo ? 5 : 2); // see NIImporter_DlrNavteq::GEO_SCALE device.setPrecision(oc.getInt("dlr-navteq.precision")); 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 header Boundary boundary = gch.getConvBoundary(); Position min(boundary.xmin(), boundary.ymin()); Position max(boundary.xmax(), boundary.ymax()); gch.cartesian2geo(min); min.mul(geoScale); gch.cartesian2geo(max); max.mul(geoScale); int multinodes = 0; for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) { if ((*i).second->getGeometry().size() > 2) { multinodes++; } } device << "# [xmin_region] " << min.x() << "\n"; device << "# [xmax_region] " << max.x() << "\n"; device << "# [ymin_region] " << min.y() << "\n"; device << "# [ymax_region] " << max.y() << "\n"; device << "# [elements_multinode] " << multinodes << "\n"; device << "# [elements_normalnode] " << nc.size() << "\n"; device << "# [xmin] " << min.x() << "\n"; device << "# [xmax] " << max.x() << "\n"; device << "# [ymin] " << min.y() << "\n"; device << "# [ymax] " << max.y() << "\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 std::vector<std::string> avoid; std::set<std::string> reservedNodeIDs; const bool numericalIDs = oc.getBool("numerical-ids"); if (oc.isSet("reserved-ids")) { NBHelpers::loadPrefixedIDsFomFile(oc.getString("reserved-ids"), "node:", reservedNodeIDs); // backward compatibility NBHelpers::loadPrefixedIDsFomFile(oc.getString("reserved-ids"), "junction:", reservedNodeIDs); // selection format } if (numericalIDs) { avoid = nc.getAllNames(); std::vector<std::string> avoid2 = ec.getAllNames(); avoid.insert(avoid.end(), avoid2.begin(), avoid2.end()); avoid.insert(avoid.end(), reservedNodeIDs.begin(), reservedNodeIDs.end()); } IDSupplier idSupplier("", avoid); for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) { NBEdge* e = (*i).second; PositionVector geom = e->getGeometry(); if (geom.size() > 2) { // the import NIImporter_DlrNavteq checks for the presence of a // negated edge id to determine spread type. We may need to do some // shifting to make this consistent const bool hasOppositeID = ec.getOppositeByID(e->getID()) != nullptr; if (e->getLaneSpreadFunction() == LANESPREAD_RIGHT && !hasOppositeID) { // need to write center-line geometry instead try { geom.move2side(e->getTotalWidth() / 2); } catch (InvalidArgument& exception) { WRITE_WARNING("Could not reconstruct shape for edge:'" + e->getID() + "' (" + exception.what() + ")."); } } else if (e->getLaneSpreadFunction() == LANESPREAD_CENTER && hasOppositeID) { // need to write left-border geometry instead try { geom.move2side(-e->getTotalWidth() / 2); } catch (InvalidArgument& exception) { WRITE_WARNING("Could not reconstruct shape for edge:'" + e->getID() + "' (" + exception.what() + ")."); } } std::string internalNodeID = e->getID(); if (internalNodeID == UNDEFINED || (nc.retrieve(internalNodeID) != nullptr) || reservedNodeIDs.count(internalNodeID) > 0 ) { // need to invent a new name to avoid clashing with the id of a 'real' node or a reserved name if (numericalIDs) { internalNodeID = idSupplier.getNext(); } else { internalNodeID += "_geometry"; } } internalNodes[e] = internalNodeID; device << internalNodeID << "\t1\t" << geom.size() - 2; for (int ii = 1; ii < (int)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(); }