SUMO - Simulation of Urban MObility

NBEdgeCont.cpp

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