NBNode.cpp

Go to the documentation of this file.
00001 /****************************************************************************/
00007 // The representation of a single node
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 <string>
00031 #include <map>
00032 #include <cassert>
00033 #include <algorithm>
00034 #include <vector>
00035 #include <deque>
00036 #include <set>
00037 #include <cmath>
00038 #include <utils/common/UtilExceptions.h>
00039 #include <utils/common/StringUtils.h>
00040 #include <utils/options/OptionsCont.h>
00041 #include <utils/geom/Line2D.h>
00042 #include <utils/geom/GeomHelper.h>
00043 #include <utils/geom/bezier.h>
00044 #include <utils/common/MsgHandler.h>
00045 #include <utils/common/StdDefs.h>
00046 #include <utils/common/ToString.h>
00047 #include <utils/geom/GeoConvHelper.h>
00048 #include <utils/iodevices/OutputDevice.h>
00049 #include <iomanip>
00050 #include "NBNode.h"
00051 #include "NBNodeCont.h"
00052 #include "NBNodeShapeComputer.h"
00053 #include "NBEdgeCont.h"
00054 #include "NBTypeCont.h"
00055 #include "NBJunctionLogicCont.h"
00056 #include "NBHelpers.h"
00057 #include "NBDistrict.h"
00058 #include "NBContHelper.h"
00059 #include "NBRequest.h"
00060 #include "NBOwnTLDef.h"
00061 #include "NBTrafficLightLogicCont.h"
00062 
00063 #ifdef CHECK_MEMORY_LEAKS
00064 #include <foreign/nvwa/debug_new.h>
00065 #endif // CHECK_MEMORY_LEAKS
00066 
00067 
00068 // ===========================================================================
00069 // some constant defnitions
00070 // ===========================================================================
00072 #define NO_INTERNAL_POINTS 5
00073 
00074 
00075 // ===========================================================================
00076 // method definitions
00077 // ===========================================================================
00078 /* -------------------------------------------------------------------------
00079  * NBNode::ApproachingDivider-methods
00080  * ----------------------------------------------------------------------- */
00081 NBNode::ApproachingDivider::ApproachingDivider(
00082     std::vector<NBEdge*> *approaching, NBEdge *currentOutgoing) throw()
00083         : myApproaching(approaching), myCurrentOutgoing(currentOutgoing) {
00084     // check whether origin lanes have been given
00085     assert(myApproaching!=0);
00086 }
00087 
00088 
00089 NBNode::ApproachingDivider::~ApproachingDivider() throw() {}
00090 
00091 
00092 void
00093 NBNode::ApproachingDivider::execute(SUMOReal src, SUMOReal dest) throw() {
00094     assert(myApproaching->size()>src);
00095     // get the origin edge
00096     NBEdge *incomingEdge = (*myApproaching)[(int) src];
00097     if (incomingEdge->getStep()==NBEdge::LANES2LANES_DONE||incomingEdge->getStep()==NBEdge::LANES2LANES_USER) {
00098         return;
00099     }
00100     std::vector<int> approachingLanes =
00101         incomingEdge->getConnectionLanes(myCurrentOutgoing);
00102     assert(approachingLanes.size()!=0);
00103     std::deque<int> *approachedLanes = spread(approachingLanes, dest);
00104     assert(approachedLanes->size()<=myCurrentOutgoing->getNoLanes());
00105     // set lanes
00106     for (unsigned int i=0; i<approachedLanes->size(); i++) {
00107         unsigned int approached = (*approachedLanes)[i];
00108         assert(approachedLanes->size()>i);
00109         assert(approachingLanes.size()>i);
00110         incomingEdge->setConnection((unsigned int) approachingLanes[i], myCurrentOutgoing,
00111                                     approached, NBEdge::L2L_COMPUTED);
00112     }
00113     delete approachedLanes;
00114 }
00115 
00116 
00117 std::deque<int> *
00118 NBNode::ApproachingDivider::spread(const std::vector<int> &approachingLanes,
00119                                    SUMOReal dest) const {
00120     std::deque<int> *ret = new std::deque<int>();
00121     unsigned int noLanes = (unsigned int) approachingLanes.size();
00122     // when only one lane is approached, we check, whether the SUMOReal-value
00123     //  is assigned more to the left or right lane
00124     if (noLanes==1) {
00125         if ((int)(dest+0.5)>dest) {
00126             ret->push_back((int)(dest+1));
00127         } else {
00128             ret->push_back((int) dest);
00129         }
00130         return ret;
00131     }
00132 
00133     unsigned int noOutgoingLanes = myCurrentOutgoing->getNoLanes();
00134     //
00135     ret->push_back((int) dest);
00136     unsigned int noSet = 1;
00137     SUMOReal roffset = 1;
00138     SUMOReal loffset = 1;
00139     while (noSet<noLanes) {
00140         // It may be possible, that there are not enough lanes the source
00141         //  lanes may be divided on
00142         //  In this case, they remain unset
00143         //  !!! this is only a hack. It is possible, that this yields in
00144         //   uncommon divisions
00145         if (noOutgoingLanes==noSet)
00146             return ret;
00147 
00148         // as due to the conversion of SUMOReal->uint the numbers will be lower
00149         //  than they should be, we try to append to the left side first
00150         //
00151         // check whether the left boundary of the approached street has
00152         //  been overridden; if so, move all lanes to the right
00153         if (((size_t) dest+loffset)>=noOutgoingLanes) {
00154             loffset -= 1;
00155             roffset += 1;
00156             for (unsigned int i=0; i<ret->size(); i++) {
00157                 (*ret)[i] = (*ret)[i] - 1;
00158             }
00159         }
00160         // append the next lane to the left of all edges
00161         //  increase the position (destination edge)
00162         ret->push_back((int)(dest+loffset));
00163         noSet++;
00164         loffset += 1;
00165 
00166         // as above
00167         if (noOutgoingLanes==noSet)
00168             return ret;
00169 
00170         // now we try to append the next lane to the right side, when needed
00171         if (noSet<noLanes) {
00172             // check whether the right boundary of the approached street has
00173             //  been overridden; if so, move all lanes to the right
00174             if (((size_t) dest-roffset)<0) {
00175                 loffset += 1;
00176                 roffset -= 1;
00177                 for (unsigned int i=0; i<ret->size(); i++) {
00178                     (*ret)[i] = (*ret)[i] + 1;
00179                 }
00180             }
00181             ret->push_front((int)(dest-roffset));
00182             noSet++;
00183             roffset += 1;
00184         }
00185     }
00186     return ret;
00187 }
00188 
00189 
00190 
00191 
00192 /* -------------------------------------------------------------------------
00193  * NBNode-methods
00194  * ----------------------------------------------------------------------- */
00195 NBNode::NBNode(const std::string &id, const Position2D &position) throw()
00196         : myID(StringUtils::convertUmlaute(id)), myPosition(position),
00197         myType(NODETYPE_UNKNOWN), myDistrict(0), myRequest(0) {
00198     myIncomingEdges = new EdgeVector();
00199     myOutgoingEdges = new EdgeVector();
00200 }
00201 
00202 
00203 NBNode::NBNode(const std::string &id, const Position2D &position,
00204                BasicNodeType type) throw()
00205         : myID(StringUtils::convertUmlaute(id)), myPosition(position),
00206         myType(type), myDistrict(0), myRequest(0) {
00207     myIncomingEdges = new EdgeVector();
00208     myOutgoingEdges = new EdgeVector();
00209 }
00210 
00211 
00212 NBNode::NBNode(const std::string &id, const Position2D &position, NBDistrict *district) throw()
00213         : myID(StringUtils::convertUmlaute(id)), myPosition(position),
00214         myType(NODETYPE_DISTRICT), myDistrict(district), myRequest(0) {
00215     myIncomingEdges = new EdgeVector();
00216     myOutgoingEdges = new EdgeVector();
00217 }
00218 
00219 
00220 NBNode::~NBNode() throw() {
00221     delete myIncomingEdges;
00222     delete myOutgoingEdges;
00223     delete myRequest;
00224 }
00225 
00226 
00227 void
00228 NBNode::reinit(const Position2D &position, BasicNodeType type) throw() {
00229     myPosition = position;
00230     // patch type
00231     myType = type;
00232     if (myType!=NODETYPE_TRAFFIC_LIGHT) {
00233         removeTrafficLights();
00234     }
00235 }
00236 
00237 
00238 
00239 // -----------  Methods for dealing with assigned traffic lights
00240 void
00241 NBNode::addTrafficLight(NBTrafficLightDefinition *tld) throw() {
00242     myTrafficLights.insert(tld);
00243 }
00244 
00245 
00246 void
00247 NBNode::removeTrafficLights() throw() {
00248     for (std::set<NBTrafficLightDefinition*>::const_iterator i=myTrafficLights.begin(); i!=myTrafficLights.end(); ++i) {
00249         (*i)->removeNode(this);
00250     }
00251     myTrafficLights.clear();
00252 }
00253 
00254 
00255 bool
00256 NBNode::isJoinedTLSControlled() const throw() {
00257     if (!isTLControlled()) {
00258         return false;
00259     }
00260     for (std::set<NBTrafficLightDefinition*>::const_iterator i=myTrafficLights.begin(); i!=myTrafficLights.end(); ++i) {
00261         if ((*i)->getID().find("joined")==0) {
00262             return true;
00263         }
00264     }
00265     return false;
00266 }
00267 
00268 
00269 // -----------
00270 void
00271 NBNode::addIncomingEdge(NBEdge *edge) {
00272     assert(edge!=0);
00273     if (find(myIncomingEdges->begin(), myIncomingEdges->end(), edge)==myIncomingEdges->end()) {
00274         myIncomingEdges->push_back(edge);
00275         myAllEdges.push_back(edge);
00276     }
00277 }
00278 
00279 
00280 void
00281 NBNode::addOutgoingEdge(NBEdge *edge) {
00282     assert(edge!=0);
00283     if (find(myOutgoingEdges->begin(), myOutgoingEdges->end(), edge)==myOutgoingEdges->end()) {
00284         myOutgoingEdges->push_back(edge);
00285         myAllEdges.push_back(edge);
00286     }
00287 }
00288 
00289 
00290 bool
00291 NBNode::swapWhenReversed(bool leftHand,
00292                          const std::vector<NBEdge*>::iterator &i1,
00293                          const std::vector<NBEdge*>::iterator &i2) {
00294     NBEdge *e1 = *i1;
00295     NBEdge *e2 = *i2;
00296     if (leftHand) {
00297         if (e1->getToNode()==this && e1->isTurningDirectionAt(this, e2)) {
00298             std::swap(*i1, *i2);
00299             return true;
00300         }
00301     } else {
00302         if (e2->getToNode()==this && e2->isTurningDirectionAt(this, e1)) {
00303             std::swap(*i1, *i2);
00304             return true;
00305         }
00306     }
00307     return false;
00308 }
00309 
00310 void
00311 NBNode::setPriorities() {
00312     // reset all priorities
00313     std::vector<NBEdge*>::iterator i;
00314     // check if the junction is not a real junction
00315     if (myIncomingEdges->size()==1&&myOutgoingEdges->size()==1) {
00316         for (i=myAllEdges.begin(); i!=myAllEdges.end(); i++) {
00317             (*i)->setJunctionPriority(this, 1);
00318         }
00319         return;
00320     }
00321     // preset all junction's edge priorities to zero
00322     for (i=myAllEdges.begin(); i!=myAllEdges.end(); i++) {
00323         (*i)->setJunctionPriority(this, 0);
00324     }
00325     // compute the priorities on junction when needed
00326     if (myType!=NODETYPE_RIGHT_BEFORE_LEFT) {
00327         setPriorityJunctionPriorities();
00328     }
00329 }
00330 
00331 
00332 NBNode::BasicNodeType
00333 NBNode::computeType(const NBTypeCont &tc) const {
00334     // the type may already be set from the data
00335     if (myType!=NODETYPE_UNKNOWN) {
00336         return myType;
00337     }
00338     // check whether the junction is not a real junction
00339     if (myIncomingEdges->size()==1) {
00340         return NODETYPE_PRIORITY_JUNCTION;
00341     }
00342     if (isSimpleContinuation()) {
00343         return NODETYPE_PRIORITY_JUNCTION;
00344     }
00345     // choose the uppermost type as default
00346     BasicNodeType type = NODETYPE_RIGHT_BEFORE_LEFT;
00347     // determine the type
00348     for (std::vector<NBEdge*>::const_iterator i=myIncomingEdges->begin(); i!=myIncomingEdges->end(); i++) {
00349         for (std::vector<NBEdge*>::const_iterator j=i+1; j!=myIncomingEdges->end(); j++) {
00350             bool isOpposite = false;
00351             if (getOppositeIncoming(*j)==*i&&myIncomingEdges->size()>2) {
00352                 isOpposite = true;
00353             }
00354 
00355             // This usage of defaults is not very well, still we do not have any
00356             //  methods for the conversion of foreign, sometimes not supplied
00357             //  road types into an own format
00358             BasicNodeType tmptype = type;
00359             if (!isOpposite) {
00360                 tmptype = tc.getJunctionType((*i)->getSpeed(), (*j)->getSpeed());
00361                 if (tmptype<type&&tmptype!=NODETYPE_UNKNOWN&&tmptype!=NODETYPE_NOJUNCTION) {
00362                     type = tmptype;
00363                 }
00364             }
00365         }
00366     }
00367     return type;
00368 }
00369 
00370 
00371 bool
00372 NBNode::isSimpleContinuation() const {
00373     // one in, one out->continuation
00374     if (myIncomingEdges->size()==1&&myOutgoingEdges->size()==1) {
00375         // both must have the same number of lanes
00376         return (*(myIncomingEdges->begin()))->getNoLanes()==(*(myOutgoingEdges->begin()))->getNoLanes();
00377     }
00378     // two in and two out and both in reverse direction
00379     if (myIncomingEdges->size()==2&&myOutgoingEdges->size()==2) {
00380         for (EdgeVector::const_iterator i=myIncomingEdges->begin(); i!=myIncomingEdges->end(); i++) {
00381             NBEdge *in = *i;
00382             EdgeVector::const_iterator opposite = find_if(myOutgoingEdges->begin(), myOutgoingEdges->end(), NBContHelper::opposite_finder(in, this));
00383             // must have an opposite edge
00384             if (opposite==myOutgoingEdges->end()) {
00385                 return false;
00386             }
00387             // both must have the same number of lanes
00388             NBContHelper::nextCW(myOutgoingEdges, opposite);
00389             if (in->getNoLanes()!=(*opposite)->getNoLanes()) {
00390                 return false;
00391             }
00392         }
00393         return true;
00394     }
00395     // nope
00396     return false;
00397 }
00398 
00399 
00400 bool
00401 samePriority(NBEdge *e1, NBEdge *e2) {
00402     if (e1==e2) {
00403         return true;
00404     }
00405     if (e1->getPriority()!=e2->getPriority()) {
00406         return false;
00407     }
00408     if ((int) e1->getSpeed()!=(int) e2->getSpeed()) {
00409         return false;
00410     }
00411     return (int) e1->getNoLanes()==(int) e2->getNoLanes();
00412 }
00413 
00414 
00415 void
00416 NBNode::setPriorityJunctionPriorities() {
00417     if (myIncomingEdges->size()==0||myOutgoingEdges->size()==0) {
00418         return;
00419     }
00420     std::vector<NBEdge*> incoming(*myIncomingEdges);
00421     std::vector<NBEdge*> outgoing(*myOutgoingEdges);
00422     // what we do want to have is to extract the pair of roads that are
00423     //  the major roads for this junction
00424     // let's get the list of incoming edges with the highest priority
00425     std::sort(incoming.begin(), incoming.end(), NBContHelper::edge_by_priority_sorter());
00426     std::vector<NBEdge*> bestIncoming;
00427     NBEdge *best = incoming[0];
00428     while (incoming.size()>0&&samePriority(best, incoming[0])) {
00429         bestIncoming.push_back(*incoming.begin());
00430         incoming.erase(incoming.begin());
00431     }
00432     // now, let's get the list of best outgoing
00433     assert(outgoing.size()!=0);
00434     sort(outgoing.begin(), outgoing.end(), NBContHelper::edge_by_priority_sorter());
00435     std::vector<NBEdge*> bestOutgoing;
00436     best = outgoing[0];
00437     while (outgoing.size()>0&&samePriority(best, outgoing[0])) {//->getPriority()==best->getPriority()) {
00438         bestOutgoing.push_back(*outgoing.begin());
00439         outgoing.erase(outgoing.begin());
00440     }
00441     // now, let's compute for each of the best incoming edges
00442     //  the incoming which is most opposite
00443     //  the outgoing which is most opposite
00444     std::vector<NBEdge*>::iterator i;
00445     std::map<NBEdge*, NBEdge*> counterIncomingEdges;
00446     std::map<NBEdge*, NBEdge*> counterOutgoingEdges;
00447     incoming = *myIncomingEdges;
00448     outgoing = *myOutgoingEdges;
00449     for (i=bestIncoming.begin(); i!=bestIncoming.end(); ++i) {
00450         std::sort(incoming.begin(), incoming.end(), NBContHelper::edge_opposite_direction_sorter(*i));
00451         counterIncomingEdges[*i] = *incoming.begin();
00452         std::sort(outgoing.begin(), outgoing.end(), NBContHelper::edge_opposite_direction_sorter(*i));
00453         counterOutgoingEdges[*i] = *outgoing.begin();
00454     }
00455     // ok, let's try
00456     // 1) there is one best incoming road
00457     if (bestIncoming.size()==1) {
00458         // let's mark this road as the best
00459         NBEdge *best1 = extractAndMarkFirst(bestIncoming);
00460         if (bestOutgoing.size()!=0) {
00461             // mark the best outgoing as the continuation
00462             sort(bestOutgoing.begin(), bestOutgoing.end(), NBContHelper::edge_similar_direction_sorter(best1));
00463             extractAndMarkFirst(bestOutgoing);
00464         }
00465         return;
00466     }
00467     // 2b) there are more than one best incoming roads
00468     //      and the same number of best outgoing roads
00469 
00470     // ok, what we want to do in this case is to determine which incoming
00471     //  has the best continuation...
00472     // This means, when several incoming roads have the same priority,
00473     //  we want a (any) straight connection to be more priorised than a turning
00474     SUMOReal bestAngle = 0;
00475     NBEdge *bestFirst = 0;
00476     NBEdge *bestSecond = 0;
00477     bool hadBest = false;
00478     for (i=bestIncoming.begin(); i!=bestIncoming.end(); ++i) {
00479         std::vector<NBEdge*>::iterator j;
00480         NBEdge *t1 = *i;
00481         SUMOReal angle1 = t1->getAngle()+180;
00482         if (angle1>=360) {
00483             angle1 -= 360;
00484         }
00485         for (j=i+1; j!=bestIncoming.end(); ++j) {
00486             NBEdge *t2 = *j;
00487             SUMOReal angle2 = t2->getAngle()+180;
00488             if (angle2>=360) {
00489                 angle2 -= 360;
00490             }
00491             SUMOReal angle = GeomHelper::getMinAngleDiff(angle1, angle2);
00492             if (!hadBest||angle>bestAngle) {
00493                 bestAngle = angle;
00494                 bestFirst = *i;
00495                 bestSecond = *j;
00496                 hadBest = true;
00497             }
00498         }
00499     }
00500     bestFirst->setJunctionPriority(this, 1);
00501     sort(bestOutgoing.begin(), bestOutgoing.end(), NBContHelper::edge_similar_direction_sorter(bestFirst));
00502     if (bestOutgoing.size()!=0) {
00503         extractAndMarkFirst(bestOutgoing);
00504     }
00505     bestSecond->setJunctionPriority(this, 1);
00506     sort(bestOutgoing.begin(), bestOutgoing.end(), NBContHelper::edge_similar_direction_sorter(bestSecond));
00507     if (bestOutgoing.size()!=0) {
00508         extractAndMarkFirst(bestOutgoing);
00509     }
00510 }
00511 
00512 
00513 NBEdge*
00514 NBNode::extractAndMarkFirst(std::vector<NBEdge*> &s) {
00515     if (s.size()==0) {
00516         return 0;
00517     }
00518     NBEdge *ret = s.front();
00519     s.erase(s.begin());
00520     ret->setJunctionPriority(this, 1);
00521     return ret;
00522 }
00523 
00524 
00525 unsigned int
00526 NBNode::countInternalLanes(bool includeSplits) {
00527     unsigned int lno = 0;
00528     EdgeVector::iterator i;
00529     for (i=myIncomingEdges->begin(); i!=myIncomingEdges->end(); i++) {
00530         unsigned int noLanesEdge = (*i)->getNoLanes();
00531         for (unsigned int j=0; j<noLanesEdge; j++) {
00532             std::vector<NBEdge::Connection> elv = (*i)->getConnectionsFromLane(j);
00533             for (std::vector<NBEdge::Connection>::iterator k=elv.begin(); k!=elv.end(); ++k) {
00534                 if ((*k).toEdge==0) {
00535                     continue;
00536                 }
00537                 lno++;
00538                 // add internal splits if any
00539                 if (includeSplits) {
00540                     std::pair<SUMOReal, std::vector<unsigned int> > cross = getCrossingPosition(*i, j, (*k).toEdge, (*k).toLane);
00541                     if (cross.first>=0) {
00542                         lno++;
00543                     }
00544                 }
00545             }
00546         }
00547     }
00548     return lno;
00549 }
00550 
00551 
00552 void
00553 NBNode::writeXMLInternalLinks(OutputDevice &into) {
00554     unsigned int noInternalNoSplits = countInternalLanes(false);
00555     if (noInternalNoSplits==0) {
00556         return;
00557     }
00558     std::string id = ":" + myID;
00559     unsigned int lno = 0;
00560     unsigned int splitNo = 0;
00561     EdgeVector::iterator i;
00562     for (i=myIncomingEdges->begin(); i!=myIncomingEdges->end(); i++) {
00563         unsigned int noLanesEdge = (*i)->getNoLanes();
00564         for (unsigned int j=0; j<noLanesEdge; j++) {
00565             std::vector<NBEdge::Connection> elv = (*i)->getConnectionsFromLane(j);
00566             for (std::vector<NBEdge::Connection>::iterator k=elv.begin(); k!=elv.end(); ++k) {
00567                 if ((*k).toEdge==0) {
00568                     continue;
00569                 }
00570                 // compute the maximum speed allowed
00571                 //  see !!! for an explanation (with a_lat_mean ~0.3)
00572                 SUMOReal vmax = (SUMOReal) 0.3 * (SUMOReal) 9.80778 *
00573                                 (*i)->getLaneShape(j).getEnd().distanceTo(
00574                                     (*k).toEdge->getLaneShape((*k).toLane).getBegin())
00575                                 / (SUMOReal) 2.0 / (SUMOReal) PI;
00576                 vmax = MIN2(vmax, (((*i)->getSpeed()+(*k).toEdge->getSpeed())/(SUMOReal) 2.0));
00577                 vmax = ((*i)->getSpeed()+(*k).toEdge->getSpeed())/(SUMOReal) 2.0;
00578                 //
00579                 std::string id = ":" + myID + "_" + toString(lno);
00580                 Position2D end = (*k).toEdge->getLaneShape((*k).toLane).getBegin();
00581                 Position2D beg = (*i)->getLaneShape(j).getEnd();
00582 
00583                 Position2DVector shape = computeInternalLaneShape(*i, j, (*k).toEdge, (*k).toLane);
00584                 if (shape.size()==1) {
00585                     shape.push_back(shape[0]);
00586                 }
00587                 SUMOReal length = MAX2(shape.length(), (SUMOReal) .1);
00588 
00589                 // get internal splits if any
00590                 std::pair<SUMOReal, std::vector<unsigned int> > cross = getCrossingPosition(*i, j, (*k).toEdge, (*k).toLane);
00591                 if (cross.first>=0) {
00592                     std::pair<Position2DVector, Position2DVector> split;
00593                     // as usual, a problem...
00594                     //  if the one edge starts exactly where the other one ends (think of a
00595                     //  turnaround edges lying over the other one) we have a shape with length=0
00596                     if (shape.length()!=0) {
00597                         split = shape.splitAt(cross.first);
00598                     } else {
00599                         split = std::pair<Position2DVector, Position2DVector>(shape, shape);
00600                     }
00601                     if (split.first.size()==1) {
00602                         split.first.push_back(split.first[0]);
00603                     }
00604                     if (split.second.size()==1) {
00605                         split.second.push_back(split.second[0]);
00606                     }
00607 
00608                     into << "   <edge id=\"" << id << "\" function=\"internal\">\n";
00609                     into << "      <lanes>\n";
00610                     into << "         <lane id=\"" << id << "_0\" depart=\"0\" "
00611                     << "maxspeed=\"" << vmax << "\" length=\""
00612                     << toString<SUMOReal>(cross.first) << "\""
00613                     << " shape=\"" << split.first << "\"/>\n"
00614                     << "      </lanes>\n"
00615                     << "   </edge>\n\n";
00616                     lno++;
00617 
00618                     std::string id = ":" + myID + "_" + toString(splitNo+noInternalNoSplits);
00619                     into << "   <edge id=\"" << id
00620                     << "\" function=\"internal\">\n";
00621                     into << "      <lanes>\n";
00622                     into << "         <lane id=\"" << id << "_0\" depart=\"0\" "
00623                     << "maxspeed=\"" << vmax << "\" length=\""
00624                     << toString<SUMOReal>(length-cross.first) << "\""
00625                     << " shape=\"" << split.second << "\"/>\n"
00626                     << "      </lanes>\n"
00627                     << "   </edge>\n\n";
00628                     splitNo++;
00629                 } else {
00630                     into << "   <edge id=\"" << id
00631                     << "\" function=\"internal\">\n";
00632                     into << "      <lanes>\n";
00633                     into << "         <lane id=\"" << id << "_0\" depart=\"0\" "
00634                     << "maxspeed=\"" << vmax << "\" length=\""
00635                     << toString<SUMOReal>(length) << "\""
00636                     << " shape=\"" << shape << "\"/>\n"
00637                     << "      </lanes>\n"
00638                     << "   </edge>\n\n";
00639                     lno++;
00640                 }
00641             }
00642         }
00643     }
00644 }
00645 
00646 
00647 Position2DVector
00648 NBNode::computeInternalLaneShape(NBEdge *fromE, int fromL,
00649                                  NBEdge *toE, int toL) {
00650     if (fromL>=(int) fromE->getNoLanes()) {
00651         throw ProcessError("Connection '" + fromE->getID() + "_" + toString(fromL) + "->" + toE->getID() + "_" + toString(toL) + "' starts at a not existing lane.");
00652     }
00653     if (toL>=(int) toE->getNoLanes()) {
00654         throw ProcessError("Connection '" + fromE->getID() + "_" + toString(fromL) + "->" + toE->getID() + "_" + toString(toL) + "' yields in a not existing lane.");
00655     }
00656     bool noSpline = false;
00657     Position2DVector ret;
00658     Position2DVector init;
00659     Position2D beg = fromE->getLaneShape(fromL).getEnd();
00660     Position2D end = toE->getLaneShape(toL).getBegin();
00661     Position2D intersection;
00662     unsigned int noInitialPoints = 0;
00663     if (beg==end) {
00664         noSpline = true;
00665     } else {
00666         if (fromE->getTurnDestination()==toE) {
00667             // turnarounds:
00668             //  - end of incoming lane
00669             //  - position between incoming/outgoing end/begin shifted by the distace orthogonally
00670             //  - begin of outgoing lane
00671             noInitialPoints = 3;
00672             init.push_back(beg);
00673             Line2D straightConn(fromE->getLaneShape(fromL)[-1],toE->getLaneShape(toL)[0]);
00674             Position2D straightCenter = straightConn.getPositionAtDistance((SUMOReal) straightConn.length() / (SUMOReal) 2.);
00675             Position2D center = straightCenter;//.add(straightCenter);
00676             Line2D cross(straightConn);
00677             cross.sub(cross.p1().x(), cross.p1().y());
00678             cross.rotateAtP1(PI/2);
00679             center.sub(cross.p2());
00680             init.push_back(center);
00681             init.push_back(end);
00682         } else {
00683             //
00684             SUMOReal angle1 = fromE->getLaneShape(fromL).getEndLine().atan2DegreeAngle();
00685             SUMOReal angle2 = toE->getLaneShape(toL).getBegLine().atan2DegreeAngle();
00686             SUMOReal angle = GeomHelper::getMinAngleDiff(angle1, angle2);
00687             if (angle<45) {
00688                 // very low angle: almost straight
00689                 noInitialPoints = 4;
00690                 init.push_back(beg);
00691                 Line2D begL = fromE->getLaneShape(fromL).getEndLine();
00692                 begL.extrapolateSecondBy(100);
00693                 Line2D endL = toE->getLaneShape(toL).getBegLine();
00694                 endL.extrapolateFirstBy(100);
00695                 SUMOReal distance = beg.distanceTo(end);
00696                 if (distance>10) {
00697                     {
00698                         SUMOReal off1 = fromE->getLaneShape(fromL).getEndLine().length() + (SUMOReal) 5. * (SUMOReal) fromE->getNoLanes();
00699                         off1 = MIN2(off1, (SUMOReal)(fromE->getLaneShape(fromL).getEndLine().length()+distance/2.));
00700                         Position2D tmp = begL.getPositionAtDistance(off1);
00701                         init.push_back(tmp);
00702                     }
00703                     {
00704                         SUMOReal off1 = (SUMOReal) 100. - (SUMOReal) 5. * (SUMOReal) toE->getNoLanes();
00705                         off1 = MAX2(off1, (SUMOReal)(100.-distance/2.));
00706                         Position2D tmp = endL.getPositionAtDistance(off1);
00707                         init.push_back(tmp);
00708                     }
00709                 } else {
00710                     noSpline = true;
00711                 }
00712                 init.push_back(end);
00713             } else {
00714                 // turning
00715                 //  - end of incoming lane
00716                 //  - intersection of the extrapolated lanes
00717                 //  - begin of outgoing lane
00718                 // attention: if there is no intersection, use a straight line
00719                 noInitialPoints = 3;
00720                 init.push_back(beg);
00721                 Line2D begL = fromE->getLaneShape(fromL).getEndLine();
00722                 Line2D endL = toE->getLaneShape(toL).getBegLine();
00723                 bool check = !begL.p1().almostSame(begL.p2()) && !endL.p1().almostSame(endL.p2());
00724                 if (check) {
00725                     begL.extrapolateSecondBy(100);
00726                     endL.extrapolateFirstBy(100);
00727                 } else {
00728                     MsgHandler::getWarningInstance()->inform("Could not use edge geometry for internal lane, node '" + getID() + "'.");
00729                 }
00730                 if (!check||!begL.intersects(endL)) {
00731                     noSpline = true;
00732                 } else {
00733                     init.push_back(begL.intersectsAt(endL));
00734                 }
00735                 init.push_back(end);
00736             }
00737         }
00738     }
00739     //
00740     if (noSpline) {
00741         ret.push_back(fromE->getLaneShape(fromL).getEnd());
00742         ret.push_back(toE->getLaneShape(toL).getBegin());
00743         return ret;
00744     }
00745 
00746     SUMOReal *def = new SUMOReal[1+noInitialPoints*3];
00747     for (int i=0; i<(int) init.size(); ++i) {
00748         // starts at index 1
00749         def[i*3+1] = init[i].x();
00750         def[i*3+2] = 0;
00751         def[i*3+3] = init[i].y();
00752     }
00753     SUMOReal ret_buf[NO_INTERNAL_POINTS*3+1];
00754     bezier(noInitialPoints, def, NO_INTERNAL_POINTS, ret_buf);
00755     delete[] def;
00756     Position2D prev;
00757 
00758     for (int i=0; i<(int) NO_INTERNAL_POINTS; i++) {
00759         Position2D current(ret_buf[i*3+1], ret_buf[i*3+3]);
00760         if (prev!=current) {
00761             ret.push_back(current);
00762         }
00763         prev = current;
00764     }
00765     return ret;
00766 }
00767 
00768 
00769 std::pair<SUMOReal, std::vector<unsigned int> >
00770 NBNode::getCrossingPosition(NBEdge *fromE, unsigned int fromL, NBEdge *toE, unsigned int toL) {
00771     std::pair<SUMOReal, std::vector<unsigned int> > ret(-1, std::vector<unsigned int>());
00772     NBMMLDirection dir = getMMLDirection(fromE, toE);
00773     switch (dir) {
00774     case MMLDIR_LEFT:
00775     case MMLDIR_PARTLEFT:
00776     case MMLDIR_TURN: {
00777         Position2DVector thisShape = computeInternalLaneShape(fromE, fromL, toE, toL);
00778         unsigned int index = 0;
00779         for (EdgeVector::iterator i2=myIncomingEdges->begin(); i2!=myIncomingEdges->end(); i2++) {
00780             unsigned int noLanesEdge = (*i2)->getNoLanes();
00781             for (unsigned int j2=0; j2<noLanesEdge; j2++) {
00782                 std::vector<NBEdge::Connection> elv = (*i2)->getConnectionsFromLane(j2);
00783                 for (std::vector<NBEdge::Connection>::iterator k2=elv.begin(); k2!=elv.end(); k2++) {
00784                     if ((*k2).toEdge==0) {
00785                         continue;
00786                     }
00787                     if (fromE!=(*i2)&&forbids(*i2, (*k2).toEdge, fromE, toE, true)) {
00788                         // compute the crossing point
00789                         ret.second.push_back(index);
00790                         Position2DVector otherShape = computeInternalLaneShape(*i2, j2, (*k2).toEdge, (*k2).toLane);
00791                         if (thisShape.intersects(otherShape)) {
00792                             DoubleVector dv = thisShape.intersectsAtLengths(otherShape);
00793                             SUMOReal minDV = dv[0];
00794                             if (minDV<thisShape.length()-.1&&minDV>.1) { // !!!?
00795                                 assert(minDV>=0);
00796                                 if (ret.first<0||ret.first>minDV) {
00797                                     ret.first = minDV;
00798                                 }
00799                             }
00800                         }
00801                     }
00802                     index++;
00803                 }
00804             }
00805         }
00806         if (dir==MMLDIR_TURN&&ret.first<0&&ret.second.size()!=0) {
00807             // let turnarounds wait at the begin if no other crossing point was found
00808             ret.first = (SUMOReal) POSITION_EPS;
00809         }
00810     }
00811     break;
00812     default:
00813         break;
00814     }
00815     return ret;
00816 }
00817 
00818 
00819 std::string
00820 NBNode::getCrossingNames_dividedBySpace(NBEdge *fromE, unsigned int fromL,
00821                                         NBEdge *toE, unsigned int toL) {
00822     std::string ret;
00823     NBMMLDirection dir = getMMLDirection(fromE, toE);
00824     switch (dir) {
00825     case MMLDIR_LEFT:
00826     case MMLDIR_PARTLEFT:
00827     case MMLDIR_TURN: {
00828         Position2DVector thisShape = computeInternalLaneShape(fromE, fromL, toE, toL);
00829         unsigned int index = 0;
00830         for (EdgeVector::iterator i2=myIncomingEdges->begin(); i2!=myIncomingEdges->end(); i2++) {
00831             unsigned int noLanesEdge = (*i2)->getNoLanes();
00832             for (unsigned int j2=0; j2<noLanesEdge; j2++) {
00833                 std::vector<NBEdge::Connection> elv = (*i2)->getConnectionsFromLane(j2);
00834                 for (std::vector<NBEdge::Connection>::iterator k2=elv.begin(); k2!=elv.end(); k2++) {
00835                     if ((*k2).toEdge==0) {
00836                         continue;
00837                     }
00838                     NBEdge *e = fromE->getToNode()->getOppositeIncoming(fromE);
00839                     if (e!=*i2) {
00840                         index++;
00841                         continue;
00842                     }
00843                     NBMMLDirection dir2 = getMMLDirection(*i2, (*k2).toEdge);
00844                     bool left = dir2==MMLDIR_LEFT || dir2==MMLDIR_PARTLEFT || dir2==MMLDIR_TURN;
00845                     left = false;
00846                     if (!left&&fromE!=(*i2)&&forbids(*i2, (*k2).toEdge, fromE, toE, true)) {
00847                         if (ret.length()!=0) {
00848                             ret += " ";
00849                         }
00850                         ret += (":" + myID + "_" + toString(index) + "_0");
00851                     }
00852                     index++;
00853                 }
00854             }
00855         }
00856     }
00857     break;
00858     default:
00859         break;
00860     }
00861     return ret;
00862 }
00863 
00864 
00865 std::string
00866 NBNode::getCrossingSourcesNames_dividedBySpace(NBEdge *fromE, unsigned int fromL,
00867         NBEdge *toE, unsigned int toL) {
00868     std::string ret;
00869     std::vector<std::string> tmp;
00870     NBMMLDirection dir = getMMLDirection(fromE, toE);
00871     switch (dir) {
00872     case MMLDIR_LEFT:
00873     case MMLDIR_PARTLEFT:
00874     case MMLDIR_TURN: {
00875         Position2DVector thisShape = computeInternalLaneShape(fromE, fromL, toE, toL);
00876         unsigned int index = 0;
00877         for (EdgeVector::iterator i2=myIncomingEdges->begin(); i2!=myIncomingEdges->end(); i2++) {
00878             unsigned int noLanesEdge = (*i2)->getNoLanes();
00879             for (unsigned int j2=0; j2<noLanesEdge; j2++) {
00880                 std::vector<NBEdge::Connection> elv = (*i2)->getConnectionsFromLane(j2);
00881                 for (std::vector<NBEdge::Connection>::iterator k2=elv.begin(); k2!=elv.end(); k2++) {
00882                     if ((*k2).toEdge==0) {
00883                         continue;
00884                     }
00885                     NBEdge *e = fromE->getToNode()->getOppositeIncoming(fromE);
00886                     if (e!=*i2) {
00887                         index++;
00888                         continue;
00889                     }
00890                     NBMMLDirection dir2 = getMMLDirection(*i2, (*k2).toEdge);
00891                     bool left = dir2==MMLDIR_LEFT || dir2==MMLDIR_PARTLEFT || dir2==MMLDIR_TURN;
00892                     left = false;
00893                     if (!left&&fromE!=(*i2)&&forbids(*i2, (*k2).toEdge, fromE, toE, true)) {
00894                         std::string nid = (*i2)->getID() + "_" + toString(j2);
00895                         if (find(tmp.begin(), tmp.end(), nid)==tmp.end()) {
00896                             tmp.push_back(nid);
00897                         }
00898                     }
00899                     index++;
00900                 }
00901             }
00902         }
00903     }
00904     break;
00905     default:
00906         break;
00907     }
00908     for (std::vector<std::string>::iterator i=tmp.begin(); i!=tmp.end(); ++i) {
00909         if (ret.length()>0) {
00910             ret = ret + " ";
00911         }
00912         ret = ret + *i;
00913     }
00914     return ret;
00915 }
00916 
00917 
00918 void
00919 NBNode::writeXMLInternalSuccInfos(OutputDevice &into) {
00920     unsigned int noInternalNoSplits = countInternalLanes(false);
00921     if (noInternalNoSplits==0) {
00922         return;
00923     }
00924     unsigned int lno = 0;
00925     unsigned int splitNo = 0;
00926     for (EdgeVector::iterator i=myIncomingEdges->begin(); i!=myIncomingEdges->end(); i++) {
00927         unsigned int noLanesEdge = (*i)->getNoLanes();
00928         for (unsigned int j=0; j<noLanesEdge; j++) {
00929             std::vector<NBEdge::Connection> elv = (*i)->getConnectionsFromLane(j);
00930             for (std::vector<NBEdge::Connection>::iterator k=elv.begin(); k!=elv.end(); ++k) {
00931                 if ((*k).toEdge==0) {
00932                     continue;
00933                 }
00934                 std::string id = ":" + myID + "_" + toString(lno);
00935                 std::string sid = ":" + myID + "_" + toString(splitNo+noInternalNoSplits);
00936                 std::pair<SUMOReal, std::vector<unsigned int> > cross = getCrossingPosition(*i, j, (*k).toEdge, (*k).toLane);
00937 
00938                 // get internal splits if any
00939                 into << "   <succ edge=\"" << id << "\" "
00940                 << "lane=\"" << id << "_"
00941                 << 0 << "\" junction=\"" << myID << "\">\n";
00942                 if (cross.first>=0) {
00943                     into << "      <succlane lane=\""
00944                     //<< sid << "_" << 0 ()
00945                     << (*k).toEdge->getID() << "_" << (*k).toLane << "\""
00946                     << " via=\"" << sid << "_" << 0 << "\""
00947                     << " tl=\"" << "" << "\" linkno=\""
00948                     << "" << "\" yield=\"1\" dir=\"s\" state=\"M\""; // !!! yield or not depends on whether it is tls controlled or not
00949                 } else {
00950                     into << "      <succlane lane=\""
00951                     << (*k).toEdge->getID() << "_" << (*k).toLane
00952                     << "\" tl=\"" << "" << "\" linkno=\""
00953                     << "" << "\" yield=\"0\" dir=\"s\" state=\"M\"";
00954                 }
00955                 into << "/>\n";
00956                 into << "   </succ>\n";
00957 
00958                 if (cross.first>=0) {
00959                     into << "   <succ edge=\"" << sid << "\" "
00960                     << "lane=\"" << sid << "_" << 0
00961                     << "\" junction=\"" << sid << "\">\n";
00962                     into << "      <succlane lane=\""
00963                     << (*k).toEdge->getID() << "_" << (*k).toLane
00964                     << "\" tl=\"" << "" << "\" linkno=\""
00965                     << "0" << "\" yield=\"0\" dir=\"s\" state=\"M\"";
00966                     into << "/>\n";
00967                     into << "   </succ>\n";
00968                     splitNo++;
00969                 }
00970                 lno++;
00971             }
00972         }
00973     }
00974 }
00975 
00976 
00977 void
00978 NBNode::writeXMLInternalNodes(OutputDevice &into) {
00979     unsigned int noInternalNoSplits = countInternalLanes(false);
00980     if (noInternalNoSplits==0) {
00981         return;
00982     }
00983     unsigned int lno = 0;
00984     unsigned int splitNo = 0;
00985     for (EdgeVector::iterator i=myIncomingEdges->begin(); i!=myIncomingEdges->end(); i++) {
00986         unsigned int noLanesEdge = (*i)->getNoLanes();
00987         for (unsigned int j=0; j<noLanesEdge; j++) {
00988             std::vector<NBEdge::Connection> elv = (*i)->getConnectionsFromLane(j);
00989             for (std::vector<NBEdge::Connection>::iterator k=elv.begin(); k!=elv.end(); ++k) {
00990                 if ((*k).toEdge==0) {
00991                     continue;
00992                 }
00993                 std::pair<SUMOReal, std::vector<unsigned int> > cross = getCrossingPosition(*i, j, (*k).toEdge, (*k).toLane);
00994                 if (cross.first<=0) {
00995                     lno++;
00996                     continue;
00997                 }
00998                 // write the attributes
00999                 std::string sid = ":" + myID + "_" + toString(splitNo+noInternalNoSplits) + "_0";
01000                 std::string iid = ":" + myID + "_" + toString(lno) + "_0";
01001                 Position2DVector shape = computeInternalLaneShape(*i, j, (*k).toEdge, (*k).toLane);
01002                 Position2D pos = shape.positionAtLengthPosition(cross.first);
01003                 into << "   <junction id=\"" << sid << '\"';
01004                 into << " type=\"" << "internal\"";
01005                 into << " x=\"" << pos.x() << "\" y=\"" << pos.y() << "\"";
01006                 into << " incLanes=\"";
01007                 std::string furtherIncoming = getCrossingSourcesNames_dividedBySpace(*i, j, (*k).toEdge, (*k).toLane);
01008                 if (furtherIncoming.length()!=0) {
01009                     into << iid << " " << furtherIncoming;
01010                 } else {
01011                     into << iid;
01012                 }
01013                 into << "\"";
01014                 into << " intLanes=\"" << getCrossingNames_dividedBySpace(*i, j, (*k).toEdge, (*k).toLane) << "\"";
01015                 into << " shape=\"\"/>\n\n";
01016                 splitNo++;
01017                 lno++;
01018             }
01019         }
01020     }
01021 }
01022 
01023 
01024 void
01025 NBNode::writeinternal(EdgeVector *myIncomingEdges, OutputDevice &into, const std::string &id) {
01026     unsigned int l = 0;
01027     unsigned int o = countInternalLanes(false);
01028     for (EdgeVector::iterator i=myIncomingEdges->begin(); i!=myIncomingEdges->end(); i++) {
01029         unsigned int noLanesEdge = (*i)->getNoLanes();
01030         for (unsigned int j=0; j<noLanesEdge; j++) {
01031             std::vector<NBEdge::Connection> elv = (*i)->getConnectionsFromLane(j);
01032             for (std::vector<NBEdge::Connection>::iterator k=elv.begin(); k!=elv.end(); ++k) {
01033                 if ((*k).toEdge==0) {
01034                     continue;
01035                 }
01036                 if (l!=0) {
01037                     into << ' ';
01038                 }
01039                 std::pair<SUMOReal, std::vector<unsigned int> > cross = getCrossingPosition(*i, j, (*k).toEdge, (*k).toLane);
01040                 if (cross.first<=0) {
01041                     into << ':' << id << '_' << l << "_0";
01042                 } else {
01043                     into << ':' << id << '_' << o << "_0";
01044                     o++;
01045                 }
01046                 l++;
01047             }
01048         }
01049     }
01050 }
01051 
01052 
01053 void
01054 NBNode::writeXML(OutputDevice &into) {
01055     // write the attributes
01056     into << "   <junction id=\"" << myID << '\"';
01057     if (myIncomingEdges->size()!=0&&myOutgoingEdges->size()!=0) {
01058         //into << " key=\"" << _key << '\"';
01059         switch (myType) {
01060         case NODETYPE_NOJUNCTION:
01061             into << " type=\"" << "unregulated\"";
01062             break;
01063         case NODETYPE_PRIORITY_JUNCTION:
01064         case NODETYPE_TRAFFIC_LIGHT:
01065             into << " type=\"" << "priority\"";
01066             break;
01067         case NODETYPE_RIGHT_BEFORE_LEFT:
01068             into << " type=\"" << "right_before_left\"";
01069             break;
01070         case NODETYPE_DISTRICT:
01071             into << " type=\"" << "district\"";
01072             break;
01073         default:
01074             throw ProcessError("An unknown junction type occured (" + toString(myType) + ")");
01075         }
01076     } else {
01077         into << " type=\"DEAD_END\"";
01078     }
01079     into << " x=\"" << myPosition.x() << "\" y=\"" << myPosition.y() << "\"";
01080     into << " incLanes=\"";
01081     // write the incoming lanes
01082     EdgeVector::iterator i;
01083     for (i=myIncomingEdges->begin(); i!=myIncomingEdges->end(); i++) {
01084         unsigned int noLanes = (*i)->getNoLanes();
01085         std::string id = (*i)->getID();
01086         for (unsigned int j=0; j<noLanes; j++) {
01087             into << id << '_' << j;
01088             if (i!=myIncomingEdges->end()-1 || j<noLanes-1) {
01089                 into << ' ';
01090             }
01091         }
01092     }
01093     into << "\"";
01094     // write the internal lanes
01095     into << " intLanes=\"";
01096     if (!OptionsCont::getOptions().getBool("no-internal-links")) {
01097         writeinternal(myIncomingEdges, into, myID);
01098     }
01099     into << "\"";
01100     // close writing
01101     into << " shape=\"" << myPoly << "\"/>\n\n";
01102 }
01103 
01104 
01105 void
01106 NBNode::computeLogic(const NBEdgeCont &ec, NBJunctionLogicCont &jc,
01107                      OptionsCont &) {
01108     if (myIncomingEdges->size()==0||myOutgoingEdges->size()==0) {
01109         // no logic if nothing happens here
01110         myType = NODETYPE_NOJUNCTION;
01111         return;
01112     }
01113     // check whether the node was set to be unregulated by the user
01114     if (OptionsCont::getOptions().getBool("keep-unregulated")
01115             ||
01116             OptionsCont::getOptions().isInStringVector("keep-unregulated.nodes", getID())
01117             ||
01118             (OptionsCont::getOptions().getBool("keep-unregulated.district-nodes")&&(isNearDistrict()||isDistrict()))) {
01119 
01120         myType = NODETYPE_NOJUNCTION;
01121         return;
01122     }
01123     // compute the logic if necessary or split the junction
01124     if (myType!=NODETYPE_NOJUNCTION&&myType!=NODETYPE_DISTRICT) {
01125         // build the request
01126         myRequest = new NBRequest(ec, this,
01127                                   static_cast<const EdgeVector * const>(&myAllEdges),
01128                                   static_cast<const EdgeVector * const>(myIncomingEdges),
01129                                   static_cast<const EdgeVector * const>(myOutgoingEdges),
01130                                   myBlockedConnections);
01131         // check whether it is not too large
01132         if (myRequest->getSizes().second>=64) {
01133             // yep -> make it untcontrolled, warn
01134             MsgHandler::getWarningInstance()->inform("Junction '" + getID() + "' is too complicated (#links>64); will be set to unregulated.");
01135             delete myRequest;
01136             myRequest = 0;
01137             myType = NODETYPE_NOJUNCTION;
01138         } else {
01139             myRequest->buildBitfieldLogic(ec.isLeftHanded(), jc, myID);
01140         }
01141     }
01142 }
01143 
01144 
01145 void
01146 NBNode::sortNodesEdges(bool leftHand, const NBTypeCont &tc) {
01147     // sort the edges
01148     sort(myAllEdges.begin(), myAllEdges.end(), NBContHelper::edge_by_junction_angle_sorter(this));
01149     sort(myIncomingEdges->begin(), myIncomingEdges->end(), NBContHelper::edge_by_junction_angle_sorter(this));
01150     sort(myOutgoingEdges->begin(), myOutgoingEdges->end(), NBContHelper::edge_by_junction_angle_sorter(this));
01151     if (myAllEdges.size()==0) {
01152         return;
01153     }
01154     std::vector<NBEdge*>::iterator i;
01155     for (i=myAllEdges.begin(); i!=myAllEdges.end()-1&&i!=myAllEdges.end(); i++) {
01156         swapWhenReversed(leftHand ,i, i+1);
01157     }
01158     if (myAllEdges.size()>1 && i!=myAllEdges.end()) {
01159         swapWhenReversed(leftHand, myAllEdges.end()-1, myAllEdges.begin());
01160     }
01161     if (myType==NODETYPE_UNKNOWN) {
01162         myType = computeType(tc);
01163     }
01164     setPriorities();
01165     // write if wished
01166     if (OptionsCont::getOptions().isSet("node-type-output")) {
01167         std::string col;
01168         switch (myType) {
01169         case NODETYPE_NOJUNCTION:
01170             col = ".5,.5,.5";
01171             break;
01172         case NODETYPE_PRIORITY_JUNCTION:
01173             col = "0,1,0";
01174             break;
01175         case NODETYPE_RIGHT_BEFORE_LEFT:
01176             col = "0,0,1";
01177             break;
01178         case NODETYPE_DISTRICT:
01179             col = "1,0,0";
01180             break;
01181         case NODETYPE_TRAFFIC_LIGHT:
01182             col = "1,1,0";
01183             break;
01184         }
01185         OutputDevice::getDeviceByOption("node-type-output") << "   <poi id=\"type_" << myID
01186         << "\" type=\"node_type\" color=\"" << col << "\""
01187         << " x=\"" << getPosition().x() << "\" y=\"" << getPosition().y() << "\"/>\n";
01188     }
01189 }
01190 
01191 
01192 void
01193 NBNode::computeNodeShape(bool leftHand) {
01194     if (myIncomingEdges->size()==0&&myOutgoingEdges->size()==0) {
01195         return;
01196     }
01197     try {
01198         NBNodeShapeComputer computer(*this);
01199         myPoly = computer.compute(leftHand);
01200     } catch (InvalidArgument &) {
01201         MsgHandler::getWarningInstance()->inform("For node '" + getID() + "': could not compute shape.");
01202     }
01203 }
01204 
01205 
01206 void
01207 NBNode::computeLanes2Lanes() {
01208     // special case a):
01209     //  one in, one out, the outgoing has one lane more
01210     if (myIncomingEdges->size()==1&&myOutgoingEdges->size()==1
01211             &&(*myIncomingEdges)[0]->getNoLanes()==(*myOutgoingEdges)[0]->getNoLanes()-1
01212             &&(*myIncomingEdges)[0]!=(*myOutgoingEdges)[0]
01213             &&(*myIncomingEdges)[0]->isConnectedTo((*myOutgoingEdges)[0])) {
01214 
01215         NBEdge *incoming = (*myIncomingEdges)[0];
01216         NBEdge *outgoing = (*myOutgoingEdges)[0];
01217         // check if it's not the turnaround
01218         if (incoming->getTurnDestination()==outgoing) {
01219             // will be added later or not...
01220             return;
01221         }
01222         for (int i=0; i<(int) incoming->getNoLanes(); ++i) {
01223             incoming->setConnection(i, outgoing, i+1, NBEdge::L2L_COMPUTED);
01224         }
01225         incoming->setConnection(0, outgoing, 0, NBEdge::L2L_COMPUTED);
01226         return;
01227     }
01228     // special case b):
01229     //  two in, one out, the outgoing has the same number of lanes as the sum of the incoming
01230     //  and a high speed, too
01231     //  --> highway on-ramp
01232     bool check = false;
01233     if (myIncomingEdges->size()==2&&myOutgoingEdges->size()==1) {
01234         check = (*myIncomingEdges)[0]->getNoLanes()+(*myIncomingEdges)[1]->getNoLanes()==(*myOutgoingEdges)[0]->getNoLanes();
01235         check &= ((*myIncomingEdges)[0]->getStep() <= NBEdge::LANES2EDGES);
01236         check &= ((*myIncomingEdges)[1]->getStep() <= NBEdge::LANES2EDGES);
01237     }
01238     if (check
01239             &&(*myIncomingEdges)[0]!=(*myOutgoingEdges)[0]
01240             &&(*myIncomingEdges)[0]->isConnectedTo((*myOutgoingEdges)[0])) {
01241         NBEdge *inc1 = (*myIncomingEdges)[0];
01242         NBEdge *inc2 = (*myIncomingEdges)[1];
01243         // for internal: check which one is the rightmost
01244         SUMOReal a1 = inc1->getAngle(*this);
01245         SUMOReal a2 = inc2->getAngle(*this);
01246         SUMOReal ccw = GeomHelper::getCCWAngleDiff(a1, a2);
01247         SUMOReal cw = GeomHelper::getCWAngleDiff(a1, a2);
01248         if (ccw<cw) {
01249             std::swap(inc1, inc2);
01250         }
01251         //
01252         inc1->addLane2LaneConnections(0, (*myOutgoingEdges)[0], 0, inc1->getNoLanes(), NBEdge::L2L_VALIDATED, true, true);
01253         inc2->addLane2LaneConnections(0, (*myOutgoingEdges)[0], inc1->getNoLanes(), inc2->getNoLanes(), NBEdge::L2L_VALIDATED, true, true);
01254         return;
01255     }
01256 
01257     // go through this node's outgoing edges
01258     //  for every outgoing edge, compute the distribution of the node's
01259     //  incoming edges on this edge when approaching this edge
01260     // the incoming edges' steps will then also be marked as LANE2LANE_RECHECK...
01261     std::vector<NBEdge*>::reverse_iterator i;
01262     for (i=myOutgoingEdges->rbegin(); i!=myOutgoingEdges->rend(); i++) {
01263         NBEdge *currentOutgoing = *i;
01264         // get the information about edges that do approach this edge
01265         std::vector<NBEdge*> *approaching = getEdgesThatApproach(currentOutgoing);
01266         if (approaching->size()!=0) {
01267             ApproachingDivider divider(approaching, currentOutgoing);
01268             Bresenham::compute(&divider, (SUMOReal) approaching->size(),
01269                                (SUMOReal) currentOutgoing->getNoLanes());
01270         }
01271         delete approaching;
01272     }
01273     // ... but we may have the case that there are no outgoing edges
01274     //  In this case, we have to mark the incoming edges as being in state
01275     //   LANE2LANE( not RECHECK) by hand
01276     if (myOutgoingEdges->size()==0) {
01277         for (i=myIncomingEdges->rbegin(); i!=myIncomingEdges->rend(); i++) {
01278             (*i)->markAsInLane2LaneState();
01279         }
01280     }
01281 }
01282 
01283 
01284 std::vector<NBEdge*> *
01285 NBNode::getEdgesThatApproach(NBEdge *currentOutgoing) {
01286     // get the position of the node to get the approaching nodes of
01287     std::vector<NBEdge*>::const_iterator i = find(myAllEdges.begin(),
01288             myAllEdges.end(), currentOutgoing);
01289     // get the first possible approaching edge
01290     NBContHelper::nextCW(&myAllEdges, i);
01291     // go through the list of edges clockwise and add the edges
01292     std::vector<NBEdge*> *approaching = new std::vector<NBEdge*>();
01293     for (; *i!=currentOutgoing;) {
01294         // check only incoming edges
01295         if ((*i)->getToNode()==this&&(*i)->getTurnDestination()!=currentOutgoing) {
01296             std::vector<int> connLanes = (*i)->getConnectionLanes(currentOutgoing);
01297             if (connLanes.size()!=0) {
01298                 approaching->push_back(*i);
01299             }
01300         }
01301         NBContHelper::nextCW(&myAllEdges, i);
01302     }
01303     return approaching;
01304 }
01305 
01306 
01307 void
01308 NBNode::reshiftPosition(SUMOReal xoff, SUMOReal yoff) {
01309     myPosition.reshiftRotate(xoff, yoff, 0);
01310     myPoly.reshiftRotate(xoff, yoff, 0);
01311 }
01312 
01313 
01314 void
01315 NBNode::replaceOutgoing(NBEdge *which, NBEdge *by, unsigned int laneOff) {
01316     // replace the edge in the list of outgoing nodes
01317     std::vector<NBEdge*>::iterator i=find(myOutgoingEdges->begin(), myOutgoingEdges->end(), which);
01318     if (i!=myOutgoingEdges->end()) {
01319         (*i) = by;
01320         i = find(myAllEdges.begin(), myAllEdges.end(), which);
01321         (*i) = by;
01322     }
01323     // replace the edge in connections of incoming edges
01324     for (i=myIncomingEdges->begin(); i!=myIncomingEdges->end(); ++i) {
01325         (*i)->replaceInConnections(which, by, laneOff);
01326     }
01327     // replace within the connetion prohibition dependencies
01328     replaceInConnectionProhibitions(which, by, 0, laneOff);
01329 }
01330 
01331 
01332 void
01333 NBNode::replaceOutgoing(const EdgeVector &which, NBEdge *by) {
01334     // replace edges
01335     unsigned int laneOff = 0;
01336     for (EdgeVector::const_iterator i=which.begin(); i!=which.end(); i++) {
01337         replaceOutgoing(*i, by, laneOff);
01338         laneOff += (*i)->getNoLanes();
01339     }
01340     // removed SUMOReal occurences
01341     removeDoubleEdges();
01342     // check whether this node belongs to a district and the edges
01343     //  must here be also remapped
01344     if (myDistrict!=0) {
01345         myDistrict->replaceOutgoing(which, by);
01346     }
01347 }
01348 
01349 
01350 void
01351 NBNode::replaceIncoming(NBEdge *which, NBEdge *by, unsigned int laneOff) {
01352     // replace the edge in the list of incoming nodes
01353     std::vector<NBEdge*>::iterator i=find(myIncomingEdges->begin(), myIncomingEdges->end(), which);
01354     if (i!=myIncomingEdges->end()) {
01355         (*i) = by;
01356         i = find(myAllEdges.begin(), myAllEdges.end(), which);
01357         (*i) = by;
01358     }
01359     // replace within the connetion prohibition dependencies
01360     replaceInConnectionProhibitions(which, by, laneOff, 0);
01361 }
01362 
01363 
01364 void
01365 NBNode::replaceIncoming(const EdgeVector &which, NBEdge *by) {
01366     // replace edges
01367     unsigned int laneOff = 0;
01368     for (EdgeVector::const_iterator i=which.begin(); i!=which.end(); i++) {
01369         replaceIncoming(*i, by, laneOff);
01370         laneOff += (*i)->getNoLanes();
01371     }
01372     // removed SUMOReal occurences
01373     removeDoubleEdges();
01374     // check whether this node belongs to a district and the edges
01375     //  must here be also remapped
01376     if (myDistrict!=0) {
01377         myDistrict->replaceIncoming(which, by);
01378     }
01379 }
01380 
01381 
01382 
01383 void
01384 NBNode::replaceInConnectionProhibitions(NBEdge *which, NBEdge *by,
01385                                         unsigned int whichLaneOff, unsigned int byLaneOff) {
01386     // replace in keys
01387     NBConnectionProhibits::iterator j = myBlockedConnections.begin();
01388     while (j!=myBlockedConnections.end()) {
01389         bool changed = false;
01390         NBConnection c = (*j).first;
01391         if (c.replaceFrom(which, whichLaneOff, by, byLaneOff)) {
01392             changed = true;
01393         }
01394         if (c.replaceTo(which, whichLaneOff, by, byLaneOff)) {
01395             changed = true;
01396         }
01397         if (changed) {
01398             myBlockedConnections[c] = (*j).second;
01399             myBlockedConnections.erase(j);
01400             j = myBlockedConnections.begin();
01401         } else {
01402             j++;
01403         }
01404     }
01405     // replace in values
01406     for (j=myBlockedConnections.begin(); j!=myBlockedConnections.end(); j++) {
01407         NBConnectionVector &prohibiting = (*j).second;
01408         for (NBConnectionVector::iterator k=prohibiting.begin(); k!=prohibiting.end(); k++) {
01409             NBConnection &sprohibiting = *k;
01410             sprohibiting.replaceFrom(which, whichLaneOff, by, byLaneOff);
01411             sprohibiting.replaceTo(which, whichLaneOff, by, byLaneOff);
01412         }
01413     }
01414 }
01415 
01416 
01417 
01418 void
01419 NBNode::removeDoubleEdges() {
01420     unsigned int i, j;
01421     // check incoming
01422     for (i=0; myIncomingEdges->size()>0&&i<myIncomingEdges->size()-1; i++) {
01423         j = i + 1;
01424         while (j<myIncomingEdges->size()) {
01425             if ((*myIncomingEdges)[i]==(*myIncomingEdges)[j]) {
01426                 myIncomingEdges->erase(myIncomingEdges->begin()+j);
01427             } else {
01428                 j++;
01429             }
01430         }
01431     }
01432     // check outgoing
01433     for (i=0; myOutgoingEdges->size()>0&&i<myOutgoingEdges->size()-1; i++) {
01434         j = i + 1;
01435         while (j<myOutgoingEdges->size()) {
01436             if ((*myOutgoingEdges)[i]==(*myOutgoingEdges)[j]) {
01437                 myOutgoingEdges->erase(myOutgoingEdges->begin()+j);
01438             } else {
01439                 j++;
01440             }
01441         }
01442     }
01443     // check all
01444     for (i=0; myAllEdges.size()>0&&i<myAllEdges.size()-1; i++) {
01445         j = i + 1;
01446         while (j<myAllEdges.size()) {
01447             if (myAllEdges[i]==myAllEdges[j]) {
01448                 myAllEdges.erase(myAllEdges.begin()+j);
01449             } else {
01450                 j++;
01451             }
01452         }
01453     }
01454 }
01455 
01456 
01457 bool
01458 NBNode::hasIncoming(const NBEdge * const e) const throw() {
01459     return find(myIncomingEdges->begin(), myIncomingEdges->end(), e)!=myIncomingEdges->end();
01460 }
01461 
01462 
01463 bool
01464 NBNode::hasOutgoing(const NBEdge * const e) const throw() {
01465     return find(myOutgoingEdges->begin(), myOutgoingEdges->end(), e)!=myOutgoingEdges->end();
01466 }
01467 
01468 
01469 NBEdge *
01470 NBNode::getOppositeIncoming(NBEdge *e) const {
01471     EdgeVector edges(*myIncomingEdges);
01472     if (find(edges.begin(), edges.end(), e)!=edges.end()) {
01473         edges.erase(find(edges.begin(), edges.end(), e));
01474     }
01475     if (e->getToNode()==this) {
01476         sort(edges.begin(), edges.end(), NBContHelper::edge_opposite_direction_sorter(e));
01477     } else {
01478         sort(edges.begin(), edges.end(), NBContHelper::edge_similar_direction_sorter(e));
01479     }
01480     return edges[0];
01481 }
01482 
01483 
01484 void
01485 NBNode::addSortedLinkFoes(const NBConnection &mayDrive,
01486                           const NBConnection &mustStop) {
01487     if (mayDrive.getFrom()==0 ||
01488             mayDrive.getTo()==0 ||
01489             mustStop.getFrom()==0 ||
01490             mustStop.getTo()==0) {
01491 
01492         WRITE_WARNING("Something went wrong during the building of a connection...");
01493         return; // !!! mark to recompute connections
01494     }
01495     NBConnectionVector conn = myBlockedConnections[mustStop];
01496     conn.push_back(mayDrive);
01497     myBlockedConnections[mustStop] = conn;
01498 }
01499 
01500 
01501 NBEdge *
01502 NBNode::getPossiblySplittedIncoming(const std::string &edgeid) {
01503     unsigned int size = (unsigned int) edgeid.length();
01504     for (EdgeVector::iterator i=myIncomingEdges->begin(); i!=myIncomingEdges->end(); i++) {
01505         std::string id = (*i)->getID();
01506         if (id.substr(0, size)==edgeid) {
01507             return *i;
01508         }
01509     }
01510     return 0;
01511 }
01512 
01513 
01514 NBEdge *
01515 NBNode::getPossiblySplittedOutgoing(const std::string &edgeid) {
01516     unsigned int size = (unsigned int) edgeid.length();
01517     for (EdgeVector::iterator i=myOutgoingEdges->begin(); i!=myOutgoingEdges->end(); i++) {
01518         std::string id = (*i)->getID();
01519         if (id.substr(0, size)==edgeid) {
01520             return *i;
01521         }
01522     }
01523     return 0;
01524 }
01525 
01526 
01527 unsigned int
01528 NBNode::eraseDummies(NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tc) {
01529     unsigned int ret = 0;
01530     if (myOutgoingEdges==0||myIncomingEdges==0) {
01531         return ret;
01532     }
01533     unsigned int pos = 0;
01534     EdgeVector::const_iterator j=myIncomingEdges->begin();
01535     while (j!=myIncomingEdges->end()) {
01536         // skip edges which are only incoming and not outgoing
01537         if (find(myOutgoingEdges->begin(), myOutgoingEdges->end(), *j)==myOutgoingEdges->end()) {
01538             j++;
01539             pos++;
01540             continue;
01541         }
01542         // an edge with both its origin and destination being the current
01543         //  node should be removed
01544         NBEdge *dummy = *j;
01545         WRITE_WARNING(" Removing dummy edge '" + dummy->getID() + "'");
01546         // get the list of incoming edges connected to the dummy
01547         EdgeVector incomingConnected;
01548         EdgeVector::const_iterator i;
01549         for (i=myIncomingEdges->begin(); i!=myIncomingEdges->end(); i++) {
01550             if ((*i)->isConnectedTo(dummy)&&*i!=dummy) {
01551                 incomingConnected.push_back(*i);
01552             }
01553         }
01554         // get the list of outgoing edges connected to the dummy
01555         EdgeVector outgoingConnected;
01556         for (i=myOutgoingEdges->begin(); i!=myOutgoingEdges->end(); i++) {
01557             if (dummy->isConnectedTo(*i)&&*i!=dummy) {
01558                 outgoingConnected.push_back(*i);
01559             }
01560         }
01561         // let the dummy remap its connections
01562         dummy->remapConnections(incomingConnected);
01563         remapRemoved(tc, dummy, incomingConnected, outgoingConnected);
01564         // delete the dummy
01565         ec.erase(dc, dummy);
01566         j = myIncomingEdges->begin() + pos;
01567         ret++;
01568     }
01569     return ret;
01570 }
01571 
01572 
01573 void
01574 NBNode::removeOutgoing(NBEdge *edge) {
01575     EdgeVector::iterator i = find(myOutgoingEdges->begin(), myOutgoingEdges->end(), edge);
01576     if (i!=myOutgoingEdges->end()) {
01577         myOutgoingEdges->erase(i);
01578         i = find(myAllEdges.begin(), myAllEdges.end(), edge);
01579         myAllEdges.erase(i);
01580         for (i=myAllEdges.begin(); i!=myAllEdges.end(); ++i) {
01581             (*i)->removeFromConnections(edge);
01582         }
01583     }
01584 }
01585 
01586 
01587 void
01588 NBNode::removeIncoming(NBEdge *edge) {
01589     EdgeVector::iterator i = find(myIncomingEdges->begin(), myIncomingEdges->end(), edge);
01590     if (i!=myIncomingEdges->end()) {
01591         myIncomingEdges->erase(i);
01592         i = find(myAllEdges.begin(), myAllEdges.end(), edge);
01593         myAllEdges.erase(i);
01594         for (i=myAllEdges.begin(); i!=myAllEdges.end(); ++i) {
01595             (*i)->removeFromConnections(edge);
01596         }
01597     }
01598 }
01599 
01600 
01601 
01602 
01603 Position2D
01604 NBNode::getEmptyDir() const {
01605     Position2D pos(0, 0);
01606     EdgeVector::const_iterator i;
01607     for (i=myIncomingEdges->begin(); i!=myIncomingEdges->end(); i++) {
01608         NBNode *conn = (*i)->getFromNode();
01609         Position2D toAdd = conn->getPosition();
01610         toAdd.sub(myPosition);
01611         toAdd.mul((SUMOReal) 1.0/sqrt(toAdd.x()*toAdd.x()+toAdd.y()*toAdd.y()));
01612         pos.add(toAdd);
01613     }
01614     for (i=myOutgoingEdges->begin(); i!=myOutgoingEdges->end(); i++) {
01615         NBNode *conn = (*i)->getToNode();
01616         Position2D toAdd = conn->getPosition();
01617         toAdd.sub(myPosition);
01618         toAdd.mul((SUMOReal) 1.0/sqrt(toAdd.x()*toAdd.x()+toAdd.y()*toAdd.y()));
01619         pos.add(toAdd);
01620     }
01621     pos.mul((SUMOReal) -1.0/(myIncomingEdges->size()+myOutgoingEdges->size()));
01622     if (pos.x()==0&&pos.y()==0) {
01623         pos = Position2D(1, 0);
01624     }
01625     pos.norm();
01626     return pos;
01627 }
01628 
01629 
01630 
01631 void
01632 NBNode::invalidateIncomingConnections() {
01633     for (EdgeVector::const_iterator i=myIncomingEdges->begin(); i!=myIncomingEdges->end(); i++) {
01634         (*i)->invalidateConnections();
01635     }
01636 }
01637 
01638 
01639 void
01640 NBNode::invalidateOutgoingConnections() {
01641     for (EdgeVector::const_iterator i=myOutgoingEdges->begin(); i!=myOutgoingEdges->end(); i++) {
01642         (*i)->invalidateConnections();
01643     }
01644 }
01645 
01646 
01647 bool
01648 NBNode::mustBrake(const NBEdge * const from, const NBEdge * const to, int toLane) const throw() {
01649     // check whether it is participant to a traffic light
01650     //  - controlled links are set by the traffic lights, not the normal
01651     //    right-of-way rules
01652     //  - uncontrolled participants (spip lanes etc.) should always break
01653     if (myTrafficLights.size()!=0) {
01654         // ok, we have a traffic light, return true by now, it will be later
01655         //  controlled by the tls
01656         return true;
01657     }
01658     // unregulated->does not need to brake
01659     if (myRequest==0) {
01660         return false;
01661     }
01662     // vehicles which do not have a following lane must always decelerate to the end
01663     if (to==0) {
01664         return true;
01665     }
01666     // check whether any other connection on this node prohibits this connection
01667     bool try1 = myRequest->mustBrake(from, to);
01668     if (!try1||toLane==-1) {
01669         return try1;
01670     }
01671     if (from->getSpeed()<70./3.6) {
01672         return try1;
01673     }
01674     // on highways (on-ramps, in fact):
01675     // check whether any other connection uses the same destination edge
01676     for (EdgeVector::const_iterator i=myIncomingEdges->begin(); i!=myIncomingEdges->end(); i++) {
01677         if ((*i)==from) {
01678             continue;
01679         }
01680         const std::vector<NBEdge::Connection> &connections = (*i)->getConnections();
01681         for (std::vector<NBEdge::Connection>::const_iterator j=connections.begin(); j!=connections.end(); ++j) {
01682             if ((*j).toEdge==to&&((*j).toLane<0||(*j).toLane==toLane)) {
01683                 return true;
01684             }
01685         }
01686     }
01687     return false;
01688 }
01689 
01690 
01691 
01692 bool
01693 NBNode::isLeftMover(const NBEdge * const from, const NBEdge * const to) const throw() {
01694     // when the junction has only one incoming edge, there are no
01695     //  problems caused by left blockings
01696     if (myIncomingEdges->size()==1) {
01697         return false;
01698     }
01699     SUMOReal ccw = GeomHelper::getCCWAngleDiff(from->getAngle(*this), to->getAngle(*this));
01700     SUMOReal cw = GeomHelper::getCWAngleDiff(from->getAngle(*this), to->getAngle(*this));
01701     return cw<ccw;
01702 }
01703 
01704 
01705 bool
01706 NBNode::forbids(const NBEdge * const possProhibitorFrom, const NBEdge * const possProhibitorTo,
01707                 const NBEdge * const possProhibitedFrom, const NBEdge * const possProhibitedTo,
01708                 bool regardNonSignalisedLowerPriority) const throw() {
01709     return myRequest!=0&&myRequest->forbids(possProhibitorFrom, possProhibitorTo,
01710                                             possProhibitedFrom, possProhibitedTo,
01711                                             regardNonSignalisedLowerPriority);
01712 }
01713 
01714 
01715 bool
01716 NBNode::foes(const NBEdge * const from1, const NBEdge * const to1,
01717              const NBEdge * const from2, const NBEdge * const to2) const throw() {
01718     return myRequest!=0&&myRequest->foes(from1, to1, from2, to2);
01719 }
01720 
01721 
01722 void
01723 NBNode::remapRemoved(NBTrafficLightLogicCont &tc,
01724                      NBEdge *removed, const EdgeVector &incoming,
01725                      const EdgeVector &outgoing) {
01726     assert(find(incoming.begin(), incoming.end(), removed)==incoming.end());
01727     bool changed = true;
01728     while (changed) {
01729         changed = false;
01730         NBConnectionProhibits blockedConnectionsTmp = myBlockedConnections;
01731         NBConnectionProhibits blockedConnectionsNew;
01732         // remap in connections
01733         for (NBConnectionProhibits::iterator i=blockedConnectionsTmp.begin(); i!=blockedConnectionsTmp.end(); i++) {
01734             const NBConnection &blocker = (*i).first;
01735             const NBConnectionVector &blocked = (*i).second;
01736             // check the blocked connections first
01737             // check whether any of the blocked must be changed
01738             bool blockedChanged = false;
01739             NBConnectionVector newBlocked;
01740             NBConnectionVector::const_iterator j;
01741             for (j=blocked.begin(); j!=blocked.end(); j++) {
01742                 const NBConnection &sblocked = *j;
01743                 if (sblocked.getFrom()==removed||sblocked.getTo()==removed) {
01744                     blockedChanged = true;
01745                 }
01746             }
01747             // adapt changes if so
01748             for (j=blocked.begin(); blockedChanged&&j!=blocked.end(); j++) {
01749                 const NBConnection &sblocked = *j;
01750                 if (sblocked.getFrom()==removed&&sblocked.getTo()==removed) {
01751                     /*                    for(EdgeVector::const_iterator k=incoming.begin(); k!=incoming.end(); k++) {
01752                     !!!                        newBlocked.push_back(NBConnection(*k, *k));
01753                                         }*/
01754                 } else if (sblocked.getFrom()==removed) {
01755                     assert(sblocked.getTo()!=removed);
01756                     for (EdgeVector::const_iterator k=incoming.begin(); k!=incoming.end(); k++) {
01757                         newBlocked.push_back(NBConnection(*k, sblocked.getTo()));
01758                     }
01759                 } else if (sblocked.getTo()==removed) {
01760                     assert(sblocked.getFrom()!=removed);
01761                     for (EdgeVector::const_iterator k=outgoing.begin(); k!=outgoing.end(); k++) {
01762                         newBlocked.push_back(NBConnection(sblocked.getFrom(), *k));
01763                     }
01764                 } else {
01765                     newBlocked.push_back(NBConnection(sblocked.getFrom(), sblocked.getTo()));
01766                 }
01767             }
01768             if (blockedChanged) {
01769                 blockedConnectionsNew[blocker] = newBlocked;
01770                 changed = true;
01771             }
01772             // if the blocked were kept
01773             else {
01774                 if (blocker.getFrom()==removed&&blocker.getTo()==removed) {
01775                     changed = true;
01776                     /*                    for(EdgeVector::const_iterator k=incoming.begin(); k!=incoming.end(); k++) {
01777                     !!!                        blockedConnectionsNew[NBConnection(*k, *k)] = blocked;
01778                                         }*/
01779                 } else if (blocker.getFrom()==removed) {
01780                     assert(blocker.getTo()!=removed);
01781                     changed = true;
01782                     for (EdgeVector::const_iterator k=incoming.begin(); k!=incoming.end(); k++) {
01783                         blockedConnectionsNew[NBConnection(*k, blocker.getTo())] = blocked;
01784                     }
01785                 } else if (blocker.getTo()==removed) {
01786                     assert(blocker.getFrom()!=removed);
01787                     changed = true;
01788                     for (EdgeVector::const_iterator k=outgoing.begin(); k!=outgoing.end(); k++) {
01789                         blockedConnectionsNew[NBConnection(blocker.getFrom(), *k)] = blocked;
01790                     }
01791                 } else {
01792                     blockedConnectionsNew[blocker] = blocked;
01793                 }
01794             }
01795         }
01796         myBlockedConnections = blockedConnectionsNew;
01797     }
01798     // remap in traffic lights
01799     tc.remapRemoved(removed, incoming, outgoing);
01800 }
01801 
01802 
01803 NBMMLDirection
01804 NBNode::getMMLDirection(const NBEdge * const incoming, const NBEdge * const outgoing) const throw() {
01805     // ok, no connection at all -> dead end
01806     if (outgoing==0) {
01807         return MMLDIR_NODIR;
01808     }
01809     // turning direction
01810     if (incoming->isTurningDirectionAt(this, outgoing)) {
01811         return MMLDIR_TURN;
01812     }
01813     // get the angle between incoming/outgoing at the junction
01814     SUMOReal angle =
01815         NBHelpers::normRelAngle(incoming->getAngle(*this), outgoing->getAngle(*this));
01816     // ok, should be a straight connection
01817     if (abs((int) angle)+1<45) {
01818         return MMLDIR_STRAIGHT;
01819     }
01820 
01821     // check for left and right, first
01822     if (angle>0) {
01823         // check whether any other edge goes further to the right
01824         EdgeVector::const_iterator i =
01825             find(myAllEdges.begin(), myAllEdges.end(), outgoing);
01826         NBContHelper::nextCW(&myAllEdges, i);
01827         while ((*i)!=incoming) {
01828             if ((*i)->getFromNode()==this) {
01829                 return MMLDIR_PARTRIGHT;
01830             }
01831             NBContHelper::nextCW(&myAllEdges, i);
01832         }
01833         return MMLDIR_RIGHT;
01834     }
01835     // check whether any other edge goes further to the left
01836     EdgeVector::const_iterator i =
01837         find(myAllEdges.begin(), myAllEdges.end(), outgoing);
01838     NBContHelper::nextCCW(&myAllEdges, i);
01839     while ((*i)!=incoming) {
01840         if ((*i)->getFromNode()==this&&!incoming->isTurningDirectionAt(this, *i)) {
01841             return MMLDIR_PARTLEFT;
01842         }
01843         NBContHelper::nextCCW(&myAllEdges, i);
01844     }
01845     return MMLDIR_LEFT;
01846 }
01847 
01848 
01849 char
01850 NBNode::stateCode(NBEdge *incoming, NBEdge *outgoing, int fromlane, bool mayDefinitelyPass) const throw() {
01851     if (outgoing==0) {
01852         return 'O'; // always off
01853     }
01854     if (myType==NODETYPE_RIGHT_BEFORE_LEFT) {
01855         return '='; // all the same
01856     }
01857     if ((!incoming->isInnerEdge()&&mustBrake(incoming, outgoing, fromlane)) && !mayDefinitelyPass) {
01858         return 'm'; // minor road
01859     }
01860     // traffic lights are not regardedm here
01861     return 'M';
01862 }
01863 
01864 
01865 bool
01866 NBNode::checkIsRemovable() const {
01867     // check whether this node is included in a traffic light
01868     if (myTrafficLights.size()!=0) {
01869         return false;
01870     }
01871     EdgeVector::const_iterator i;
01872     // one in, one out -> just a geometry ...
01873     if (myOutgoingEdges->size()==1&&myIncomingEdges->size()==1) {
01874         // ... if types match ...
01875         if (!(*myIncomingEdges)[0]->expandableBy((*myOutgoingEdges)[0])) {
01876             return false;
01877         }
01878         //
01879         return (*myIncomingEdges)[0]->getFromNode()!=(*myOutgoingEdges)[0]->getToNode();
01880     }
01881     // two in, two out -> may be something else
01882     if (myOutgoingEdges->size()==2&&myIncomingEdges->size()==2) {
01883         // check whether the origin nodes of the incoming edges differ
01884         std::set<NBNode*> origSet;
01885         for (i=myIncomingEdges->begin(); i!=myIncomingEdges->end(); i++) {
01886             origSet.insert((*i)->getFromNode());
01887         }
01888         if (origSet.size()<2) {
01889             return false;
01890         }
01891         // check whether this node is an intermediate node of
01892         //  a two-directional street
01893         for (i=myIncomingEdges->begin(); i!=myIncomingEdges->end(); i++) {
01894             // try to find the opposite direction
01895             NBNode *origin = (*i)->getFromNode();
01896             // find the back direction of the current edge
01897             EdgeVector::const_iterator j =
01898                 find_if(myOutgoingEdges->begin(), myOutgoingEdges->end(),
01899                         NBContHelper::edge_with_destination_finder(origin));
01900             // check whether the back direction exists
01901             if (j!=myOutgoingEdges->end()) {
01902                 // check whether the edge from the backdirection (must be
01903                 //  the counter-clockwise one) may be joined with the current
01904                 NBContHelper::nextCCW(myOutgoingEdges, j);
01905                 // check whether the types allow joining
01906                 if (!(*i)->expandableBy(*j)) {
01907                     return false;
01908                 }
01909             } else {
01910                 // ok, at least one outgoing edge is not an opposite
01911                 //  of an incoming one
01912                 return false;
01913             }
01914         }
01915         return true;
01916     }
01917     // ok, a real node
01918     return false;
01919 }
01920 
01921 
01922 std::vector<std::pair<NBEdge*, NBEdge*> >
01923 NBNode::getEdgesToJoin() const {
01924     assert(checkIsRemovable());
01925     std::vector<std::pair<NBEdge*, NBEdge*> > ret;
01926     // one in, one out-case
01927     if (myOutgoingEdges->size()==1&&myIncomingEdges->size()==1) {
01928         ret.push_back(
01929             std::pair<NBEdge*, NBEdge*>(
01930                 (*myIncomingEdges)[0], (*myOutgoingEdges)[0]));
01931         return ret;
01932     }
01933     // two in, two out-case
01934     for (EdgeVector::const_iterator i=myIncomingEdges->begin(); i!=myIncomingEdges->end(); i++) {
01935         NBNode *origin = (*i)->getFromNode();
01936         EdgeVector::const_iterator j =
01937             find_if(myOutgoingEdges->begin(), myOutgoingEdges->end(),
01938                     NBContHelper::edge_with_destination_finder(origin));
01939         NBContHelper::nextCCW(myOutgoingEdges, j);
01940         ret.push_back(std::pair<NBEdge*, NBEdge*>(*i, *j));
01941     }
01942     return ret;
01943 }
01944 
01945 
01946 const Position2DVector &
01947 NBNode::getShape() const {
01948     return myPoly;
01949 }
01950 
01951 std::string
01952 NBNode::getInternalLaneID(NBEdge *from, unsigned int fromlane,
01953                           NBEdge *to, unsigned int tolane) const {
01954     unsigned int l = 0;
01955     for (EdgeVector::const_iterator i=myIncomingEdges->begin(); i!=myIncomingEdges->end(); i++) {
01956         unsigned int noLanesEdge = (*i)->getNoLanes();
01957         for (unsigned int j=0; j<noLanesEdge; j++) {
01958             std::vector<NBEdge::Connection> elv = (*i)->getConnectionsFromLane(j);
01959             for (std::vector<NBEdge::Connection>::iterator k=elv.begin(); k!=elv.end(); ++k) {
01960                 if ((*k).toEdge==0) {
01961                     continue;
01962                 }
01963                 if ((from==*i)&&(j==fromlane)&&((*k).toEdge==to)&&((*k).toLane==tolane)) {
01964                     return ":" + myID + "_" + toString(l);
01965                 }
01966                 l++;
01967             }
01968         }
01969     }
01970     throw 1;
01971 }
01972 
01973 
01974 SUMOReal
01975 NBNode::getMaxEdgeWidth() const {
01976     EdgeVector::const_iterator i=myAllEdges.begin();
01977     assert(i!=myAllEdges.end());
01978     SUMOReal ret = (*i)->width();
01979     ++i;
01980     for (; i!=myAllEdges.end(); i++) {
01981         ret = ret > (*i)->width()
01982               ? ret
01983               : (*i)->width();
01984     }
01985     return ret;
01986 }
01987 
01988 
01989 NBEdge *
01990 NBNode::getConnectionTo(NBNode *n) const {
01991     std::vector<NBEdge*>::iterator i;
01992     for (i=myOutgoingEdges->begin(); i!=myOutgoingEdges->end(); i++) {
01993         if ((*i)->getToNode()==n) {
01994             return (*i);
01995         }
01996     }
01997     return 0;
01998 }
01999 
02000 
02001 bool
02002 NBNode::isNearDistrict() const {
02003     if (isDistrict()) {
02004         return false;
02005     }
02006     EdgeVector edges;
02007     copy(getIncomingEdges().begin(), getIncomingEdges().end(),
02008          back_inserter(edges));
02009     copy(getOutgoingEdges().begin(), getOutgoingEdges().end(),
02010          back_inserter(edges));
02011     for (EdgeVector::const_iterator j=edges.begin(); j!=edges.end(); ++j) {
02012         NBEdge *t = *j;
02013         NBNode *other = 0;
02014         if (t->getToNode()==this) {
02015             other = t->getFromNode();
02016         } else {
02017             other = t->getToNode();
02018         }
02019         EdgeVector edges2;
02020         copy(other->getIncomingEdges().begin(), other->getIncomingEdges().end(), back_inserter(edges2));
02021         copy(other->getOutgoingEdges().begin(), other->getOutgoingEdges().end(), back_inserter(edges2));
02022         for (EdgeVector::const_iterator k=edges2.begin(); k!=edges2.end(); ++k) {
02023             if ((*k)->getFromNode()->isDistrict()||(*k)->getToNode()->isDistrict()) {
02024                 return true;
02025             }
02026         }
02027     }
02028     return false;
02029 }
02030 
02031 
02032 bool
02033 NBNode::isDistrict() const {
02034     return myType==NODETYPE_DISTRICT;
02035 }
02036 
02037 
02038 
02039 /****************************************************************************/
02040 

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