|
SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00007 // Methods for the representation of a single edge 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 <algorithm> 00033 #include <cassert> 00034 #include "NBEdgeCont.h" 00035 #include "NBNode.h" 00036 #include "NBNodeCont.h" 00037 #include "NBContHelper.h" 00038 #include "NBHelpers.h" 00039 #include <cmath> 00040 #include <iomanip> 00041 #include "NBTypeCont.h" 00042 #include <utils/geom/GeomHelper.h> 00043 #include <utils/common/MsgHandler.h> 00044 #include <utils/common/StringUtils.h> 00045 #include <utils/common/ToString.h> 00046 #include <utils/common/UtilExceptions.h> 00047 #include <utils/common/StdDefs.h> 00048 #include "NBEdge.h" 00049 #include <utils/options/OptionsCont.h> 00050 #include <utils/iodevices/OutputDevice.h> 00051 00052 #ifdef CHECK_MEMORY_LEAKS 00053 #include <foreign/nvwa/debug_new.h> 00054 #endif // CHECK_MEMORY_LEAKS 00055 00056 // =========================================================================== 00057 // static members 00058 // =========================================================================== 00059 const SUMOReal NBEdge::UNSPECIFIED_WIDTH = -1; 00060 const SUMOReal NBEdge::UNSPECIFIED_LOADED_LENGTH = -1; 00061 const SUMOReal NBEdge::UNSPECIFIED_OFFSET = 0; 00062 00063 // =========================================================================== 00064 // method definitions 00065 // =========================================================================== 00066 /* ------------------------------------------------------------------------- 00067 * NBEdge::ToEdgeConnectionsAdder-methods 00068 * ----------------------------------------------------------------------- */ 00069 void 00070 NBEdge::ToEdgeConnectionsAdder::execute(const unsigned int lane, const unsigned int virtEdge) throw() { 00071 // check 00072 assert(myTransitions.size() > virtEdge); 00073 // get the approached edge 00074 NBEdge* succEdge = myTransitions[virtEdge]; 00075 std::vector<unsigned int> lanes; 00076 00077 // check whether the currently regarded, approached edge has already 00078 // a connection starting at the edge which is currently being build 00079 std::map<NBEdge*, std::vector<unsigned int> >::iterator i=myConnections.find(succEdge); 00080 if (i!=myConnections.end()) { 00081 // if there were already lanes assigned, get them 00082 lanes = (*i).second; 00083 } 00084 00085 // check whether the current lane was already used to connect the currently 00086 // regarded approached edge 00087 std::vector<unsigned int>::iterator j=find(lanes.begin(), lanes.end(), lane); 00088 if (j==lanes.end()) { 00089 // if not, add it to the list 00090 lanes.push_back(lane); 00091 } 00092 // set information about connecting lanes 00093 myConnections[succEdge] = lanes; 00094 } 00095 00096 00097 00098 /* ------------------------------------------------------------------------- 00099 * NBEdge::MainDirections-methods 00100 * ----------------------------------------------------------------------- */ 00101 NBEdge::MainDirections::MainDirections(const EdgeVector& outgoing, 00102 NBEdge* parent, NBNode* to) { 00103 if (outgoing.size()==0) { 00104 return; 00105 } 00106 // check whether the right turn has a higher priority 00107 assert(outgoing.size()>0); 00108 if (outgoing[0]->getJunctionPriority(to)==1) { 00109 myDirs.push_back(MainDirections::DIR_RIGHTMOST); 00110 } 00111 // check whether the left turn has a higher priority 00112 if (outgoing.back()->getJunctionPriority(to)==1) { 00113 // ok, the left turn belongs to the higher priorised edges on the junction 00114 // let's check, whether it has also a higher priority (lane number/speed) 00115 // than the current 00116 EdgeVector tmp(outgoing); 00117 sort(tmp.begin(), tmp.end(), NBContHelper::edge_similar_direction_sorter(parent)); 00118 if (outgoing.back()->getPriority()>tmp[0]->getPriority()) { 00119 myDirs.push_back(MainDirections::DIR_LEFTMOST); 00120 } else { 00121 if (outgoing.back()->getNumLanes()>tmp[0]->getNumLanes()) { 00122 myDirs.push_back(MainDirections::DIR_LEFTMOST); 00123 } 00124 } 00125 } 00126 // check whether the forward direction has a higher priority 00127 // try to get the forward direction 00128 EdgeVector tmp(outgoing); 00129 sort(tmp.begin(), tmp.end(), NBContHelper::edge_similar_direction_sorter(parent)); 00130 NBEdge* edge = *(tmp.begin()); 00131 // check whether it has a higher priority and is going straight 00132 if (edge->getJunctionPriority(to)==1 && to->getDirection(parent, edge)==LINKDIR_STRAIGHT) { 00133 myDirs.push_back(MainDirections::DIR_FORWARD); 00134 } 00135 } 00136 00137 00138 NBEdge::MainDirections::~MainDirections() {} 00139 00140 00141 bool 00142 NBEdge::MainDirections::empty() const { 00143 return myDirs.empty(); 00144 } 00145 00146 00147 bool 00148 NBEdge::MainDirections::includes(Direction d) const { 00149 return find(myDirs.begin(), myDirs.end(), d)!=myDirs.end(); 00150 } 00151 00152 00153 00154 /* ------------------------------------------------------------------------- 00155 * NBEdge-methods 00156 * ----------------------------------------------------------------------- */ 00157 NBEdge::NBEdge(const std::string& id, NBNode* from, NBNode* to, 00158 std::string type, SUMOReal speed, unsigned int nolanes, 00159 int priority, SUMOReal width, SUMOReal offset, 00160 const std::string& streetName, 00161 LaneSpreadFunction spread) throw(ProcessError) : 00162 Named(StringUtils::convertUmlaute(id)), 00163 myStep(INIT), 00164 myType(StringUtils::convertUmlaute(type)), 00165 myFrom(from), myTo(to), myAngle(0), 00166 myPriority(priority), mySpeed(speed), 00167 myTurnDestination(0), 00168 myFromJunctionPriority(-1), myToJunctionPriority(-1), 00169 myLaneSpreadFunction(spread), myOffset(offset), myWidth(width), 00170 myLoadedLength(UNSPECIFIED_LOADED_LENGTH), myAmLeftHand(false), myAmTurningWithAngle(0), myAmTurningOf(0), 00171 myAmInnerEdge(false), myAmMacroscopicConnector(false), 00172 myStreetName(streetName) { 00173 init(nolanes, false); 00174 } 00175 00176 00177 NBEdge::NBEdge(const std::string& id, NBNode* from, NBNode* to, 00178 std::string type, SUMOReal speed, unsigned int nolanes, 00179 int priority, SUMOReal width, SUMOReal offset, 00180 PositionVector geom, 00181 const std::string& streetName, 00182 LaneSpreadFunction spread, bool tryIgnoreNodePositions) throw(ProcessError) : 00183 Named(StringUtils::convertUmlaute(id)), 00184 myStep(INIT), 00185 myType(StringUtils::convertUmlaute(type)), 00186 myFrom(from), myTo(to), myAngle(0), 00187 myPriority(priority), mySpeed(speed), 00188 myTurnDestination(0), 00189 myFromJunctionPriority(-1), myToJunctionPriority(-1), 00190 myGeom(geom), myLaneSpreadFunction(spread), myOffset(offset), myWidth(width), 00191 myLoadedLength(UNSPECIFIED_LOADED_LENGTH), myAmLeftHand(false), myAmTurningWithAngle(0), myAmTurningOf(0), 00192 myAmInnerEdge(false), myAmMacroscopicConnector(false), 00193 myStreetName(streetName) { 00194 init(nolanes, tryIgnoreNodePositions); 00195 } 00196 00197 00198 NBEdge::NBEdge(const std::string& id, NBNode* from, NBNode* to, NBEdge* tpl) : 00199 Named(StringUtils::convertUmlaute(id)), 00200 myStep(INIT), 00201 myType(tpl->getTypeID()), 00202 myFrom(from), myTo(to), myAngle(0), 00203 myPriority(tpl->getPriority()), mySpeed(tpl->getSpeed()), 00204 myTurnDestination(0), 00205 myFromJunctionPriority(-1), myToJunctionPriority(-1), 00206 myLaneSpreadFunction(tpl->getLaneSpreadFunction()), 00207 myOffset(tpl->getOffset()), 00208 myWidth(tpl->getWidth()), 00209 myLoadedLength(UNSPECIFIED_LOADED_LENGTH), myAmLeftHand(false), myAmTurningWithAngle(0), myAmTurningOf(0), 00210 myAmInnerEdge(false), myAmMacroscopicConnector(false), 00211 myStreetName(tpl->getStreetName()) { 00212 init(tpl->getNumLanes(), false); 00213 for (unsigned int i = 0; i < getNumLanes(); i++) { 00214 setLaneSpeed(i, tpl->getLaneSpeed(i)); 00215 setVehicleClasses(tpl->getAllowedVehicleClasses(i), tpl->getDisallowedVehicleClasses(i), i); 00216 } 00217 } 00218 00219 00220 void 00221 NBEdge::reinit(NBNode* from, NBNode* to, const std::string& type, 00222 SUMOReal speed, unsigned int nolanes, int priority, 00223 PositionVector geom, SUMOReal width, SUMOReal offset, 00224 LaneSpreadFunction spread, 00225 bool tryIgnoreNodePositions) throw(ProcessError) { 00226 // connections may still be valid 00227 if (myFrom!=from) { 00228 myFrom->removeEdge(this, false); 00229 } 00230 if (myTo!=to) { 00231 myTo->removeEdge(this, false); 00232 } 00233 myType = StringUtils::convertUmlaute(type); 00234 myFrom = from; 00235 myTo = to; 00236 myPriority = priority; 00237 mySpeed = speed; 00238 //?myTurnDestination(0), 00239 //?myFromJunctionPriority(-1), myToJunctionPriority(-1), 00240 myGeom = geom; 00241 myLaneSpreadFunction = spread; 00242 myOffset = offset; 00243 myWidth = width; 00244 myLoadedLength = UNSPECIFIED_LOADED_LENGTH; 00245 //?, myAmTurningWithAngle(0), myAmTurningOf(0), 00246 //?myAmInnerEdge(false), myAmMacroscopicConnector(false) 00247 init(nolanes, tryIgnoreNodePositions); 00248 } 00249 00250 00251 void 00252 NBEdge::init(unsigned int noLanes, bool tryIgnoreNodePositions) throw(ProcessError) { 00253 if (noLanes==0) { 00254 throw ProcessError("Edge '" + myID + "' needs at least one lane."); 00255 } 00256 if (myFrom==0||myTo==0) { 00257 throw ProcessError("At least one of edge's '" + myID + "' nodes is not known."); 00258 } 00259 // revisit geometry 00260 // should have at least two points at the end... 00261 // and in dome cases, the node positions must be added 00262 myGeom.removeDoublePoints(); 00263 if (!tryIgnoreNodePositions||myGeom.size()<2) { 00264 if (myGeom.size()==0) { 00265 myGeom.push_back(myTo->getPosition()); 00266 myGeom.push_front(myFrom->getPosition()); 00267 } else { 00268 myGeom.push_back_noDoublePos(myTo->getPosition()); 00269 myGeom.push_front_noDoublePos(myFrom->getPosition()); 00270 } 00271 } 00272 if (myGeom.size()<2) { 00273 myGeom.clear(); 00274 myGeom.push_back(myTo->getPosition()); 00275 myGeom.push_front(myFrom->getPosition()); 00276 } 00277 if (myGeom.size()==2&&myGeom[0]==myGeom[1]) { 00278 WRITE_ERROR("Edge's '" + myID + "' from- and to-node are at the same position."); 00279 myGeom[1].add(Position(POSITION_EPS, POSITION_EPS)); 00280 } 00281 // 00282 myAngle = NBHelpers::angle( 00283 myFrom->getPosition().x(), myFrom->getPosition().y(), 00284 myTo->getPosition().x(), myTo->getPosition().y() 00285 ); 00286 myFrom->addOutgoingEdge(this); 00287 myTo->addIncomingEdge(this); 00288 // prepare container 00289 myLength = myFrom->getPosition().distanceTo(myTo->getPosition()); 00290 assert(myGeom.size()>=2); 00291 myLanes.clear(); 00292 for (unsigned int i=0; i<noLanes; i++) { 00293 Lane l; 00294 l.speed = mySpeed; 00295 l.offset = myOffset; 00296 l.width = myWidth; 00297 myLanes.push_back(l); 00298 } 00299 computeLaneShapes(); 00300 } 00301 00302 00303 NBEdge::~NBEdge() throw() {} 00304 00305 00306 // ----------- Applying offset 00307 void 00308 NBEdge::reshiftPosition(SUMOReal xoff, SUMOReal yoff) throw() { 00309 myGeom.reshiftRotate(xoff, yoff, 0); 00310 for (unsigned int i=0; i<myLanes.size(); i++) { 00311 myLanes[i].shape.reshiftRotate(xoff, yoff, 0); 00312 } 00313 } 00314 00315 00316 // ----------- Edge geometry access and computation 00317 const PositionVector 00318 NBEdge::getInnerGeometry() const { 00319 PositionVector result = getGeometry(); 00320 result.pop_front(); 00321 result.pop_back(); 00322 return result; 00323 } 00324 00325 00326 bool 00327 NBEdge::hasDefaultGeometry() const { 00328 return myGeom.size() == 2 && hasDefaultGeometryEndpoints(); 00329 } 00330 00331 00332 bool 00333 NBEdge::hasDefaultGeometryEndpoints() const { 00334 return myGeom.getBegin() == myFrom->getPosition() && 00335 myGeom.getEnd() == myTo->getPosition(); 00336 } 00337 00338 00339 void 00340 NBEdge::setGeometry(const PositionVector& s, bool inner) throw() { 00341 Position begin = myGeom.getBegin(); // may differ from node position 00342 Position end = myGeom.getEnd(); // may differ from node position 00343 myGeom = s; 00344 if (inner) { 00345 myGeom.push_front(begin); 00346 myGeom.push_back(end); 00347 } 00348 computeLaneShapes(); 00349 } 00350 00351 00352 void 00353 NBEdge::computeEdgeShape() throw() { 00354 unsigned int i; 00355 for (i=0; i<myLanes.size(); i++) { 00356 PositionVector& shape = myLanes[i].shape; 00357 // get lane begin and end 00358 Line lb = Line(shape[0], shape[1]); 00359 Line le = Line(shape[-1], shape[-2]); 00360 lb.extrapolateBy(100.0); 00361 le.extrapolateBy(100.0); 00362 // 00363 PositionVector old = shape; 00364 Position nb, ne; 00365 // lane begin 00366 if (myFrom->getShape().intersects(shape)) { 00367 // get the intersection position with the junction 00368 DoubleVector pbv = shape.intersectsAtLengths(myFrom->getShape()); 00369 if (pbv.size()>0) { 00370 SUMOReal pb = VectorHelper<SUMOReal>::maxValue(pbv); 00371 if (pb>=0&&pb<=shape.length()) { 00372 shape = shape.getSubpart(pb, shape.length()); 00373 } 00374 } 00375 } else if (myFrom->getShape().intersects(lb.p1(), lb.p2())) { 00376 DoubleVector pbv = lb.intersectsAtLengths(myFrom->getShape()); 00377 if (pbv.size()>0) { 00378 SUMOReal pb = VectorHelper<SUMOReal>::maxValue(pbv); 00379 if (pb>=0) { 00380 shape.eraseAt(0); 00381 shape.push_front_noDoublePos(lb.getPositionAtDistance(pb)); 00382 } 00383 } 00384 } 00385 // lane end 00386 if (myTo->getShape().intersects(shape)) { 00387 // get the intersection position with the junction 00388 DoubleVector pev = shape.intersectsAtLengths(myTo->getShape()); 00389 if (pev.size()>0) { 00390 SUMOReal pe = VectorHelper<SUMOReal>::minValue(pev); 00391 if (pe>=0&&pe<=shape.length()) { 00392 shape = shape.getSubpart(0, pe); 00393 } 00394 } 00395 } else if (myTo->getShape().intersects(le.p1(), le.p2())) { 00396 DoubleVector pev = le.intersectsAtLengths(myTo->getShape()); 00397 if (pev.size()>0) { 00398 SUMOReal pe = VectorHelper<SUMOReal>::maxValue(pev); 00399 if (pe>=0) { 00400 shape.eraseAt((int) shape.size()-1); 00401 shape.push_back(le.getPositionAtDistance(pe)); 00402 } 00403 } 00404 } 00405 if (shape.length() < POSITION_EPS) { 00406 WRITE_MESSAGE("Lane '" + myID + "' has calculated shape length near zero. Revert it back to old shape."); 00407 shape = old; 00408 } else { 00409 Line lc(shape[0], shape[-1]); 00410 Line lo(old[0], old[-1]); 00411 if (135<GeomHelper::getMinAngleDiff(lc.atan2DegreeAngle(), lo.atan2DegreeAngle())) { 00412 shape = shape.reverse(); 00413 } 00414 } 00415 } 00416 // recompute edge's length 00417 SUMOReal length = 0; 00418 for (i=0; i<myLanes.size(); i++) { 00419 assert(myLanes[i].shape.length()>0); 00420 length += myLanes[i].shape.length(); 00421 } 00422 myLength = length / (SUMOReal) myLanes.size(); 00423 } 00424 00425 00426 const PositionVector& 00427 NBEdge::getLaneShape(unsigned int i) const throw() { 00428 return myLanes[i].shape; 00429 } 00430 00431 00432 void 00433 NBEdge::setLaneSpreadFunction(LaneSpreadFunction spread) throw() { 00434 myLaneSpreadFunction = spread; 00435 } 00436 00437 00438 void 00439 NBEdge::addGeometryPoint(int index, const Position& p) throw() { 00440 myGeom.insertAt(index, p); 00441 } 00442 00443 00444 bool 00445 NBEdge::splitGeometry(NBEdgeCont& ec, NBNodeCont& nc) { 00446 // check whether there any splits to perform 00447 if (myGeom.size()<3) { 00448 return false; 00449 } 00450 // ok, split 00451 NBNode* newFrom = myFrom; 00452 NBNode* myLastNode = myTo; 00453 NBNode* newTo = 0; 00454 NBEdge* currentEdge = this; 00455 for (int i=1; i<(int) myGeom.size()-1; i++) { 00456 // build the node first 00457 if (i!=static_cast<int>(myGeom.size()-2)) { 00458 std::string nodename = myID + "_in_between#" + toString(i); 00459 if (!nc.insert(nodename, myGeom[i])) { 00460 throw ProcessError("Error on adding in-between node '" + nodename + "'."); 00461 } 00462 newTo = nc.retrieve(nodename); 00463 } else { 00464 newTo = myLastNode; 00465 } 00466 if (i==1) { 00467 currentEdge->myTo->removeEdge(this); 00468 currentEdge->myTo = newTo; 00469 newTo->addIncomingEdge(currentEdge); 00470 } else { 00471 std::string edgename = myID + "[" + toString(i-1) + "]"; 00472 // @bug lane-specific width, speed, overall offset and restrictions are ignored 00473 currentEdge = new NBEdge(edgename, newFrom, newTo, myType, mySpeed, (unsigned int) myLanes.size(), 00474 myPriority, myWidth, UNSPECIFIED_OFFSET, myStreetName, myLaneSpreadFunction); 00475 if (!ec.insert(currentEdge, true)) { 00476 throw ProcessError("Error on adding splitted edge '" + edgename + "'."); 00477 } 00478 } 00479 newFrom = newTo; 00480 } 00481 myGeom.clear(); 00482 myGeom.push_back(myFrom->getPosition()); 00483 myGeom.push_back(myTo->getPosition()); 00484 myStep = INIT; 00485 return true; 00486 } 00487 00488 00489 // ----------- Setting and getting connections 00490 bool 00491 NBEdge::addEdge2EdgeConnection(NBEdge* dest) throw() { 00492 if (myStep==INIT_REJECT_CONNECTIONS) { 00493 return true; 00494 } 00495 // check whether the node was merged and now a connection between 00496 // not matching edges is tried to be added 00497 // This happens f.e. within the ptv VISSIM-example "Beijing" 00498 if (dest!=0 && myTo!=dest->myFrom) { 00499 return false; 00500 } 00501 if (dest == 0) { 00502 invalidateConnections(); 00503 myConnections.push_back(Connection(-1, dest, -1)); 00504 } else if (find_if(myConnections.begin(), myConnections.end(), connections_toedge_finder(dest))==myConnections.end()) { 00505 myConnections.push_back(Connection(-1, dest, -1)); 00506 } 00507 if (myStep<EDGE2EDGES) { 00508 myStep = EDGE2EDGES; 00509 } 00510 return true; 00511 } 00512 00513 00514 bool 00515 NBEdge::addLane2LaneConnection(unsigned int from, NBEdge* dest, 00516 unsigned int toLane, Lane2LaneInfoType type, 00517 bool mayUseSameDestination, 00518 bool mayDefinitelyPass) throw() { 00519 if (myStep==INIT_REJECT_CONNECTIONS) { 00520 return true; 00521 } 00522 // check whether the node was merged and now a connection between 00523 // not matching edges is tried to be added 00524 // This happens f.e. within the ptv VISSIM-example "Beijing" 00525 if (myTo!=dest->myFrom) { 00526 return false; 00527 } 00528 if (!addEdge2EdgeConnection(dest)) { 00529 return false; 00530 } 00531 setConnection(from, dest, toLane, type, mayUseSameDestination, mayDefinitelyPass); 00532 return true; 00533 } 00534 00535 00536 bool 00537 NBEdge::addLane2LaneConnections(unsigned int fromLane, 00538 NBEdge* dest, unsigned int toLane, 00539 unsigned int no, Lane2LaneInfoType type, 00540 bool invalidatePrevious, 00541 bool mayDefinitelyPass) throw() { 00542 if (invalidatePrevious) { 00543 invalidateConnections(true); 00544 } 00545 bool ok = true; 00546 for (unsigned int i=0; i<no&&ok; i++) { 00547 ok &= addLane2LaneConnection(fromLane+i, dest, toLane+i, type, false, mayDefinitelyPass); 00548 } 00549 return ok; 00550 } 00551 00552 00553 void 00554 NBEdge::setConnection(unsigned int lane, NBEdge* destEdge, 00555 unsigned int destLane, Lane2LaneInfoType type, 00556 bool mayUseSameDestination, 00557 bool mayDefinitelyPass) throw() { 00558 if (myStep==INIT_REJECT_CONNECTIONS) { 00559 return; 00560 } 00561 // some kind of a misbehaviour which may occure when the junction's outgoing 00562 // edge priorities were not properly computed, what may happen due to 00563 // an incomplete or not proper input 00564 // what happens is that under some circumstances a single lane may set to 00565 // be approached more than once by the one of our lanes. 00566 // This must not be! 00567 // we test whether it is the case and do nothing if so - the connection 00568 // will be refused 00569 // 00570 if (!mayUseSameDestination && hasConnectionTo(destEdge, destLane)) { 00571 return; 00572 } 00573 if (find_if(myConnections.begin(), myConnections.end(), connections_finder(lane, destEdge, destLane))!=myConnections.end()) { 00574 return; 00575 } 00576 if (myLanes.size()<=lane) { 00577 WRITE_ERROR("Could not set connection from '" + getLaneID(lane) + "' to '" + destEdge->getLaneID(destLane) + "'."); 00578 return; 00579 } 00580 for (std::vector<Connection>::iterator i=myConnections.begin(); i!=myConnections.end();) { 00581 if ((*i).toEdge==destEdge && ((*i).fromLane==-1 || (*i).toLane==-1)) { 00582 i = myConnections.erase(i); 00583 } else { 00584 ++i; 00585 } 00586 } 00587 myConnections.push_back(Connection(lane, destEdge, destLane)); 00588 if (mayDefinitelyPass) { 00589 myConnections.back().mayDefinitelyPass = true; 00590 } 00591 if (type==L2L_USER) { 00592 myStep = LANES2LANES_USER; 00593 } else { 00594 // check whether we have to take another look at it later 00595 if (type==L2L_COMPUTED) { 00596 // yes, the connection was set using an algorithm which requires a recheck 00597 myStep = LANES2LANES_RECHECK; 00598 } else { 00599 // ok, let's only not recheck it if we did no add something that has to be recheked 00600 if (myStep!=LANES2LANES_RECHECK) { 00601 myStep = LANES2LANES_DONE; 00602 } 00603 } 00604 } 00605 } 00606 00607 00608 std::vector<NBEdge::Connection> 00609 NBEdge::getConnectionsFromLane(unsigned int lane) const throw() { 00610 std::vector<NBEdge::Connection> ret; 00611 for (std::vector<Connection>::const_iterator i=myConnections.begin(); i!=myConnections.end(); ++i) { 00612 if ((*i).fromLane==static_cast<int>(lane)) { 00613 ret.push_back(*i); 00614 } 00615 } 00616 return ret; 00617 } 00618 00619 00620 bool 00621 NBEdge::hasConnectionTo(NBEdge* destEdge, unsigned int destLane) const throw() { 00622 return destEdge!=0&&find_if(myConnections.begin(), myConnections.end(), connections_toedgelane_finder(destEdge, destLane))!=myConnections.end(); 00623 } 00624 00625 00626 void 00627 NBEdge::buildInnerEdges(const NBNode& n, unsigned int noInternalNoSplits, unsigned int& lno, unsigned int& splitNo) { 00628 std::string innerID = ":" + n.getID(); 00629 for (std::vector<Connection>::iterator i=myConnections.begin(); i!=myConnections.end(); ++i) { 00630 if ((*i).toEdge==0) { 00631 continue; 00632 } 00633 00634 PositionVector shape = n.computeInternalLaneShape(this, (*i).fromLane, (*i).toEdge, (*i).toLane); 00635 00636 LinkDirection dir = n.getDirection(this, (*i).toEdge); 00637 std::pair<SUMOReal, std::vector<unsigned int> > crossingPositions(-1, std::vector<unsigned int>()); 00638 std::string crossingNames; 00639 std::set<std::string> tmpSourceNames; 00640 switch (dir) { 00641 case LINKDIR_LEFT: 00642 case LINKDIR_PARTLEFT: 00643 case LINKDIR_TURN: { 00644 unsigned int index = 0; 00645 const std::vector<NBEdge*> &incoming = n.getIncomingEdges(); 00646 for (EdgeVector::const_iterator i2=incoming.begin(); i2!=incoming.end(); ++i2) { 00647 const std::vector<Connection> &elv = (*i2)->getConnections(); 00648 for (std::vector<NBEdge::Connection>::const_iterator k2=elv.begin(); k2!=elv.end(); k2++) { 00649 if ((*k2).toEdge==0) { 00650 continue; 00651 } 00652 bool needsCont = n.needsCont(this, (*i).toEdge, *i2, (*k2).toEdge, *k2); 00653 // compute the crossing point 00654 if (needsCont) { 00655 crossingPositions.second.push_back(index); 00656 PositionVector otherShape = n.computeInternalLaneShape(*i2, (*k2).fromLane, (*k2).toEdge, (*k2).toLane); 00657 if (shape.intersects(otherShape)) { 00658 DoubleVector dv = shape.intersectsAtLengths(otherShape); 00659 SUMOReal minDV = dv[0]; 00660 if (minDV<shape.length()-.1&&minDV>.1) { // !!!? 00661 assert(minDV>=0); 00662 if (crossingPositions.first<0||crossingPositions.first>minDV) { 00663 crossingPositions.first = minDV; 00664 } 00665 } 00666 } 00667 } 00668 // compute crossing ids 00669 NBEdge* e = getToNode()->getOppositeIncoming(this); 00670 if (e!=*i2) { 00671 index++; 00672 continue; 00673 } 00674 if (needsCont) { 00675 if (crossingNames.length()!=0) { 00676 crossingNames += " "; 00677 } 00678 crossingNames += (":" + n.getID() + "_" + toString(index) + "_0"); 00679 } 00680 00681 // compute source ids 00682 if ((*k2).mayDefinitelyPass) { 00683 index++; 00684 continue; 00685 } 00686 if (needsCont) { 00687 tmpSourceNames.insert((*i2)->getID() + "_" + toString((*k2).fromLane)); 00688 } 00689 index++; 00690 } 00691 } 00692 if (dir==LINKDIR_TURN&&crossingPositions.first<0&&crossingPositions.second.size()!=0) { 00693 // let turnarounds wait at the begin if no other crossing point was found 00694 crossingPositions.first = (SUMOReal) shape.length() / 2.; 00695 } 00696 } 00697 break; 00698 default: 00699 break; 00700 } 00701 00702 00703 // compute the maximum speed allowed 00704 // see !!! for an explanation (with a_lat_mean ~0.3) 00705 SUMOReal vmax = (SUMOReal) 0.3 * (SUMOReal) 9.80778 * 00706 getLaneShape((*i).fromLane).getEnd().distanceTo( 00707 (*i).toEdge->getLaneShape((*i).toLane).getBegin()) 00708 / (SUMOReal) 2.0 / (SUMOReal) PI; 00709 vmax = MIN2(vmax, ((getSpeed()+(*i).toEdge->getSpeed())/(SUMOReal) 2.0)); 00710 vmax = (getSpeed()+(*i).toEdge->getSpeed())/(SUMOReal) 2.0; 00711 // 00712 Position end = (*i).toEdge->getLaneShape((*i).toLane).getBegin(); 00713 Position beg = getLaneShape((*i).fromLane).getEnd(); 00714 00715 assert(shape.size() >= 2); 00716 // get internal splits if any 00717 if (crossingPositions.first>=0) { 00718 std::pair<PositionVector, PositionVector> split = shape.splitAt(crossingPositions.first); 00719 (*i).id = innerID + "_" + toString(lno); 00720 (*i).vmax = vmax; 00721 (*i).shape = split.first; 00722 (*i).crossingNames = crossingNames; 00723 for (std::set<std::string>::iterator q=tmpSourceNames.begin(); q!=tmpSourceNames.end(); ++q) { 00724 if ((*i).sourceNames.length()!=0) { 00725 (*i).sourceNames += " "; 00726 } 00727 (*i).sourceNames += *q; 00728 } 00729 (*i).viaID = innerID + "_" + toString(splitNo+noInternalNoSplits); 00730 (*i).viaVmax = vmax; 00731 (*i).viaShape = split.second; 00732 (*i).haveVia = true; 00733 splitNo++; 00734 } else { 00735 (*i).id = innerID + "_" + toString(lno); 00736 (*i).vmax = vmax; 00737 (*i).shape = shape; 00738 } 00739 00740 00741 lno++; 00742 } 00743 } 00744 00745 // ----------- 00746 00747 00748 int 00749 NBEdge::getJunctionPriority(const NBNode* const node) const { 00750 if (node==myFrom) { 00751 return myFromJunctionPriority; 00752 } else { 00753 return myToJunctionPriority; 00754 } 00755 } 00756 00757 00758 void 00759 NBEdge::setJunctionPriority(const NBNode* const node, int prio) { 00760 if (node==myFrom) { 00761 myFromJunctionPriority = prio; 00762 } else { 00763 myToJunctionPriority = prio; 00764 } 00765 } 00766 00767 00768 void 00769 NBEdge::computeTurningDirections() { 00770 myTurnDestination = 0; 00771 EdgeVector outgoing = myTo->getOutgoingEdges(); 00772 for (EdgeVector::iterator i=outgoing.begin(); i!=outgoing.end(); i++) { 00773 NBEdge* outedge = *i; 00774 if (myConnections.size()!=0&&!isConnectedTo(outedge)) { 00775 continue; 00776 } 00777 SUMOReal relAngle = 00778 NBHelpers::relAngle(getAngle(*myTo), outedge->getAngle(*myTo)); 00779 // do not append the turnaround 00780 if (fabs(relAngle)>160) { 00781 setTurningDestination(outedge); 00782 } 00783 } 00784 } 00785 00786 00787 SUMOReal 00788 NBEdge::getAngle(const NBNode& atNode) const { 00789 if (&atNode==myFrom) { 00790 return myGeom.getBegLine().atan2DegreeAngle(); 00791 } else { 00792 assert(&atNode==myTo); 00793 return myGeom.getEndLine().atan2DegreeAngle(); 00794 } 00795 } 00796 00797 00798 void 00799 NBEdge::setTurningDestination(NBEdge* e) { 00800 SUMOReal cur = fabs(NBHelpers::relAngle(getAngle(), e->getAngle())); 00801 SUMOReal old = 00802 myTurnDestination==0 00803 ? 0 00804 : fabs(NBHelpers::relAngle(getAngle(), myTurnDestination->getAngle())); 00805 if (cur>old 00806 && 00807 e->acceptBeingTurning(this)) { 00808 00809 myTurnDestination = e; 00810 } 00811 } 00812 00813 00814 bool 00815 NBEdge::acceptBeingTurning(NBEdge* e) { 00816 if (e==myAmTurningOf) { 00817 return true; 00818 } 00819 SUMOReal angle = fabs(NBHelpers::relAngle(getAngle(), e->getAngle())); 00820 if (myAmTurningWithAngle>angle) { 00821 return false; 00822 } 00823 if (myAmTurningWithAngle==angle) { 00824 return false; // !!! ok, this happens only within a cell-network (backgrnd), we have to take a further look sometime 00825 } 00826 NBEdge* previous = myAmTurningOf; 00827 myAmTurningWithAngle = angle; 00828 myAmTurningOf = e; 00829 if (previous!=0) { 00830 previous->computeTurningDirections(); 00831 } 00832 return true; 00833 } 00834 00835 00836 void 00837 NBEdge::setLaneSpeed(unsigned int lane, SUMOReal speed) { 00838 myLanes[lane].speed = speed; 00839 } 00840 00841 00842 SUMOReal 00843 NBEdge::getLaneSpeed(unsigned int lane) const { 00844 return myLanes[lane].speed; 00845 } 00846 00847 00848 void 00849 NBEdge::computeLaneShapes() throw() { 00850 // vissim needs this 00851 if (myFrom==myTo) { 00852 return; 00853 } 00854 // build the shape of each lane 00855 for (unsigned int i=0; i<myLanes.size(); i++) { 00856 try { 00857 myLanes[i].shape = computeLaneShape(i); 00858 } catch (InvalidArgument& e) { 00859 WRITE_WARNING("In edge '" + getID() + "': lane shape could not been determined (" + e.what() + ")"); 00860 myLanes[i].shape = myGeom; 00861 } 00862 } 00863 } 00864 00865 00866 PositionVector 00867 NBEdge::computeLaneShape(unsigned int lane) throw(InvalidArgument) { 00868 PositionVector shape; 00869 bool haveWarned = false; 00870 for (int i=0; i<(int) myGeom.size(); i++) { 00871 if (i==0) { 00872 Position from = myGeom[i]; 00873 Position to = myGeom[i+1]; 00874 std::pair<SUMOReal, SUMOReal> offsets = laneOffset(from, to, SUMO_const_laneWidthAndOffset, (unsigned int)(myLanes.size()-1-lane)); 00875 shape.push_back( 00876 // (methode umbenennen; was heisst hier "-") 00877 Position(from.x()-offsets.first, from.y()-offsets.second, from.z())); 00878 } else if (i==static_cast<int>(myGeom.size()-1)) { 00879 Position from = myGeom[i-1]; 00880 Position to = myGeom[i]; 00881 std::pair<SUMOReal, SUMOReal> offsets = laneOffset(from, to, SUMO_const_laneWidthAndOffset, (unsigned int)(myLanes.size()-1-lane)); 00882 shape.push_back( 00883 // (methode umbenennen; was heisst hier "-") 00884 Position(to.x()-offsets.first, to.y()-offsets.second, to.z())); 00885 } else { 00886 Position from = myGeom[i-1]; 00887 Position me = myGeom[i]; 00888 Position to = myGeom[i+1]; 00889 std::pair<SUMOReal, SUMOReal> offsets = laneOffset(from, me, SUMO_const_laneWidthAndOffset, (unsigned int)(myLanes.size()-1-lane)); 00890 std::pair<SUMOReal, SUMOReal> offsets2 = laneOffset(me, to, SUMO_const_laneWidthAndOffset, (unsigned int)(myLanes.size()-1-lane)); 00891 Line l1( 00892 Position(from.x()-offsets.first, from.y()-offsets.second), 00893 Position(me.x()-offsets.first, me.y()-offsets.second)); 00894 l1.extrapolateBy(100); 00895 Line l2( 00896 Position(me.x()-offsets2.first, me.y()-offsets2.second), 00897 Position(to.x()-offsets2.first, to.y()-offsets2.second)); 00898 const SUMOReal angle = GeomHelper::getCWAngleDiff(l1.atan2DegreeAngle(), l2.atan2DegreeAngle()); 00899 if (angle<10.||angle>350.) { 00900 shape.push_back( 00901 // (methode umbenennen; was heisst hier "-") 00902 Position(me.x()-offsets.first, me.y()-offsets.second, me.z())); 00903 continue; 00904 } 00905 l2.extrapolateBy(100); 00906 if (l1.intersects(l2)) { 00907 Position intersetion = l1.intersectsAt(l2); 00908 shape.push_back(Position(intersetion.x(), intersetion.y(), me.z())); 00909 } else { 00910 if (!haveWarned) { 00911 WRITE_WARNING("In lane '" + getLaneID(lane) + "': Could not build shape."); 00912 haveWarned = true; 00913 } 00914 } 00915 } 00916 } 00917 return shape; 00918 } 00919 00920 00921 std::pair<SUMOReal, SUMOReal> 00922 NBEdge::laneOffset(const Position& from, const Position& to, 00923 SUMOReal lanewidth, unsigned int lane) throw(InvalidArgument) { 00924 return laneOffset(from, to, lanewidth, lane, 00925 myLanes.size(), myLaneSpreadFunction, myAmLeftHand); 00926 } 00927 00928 00929 std::pair<SUMOReal, SUMOReal> 00930 NBEdge::laneOffset(const Position& from, const Position& to, 00931 SUMOReal lanewidth, unsigned int lane, 00932 size_t noLanes, LaneSpreadFunction lsf, bool leftHand) { 00933 std::pair<SUMOReal, SUMOReal> offsets = 00934 GeomHelper::getNormal90D_CW(from, to, lanewidth); 00935 SUMOReal xoff = offsets.first / (SUMOReal) 2.0; 00936 SUMOReal yoff = offsets.second / (SUMOReal) 2.0; 00937 if (lsf==LANESPREAD_RIGHT) { 00938 xoff += (offsets.first * (SUMOReal) lane); 00939 yoff += (offsets.second * (SUMOReal) lane); 00940 } else { 00941 xoff += (offsets.first * (SUMOReal) lane) - (offsets.first * (SUMOReal) noLanes / (SUMOReal) 2.0); 00942 yoff += (offsets.second * (SUMOReal) lane) - (offsets.second * (SUMOReal) noLanes / (SUMOReal) 2.0); 00943 } 00944 if (leftHand) { 00945 return std::pair<SUMOReal, SUMOReal>(-xoff, -yoff); 00946 } else { 00947 return std::pair<SUMOReal, SUMOReal>(xoff, yoff); 00948 } 00949 } 00950 00951 00952 bool 00953 NBEdge::hasRestrictions() const { 00954 for (std::vector<Lane>::const_iterator i=myLanes.begin(); i!=myLanes.end(); ++i) { 00955 if ((*i).allowed.size()!=0 || (*i).notAllowed.size()!=0) { 00956 return true; 00957 } 00958 } 00959 return false; 00960 } 00961 00962 00963 bool 00964 NBEdge::hasLaneSpecificAllow() const { 00965 std::vector<Lane>::const_iterator i=myLanes.begin(); 00966 const SUMOVehicleClasses& allowed = i->allowed; 00967 i++; 00968 for (; i!=myLanes.end(); ++i) { 00969 if (i->allowed != allowed) { 00970 return true; 00971 } 00972 } 00973 return false; 00974 } 00975 00976 00977 bool 00978 NBEdge::hasLaneSpecificDisallow() const { 00979 std::vector<Lane>::const_iterator i=myLanes.begin(); 00980 const SUMOVehicleClasses& notAllowed = i->notAllowed; 00981 i++; 00982 for (; i!=myLanes.end(); ++i) { 00983 if (i->notAllowed != notAllowed) { 00984 return true; 00985 } 00986 } 00987 return false; 00988 } 00989 00990 00991 bool 00992 NBEdge::hasLaneSpecificWidth() const { 00993 for (std::vector<Lane>::const_iterator i=myLanes.begin(); i!=myLanes.end(); ++i) { 00994 if (i->width != getWidth()) { 00995 return true; 00996 } 00997 } 00998 return false; 00999 } 01000 01001 01002 bool 01003 NBEdge::hasLaneSpecificSpeed() const { 01004 for (std::vector<Lane>::const_iterator i=myLanes.begin(); i!=myLanes.end(); ++i) { 01005 if (i->speed != getSpeed()) { 01006 return true; 01007 } 01008 } 01009 return false; 01010 } 01011 01012 01013 bool 01014 NBEdge::hasLaneSpecificOffset() const { 01015 for (std::vector<Lane>::const_iterator i=myLanes.begin(); i!=myLanes.end(); ++i) { 01016 if (i->offset != getOffset()) { 01017 return true; 01018 } 01019 } 01020 return false; 01021 } 01022 01023 01024 bool 01025 NBEdge::needsLaneSpecificOutput() const { 01026 return hasRestrictions() || hasLaneSpecificSpeed() || hasLaneSpecificWidth() || hasLaneSpecificOffset(); 01027 } 01028 01029 01030 01031 bool 01032 NBEdge::computeEdge2Edges(bool noLeftMovers) { 01033 // return if this relationship has been build in previous steps or 01034 // during the import 01035 if (myStep>=EDGE2EDGES) { 01036 return true; 01037 } 01038 if (myConnections.size()==0) { 01039 const EdgeVector& o = myTo->getOutgoingEdges(); 01040 for (EdgeVector::const_iterator i=o.begin(); i!=o.end(); ++i) { 01041 if (noLeftMovers&&myTo->isLeftMover(this, *i)) { 01042 continue; 01043 } 01044 myConnections.push_back(Connection(-1, *i, -1)); 01045 } 01046 } 01047 myStep = EDGE2EDGES; 01048 return true; 01049 } 01050 01051 01052 bool 01053 NBEdge::computeLanes2Edges() { 01054 // return if this relationship has been build in previous steps or 01055 // during the import 01056 if (myStep>=LANES2EDGES) { 01057 return true; 01058 } 01059 assert(myStep==EDGE2EDGES); 01060 // get list of possible outgoing edges sorted by direction clockwise 01061 // the edge in the backward direction (turnaround) is not in the list 01062 const EdgeVector* edges = getConnectedSorted(); 01063 if (myConnections.size()!=0&&edges->size()==0) { 01064 // dead end per definition!? 01065 myConnections.clear(); 01066 } else { 01067 // divide the lanes on reachable edges 01068 divideOnEdges(edges); 01069 } 01070 delete edges; 01071 myStep = LANES2EDGES; 01072 return true; 01073 } 01074 01075 01076 bool 01077 NBEdge::recheckLanes() { 01078 std::vector<unsigned int> connNumbersPerLane(myLanes.size(), 0); 01079 for (std::vector<Connection>::iterator i=myConnections.begin(); i!=myConnections.end();) { 01080 if ((*i).toEdge==0||(*i).fromLane<0||(*i).toLane<0) { 01081 i = myConnections.erase(i); 01082 } else { 01083 if ((*i).fromLane>=0) { 01084 ++connNumbersPerLane[(*i).fromLane]; 01085 } 01086 ++i; 01087 } 01088 } 01089 if (myStep!=LANES2LANES_DONE&&myStep!=LANES2LANES_USER) { 01090 // check #1: 01091 // If there is a lane with no connections and any neighbour lane has 01092 // more than one connections, try to move one of them. 01093 // This check is only done for edges which connections were assigned 01094 // using the standard algorithm. 01095 for (unsigned int i=0; i<myLanes.size(); i++) { 01096 if (connNumbersPerLane[i]==0) { 01097 if (i>0&&connNumbersPerLane[i-1]>1) { 01098 moveConnectionToLeft(i-1); 01099 } else if (i<myLanes.size()-1&&connNumbersPerLane[i+1]>1) { 01100 moveConnectionToRight(i+1); 01101 } 01102 } 01103 } 01104 } 01105 return true; 01106 } 01107 01108 01109 void 01110 NBEdge::moveConnectionToLeft(unsigned int lane) { 01111 unsigned int index = 0; 01112 if (myAmLeftHand) { 01113 for (int i=(int) myConnections.size()-1; i>=0; --i) { 01114 if (myConnections[i].fromLane==static_cast<int>(lane)&&getTurnDestination()!=myConnections[i].toEdge) { 01115 index = i; 01116 } 01117 } 01118 } else { 01119 for (unsigned int i=0; i<myConnections.size(); ++i) { 01120 if (myConnections[i].fromLane==static_cast<int>(lane)) { 01121 index = i; 01122 } 01123 } 01124 } 01125 std::vector<Connection>::iterator i = myConnections.begin() + index; 01126 Connection c = *i; 01127 myConnections.erase(i); 01128 setConnection(lane+1, c.toEdge, c.toLane, L2L_VALIDATED, false); 01129 } 01130 01131 01132 void 01133 NBEdge::moveConnectionToRight(unsigned int lane) { 01134 if (myAmLeftHand) { 01135 for (int i=(int) myConnections.size()-1; i>=0; --i) { 01136 if (myConnections[i].fromLane==static_cast<int>(lane)&&getTurnDestination()!=myConnections[i].toEdge) { 01137 Connection c = myConnections[i]; 01138 myConnections.erase(myConnections.begin() + i); 01139 setConnection(lane-1, c.toEdge, c.toLane, L2L_VALIDATED, false); 01140 return; 01141 } 01142 } 01143 } else { 01144 for (std::vector<Connection>::iterator i=myConnections.begin(); i!=myConnections.end(); ++i) { 01145 if ((*i).fromLane==static_cast<int>(lane)) { 01146 Connection c = *i; 01147 i = myConnections.erase(i); 01148 setConnection(lane-1, c.toEdge, c.toLane, L2L_VALIDATED, false); 01149 return; 01150 } 01151 } 01152 } 01153 } 01154 01155 01156 std::vector<int> 01157 NBEdge::getConnectionLanes(NBEdge* currentOutgoing) const { 01158 std::vector<int> ret; 01159 if (currentOutgoing!=myTurnDestination) { 01160 for (std::vector<Connection>::const_iterator i=myConnections.begin(); i!=myConnections.end(); ++i) { 01161 if ((*i).toEdge==currentOutgoing) { 01162 ret.push_back((*i).fromLane); 01163 } 01164 } 01165 } 01166 return ret; 01167 } 01168 01169 01170 const EdgeVector* 01171 NBEdge::getConnectedSorted() { 01172 // check whether connections exist and if not, use edges from the node 01173 EdgeVector outgoing; 01174 if (myConnections.size()==0) { 01175 outgoing = myTo->getOutgoingEdges(); 01176 } else { 01177 for (std::vector<Connection>::const_iterator i=myConnections.begin(); i!=myConnections.end(); ++i) { 01178 if (find(outgoing.begin(), outgoing.end(), (*i).toEdge)==outgoing.end()) { 01179 outgoing.push_back((*i).toEdge); 01180 } 01181 } 01182 } 01183 // allocate the sorted container 01184 unsigned int size = (unsigned int) outgoing.size(); 01185 EdgeVector* edges = new EdgeVector(); 01186 edges->reserve(size); 01187 for (EdgeVector::const_iterator i=outgoing.begin(); i!=outgoing.end(); i++) { 01188 NBEdge* outedge = *i; 01189 if (outedge!=0&&outedge!=myTurnDestination) { 01190 edges->push_back(outedge); 01191 } 01192 } 01193 sort(edges->begin(), edges->end(), NBContHelper::relative_edge_sorter(this, myTo)); 01194 return edges; 01195 } 01196 01197 01198 void 01199 NBEdge::divideOnEdges(const EdgeVector* outgoing) { 01200 if (outgoing->size()==0) { 01201 // we have to do this, because the turnaround may have been added before 01202 myConnections.clear(); 01203 return; 01204 } 01205 // precompute priorities; needed as some kind of assumptions for 01206 // priorities of directions (see preparePriorities) 01207 std::vector<unsigned int> *priorities = preparePriorities(outgoing); 01208 01209 // compute the sum of priorities (needed for normalisation) 01210 unsigned int prioSum = computePrioritySum(priorities); 01211 // compute the resulting number of lanes that should be used to 01212 // reach the following edge 01213 unsigned int size = (unsigned int) outgoing->size(); 01214 std::vector<SUMOReal> resultingLanes; 01215 resultingLanes.reserve(size); 01216 SUMOReal sumResulting = 0; // the sum of resulting lanes 01217 SUMOReal minResulting = 10000; // the least number of lanes to reach an edge 01218 unsigned int i; 01219 for (i=0; i<size; i++) { 01220 // res will be the number of lanes which are meant to reach the 01221 // current outgoing edge 01222 SUMOReal res = 01223 (SUMOReal)(*priorities)[i] * 01224 (SUMOReal) myLanes.size() / (SUMOReal) prioSum; 01225 // do not let this number be greater than the number of available lanes 01226 if (res>myLanes.size()) { 01227 res = (SUMOReal) myLanes.size(); 01228 } 01229 // add it to the list 01230 resultingLanes.push_back(res); 01231 sumResulting += res; 01232 if (minResulting>res) { 01233 minResulting = res; 01234 } 01235 } 01236 // compute the number of virtual edges 01237 // a virtual edge is used as a replacement for a real edge from now on 01238 // it shall ollow to divide the existing lanes on this structure without 01239 // regarding the structure of outgoing edges 01240 sumResulting += minResulting / (SUMOReal) 2.; 01241 unsigned int noVirtual = (unsigned int)(sumResulting / minResulting); 01242 // compute the transition from virtual to real edges 01243 EdgeVector transition; 01244 transition.reserve(size); 01245 for (i=0; i<size; i++) { 01246 // tmpNo will be the number of connections from this edge 01247 // to the next edge 01248 assert(i<resultingLanes.size()); 01249 SUMOReal tmpNo = (SUMOReal) resultingLanes[i] / (SUMOReal) minResulting; 01250 for (SUMOReal j=0; j<tmpNo; j++) { 01251 assert(outgoing->size()>i); 01252 transition.push_back((*outgoing)[i]); 01253 } 01254 } 01255 01256 // assign lanes to edges 01257 // (conversion from virtual to real edges is done) 01258 ToEdgeConnectionsAdder adder(transition); 01259 Bresenham::compute(&adder, static_cast<unsigned int>(myLanes.size()), noVirtual); 01260 const std::map<NBEdge*, std::vector<unsigned int> > &l2eConns = adder.getBuiltConnections(); 01261 myConnections.clear(); 01262 for (std::map<NBEdge*, std::vector<unsigned int> >::const_iterator i=l2eConns.begin(); i!=l2eConns.end(); ++i) { 01263 const std::vector<unsigned int> lanes = (*i).second; 01264 for (std::vector<unsigned int>::const_iterator j=lanes.begin(); j!=lanes.end(); ++j) { 01265 if (myAmLeftHand) { 01266 myConnections.push_back(Connection(int(myLanes.size() - 1 - *j), (*i).first, -1)); 01267 } else { 01268 myConnections.push_back(Connection(int(*j), (*i).first, -1)); 01269 } 01270 } 01271 } 01272 delete priorities; 01273 } 01274 01275 01276 std::vector<unsigned int> * 01277 NBEdge::preparePriorities(const EdgeVector* outgoing) { 01278 // copy the priorities first 01279 std::vector<unsigned int> *priorities = new std::vector<unsigned int>(); 01280 if (outgoing->size()==0) { 01281 return priorities; 01282 } 01283 priorities->reserve(outgoing->size()); 01284 EdgeVector::const_iterator i; 01285 for (i=outgoing->begin(); i!=outgoing->end(); i++) { 01286 int prio = (*i)->getJunctionPriority(myTo); 01287 assert((prio+1)*2>0); 01288 prio = (prio+1) * 2; 01289 priorities->push_back(prio); 01290 } 01291 // when the right turning direction has not a higher priority, divide 01292 // the importance by 2 due to the possibility to leave the junction 01293 // faster from this lane 01294 MainDirections mainDirections(*outgoing, this, myTo); 01295 EdgeVector tmp(*outgoing); 01296 sort(tmp.begin(), tmp.end(), NBContHelper::edge_similar_direction_sorter(this)); 01297 i=find(outgoing->begin(), outgoing->end(), *(tmp.begin())); 01298 unsigned int dist = (unsigned int) distance(outgoing->begin(), i); 01299 if (dist!=0&&!mainDirections.includes(MainDirections::DIR_RIGHTMOST)) { 01300 assert(priorities->size()>0); 01301 (*priorities)[0] = (*priorities)[0] / 2; 01302 } 01303 // HEURISTIC: 01304 // when no higher priority exists, let the forward direction be 01305 // the main direction 01306 if (mainDirections.empty()) { 01307 assert(dist<priorities->size()); 01308 (*priorities)[dist] = (*priorities)[dist] * 2; 01309 } 01310 if (mainDirections.includes(MainDirections::DIR_FORWARD)&&myLanes.size()>2) { 01311 (*priorities)[dist] = (*priorities)[dist] * 2; 01312 } 01313 // return 01314 return priorities; 01315 } 01316 01317 01318 unsigned int 01319 NBEdge::computePrioritySum(std::vector<unsigned int> *priorities) { 01320 unsigned int sum = 0; 01321 for (std::vector<unsigned int>::iterator i=priorities->begin(); i!=priorities->end(); i++) { 01322 sum += int(*i); 01323 } 01324 return sum; 01325 } 01326 01327 01328 void 01329 NBEdge::appendTurnaround(bool noTLSControlled) throw() { 01330 // do nothing if no turnaround is known 01331 if (myTurnDestination==0) { 01332 return; 01333 } 01334 // do nothing if the destination node is controlled by a tls and no turnarounds 01335 // shall be appended for such junctions 01336 if (noTLSControlled&&myTo->isTLControlled()) { 01337 return; 01338 } 01339 setConnection((unsigned int)(myLanes.size()-1), myTurnDestination, myTurnDestination->getNumLanes()-1, L2L_VALIDATED); 01340 } 01341 01342 01343 void 01344 NBEdge::sortOutgoingConnectionsByAngle() { 01345 sort(myConnections.begin(), myConnections.end(), connections_relative_edgelane_sorter(this, myTo)); 01346 } 01347 01348 01349 void 01350 NBEdge::sortOutgoingConnectionsByIndex() { 01351 sort(myConnections.begin(), myConnections.end(), connections_sorter); 01352 } 01353 01354 01355 bool 01356 NBEdge::isTurningDirectionAt(const NBNode* n, const NBEdge* const edge) const throw() { 01357 // maybe it was already set as the turning direction 01358 if (edge == myTurnDestination) { 01359 return true; 01360 } else if (myTurnDestination!=0) { 01361 // otherwise - it's not if a turning direction exists 01362 return false; 01363 } 01364 // if the same nodes are connected 01365 if (myFrom==edge->myTo &&myTo==edge->myFrom) { 01366 return true; 01367 } 01368 // we have to checke whether the connection between the nodes is 01369 // geometrically similar 01370 SUMOReal thisFromAngle2 = getAngle(*n); 01371 SUMOReal otherToAngle2 = edge->getAngle(*n); 01372 if (thisFromAngle2<otherToAngle2) { 01373 std::swap(thisFromAngle2, otherToAngle2); 01374 } 01375 if (thisFromAngle2-otherToAngle2>170&&thisFromAngle2-otherToAngle2<190) { 01376 return true; 01377 } 01378 return false; 01379 } 01380 01381 01382 01383 NBNode* 01384 NBEdge::tryGetNodeAtPosition(SUMOReal pos, SUMOReal tolerance) const { 01385 // return the from-node when the position is at the begin of the edge 01386 if (pos<tolerance) { 01387 return myFrom; 01388 } 01389 // return the to-node when the position is at the end of the edge 01390 if (pos>myLength-tolerance) { 01391 return myTo; 01392 } 01393 return 0; 01394 } 01395 01396 01397 void 01398 NBEdge::replaceInConnections(NBEdge* which, NBEdge* by, unsigned int laneOff) { 01399 UNUSED_PARAMETER(laneOff); 01400 // replace in "_connectedEdges" 01401 for (std::vector<Connection>::iterator i=myConnections.begin(); i!=myConnections.end(); ++i) { 01402 if ((*i).toEdge==which) { 01403 (*i).toEdge = by; 01404 } 01405 } 01406 // check whether it was the turn destination 01407 if (myTurnDestination==which) { 01408 myTurnDestination = by; 01409 } 01410 } 01411 01412 01413 void 01414 NBEdge::moveOutgoingConnectionsFrom(NBEdge* e, unsigned int laneOff) { 01415 unsigned int lanes = e->getNumLanes(); 01416 for (unsigned int i=0; i<lanes; i++) { 01417 std::vector<NBEdge::Connection> elv = e->getConnectionsFromLane(i); 01418 for (std::vector<NBEdge::Connection>::iterator j=elv.begin(); j!=elv.end(); j++) { 01419 NBEdge::Connection el = *j; 01420 assert(el.tlID==""); 01421 bool ok = addLane2LaneConnection(i+laneOff, el.toEdge, el.toLane, L2L_COMPUTED); 01422 assert(ok); 01423 } 01424 } 01425 } 01426 01427 01428 bool 01429 NBEdge::isConnectedTo(NBEdge* e) { 01430 if (e==myTurnDestination) { 01431 return true; 01432 } 01433 return 01434 find_if(myConnections.begin(), myConnections.end(), connections_toedge_finder(e)) 01435 != 01436 myConnections.end(); 01437 01438 } 01439 01440 01441 EdgeVector 01442 NBEdge::getConnectedEdges() const throw() { 01443 EdgeVector ret; 01444 for (std::vector<Connection>::const_iterator i=myConnections.begin(); i!=myConnections.end(); ++i) { 01445 if (find(ret.begin(), ret.end(), (*i).toEdge)==ret.end()) { 01446 ret.push_back((*i).toEdge); 01447 } 01448 } 01449 return ret; 01450 } 01451 01452 01453 void 01454 NBEdge::remapConnections(const EdgeVector& incoming) { 01455 EdgeVector connected = getConnectedEdges(); 01456 for (EdgeVector::const_iterator i=incoming.begin(); i!=incoming.end(); i++) { 01457 NBEdge* inc = *i; 01458 // We have to do this 01459 inc->myStep = EDGE2EDGES; 01460 // add all connections 01461 for (EdgeVector::iterator j=connected.begin(); j!=connected.end(); j++) { 01462 inc->addEdge2EdgeConnection(*j); 01463 } 01464 inc->removeFromConnections(this); 01465 } 01466 } 01467 01468 01469 void 01470 NBEdge::removeFromConnections(NBEdge* toEdge, int fromLane, int toLane) { 01471 // remove from "myConnections" 01472 for (std::vector<Connection>::iterator i=myConnections.begin(); i!=myConnections.end();) { 01473 Connection& c = *i; 01474 if (c.toEdge==toEdge 01475 && (fromLane<0 || c.fromLane==fromLane) 01476 && (toLane<0 || c.toLane==toLane)) { 01477 i = myConnections.erase(i); 01478 } else { 01479 ++i; 01480 } 01481 } 01482 // check whether it was the turn destination 01483 if (myTurnDestination==toEdge && fromLane<0) { 01484 myTurnDestination = 0; 01485 } 01486 } 01487 01488 01489 void 01490 NBEdge::invalidateConnections(bool reallowSetting) { 01491 myTurnDestination = 0; 01492 myConnections.clear(); 01493 if (reallowSetting) { 01494 myStep = INIT; 01495 } else { 01496 myStep = INIT_REJECT_CONNECTIONS; 01497 } 01498 } 01499 01500 01501 bool 01502 NBEdge::lanesWereAssigned() const { 01503 return myStep==LANES2LANES_DONE||myStep==LANES2LANES_USER; 01504 } 01505 01506 01507 SUMOReal 01508 NBEdge::getMaxLaneOffset() { 01509 return (SUMOReal) SUMO_const_laneWidthAndOffset * myLanes.size(); 01510 } 01511 01512 01513 Position 01514 NBEdge::getMinLaneOffsetPositionAt(NBNode* node, SUMOReal width) const { 01515 const PositionVector& shape0 = myLanes[0].shape; 01516 const PositionVector& shapel = myLanes.back().shape; 01517 width = width < shape0.length()/(SUMOReal) 2.0 01518 ? width 01519 : shape0.length()/(SUMOReal) 2.0; 01520 if (node==myFrom) { 01521 Position pos = shapel.positionAtLengthPosition(width); 01522 GeomHelper::transfer_to_side(pos, shapel[0], shapel[-1], SUMO_const_halfLaneAndOffset); 01523 return pos; 01524 } else { 01525 Position pos = shape0.positionAtLengthPosition(shape0.length() - width); 01526 GeomHelper::transfer_to_side(pos, shape0[-1], shape0[0], SUMO_const_halfLaneAndOffset); 01527 return pos; 01528 } 01529 } 01530 01531 01532 Position 01533 NBEdge::getMaxLaneOffsetPositionAt(NBNode* node, SUMOReal width) const { 01534 const PositionVector& shape0 = myLanes[0].shape; 01535 const PositionVector& shapel = myLanes.back().shape; 01536 width = width < shape0.length()/(SUMOReal) 2.0 01537 ? width 01538 : shape0.length()/(SUMOReal) 2.0; 01539 if (node==myFrom) { 01540 Position pos = shape0.positionAtLengthPosition(width); 01541 GeomHelper::transfer_to_side(pos, shape0[0], shape0[-1], -SUMO_const_halfLaneAndOffset); 01542 return pos; 01543 } else { 01544 Position pos = shapel.positionAtLengthPosition(shapel.length() - width); 01545 GeomHelper::transfer_to_side(pos, shapel[-1], shapel[0], -SUMO_const_halfLaneAndOffset); 01546 return pos; 01547 } 01548 } 01549 01550 01551 bool 01552 NBEdge::mayBeTLSControlled(int fromLane, NBEdge* toEdge, int toLane) const throw() { 01553 TLSDisabledConnection tpl; 01554 tpl.fromLane = fromLane; 01555 tpl.to = toEdge; 01556 tpl.toLane = toLane; 01557 std::vector<TLSDisabledConnection>::const_iterator i = find_if(myTLSDisabledConnections.begin(), myTLSDisabledConnections.end(), tls_disable_finder(tpl)); 01558 return i==myTLSDisabledConnections.end(); 01559 } 01560 01561 01562 bool 01563 NBEdge::setControllingTLInformation(const NBConnection& c, const std::string& tlID) { 01564 int fromLane = c.getFromLane(); 01565 NBEdge* toEdge = c.getTo(); 01566 int toLane = c.getToLane(); 01567 int tlIndex = c.getTLIndex(); 01568 // check whether the connection was not set as not to be controled previously 01569 TLSDisabledConnection tpl; 01570 tpl.fromLane = fromLane; 01571 tpl.to = toEdge; 01572 tpl.toLane = toLane; 01573 std::vector<TLSDisabledConnection>::iterator i = find_if(myTLSDisabledConnections.begin(), myTLSDisabledConnections.end(), tls_disable_finder(tpl)); 01574 if (i!=myTLSDisabledConnections.end()) { 01575 return false; 01576 } 01577 01578 assert(fromLane<0||fromLane<(int) myLanes.size()); 01579 // try to use information about the connections if given 01580 if (fromLane>=0&&toLane>=0) { 01581 // find the specified connection 01582 std::vector<Connection>::iterator i = 01583 find_if(myConnections.begin(), myConnections.end(), connections_finder(fromLane, toEdge, toLane)); 01584 // ok, we have to test this as on the removal of dummy edges some connections 01585 // will be reassigned 01586 if (i!=myConnections.end()) { 01587 // get the connection 01588 Connection& connection = *i; 01589 // set the information about the tl 01590 connection.tlID = tlID; 01591 connection.tlLinkNo = tlIndex; 01592 return true; 01593 } 01594 } 01595 // if the original connection was not found, set the information for all 01596 // connections 01597 unsigned int no = 0; 01598 bool hadError = false; 01599 for (std::vector<Connection>::iterator i=myConnections.begin(); i!=myConnections.end(); ++i) { 01600 if ((*i).toEdge!=toEdge) { 01601 continue; 01602 } 01603 if (fromLane>=0&&fromLane!=(*i).fromLane) { 01604 continue; 01605 } 01606 if (toLane>=0&&toLane!=(*i).toLane) { 01607 continue; 01608 } 01609 if ((*i).tlID=="") { 01610 (*i).tlID = tlID; 01611 (*i).tlLinkNo = tlIndex; 01612 no++; 01613 } else { 01614 if ((*i).tlID!=tlID&&(*i).tlLinkNo==tlIndex) { 01615 WRITE_WARNING("The lane " + toString<int>((*i).fromLane)+ " on edge " + getID()+ " already had a traffic light signal."); 01616 hadError = true; 01617 } 01618 } 01619 } 01620 if (hadError&&no==0) { 01621 WRITE_WARNING("Could not set any signal of the traffic light '" + tlID + "' (unknown group)"); 01622 } 01623 return true; 01624 } 01625 01626 01627 void 01628 NBEdge::clearControllingTLInformation() { 01629 for (std::vector<Connection>::iterator it=myConnections.begin(); it!=myConnections.end(); it++) { 01630 it->tlID = ""; 01631 } 01632 } 01633 01634 01635 void 01636 NBEdge::disableConnection4TLS(int fromLane, NBEdge* toEdge, int toLane) { 01637 TLSDisabledConnection c; 01638 c.fromLane = fromLane; 01639 c.to = toEdge; 01640 c.toLane = toLane; 01641 myTLSDisabledConnections.push_back(c); 01642 } 01643 01644 01645 PositionVector 01646 NBEdge::getCWBoundaryLine(const NBNode& n, SUMOReal offset) const { 01647 PositionVector ret; 01648 if (myFrom==(&n)) { 01649 // outgoing 01650 ret = !myAmLeftHand ? myLanes[0].shape : myLanes.back().shape; 01651 } else { 01652 // incoming 01653 ret = !myAmLeftHand ? myLanes.back().shape.reverse() : myLanes[0].shape.reverse(); 01654 } 01655 ret.move2side(offset); 01656 return ret; 01657 } 01658 01659 01660 PositionVector 01661 NBEdge::getCCWBoundaryLine(const NBNode& n, SUMOReal offset) const { 01662 PositionVector ret; 01663 if (myFrom==(&n)) { 01664 // outgoing 01665 ret = !myAmLeftHand ? myLanes.back().shape : myLanes[0].shape; 01666 } else { 01667 // incoming 01668 ret = !myAmLeftHand ? myLanes[0].shape.reverse() : myLanes.back().shape.reverse(); 01669 } 01670 ret.move2side(-offset); 01671 return ret; 01672 } 01673 01674 01675 SUMOReal 01676 NBEdge::width() const { 01677 return (SUMOReal) myLanes.size() * SUMO_const_laneWidth + (SUMOReal)(myLanes.size()-1) * SUMO_const_laneOffset; 01678 } 01679 01680 01681 bool 01682 NBEdge::expandableBy(NBEdge* possContinuation) const { 01683 // ok, the number of lanes must match 01684 if (myLanes.size()!=possContinuation->myLanes.size()) { 01685 return false; 01686 } 01687 // the priority, too (?) 01688 if (getPriority()!=possContinuation->getPriority()) { 01689 return false; 01690 } 01691 // the speed allowed 01692 if (mySpeed!=possContinuation->mySpeed) { 01693 return false; 01694 } 01695 // the vehicle class constraints, too 01703 // also, check whether the connections - if any exit do allow to join 01704 // both edges 01705 // This edge must have a one-to-one connection to the following lanes 01706 switch (myStep) { 01707 case INIT_REJECT_CONNECTIONS: 01708 break; 01709 case INIT: 01710 break; 01711 case EDGE2EDGES: { 01712 // the following edge must be connected 01713 const EdgeVector& conn = getConnectedEdges(); 01714 if (find(conn.begin(), conn.end(), possContinuation) 01715 ==conn.end()) { 01716 01717 return false; 01718 } 01719 } 01720 break; 01721 case LANES2EDGES: 01722 case LANES2LANES_RECHECK: 01723 case LANES2LANES_DONE: 01724 case LANES2LANES_USER: { 01725 // the possible continuation must be connected 01726 if (find_if(myConnections.begin(), myConnections.end(), connections_toedge_finder(possContinuation))==myConnections.end()) { 01727 return false; 01728 } 01729 // all lanes must go to the possible continuation 01730 std::vector<int> conns = getConnectionLanes(possContinuation); 01731 if (conns.size()!=myLanes.size()) { 01732 return false; 01733 } 01734 } 01735 break; 01736 default: 01737 break; 01738 } 01739 return true; 01740 } 01741 01742 01743 void 01744 NBEdge::append(NBEdge* e) { 01745 // append geometry 01746 myGeom.appendWithCrossingPoint(e->myGeom); 01747 for (unsigned int i=0; i<myLanes.size(); i++) { 01748 myLanes[i].shape.appendWithCrossingPoint(e->myLanes[i].shape); 01749 } 01750 // recompute length 01751 myLength += e->myLength; 01752 // copy the connections and the building step if given 01753 myStep = e->myStep; 01754 myConnections = e->myConnections; 01755 myTurnDestination = e->myTurnDestination; 01756 // set the node 01757 myTo = e->myTo; 01758 } 01759 01760 01761 01762 01763 01764 bool 01765 NBEdge::hasSignalisedConnectionTo(const NBEdge* const e) const throw() { 01766 for (std::vector<Connection>::const_iterator i=myConnections.begin(); i!=myConnections.end(); ++i) { 01767 if ((*i).toEdge==e && (*i).tlID!="") { 01768 return true; 01769 } 01770 } 01771 return false; 01772 } 01773 01774 01775 NBEdge* 01776 NBEdge::getTurnDestination() const { 01777 return myTurnDestination; 01778 } 01779 01780 01781 std::string 01782 NBEdge::getLaneID(unsigned int lane) const { 01783 assert(lane<myLanes.size()); 01784 return myID + "_" + toString(lane); 01785 } 01786 01787 01788 bool 01789 NBEdge::isNearEnough2BeJoined2(NBEdge* e, SUMOReal threshold) const { 01790 DoubleVector distances = myGeom.distances(e->getGeometry()); 01791 assert(distances.size() > 0); 01792 return VectorHelper<SUMOReal>::maxValue(distances) < threshold; 01793 } 01794 01795 01796 SUMOReal 01797 NBEdge::getNormedAngle(const NBNode& atNode) const { 01798 SUMOReal angle = getAngle(atNode); 01799 if (angle<0) { 01800 angle = 360 + angle; 01801 } 01802 assert(angle>=0&&angle<=360); 01803 return angle; 01804 } 01805 01806 01807 SUMOReal 01808 NBEdge::getNormedAngle() const { 01809 SUMOReal angle = myAngle; 01810 if (angle<0) { 01811 angle = 360 + angle; 01812 } 01813 assert(angle>=0&&angle<360); 01814 return angle; 01815 } 01816 01817 01818 void 01819 NBEdge::incLaneNo(unsigned int by) { 01820 unsigned int newLaneNo = (unsigned int) myLanes.size() + by; 01821 while (myLanes.size()<newLaneNo) { 01822 Lane l; 01823 l.speed = mySpeed; 01824 l.offset = myOffset; 01825 l.width = myWidth; 01826 myLanes.push_back(l); 01827 } 01828 computeLaneShapes(); 01829 const EdgeVector& incs = myFrom->getIncomingEdges(); 01830 for (EdgeVector::const_iterator i=incs.begin(); i!=incs.end(); ++i) { 01831 (*i)->invalidateConnections(true); 01832 } 01833 invalidateConnections(true); 01834 } 01835 01836 01837 void 01838 NBEdge::decLaneNo(unsigned int by, int dir) { 01839 unsigned int newLaneNo = (unsigned int) myLanes.size() - by; 01840 while (myLanes.size()>newLaneNo) { 01841 myLanes.pop_back(); 01842 } 01843 computeLaneShapes(); 01844 const EdgeVector& incs = myFrom->getIncomingEdges(); 01845 for (EdgeVector::const_iterator i=incs.begin(); i!=incs.end(); ++i) { 01846 (*i)->invalidateConnections(true); 01847 } 01848 if (dir==0) { 01849 invalidateConnections(true); 01850 } else { 01851 const EdgeVector& outs = myTo->getOutgoingEdges(); 01852 assert(outs.size()==1); 01853 NBEdge* out = outs[0]; 01854 if (dir<0) { 01855 removeFromConnections(out, 0); 01856 } else { 01857 removeFromConnections(out, (int) myLanes.size()); 01858 } 01859 } 01860 } 01861 01862 01863 void 01864 NBEdge::copyConnectionsFrom(NBEdge* src) { 01865 myStep = src->myStep; 01866 myConnections = src->myConnections; 01867 } 01868 01869 01870 void 01871 NBEdge::markAsInLane2LaneState() { 01872 assert(myTo->getOutgoingEdges().size()==0); 01873 myStep = LANES2LANES_DONE; 01874 } 01875 01876 01877 void 01878 NBEdge::allowVehicleClass(int lane, SUMOVehicleClass vclass) { 01879 if (lane<0) { 01880 // if all lanes are meant... 01881 for (unsigned int i=0; i<myLanes.size(); i++) { 01882 // ... do it for each lane 01883 allowVehicleClass((int) i, vclass); 01884 } 01885 return; 01886 } 01887 assert(lane<(int) myLanes.size()); 01888 myLanes[lane].allowed.insert(vclass); 01889 if (myLanes[lane].notAllowed.count(vclass) > 0) { 01890 // overrride earlier disallow 01891 myLanes[lane].notAllowed.erase(vclass); 01892 WRITE_WARNING("Overriding previous '" + toString(SUMO_ATTR_DISALLOW) + "=" + 01893 toString(vclass) + "' for lane '" + getLaneID(lane) + "'.") 01894 } 01895 } 01896 01897 01898 void 01899 NBEdge::disallowVehicleClass(int lane, SUMOVehicleClass vclass) { 01900 if (lane<0) { 01901 // if all lanes are meant... 01902 for (unsigned int i=0; i<myLanes.size(); i++) { 01903 // ... do it for each lane 01904 disallowVehicleClass((int) i, vclass); 01905 } 01906 return; 01907 } 01908 assert(lane<(int) myLanes.size()); 01909 myLanes[lane].notAllowed.insert(vclass); 01910 if (myLanes[lane].allowed.count(vclass) > 0) { 01911 // overrride earlier allow 01912 myLanes[lane].allowed.erase(vclass); 01913 WRITE_WARNING("Overriding previous '" + toString(SUMO_ATTR_ALLOW) + "=" + 01914 toString(vclass) + "' for lane '" + getLaneID(lane) + "'.") 01915 } 01916 } 01917 01918 01919 void 01920 NBEdge::preferVehicleClass(int lane, SUMOVehicleClass vclass) { 01921 if (lane<0) { 01922 // if all lanes are meant... 01923 for (unsigned int i=0; i<myLanes.size(); i++) { 01924 // ... do it for each lane 01925 preferVehicleClass((int) i, vclass); 01926 } 01927 return; 01928 } 01929 assert(lane<(int) myLanes.size()); 01930 myLanes[lane].preferred.insert(vclass); 01931 } 01932 01933 01934 void 01935 NBEdge::setWidth(int lane, SUMOReal width) { 01936 if (lane<0) { 01937 // all lanes are meant... 01938 myWidth = width; 01939 for (unsigned int i=0; i<myLanes.size(); i++) { 01940 // ... do it for each lane 01941 setWidth((int) i, width); 01942 } 01943 return; 01944 } 01945 assert(lane<(int) myLanes.size()); 01946 myLanes[lane].width = width; 01947 } 01948 01949 01950 void 01951 NBEdge::setOffset(int lane, SUMOReal offset) { 01952 if (lane<0) { 01953 // all lanes are meant... 01954 myOffset = offset; 01955 for (unsigned int i=0; i<myLanes.size(); i++) { 01956 // ... do it for each lane 01957 setOffset((int) i, offset); 01958 } 01959 return; 01960 } 01961 assert(lane<(int) myLanes.size()); 01962 myLanes[lane].offset = offset; 01963 } 01964 01965 01966 void 01967 NBEdge::setSpeed(int lane, SUMOReal speed) { 01968 if (lane<0) { 01969 // all lanes are meant... 01970 mySpeed = speed; 01971 for (unsigned int i=0; i<myLanes.size(); i++) { 01972 // ... do it for each lane 01973 setOffset((int) i, speed); 01974 } 01975 return; 01976 } 01977 assert(lane<(int) myLanes.size()); 01978 myLanes[lane].speed = speed; 01979 } 01980 01981 01982 void 01983 NBEdge::setVehicleClasses(const SUMOVehicleClasses& allowed, const SUMOVehicleClasses& disallowed, int lane) { 01984 for (SUMOVehicleClasses::const_iterator i=allowed.begin(); i!=allowed.end(); ++i) { 01985 allowVehicleClass(lane, *i); 01986 } 01987 for (SUMOVehicleClasses::const_iterator i=disallowed.begin(); i!=disallowed.end(); ++i) { 01988 disallowVehicleClass(lane, *i); 01989 } 01990 } 01991 01992 01993 SUMOVehicleClasses 01994 NBEdge::getAllowedVehicleClasses() const { 01995 SUMOVehicleClasses ret; 01996 for (std::vector<Lane>::const_iterator i=myLanes.begin(); i!=myLanes.end(); ++i) { 01997 const SUMOVehicleClasses& allowed = (*i).allowed; 01998 ret.insert(allowed.begin(), allowed.end()); 01999 } 02000 return ret; 02001 } 02002 02003 02004 SUMOVehicleClasses 02005 NBEdge::getDisallowedVehicleClasses() const { 02006 SUMOVehicleClasses ret; 02007 for (std::vector<Lane>::const_iterator i=myLanes.begin(); i!=myLanes.end(); ++i) { 02008 const SUMOVehicleClasses& notAllowed = (*i).notAllowed; 02009 ret.insert(notAllowed.begin(), notAllowed.end()); 02010 } 02011 return ret; 02012 } 02013 02014 02015 SUMOVehicleClasses 02016 NBEdge::getAllowedVehicleClasses(unsigned int lane) const { 02017 assert(lane < myLanes.size()); 02018 return myLanes[lane].allowed; 02019 } 02020 02021 02022 SUMOVehicleClasses 02023 NBEdge::getDisallowedVehicleClasses(unsigned int lane) const { 02024 assert(lane < myLanes.size()); 02025 return myLanes[lane].notAllowed; 02026 } 02027 02028 02029 int 02030 NBEdge::getMinConnectedLane(NBEdge* of) const { 02031 int ret = -1; 02032 for (std::vector<Connection>::const_iterator i=myConnections.begin(); i!=myConnections.end(); ++i) { 02033 if ((*i).toEdge==of && (ret==-1 || (*i).toLane<ret)) { 02034 ret = (*i).toLane; 02035 } 02036 } 02037 return ret; 02038 } 02039 02040 02041 int 02042 NBEdge::getMaxConnectedLane(NBEdge* of) const { 02043 int ret = -1; 02044 for (std::vector<Connection>::const_iterator i=myConnections.begin(); i!=myConnections.end(); ++i) { 02045 if ((*i).toEdge==of && (*i).toLane>ret) { 02046 ret = (*i).toLane; 02047 } 02048 } 02049 return ret; 02050 } 02051 02052 02053 void 02054 NBEdge::setLoadedLength(SUMOReal val) { 02055 myLoadedLength = val; 02056 } 02057 02058 02059 void 02060 NBEdge::dismissVehicleClassInformation() { 02061 for (std::vector<Lane>::iterator i=myLanes.begin(); i!=myLanes.end(); ++i) { 02062 (*i).allowed.clear(); 02063 (*i).notAllowed.clear(); 02064 (*i).preferred.clear(); 02065 } 02066 } 02067 02068 02069 /****************************************************************************/