SUMO - Simulation of Urban MObility

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 (C) 2001-2011 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 <iterator>
00039 #include <utils/common/UtilExceptions.h>
00040 #include <utils/common/StringUtils.h>
00041 #include <utils/options/OptionsCont.h>
00042 #include <utils/geom/Line.h>
00043 #include <utils/geom/GeomHelper.h>
00044 #include <utils/geom/bezier.h>
00045 #include <utils/common/MsgHandler.h>
00046 #include <utils/common/StdDefs.h>
00047 #include <utils/common/ToString.h>
00048 #include <utils/geom/GeoConvHelper.h>
00049 #include <utils/iodevices/OutputDevice.h>
00050 #include <iomanip>
00051 #include "NBNode.h"
00052 #include "NBNodeCont.h"
00053 #include "NBNodeShapeComputer.h"
00054 #include "NBEdgeCont.h"
00055 #include "NBTypeCont.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 // static members
00070 // ===========================================================================
00071 
00072 // ===========================================================================
00073 // method definitions
00074 // ===========================================================================
00075 /* -------------------------------------------------------------------------
00076  * NBNode::ApproachingDivider-methods
00077  * ----------------------------------------------------------------------- */
00078 NBNode::ApproachingDivider::ApproachingDivider(
00079     EdgeVector* approaching, NBEdge* currentOutgoing) throw() :
00080     myApproaching(approaching), myCurrentOutgoing(currentOutgoing) {
00081     // check whether origin lanes have been given
00082     assert(myApproaching!=0);
00083 }
00084 
00085 
00086 NBNode::ApproachingDivider::~ApproachingDivider() throw() {}
00087 
00088 
00089 void
00090 NBNode::ApproachingDivider::execute(const unsigned int src, const unsigned int dest) throw() {
00091     assert(myApproaching->size()>src);
00092     // get the origin edge
00093     NBEdge* incomingEdge = (*myApproaching)[src];
00094     if (incomingEdge->getStep()==NBEdge::LANES2LANES_DONE||incomingEdge->getStep()==NBEdge::LANES2LANES_USER) {
00095         return;
00096     }
00097     std::vector<int> approachingLanes =
00098         incomingEdge->getConnectionLanes(myCurrentOutgoing);
00099     assert(approachingLanes.size()!=0);
00100     std::deque<int> *approachedLanes = spread(approachingLanes, dest);
00101     assert(approachedLanes->size()<=myCurrentOutgoing->getNumLanes());
00102     // set lanes
00103     for (unsigned int i=0; i<approachedLanes->size(); i++) {
00104         unsigned int approached = (*approachedLanes)[i];
00105         assert(approachedLanes->size()>i);
00106         assert(approachingLanes.size()>i);
00107         incomingEdge->setConnection((unsigned int) approachingLanes[i], myCurrentOutgoing,
00108                                     approached, NBEdge::L2L_COMPUTED);
00109     }
00110     delete approachedLanes;
00111 }
00112 
00113 
00114 std::deque<int> *
00115 NBNode::ApproachingDivider::spread(const std::vector<int> &approachingLanes,
00116                                    int dest) const {
00117     std::deque<int> *ret = new std::deque<int>();
00118     unsigned int noLanes = (unsigned int) approachingLanes.size();
00119     // when only one lane is approached, we check, whether the SUMOReal-value
00120     //  is assigned more to the left or right lane
00121     if (noLanes==1) {
00122         ret->push_back(dest);
00123         return ret;
00124     }
00125 
00126     unsigned int noOutgoingLanes = myCurrentOutgoing->getNumLanes();
00127     //
00128     ret->push_back(dest);
00129     unsigned int noSet = 1;
00130     int roffset = 1;
00131     int loffset = 1;
00132     while (noSet<noLanes) {
00133         // It may be possible, that there are not enough lanes the source
00134         //  lanes may be divided on
00135         //  In this case, they remain unset
00136         //  !!! this is only a hack. It is possible, that this yields in
00137         //   uncommon divisions
00138         if (noOutgoingLanes==noSet) {
00139             return ret;
00140         }
00141 
00142         // as due to the conversion of SUMOReal->uint the numbers will be lower
00143         //  than they should be, we try to append to the left side first
00144         //
00145         // check whether the left boundary of the approached street has
00146         //  been overridden; if so, move all lanes to the right
00147         if (dest+loffset >= static_cast<int>(noOutgoingLanes)) {
00148             loffset -= 1;
00149             roffset += 1;
00150             for (unsigned int i=0; i<ret->size(); i++) {
00151                 (*ret)[i] = (*ret)[i] - 1;
00152             }
00153         }
00154         // append the next lane to the left of all edges
00155         //  increase the position (destination edge)
00156         ret->push_back(dest+loffset);
00157         noSet++;
00158         loffset += 1;
00159 
00160         // as above
00161         if (noOutgoingLanes==noSet) {
00162             return ret;
00163         }
00164 
00165         // now we try to append the next lane to the right side, when needed
00166         if (noSet<noLanes) {
00167             // check whether the right boundary of the approached street has
00168             //  been overridden; if so, move all lanes to the right
00169             if (dest < roffset) {
00170                 loffset += 1;
00171                 roffset -= 1;
00172                 for (unsigned int i=0; i<ret->size(); i++) {
00173                     (*ret)[i] = (*ret)[i] + 1;
00174                 }
00175             }
00176             ret->push_front(dest-roffset);
00177             noSet++;
00178             roffset += 1;
00179         }
00180     }
00181     return ret;
00182 }
00183 
00184 
00185 
00186 
00187 /* -------------------------------------------------------------------------
00188  * NBNode-methods
00189  * ----------------------------------------------------------------------- */
00190 NBNode::NBNode(const std::string& id, const Position& position) throw() :
00191     Named(StringUtils::convertUmlaute(id)),
00192     myPosition(position),
00193     myType(NODETYPE_UNKNOWN), myDistrict(0), myRequest(0)
00194 { }
00195 
00196 
00197 NBNode::NBNode(const std::string& id, const Position& position,
00198                SumoXMLNodeType type) throw() :
00199     Named(StringUtils::convertUmlaute(id)),
00200     myPosition(position),
00201     myType(type), myDistrict(0), myRequest(0)
00202 { }
00203 
00204 
00205 NBNode::NBNode(const std::string& id, const Position& position, NBDistrict* district) throw() :
00206     Named(StringUtils::convertUmlaute(id)),
00207     myPosition(position),
00208     myType(NODETYPE_DISTRICT), myDistrict(district), myRequest(0)
00209 { }
00210 
00211 
00212 NBNode::~NBNode() throw() {
00213     delete myRequest;
00214 }
00215 
00216 
00217 void
00218 NBNode::reinit(const Position& position, SumoXMLNodeType type,
00219                bool updateEdgeGeometries) {
00220     myPosition = position;
00221     // patch type
00222     myType = type;
00223     if (myType!=NODETYPE_TRAFFIC_LIGHT) {
00224         removeTrafficLights();
00225     }
00226     if (updateEdgeGeometries) {
00227         for (EdgeVector::iterator i=myIncomingEdges.begin(); i!=myIncomingEdges.end(); i++) {
00228             PositionVector geom = (*i)->getGeometry();
00229             geom[-1] = myPosition;
00230             (*i)->setGeometry(geom);
00231         }
00232         for (EdgeVector::iterator i=myOutgoingEdges.begin(); i!=myOutgoingEdges.end(); i++) {
00233             PositionVector geom = (*i)->getGeometry();
00234             geom[0] = myPosition;
00235             (*i)->setGeometry(geom);
00236         }
00237     }
00238 }
00239 
00240 
00241 
00242 // -----------  Applying offset
00243 void
00244 NBNode::reshiftPosition(SUMOReal xoff, SUMOReal yoff) {
00245     myPosition.reshiftRotate(xoff, yoff, 0);
00246     myPoly.reshiftRotate(xoff, yoff, 0);
00247 }
00248 
00249 
00250 // -----------  Methods for dealing with assigned traffic lights
00251 void
00252 NBNode::addTrafficLight(NBTrafficLightDefinition* tlDef) throw() {
00253     myTrafficLights.insert(tlDef);
00254     myType = NODETYPE_TRAFFIC_LIGHT;
00255 }
00256 
00257 
00258 void
00259 NBNode::removeTrafficLight(NBTrafficLightDefinition* tlDef) throw() {
00260     tlDef->removeNode(this);
00261     myTrafficLights.erase(tlDef);
00262 }
00263 
00264 
00265 void
00266 NBNode::removeTrafficLights() throw() {
00267     std::set<NBTrafficLightDefinition*> trafficLights = myTrafficLights; // make a copy because we will modify the original
00268     for (std::set<NBTrafficLightDefinition*>::const_iterator i=trafficLights.begin(); i!=trafficLights.end(); ++i) {
00269         removeTrafficLight(*i);
00270     }
00271 }
00272 
00273 
00274 bool
00275 NBNode::isJoinedTLSControlled() const throw() {
00276     if (!isTLControlled()) {
00277         return false;
00278     }
00279     for (std::set<NBTrafficLightDefinition*>::const_iterator i=myTrafficLights.begin(); i!=myTrafficLights.end(); ++i) {
00280         if ((*i)->getID().find("joined")==0) {
00281             return true;
00282         }
00283     }
00284     return false;
00285 }
00286 
00287 
00288 // ----------- Prunning the input
00289 unsigned int
00290 NBNode::removeDummyEdges(NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tc) {
00291     unsigned int ret = 0;
00292     unsigned int pos = 0;
00293     EdgeVector::const_iterator j=myIncomingEdges.begin();
00294     while (j!=myIncomingEdges.end()) {
00295         // skip edges which are only incoming and not outgoing
00296         if (find(myOutgoingEdges.begin(), myOutgoingEdges.end(), *j)==myOutgoingEdges.end()) {
00297             ++j;
00298             ++pos;
00299             continue;
00300         }
00301         // an edge with both its origin and destination being the current
00302         //  node should be removed
00303         NBEdge* dummy = *j;
00304         WRITE_WARNING(" Removing dummy edge '" + dummy->getID() + "'");
00305         // get the list of incoming edges connected to the dummy
00306         EdgeVector incomingConnected;
00307         for (EdgeVector::const_iterator i=myIncomingEdges.begin(); i!=myIncomingEdges.end(); i++) {
00308             if ((*i)->isConnectedTo(dummy)&&*i!=dummy) {
00309                 incomingConnected.push_back(*i);
00310             }
00311         }
00312         // get the list of outgoing edges connected to the dummy
00313         EdgeVector outgoingConnected;
00314         for (EdgeVector::const_iterator i=myOutgoingEdges.begin(); i!=myOutgoingEdges.end(); i++) {
00315             if (dummy->isConnectedTo(*i)&&*i!=dummy) {
00316                 outgoingConnected.push_back(*i);
00317             }
00318         }
00319         // let the dummy remap its connections
00320         dummy->remapConnections(incomingConnected);
00321         remapRemoved(tc, dummy, incomingConnected, outgoingConnected);
00322         // delete the dummy
00323         ec.erase(dc, dummy);
00324         j = myIncomingEdges.begin() + pos;
00325         ++ret;
00326     }
00327     return ret;
00328 }
00329 
00330 
00331 // -----------
00332 void
00333 NBNode::addIncomingEdge(NBEdge* edge) {
00334     assert(edge!=0);
00335     if (find(myIncomingEdges.begin(), myIncomingEdges.end(), edge)==myIncomingEdges.end()) {
00336         myIncomingEdges.push_back(edge);
00337         myAllEdges.push_back(edge);
00338     }
00339 }
00340 
00341 
00342 void
00343 NBNode::addOutgoingEdge(NBEdge* edge) {
00344     assert(edge!=0);
00345     if (find(myOutgoingEdges.begin(), myOutgoingEdges.end(), edge)==myOutgoingEdges.end()) {
00346         myOutgoingEdges.push_back(edge);
00347         myAllEdges.push_back(edge);
00348     }
00349 }
00350 
00351 
00352 bool
00353 NBNode::swapWhenReversed(bool leftHand,
00354                          const EdgeVector::iterator& i1,
00355                          const EdgeVector::iterator& i2) {
00356     NBEdge* e1 = *i1;
00357     NBEdge* e2 = *i2;
00358     if (leftHand) {
00359         if (e1->getToNode()==this && e1->isTurningDirectionAt(this, e2)) {
00360             std::swap(*i1, *i2);
00361             return true;
00362         }
00363     } else {
00364         if (e2->getToNode()==this && e2->isTurningDirectionAt(this, e1)) {
00365             std::swap(*i1, *i2);
00366             return true;
00367         }
00368     }
00369     return false;
00370 }
00371 
00372 void
00373 NBNode::computePriorities() {
00374     // reset all priorities
00375     EdgeVector::iterator i;
00376     // check if the junction is not a real junction
00377     if (myIncomingEdges.size()==1&&myOutgoingEdges.size()==1) {
00378         for (i=myAllEdges.begin(); i!=myAllEdges.end(); i++) {
00379             (*i)->setJunctionPriority(this, 1);
00380         }
00381         return;
00382     }
00383     // preset all junction's edge priorities to zero
00384     for (i=myAllEdges.begin(); i!=myAllEdges.end(); i++) {
00385         (*i)->setJunctionPriority(this, 0);
00386     }
00387     // compute the priorities on junction when needed
00388     if (myType!=NODETYPE_RIGHT_BEFORE_LEFT) {
00389         setPriorityJunctionPriorities();
00390     }
00391 }
00392 
00393 
00394 void
00395 NBNode::computeType(const NBTypeCont& tc) {
00396     // the type may already be set from the data
00397     if (myType!=NODETYPE_UNKNOWN) {
00398         return;
00399     }
00400     // check whether the junction is not a real junction
00401     if (myIncomingEdges.size()==1) {
00402         myType = NODETYPE_PRIORITY_JUNCTION;
00403         return;
00404     }
00405     if (isSimpleContinuation()) {
00406         myType = NODETYPE_PRIORITY_JUNCTION;
00407         return;
00408     }
00409     // choose the uppermost type as default
00410     SumoXMLNodeType type = NODETYPE_RIGHT_BEFORE_LEFT;
00411     // determine the type
00412     for (EdgeVector::const_iterator i=myIncomingEdges.begin(); i!=myIncomingEdges.end(); i++) {
00413         for (EdgeVector::const_iterator j=i+1; j!=myIncomingEdges.end(); j++) {
00414             bool isOpposite = false;
00415             if (getOppositeIncoming(*j)==*i&&myIncomingEdges.size()>2) {
00416                 isOpposite = true;
00417             }
00418 
00419             // This usage of defaults is not very well, still we do not have any
00420             //  methods for the conversion of foreign, sometimes not supplied
00421             //  road types into an own format
00422             SumoXMLNodeType tmptype = type;
00423             if (!isOpposite) {
00424                 tmptype = tc.getJunctionType((*i)->getSpeed(), (*j)->getSpeed());
00425                 if (tmptype<type&&tmptype!=NODETYPE_UNKNOWN&&tmptype!=NODETYPE_NOJUNCTION) {
00426                     type = tmptype;
00427                 }
00428             }
00429         }
00430     }
00431     myType = type;
00432 }
00433 
00434 
00435 bool
00436 NBNode::isSimpleContinuation() const {
00437     // one in, one out->continuation
00438     if (myIncomingEdges.size()==1&&myOutgoingEdges.size()==1) {
00439         // both must have the same number of lanes
00440         return (*(myIncomingEdges.begin()))->getNumLanes()==(*(myOutgoingEdges.begin()))->getNumLanes();
00441     }
00442     // two in and two out and both in reverse direction
00443     if (myIncomingEdges.size()==2&&myOutgoingEdges.size()==2) {
00444         for (EdgeVector::const_iterator i=myIncomingEdges.begin(); i!=myIncomingEdges.end(); i++) {
00445             NBEdge* in = *i;
00446             EdgeVector::const_iterator opposite = find_if(myOutgoingEdges.begin(), myOutgoingEdges.end(), NBContHelper::opposite_finder(in, this));
00447             // must have an opposite edge
00448             if (opposite==myOutgoingEdges.end()) {
00449                 return false;
00450             }
00451             // both must have the same number of lanes
00452             NBContHelper::nextCW(myOutgoingEdges, opposite);
00453             if (in->getNumLanes()!=(*opposite)->getNumLanes()) {
00454                 return false;
00455             }
00456         }
00457         return true;
00458     }
00459     // nope
00460     return false;
00461 }
00462 
00463 
00464 bool
00465 samePriority(NBEdge* e1, NBEdge* e2) {
00466     if (e1==e2) {
00467         return true;
00468     }
00469     if (e1->getPriority()!=e2->getPriority()) {
00470         return false;
00471     }
00472     if ((int) e1->getSpeed()!=(int) e2->getSpeed()) {
00473         return false;
00474     }
00475     return (int) e1->getNumLanes()==(int) e2->getNumLanes();
00476 }
00477 
00478 
00479 void
00480 NBNode::setPriorityJunctionPriorities() {
00481     if (myIncomingEdges.size()==0||myOutgoingEdges.size()==0) {
00482         return;
00483     }
00484     EdgeVector incoming = myIncomingEdges;
00485     EdgeVector outgoing = myOutgoingEdges;
00486     // what we do want to have is to extract the pair of roads that are
00487     //  the major roads for this junction
00488     // let's get the list of incoming edges with the highest priority
00489     std::sort(incoming.begin(), incoming.end(), NBContHelper::edge_by_priority_sorter());
00490     EdgeVector bestIncoming;
00491     NBEdge* best = incoming[0];
00492     while (incoming.size()>0&&samePriority(best, incoming[0])) {
00493         bestIncoming.push_back(*incoming.begin());
00494         incoming.erase(incoming.begin());
00495     }
00496     // now, let's get the list of best outgoing
00497     assert(outgoing.size()!=0);
00498     sort(outgoing.begin(), outgoing.end(), NBContHelper::edge_by_priority_sorter());
00499     EdgeVector bestOutgoing;
00500     best = outgoing[0];
00501     while (outgoing.size()>0&&samePriority(best, outgoing[0])) {//->getPriority()==best->getPriority()) {
00502         bestOutgoing.push_back(*outgoing.begin());
00503         outgoing.erase(outgoing.begin());
00504     }
00505     // now, let's compute for each of the best incoming edges
00506     //  the incoming which is most opposite
00507     //  the outgoing which is most opposite
00508     EdgeVector::iterator i;
00509     std::map<NBEdge*, NBEdge*> counterIncomingEdges;
00510     std::map<NBEdge*, NBEdge*> counterOutgoingEdges;
00511     incoming = myIncomingEdges;
00512     outgoing = myOutgoingEdges;
00513     for (i=bestIncoming.begin(); i!=bestIncoming.end(); ++i) {
00514         std::sort(incoming.begin(), incoming.end(), NBContHelper::edge_opposite_direction_sorter(*i, this));
00515         counterIncomingEdges[*i] = *incoming.begin();
00516         std::sort(outgoing.begin(), outgoing.end(), NBContHelper::edge_opposite_direction_sorter(*i, this));
00517         counterOutgoingEdges[*i] = *outgoing.begin();
00518     }
00519     // ok, let's try
00520     // 1) there is one best incoming road
00521     if (bestIncoming.size()==1) {
00522         // let's mark this road as the best
00523         NBEdge* best1 = extractAndMarkFirst(bestIncoming);
00524         if (bestOutgoing.size()!=0) {
00525             // mark the best outgoing as the continuation
00526             sort(bestOutgoing.begin(), bestOutgoing.end(), NBContHelper::edge_similar_direction_sorter(best1));
00527             extractAndMarkFirst(bestOutgoing);
00528         }
00529         return;
00530     }
00531     // 2b) there are more than one best incoming roads
00532     //      and the same number of best outgoing roads
00533 
00534     // ok, what we want to do in this case is to determine which incoming
00535     //  has the best continuation...
00536     // This means, when several incoming roads have the same priority,
00537     //  we want a (any) straight connection to be more priorised than a turning
00538     SUMOReal bestAngle = 0;
00539     NBEdge* bestFirst = 0;
00540     NBEdge* bestSecond = 0;
00541     bool hadBest = false;
00542     for (i=bestIncoming.begin(); i!=bestIncoming.end(); ++i) {
00543         EdgeVector::iterator j;
00544         NBEdge* t1 = *i;
00545         SUMOReal angle1 = t1->getAngle()+180;
00546         if (angle1>=360) {
00547             angle1 -= 360;
00548         }
00549         for (j=i+1; j!=bestIncoming.end(); ++j) {
00550             NBEdge* t2 = *j;
00551             SUMOReal angle2 = t2->getAngle()+180;
00552             if (angle2>=360) {
00553                 angle2 -= 360;
00554             }
00555             SUMOReal angle = GeomHelper::getMinAngleDiff(angle1, angle2);
00556             if (!hadBest||angle>bestAngle) {
00557                 bestAngle = angle;
00558                 bestFirst = *i;
00559                 bestSecond = *j;
00560                 hadBest = true;
00561             }
00562         }
00563     }
00564     bestFirst->setJunctionPriority(this, 1);
00565     sort(bestOutgoing.begin(), bestOutgoing.end(), NBContHelper::edge_similar_direction_sorter(bestFirst));
00566     if (bestOutgoing.size()!=0) {
00567         extractAndMarkFirst(bestOutgoing);
00568     }
00569     bestSecond->setJunctionPriority(this, 1);
00570     sort(bestOutgoing.begin(), bestOutgoing.end(), NBContHelper::edge_similar_direction_sorter(bestSecond));
00571     if (bestOutgoing.size()!=0) {
00572         extractAndMarkFirst(bestOutgoing);
00573     }
00574 }
00575 
00576 
00577 NBEdge*
00578 NBNode::extractAndMarkFirst(EdgeVector& s) {
00579     if (s.size()==0) {
00580         return 0;
00581     }
00582     NBEdge* ret = s.front();
00583     s.erase(s.begin());
00584     ret->setJunctionPriority(this, 1);
00585     return ret;
00586 }
00587 
00588 
00589 PositionVector
00590 NBNode::computeInternalLaneShape(NBEdge* fromE, int fromL,
00591                                  NBEdge* toE, int toL, int numPoints) const {
00592     if (fromL>=(int) fromE->getNumLanes()) {
00593         throw ProcessError("Connection '" + fromE->getID() + "_" + toString(fromL) + "->" + toE->getID() + "_" + toString(toL) + "' starts at a not existing lane.");
00594     }
00595     if (toL>=(int) toE->getNumLanes()) {
00596         throw ProcessError("Connection '" + fromE->getID() + "_" + toString(fromL) + "->" + toE->getID() + "_" + toString(toL) + "' yields in a not existing lane.");
00597     }
00598     bool noSpline = false;
00599     PositionVector ret;
00600     PositionVector init;
00601     Position beg = fromE->getLaneShape(fromL).getEnd();
00602     Position end = toE->getLaneShape(toL).getBegin();
00603     Position intersection;
00604     unsigned int noInitialPoints = 0;
00605     if (beg.distanceTo(end) <= POSITION_EPS) {
00606         noSpline = true;
00607     } else {
00608         if (fromE->getTurnDestination()==toE) {
00609             // turnarounds:
00610             //  - end of incoming lane
00611             //  - position between incoming/outgoing end/begin shifted by the distace orthogonally
00612             //  - begin of outgoing lane
00613             noInitialPoints = 3;
00614             init.push_back(beg);
00615             Line straightConn(fromE->getLaneShape(fromL)[-1],toE->getLaneShape(toL)[0]);
00616             Position straightCenter = straightConn.getPositionAtDistance((SUMOReal) straightConn.length() / (SUMOReal) 2.);
00617             Position center = straightCenter;//.add(straightCenter);
00618             Line cross(straightConn);
00619             cross.sub(cross.p1().x(), cross.p1().y());
00620             cross.rotateAtP1(PI/2);
00621             center.sub(cross.p2());
00622             init.push_back(center);
00623             init.push_back(end);
00624         } else {
00625             const SUMOReal angle = fabs(fromE->getLaneShape(fromL).getEndLine().atan2Angle() - toE->getLaneShape(toL).getBegLine().atan2Angle());
00626             if (angle < PI/4. || angle > 7./4.*PI) {
00627                 // very low angle: almost straight
00628                 noInitialPoints = 4;
00629                 init.push_back(beg);
00630                 Line begL = fromE->getLaneShape(fromL).getEndLine();
00631                 begL.extrapolateSecondBy(100);
00632                 Line endL = toE->getLaneShape(toL).getBegLine();
00633                 endL.extrapolateFirstBy(100);
00634                 SUMOReal distance = beg.distanceTo(end);
00635                 if (distance>10) {
00636                     {
00637                         SUMOReal off1 = fromE->getLaneShape(fromL).getEndLine().length() + (SUMOReal) 5. * (SUMOReal) fromE->getNumLanes();
00638                         off1 = MIN2(off1, (SUMOReal)(fromE->getLaneShape(fromL).getEndLine().length()+distance/2.));
00639                         Position tmp = begL.getPositionAtDistance(off1);
00640                         init.push_back(tmp);
00641                     }
00642                     {
00643                         SUMOReal off1 = (SUMOReal) 100. - (SUMOReal) 5. * (SUMOReal) toE->getNumLanes();
00644                         off1 = MAX2(off1, (SUMOReal)(100.-distance/2.));
00645                         Position tmp = endL.getPositionAtDistance(off1);
00646                         init.push_back(tmp);
00647                     }
00648                 } else {
00649                     noSpline = true;
00650                 }
00651                 init.push_back(end);
00652             } else {
00653                 // turning
00654                 //  - end of incoming lane
00655                 //  - intersection of the extrapolated lanes
00656                 //  - begin of outgoing lane
00657                 // attention: if there is no intersection, use a straight line
00658                 noInitialPoints = 3;
00659                 init.push_back(beg);
00660                 Line begL = fromE->getLaneShape(fromL).getEndLine();
00661                 Line endL = toE->getLaneShape(toL).getBegLine();
00662                 bool check = !begL.p1().almostSame(begL.p2()) && !endL.p1().almostSame(endL.p2());
00663                 if (check) {
00664                     begL.extrapolateSecondBy(100);
00665                     endL.extrapolateFirstBy(100);
00666                 } else {
00667                     WRITE_WARNING("Could not use edge geometry for internal lane, node '" + getID() + "'.");
00668                 }
00669                 if (!check||!begL.intersects(endL)) {
00670                     noSpline = true;
00671                 } else {
00672                     init.push_back(begL.intersectsAt(endL));
00673                 }
00674                 init.push_back(end);
00675             }
00676         }
00677     }
00678     //
00679     if (noSpline) {
00680         ret.push_back(fromE->getLaneShape(fromL).getEnd());
00681         ret.push_back(toE->getLaneShape(toL).getBegin());
00682     } else {
00683         SUMOReal* def = new SUMOReal[1+noInitialPoints*3];
00684         for (int i=0; i<(int) init.size(); ++i) {
00685             // starts at index 1
00686             def[i*3+1] = init[i].x();
00687             def[i*3+2] = 0;
00688             def[i*3+3] = init[i].y();
00689         }
00690         SUMOReal* ret_buf = new SUMOReal[numPoints*3+1];
00691         bezier(noInitialPoints, def, numPoints, ret_buf);
00692         delete[] def;
00693         Position prev;
00694         for (int i=0; i<(int) numPoints; i++) {
00695             Position current(ret_buf[i*3+1], ret_buf[i*3+3]);
00696             if (prev!=current) {
00697                 ret.push_back(current);
00698             }
00699             prev = current;
00700         }
00701         delete[] ret_buf;
00702     }
00703     const NBEdge::Lane& lane = fromE->getLaneStruct(fromL);
00704     if (lane.offset>0) {
00705         PositionVector beg = lane.shape.getSubpart(lane.shape.length()-lane.offset, lane.shape.length());;
00706         beg.appendWithCrossingPoint(ret);
00707         ret = beg;
00708     }
00709     return ret;
00710 }
00711 
00712 
00713 bool
00714 NBNode::needsCont(NBEdge* fromE, NBEdge* toE, NBEdge* otherFromE, NBEdge* otherToE, const NBEdge::Connection& c) const {
00715     if (myType==NODETYPE_RIGHT_BEFORE_LEFT) {
00716         return false;
00717     }
00718     if (fromE==otherFromE) {
00719         // ignore same edge links
00720         return false;
00721     }
00722     if (!foes(otherFromE, otherToE, fromE, toE)) {
00723         // if they do not cross, no waiting place is needed
00724         return false;
00725     }
00726     LinkDirection d1 = getDirection(fromE, toE);
00727     LinkDirection d2 = getDirection(otherFromE, otherToE);
00728     bool thisLeft = (d1==LINKDIR_LEFT||d1==LINKDIR_TURN);
00729     bool otherLeft = (d2==LINKDIR_LEFT||d2==LINKDIR_TURN);
00730     bool bothLeft = thisLeft&&otherLeft;
00731     if (c.tlID!=""&&!bothLeft) {
00732         // tls-controlled links will have space
00733         return true;
00734     }
00735     if (fromE->getJunctionPriority(this)>0&&otherFromE->getJunctionPriority(this)>0) {
00736         return true;
00737     }
00738     return false;
00739 }
00740 
00741 
00742 void
00743 NBNode::computeLogic(const NBEdgeCont& ec, OptionsCont& oc) {
00744     delete myRequest; // possibly recomputation step
00745     myRequest = 0;
00746     if (myIncomingEdges.size()==0||myOutgoingEdges.size()==0) {
00747         // no logic if nothing happens here
00748         myType = NODETYPE_NOJUNCTION;
00749         return;
00750     }
00751     // check whether the node was set to be unregulated by the user
00752     if (oc.getBool("keep-nodes-unregulated") || oc.isInStringVector("keep-nodes-unregulated.explicit", getID())
00753             || (oc.getBool("keep-nodes-unregulated.district-nodes")&&(isNearDistrict()||isDistrict()))) {
00754         myType = NODETYPE_NOJUNCTION;
00755         return;
00756     }
00757     // compute the logic if necessary or split the junction
00758     if (myType!=NODETYPE_NOJUNCTION&&myType!=NODETYPE_DISTRICT) {
00759         // build the request
00760         myRequest = new NBRequest(ec, this,
00761                                   myAllEdges, myIncomingEdges, myOutgoingEdges, myBlockedConnections);
00762         // check whether it is not too large
00763         unsigned int numConnections = myRequest->getSizes().second;
00764         if (numConnections >= 64) {
00765             // yep -> make it untcontrolled, warn
00766             WRITE_WARNING("Junction '" + getID() + "' is too complicated (#links>64); will be set to unregulated.");
00767             delete myRequest;
00768             myRequest = 0;
00769             myType = NODETYPE_NOJUNCTION;
00770         } else if (numConnections == 0) {
00771             delete myRequest;
00772             myRequest = 0;
00773             myType = NODETYPE_DEAD_END;
00774         } else {
00775             myRequest->buildBitfieldLogic(ec.isLeftHanded());
00776         }
00777     }
00778 }
00779 
00780 
00781 bool
00782 NBNode::writeLogic(OutputDevice& into) const {
00783     if (myRequest) {
00784         myRequest->writeLogic(myID, into);
00785         return true;
00786     }
00787     return false;
00788 }
00789 
00790 
00791 void
00792 NBNode::sortNodesEdges(bool leftHand) {
00793     // sort the edges
00794     sort(myAllEdges.begin(), myAllEdges.end(), NBContHelper::edge_by_junction_angle_sorter(this));
00795     sort(myIncomingEdges.begin(), myIncomingEdges.end(), NBContHelper::edge_by_junction_angle_sorter(this));
00796     sort(myOutgoingEdges.begin(), myOutgoingEdges.end(), NBContHelper::edge_by_junction_angle_sorter(this));
00797     if (myAllEdges.size()==0) {
00798         return;
00799     }
00800     EdgeVector::iterator i;
00801     for (i=myAllEdges.begin(); i!=myAllEdges.end()-1&&i!=myAllEdges.end(); i++) {
00802         swapWhenReversed(leftHand ,i, i+1);
00803     }
00804     if (myAllEdges.size()>1 && i!=myAllEdges.end()) {
00805         swapWhenReversed(leftHand, myAllEdges.end()-1, myAllEdges.begin());
00806     }
00807 }
00808 
00809 
00810 void
00811 NBNode::computeNodeShape(bool leftHand) {
00812     if (myIncomingEdges.size()==0&&myOutgoingEdges.size()==0) {
00813         return;
00814     }
00815     try {
00816         NBNodeShapeComputer computer(*this);
00817         myPoly = computer.compute(leftHand);
00818     } catch (InvalidArgument&) {
00819         WRITE_WARNING("For node '" + getID() + "': could not compute shape.");
00820     }
00821 }
00822 
00823 
00824 void
00825 NBNode::computeLanes2Lanes() {
00826     // special case a):
00827     //  one in, one out, the outgoing has one lane more
00828     if (myIncomingEdges.size()==1&&myOutgoingEdges.size()==1
00829             && myIncomingEdges[0]->getNumLanes()==myOutgoingEdges[0]->getNumLanes()-1
00830             && myIncomingEdges[0]!=myOutgoingEdges[0]
00831             && myIncomingEdges[0]->isConnectedTo(myOutgoingEdges[0])) {
00832 
00833         NBEdge* incoming = myIncomingEdges[0];
00834         NBEdge* outgoing = myOutgoingEdges[0];
00835         // check if it's not the turnaround
00836         if (incoming->getTurnDestination()==outgoing) {
00837             // will be added later or not...
00838             return;
00839         }
00840         for (int i=0; i<(int) incoming->getNumLanes(); ++i) {
00841             incoming->setConnection(i, outgoing, i+1, NBEdge::L2L_COMPUTED);
00842         }
00843         incoming->setConnection(0, outgoing, 0, NBEdge::L2L_COMPUTED);
00844         return;
00845     }
00846     // special case b):
00847     //  two in, one out, the outgoing has the same number of lanes as the sum of the incoming
00848     //  and a high speed, too
00849     //  --> highway on-ramp
00850     bool check = false;
00851     if (myIncomingEdges.size()==2&&myOutgoingEdges.size()==1) {
00852         check = myIncomingEdges[0]->getNumLanes()+myIncomingEdges[1]->getNumLanes()==myOutgoingEdges[0]->getNumLanes();
00853         check &= (myIncomingEdges[0]->getStep() <= NBEdge::LANES2EDGES);
00854         check &= (myIncomingEdges[1]->getStep() <= NBEdge::LANES2EDGES);
00855     }
00856     if (check
00857             && myIncomingEdges[0]!=myOutgoingEdges[0]
00858             && myIncomingEdges[0]->isConnectedTo(myOutgoingEdges[0])) {
00859         NBEdge* inc1 = myIncomingEdges[0];
00860         NBEdge* inc2 = myIncomingEdges[1];
00861         // for internal: check which one is the rightmost
00862         SUMOReal a1 = inc1->getAngle(*this);
00863         SUMOReal a2 = inc2->getAngle(*this);
00864         SUMOReal ccw = GeomHelper::getCCWAngleDiff(a1, a2);
00865         SUMOReal cw = GeomHelper::getCWAngleDiff(a1, a2);
00866         if (ccw<cw) {
00867             std::swap(inc1, inc2);
00868         }
00869         //
00870         inc1->addLane2LaneConnections(0, myOutgoingEdges[0], 0, inc1->getNumLanes(), NBEdge::L2L_VALIDATED, true, true);
00871         inc2->addLane2LaneConnections(0, myOutgoingEdges[0], inc1->getNumLanes(), inc2->getNumLanes(), NBEdge::L2L_VALIDATED, true, true);
00872         return;
00873     }
00874 
00875     // go through this node's outgoing edges
00876     //  for every outgoing edge, compute the distribution of the node's
00877     //  incoming edges on this edge when approaching this edge
00878     // the incoming edges' steps will then also be marked as LANE2LANE_RECHECK...
00879     EdgeVector::reverse_iterator i;
00880     for (i=myOutgoingEdges.rbegin(); i!=myOutgoingEdges.rend(); i++) {
00881         NBEdge* currentOutgoing = *i;
00882         // get the information about edges that do approach this edge
00883         EdgeVector* approaching = getEdgesThatApproach(currentOutgoing);
00884         if (approaching->size()!=0) {
00885             ApproachingDivider divider(approaching, currentOutgoing);
00886             Bresenham::compute(&divider, static_cast<unsigned int>(approaching->size()),
00887                                currentOutgoing->getNumLanes());
00888         }
00889         delete approaching;
00890     }
00891     // ... but we may have the case that there are no outgoing edges
00892     //  In this case, we have to mark the incoming edges as being in state
00893     //   LANE2LANE( not RECHECK) by hand
00894     if (myOutgoingEdges.size()==0) {
00895         for (i=myIncomingEdges.rbegin(); i!=myIncomingEdges.rend(); i++) {
00896             (*i)->markAsInLane2LaneState();
00897         }
00898     }
00899 }
00900 
00901 
00902 EdgeVector*
00903 NBNode::getEdgesThatApproach(NBEdge* currentOutgoing) {
00904     // get the position of the node to get the approaching nodes of
00905     EdgeVector::const_iterator i = find(myAllEdges.begin(),
00906                                         myAllEdges.end(), currentOutgoing);
00907     // get the first possible approaching edge
00908     NBContHelper::nextCW(myAllEdges, i);
00909     // go through the list of edges clockwise and add the edges
00910     EdgeVector* approaching = new EdgeVector();
00911     for (; *i!=currentOutgoing;) {
00912         // check only incoming edges
00913         if ((*i)->getToNode()==this&&(*i)->getTurnDestination()!=currentOutgoing) {
00914             std::vector<int> connLanes = (*i)->getConnectionLanes(currentOutgoing);
00915             if (connLanes.size()!=0) {
00916                 approaching->push_back(*i);
00917             }
00918         }
00919         NBContHelper::nextCW(myAllEdges, i);
00920     }
00921     return approaching;
00922 }
00923 
00924 
00925 void
00926 NBNode::replaceOutgoing(NBEdge* which, NBEdge* by, unsigned int laneOff) {
00927     // replace the edge in the list of outgoing nodes
00928     EdgeVector::iterator i=find(myOutgoingEdges.begin(), myOutgoingEdges.end(), which);
00929     if (i!=myOutgoingEdges.end()) {
00930         (*i) = by;
00931         i = find(myAllEdges.begin(), myAllEdges.end(), which);
00932         (*i) = by;
00933     }
00934     // replace the edge in connections of incoming edges
00935     for (i=myIncomingEdges.begin(); i!=myIncomingEdges.end(); ++i) {
00936         (*i)->replaceInConnections(which, by, laneOff);
00937     }
00938     // replace within the connetion prohibition dependencies
00939     replaceInConnectionProhibitions(which, by, 0, laneOff);
00940 }
00941 
00942 
00943 void
00944 NBNode::replaceOutgoing(const EdgeVector& which, NBEdge* by) {
00945     // replace edges
00946     unsigned int laneOff = 0;
00947     for (EdgeVector::const_iterator i=which.begin(); i!=which.end(); i++) {
00948         replaceOutgoing(*i, by, laneOff);
00949         laneOff += (*i)->getNumLanes();
00950     }
00951     // removed SUMOReal occurences
00952     removeDoubleEdges();
00953     // check whether this node belongs to a district and the edges
00954     //  must here be also remapped
00955     if (myDistrict!=0) {
00956         myDistrict->replaceOutgoing(which, by);
00957     }
00958 }
00959 
00960 
00961 void
00962 NBNode::replaceIncoming(NBEdge* which, NBEdge* by, unsigned int laneOff) {
00963     // replace the edge in the list of incoming nodes
00964     EdgeVector::iterator i=find(myIncomingEdges.begin(), myIncomingEdges.end(), which);
00965     if (i!=myIncomingEdges.end()) {
00966         (*i) = by;
00967         i = find(myAllEdges.begin(), myAllEdges.end(), which);
00968         (*i) = by;
00969     }
00970     // replace within the connetion prohibition dependencies
00971     replaceInConnectionProhibitions(which, by, laneOff, 0);
00972 }
00973 
00974 
00975 void
00976 NBNode::replaceIncoming(const EdgeVector& which, NBEdge* by) {
00977     // replace edges
00978     unsigned int laneOff = 0;
00979     for (EdgeVector::const_iterator i=which.begin(); i!=which.end(); i++) {
00980         replaceIncoming(*i, by, laneOff);
00981         laneOff += (*i)->getNumLanes();
00982     }
00983     // removed SUMOReal occurences
00984     removeDoubleEdges();
00985     // check whether this node belongs to a district and the edges
00986     //  must here be also remapped
00987     if (myDistrict!=0) {
00988         myDistrict->replaceIncoming(which, by);
00989     }
00990 }
00991 
00992 
00993 
00994 void
00995 NBNode::replaceInConnectionProhibitions(NBEdge* which, NBEdge* by,
00996                                         unsigned int whichLaneOff, unsigned int byLaneOff) {
00997     // replace in keys
00998     NBConnectionProhibits::iterator j = myBlockedConnections.begin();
00999     while (j!=myBlockedConnections.end()) {
01000         bool changed = false;
01001         NBConnection c = (*j).first;
01002         if (c.replaceFrom(which, whichLaneOff, by, byLaneOff)) {
01003             changed = true;
01004         }
01005         if (c.replaceTo(which, whichLaneOff, by, byLaneOff)) {
01006             changed = true;
01007         }
01008         if (changed) {
01009             myBlockedConnections[c] = (*j).second;
01010             myBlockedConnections.erase(j);
01011             j = myBlockedConnections.begin();
01012         } else {
01013             j++;
01014         }
01015     }
01016     // replace in values
01017     for (j=myBlockedConnections.begin(); j!=myBlockedConnections.end(); j++) {
01018         NBConnectionVector& prohibiting = (*j).second;
01019         for (NBConnectionVector::iterator k=prohibiting.begin(); k!=prohibiting.end(); k++) {
01020             NBConnection& sprohibiting = *k;
01021             sprohibiting.replaceFrom(which, whichLaneOff, by, byLaneOff);
01022             sprohibiting.replaceTo(which, whichLaneOff, by, byLaneOff);
01023         }
01024     }
01025 }
01026 
01027 
01028 
01029 void
01030 NBNode::removeDoubleEdges() {
01031     unsigned int i, j;
01032     // check incoming
01033     for (i=0; myIncomingEdges.size()>0&&i<myIncomingEdges.size()-1; i++) {
01034         j = i + 1;
01035         while (j<myIncomingEdges.size()) {
01036             if (myIncomingEdges[i]==myIncomingEdges[j]) {
01037                 myIncomingEdges.erase(myIncomingEdges.begin()+j);
01038             } else {
01039                 j++;
01040             }
01041         }
01042     }
01043     // check outgoing
01044     for (i=0; myOutgoingEdges.size()>0&&i<myOutgoingEdges.size()-1; i++) {
01045         j = i + 1;
01046         while (j<myOutgoingEdges.size()) {
01047             if (myOutgoingEdges[i]==myOutgoingEdges[j]) {
01048                 myOutgoingEdges.erase(myOutgoingEdges.begin()+j);
01049             } else {
01050                 j++;
01051             }
01052         }
01053     }
01054     // check all
01055     for (i=0; myAllEdges.size()>0&&i<myAllEdges.size()-1; i++) {
01056         j = i + 1;
01057         while (j<myAllEdges.size()) {
01058             if (myAllEdges[i]==myAllEdges[j]) {
01059                 myAllEdges.erase(myAllEdges.begin()+j);
01060             } else {
01061                 j++;
01062             }
01063         }
01064     }
01065 }
01066 
01067 
01068 bool
01069 NBNode::hasIncoming(const NBEdge* const e) const throw() {
01070     return find(myIncomingEdges.begin(), myIncomingEdges.end(), e)!=myIncomingEdges.end();
01071 }
01072 
01073 
01074 bool
01075 NBNode::hasOutgoing(const NBEdge* const e) const throw() {
01076     return find(myOutgoingEdges.begin(), myOutgoingEdges.end(), e)!=myOutgoingEdges.end();
01077 }
01078 
01079 
01080 NBEdge*
01081 NBNode::getOppositeIncoming(NBEdge* e) const {
01082     EdgeVector edges = myIncomingEdges;
01083     if (find(edges.begin(), edges.end(), e)!=edges.end()) {
01084         edges.erase(find(edges.begin(), edges.end(), e));
01085     }
01086     if (e->getToNode()==this) {
01087         sort(edges.begin(), edges.end(), NBContHelper::edge_opposite_direction_sorter(e, this));
01088     } else {
01089         sort(edges.begin(), edges.end(), NBContHelper::edge_similar_direction_sorter(e));
01090     }
01091     return edges[0];
01092 }
01093 
01094 
01095 void
01096 NBNode::addSortedLinkFoes(const NBConnection& mayDrive,
01097                           const NBConnection& mustStop) {
01098     if (mayDrive.getFrom()==0 ||
01099             mayDrive.getTo()==0 ||
01100             mustStop.getFrom()==0 ||
01101             mustStop.getTo()==0) {
01102 
01103         WRITE_WARNING("Something went wrong during the building of a connection...");
01104         return; // !!! mark to recompute connections
01105     }
01106     NBConnectionVector conn = myBlockedConnections[mustStop];
01107     conn.push_back(mayDrive);
01108     myBlockedConnections[mustStop] = conn;
01109 }
01110 
01111 
01112 NBEdge*
01113 NBNode::getPossiblySplittedIncoming(const std::string& edgeid) {
01114     unsigned int size = (unsigned int) edgeid.length();
01115     for (EdgeVector::iterator i=myIncomingEdges.begin(); i!=myIncomingEdges.end(); i++) {
01116         std::string id = (*i)->getID();
01117         if (id.substr(0, size)==edgeid) {
01118             return *i;
01119         }
01120     }
01121     return 0;
01122 }
01123 
01124 
01125 NBEdge*
01126 NBNode::getPossiblySplittedOutgoing(const std::string& edgeid) {
01127     unsigned int size = (unsigned int) edgeid.length();
01128     for (EdgeVector::iterator i=myOutgoingEdges.begin(); i!=myOutgoingEdges.end(); i++) {
01129         std::string id = (*i)->getID();
01130         if (id.substr(0, size)==edgeid) {
01131             return *i;
01132         }
01133     }
01134     return 0;
01135 }
01136 
01137 
01138 void
01139 NBNode::removeEdge(NBEdge* edge, bool removeFromConnections) {
01140     EdgeVector::iterator i = find(myAllEdges.begin(), myAllEdges.end(), edge);
01141     if (i!=myAllEdges.end()) {
01142         myAllEdges.erase(i);
01143         i = find(myOutgoingEdges.begin(), myOutgoingEdges.end(), edge);
01144         if (i!=myOutgoingEdges.end()) {
01145             myOutgoingEdges.erase(i);
01146         } else {
01147             i = find(myIncomingEdges.begin(), myIncomingEdges.end(), edge);
01148             if (i!=myIncomingEdges.end()) {
01149                 myIncomingEdges.erase(i);
01150             } else {
01151                 // edge must have been either incoming or outgoing
01152                 assert(false);
01153             }
01154         }
01155         if (removeFromConnections) {
01156             for (i=myAllEdges.begin(); i!=myAllEdges.end(); ++i) {
01157                 (*i)->removeFromConnections(edge);
01158             }
01159         }
01160     }
01161 }
01162 
01163 
01164 Position
01165 NBNode::getEmptyDir() const {
01166     Position pos(0, 0);
01167     EdgeVector::const_iterator i;
01168     for (i=myIncomingEdges.begin(); i!=myIncomingEdges.end(); i++) {
01169         NBNode* conn = (*i)->getFromNode();
01170         Position toAdd = conn->getPosition();
01171         toAdd.sub(myPosition);
01172         toAdd.mul((SUMOReal) 1.0/sqrt(toAdd.x()*toAdd.x()+toAdd.y()*toAdd.y()));
01173         pos.add(toAdd);
01174     }
01175     for (i=myOutgoingEdges.begin(); i!=myOutgoingEdges.end(); i++) {
01176         NBNode* conn = (*i)->getToNode();
01177         Position toAdd = conn->getPosition();
01178         toAdd.sub(myPosition);
01179         toAdd.mul((SUMOReal) 1.0/sqrt(toAdd.x()*toAdd.x()+toAdd.y()*toAdd.y()));
01180         pos.add(toAdd);
01181     }
01182     pos.mul((SUMOReal) -1.0/(myIncomingEdges.size()+myOutgoingEdges.size()));
01183     if (pos.x()==0&&pos.y()==0) {
01184         pos = Position(1, 0);
01185     }
01186     pos.norm2d();
01187     return pos;
01188 }
01189 
01190 
01191 
01192 void
01193 NBNode::invalidateIncomingConnections() {
01194     for (EdgeVector::const_iterator i=myIncomingEdges.begin(); i!=myIncomingEdges.end(); i++) {
01195         (*i)->invalidateConnections();
01196     }
01197 }
01198 
01199 
01200 void
01201 NBNode::invalidateOutgoingConnections() {
01202     for (EdgeVector::const_iterator i=myOutgoingEdges.begin(); i!=myOutgoingEdges.end(); i++) {
01203         (*i)->invalidateConnections();
01204     }
01205 }
01206 
01207 
01208 bool
01209 NBNode::mustBrake(const NBEdge* const from, const NBEdge* const to, int toLane) const throw() {
01210     // check whether it is participant to a traffic light
01211     //  - controlled links are set by the traffic lights, not the normal
01212     //    right-of-way rules
01213     //  - uncontrolled participants (spip lanes etc.) should always break
01214     if (myTrafficLights.size()!=0) {
01215         // ok, we have a traffic light, return true by now, it will be later
01216         //  controlled by the tls
01217         return true;
01218     }
01219     // unregulated->does not need to brake
01220     if (myRequest==0) {
01221         return false;
01222     }
01223     // vehicles which do not have a following lane must always decelerate to the end
01224     if (to==0) {
01225         return true;
01226     }
01227     // check whether any other connection on this node prohibits this connection
01228     bool try1 = myRequest->mustBrake(from, to);
01229     if (!try1||toLane==-1) {
01230         return try1;
01231     }
01232     if (from->getSpeed()<70./3.6) {
01233         return try1;
01234     }
01235     // on highways (on-ramps, in fact):
01236     // check whether any other connection uses the same destination edge
01237     for (EdgeVector::const_iterator i=myIncomingEdges.begin(); i!=myIncomingEdges.end(); i++) {
01238         if ((*i)==from) {
01239             continue;
01240         }
01241         const std::vector<NBEdge::Connection> &connections = (*i)->getConnections();
01242         for (std::vector<NBEdge::Connection>::const_iterator j=connections.begin(); j!=connections.end(); ++j) {
01243             if ((*j).toEdge==to&&((*j).toLane<0||(*j).toLane==toLane)) {
01244                 return true;
01245             }
01246         }
01247     }
01248     return false;
01249 }
01250 
01251 
01252 bool
01253 NBNode::isLeftMover(const NBEdge* const from, const NBEdge* const to) const throw() {
01254     // when the junction has only one incoming edge, there are no
01255     //  problems caused by left blockings
01256     if (myIncomingEdges.size()==1||myOutgoingEdges.size()==1) {
01257         return false;
01258     }
01259     SUMOReal fromAngle = from->getAngle(*this);
01260     SUMOReal toAngle = to->getAngle(*this);
01261     SUMOReal cw = GeomHelper::getCWAngleDiff(fromAngle, toAngle);
01262     SUMOReal ccw = GeomHelper::getCCWAngleDiff(fromAngle, toAngle);
01263     std::vector<NBEdge*>::const_iterator i = std::find(myAllEdges.begin(), myAllEdges.end(), from);
01264     do {
01265         NBContHelper::nextCW(myAllEdges, i);
01266     } while ((!hasOutgoing(*i)||from->getTurnDestination()==*i)&&*i!=from);
01267     return cw<ccw&&(*i)==to&&myOutgoingEdges.size()>2;
01268 }
01269 
01270 
01271 bool
01272 NBNode::forbids(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,
01273                 const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo,
01274                 bool regardNonSignalisedLowerPriority) const throw() {
01275     return myRequest!=0&&myRequest->forbids(possProhibitorFrom, possProhibitorTo,
01276                                             possProhibitedFrom, possProhibitedTo,
01277                                             regardNonSignalisedLowerPriority);
01278 }
01279 
01280 
01281 bool
01282 NBNode::foes(const NBEdge* const from1, const NBEdge* const to1,
01283              const NBEdge* const from2, const NBEdge* const to2) const throw() {
01284     return myRequest!=0&&myRequest->foes(from1, to1, from2, to2);
01285 }
01286 
01287 
01288 void
01289 NBNode::remapRemoved(NBTrafficLightLogicCont& tc,
01290                      NBEdge* removed, const EdgeVector& incoming,
01291                      const EdgeVector& outgoing) {
01292     assert(find(incoming.begin(), incoming.end(), removed)==incoming.end());
01293     bool changed = true;
01294     while (changed) {
01295         changed = false;
01296         NBConnectionProhibits blockedConnectionsTmp = myBlockedConnections;
01297         NBConnectionProhibits blockedConnectionsNew;
01298         // remap in connections
01299         for (NBConnectionProhibits::iterator i=blockedConnectionsTmp.begin(); i!=blockedConnectionsTmp.end(); i++) {
01300             const NBConnection& blocker = (*i).first;
01301             const NBConnectionVector& blocked = (*i).second;
01302             // check the blocked connections first
01303             // check whether any of the blocked must be changed
01304             bool blockedChanged = false;
01305             NBConnectionVector newBlocked;
01306             NBConnectionVector::const_iterator j;
01307             for (j=blocked.begin(); j!=blocked.end(); j++) {
01308                 const NBConnection& sblocked = *j;
01309                 if (sblocked.getFrom()==removed||sblocked.getTo()==removed) {
01310                     blockedChanged = true;
01311                 }
01312             }
01313             // adapt changes if so
01314             for (j=blocked.begin(); blockedChanged&&j!=blocked.end(); j++) {
01315                 const NBConnection& sblocked = *j;
01316                 if (sblocked.getFrom()==removed&&sblocked.getTo()==removed) {
01317                     /*                    for(EdgeVector::const_iterator k=incoming.begin(); k!=incoming.end(); k++) {
01318                     !!!                        newBlocked.push_back(NBConnection(*k, *k));
01319                                         }*/
01320                 } else if (sblocked.getFrom()==removed) {
01321                     assert(sblocked.getTo()!=removed);
01322                     for (EdgeVector::const_iterator k=incoming.begin(); k!=incoming.end(); k++) {
01323                         newBlocked.push_back(NBConnection(*k, sblocked.getTo()));
01324                     }
01325                 } else if (sblocked.getTo()==removed) {
01326                     assert(sblocked.getFrom()!=removed);
01327                     for (EdgeVector::const_iterator k=outgoing.begin(); k!=outgoing.end(); k++) {
01328                         newBlocked.push_back(NBConnection(sblocked.getFrom(), *k));
01329                     }
01330                 } else {
01331                     newBlocked.push_back(NBConnection(sblocked.getFrom(), sblocked.getTo()));
01332                 }
01333             }
01334             if (blockedChanged) {
01335                 blockedConnectionsNew[blocker] = newBlocked;
01336                 changed = true;
01337             }
01338             // if the blocked were kept
01339             else {
01340                 if (blocker.getFrom()==removed&&blocker.getTo()==removed) {
01341                     changed = true;
01342                     /*                    for(EdgeVector::const_iterator k=incoming.begin(); k!=incoming.end(); k++) {
01343                     !!!                        blockedConnectionsNew[NBConnection(*k, *k)] = blocked;
01344                                         }*/
01345                 } else if (blocker.getFrom()==removed) {
01346                     assert(blocker.getTo()!=removed);
01347                     changed = true;
01348                     for (EdgeVector::const_iterator k=incoming.begin(); k!=incoming.end(); k++) {
01349                         blockedConnectionsNew[NBConnection(*k, blocker.getTo())] = blocked;
01350                     }
01351                 } else if (blocker.getTo()==removed) {
01352                     assert(blocker.getFrom()!=removed);
01353                     changed = true;
01354                     for (EdgeVector::const_iterator k=outgoing.begin(); k!=outgoing.end(); k++) {
01355                         blockedConnectionsNew[NBConnection(blocker.getFrom(), *k)] = blocked;
01356                     }
01357                 } else {
01358                     blockedConnectionsNew[blocker] = blocked;
01359                 }
01360             }
01361         }
01362         myBlockedConnections = blockedConnectionsNew;
01363     }
01364     // remap in traffic lights
01365     tc.remapRemoved(removed, incoming, outgoing);
01366 }
01367 
01368 
01369 LinkDirection
01370 NBNode::getDirection(const NBEdge* const incoming, const NBEdge* const outgoing) const throw() {
01371     // ok, no connection at all -> dead end
01372     if (outgoing==0) {
01373         return LINKDIR_NODIR;
01374     }
01375     // turning direction
01376     if (incoming->isTurningDirectionAt(this, outgoing)) {
01377         return LINKDIR_TURN;
01378     }
01379     // get the angle between incoming/outgoing at the junction
01380     SUMOReal angle =
01381         NBHelpers::normRelAngle(incoming->getAngle(*this), outgoing->getAngle(*this));
01382     // ok, should be a straight connection
01383     if (abs((int) angle)+1<45) {
01384         return LINKDIR_STRAIGHT;
01385     }
01386 
01387     // check for left and right, first
01388     if (angle>0) {
01389         // check whether any other edge goes further to the right
01390         EdgeVector::const_iterator i =
01391             find(myAllEdges.begin(), myAllEdges.end(), outgoing);
01392         NBContHelper::nextCW(myAllEdges, i);
01393         while ((*i)!=incoming) {
01394             if ((*i)->getFromNode()==this) {
01395                 return LINKDIR_PARTRIGHT;
01396             }
01397             NBContHelper::nextCW(myAllEdges, i);
01398         }
01399         return LINKDIR_RIGHT;
01400     }
01401     // check whether any other edge goes further to the left
01402     EdgeVector::const_iterator i =
01403         find(myAllEdges.begin(), myAllEdges.end(), outgoing);
01404     NBContHelper::nextCCW(myAllEdges, i);
01405     while ((*i)!=incoming) {
01406         if ((*i)->getFromNode()==this&&!incoming->isTurningDirectionAt(this, *i)) {
01407             return LINKDIR_PARTLEFT;
01408         }
01409         NBContHelper::nextCCW(myAllEdges, i);
01410     }
01411     return LINKDIR_LEFT;
01412 }
01413 
01414 
01415 std::string
01416 NBNode::stateCode(const NBEdge* incoming, NBEdge* outgoing, int fromlane, bool mayDefinitelyPass) const throw() {
01417     if (outgoing==0) { // always off
01418         return toString(LINKSTATE_TL_OFF_NOSIGNAL);
01419     }
01420     if (myType==NODETYPE_RIGHT_BEFORE_LEFT) {
01421         return toString(LINKSTATE_EQUAL); // all the same
01422     }
01423     if ((!incoming->isInnerEdge()&&mustBrake(incoming, outgoing, fromlane)) && !mayDefinitelyPass) {
01424         return toString(LINKSTATE_MINOR); // minor road
01425     }
01426     // traffic lights are not regardedm here
01427     return toString(LINKSTATE_MAJOR);
01428 }
01429 
01430 
01431 bool
01432 NBNode::checkIsRemovable() const {
01433     // check whether this node is included in a traffic light
01434     if (myTrafficLights.size()!=0) {
01435         return false;
01436     }
01437     EdgeVector::const_iterator i;
01438     // one in, one out -> just a geometry ...
01439     if (myOutgoingEdges.size()==1&&myIncomingEdges.size()==1) {
01440         // ... if types match ...
01441         if (!myIncomingEdges[0]->expandableBy(myOutgoingEdges[0])) {
01442             return false;
01443         }
01444         //
01445         return myIncomingEdges[0]->getFromNode()!=myOutgoingEdges[0]->getToNode();
01446     }
01447     // two in, two out -> may be something else
01448     if (myOutgoingEdges.size()==2&&myIncomingEdges.size()==2) {
01449         // check whether the origin nodes of the incoming edges differ
01450         std::set<NBNode*> origSet;
01451         for (i=myIncomingEdges.begin(); i!=myIncomingEdges.end(); i++) {
01452             origSet.insert((*i)->getFromNode());
01453         }
01454         if (origSet.size()<2) {
01455             return false;
01456         }
01457         // check whether this node is an intermediate node of
01458         //  a two-directional street
01459         for (i=myIncomingEdges.begin(); i!=myIncomingEdges.end(); i++) {
01460             // try to find the opposite direction
01461             NBNode* origin = (*i)->getFromNode();
01462             // find the back direction of the current edge
01463             EdgeVector::const_iterator j =
01464                 find_if(myOutgoingEdges.begin(), myOutgoingEdges.end(),
01465                         NBContHelper::edge_with_destination_finder(origin));
01466             // check whether the back direction exists
01467             if (j!=myOutgoingEdges.end()) {
01468                 // check whether the edge from the backdirection (must be
01469                 //  the counter-clockwise one) may be joined with the current
01470                 NBContHelper::nextCCW(myOutgoingEdges, j);
01471                 // check whether the types allow joining
01472                 if (!(*i)->expandableBy(*j)) {
01473                     return false;
01474                 }
01475             } else {
01476                 // ok, at least one outgoing edge is not an opposite
01477                 //  of an incoming one
01478                 return false;
01479             }
01480         }
01481         return true;
01482     }
01483     // ok, a real node
01484     return false;
01485 }
01486 
01487 
01488 std::vector<std::pair<NBEdge*, NBEdge*> >
01489 NBNode::getEdgesToJoin() const {
01490     assert(checkIsRemovable());
01491     std::vector<std::pair<NBEdge*, NBEdge*> > ret;
01492     // one in, one out-case
01493     if (myOutgoingEdges.size()==1&&myIncomingEdges.size()==1) {
01494         ret.push_back(
01495             std::pair<NBEdge*, NBEdge*>(
01496                 myIncomingEdges[0], myOutgoingEdges[0]));
01497         return ret;
01498     }
01499     // two in, two out-case
01500     for (EdgeVector::const_iterator i=myIncomingEdges.begin(); i!=myIncomingEdges.end(); i++) {
01501         NBNode* origin = (*i)->getFromNode();
01502         EdgeVector::const_iterator j =
01503             find_if(myOutgoingEdges.begin(), myOutgoingEdges.end(),
01504                     NBContHelper::edge_with_destination_finder(origin));
01505         NBContHelper::nextCCW(myOutgoingEdges, j);
01506         ret.push_back(std::pair<NBEdge*, NBEdge*>(*i, *j));
01507     }
01508     return ret;
01509 }
01510 
01511 
01512 const PositionVector&
01513 NBNode::getShape() const {
01514     return myPoly;
01515 }
01516 
01517 
01518 SUMOReal
01519 NBNode::getMaxEdgeWidth() const {
01520     EdgeVector::const_iterator i=myAllEdges.begin();
01521     assert(i!=myAllEdges.end());
01522     SUMOReal ret = (*i)->width();
01523     ++i;
01524     for (; i!=myAllEdges.end(); i++) {
01525         ret = ret > (*i)->width() ? ret : (*i)->width();
01526     }
01527     return ret;
01528 }
01529 
01530 
01531 NBEdge*
01532 NBNode::getConnectionTo(NBNode* n) const {
01533     for (EdgeVector::const_iterator i=myOutgoingEdges.begin(); i!=myOutgoingEdges.end(); i++) {
01534         if ((*i)->getToNode()==n) {
01535             return (*i);
01536         }
01537     }
01538     return 0;
01539 }
01540 
01541 
01542 bool
01543 NBNode::isNearDistrict() const {
01544     if (isDistrict()) {
01545         return false;
01546     }
01547     EdgeVector edges;
01548     copy(getIncomingEdges().begin(), getIncomingEdges().end(),
01549          back_inserter(edges));
01550     copy(getOutgoingEdges().begin(), getOutgoingEdges().end(),
01551          back_inserter(edges));
01552     for (EdgeVector::const_iterator j=edges.begin(); j!=edges.end(); ++j) {
01553         NBEdge* t = *j;
01554         NBNode* other = 0;
01555         if (t->getToNode()==this) {
01556             other = t->getFromNode();
01557         } else {
01558             other = t->getToNode();
01559         }
01560         EdgeVector edges2;
01561         copy(other->getIncomingEdges().begin(), other->getIncomingEdges().end(), back_inserter(edges2));
01562         copy(other->getOutgoingEdges().begin(), other->getOutgoingEdges().end(), back_inserter(edges2));
01563         for (EdgeVector::const_iterator k=edges2.begin(); k!=edges2.end(); ++k) {
01564             if ((*k)->getFromNode()->isDistrict()||(*k)->getToNode()->isDistrict()) {
01565                 return true;
01566             }
01567         }
01568     }
01569     return false;
01570 }
01571 
01572 
01573 bool
01574 NBNode::isDistrict() const {
01575     return myType==NODETYPE_DISTRICT;
01576 }
01577 
01578 
01579 void
01580 NBNode::buildInnerEdges() {
01581     unsigned int noInternalNoSplits = 0;
01582     for (EdgeVector::const_iterator i=myIncomingEdges.begin(); i!=myIncomingEdges.end(); i++) {
01583         const std::vector<NBEdge::Connection> &elv = (*i)->getConnections();
01584         for (std::vector<NBEdge::Connection>::const_iterator k=elv.begin(); k!=elv.end(); ++k) {
01585             if ((*k).toEdge==0) {
01586                 continue;
01587             }
01588             noInternalNoSplits++;
01589         }
01590     }
01591     unsigned int lno = 0;
01592     unsigned int splitNo = 0;
01593     for (EdgeVector::const_iterator i=myIncomingEdges.begin(); i!=myIncomingEdges.end(); i++) {
01594         (*i)->buildInnerEdges(*this, noInternalNoSplits, lno, splitNo);
01595     }
01596 }
01597 
01598 
01599 /****************************************************************************/
01600 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines