SUMO - Simulation of Urban MObility

NBEdgeCont.cpp

Go to the documentation of this file.
00001 /****************************************************************************/
00010 // Storage for edges, including some functionality operating on multiple edges
00011 /****************************************************************************/
00012 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00013 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
00014 /****************************************************************************/
00015 //
00016 //   This file is part of SUMO.
00017 //   SUMO is free software: you can redistribute it and/or modify
00018 //   it under the terms of the GNU General Public License as published by
00019 //   the Free Software Foundation, either version 3 of the License, or
00020 //   (at your option) any later version.
00021 //
00022 /****************************************************************************/
00023 
00024 
00025 // ===========================================================================
00026 // included modules
00027 // ===========================================================================
00028 #ifdef _MSC_VER
00029 #include <windows_config.h>
00030 #else
00031 #include <config.h>
00032 #endif
00033 
00034 #include <vector>
00035 #include <string>
00036 #include <cassert>
00037 #include <algorithm>
00038 #include <iostream>
00039 #include <fstream>
00040 #include <iomanip>
00041 #include <utils/geom/GeomHelper.h>
00042 #include <utils/common/MsgHandler.h>
00043 #include <utils/common/ToString.h>
00044 #include <utils/common/TplConvert.h>
00045 #include <utils/options/OptionsCont.h>
00046 #include "NBNetBuilder.h"
00047 #include "NBEdgeCont.h"
00048 #include "NBNodeCont.h"
00049 #include "NBHelpers.h"
00050 #include "NBCont.h"
00051 #include "NBTrafficLightLogicCont.h"
00052 #include "NBDistrictCont.h"
00053 #include <cmath>
00054 #include "NBTypeCont.h"
00055 #include <iostream>
00056 #include <utils/common/StringTokenizer.h>
00057 #include <utils/common/UtilExceptions.h>
00058 #include <utils/iodevices/OutputDevice.h>
00059 
00060 #ifdef CHECK_MEMORY_LEAKS
00061 #include <foreign/nvwa/debug_new.h>
00062 #endif // CHECK_MEMORY_LEAKS
00063 
00064 
00065 // ===========================================================================
00066 // method definitions
00067 // ===========================================================================
00068 NBEdgeCont::NBEdgeCont(NBTypeCont& tc)
00069     : myEdgesSplit(0), myTypeCont(tc) {}
00070 
00071 
00072 NBEdgeCont::~NBEdgeCont() {
00073     clear();
00074 }
00075 
00076 
00077 void
00078 NBEdgeCont::applyOptions(OptionsCont& oc) {
00079     myAmLeftHanded = oc.getBool("lefthand");
00080     // set edges dismiss/accept options
00081     myEdgesMinSpeed = oc.isSet("keep-edges.min-speed") ? oc.getFloat("keep-edges.min-speed") : -1;
00082     myRemoveEdgesAfterJoining = oc.exists("keep-edges.postload") && oc.getBool("keep-edges.postload");
00083     if (oc.isSet("keep-edges.explicit")) {
00084         const std::vector<std::string> edges = oc.getStringVector("keep-edges.explicit");
00085         myEdges2Keep.insert(edges.begin(), edges.end());
00086     }
00087     if (oc.isSet("remove-edges.explicit")) {
00088         const std::vector<std::string> edges = oc.getStringVector("remove-edges.explicit");
00089         myEdges2Remove.insert(edges.begin(), edges.end());
00090     }
00091     if (oc.exists("keep-edges.by-vclass") && oc.isSet("keep-edges.by-vclass")) {
00092         const std::vector<std::string> classes = oc.getStringVector("keep-edges.by-vclass");
00093         for (std::vector<std::string>::const_iterator i = classes.begin(); i != classes.end(); ++i) {
00094             SUMOVehicleClass svc = getVehicleClassID(*i);
00095             myVehicleClasses2Keep.insert(svc);
00096         }
00097     }
00098     if (oc.exists("remove-edges.by-vclass") && oc.isSet("remove-edges.by-vclass")) {
00099         const std::vector<std::string> classes = oc.getStringVector("remove-edges.by-vclass");
00100         for (std::vector<std::string>::const_iterator i = classes.begin(); i != classes.end(); ++i) {
00101             SUMOVehicleClass svc = getVehicleClassID(*i);
00102             myVehicleClasses2Remove.insert(svc);
00103         }
00104     }
00105     if (oc.exists("keep-edges.by-type") && oc.isSet("keep-edges.by-type")) {
00106         const std::vector<std::string> types = oc.getStringVector("keep-edges.by-type");
00107         myTypes2Keep.insert(types.begin(), types.end());
00108     }
00109     if (oc.exists("remove-edges.by-type") && oc.isSet("remove-edges.by-type")) {
00110         const std::vector<std::string> types = oc.getStringVector("remove-edges.by-type");
00111         myTypes2Remove.insert(types.begin(), types.end());
00112     }
00113 
00114     if (oc.isSet("keep-edges.in-boundary")) {
00115         std::vector<std::string> polyS = oc.getStringVector("keep-edges.in-boundary");
00116         // !!! throw something if length<4 || length%2!=0?
00117         std::vector<SUMOReal> poly;
00118         for (std::vector<std::string>::iterator i = polyS.begin(); i != polyS.end(); ++i) {
00119             poly.push_back(TplConvert<char>::_2SUMOReal((*i).c_str())); // !!! may throw something anyhow...
00120         }
00121         if (poly.size() == 4) {
00122             // prunning boundary (box)
00123             myPrunningBoundary.push_back(Position(poly[0], poly[1]));
00124             myPrunningBoundary.push_back(Position(poly[2], poly[1]));
00125             myPrunningBoundary.push_back(Position(poly[2], poly[3]));
00126             myPrunningBoundary.push_back(Position(poly[0], poly[3]));
00127         } else {
00128             for (std::vector<SUMOReal>::iterator j = poly.begin(); j != poly.end();) {
00129                 SUMOReal x = *j++;
00130                 SUMOReal y = *j++;
00131                 myPrunningBoundary.push_back(Position(x, y));
00132             }
00133         }
00134     }
00135 }
00136 
00137 
00138 void
00139 NBEdgeCont::clear() {
00140     for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
00141         delete((*i).second);
00142     }
00143     myEdges.clear();
00144     for (EdgeCont::iterator i = myExtractedEdges.begin(); i != myExtractedEdges.end(); i++) {
00145         delete((*i).second);
00146     }
00147     myExtractedEdges.clear();
00148 }
00149 
00150 
00151 
00152 // ----- edge access methods
00153 bool
00154 NBEdgeCont::insert(NBEdge* edge, bool ignorePrunning) {
00155     if (myAmLeftHanded) {
00156         edge->setLeftHanded();
00157     }
00158     if (myEdges.count(edge->getID())) {
00159         return false;
00160     }
00161     if (!ignorePrunning && ignoreFilterMatch(edge)) {
00162         edge->getFromNode()->removeEdge(edge);
00163         edge->getToNode()->removeEdge(edge);
00164         myIgnoredEdges.insert(edge->getID());
00165         delete edge;
00166     } else {
00167         OptionsCont& oc = OptionsCont::getOptions();
00168         if (oc.exists("dismiss-vclasses") && oc.getBool("dismiss-vclasses")) {
00169             edge->dismissVehicleClassInformation();
00170         }
00171         myEdges[edge->getID()] = edge;
00172     }
00173     return true;
00174 }
00175 
00176 
00177 bool 
00178 NBEdgeCont::ignoreFilterMatch(NBEdge *edge) {
00179     // remove edges which allow a speed below a set one (set using "keep-edges.min-speed")
00180     if (edge->getSpeed() < myEdgesMinSpeed) {
00181         return true;
00182     }
00183     // check whether the edge is a named edge to keep
00184     if (!myRemoveEdgesAfterJoining && myEdges2Keep.size() != 0) {
00185         if (find(myEdges2Keep.begin(), myEdges2Keep.end(), edge->getID()) == myEdges2Keep.end()) {
00186             return true;
00187         }
00188     }
00189     // check whether the edge is a named edge to remove
00190     if (myEdges2Remove.size() != 0) {
00191         if (find(myEdges2Remove.begin(), myEdges2Remove.end(), edge->getID()) != myEdges2Remove.end()) {
00192             return true;
00193         }
00194     }
00195     // check whether the edge shall be removed because it does not allow any of the wished classes
00196     if (myVehicleClasses2Keep.size() != 0) {
00197         SUMOVehicleClasses allowed = edge->getAllowedVehicleClasses();
00198         // @todo also check disallowed
00199         if (allowed.size() > 0) {
00200             int matching = 0;
00201             for (SUMOVehicleClasses::const_iterator i = myVehicleClasses2Keep.begin(); i != myVehicleClasses2Keep.end(); ++i) {
00202                 if (allowed.count(*i)) {
00203                     allowed.erase(*i);
00204                     matching++;
00205                 }
00206             }
00207             if (matching == 0) {
00208                 return true;
00209             }
00210         }
00211     }
00212     // check whether the edge shall be removed due to allowing unwished classes only
00213     if (myVehicleClasses2Remove.size() != 0) {
00214         int matching = 0;
00215         SUMOVehicleClasses allowed = edge->getAllowedVehicleClasses();
00216         for (SUMOVehicleClasses::const_iterator i = myVehicleClasses2Remove.begin(); i != myVehicleClasses2Remove.end(); ++i) {
00217             if (allowed.count(*i)) {
00218                 allowed.erase(*i);
00219                 matching++;
00220             }
00221         }
00222         // remove the edge if all allowed
00223         if (allowed.size() == 0 && matching != 0) {
00224             return true;
00225         }
00226     }
00227     // check whether the edge shall be removed because it does not have one of the requested types
00228     if (myTypes2Keep.size() != 0) {
00229         if (myTypes2Keep.count(edge->getTypeID()) == 0) {
00230             return true;
00231         }
00232     }
00233     // check whether the edge shall be removed because it has one of the forbidden types
00234     if (myTypes2Remove.size() != 0) {
00235         if (myTypes2Remove.count(edge->getTypeID()) > 0) {
00236             return true;
00237         }
00238     }
00239     // check whether the edge is within the prunning boundary
00240     if (myPrunningBoundary.size() != 0) {
00241         if (!(edge->getGeometry().getBoxBoundary().grow((SUMOReal) POSITION_EPS).overlapsWith(myPrunningBoundary))) {
00242             return true;
00243         }
00244     }
00245     if (myTypeCont.knows(edge->getTypeID()) && myTypeCont.getShallBeDiscarded(edge->getTypeID())) {
00246         return true;
00247     }
00248     return false;
00249 }
00250 
00251 
00252 NBEdge*
00253 NBEdgeCont::retrieve(const std::string& id, bool retrieveExtracted) const {
00254     EdgeCont::const_iterator i = myEdges.find(id);
00255     if (i == myEdges.end()) {
00256         if (retrieveExtracted) {
00257             i = myExtractedEdges.find(id);
00258             if (i == myExtractedEdges.end()) {
00259                 return 0;
00260             }
00261         } else {
00262             return 0;
00263         }
00264     }
00265     return (*i).second;
00266 }
00267 
00268 
00269 NBEdge*
00270 NBEdgeCont::retrievePossiblySplitted(const std::string& id,
00271                                      const std::string& hint,
00272                                      bool incoming) const {
00273     // try to retrieve using the given name (iterative)
00274     NBEdge* edge = retrieve(id);
00275     if (edge != 0) {
00276         return edge;
00277     }
00278     // now, we did not find it; we have to look over all possibilities
00279     EdgeVector hints;
00280     // check whether at least the hint was not splitted
00281     NBEdge* hintedge = retrieve(hint);
00282     if (hintedge == 0) {
00283         hints = getGeneratedFrom(hint);
00284     } else {
00285         hints.push_back(hintedge);
00286     }
00287     EdgeVector candidates = getGeneratedFrom(id);
00288     for (EdgeVector::iterator i = hints.begin(); i != hints.end(); i++) {
00289         NBEdge* hintedge = (*i);
00290         for (EdgeVector::iterator j = candidates.begin(); j != candidates.end(); j++) {
00291             NBEdge* poss_searched = (*j);
00292             NBNode* node = incoming
00293                            ? poss_searched->myTo : poss_searched->myFrom;
00294             const EdgeVector& cont = incoming
00295                                      ? node->getOutgoingEdges() : node->getIncomingEdges();
00296             if (find(cont.begin(), cont.end(), hintedge) != cont.end()) {
00297                 return poss_searched;
00298             }
00299         }
00300     }
00301     return 0;
00302 }
00303 
00304 
00305 NBEdge*
00306 NBEdgeCont::retrievePossiblySplitted(const std::string& id, SUMOReal pos) const {
00307     // check whether the edge was not split, yet
00308     NBEdge* edge = retrieve(id);
00309     if (edge != 0) {
00310         return edge;
00311     }
00312     size_t maxLength = 0;
00313     std::string tid = id + "[";
00314     for (EdgeCont::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
00315         if ((*i).first.find(tid) == 0) {
00316             maxLength = MAX2(maxLength, (*i).first.length());
00317         }
00318     }
00319     // find the part of the edge which matches the position
00320     SUMOReal seen = 0;
00321     std::vector<std::string> names;
00322     names.push_back(id + "[1]");
00323     names.push_back(id + "[0]");
00324     while (names.size() > 0) {
00325         // retrieve the first subelement (to follow)
00326         std::string cid = names.back();
00327         names.pop_back();
00328         edge = retrieve(cid);
00329         // The edge was splitted; check its subparts within the
00330         //  next step
00331         if (edge == 0) {
00332             if (cid.length() + 3 < maxLength) {
00333                 names.push_back(cid + "[1]");
00334                 names.push_back(cid + "[0]");
00335             }
00336         }
00337         // an edge with the name was found,
00338         //  check whether the position lies within it
00339         else {
00340             seen += edge->getLength();
00341             if (seen >= pos) {
00342                 return edge;
00343             }
00344         }
00345     }
00346     return 0;
00347 }
00348 
00349 
00350 void
00351 NBEdgeCont::erase(NBDistrictCont& dc, NBEdge* edge) {
00352     extract(dc, edge);
00353     delete edge;
00354 }
00355 
00356 
00357 void
00358 NBEdgeCont::extract(NBDistrictCont& dc, NBEdge* edge, bool remember) {
00359     if (remember) {
00360         myExtractedEdges[edge->getID()] = edge;
00361     }
00362     myEdges.erase(edge->getID());
00363     edge->myFrom->removeEdge(edge);
00364     edge->myTo->removeEdge(edge);
00365     dc.removeFromSinksAndSources(edge);
00366 }
00367 
00368 
00369 
00370 // ----- explicit edge manipulation methods
00371 bool
00372 NBEdgeCont::splitAt(NBDistrictCont& dc, NBEdge* edge, NBNode* node) {
00373     return splitAt(dc, edge, node, edge->getID() + "[0]", edge->getID() + "[1]",
00374                    (unsigned int) edge->myLanes.size(), (unsigned int) edge->myLanes.size());
00375 }
00376 
00377 
00378 bool
00379 NBEdgeCont::splitAt(NBDistrictCont& dc, NBEdge* edge, NBNode* node,
00380                     const std::string& firstEdgeName,
00381                     const std::string& secondEdgeName,
00382                     unsigned int noLanesFirstEdge, unsigned int noLanesSecondEdge) {
00383     SUMOReal pos;
00384     pos = edge->getGeometry().nearest_position_on_line_to_point(node->getPosition());
00385     if (pos <= 0) {
00386         pos = GeomHelper::nearest_position_on_line_to_point2D(
00387                   edge->myFrom->getPosition(), edge->myTo->getPosition(),
00388                   node->getPosition());
00389     }
00390     if (pos <= 0 || pos + POSITION_EPS > edge->getGeometry().length()) {
00391         return false;
00392     }
00393     return splitAt(dc, edge, pos, node, firstEdgeName, secondEdgeName,
00394                    noLanesFirstEdge, noLanesSecondEdge);
00395 }
00396 
00397 
00398 bool
00399 NBEdgeCont::splitAt(NBDistrictCont& dc,
00400                     NBEdge* edge, SUMOReal pos, NBNode* node,
00401                     const std::string& firstEdgeName,
00402                     const std::string& secondEdgeName,
00403                     unsigned int noLanesFirstEdge, unsigned int noLanesSecondEdge) {
00404     // build the new edges' geometries
00405     std::pair<PositionVector, PositionVector> geoms =
00406         edge->getGeometry().splitAt(pos);
00407     if (geoms.first[-1] != node->getPosition()) {
00408         geoms.first.pop_back();
00409         geoms.first.push_back(node->getPosition());
00410     }
00411 
00412     if (geoms.second[0] != node->getPosition()) {
00413         geoms.second.pop_front();
00414         geoms.second.push_front(node->getPosition());
00415     }
00416     // build and insert the edges
00417     NBEdge* one = new NBEdge(firstEdgeName,
00418                              edge->myFrom, node, edge->myType, edge->mySpeed, noLanesFirstEdge,
00419                              edge->getPriority(), edge->myWidth, 0, geoms.first,
00420                              edge->getStreetName(), edge->myLaneSpreadFunction, true);
00421     for (unsigned int i = 0; i < noLanesFirstEdge && i < edge->getNumLanes(); i++) {
00422         one->setSpeed(i, edge->getLaneSpeed(i));
00423     }
00424     NBEdge* two = new NBEdge(secondEdgeName,
00425                              node, edge->myTo, edge->myType, edge->mySpeed, noLanesSecondEdge,
00426                              edge->getPriority(), edge->myWidth, edge->myOffset, geoms.second,
00427                              edge->getStreetName(), edge->myLaneSpreadFunction, true);
00428     for (unsigned int i = 0; i < noLanesSecondEdge && i < edge->getNumLanes(); i++) {
00429         two->setSpeed(i, edge->getLaneSpeed(i));
00430     }
00431     two->copyConnectionsFrom(edge);
00432     // replace information about this edge within the nodes
00433     edge->myFrom->replaceOutgoing(edge, one, 0);
00434     edge->myTo->replaceIncoming(edge, two, 0);
00435     // the edge is now occuring twice in both nodes...
00436     //  clean up
00437     edge->myFrom->removeDoubleEdges();
00438     edge->myTo->removeDoubleEdges();
00439     // add connections from the first to the second edge
00440     // check special case:
00441     //  one in, one out, the outgoing has one lane more
00442     if (noLanesFirstEdge == noLanesSecondEdge - 1) {
00443         for (unsigned int i = 0; i < one->getNumLanes(); i++) {
00444             if (!one->addLane2LaneConnection(i, two, i + 1, NBEdge::L2L_COMPUTED)) { // !!! Bresenham, here!!!
00445                 throw ProcessError("Could not set connection!");
00446             }
00447         }
00448         one->addLane2LaneConnection(0, two, 0, NBEdge::L2L_COMPUTED);
00449     } else {
00450         for (unsigned int i = 0; i < one->getNumLanes() && i < two->getNumLanes(); i++) {
00451             if (!one->addLane2LaneConnection(i, two, i, NBEdge::L2L_COMPUTED)) {// !!! Bresenham, here!!!
00452                 throw ProcessError("Could not set connection!");
00453             }
00454         }
00455     }
00456     if (myRemoveEdgesAfterJoining) {
00457         if (find(myEdges2Keep.begin(), myEdges2Keep.end(), edge->getID()) != myEdges2Keep.end()) {
00458             myEdges2Keep.insert(one->getID());
00459             myEdges2Keep.insert(two->getID());
00460         }
00461         if (find(myEdges2Remove.begin(), myEdges2Remove.end(), edge->getID()) != myEdges2Remove.end()) {
00462             myEdges2Remove.insert(one->getID());
00463             myEdges2Remove.insert(two->getID());
00464         }
00465     }
00466     // erase the splitted edge
00467     erase(dc, edge);
00468     insert(one, true);
00469     insert(two, true);
00470     myEdgesSplit++;
00471     return true;
00472 }
00473 
00474 
00475 
00476 // ----- container access methods
00477 std::vector<std::string>
00478 NBEdgeCont::getAllNames() const {
00479     std::vector<std::string> ret;
00480     for (EdgeCont::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
00481         ret.push_back((*i).first);
00482     }
00483     return ret;
00484 }
00485 
00486 
00487 // ----- Adapting the input
00488 void
00489 NBEdgeCont::removeUnwishedEdges(NBDistrictCont& dc) {
00490     EdgeVector toRemove;
00491     for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
00492         NBEdge* edge = (*i).second;
00493         if (!myEdges2Keep.count(edge->getID())) {
00494             edge->getFromNode()->removeEdge(edge);
00495             edge->getToNode()->removeEdge(edge);
00496             toRemove.push_back(edge);
00497         }
00498     }
00499     for (EdgeVector::iterator j = toRemove.begin(); j != toRemove.end(); ++j) {
00500         erase(dc, *j);
00501     }
00502 }
00503 
00504 
00505 void
00506 NBEdgeCont::splitGeometry(NBNodeCont& nc) {
00507     for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
00508         if ((*i).second->getGeometry().size() < 3) {
00509             continue;
00510         }
00511         (*i).second->splitGeometry(*this, nc);
00512     }
00513 }
00514 
00515 
00516 // ----- processing methods
00517 void
00518 NBEdgeCont::computeTurningDirections() {
00519     for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
00520         (*i).second->computeTurningDirections();
00521     }
00522 }
00523 
00524 
00525 void
00526 NBEdgeCont::clearControllingTLInformation() const {
00527     for (EdgeCont::const_iterator i = myEdges.begin(); i != myEdges.end(); i++) {
00528         (*i).second->clearControllingTLInformation();
00529     }
00530 }
00531 
00532 
00533 void
00534 NBEdgeCont::sortOutgoingLanesConnections() {
00535     for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
00536         (*i).second->sortOutgoingConnectionsByAngle();
00537     }
00538 }
00539 
00540 
00541 void
00542 NBEdgeCont::computeEdge2Edges(bool noLeftMovers) {
00543     for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
00544         (*i).second->computeEdge2Edges(noLeftMovers);
00545     }
00546 }
00547 
00548 
00549 void
00550 NBEdgeCont::computeLanes2Edges() {
00551     for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
00552         (*i).second->computeLanes2Edges();
00553     }
00554 }
00555 
00556 
00557 void
00558 NBEdgeCont::recheckLanes() {
00559     for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
00560         (*i).second->recheckLanes();
00561     }
00562 }
00563 
00564 
00565 void
00566 NBEdgeCont::appendTurnarounds(bool noTLSControlled) {
00567     for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
00568         (*i).second->appendTurnaround(noTLSControlled);
00569     }
00570 }
00571 
00572 
00573 void
00574 NBEdgeCont::appendTurnarounds(const std::set<std::string> &ids, bool noTLSControlled) {
00575     for (std::set<std::string>::const_iterator it = ids.begin(); it != ids.end(); it++) {
00576         myEdges[*it]->appendTurnaround(noTLSControlled);
00577     }
00578 }
00579 
00580 
00581 void
00582 NBEdgeCont::computeEdgeShapes() {
00583     for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
00584         (*i).second->computeEdgeShape();
00585     }
00586 }
00587 
00588 
00589 void
00590 NBEdgeCont::recomputeLaneShapes() {
00591     for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
00592         (*i).second->computeLaneShapes();
00593     }
00594 }
00595 
00596 
00597 void
00598 NBEdgeCont::joinSameNodeConnectingEdges(NBDistrictCont& dc,
00599                                         NBTrafficLightLogicCont& tlc,
00600                                         EdgeVector edges) {
00601     // !!! Attention!
00602     //  No merging of the geometry to come is being done
00603     //  The connections are moved from one edge to another within
00604     //   the replacement where the edge is a node's incoming edge.
00605 
00606     // count the number of lanes, the speed and the id
00607     unsigned int nolanes = 0;
00608     SUMOReal speed = 0;
00609     int priority = 0;
00610     std::string id;
00611     sort(edges.begin(), edges.end(), NBContHelper::same_connection_edge_sorter());
00612     // retrieve the connected nodes
00613     NBEdge* tpledge = *(edges.begin());
00614     NBNode* from = tpledge->getFromNode();
00615     NBNode* to = tpledge->getToNode();
00616     EdgeVector::const_iterator i;
00617     for (i = edges.begin(); i != edges.end(); i++) {
00618         // some assertions
00619         assert((*i)->getFromNode() == from);
00620         assert((*i)->getToNode() == to);
00621         // ad the number of lanes the current edge has
00622         nolanes += (*i)->getNumLanes();
00623         // build the id
00624         if (i != edges.begin()) {
00625             id += "+";
00626         }
00627         id += (*i)->getID();
00628         // compute the speed
00629         speed += (*i)->getSpeed();
00630         // build the priority
00631         priority = MAX2(priority, (*i)->getPriority());
00632     }
00633     speed /= edges.size();
00634     // build the new edge
00635     // @bug new edge does not know about allowed vclass of old edges
00636     // @bug both the width and the offset are not regarded
00637     NBEdge* newEdge = new NBEdge(id, from, to, "", speed, nolanes, priority,
00638                                  NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET,
00639                                  tpledge->getStreetName(), tpledge->myLaneSpreadFunction);
00640     insert(newEdge, true);
00641     // replace old edge by current within the nodes
00642     //  and delete the old
00643     from->replaceOutgoing(edges, newEdge);
00644     to->replaceIncoming(edges, newEdge);
00645     // patch connections
00646     //  add edge2edge-information
00647     for (i = edges.begin(); i != edges.end(); i++) {
00648         EdgeVector ev = (*i)->getConnectedEdges();
00649         for (EdgeVector::iterator j = ev.begin(); j != ev.end(); j++) {
00650             newEdge->addEdge2EdgeConnection(*j);
00651         }
00652     }
00653     //  move lane2lane-connections
00654     unsigned int currLane = 0;
00655     for (i = edges.begin(); i != edges.end(); i++) {
00656         newEdge->moveOutgoingConnectionsFrom(*i, currLane);
00657         currLane += (*i)->getNumLanes();
00658     }
00659     // patch tl-information
00660     currLane = 0;
00661     for (i = edges.begin(); i != edges.end(); i++) {
00662         unsigned int noLanes = (*i)->getNumLanes();
00663         for (unsigned int j = 0; j < noLanes; j++, currLane++) {
00664             // replace in traffic lights
00665             tlc.replaceRemoved(*i, j, newEdge, currLane);
00666         }
00667     }
00668     // delete joined edges
00669     for (i = edges.begin(); i != edges.end(); i++) {
00670         erase(dc, *i);
00671     }
00672 }
00673 
00674 
00675 void
00676 NBEdgeCont::recheckLaneSpread() {
00677     for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
00678         std::string oppositeID;
00679         if ((*i).first[0] == '-') {
00680             oppositeID = (*i).first.substr(1);
00681         } else {
00682             oppositeID = "-" + (*i).first;
00683         }
00684         if (myEdges.find(oppositeID) != myEdges.end()) {
00685             (*i).second->setLaneSpreadFunction(LANESPREAD_RIGHT);
00686             myEdges.find(oppositeID)->second->setLaneSpreadFunction(LANESPREAD_RIGHT);
00687         } else {
00688             (*i).second->setLaneSpreadFunction(LANESPREAD_CENTER);
00689         }
00690     }
00691 }
00692 
00693 
00694 
00695 // ----- other
00696 EdgeVector
00697 NBEdgeCont::getGeneratedFrom(const std::string& id) const {
00698     size_t len = id.length();
00699     EdgeVector ret;
00700     for (EdgeCont::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
00701         std::string curr = (*i).first;
00702         // the next check makes it possibly faster - we don not have
00703         //  to compare the names
00704         if (curr.length() <= len) {
00705             continue;
00706         }
00707         // the name must be the same as the given id but something
00708         //  beginning with a '[' must be appended to it
00709         if (curr.substr(0, len) == id && curr[len] == '[') {
00710             ret.push_back((*i).second);
00711             continue;
00712         }
00713         // ok, maybe the edge is a compound made during joining of edges
00714         size_t pos = curr.find(id);
00715         // surely not
00716         if (pos == std::string::npos) {
00717             continue;
00718         }
00719         // check leading char
00720         if (pos > 0) {
00721             if (curr[pos - 1] != ']' && curr[pos - 1] != '+') {
00722                 // actually, this is another id
00723                 continue;
00724             }
00725         }
00726         if (pos + id.length() < curr.length()) {
00727             if (curr[pos + id.length()] != '[' && curr[pos + id.length()] != '+') {
00728                 // actually, this is another id
00729                 continue;
00730             }
00731         }
00732         ret.push_back((*i).second);
00733     }
00734     return ret;
00735 }
00736 
00737 
00738 void
00739 NBEdgeCont::guessRoundabouts(std::vector<std::set<NBEdge*> > &marked) {
00740     // step 1: keep only those edges which have no turnarounds
00741     std::set<NBEdge*> candidates;
00742     for (EdgeCont::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
00743         NBEdge* e = (*i).second;
00744         NBNode* const to = e->getToNode();
00745         if (e->getTurnDestination() == 0 && to->getConnectionTo(e->getFromNode()) == 0) {
00746             candidates.insert(e);
00747         }
00748     }
00749     // step 2:
00750     std::set<NBEdge*> visited;
00751     for (std::set<NBEdge*>::const_iterator i = candidates.begin(); i != candidates.end(); ++i) {
00752         std::set<NBEdge*> loopEdges;
00753         // start with a random edge, keep it as "begin"
00754         NBEdge* begin = (*i);
00755         if (find(visited.begin(), visited.end(), begin) != visited.end()) {
00756             // already seen
00757             continue;
00758         }
00759         NBEdge* e = (*i);
00760         // loop over connected edges (using always the leftmost one)
00761         bool noLoop = false;
00762         do {
00763             visited.insert(e);
00764             EdgeVector edges = e->getToNode()->getEdges();
00765             if (edges.size() < 2) {
00766                 noLoop = true;
00767                 break;
00768             }
00769             sort(edges.begin(), edges.end(), NBContHelper::edge_by_junction_angle_sorter(e->getToNode()));
00770             EdgeVector::const_iterator me = find(edges.begin(), edges.end(), e);
00771             NBContHelper::nextCW(edges, me);
00772             NBEdge* left = *me;
00773             loopEdges.insert(left);
00774             if (left == begin) {
00775                 break;
00776             }
00777             if (find(candidates.begin(), candidates.end(), left) == candidates.end()) {
00778                 noLoop = true;
00779                 break;
00780             }
00781             if (find(visited.begin(), visited.end(), left) != visited.end()) {
00782                 noLoop = true;
00783                 break;
00784             }
00785             e = left;
00786         } while (true);
00787         // mark collected edges in the case a loop (roundabout) was found
00788         if (!noLoop) {
00789             for (std::set<NBEdge*>::const_iterator j = loopEdges.begin(); j != loopEdges.end(); ++j) {
00790 
00791                 // disable turnarounds on incoming edges
00792                 const EdgeVector& incoming = (*j)->getToNode()->getIncomingEdges();
00793                 const EdgeVector& outgoing = (*j)->getToNode()->getOutgoingEdges();
00794                 for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); ++k) {
00795                     if (loopEdges.find(*k) != loopEdges.end()) {
00796                         continue;
00797                     }
00798                     if ((*k)->getStep() >= NBEdge::LANES2LANES_USER) {
00799                         continue;
00800                     }
00801                     for (EdgeVector::const_iterator l = outgoing.begin(); l != outgoing.end(); ++l) {
00802                         if (loopEdges.find(*l) != loopEdges.end()) {
00803                             (*k)->addEdge2EdgeConnection(*l);
00804                         } else {
00805                             (*k)->removeFromConnections(*l, -1);
00806                         }
00807                     }
00808                 }
00809 
00810 
00811                 // let the connections to succeeding roundabout edge have a higher priority
00812                 (*j)->setJunctionPriority((*j)->getToNode(), 1000);
00813             }
00814             marked.push_back(loopEdges);
00815         }
00816     }
00817 }
00818 
00819 
00820 /****************************************************************************/
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines