NBEdge.cpp

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

Generated on Wed May 5 00:06:33 2010 for Sumo - Simulation of Urban MObility by  doxygen 1.5.6