NBNodeCont.cpp

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

Generated on Wed May 5 00:06:33 2010 for Sumo - Simulation of Urban MObility by  doxygen 1.5.6