|
SUMO - Simulation of Urban MObility
|
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 /****************************************************************************/