|
SUMO - Simulation of Urban MObility
|
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(÷r, 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