SUMO - Simulation of Urban MObility

NBNode.cpp

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