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