SUMO - Simulation of Urban MObility

NBNodeCont.cpp

Go to the documentation of this file.
00001 /****************************************************************************/
00013 // Container for nodes during the netbuilding process
00014 /****************************************************************************/
00015 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00016 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
00017 /****************************************************************************/
00018 //
00019 //   This file is part of SUMO.
00020 //   SUMO is free software: you can redistribute it and/or modify
00021 //   it under the terms of the GNU General Public License as published by
00022 //   the Free Software Foundation, either version 3 of the License, or
00023 //   (at your option) any later version.
00024 //
00025 /****************************************************************************/
00026 
00027 
00028 // ===========================================================================
00029 // included modules
00030 // ===========================================================================
00031 #ifdef _MSC_VER
00032 #include <windows_config.h>
00033 #else
00034 #include <config.h>
00035 #endif
00036 
00037 #include <string>
00038 #include <map>
00039 #include <algorithm>
00040 #include <cmath>
00041 #include <utils/options/OptionsCont.h>
00042 #include <utils/geom/Boundary.h>
00043 #include <utils/geom/GeomHelper.h>
00044 #include <utils/common/MsgHandler.h>
00045 #include <utils/common/UtilExceptions.h>
00046 #include <utils/common/StringTokenizer.h>
00047 #include <utils/common/StdDefs.h>
00048 #include <utils/common/ToString.h>
00049 #include <utils/xml/SUMOXMLDefinitions.h>
00050 #include <utils/geom/GeoConvHelper.h>
00051 #include <utils/iodevices/OutputDevice.h>
00052 #include "NBDistrict.h"
00053 #include "NBEdgeCont.h"
00054 #include "NBTrafficLightLogicCont.h"
00055 #include "NBJoinedEdgesMap.h"
00056 #include "NBOwnTLDef.h"
00057 #include "NBNodeCont.h"
00058 
00059 #ifdef CHECK_MEMORY_LEAKS
00060 #include <foreign/nvwa/debug_new.h>
00061 #endif // CHECK_MEMORY_LEAKS
00062 
00063 
00064 // ===========================================================================
00065 // method definitions
00066 // ===========================================================================
00067 NBNodeCont::NBNodeCont()
00068     : myInternalID(1) {}
00069 
00070 
00071 NBNodeCont::~NBNodeCont() {
00072     clear();
00073 }
00074 
00075 
00076 // ----------- Insertion/removal/retrieval of nodes
00077 bool
00078 NBNodeCont::insert(const std::string& id, const Position& position,
00079                    NBDistrict* district) {
00080     NodeCont::iterator i = myNodes.find(id);
00081     if (i != myNodes.end()) {
00082         return false;
00083     }
00084     NBNode* node = new NBNode(id, position, district);
00085     myNodes[id] = node;
00086     return true;
00087 }
00088 
00089 
00090 bool
00091 NBNodeCont::insert(const std::string& id, const Position& position) {
00092     NodeCont::iterator i = myNodes.find(id);
00093     if (i != myNodes.end()) {
00094         return false;
00095     }
00096     NBNode* node = new NBNode(id, position);
00097     myNodes[id] = node;
00098     return true;
00099 }
00100 
00101 
00102 Position
00103 NBNodeCont::insert(const std::string& id) {
00104     std::pair<SUMOReal, SUMOReal> ret(-1.0, -1.0);
00105     NodeCont::iterator i = myNodes.find(id);
00106     if (i != myNodes.end()) {
00107         return (*i).second->getPosition();
00108     } else {
00109         NBNode* node = new NBNode(id, Position(-1.0, -1.0));
00110         myNodes[id] = node;
00111     }
00112     return Position(-1, -1);
00113 }
00114 
00115 
00116 bool
00117 NBNodeCont::insert(NBNode* node) {
00118     std::string id = node->getID();
00119     NodeCont::iterator i = myNodes.find(id);
00120     if (i != myNodes.end()) {
00121         return false;
00122     }
00123     myNodes[id] = node;
00124     return true;
00125 }
00126 
00127 
00128 NBNode*
00129 NBNodeCont::retrieve(const std::string& id) const {
00130     NodeCont::const_iterator i = myNodes.find(id);
00131     if (i == myNodes.end()) {
00132         return 0;
00133     }
00134     return (*i).second;
00135 }
00136 
00137 
00138 NBNode*
00139 NBNodeCont::retrieve(const Position& position, SUMOReal offset) const {
00140     for (NodeCont::const_iterator i = myNodes.begin(); i != myNodes.end(); i++) {
00141         NBNode* node = (*i).second;
00142         if (fabs(node->getPosition().x() - position.x()) < offset
00143                 &&
00144                 fabs(node->getPosition().y() - position.y()) < offset) {
00145             return node;
00146         }
00147     }
00148     return 0;
00149 }
00150 
00151 
00152 bool
00153 NBNodeCont::erase(NBNode* node) {
00154     if (extract(node)) {
00155         delete node;
00156         return true;
00157     } else {
00158         return false;
00159     }
00160 }
00161 
00162 
00163 bool
00164 NBNodeCont::extract(NBNode* node, bool remember) {
00165     NodeCont::iterator i = myNodes.find(node->getID());
00166     if (i == myNodes.end()) {
00167         return false;
00168     }
00169     myNodes.erase(i);
00170     node->removeTrafficLights();
00171     if (remember) {
00172         myExtractedNodes.insert(node);
00173     }
00174     return true;
00175 }
00176 
00177 
00178 // ----------- Adapting the input
00179 void
00180 NBNodeCont::removeSelfLoops(NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tc) {
00181     unsigned int no = 0;
00182     for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
00183         no += (*i).second->removeSelfLoops(dc, ec, tc);
00184     }
00185     if (no != 0) {
00186         WRITE_WARNING(toString(no) + " self-looping edge(s) removed.");
00187     }
00188 }
00189 
00190 
00191 void
00192 NBNodeCont::joinSimilarEdges(NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tlc) {
00193     // magic values
00194     SUMOReal distanceThreshold = 7; // don't merge edges further apart
00195     SUMOReal lengthThreshold = 0.05; // don't merge edges with higher relative length-difference
00196 
00197     for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
00198         // count the edges to other nodes outgoing from the current node
00199         std::map<NBNode*, EdgeVector> connectionCount;
00200         const EdgeVector& outgoing = (*i).second->getOutgoingEdges();
00201         for (EdgeVector::const_iterator j = outgoing.begin(); j != outgoing.end(); j++) {
00202             NBEdge* e = (*j);
00203             NBNode* connected = e->getToNode();
00204             if (connectionCount.find(connected) == connectionCount.end()) {
00205                 connectionCount[connected] = EdgeVector();
00206             }
00207             connectionCount[connected].push_back(e);
00208         }
00209         // check whether more than a single edge connect another node and join them
00210         std::map<NBNode*, EdgeVector>::iterator k;
00211         for (k = connectionCount.begin(); k != connectionCount.end(); k++) {
00212             // possibly we do not have anything to join...
00213             if ((*k).second.size() < 2) {
00214                 continue;
00215             }
00216             // for the edges that seem to be a single street,
00217             //  check whether the geometry is similar
00218             const EdgeVector& ev = (*k).second;
00219             const NBEdge* const first = ev.front();
00220             EdgeVector::const_iterator jci; // join candidate iterator
00221             for (jci = ev.begin() + 1; jci != ev.end(); ++jci) {
00222                 const SUMOReal relativeLengthDifference = fabs(first->getLoadedLength() - (*jci)->getLoadedLength()) / first->getLoadedLength();
00223                 if ((!first->isNearEnough2BeJoined2(*jci, distanceThreshold)) ||
00224                         (relativeLengthDifference > lengthThreshold) ||
00225                         (first->getSpeed() != (*jci)->getSpeed())
00226                         // @todo check vclass
00227                    ) {
00228                     break;
00229                 }
00230             }
00231             // @bug If there are 3 edges of which 2 can be joined, no joining will
00232             //   take place with the current implementation
00233             if (jci == ev.end()) {
00234                 ec.joinSameNodeConnectingEdges(dc, tlc, ev);
00235             }
00236         }
00237     }
00238 }
00239 
00240 
00241 void
00242 NBNodeCont::removeIsolatedRoads(NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tc) {
00243     UNUSED_PARAMETER(tc);
00244     // Warn of isolated edges, i.e. a single edge with no connection to another edge
00245     int edgeCounter = 0;
00246     const std::vector<std::string> &edgeNames = ec.getAllNames();
00247     for (std::vector<std::string>::const_iterator it = edgeNames.begin(); it != edgeNames.end(); ++it) {
00248         // Test whether this node starts at a dead end, i.e. it has only one adjacent node
00249         // to which an edge exists and from which an edge may come.
00250         NBEdge* e = ec.retrieve(*it);
00251         if (e == 0) {
00252             continue;
00253         }
00254         NBNode* from = e->getFromNode();
00255         const EdgeVector& outgoingEdges = from->getOutgoingEdges();
00256         if (outgoingEdges.size() != 1) {
00257             // At this node, several edges or no edge start; so, this node is no dead end.
00258             continue;
00259         }
00260         const EdgeVector& incomingEdges = from->getIncomingEdges();
00261         if (incomingEdges.size() > 1) {
00262             // At this node, several edges end; so, this node is no dead end.
00263             continue;
00264         } else if (incomingEdges.size() == 1) {
00265             NBNode* fromNodeOfIncomingEdge = incomingEdges[0]->getFromNode();
00266             NBNode* toNodeOfOutgoingEdge = outgoingEdges[0]->getToNode();
00267             if (fromNodeOfIncomingEdge != toNodeOfOutgoingEdge) {
00268                 // At this node, an edge ends which is not the inverse direction of
00269                 // the starting node.
00270                 continue;
00271             }
00272         }
00273         // Now we know that the edge e starts a dead end.
00274         // Next we test if the dead end is isolated, i.e. does not lead to a junction
00275         bool hasJunction = false;
00276         EdgeVector road;
00277         NBEdge* eOld = 0;
00278         NBNode* to;
00279         std::set<NBNode*> adjacentNodes;
00280         do {
00281             road.push_back(e);
00282             eOld = e;
00283             from = e->getFromNode();
00284             to = e->getToNode();
00285             const EdgeVector& outgoingEdgesOfToNode = to->getOutgoingEdges();
00286             const EdgeVector& incomingEdgesOfToNode = to->getIncomingEdges();
00287             adjacentNodes.clear();
00288             for (EdgeVector::const_iterator itOfOutgoings = outgoingEdgesOfToNode.begin(); itOfOutgoings != outgoingEdgesOfToNode.end(); ++itOfOutgoings) {
00289                 if ((*itOfOutgoings)->getToNode() != from        // The back path
00290                         && (*itOfOutgoings)->getToNode() != to   // A loop / dummy edge
00291                    ) {
00292                     e = *itOfOutgoings; // Probably the next edge
00293                 }
00294                 adjacentNodes.insert((*itOfOutgoings)->getToNode());
00295             }
00296             for (EdgeVector::const_iterator itOfIncomings = incomingEdgesOfToNode.begin(); itOfIncomings != incomingEdgesOfToNode.end(); ++itOfIncomings) {
00297                 adjacentNodes.insert((*itOfIncomings)->getFromNode());
00298             }
00299             adjacentNodes.erase(to);  // Omit loops
00300             if (adjacentNodes.size() > 2) {
00301                 hasJunction = true;
00302             }
00303         } while (!hasJunction && eOld != e);
00304         if (!hasJunction) {
00305             edgeCounter +=  int(road.size());
00306             std::string warningString = "Removed a road without junctions: ";
00307             for (EdgeVector::iterator roadIt = road.begin(); roadIt != road.end(); ++roadIt) {
00308                 if (roadIt == road.begin()) {
00309                     warningString += (*roadIt)->getID();
00310                 } else {
00311                     warningString += ", " + (*roadIt)->getID();
00312                 }
00313 
00314                 NBNode* fromNode = (*roadIt)->getFromNode();
00315                 NBNode* toNode = (*roadIt)->getToNode();
00316                 ec.erase(dc, *roadIt);
00317                 if (fromNode->getIncomingEdges().size() == 0 && fromNode->getOutgoingEdges().size() == 0) {
00318                     // Node is empty; can be removed
00319                     erase(fromNode);
00320                 }
00321                 if (toNode->getIncomingEdges().size() == 0 && toNode->getOutgoingEdges().size() == 0) {
00322                     // Node is empty; can be removed
00323                     erase(toNode);
00324                 }
00325             }
00326             WRITE_WARNING(warningString);
00327         }
00328     }
00329     if (edgeCounter > 0 && !OptionsCont::getOptions().getBool("remove-edges.isolated")) {
00330         WRITE_WARNING("Detected isolated roads. Use the option --remove-edges.isolated to get a list of all affected edges.");
00331     }
00332 }
00333 
00334 
00335 unsigned int
00336 NBNodeCont::removeUnwishedNodes(NBDistrictCont& dc, NBEdgeCont& ec,
00337                                 NBJoinedEdgesMap& je, NBTrafficLightLogicCont& tlc,
00338                                 bool removeGeometryNodes) {
00339     unsigned int no = 0;
00340     std::vector<NBNode*> toRemove;
00341     for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
00342         NBNode* current = (*i).second;
00343         bool remove = false;
00344         std::vector<std::pair<NBEdge*, NBEdge*> > toJoin;
00345         // check for completely empty nodes
00346         if (current->getOutgoingEdges().size() == 0 && current->getIncomingEdges().size() == 0) {
00347             // remove if empty
00348             remove = true;
00349         }
00350         // check for nodes which are only geometry nodes
00351         if (removeGeometryNodes) {
00352             if ((current->getOutgoingEdges().size() == 1 && current->getIncomingEdges().size() == 1)
00353                     ||
00354                     (current->getOutgoingEdges().size() == 2 && current->getIncomingEdges().size() == 2)) {
00355                 // ok, one in, one out or two in, two out
00356                 //  -> ask the node whether to join
00357                 remove = current->checkIsRemovable();
00358                 if (remove) {
00359                     toJoin = current->getEdgesToJoin();
00360                 }
00361             }
00362         }
00363         // remove the node and join the geometries when wished
00364         if (!remove) {
00365             continue;
00366         }
00367         for (std::vector<std::pair<NBEdge*, NBEdge*> >::iterator j = toJoin.begin(); j != toJoin.end(); j++) {
00368             NBEdge* begin = (*j).first;
00369             NBEdge* continuation = (*j).second;
00370             begin->append(continuation);
00371             continuation->getToNode()->replaceIncoming(continuation, begin, 0);
00372             tlc.replaceRemoved(continuation, -1, begin, -1);
00373             je.appended(begin->getID(), continuation->getID());
00374             ec.erase(dc, continuation);
00375         }
00376         toRemove.push_back(current);
00377         no++;
00378     }
00379     // erase all
00380     for (std::vector<NBNode*>::iterator j = toRemove.begin(); j != toRemove.end(); ++j) {
00381         erase(*j);
00382     }
00383     return no;
00384 }
00385 
00386 
00387 // ----------- (Helper) methods for joining nodes
00388 void
00389 NBNodeCont::generateNodeClusters(SUMOReal maxDist, NodeClusters& into) const {
00390     std::set<NBNode*> visited;
00391     for (NodeCont::const_iterator i = myNodes.begin(); i != myNodes.end(); i++) {
00392         std::vector<NBNode*> toProc;
00393         if (visited.find((*i).second) != visited.end()) {
00394             continue;
00395         }
00396         toProc.push_back((*i).second);
00397         std::set<NBNode*> c;
00398         while (!toProc.empty()) {
00399             NBNode* n = toProc.back();
00400             toProc.pop_back();
00401             if (visited.find(n) != visited.end()) {
00402                 continue;
00403             }
00404             c.insert(n);
00405             visited.insert(n);
00406             const EdgeVector& edges = n->getEdges();
00407             for (EdgeVector::const_iterator j = edges.begin(); j != edges.end(); ++j) {
00408                 NBEdge* e = *j;
00409                 NBNode* s = 0;
00410                 if (n->hasIncoming(e)) {
00411                     s = e->getFromNode();
00412                 } else {
00413                     s = e->getToNode();
00414                 }
00415                 if (visited.find(s) != visited.end()) {
00416                     continue;
00417                 }
00418                 if (n->getPosition().distanceTo(s->getPosition()) < maxDist) {
00419                     toProc.push_back(s);
00420                 }
00421             }
00422         }
00423         if (c.size() < 2) {
00424             continue;
00425         }
00426         into.push_back(c);
00427     }
00428 }
00429 
00430 
00431 void
00432 NBNodeCont::addJoinExclusion(const std::vector<std::string> &ids, bool check) {
00433     for (std::vector<std::string>::const_iterator it = ids.begin(); it != ids.end(); it++) {
00434         // error handling has to take place here since joinExclusions could be
00435         // loaded from multiple files / command line
00436         if (myJoined.count(*it) > 0) {
00437             WRITE_WARNING("Ignoring join exclusion for node '" + *it +  "' since it already occured in a list of nodes to be joined");
00438         } else if (check && retrieve(*it) == 0) {
00439             WRITE_WARNING("Ignoring join exclusion for unknown node '" + *it + "'");
00440         } else {
00441             myJoinExclusions.insert(*it);
00442         }
00443     }
00444 }
00445 
00446 
00447 void
00448 NBNodeCont::addCluster2Join(std::set<std::string> cluster) {
00449     // error handling has to take place here since joins could be loaded from multiple files
00450     for (std::set<std::string>::const_iterator it = cluster.begin(); it != cluster.end(); it++) {
00451         if (myJoinExclusions.count(*it) > 0) {
00452             WRITE_WARNING("Ignoring join-cluster because node '" + *it + "' was already excluded from joining");
00453             return;
00454         } else if (myJoined.count(*it) > 0) {
00455             WRITE_WARNING("Ignoring join-cluster because node '" + *it + "' already occured in another join-cluster");
00456             return;
00457         } else {
00458             myJoined.insert(*it);
00459         }
00460     }
00461     myClusters2Join.push_back(cluster);
00462 }
00463 
00464 
00465 unsigned int
00466 NBNodeCont::joinLoadedClusters(NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tlc) {
00467     NodeClusters clusters;
00468     for (std::vector<std::set<std::string> >::iterator it = myClusters2Join.begin(); it != myClusters2Join.end(); it++) {
00469         // verify loaded cluster
00470         std::set<NBNode*> cluster;
00471         for (std::set<std::string>::iterator it_id = it->begin(); it_id != it->end(); it_id++) {
00472             NBNode* node = retrieve(*it_id);
00473             if (node == 0) {
00474                 WRITE_WARNING("Ignoring unknown node '" + *it_id + "' while joining");
00475             } else {
00476                 cluster.insert(node);
00477             }
00478         }
00479         if (cluster.size() > 1) {
00480             clusters.push_back(cluster);
00481         }
00482     }
00483     joinNodeClusters(clusters, dc, ec, tlc);
00484     return (int)clusters.size();
00485 }
00486 
00487 
00488 unsigned int
00489 NBNodeCont::joinJunctions(SUMOReal maxdist, NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tlc) {
00490     NodeClusters cands;
00491     NodeClusters clusters;
00492     generateNodeClusters(maxdist, cands);
00493     for (NodeClusters::iterator i = cands.begin(); i != cands.end(); ++i) {
00494         const std::set<NBNode*> &candCluster = (*i);
00495         std::set<NBNode*> cluster;
00496         // remove nodes with degree = 2 at fringe of the cluster (at least one edge leads to a non-cluster node)
00497         for (std::set<NBNode*>::const_iterator j = candCluster.begin(); j != candCluster.end(); j++) {
00498             NBNode* n = *j;
00499             if (n->getIncomingEdges().size() == 1 &&
00500                     n->getOutgoingEdges().size() == 1 &&
00501                     (!cluster.count(n->getIncomingEdges()[0]->getFromNode()) ||
00502                      !cluster.count(n->getOutgoingEdges()[0]->getToNode()))) {
00503                 continue;
00504             } else if (myJoinExclusions.count(n->getID()) > 0) {
00505                 continue;
00506             } else {
00507                 cluster.insert(n);
00508             }
00509         }
00510         if (cluster.size() > 1) {
00511             clusters.push_back(cluster);
00512         }
00513     }
00514     joinNodeClusters(clusters, dc, ec, tlc);
00515     return (int)clusters.size();
00516 }
00517 
00518 
00519 void
00520 NBNodeCont::joinNodeClusters(NodeClusters clusters,
00521                              NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tlc) {
00522     for (NodeClusters::iterator i = clusters.begin(); i != clusters.end(); ++i) {
00523         std::set<NBNode*> cluster = *i;
00524         assert(cluster.size() > 1);
00525         Position pos;
00526         bool setTL;
00527         std::string id;
00528         analyzeCluster(cluster, id, pos, setTL);
00529         if (!insert(id, pos)) {
00530             // should not fail
00531             WRITE_WARNING("Could not join junctions " + id);
00532             continue;
00533         }
00534         NBNode* newNode = retrieve(id);
00535         if (setTL) {
00536             NBTrafficLightDefinition* tlDef = new NBOwnTLDef(id, newNode);
00537             if (!tlc.insert(tlDef)) {
00538                 // actually, nothing should fail here
00539                 delete tlDef;
00540                 throw ProcessError("Could not allocate tls '" + id + "'.");
00541             }
00542         }
00543         // collect edges
00544         std::set<NBEdge*> allEdges;
00545         for (std::set<NBNode*>::const_iterator j=cluster.begin(); j!=cluster.end(); ++j) {
00546             const std::vector<NBEdge*> &edges = (*j)->getEdges();
00547             allEdges.insert(edges.begin(), edges.end());
00548         }
00549 
00550         // remap and remove edges which are completely within the new intersection
00551         for(std::set<NBEdge*>::iterator j=allEdges.begin(); j!=allEdges.end();) {
00552             NBEdge *e = (*j);
00553             NBNode *from = e->getFromNode();
00554             NBNode *to = e->getToNode();
00555             if(cluster.count(from) > 0 && cluster.count(to) > 0) {
00556                 for(std::set<NBEdge*>::iterator l=allEdges.begin(); l!=allEdges.end(); ++l) {
00557                     if(e != *l) {
00558                         (*l)->replaceInConnections(e, e->getConnections());
00559                     }
00560                 }
00561                 ec.erase(dc, e);
00562                 allEdges.erase(j++); // erase does not invalidate the other iterators
00563             } else {
00564                 ++j;
00565             }
00566         }
00567 
00568         // remap edges which are incoming / outgoing
00569         for(std::set<NBEdge*>::iterator j=allEdges.begin(); j!=allEdges.end(); ++j) {
00570             NBEdge *e = (*j);
00571             std::vector<NBEdge::Connection> conns = e->getConnections();
00572             PositionVector g = e->getGeometry();
00573             const bool outgoing = cluster.count(e->getFromNode()) > 0;
00574             NBNode *from = outgoing ? newNode : e->getFromNode();
00575             NBNode *to   = outgoing ? e->getToNode() : newNode;
00576             e->reinit(from, to, e->getTypeID(), e->getSpeed(),
00577                 e->getNumLanes(), e->getPriority(), e->getGeometry(),
00578                 e->getWidth(), e->getOffset(), e->getStreetName(), e->getLaneSpreadFunction());
00579             e->setGeometry(g);
00580             for(std::vector<NBEdge::Connection>::iterator k=conns.begin(); k!=conns.end(); ++k) {
00581                 e->addLane2LaneConnection((*k).fromLane, (*k).toEdge, (*k).toLane, NBEdge::L2L_USER, false, (*k).mayDefinitelyPass);
00582             }
00583         }
00584     }
00585 }
00586 
00587 
00588 void
00589 NBNodeCont::analyzeCluster(std::set<NBNode*> cluster, std::string& id, Position& pos, bool& hasTLS) {
00590     id = "cluster";
00591     hasTLS = false;
00592     std::vector<std::string> member_ids;
00593     for (std::set<NBNode*>::const_iterator j = cluster.begin(); j != cluster.end(); j++) {
00594         member_ids.push_back((*j)->getID());
00595         pos.add((*j)->getPosition());
00596         // add a traffic light if any of the cluster members was controlled
00597         if ((*j)->isTLControlled()) {
00598             hasTLS = true;
00599         }
00600     }
00601     pos.mul(1.0 / cluster.size());
00602     // need to sort the member names to make the output deterministic
00603     sort(member_ids.begin(), member_ids.end());
00604     for (std::vector<std::string>::iterator j = member_ids.begin(); j != member_ids.end(); j++) {
00605         id = id + "_" + (*j);
00606     }
00607 }
00608 
00609 
00610 // ----------- (Helper) methods for guessing/computing traffic lights
00611 bool
00612 NBNodeCont::shouldBeTLSControlled(const std::set<NBNode*> &c) const {
00613     unsigned int noIncoming = 0;
00614     unsigned int noOutgoing = 0;
00615     bool tooFast = false;
00616     SUMOReal f = 0;
00617     std::set<NBEdge*> seen;
00618     for (std::set<NBNode*>::const_iterator j = c.begin(); j != c.end(); ++j) {
00619         const EdgeVector& edges = (*j)->getEdges();
00620         for (EdgeVector::const_iterator k = edges.begin(); k != edges.end(); ++k) {
00621             if (c.find((*k)->getFromNode()) != c.end() && c.find((*k)->getToNode()) != c.end()) {
00622                 continue;
00623             }
00624             if ((*j)->hasIncoming(*k)) {
00625                 ++noIncoming;
00626                 f += (SUMOReal)(*k)->getNumLanes() * (*k)->getLaneSpeed(0);
00627             } else {
00628                 ++noOutgoing;
00629             }
00630             if ((*k)->getLaneSpeed(0) * 3.6 > 79) {
00631                 tooFast = true;
00632             }
00633         }
00634     }
00635     return !tooFast && f >= 150. / 3.6 && c.size() != 0;
00636 }
00637 
00638 
00639 void
00640 NBNodeCont::guessTLs(OptionsCont& oc, NBTrafficLightLogicCont& tlc) {
00641     // build list of definitely not tls-controlled junctions
00642     std::vector<NBNode*> ncontrolled;
00643     if (oc.isSet("tls.unset")) {
00644         std::vector<std::string> notTLControlledNodes = oc.getStringVector("tls.unset");
00645         for (std::vector<std::string>::const_iterator i = notTLControlledNodes.begin(); i != notTLControlledNodes.end(); ++i) {
00646             NBNode* n = NBNodeCont::retrieve(*i);
00647             if (n == 0) {
00648                 throw ProcessError(" The node '" + *i + "' to set as not-controlled is not known.");
00649             }
00650             std::set<NBTrafficLightDefinition*> tls = n->getControllingTLS();
00651             for (std::set<NBTrafficLightDefinition*>::const_iterator j = tls.begin(); j != tls.end(); ++j) {
00652                 (*j)->removeNode(n);
00653             }
00654             n->removeTrafficLights();
00655             ncontrolled.push_back(n);
00656         }
00657     }
00658 
00659     // loop#1 checking whether the node shall be tls controlled,
00660     //  because it is assigned to a district
00661     if (oc.exists("tls.taz-nodes") && oc.getBool("tls.taz-nodes")) {
00662         for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
00663             NBNode* cur = (*i).second;
00664             if (cur->isNearDistrict() && find(ncontrolled.begin(), ncontrolled.end(), cur) == ncontrolled.end()) {
00665                 setAsTLControlled(cur, tlc);
00666             }
00667         }
00668     }
00669 
00670     // maybe no tls shall be guessed
00671     if (!oc.getBool("tls.guess")) {
00672         return;
00673     }
00674 
00675     // guess joined tls first, if wished
00676     if (oc.getBool("tls-guess.joining")) {
00677         // get node clusters
00678         SUMOReal MAXDIST = 25;
00679         std::vector<std::set<NBNode*> > cands;
00680         generateNodeClusters(MAXDIST, cands);
00681         // check these candidates (clusters) whether they should be controlled by a tls
00682         for (std::vector<std::set<NBNode*> >::iterator i = cands.begin(); i != cands.end();) {
00683             std::set<NBNode*> &c = (*i);
00684             // regard only junctions which are not yet controlled and are not
00685             //  forbidden to be controlled
00686             for (std::set<NBNode*>::iterator j = c.begin(); j != c.end();) {
00687                 if ((*j)->isTLControlled() || find(ncontrolled.begin(), ncontrolled.end(), *j) != ncontrolled.end()) {
00688                     c.erase(j++);
00689                 } else {
00690                     ++j;
00691                 }
00692             }
00693             // check whether the cluster should be controlled
00694             if (!shouldBeTLSControlled(c)) {
00695                 i = cands.erase(i);
00696             } else {
00697                 ++i;
00698             }
00699         }
00700         // cands now only contain sets of junctions that shall be joined into being tls-controlled
00701         unsigned int index = 0;
00702         for (std::vector<std::set<NBNode*> >::iterator i = cands.begin(); i != cands.end(); ++i) {
00703             std::vector<NBNode*> nodes;
00704             for (std::set<NBNode*>::iterator j = (*i).begin(); j != (*i).end(); j++) {
00705                 nodes.push_back(*j);
00706             }
00707             std::string id = "joinedG_" + toString(index++);
00708             NBTrafficLightDefinition* tlDef = new NBOwnTLDef(id, nodes);
00709             if (!tlc.insert(tlDef)) {
00710                 // actually, nothing should fail here
00711                 WRITE_WARNING("Could not build guessed, joined tls");
00712                 delete tlDef;
00713                 return;
00714             }
00715         }
00716     }
00717 
00718     // guess tls
00719     for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
00720         NBNode* cur = (*i).second;
00721         //  do nothing if already is tl-controlled
00722         if (cur->isTLControlled()) {
00723             continue;
00724         }
00725         // do nothing if in the list of explicit non-controlled junctions
00726         if (find(ncontrolled.begin(), ncontrolled.end(), cur) != ncontrolled.end()) {
00727             continue;
00728         }
00729         std::set<NBNode*> c;
00730         c.insert(cur);
00731         if (!shouldBeTLSControlled(c) || cur->getIncomingEdges().size() < 3) {
00732             continue;
00733         }
00734         setAsTLControlled((*i).second, tlc);
00735     }
00736 }
00737 
00738 
00739 void
00740 NBNodeCont::joinTLS(NBTrafficLightLogicCont& tlc) {
00741     SUMOReal MAXDIST = 25;
00742     std::vector<std::set<NBNode*> > cands;
00743     generateNodeClusters(MAXDIST, cands);
00744     unsigned int index = 0;
00745     for (std::vector<std::set<NBNode*> >::iterator i = cands.begin(); i != cands.end(); ++i) {
00746         std::set<NBNode*> &c = (*i);
00747         for (std::set<NBNode*>::iterator j = c.begin(); j != c.end();) {
00748             if (!(*j)->isTLControlled()) {
00749                 c.erase(j++);
00750             } else {
00751                 ++j;
00752             }
00753         }
00754         if (c.size() < 2) {
00755             continue;
00756         }
00757         for (std::set<NBNode*>::iterator j = c.begin(); j != c.end(); ++j) {
00758             std::set<NBTrafficLightDefinition*> tls = (*j)->getControllingTLS();
00759             (*j)->removeTrafficLights();
00760             for (std::set<NBTrafficLightDefinition*>::iterator k = tls.begin(); k != tls.end(); ++k) {
00761                 tlc.removeFully((*j)->getID());
00762             }
00763         }
00764         std::string id = "joinedS_" + toString(index++);
00765         std::vector<NBNode*> nodes;
00766         for (std::set<NBNode*>::iterator j = c.begin(); j != c.end(); j++) {
00767             nodes.push_back(*j);
00768         }
00769         NBTrafficLightDefinition* tlDef = new NBOwnTLDef(id, nodes);
00770         if (!tlc.insert(tlDef)) {
00771             // actually, nothing should fail here
00772             WRITE_WARNING("Could not build a joined tls.");
00773             delete tlDef;
00774             return;
00775         }
00776     }
00777 }
00778 
00779 
00780 void
00781 NBNodeCont::setAsTLControlled(NBNode* node, NBTrafficLightLogicCont& tlc, std::string id) {
00782     if (id == "") {
00783         id = node->getID();
00784     }
00785     NBTrafficLightDefinition* tlDef = new NBOwnTLDef(id, node);
00786     if (!tlc.insert(tlDef)) {
00787         // actually, nothing should fail here
00788         WRITE_WARNING("Building a tl-logic for node '" + id + "' twice is not possible.");
00789         delete tlDef;
00790         return;
00791     }
00792 }
00793 
00794 
00795 // -----------
00796 void
00797 NBNodeCont::computeLanes2Lanes() {
00798     for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
00799         (*i).second->computeLanes2Lanes();
00800     }
00801 }
00802 
00803 
00804 // computes the "wheel" of incoming and outgoing edges for every node
00805 void
00806 NBNodeCont::computeLogics(const NBEdgeCont& ec, OptionsCont& oc) {
00807     for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
00808         (*i).second->computeLogic(ec, oc);
00809     }
00810 }
00811 
00812 
00813 void
00814 NBNodeCont::sortNodesEdges(bool leftHand) {
00815     for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
00816         (*i).second->sortNodesEdges(leftHand);
00817     }
00818 }
00819 
00820 
00821 void
00822 NBNodeCont::computeNodeTypes(const NBTypeCont& tc) {
00823     for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
00824         (*i).second->computeType(tc);
00825     }
00826 }
00827 
00828 
00829 void
00830 NBNodeCont::computePriorities() {
00831     for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
00832         (*i).second->computePriorities();
00833     }
00834 }
00835 
00836 
00837 void
00838 NBNodeCont::clear() {
00839     for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
00840         delete((*i).second);
00841     }
00842     myNodes.clear();
00843     for (std::set<NBNode*>::iterator i = myExtractedNodes.begin(); i != myExtractedNodes.end(); i++) {
00844         delete(*i);
00845     }
00846     myExtractedNodes.clear();
00847 }
00848 
00849 
00850 std::string
00851 NBNodeCont::getFreeID() {
00852     // !!! not guaranteed to be free
00853     std::string ret = "SUMOGenerated" + toString<int>(size());
00854     assert(retrieve(ret) == 0);
00855     return ret;
00856 }
00857 
00858 
00859 void
00860 NBNodeCont::computeNodeShapes(bool leftHand) {
00861     for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
00862         (*i).second->computeNodeShape(leftHand);
00863     }
00864 }
00865 
00866 
00867 bool
00868 NBNodeCont::mayNeedOnRamp(OptionsCont& oc, NBNode* cur) const {
00869     if (cur->getIncomingEdges().size() == 2 && cur->getOutgoingEdges().size() == 1) {
00870         // may be an on-ramp
00871         NBEdge* pot_highway = cur->getIncomingEdges()[0];
00872         NBEdge* pot_ramp = cur->getIncomingEdges()[1];
00873         NBEdge* cont = cur->getOutgoingEdges()[0];
00874 
00875         // do not build ramps on connectors
00876         if (pot_highway->isMacroscopicConnector() || pot_ramp->isMacroscopicConnector() || cont->isMacroscopicConnector()) {
00877             return false;
00878         }
00879 
00880         // check whether a lane is missing
00881         if (pot_highway->getNumLanes() + pot_ramp->getNumLanes() <= cont->getNumLanes()) {
00882             return false;
00883         }
00884 
00885         // assign highway/ramp properly
00886         if (pot_highway->getSpeed() < pot_ramp->getSpeed()) {
00887             std::swap(pot_highway, pot_ramp);
00888         } else if (pot_highway->getSpeed() == pot_ramp->getSpeed()
00889                    &&
00890                    pot_highway->getNumLanes() < pot_ramp->getNumLanes()) {
00891 
00892             std::swap(pot_highway, pot_ramp);
00893         }
00894 
00895         // check conditions
00896         // is it really a highway?
00897         SUMOReal minHighwaySpeed = oc.getFloat("ramps.min-highway-speed");
00898         if (pot_highway->getSpeed() < minHighwaySpeed || cont->getSpeed() < minHighwaySpeed) {
00899             return false;
00900         }
00901         // is it really a ramp?
00902         SUMOReal maxRampSpeed = oc.getFloat("ramps.max-ramp-speed");
00903         if (maxRampSpeed > 0 && maxRampSpeed < pot_ramp->getSpeed()) {
00904             return false;
00905         }
00906 
00907         // ok, may be
00908         return true;
00909     }
00910     return false;
00911 }
00912 
00913 
00914 bool
00915 NBNodeCont::buildOnRamp(OptionsCont& oc, NBNode* cur,
00916                         NBEdgeCont& ec, NBDistrictCont& dc,
00917                         EdgeVector& incremented) {
00918     NBEdge* pot_highway = cur->getIncomingEdges()[0];
00919     NBEdge* pot_ramp = cur->getIncomingEdges()[1];
00920     NBEdge* cont = cur->getOutgoingEdges()[0];
00921     bool bEdgeDeleted = false;
00922 
00923     // assign highway/ramp properly
00924     if (pot_highway->getSpeed() < pot_ramp->getSpeed()) {
00925         std::swap(pot_highway, pot_ramp);
00926     } else if (pot_highway->getSpeed() == pot_ramp->getSpeed()
00927                &&
00928                pot_highway->getNumLanes() < pot_ramp->getNumLanes()) {
00929 
00930         std::swap(pot_highway, pot_ramp);
00931     }
00932 
00933     // compute the number of lanes to append
00934     int toAdd = (pot_ramp->getNumLanes() + pot_highway->getNumLanes()) - cont->getNumLanes();
00935     if (toAdd <= 0) {
00936         return false;
00937     }
00938 
00939     //
00940     if (cont->getGeometry().length() - POSITION_EPS <= oc.getFloat("ramps.ramp-length")) {
00941         // the edge is shorter than the wished ramp
00942         //  append a lane only
00943         if (find(incremented.begin(), incremented.end(), cont) == incremented.end()) {
00944             cont->incLaneNo(toAdd);
00945             incremented.push_back(cont);
00946             if (!pot_highway->addLane2LaneConnections(0, cont, pot_ramp->getNumLanes(),
00947                     MIN2(cont->getNumLanes() - pot_ramp->getNumLanes(), pot_highway->getNumLanes()), NBEdge::L2L_VALIDATED, true, true)) {
00948                 throw ProcessError("Could not set connection!");
00949             }
00950             if (!pot_ramp->addLane2LaneConnections(0, cont, 0, pot_ramp->getNumLanes(), NBEdge::L2L_VALIDATED, true, true)) {
00951                 throw ProcessError("Could not set connection!");
00952             }
00953             //
00954             cont->invalidateConnections(true);
00955             const EdgeVector& o1 = cont->getToNode()->getOutgoingEdges();
00956             if (o1.size() == 1 && o1[0]->getNumLanes() < cont->getNumLanes()) {
00957                 cont->addLane2LaneConnections(cont->getNumLanes() - o1[0]->getNumLanes(),
00958                                               o1[0], 0, o1[0]->getNumLanes(), NBEdge::L2L_VALIDATED);
00959             }
00960             //
00961             if (cont->getLaneSpreadFunction() == LANESPREAD_CENTER) {
00962                 try {
00963                     PositionVector g = cont->getGeometry();
00964                     g.move2side(SUMO_const_laneWidthAndOffset);
00965                     cont->setGeometry(g);
00966                 } catch (InvalidArgument&) {
00967                     WRITE_WARNING("For edge '" + cont->getID() + "': could not compute shape.");
00968                 }
00969             }
00970         }
00971         PositionVector p = pot_ramp->getGeometry();
00972         p.pop_back();
00973         p.push_back(cont->getFromNode()->getPosition());
00974         pot_ramp->setGeometry(p);
00975     } else {
00976         bEdgeDeleted = true;
00977         // there is enough place to build a ramp; do it
00978         NBNode* rn =
00979             new NBNode(cont->getID() + "-AddedOnRampNode",
00980                        cont->getGeometry().positionAtLengthPosition(
00981                            oc.getFloat("ramps.ramp-length")));
00982         if (!insert(rn)) {
00983             throw ProcessError("Ups - could not build on-ramp for edge '" + pot_highway->getID() + "' (node could not be build)!");
00984         }
00985         std::string name = cont->getID();
00986         bool ok = ec.splitAt(dc, cont, rn,
00987                              cont->getID() + "-AddedOnRampEdge", cont->getID(),
00988                              cont->getNumLanes() + toAdd, cont->getNumLanes());
00989         if (!ok) {
00990             WRITE_ERROR("Ups - could not build on-ramp for edge '" + pot_highway->getID() + "'!");
00991             return true;
00992         } else {
00993             NBEdge* added_ramp = ec.retrieve(name + "-AddedOnRampEdge");
00994             NBEdge* added = ec.retrieve(name);
00995             incremented.push_back(added_ramp);
00996             if (added_ramp->getNumLanes() != added->getNumLanes()) {
00997                 int off = added_ramp->getNumLanes() - added->getNumLanes();
00998                 if (!added_ramp->addLane2LaneConnections(off, added, 0, added->getNumLanes(), NBEdge::L2L_VALIDATED, true)) {
00999                     throw ProcessError("Could not set connection!");
01000                 }
01001                 if (added_ramp->getLaneSpreadFunction() == LANESPREAD_CENTER) {
01002                     try {
01003                         PositionVector g = added_ramp->getGeometry();
01004                         SUMOReal factor = SUMO_const_laneWidthAndOffset * (SUMOReal)(toAdd - 1) + SUMO_const_halfLaneAndOffset * (SUMOReal)(toAdd % 2);
01005                         g.move2side(factor);
01006                         added_ramp->setGeometry(g);
01007                     } catch (InvalidArgument&) {
01008                         WRITE_WARNING("For edge '" + added_ramp->getID() + "': could not compute shape.");
01009                     }
01010                 }
01011             } else {
01012                 if (!added_ramp->addLane2LaneConnections(0, added, 0, added_ramp->getNumLanes(), NBEdge::L2L_VALIDATED, true)) {
01013                     throw ProcessError("Could not set connection!");
01014                 }
01015             }
01016             if (!pot_highway->addLane2LaneConnections(0, added_ramp, pot_ramp->getNumLanes(),
01017                     MIN2(added_ramp->getNumLanes() - pot_ramp->getNumLanes(), pot_highway->getNumLanes()), NBEdge::L2L_VALIDATED, false, true)) {
01018                 throw ProcessError("Could not set connection!");
01019 
01020             }
01021             if (!pot_ramp->addLane2LaneConnections(0, added_ramp, 0, pot_ramp->getNumLanes(), NBEdge::L2L_VALIDATED, true, true)) {
01022                 throw ProcessError("Could not set connection!");
01023             }
01024             PositionVector p = pot_ramp->getGeometry();
01025             p.pop_back();
01026             p.push_back(added_ramp->getFromNode()->getPosition());//added_ramp->getLaneShape(0).at(0));
01027             pot_ramp->setGeometry(p);
01028         }
01029     }
01030     return bEdgeDeleted;
01031 }
01032 
01033 
01034 void
01035 NBNodeCont::buildOffRamp(OptionsCont& oc, NBNode* cur,
01036                          NBEdgeCont& ec, NBDistrictCont& dc,
01037                          EdgeVector& incremented) {
01038     NBEdge* pot_highway = cur->getOutgoingEdges()[0];
01039     NBEdge* pot_ramp = cur->getOutgoingEdges()[1];
01040     NBEdge* prev = cur->getIncomingEdges()[0];
01041     // assign highway/ramp properly
01042     if (pot_highway->getSpeed() < pot_ramp->getSpeed()) {
01043         std::swap(pot_highway, pot_ramp);
01044     } else if (pot_highway->getSpeed() == pot_ramp->getSpeed()
01045                &&
01046                pot_highway->getNumLanes() < pot_ramp->getNumLanes()) {
01047 
01048         std::swap(pot_highway, pot_ramp);
01049     }
01050     // compute the number of lanes to append
01051     int toAdd = (pot_ramp->getNumLanes() + pot_highway->getNumLanes()) - prev->getNumLanes();
01052     if (toAdd <= 0) {
01053         return;
01054     }
01055     // append on-ramp
01056     if (prev->getGeometry().length() - POSITION_EPS <= oc.getFloat("ramps.ramp-length")) {
01057         // the edge is shorter than the wished ramp
01058         //  append a lane only
01059         if (find(incremented.begin(), incremented.end(), prev) == incremented.end()) {
01060             incremented.push_back(prev);
01061             prev->incLaneNo(toAdd);
01062             prev->invalidateConnections(true);
01063             if (!prev->addLane2LaneConnections(pot_ramp->getNumLanes(), pot_highway, 0,
01064                                                MIN2(prev->getNumLanes() - 1, pot_highway->getNumLanes()), NBEdge::L2L_VALIDATED, true)) {
01065 
01066                 throw ProcessError("Could not set connection!");
01067 
01068             }
01069             if (!prev->addLane2LaneConnections(0, pot_ramp, 0, pot_ramp->getNumLanes(), NBEdge::L2L_VALIDATED, false)) {
01070                 throw ProcessError("Could not set connection!");
01071 
01072             }
01073             if (prev->getLaneSpreadFunction() == LANESPREAD_CENTER) {
01074                 try {
01075                     PositionVector g = prev->getGeometry();
01076                     g.move2side(SUMO_const_laneWidthAndOffset);
01077                     prev->setGeometry(g);
01078                 } catch (InvalidArgument&) {
01079                     WRITE_WARNING("For edge '" + prev->getID() + "': could not compute shape.");
01080                 }
01081             }
01082         }
01083         PositionVector p = pot_ramp->getGeometry();
01084         p.pop_front();
01085         p.push_front(prev->getToNode()->getPosition());//added_ramp->getLaneShape(0).at(-1));
01086         pot_ramp->setGeometry(p);
01087     } else {
01088         Position pos =
01089             prev->getGeometry().positionAtLengthPosition(
01090                 prev->getGeometry().length() - oc.getFloat("ramps.ramp-length"));
01091         NBNode* rn = new NBNode(prev->getID() + "-AddedOffRampNode", pos);
01092         if (!insert(rn)) {
01093             throw ProcessError("Ups - could not build off-ramp for edge '" + pot_highway->getID() + "' (node could not be build)!");
01094 
01095         }
01096         std::string name = prev->getID();
01097         bool ok = ec.splitAt(dc, prev, rn,
01098                              prev->getID(), prev->getID() + "-AddedOffRampEdge",
01099                              prev->getNumLanes(), prev->getNumLanes() + toAdd);
01100         if (!ok) {
01101             WRITE_ERROR("Ups - could not build on-ramp for edge '" + pot_highway->getID() + "'!");
01102             return;
01103         } else {
01104             NBEdge* added_ramp = ec.retrieve(name + "-AddedOffRampEdge");
01105             NBEdge* added = ec.retrieve(name);
01106             if (added_ramp->getNumLanes() != added->getNumLanes()) {
01107                 incremented.push_back(added_ramp);
01108                 int off = added_ramp->getNumLanes() - added->getNumLanes();
01109                 if (!added->addLane2LaneConnections(0, added_ramp, off, added->getNumLanes(), NBEdge::L2L_VALIDATED, true)) {
01110                     throw ProcessError("Could not set connection!");
01111 
01112                 }
01113                 if (added_ramp->getLaneSpreadFunction() == LANESPREAD_CENTER) {
01114                     try {
01115                         PositionVector g = added_ramp->getGeometry();
01116                         SUMOReal factor = SUMO_const_laneWidthAndOffset * (SUMOReal)(toAdd - 1) + SUMO_const_halfLaneAndOffset * (SUMOReal)(toAdd % 2);
01117                         g.move2side(factor);
01118                         added_ramp->setGeometry(g);
01119                     } catch (InvalidArgument&) {
01120                         WRITE_WARNING("For edge '" + added_ramp->getID() + "': could not compute shape.");
01121                     }
01122                 }
01123             } else {
01124                 if (!added->addLane2LaneConnections(0, added_ramp, 0, added_ramp->getNumLanes(), NBEdge::L2L_VALIDATED, true)) {
01125                     throw ProcessError("Could not set connection!");
01126                 }
01127             }
01128             if (!added_ramp->addLane2LaneConnections(pot_ramp->getNumLanes(), pot_highway, 0,
01129                     MIN2(added_ramp->getNumLanes() - pot_ramp->getNumLanes(), pot_highway->getNumLanes()), NBEdge::L2L_VALIDATED, true)) {
01130                 throw ProcessError("Could not set connection!");
01131             }
01132             if (!added_ramp->addLane2LaneConnections(0, pot_ramp, 0, pot_ramp->getNumLanes(), NBEdge::L2L_VALIDATED, false)) {
01133                 throw ProcessError("Could not set connection!");
01134 
01135             }
01136             PositionVector p = pot_ramp->getGeometry();
01137             p.pop_front();
01138             p.push_front(added_ramp->getToNode()->getPosition());//added_ramp->getLaneShape(0).at(-1));
01139             pot_ramp->setGeometry(p);
01140         }
01141     }
01142 }
01143 
01144 
01145 bool
01146 NBNodeCont::mayNeedOffRamp(OptionsCont& oc, NBNode* cur) const {
01147     if (cur->getIncomingEdges().size() == 1 && cur->getOutgoingEdges().size() == 2) {
01148         // may be an off-ramp
01149         NBEdge* pot_highway = cur->getOutgoingEdges()[0];
01150         NBEdge* pot_ramp = cur->getOutgoingEdges()[1];
01151         NBEdge* prev = cur->getIncomingEdges()[0];
01152 
01153         // do not build ramps on connectors
01154         if (pot_highway->isMacroscopicConnector() || pot_ramp->isMacroscopicConnector() || prev->isMacroscopicConnector()) {
01155             return false;
01156         }
01157 
01158         // check whether a lane is missing
01159         if (pot_highway->getNumLanes() + pot_ramp->getNumLanes() <= prev->getNumLanes()) {
01160             return false;
01161         }
01162 
01163         // assign highway/ramp properly
01164         if (pot_highway->getSpeed() < pot_ramp->getSpeed()) {
01165             std::swap(pot_highway, pot_ramp);
01166         } else if (pot_highway->getSpeed() == pot_ramp->getSpeed()
01167                    &&
01168                    pot_highway->getNumLanes() < pot_ramp->getNumLanes()) {
01169 
01170             std::swap(pot_highway, pot_ramp);
01171         }
01172 
01173         // check conditions
01174         // is it really a highway?
01175         SUMOReal minHighwaySpeed = oc.getFloat("ramps.min-highway-speed");
01176         if (pot_highway->getSpeed() < minHighwaySpeed || prev->getSpeed() < minHighwaySpeed) {
01177             return false;
01178         }
01179         // is it really a ramp?
01180         SUMOReal maxRampSpeed = oc.getFloat("ramps.max-ramp-speed");
01181         if (maxRampSpeed > 0 && maxRampSpeed < pot_ramp->getSpeed()) {
01182             return false;
01183         }
01184 
01185         return true;
01186     }
01187     return false;
01188 }
01189 
01190 
01191 void
01192 NBNodeCont::checkHighwayRampOrder(NBEdge *&pot_highway, NBEdge *&pot_ramp) {
01193     if (pot_highway->getSpeed() < pot_ramp->getSpeed()) {
01194         std::swap(pot_highway, pot_ramp);
01195     } else if (pot_highway->getSpeed() == pot_ramp->getSpeed()
01196                &&
01197                pot_highway->getNumLanes() < pot_ramp->getNumLanes()) {
01198 
01199         std::swap(pot_highway, pot_ramp);
01200     }
01201 }
01202 
01203 
01204 void
01205 NBNodeCont::guessRamps(OptionsCont& oc, NBEdgeCont& ec,
01206                        NBDistrictCont& dc) {
01207     EdgeVector incremented;
01208     bool bEdgeDeleted = false;
01209     // check whether on-off ramps shall be guessed
01210     if (oc.getBool("ramps.guess")) {
01211         for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
01212             NBNode* cur = (*i).second;
01213             if (mayNeedOnRamp(oc, cur)) {
01214                 buildOnRamp(oc, cur, ec, dc, incremented);
01215             }
01216             if (mayNeedOffRamp(oc, cur)) {
01217                 buildOffRamp(oc, cur, ec, dc, incremented);
01218             }
01219         }
01220     }
01221     // check whether on-off ramps shall be guessed
01222     if (oc.isSet("ramps.set")) {
01223         std::vector<std::string> edges = oc.getStringVector("ramps.set");
01224         for (std::vector<std::string>::iterator i = edges.begin(); i != edges.end(); ++i) {
01225             NBEdge* e = ec.retrieve(*i);
01226             if (e == 0) {
01227                 WRITE_WARNING("Can not build on ramp on edge '" + *i + "' - the edge is not known.");
01228                 continue;
01229             }
01230             NBNode* from = e->getFromNode();
01231             if (from->getIncomingEdges().size() == 2 && from->getOutgoingEdges().size() == 1) {
01232                 bEdgeDeleted = buildOnRamp(oc, from, ec, dc, incremented);
01233             }
01234             // load edge again to check offramps
01235             e = ec.retrieve(*i);
01236             if (e == 0) {
01237                 WRITE_WARNING("Can not build off ramp on edge '" + *i + "' - the edge is not known.");
01238                 continue;
01239             }
01240             NBNode* to = e->getToNode();
01241             if (to->getIncomingEdges().size() == 1 && to->getOutgoingEdges().size() == 2) {
01242                 buildOffRamp(oc, to, ec, dc, incremented);
01243             }
01244         }
01245     }
01246 }
01247 
01248 
01249 void
01250 NBNodeCont::printBuiltNodesStatistics() const {
01251     int numUnregulatedJunctions = 0;
01252     int numDeadEndJunctions = 0;
01253     int numPriorityJunctions = 0;
01254     int numRightBeforeLeftJunctions = 0;
01255     for (NodeCont::const_iterator i = myNodes.begin(); i != myNodes.end(); i++) {
01256         switch ((*i).second->getType()) {
01257             case NODETYPE_NOJUNCTION:
01258                 ++numUnregulatedJunctions;
01259                 break;
01260             case NODETYPE_DEAD_END:
01261                 ++numDeadEndJunctions;
01262                 break;
01263             case NODETYPE_PRIORITY_JUNCTION:
01264             case NODETYPE_TRAFFIC_LIGHT:
01265                 ++numPriorityJunctions;
01266                 break;
01267             case NODETYPE_RIGHT_BEFORE_LEFT:
01268                 ++numRightBeforeLeftJunctions;
01269                 break;
01270             case NODETYPE_DISTRICT:
01271                 ++numRightBeforeLeftJunctions;
01272                 break;
01273             case NODETYPE_UNKNOWN:
01274                 break;
01275             default:
01276                 break;
01277         }
01278     }
01279     WRITE_MESSAGE(" Node type statistics:");
01280     WRITE_MESSAGE("  Unregulated junctions       : " + toString(numUnregulatedJunctions));
01281     if (numDeadEndJunctions > 0) {
01282         WRITE_MESSAGE("  Dead-end junctions          : " + toString(numDeadEndJunctions));
01283     }
01284     WRITE_MESSAGE("  Priority junctions          : " + toString(numPriorityJunctions));
01285     WRITE_MESSAGE("  Right-before-left junctions : " + toString(numRightBeforeLeftJunctions));
01286 }
01287 
01288 
01289 std::vector<std::string>
01290 NBNodeCont::getAllNames() const {
01291     std::vector<std::string> ret;
01292     for (NodeCont::const_iterator i = myNodes.begin(); i != myNodes.end(); ++i) {
01293         ret.push_back((*i).first);
01294     }
01295     return ret;
01296 }
01297 
01298 
01299 
01300 /****************************************************************************/
01301 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines