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