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