bool NWWriter_SUMO::writeInternalNodes(OutputDevice& into, const NBNode& n) { bool ret = false; const std::vector<NBEdge*>& incoming = n.getIncomingEdges(); // build the list of internal lane ids std::vector<std::string> internalLaneIDs; for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) { const std::vector<NBEdge::Connection>& elv = (*i)->getConnections(); for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) { if ((*k).toEdge != 0) { internalLaneIDs.push_back((*k).getInternalLaneID()); } } } const std::vector<NBNode::Crossing>& crossings = n.getCrossings(); for (std::vector<NBNode::Crossing>::const_iterator it_c = crossings.begin(); it_c != crossings.end(); ++it_c) { internalLaneIDs.push_back((*it_c).id + "_0"); } // write the internal nodes for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); i++) { const std::vector<NBEdge::Connection>& elv = (*i)->getConnections(); for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) { if ((*k).toEdge == 0 || !(*k).haveVia) { continue; } Position pos = (*k).shape[-1]; into.openTag(SUMO_TAG_JUNCTION).writeAttr(SUMO_ATTR_ID, (*k).viaID + "_0"); into.writeAttr(SUMO_ATTR_TYPE, NODETYPE_INTERNAL); NWFrame::writePositionLong(pos, into); std::string incLanes = (*k).getInternalLaneID(); if ((*k).foeIncomingLanes.length() != 0) { incLanes += " " + (*k).foeIncomingLanes; } into.writeAttr(SUMO_ATTR_INCLANES, incLanes); const std::vector<unsigned int>& foes = (*k).foeInternalLinks; std::vector<std::string> foeIDs; for (std::vector<unsigned int>::const_iterator it = foes.begin(); it != foes.end(); ++it) { foeIDs.push_back(internalLaneIDs[*it]); } into.writeAttr(SUMO_ATTR_INTLANES, joinToString(foeIDs, " ")); into.closeTag(); ret = true; } } return ret; }
void GNETLSEditorFrame::buildIinternalLanes(NBTrafficLightDefinition* tlDef) { // clean up previous objects SUMORTree& rtree = myViewNet->getNet()->getVisualisationSpeedUp(); for (TLIndexMap::iterator it = myInternalLanes.begin(); it != myInternalLanes.end(); it++) { std::vector<GNEInternalLane*> lanes = it->second; for (std::vector<GNEInternalLane*>::iterator it_lane = lanes.begin(); it_lane != lanes.end(); it_lane++) { rtree.removeAdditionalGLObject(*it_lane); delete *it_lane; } } myInternalLanes.clear(); if (tlDef != 0) { const int NUM_POINTS = 10; assert(myCurrentJunction); SUMORTree& rtree = myViewNet->getNet()->getVisualisationSpeedUp(); NBNode* nbn = myCurrentJunction->getNBNode(); std::string innerID = ":" + nbn->getID(); // see NWWriter_SUMO::writeInternalEdges const NBConnectionVector& links = tlDef->getControlledLinks(); for (NBConnectionVector::const_iterator it = links.begin(); it != links.end(); it++) { int tlIndex = it->getTLIndex(); PositionVector shape = nbn->computeInternalLaneShape(it->getFrom(), NBEdge::Connection(it->getFromLane(), it->getTo(), it->getToLane()), NUM_POINTS); GNEInternalLane* ilane = new GNEInternalLane(this, innerID + '_' + toString(tlIndex), shape, tlIndex); rtree.addAdditionalGLObject(ilane); myInternalLanes[tlIndex].push_back(ilane); } const std::vector<NBNode::Crossing>& crossings = nbn->getCrossings(); for (std::vector<NBNode::Crossing>::const_iterator it = crossings.begin(); it != crossings.end(); it++) { const NBNode::Crossing& c = *it; GNEInternalLane* ilane = new GNEInternalLane(this, c.id, c.shape, c.tlLinkNo); rtree.addAdditionalGLObject(ilane); myInternalLanes[c.tlLinkNo].push_back(ilane); } } }
// =========================================================================== // method definitions // =========================================================================== // --------------------------------------------------------------------------- // static methods // --------------------------------------------------------------------------- void NWWriter_SUMO::writeNetwork(const OptionsCont& oc, NBNetBuilder& nb) { // check whether a sumo net-file shall be generated if (!oc.isSet("output-file")) { return; } OutputDevice& device = OutputDevice::getDevice(oc.getString("output-file")); const std::string lefthand = oc.getBool("lefthand") ? " " + toString(SUMO_ATTR_LEFTHAND) + "=\"true\"" : ""; const int cornerDetail = oc.getInt("junctions.corner-detail"); const int linkDetail = oc.getInt("junctions.internal-link-detail"); const std::string junctionCornerDetail = (cornerDetail > 0 ? " " + toString(SUMO_ATTR_CORNERDETAIL) + "=\"" + toString(cornerDetail) + "\"" : ""); const std::string junctionLinkDetail = (oc.isDefault("junctions.internal-link-detail") ? "" : " " + toString(SUMO_ATTR_LINKDETAIL) + "=\"" + toString(linkDetail) + "\""); device.writeXMLHeader("net", NWFrame::MAJOR_VERSION + lefthand + junctionCornerDetail + junctionLinkDetail + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo.dlr.de/xsd/net_file.xsd\""); // street names may contain non-ascii chars device.lf(); // get involved container const NBNodeCont& nc = nb.getNodeCont(); const NBEdgeCont& ec = nb.getEdgeCont(); const NBDistrictCont& dc = nb.getDistrictCont(); // write network offsets and projection GeoConvHelper::writeLocation(device); // write edge types and restrictions nb.getTypeCont().writeTypes(device); // write inner lanes bool origNames = oc.getBool("output.original-names"); if (!oc.getBool("no-internal-links")) { bool hadAny = false; for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { hadAny |= writeInternalEdges(device, *(*i).second, origNames); } if (hadAny) { device.lf(); } } // write edges with lanes and connected edges bool noNames = !oc.getBool("output.street-names"); for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) { writeEdge(device, *(*i).second, noNames, origNames); } device.lf(); // write tls logics writeTrafficLights(device, nb.getTLLogicCont()); // write the nodes (junctions) std::set<NBNode*> roundaboutNodes; const bool checkLaneFoesAll = oc.getBool("check-lane-foes.all"); const bool checkLaneFoesRoundabout = !checkLaneFoesAll && oc.getBool("check-lane-foes.roundabout"); if (checkLaneFoesRoundabout) { const std::set<EdgeSet>& roundabouts = ec.getRoundabouts(); for (std::set<EdgeSet>::const_iterator i = roundabouts.begin(); i != roundabouts.end(); ++i) { for (EdgeSet::const_iterator j = (*i).begin(); j != (*i).end(); ++j) { roundaboutNodes.insert((*j)->getToNode()); } } } for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { const bool checkLaneFoes = checkLaneFoesAll || (checkLaneFoesRoundabout && roundaboutNodes.count((*i).second) > 0); writeJunction(device, *(*i).second, checkLaneFoes); } device.lf(); const bool includeInternal = !oc.getBool("no-internal-links"); if (includeInternal) { // ... internal nodes if not unwanted bool hadAny = false; for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { hadAny |= writeInternalNodes(device, *(*i).second); } if (hadAny) { device.lf(); } } // write the successors of lanes unsigned int numConnections = 0; for (std::map<std::string, NBEdge*>::const_iterator it_edge = ec.begin(); it_edge != ec.end(); it_edge++) { NBEdge* from = it_edge->second; from->sortOutgoingConnectionsByIndex(); const std::vector<NBEdge::Connection> connections = from->getConnections(); numConnections += (unsigned int)connections.size(); for (std::vector<NBEdge::Connection>::const_iterator it_c = connections.begin(); it_c != connections.end(); it_c++) { writeConnection(device, *from, *it_c, includeInternal); } } if (numConnections > 0) { device.lf(); } if (includeInternal) { // ... internal successors if not unwanted bool hadAny = false; for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { hadAny |= writeInternalConnections(device, *(*i).second); } if (hadAny) { device.lf(); } } for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NBNode* node = (*i).second; // write connections from pedestrian crossings const std::vector<NBNode::Crossing>& crossings = node->getCrossings(); for (std::vector<NBNode::Crossing>::const_iterator it = crossings.begin(); it != crossings.end(); it++) { NWWriter_SUMO::writeInternalConnection(device, (*it).id, (*it).nextWalkingArea, 0, 0, ""); } // write connections from pedestrian walking areas const std::vector<NBNode::WalkingArea>& WalkingAreas = node->getWalkingAreas(); for (std::vector<NBNode::WalkingArea>::const_iterator it = WalkingAreas.begin(); it != WalkingAreas.end(); it++) { if ((*it).nextCrossing != "") { const NBNode::Crossing& nextCrossing = node->getCrossing((*it).nextCrossing); // connection to next crossing (may be tls-controlled) device.openTag(SUMO_TAG_CONNECTION); device.writeAttr(SUMO_ATTR_FROM, (*it).id); device.writeAttr(SUMO_ATTR_TO, (*it).nextCrossing); device.writeAttr(SUMO_ATTR_FROM_LANE, 0); device.writeAttr(SUMO_ATTR_TO_LANE, 0); if (node->isTLControlled()) { device.writeAttr(SUMO_ATTR_TLID, (*node->getControllingTLS().begin())->getID()); assert(nextCrossing.tlLinkNo >= 0); device.writeAttr(SUMO_ATTR_TLLINKINDEX, nextCrossing.tlLinkNo); } device.writeAttr(SUMO_ATTR_DIR, LINKDIR_STRAIGHT); device.writeAttr(SUMO_ATTR_STATE, nextCrossing.priority ? LINKSTATE_MAJOR : LINKSTATE_MINOR); device.closeTag(); } // optional connections from/to sidewalk for (std::vector<std::string>::const_iterator it_sw = (*it).nextSidewalks.begin(); it_sw != (*it).nextSidewalks.end(); ++it_sw) { NWWriter_SUMO::writeInternalConnection(device, (*it).id, (*it_sw), 0, 0, ""); } for (std::vector<std::string>::const_iterator it_sw = (*it).prevSidewalks.begin(); it_sw != (*it).prevSidewalks.end(); ++it_sw) { NWWriter_SUMO::writeInternalConnection(device, (*it_sw), (*it).id, 0, 0, ""); } } } // write loaded prohibitions for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { writeProhibitions(device, i->second->getProhibitions()); } // write roundabout information writeRoundabouts(device, ec.getRoundabouts(), ec); // write the districts for (std::map<std::string, NBDistrict*>::const_iterator i = dc.begin(); i != dc.end(); i++) { writeDistrict(device, *(*i).second); } if (dc.size() != 0) { device.lf(); } device.close(); }
void NWWriter_SUMO::writeJunction(OutputDevice& into, const NBNode& n, const bool checkLaneFoes) { // write the attributes into.openTag(SUMO_TAG_JUNCTION).writeAttr(SUMO_ATTR_ID, n.getID()); into.writeAttr(SUMO_ATTR_TYPE, n.getType()); NWFrame::writePositionLong(n.getPosition(), into); // write the incoming lanes std::string incLanes; const std::vector<NBEdge*>& incoming = n.getIncomingEdges(); for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); ++i) { unsigned int noLanes = (*i)->getNumLanes(); for (unsigned int j = 0; j < noLanes; j++) { incLanes += (*i)->getLaneID(j); if (i != incoming.end() - 1 || j < noLanes - 1) { incLanes += ' '; } } } const std::vector<NBNode::Crossing>& crossings = n.getCrossings(); for (std::vector<NBNode::Crossing>::const_iterator it = crossings.begin(); it != crossings.end(); it++) { incLanes += ' ' + (*it).prevWalkingArea + "_0"; } into.writeAttr(SUMO_ATTR_INCLANES, incLanes); // write the internal lanes std::string intLanes; if (!OptionsCont::getOptions().getBool("no-internal-links")) { unsigned int l = 0; for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) { const std::vector<NBEdge::Connection>& elv = (*i)->getConnections(); for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) { if ((*k).toEdge == 0) { continue; } if (l != 0) { intLanes += ' '; } if (!(*k).haveVia) { intLanes += (*k).getInternalLaneID(); } else { intLanes += (*k).viaID + "_0"; } l++; } } } if (n.getType() != NODETYPE_DEAD_END && n.getType() != NODETYPE_NOJUNCTION) { for (std::vector<NBNode::Crossing>::const_iterator it = crossings.begin(); it != crossings.end(); it++) { intLanes += ' ' + (*it).id + "_0"; } } into.writeAttr(SUMO_ATTR_INTLANES, intLanes); // close writing into.writeAttr(SUMO_ATTR_SHAPE, n.getShape()); // write optional radius if (n.getRadius() != NBNode::UNSPECIFIED_RADIUS) { into.writeAttr(SUMO_ATTR_RADIUS, n.getRadius()); } // specify whether a custom shape was used if (n.hasCustomShape()) { into.writeAttr(SUMO_ATTR_CUSTOMSHAPE, true); } if (n.getType() == NODETYPE_DEAD_END) { into.closeTag(); } else { // write right-of-way logics n.writeLogic(into, checkLaneFoes); into.closeTag(); } }
bool NWWriter_SUMO::writeInternalEdges(OutputDevice& into, const NBNode& n, bool origNames) { bool ret = false; const EdgeVector& incoming = n.getIncomingEdges(); for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) { const std::vector<NBEdge::Connection>& elv = (*i)->getConnections(); if (elv.size() > 0) { bool haveVia = false; NBEdge* toEdge = 0; std::string internalEdgeID = ""; // first pass: compute average lengths of non-via edges std::map<NBEdge*, SUMOReal> lengthSum; std::map<NBEdge*, int> numLanes; for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) { lengthSum[(*k).toEdge] += MAX2((*k).shape.length(), POSITION_EPS); numLanes[(*k).toEdge] += 1; } // second pass: write non-via edges for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) { if ((*k).toEdge == 0) { assert(false); // should never happen. tell me when it does continue; } if (toEdge != (*k).toEdge) { internalEdgeID = (*k).id; if (toEdge != 0) { // close the previous edge into.closeTag(); } toEdge = (*k).toEdge; into.openTag(SUMO_TAG_EDGE); into.writeAttr(SUMO_ATTR_ID, internalEdgeID); into.writeAttr(SUMO_ATTR_FUNCTION, EDGEFUNC_INTERNAL); // open a new edge } // to avoid changing to an internal lane which has a successor // with the wrong permissions we need to inherit them from the successor const NBEdge::Lane& successor = (*k).toEdge->getLanes()[(*k).toLane]; const SUMOReal length = lengthSum[toEdge] / numLanes[toEdge]; // @note the actual length should be used once sumo supports lanes of // varying length within the same edge //const SUMOReal length = MAX2((*k).shape.length(), POSITION_EPS); writeLane(into, internalEdgeID, (*k).getInternalLaneID(), (*k).vmax, successor.permissions, successor.preferred, NBEdge::UNSPECIFIED_OFFSET, successor.width, (*k).shape, (*k).origID, length, (*k).internalLaneIndex, origNames, &n); haveVia = haveVia || (*k).haveVia; } ret = true; into.closeTag(); // close the last edge // third pass: write via edges if (haveVia) { for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) { if (!(*k).haveVia) { continue; } if ((*k).toEdge == 0) { assert(false); // should never happen. tell me when it does continue; } const NBEdge::Lane& successor = (*k).toEdge->getLanes()[(*k).toLane]; into.openTag(SUMO_TAG_EDGE); into.writeAttr(SUMO_ATTR_ID, (*k).viaID); into.writeAttr(SUMO_ATTR_FUNCTION, EDGEFUNC_INTERNAL); writeLane(into, (*k).viaID, (*k).viaID + "_0", (*k).viaVmax, SVCAll, SVCAll, NBEdge::UNSPECIFIED_OFFSET, successor.width, (*k).viaShape, (*k).origID, MAX2((*k).viaShape.length(), POSITION_EPS), // microsim needs positive length 0, origNames, &n); into.closeTag(); } } } } // write pedestrian crossings const std::vector<NBNode::Crossing>& crossings = n.getCrossings(); for (std::vector<NBNode::Crossing>::const_iterator it = crossings.begin(); it != crossings.end(); it++) { into.openTag(SUMO_TAG_EDGE); into.writeAttr(SUMO_ATTR_ID, (*it).id); into.writeAttr(SUMO_ATTR_FUNCTION, EDGEFUNC_CROSSING); into.writeAttr(SUMO_ATTR_CROSSING_EDGES, (*it).edges); writeLane(into, (*it).id, (*it).id + "_0", 1, SVC_PEDESTRIAN, 0, NBEdge::UNSPECIFIED_OFFSET, (*it).width, (*it).shape, "", (*it).shape.length(), 0, false, &n); into.closeTag(); } // write pedestrian walking areas const std::vector<NBNode::WalkingArea>& WalkingAreas = n.getWalkingAreas(); for (std::vector<NBNode::WalkingArea>::const_iterator it = WalkingAreas.begin(); it != WalkingAreas.end(); it++) { const NBNode::WalkingArea& wa = *it; into.openTag(SUMO_TAG_EDGE); into.writeAttr(SUMO_ATTR_ID, wa.id); into.writeAttr(SUMO_ATTR_FUNCTION, EDGEFUNC_WALKINGAREA); writeLane(into, wa.id, wa.id + "_0", 1, SVC_PEDESTRIAN, 0, NBEdge::UNSPECIFIED_OFFSET, wa.width, wa.shape, "", wa.length, 0, false, &n); into.closeTag(); } return ret; }