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