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/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 /****************************************************************************/