std::pair<NBEdge*, NBEdge*> NBOwnTLDef::getBestPair(EdgeVector& incoming) { if (incoming.size() == 1) { // only one there - return the one std::pair<NBEdge*, NBEdge*> ret(*incoming.begin(), static_cast<NBEdge*>(0)); incoming.clear(); return ret; } // determine the best combination // by priority, first EdgeVector used; std::sort(incoming.begin(), incoming.end(), edge_by_incoming_priority_sorter()); used.push_back(*incoming.begin()); // the first will definitely be used // get the ones with the same priority int prio = getToPrio(*used.begin()); for (EdgeVector::iterator i = incoming.begin() + 1; i != incoming.end() && prio != getToPrio(*i); ++i) { used.push_back(*i); } // if there only lower priorised, use these, too if (used.size() < 2) { used = incoming; } std::pair<NBEdge*, NBEdge*> ret = getBestCombination(used); incoming.erase(find(incoming.begin(), incoming.end(), ret.first)); incoming.erase(find(incoming.begin(), incoming.end(), ret.second)); return ret; }
void NBDistrict::replaceOutgoing(const EdgeVector& which, NBEdge* const by) { // temporary structures EdgeVector newList; WeightsCont newWeights; SUMOReal joinedVal = 0; // go through the list of sinks EdgeVector::iterator i = mySources.begin(); WeightsCont::iterator j = mySourceWeights.begin(); for (; i != mySources.end(); i++, j++) { NBEdge* tmp = (*i); SUMOReal val = (*j); if (find(which.begin(), which.end(), tmp) == which.end()) { // if the current edge shall not be replaced, add to the // temporary list newList.push_back(tmp); newWeights.push_back(val); } else { // otherwise, skip it and add its weight to the one to be inserted // instead joinedVal += val; } } // add the one to be inserted instead newList.push_back(by); newWeights.push_back(joinedVal); // assign to values mySources = newList; mySourceWeights = newWeights; }
void Plot::createCubic3() { createCube(1, Triple(0,0,0)); createCube(2, Triple(1,1,1) * (-0.5)); edges.push_back(Edge(0, 8)); edges.push_back(Edge(1, 9)); edges.push_back(Edge(2, 10)); edges.push_back(Edge(3, 11)); edges.push_back(Edge(4, 12)); edges.push_back(Edge(5, 13)); edges.push_back(Edge(6, 14)); edges.push_back(Edge(7, 15)); createDataset(nodes, edges); }
RealType bottleneck_distance(const Diagram1& dgm1, const Diagram2& dgm2, const Norm& norm) { typedef typename Diagram1::const_iterator Citer1; typedef typename Diagram2::const_iterator Citer2; const unsigned max_size = dgm1.size() + dgm2.size(); // Compute all the edges and sort them by distance EdgeVector edges; // Connect all diagonal points to each other for (unsigned i = dgm1.size(); i < max_size; ++i) for (unsigned j = max_size + dgm2.size(); j < 2*max_size; ++j) edges.push_back(Edge(i, j, 0)); // Edges between real points unsigned i = 0; for (Citer1 cur1 = dgm1.begin(); cur1 != dgm1.end(); ++cur1) { unsigned j = max_size; for (Citer2 cur2 = dgm2.begin(); cur2 != dgm2.end(); ++cur2) edges.push_back(Edge(i,j++, norm(*cur1, *cur2))); ++i; } // Edges between real points and their corresponding diagonal points i = 0; for (Citer1 cur1 = dgm1.begin(); cur1 != dgm1.end(); ++cur1, ++i) edges.push_back(Edge(i, max_size + dgm2.size() + i, norm.diagonal(*cur1))); i = max_size; for (Citer2 cur2 = dgm2.begin(); cur2 != dgm2.end(); ++cur2, ++i) edges.push_back(Edge(dgm1.size() + (i - max_size), i, norm.diagonal(*cur2))); std::sort(edges.begin(), edges.end()); //for (i = 0; i < edges.size(); ++i) // std::cout << "Edge: " << edges[i].first << " " << edges[i].second << " " << edges[i].distance << std::endl; // Perform cardinality based binary search typedef boost::counting_iterator<EV_const_iterator> EV_counting_const_iterator; EV_counting_const_iterator bdistance = std::upper_bound(EV_counting_const_iterator(edges.begin()), EV_counting_const_iterator(edges.end()), edges.begin(), CardinaliyComparison(max_size, edges.begin())); return (*bdistance)->distance; }
NBEdge* NBEdgeCont::retrievePossiblySplit(const std::string& id, const std::string& hint, bool incoming) const { // try to retrieve using the given name (iterative) NBEdge* edge = retrieve(id); if (edge != 0) { return edge; } // now, we did not find it; we have to look over all possibilities EdgeVector hints; // check whether at least the hint was not splitted NBEdge* hintedge = retrieve(hint); if (hintedge == 0) { hints = getGeneratedFrom(hint); } else { hints.push_back(hintedge); } EdgeVector candidates = getGeneratedFrom(id); for (EdgeVector::iterator i = hints.begin(); i != hints.end(); i++) { NBEdge* hintedge = (*i); for (EdgeVector::iterator j = candidates.begin(); j != candidates.end(); j++) { NBEdge* poss_searched = (*j); NBNode* node = incoming ? poss_searched->myTo : poss_searched->myFrom; const EdgeVector& cont = incoming ? node->getOutgoingEdges() : node->getIncomingEdges(); if (find(cont.begin(), cont.end(), hintedge) != cont.end()) { return poss_searched; } } } return 0; }
// check that for HEFace f the vertices TYPE are connected bool VoronoiDiagramChecker::faceVerticesConnected( HEFace f, VoronoiVertexStatus Vtype ) { VertexVector face_verts = g.face_vertices(f); VertexVector type_verts; BOOST_FOREACH( HEVertex v, face_verts ) { if ( g[v].status == Vtype ) type_verts.push_back(v); // build a vector of all Vtype vertices } assert( !type_verts.empty() ); if (type_verts.size()==1) // set of 1 is allways connected return true; // check that type_verts are connected HEEdge currentEdge = g[f].edge; HEVertex endVertex = g.source(currentEdge); // stop when target here EdgeVector startEdges; bool done = false; while (!done) { HEVertex src = g.source( currentEdge ); HEVertex trg = g.target( currentEdge ); if ( g[src].status != Vtype ) { // seach ?? - Vtype if ( g[trg].status == Vtype ) { // we have found ?? - Vtype startEdges.push_back( currentEdge ); } } currentEdge = g[currentEdge].next; if ( trg == endVertex ) { done = true; } } assert( !startEdges.empty() ); if ( startEdges.size() != 1 ) // when the Vtype vertices are connected, there is exactly one startEdge return false; else return true; }
EdgeVector NBEdgeCont::getGeneratedFrom(const std::string& id) const { size_t len = id.length(); EdgeVector ret; for (EdgeCont::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) { std::string curr = (*i).first; // the next check makes it possibly faster - we don not have // to compare the names if (curr.length() <= len) { continue; } // the name must be the same as the given id but something // beginning with a '[' must be appended to it if (curr.substr(0, len) == id && curr[len] == '[') { ret.push_back((*i).second); continue; } // ok, maybe the edge is a compound made during joining of edges size_t pos = curr.find(id); // surely not if (pos == std::string::npos) { continue; } // check leading char if (pos > 0) { if (curr[pos - 1] != ']' && curr[pos - 1] != '+') { // actually, this is another id continue; } } if (pos + id.length() < curr.length()) { if (curr[pos + id.length()] != '[' && curr[pos + id.length()] != '+') { // actually, this is another id continue; } } ret.push_back((*i).second); } return ret; }
void Plot::createCube(double length, const Triple& shift) { unsigned m = nodes.size(); nodes.push_back(Triple(0,0,0)+shift); nodes.push_back(Triple(0,0,length)+shift); nodes.push_back(Triple(0,length,length)+shift); nodes.push_back(Triple(0,length,0)+shift); nodes.push_back(Triple(length,0,0)+shift); nodes.push_back(Triple(length,0,length)+shift); nodes.push_back(Triple(length,length,length)+shift); nodes.push_back(Triple(length,length,0)+shift); edges.push_back(Edge(m+0, m+1)); edges.push_back(Edge(m+1, m+2)); edges.push_back(Edge(m+2, m+3)); edges.push_back(Edge(m+3, m+0)); unsigned n = 4; edges.push_back(Edge(m+0+n, m+1+n)); edges.push_back(Edge(m+1+n, m+2+n)); edges.push_back(Edge(m+2+n, m+3+n)); edges.push_back(Edge(m+3+n, m+0+n)); edges.push_back(Edge(m+0, m+0+n)); edges.push_back(Edge(m+1, m+1+n)); edges.push_back(Edge(m+2, m+2+n)); edges.push_back(Edge(m+3, m+3+n)); }
bool GNECrossing::isValid(SumoXMLAttr key, const std::string& value) { auto crossing = myParentJunction->getNBNode()->getCrossing(myCrossingEdges); switch (key) { case SUMO_ATTR_ID: return false; case SUMO_ATTR_EDGES: if (canParse<std::vector<GNEEdge*> >(myNet, value, false)) { // parse edges and save their IDs in a set std::vector<GNEEdge*> parsedEdges = parse<std::vector<GNEEdge*> >(myNet, value); EdgeVector nbEdges; for (auto i : parsedEdges) { nbEdges.push_back(i->getNBEdge()); } std::sort(nbEdges.begin(), nbEdges.end()); // EdgeVector originalEdges = crossing->edges; std::sort(originalEdges.begin(), originalEdges.end()); // return true if we're setting the same edges if (toString(nbEdges) == toString(originalEdges)) { return true; } else { return !myParentJunction->getNBNode()->checkCrossingDuplicated(nbEdges); } } else { return false; } case SUMO_ATTR_WIDTH: return canParse<double>(value) && ((parse<double>(value) > 0) || (parse<double>(value) == -1)); // kann NICHT 0 sein, oder -1 (bedeutet default) case SUMO_ATTR_PRIORITY: return canParse<bool>(value); case SUMO_ATTR_TLLINKINDEX: case SUMO_ATTR_TLLINKINDEX2: return (crossing->tlID != "" && canParse<int>(value) // -1 means that tlLinkIndex2 takes on the same value as tlLinkIndex when setting idnices && ((parse<double>(value) >= 0) || ((parse<double>(value) == -1) && (key == SUMO_ATTR_TLLINKINDEX2))) && myParentJunction->getNBNode()->getControllingTLS().size() > 0 && (*myParentJunction->getNBNode()->getControllingTLS().begin())->getMaxValidIndex() >= parse<int>(value)); case SUMO_ATTR_CUSTOMSHAPE: { // empty shapes are allowed return canParse<PositionVector>(value); } case GNE_ATTR_SELECTED: return canParse<bool>(value); case GNE_ATTR_GENERIC: return isGenericParametersValid(value); default: throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'"); } }
// ----- 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 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 Plot::createCubic2() { unsigned xs = 2; unsigned ys = xs; unsigned zs = xs; unsigned i,j,k; for (i=0; i!=xs; ++i) for (j=0; j!=ys; ++j) for (k=0; k!=zs; ++k) nodes.push_back(Triple(i,j,k)); for (i=0; i!=nodes.size()-1; ++i) { edges.push_back(Edge(i,i+1)); } createDataset(nodes, edges); }
void NIXMLConnectionsHandler::addWalkingArea(const SUMOSAXAttributes& attrs) { bool ok = true; NBNode* node = 0; EdgeVector edges; const std::string nodeID = attrs.get<std::string>(SUMO_ATTR_NODE, 0, ok); std::vector<std::string> edgeIDs; if (!attrs.hasAttribute(SUMO_ATTR_EDGES)) { WRITE_ERROR("No edges specified for walkingArea at node '" + nodeID + "'."); return; } SUMOSAXAttributes::parseStringVector(attrs.get<std::string>(SUMO_ATTR_EDGES, 0, ok), edgeIDs); if (!ok) { return; } for (std::vector<std::string>::const_iterator it = edgeIDs.begin(); it != edgeIDs.end(); ++it) { NBEdge* edge = myEdgeCont.retrieve(*it); if (edge == 0) { WRITE_ERROR("Edge '" + (*it) + "' for walkingArea at node '" + nodeID + "' is not known."); return; } if (node == 0) { if (edge->getToNode()->getID() == nodeID) { node = edge->getToNode(); } else if (edge->getFromNode()->getID() == nodeID) { node = edge->getFromNode(); } else { WRITE_ERROR("Edge '" + (*it) + "' does not touch node '" + nodeID + "'."); return; } } else { if (edge->getToNode() != node && edge->getFromNode() != node) { WRITE_ERROR("Edge '" + (*it) + "' does not touch node '" + nodeID + "'."); return; } } edges.push_back(edge); } PositionVector customShape = attrs.getOpt<PositionVector>(SUMO_ATTR_SHAPE, 0, ok, PositionVector::EMPTY); if (!NBNetBuilder::transformCoordinates(customShape)) { WRITE_ERROR("Unable to project shape for walkingArea at node '" + node->getID() + "'."); } node->addWalkingAreaShape(edges, customShape); }
std::set<NBEdge*> NBTrafficLightDefinition::collectReachable(EdgeVector outer, const EdgeVector& within, bool checkControlled) { std::set<NBEdge*> reachable; while (outer.size() > 0) { NBEdge* from = outer.back(); outer.pop_back(); std::vector<NBEdge::Connection>& cons = from->getConnections(); for (std::vector<NBEdge::Connection>::iterator k = cons.begin(); k != cons.end(); k++) { NBEdge* to = (*k).toEdge; if (reachable.count(to) == 0 && (find(within.begin(), within.end(), to) != within.end()) && (!checkControlled || from->mayBeTLSControlled((*k).fromLane, to, (*k).toLane))) { reachable.insert(to); outer.push_back(to); } } } return reachable; }
static void mergeBlocks(ir::IRKernel& k, ir::ControlFlowGraph::iterator predecessor, ir::ControlFlowGraph::iterator block) { typedef std::vector<ir::Edge> EdgeVector; // delete the branch at the end of the predecessor auto branch = getBranch(predecessor); if(branch != 0) { delete branch; predecessor->instructions.pop_back(); } // move remaining instructions intro the predecessor predecessor->instructions.insert(predecessor->instructions.end(), block->instructions.begin(), block->instructions.end()); block->instructions.clear(); // track the block's out edges EdgeVector outEdges; for(auto edge = block->out_edges.begin(); edge != block->out_edges.end(); ++edge) { outEdges.push_back(**edge); } // remove the block k.cfg()->remove_block(block); // add the edges back in for(auto edge = outEdges.begin(); edge != outEdges.end(); ++edge) { k.cfg()->insert_edge(ir::Edge(predecessor, edge->tail, edge->type)); } }
void NIImporter_SUMO::_loadNetwork(OptionsCont& oc) { // check whether the option is set (properly) if (!oc.isUsableFileList("sumo-net-file")) { return; } // parse file(s) std::vector<std::string> files = oc.getStringVector("sumo-net-file"); for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) { if (!FileHelpers::isReadable(*file)) { WRITE_ERROR("Could not open sumo-net-file '" + *file + "'."); return; } setFileName(*file); PROGRESS_BEGIN_MESSAGE("Parsing sumo-net from '" + *file + "'"); XMLSubSys::runParser(*this, *file, true); PROGRESS_DONE_MESSAGE(); } // build edges for (std::map<std::string, EdgeAttrs*>::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) { EdgeAttrs* ed = (*i).second; // skip internal edges if (ed->func == EDGEFUNC_INTERNAL || ed->func == EDGEFUNC_CROSSING || ed->func == EDGEFUNC_WALKINGAREA) { continue; } // get and check the nodes NBNode* from = myNodeCont.retrieve(ed->fromNode); NBNode* to = myNodeCont.retrieve(ed->toNode); if (from == 0) { WRITE_ERROR("Edge's '" + ed->id + "' from-node '" + ed->fromNode + "' is not known."); continue; } if (to == 0) { WRITE_ERROR("Edge's '" + ed->id + "' to-node '" + ed->toNode + "' is not known."); continue; } // edge shape PositionVector geom; if (ed->shape.size() > 0) { geom = ed->shape; } else { // either the edge has default shape consisting only of the two node // positions or we have a legacy network geom = reconstructEdgeShape(ed, from->getPosition(), to->getPosition()); } // build and insert the edge NBEdge* e = new NBEdge(ed->id, from, to, ed->type, ed->maxSpeed, (unsigned int) ed->lanes.size(), ed->priority, NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET, geom, ed->streetName, "", ed->lsf, true); // always use tryIgnoreNodePositions to keep original shape e->setLoadedLength(ed->length); if (!myNetBuilder.getEdgeCont().insert(e)) { WRITE_ERROR("Could not insert edge '" + ed->id + "'."); delete e; continue; } ed->builtEdge = myNetBuilder.getEdgeCont().retrieve(ed->id); } // assign further lane attributes (edges are built) for (std::map<std::string, EdgeAttrs*>::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) { EdgeAttrs* ed = (*i).second; NBEdge* nbe = ed->builtEdge; if (nbe == 0) { // inner edge or removed by explicit list, vclass, ... continue; } for (unsigned int fromLaneIndex = 0; fromLaneIndex < (unsigned int) ed->lanes.size(); ++fromLaneIndex) { LaneAttrs* lane = ed->lanes[fromLaneIndex]; // connections const std::vector<Connection>& connections = lane->connections; for (std::vector<Connection>::const_iterator c_it = connections.begin(); c_it != connections.end(); c_it++) { const Connection& c = *c_it; if (myEdges.count(c.toEdgeID) == 0) { WRITE_ERROR("Unknown edge '" + c.toEdgeID + "' given in connection."); continue; } NBEdge* toEdge = myEdges[c.toEdgeID]->builtEdge; if (toEdge == 0) { // removed by explicit list, vclass, ... continue; } if (nbe->hasConnectionTo(toEdge, c.toLaneIdx)) { WRITE_WARNING("Target lane '" + toEdge->getLaneID(c.toLaneIdx) + "' has multiple connections from '" + nbe->getID() + "'."); } nbe->addLane2LaneConnection( fromLaneIndex, toEdge, c.toLaneIdx, NBEdge::L2L_VALIDATED, true, c.mayDefinitelyPass, c.keepClear, c.contPos); // maybe we have a tls-controlled connection if (c.tlID != "" && myRailSignals.count(c.tlID) == 0) { const std::map<std::string, NBTrafficLightDefinition*>& programs = myTLLCont.getPrograms(c.tlID); if (programs.size() > 0) { std::map<std::string, NBTrafficLightDefinition*>::const_iterator it; for (it = programs.begin(); it != programs.end(); it++) { NBLoadedSUMOTLDef* tlDef = dynamic_cast<NBLoadedSUMOTLDef*>(it->second); if (tlDef) { tlDef->addConnection(nbe, toEdge, fromLaneIndex, c.toLaneIdx, c.tlLinkNo); } else { throw ProcessError("Corrupt traffic light definition '" + c.tlID + "' (program '" + it->first + "')"); } } } else { WRITE_ERROR("The traffic light '" + c.tlID + "' is not known."); } } } // allow/disallow XXX preferred nbe->setPermissions(parseVehicleClasses(lane->allow, lane->disallow), fromLaneIndex); // width, offset nbe->setLaneWidth(fromLaneIndex, lane->width); nbe->setEndOffset(fromLaneIndex, lane->endOffset); nbe->setSpeed(fromLaneIndex, lane->maxSpeed); } nbe->declareConnectionsAsLoaded(); if (!nbe->hasLaneSpecificWidth() && nbe->getLanes()[0].width != NBEdge::UNSPECIFIED_WIDTH) { nbe->setLaneWidth(-1, nbe->getLaneWidth(0)); } if (!nbe->hasLaneSpecificEndOffset() && nbe->getEndOffset(0) != NBEdge::UNSPECIFIED_OFFSET) { nbe->setEndOffset(-1, nbe->getEndOffset(0)); } } // insert loaded prohibitions for (std::vector<Prohibition>::const_iterator it = myProhibitions.begin(); it != myProhibitions.end(); it++) { NBEdge* prohibitedFrom = myEdges[it->prohibitedFrom]->builtEdge; NBEdge* prohibitedTo = myEdges[it->prohibitedTo]->builtEdge; NBEdge* prohibitorFrom = myEdges[it->prohibitorFrom]->builtEdge; NBEdge* prohibitorTo = myEdges[it->prohibitorTo]->builtEdge; if (prohibitedFrom == 0) { WRITE_WARNING("Edge '" + it->prohibitedFrom + "' in prohibition was not built"); } else if (prohibitedTo == 0) { WRITE_WARNING("Edge '" + it->prohibitedTo + "' in prohibition was not built"); } else if (prohibitorFrom == 0) { WRITE_WARNING("Edge '" + it->prohibitorFrom + "' in prohibition was not built"); } else if (prohibitorTo == 0) { WRITE_WARNING("Edge '" + it->prohibitorTo + "' in prohibition was not built"); } else { NBNode* n = prohibitedFrom->getToNode(); n->addSortedLinkFoes( NBConnection(prohibitorFrom, prohibitorTo), NBConnection(prohibitedFrom, prohibitedTo)); } } if (!myHaveSeenInternalEdge) { myNetBuilder.haveLoadedNetworkWithoutInternalEdges(); } if (oc.isDefault("lefthand")) { oc.set("lefthand", toString(myAmLefthand)); } if (oc.isDefault("junctions.corner-detail")) { oc.set("junctions.corner-detail", toString(myCornerDetail)); } if (oc.isDefault("junctions.internal-link-detail") && myLinkDetail > 0) { oc.set("junctions.internal-link-detail", toString(myLinkDetail)); } if (!deprecatedVehicleClassesSeen.empty()) { WRITE_WARNING("Deprecated vehicle class(es) '" + toString(deprecatedVehicleClassesSeen) + "' in input network."); deprecatedVehicleClassesSeen.clear(); } // add loaded crossings if (!oc.getBool("no-internal-links")) { for (std::map<std::string, std::vector<Crossing> >::const_iterator it = myPedestrianCrossings.begin(); it != myPedestrianCrossings.end(); ++it) { NBNode* node = myNodeCont.retrieve((*it).first); for (std::vector<Crossing>::const_iterator it_c = (*it).second.begin(); it_c != (*it).second.end(); ++it_c) { const Crossing& crossing = (*it_c); EdgeVector edges; for (std::vector<std::string>::const_iterator it_e = crossing.crossingEdges.begin(); it_e != crossing.crossingEdges.end(); ++it_e) { NBEdge* edge = myNetBuilder.getEdgeCont().retrieve(*it_e); // edge might have been removed due to options if (edge != 0) { edges.push_back(edge); } } if (edges.size() > 0) { node->addCrossing(edges, crossing.width, crossing.priority, true); } } } } // add roundabouts for (std::vector<std::vector<std::string> >::const_iterator it = myRoundabouts.begin(); it != myRoundabouts.end(); ++it) { EdgeSet roundabout; for (std::vector<std::string>::const_iterator it_r = it->begin(); it_r != it->end(); ++it_r) { NBEdge* edge = myNetBuilder.getEdgeCont().retrieve(*it_r); if (edge == 0) { if (!myNetBuilder.getEdgeCont().wasIgnored(*it_r)) { WRITE_ERROR("Unknown edge '" + (*it_r) + "' in roundabout"); } } else { roundabout.insert(edge); } } myNetBuilder.getEdgeCont().addRoundabout(roundabout); } }
void NBEdgeCont::guessRoundabouts(std::vector<EdgeVector>& marked) { // step 1: keep only those edges which have no turnarounds std::set<NBEdge*> candidates; for (EdgeCont::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) { NBEdge* e = (*i).second; NBNode* const to = e->getToNode(); if (e->getTurnDestination() == 0 && to->getConnectionTo(e->getFromNode()) == 0) { candidates.insert(e); } } // step 2: std::set<NBEdge*> visited; for (std::set<NBEdge*>::const_iterator i = candidates.begin(); i != candidates.end(); ++i) { EdgeVector loopEdges; // start with a random edge (this doesn't have to be a roundabout edge) // loop over connected edges (using always the leftmost one) // and keep the list in loopEdges // continue until we loop back onto a loopEdges and extract the loop NBEdge* e = (*i); if (visited.count(e) > 0) { // already seen continue; } loopEdges.push_back(e); bool doLoop = true; do { visited.insert(e); const EdgeVector& edges = e->getToNode()->getEdges(); if (edges.size() < 2) { doLoop = false; break; } if (e->getTurnDestination() != 0 || e->getToNode()->getConnectionTo(e->getFromNode()) != 0) { // do not follow turn-arounds while in a (tentative) loop doLoop = false; break; } EdgeVector::const_iterator me = find(edges.begin(), edges.end(), e); NBContHelper::nextCW(edges, me); NBEdge* left = *me; SUMOReal angle = fabs(NBHelpers::relAngle(e->getAngleAtNode(e->getToNode()), left->getAngleAtNode(e->getToNode()))); if (angle >= 90) { // roundabouts do not have sharp turns (or they wouldn't be called 'round') doLoop = false; break; } EdgeVector::const_iterator loopClosed = find(loopEdges.begin(), loopEdges.end(), left); const size_t loopSize = loopEdges.end() - loopClosed; if (loopSize > 0) { // loop found if (loopSize < 3) { doLoop = false; // need at least 3 edges for a roundabout } else if (loopSize < loopEdges.size()) { // remove initial edges not belonging to the loop EdgeVector(loopEdges.begin() + (loopEdges.size() - loopSize), loopEdges.end()).swap(loopEdges); } // count attachments to the outside. need at least 3 or a roundabout doesn't make much sense int attachments = 0; for (EdgeVector::const_iterator j = loopEdges.begin(); j != loopEdges.end(); ++j) { if ((*j)->getToNode()->getEdges().size() > 2) { attachments++; } } if (attachments < 3) { doLoop = false; } break; } if (visited.count(left) > 0) { doLoop = false; } else { // keep going loopEdges.push_back(left); e = left; } } while (doLoop); // mark collected edges in the case a loop (roundabout) was found if (doLoop) { std::set<NBEdge*> loopEdgesSet(loopEdges.begin(), loopEdges.end()); for (std::set<NBEdge*>::const_iterator j = loopEdgesSet.begin(); j != loopEdgesSet.end(); ++j) { // disable turnarounds on incoming edges NBNode* node = (*j)->getToNode(); const EdgeVector& incoming = node->getIncomingEdges(); for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); ++k) { NBEdge* inEdge = *k; if (loopEdgesSet.count(inEdge) > 0) { continue; } if ((inEdge)->getStep() >= NBEdge::LANES2LANES_USER) { continue; } inEdge->removeFromConnections(inEdge->getTurnDestination(), -1); } // let the connections to succeeding roundabout edge have a higher priority (*j)->setJunctionPriority(node, 1000); } marked.push_back(loopEdges); } } }
void NBEdgePriorityComputer::setPriorityJunctionPriorities(NBNode& n) { if (n.myIncomingEdges.size() == 0 || n.myOutgoingEdges.size() == 0) { return; } EdgeVector incoming = n.myIncomingEdges; EdgeVector outgoing = n.myOutgoingEdges; // what we do want to have is to extract the pair of roads that are // the major roads for this junction // let's get the list of incoming edges with the highest priority std::sort(incoming.begin(), incoming.end(), NBContHelper::edge_by_priority_sorter()); EdgeVector bestIncoming; NBEdge* best = incoming[0]; while (incoming.size() > 0 && samePriority(best, incoming[0])) { bestIncoming.push_back(*incoming.begin()); incoming.erase(incoming.begin()); } // now, let's get the list of best outgoing assert(outgoing.size() != 0); sort(outgoing.begin(), outgoing.end(), NBContHelper::edge_by_priority_sorter()); EdgeVector bestOutgoing; best = outgoing[0]; while (outgoing.size() > 0 && samePriority(best, outgoing[0])) { //->getPriority()==best->getPriority()) { bestOutgoing.push_back(*outgoing.begin()); outgoing.erase(outgoing.begin()); } // now, let's compute for each of the best incoming edges // the incoming which is most opposite // the outgoing which is most opposite EdgeVector::iterator i; std::map<NBEdge*, NBEdge*> counterIncomingEdges; std::map<NBEdge*, NBEdge*> counterOutgoingEdges; incoming = n.myIncomingEdges; outgoing = n.myOutgoingEdges; for (i = bestIncoming.begin(); i != bestIncoming.end(); ++i) { std::sort(incoming.begin(), incoming.end(), NBContHelper::edge_opposite_direction_sorter(*i, &n)); counterIncomingEdges[*i] = *incoming.begin(); std::sort(outgoing.begin(), outgoing.end(), NBContHelper::edge_opposite_direction_sorter(*i, &n)); counterOutgoingEdges[*i] = *outgoing.begin(); } // ok, let's try // 1) there is one best incoming road if (bestIncoming.size() == 1) { // let's mark this road as the best NBEdge* best1 = extractAndMarkFirst(n, bestIncoming); if (counterIncomingEdges.find(best1) != counterIncomingEdges.end()) { // ok, look, what we want is the opposit of the straight continuation edge // but, what if such an edge does not exist? By now, we'll determine it // geometrically NBEdge* s = counterIncomingEdges.find(best1)->second; if (GeomHelper::getMinAngleDiff(best1->getAngleAtNode(&n), s->getAngleAtNode(&n)) > 180 - 45) { s->setJunctionPriority(&n, 1); } } if (bestOutgoing.size() != 0) { // mark the best outgoing as the continuation sort(bestOutgoing.begin(), bestOutgoing.end(), NBContHelper::edge_similar_direction_sorter(best1)); best1 = extractAndMarkFirst(n, bestOutgoing); if (counterOutgoingEdges.find(best1) != counterOutgoingEdges.end()) { NBEdge* s = counterOutgoingEdges.find(best1)->second; if (GeomHelper::getMinAngleDiff(best1->getAngleAtNode(&n), s->getAngleAtNode(&n)) > 180 - 45) { s->setJunctionPriority(&n, 1); } } } return; } // ok, what we want to do in this case is to determine which incoming // has the best continuation... // This means, when several incoming roads have the same priority, // we want a (any) straight connection to be more priorised than a turning SUMOReal bestAngle = 0; NBEdge* bestFirst = 0; NBEdge* bestSecond = 0; bool hadBest = false; for (i = bestIncoming.begin(); i != bestIncoming.end(); ++i) { EdgeVector::iterator j; NBEdge* t1 = *i; SUMOReal angle1 = t1->getTotalAngle() + 180; if (angle1 >= 360) { angle1 -= 360; } for (j = i + 1; j != bestIncoming.end(); ++j) { NBEdge* t2 = *j; SUMOReal angle2 = t2->getTotalAngle() + 180; if (angle2 >= 360) { angle2 -= 360; } SUMOReal angle = GeomHelper::getMinAngleDiff(angle1, angle2); if (!hadBest || angle > bestAngle) { bestAngle = angle; bestFirst = *i; bestSecond = *j; hadBest = true; } } } bestFirst->setJunctionPriority(&n, 1); sort(bestOutgoing.begin(), bestOutgoing.end(), NBContHelper::edge_similar_direction_sorter(bestFirst)); if (bestOutgoing.size() != 0) { extractAndMarkFirst(n, bestOutgoing); } bestSecond->setJunctionPriority(&n, 1); sort(bestOutgoing.begin(), bestOutgoing.end(), NBContHelper::edge_similar_direction_sorter(bestSecond)); if (bestOutgoing.size() != 0) { extractAndMarkFirst(n, bestOutgoing); } }
void NIXMLConnectionsHandler::addCrossing(const SUMOSAXAttributes& attrs) { bool ok = true; NBNode* node = 0; EdgeVector edges; const std::string nodeID = attrs.get<std::string>(SUMO_ATTR_NODE, 0, ok); const double width = attrs.getOpt<double>(SUMO_ATTR_WIDTH, nodeID.c_str(), ok, NBEdge::UNSPECIFIED_WIDTH, true); const bool discard = attrs.getOpt<bool>(SUMO_ATTR_DISCARD, nodeID.c_str(), ok, false, true); int tlIndex = attrs.getOpt<int>(SUMO_ATTR_TLLINKINDEX, 0, ok, -1); int tlIndex2 = attrs.getOpt<int>(SUMO_ATTR_TLLINKINDEX2, 0, ok, -1); std::vector<std::string> edgeIDs; if (!attrs.hasAttribute(SUMO_ATTR_EDGES)) { if (discard) { node = myNodeCont.retrieve(nodeID); if (node == 0) { WRITE_ERROR("Node '" + nodeID + "' in crossing is not known."); return; } node->discardAllCrossings(true); return; } else { WRITE_ERROR("No edges specified for crossing at node '" + nodeID + "'."); return; } } SUMOSAXAttributes::parseStringVector(attrs.get<std::string>(SUMO_ATTR_EDGES, 0, ok), edgeIDs); if (!ok) { return; } for (std::vector<std::string>::const_iterator it = edgeIDs.begin(); it != edgeIDs.end(); ++it) { NBEdge* edge = myEdgeCont.retrieve(*it); if (edge == 0) { WRITE_ERROR("Edge '" + (*it) + "' for crossing at node '" + nodeID + "' is not known."); return; } if (node == 0) { if (edge->getToNode()->getID() == nodeID) { node = edge->getToNode(); } else if (edge->getFromNode()->getID() == nodeID) { node = edge->getFromNode(); } else { WRITE_ERROR("Edge '" + (*it) + "' does not touch node '" + nodeID + "'."); return; } } else { if (edge->getToNode() != node && edge->getFromNode() != node) { WRITE_ERROR("Edge '" + (*it) + "' does not touch node '" + nodeID + "'."); return; } } edges.push_back(edge); } bool priority = attrs.getOpt<bool>(SUMO_ATTR_PRIORITY, nodeID.c_str(), ok, node->isTLControlled(), true); if (node->isTLControlled() && !priority) { // traffic_light nodes should always have priority crossings WRITE_WARNING("Crossing at controlled node '" + nodeID + "' must be prioritized"); priority = true; } PositionVector customShape = attrs.getOpt<PositionVector>(SUMO_ATTR_SHAPE, 0, ok, PositionVector::EMPTY); if (!NBNetBuilder::transformCoordinates(customShape)) { WRITE_ERROR("Unable to project shape for crossing at node '" + node->getID() + "'."); } if (discard) { node->removeCrossing(edges); } else { if (node->checkCrossingDuplicated(edges)) { WRITE_ERROR("Crossing with edges '" + toString(edges) + "' already exists at node '" + node->getID() + "'."); return; } node->addCrossing(edges, width, priority, tlIndex, tlIndex2, customShape); } }
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."); } }