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