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), 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 /****************************************************************************/
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines