SUMO - Simulation of Urban MObility
NBEdge.cpp
Go to the documentation of this file.
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 /****************************************************************************/
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines