00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
00060
00061 NBNodeCont::NBNodeCont() throw()
00062 : myInternalID(1) {}
00063
00064
00065 NBNodeCont::~NBNodeCont() throw() {
00066 clear();
00067 }
00068
00069
00070
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
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
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
00252
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
00263 if (!oc.getBool("guess-tls")) {
00264 return;
00265 }
00266
00267
00268 if (oc.getBool("tls-guess.joining")) {
00269
00270 SUMOReal MAXDIST = 25;
00271 std::vector<std::set<NBNode*> > cands;
00272 generateNodeClusters(MAXDIST, cands);
00273
00274 for (std::vector<std::set<NBNode*> >::iterator i=cands.begin(); i!=cands.end();) {
00275 std::set<NBNode*> &c = (*i);
00276
00277
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
00286 if (!shouldBeTLSControlled(c)) {
00287 i = cands.erase(i);
00288 } else {
00289 ++i;
00290 }
00291 }
00292
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
00303 WRITE_WARNING("Could not build guessed, joined tls");
00304 delete tlDef;
00305 return;
00306 }
00307 }
00308 }
00309
00310
00311 for (NodeCont::iterator i=myNodes.begin(); i!=myNodes.end(); i++) {
00312 NBNode *cur = (*i).second;
00313
00314 if (cur->isTLControlled()) {
00315 continue;
00316 }
00317
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
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
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
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
00472
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
00486
00487 std::map<NBNode*, EdgeVector>::iterator k;
00488 for (k=connectionCount.begin(); k!=connectionCount.end(); k++) {
00489
00490 if ((*k).second.size()<2) {
00491 continue;
00492 }
00493
00494
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
00500 if (geometryCombinations.size()==0) {
00501 EdgeVector tmp;
00502 tmp.push_back(*l);
00503 geometryCombinations.push_back(tmp);
00504 continue;
00505 }
00506
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
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
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
00546
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
00555 continue;
00556 }
00557 const EdgeVector &incomingEdges = from->getIncomingEdges();
00558 if (incomingEdges.size() > 1) {
00559
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
00566
00567 continue;
00568 }
00569 }
00570
00571
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
00587 && (*itOfOutgoings)->getToNode() != to
00588 ) {
00589 e = *itOfOutgoings;
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);
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
00619 erase(fromNode);
00620 }
00621 if (toNode->getIncomingEdges().size() == 0
00622 && toNode->getOutgoingEdges().size() == 0) {
00623
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
00675 if (current->getOutgoingEdges().size()==0
00676 &&
00677 current->getIncomingEdges().size()==0) {
00678
00679
00680 remove = true;
00681 }
00682
00683 if (removeGeometryNodes) {
00684 if ((current->getOutgoingEdges().size()==1 && current->getIncomingEdges().size()==1)
00685 ||
00686 (current->getOutgoingEdges().size()==2 && current->getIncomingEdges().size()==2)) {
00687
00688
00689 remove = current->checkIsRemovable();
00690 if (remove) {
00691 toJoin = current->getEdgesToJoin();
00692 }
00693 }
00694 }
00695
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
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
00725 NBEdge *pot_highway = cur->getIncomingEdges()[0];
00726 NBEdge *pot_ramp = cur->getIncomingEdges()[1];
00727 NBEdge *cont = cur->getOutgoingEdges()[0];
00728
00729
00730 if (pot_highway->isMacroscopicConnector()||pot_ramp->isMacroscopicConnector()||cont->isMacroscopicConnector()) {
00731 return false;
00732 }
00733
00734
00735 if (pot_highway->getNoLanes()+pot_ramp->getNoLanes()<=cont->getNoLanes()) {
00736 return false;
00737 }
00738
00739
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
00750
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
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
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
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
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
00798
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
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());
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
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
00907 int toAdd = (pot_ramp->getNoLanes() + pot_highway->getNoLanes()) - prev->getNoLanes();
00908 if (toAdd<=0) {
00909 return;
00910 }
00911
00912 if (prev->getGeometry().length()-POSITION_EPS<=oc.getFloat("ramp-guess.ramp-length")) {
00913
00914
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());
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());
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
01005 NBEdge *pot_highway = cur->getOutgoingEdges()[0];
01006 NBEdge *pot_ramp = cur->getOutgoingEdges()[1];
01007 NBEdge *prev = cur->getIncomingEdges()[0];
01008
01009
01010 if (pot_highway->isMacroscopicConnector()||pot_ramp->isMacroscopicConnector()||prev->isMacroscopicConnector()) {
01011 return false;
01012 }
01013
01014
01015 if (pot_highway->getNoLanes()+pot_ramp->getNoLanes()<=prev->getNoLanes()) {
01016 return false;
01017 }
01018
01019
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
01030
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
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
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
01101
01102
01103
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
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
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
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