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.add(xoff, yoff, 0); 00250 myPoly.add(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::isSimpleContinuation() const { 00358 // one in, one out->continuation 00359 if (myIncomingEdges.size() == 1 && myOutgoingEdges.size() == 1) { 00360 // both must have the same number of lanes 00361 return (*(myIncomingEdges.begin()))->getNumLanes() == (*(myOutgoingEdges.begin()))->getNumLanes(); 00362 } 00363 // two in and two out and both in reverse direction 00364 if (myIncomingEdges.size() == 2 && myOutgoingEdges.size() == 2) { 00365 for (EdgeVector::const_iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) { 00366 NBEdge* in = *i; 00367 EdgeVector::const_iterator opposite = find_if(myOutgoingEdges.begin(), myOutgoingEdges.end(), NBContHelper::opposite_finder(in, this)); 00368 // must have an opposite edge 00369 if (opposite == myOutgoingEdges.end()) { 00370 return false; 00371 } 00372 // both must have the same number of lanes 00373 NBContHelper::nextCW(myOutgoingEdges, opposite); 00374 if (in->getNumLanes() != (*opposite)->getNumLanes()) { 00375 return false; 00376 } 00377 } 00378 return true; 00379 } 00380 // nope 00381 return false; 00382 } 00383 00384 00385 PositionVector 00386 NBNode::computeInternalLaneShape(NBEdge* fromE, int fromL, 00387 NBEdge* toE, int toL, int numPoints) const { 00388 if (fromL >= (int) fromE->getNumLanes()) { 00389 throw ProcessError("Connection '" + fromE->getID() + "_" + toString(fromL) + "->" + toE->getID() + "_" + toString(toL) + "' starts at a not existing lane."); 00390 } 00391 if (toL >= (int) toE->getNumLanes()) { 00392 throw ProcessError("Connection '" + fromE->getID() + "_" + toString(fromL) + "->" + toE->getID() + "_" + toString(toL) + "' yields in a not existing lane."); 00393 } 00394 bool noSpline = false; 00395 PositionVector ret; 00396 PositionVector init; 00397 Position beg = fromE->getLaneShape(fromL).getEnd(); 00398 Position end = toE->getLaneShape(toL).getBegin(); 00399 Position intersection; 00400 unsigned int noInitialPoints = 0; 00401 if (beg.distanceTo(end) <= POSITION_EPS) { 00402 noSpline = true; 00403 } else { 00404 if (fromE->getTurnDestination() == toE) { 00405 // turnarounds: 00406 // - end of incoming lane 00407 // - position between incoming/outgoing end/begin shifted by the distance orthogonally 00408 // - begin of outgoing lane 00409 noInitialPoints = 3; 00410 init.push_back(beg); 00411 Line straightConn(fromE->getLaneShape(fromL)[-1], toE->getLaneShape(toL)[0]); 00412 Position straightCenter = straightConn.getPositionAtDistance((SUMOReal) straightConn.length() / (SUMOReal) 2.); 00413 Position center = straightCenter;//.add(straightCenter); 00414 Line cross(straightConn); 00415 cross.sub(cross.p1().x(), cross.p1().y()); 00416 cross.rotateAtP1(PI / 2); 00417 center.sub(cross.p2()); 00418 init.push_back(center); 00419 init.push_back(end); 00420 } else { 00421 const SUMOReal angle = fabs(fromE->getLaneShape(fromL).getEndLine().atan2Angle() - toE->getLaneShape(toL).getBegLine().atan2Angle()); 00422 if (angle < PI / 4. || angle > 7. / 4.*PI) { 00423 // very low angle: almost straight 00424 noInitialPoints = 4; 00425 init.push_back(beg); 00426 Line begL = fromE->getLaneShape(fromL).getEndLine(); 00427 begL.extrapolateSecondBy(100); 00428 Line endL = toE->getLaneShape(toL).getBegLine(); 00429 endL.extrapolateFirstBy(100); 00430 SUMOReal distance = beg.distanceTo(end); 00431 if (distance > 10) { 00432 { 00433 SUMOReal off1 = fromE->getLaneShape(fromL).getEndLine().length() + (SUMOReal) 5. * (SUMOReal) fromE->getNumLanes(); 00434 off1 = MIN2(off1, (SUMOReal)(fromE->getLaneShape(fromL).getEndLine().length() + distance / 2.)); 00435 Position tmp = begL.getPositionAtDistance(off1); 00436 init.push_back(tmp); 00437 } 00438 { 00439 SUMOReal off1 = (SUMOReal) 100. - (SUMOReal) 5. * (SUMOReal) toE->getNumLanes(); 00440 off1 = MAX2(off1, (SUMOReal)(100. - distance / 2.)); 00441 Position tmp = endL.getPositionAtDistance(off1); 00442 init.push_back(tmp); 00443 } 00444 } else { 00445 noSpline = true; 00446 } 00447 init.push_back(end); 00448 } else { 00449 // turning 00450 // - end of incoming lane 00451 // - intersection of the extrapolated lanes 00452 // - begin of outgoing lane 00453 // attention: if there is no intersection, use a straight line 00454 noInitialPoints = 3; 00455 init.push_back(beg); 00456 Line begL = fromE->getLaneShape(fromL).getEndLine(); 00457 Line endL = toE->getLaneShape(toL).getBegLine(); 00458 bool check = !begL.p1().almostSame(begL.p2()) && !endL.p1().almostSame(endL.p2()); 00459 if (check) { 00460 begL.extrapolateSecondBy(100); 00461 endL.extrapolateFirstBy(100); 00462 } else { 00463 WRITE_WARNING("Could not use edge geometry for internal lane, node '" + getID() + "'."); 00464 } 00465 if (!check || !begL.intersects(endL)) { 00466 noSpline = true; 00467 } else { 00468 init.push_back(begL.intersectsAt(endL)); 00469 } 00470 init.push_back(end); 00471 } 00472 } 00473 } 00474 // 00475 if (noSpline) { 00476 ret.push_back(fromE->getLaneShape(fromL).getEnd()); 00477 ret.push_back(toE->getLaneShape(toL).getBegin()); 00478 } else { 00479 SUMOReal* def = new SUMOReal[1 + noInitialPoints * 3]; 00480 for (int i = 0; i < (int) init.size(); ++i) { 00481 // starts at index 1 00482 def[i * 3 + 1] = init[i].x(); 00483 def[i * 3 + 2] = 0; 00484 def[i * 3 + 3] = init[i].y(); 00485 } 00486 SUMOReal* ret_buf = new SUMOReal[numPoints * 3 + 1]; 00487 bezier(noInitialPoints, def, numPoints, ret_buf); 00488 delete[] def; 00489 Position prev; 00490 for (int i = 0; i < (int) numPoints; i++) { 00491 Position current(ret_buf[i * 3 + 1], ret_buf[i * 3 + 3]); 00492 if (prev != current) { 00493 ret.push_back(current); 00494 } 00495 prev = current; 00496 } 00497 delete[] ret_buf; 00498 } 00499 const NBEdge::Lane& lane = fromE->getLaneStruct(fromL); 00500 if (lane.offset > 0) { 00501 PositionVector beg = lane.shape.getSubpart(lane.shape.length() - lane.offset, lane.shape.length());; 00502 beg.appendWithCrossingPoint(ret); 00503 ret = beg; 00504 } 00505 return ret; 00506 } 00507 00508 00509 bool 00510 NBNode::needsCont(NBEdge* fromE, NBEdge* toE, NBEdge* otherFromE, NBEdge* otherToE, const NBEdge::Connection& c) const { 00511 if (myType == NODETYPE_RIGHT_BEFORE_LEFT) { 00512 return false; 00513 } 00514 if (fromE == otherFromE) { 00515 // ignore same edge links 00516 return false; 00517 } 00518 if (!foes(otherFromE, otherToE, fromE, toE)) { 00519 // if they do not cross, no waiting place is needed 00520 return false; 00521 } 00522 LinkDirection d1 = getDirection(fromE, toE); 00523 LinkDirection d2 = getDirection(otherFromE, otherToE); 00524 bool thisLeft = (d1 == LINKDIR_LEFT || d1 == LINKDIR_TURN); 00525 bool otherLeft = (d2 == LINKDIR_LEFT || d2 == LINKDIR_TURN); 00526 bool bothLeft = thisLeft && otherLeft; 00527 if (c.tlID != "" && !bothLeft) { 00528 // tls-controlled links will have space 00529 return true; 00530 } 00531 if (fromE->getJunctionPriority(this) > 0 && otherFromE->getJunctionPriority(this) > 0) { 00532 return mustBrake(fromE, toE, c.toLane); 00533 } 00534 return false; 00535 } 00536 00537 00538 void 00539 NBNode::computeLogic(const NBEdgeCont& ec, OptionsCont& oc) { 00540 delete myRequest; // possibly recomputation step 00541 myRequest = 0; 00542 if (myIncomingEdges.size() == 0 || myOutgoingEdges.size() == 0) { 00543 // no logic if nothing happens here 00544 myType = NODETYPE_NOJUNCTION; 00545 return; 00546 } 00547 // check whether the node was set to be unregulated by the user 00548 if (oc.getBool("keep-nodes-unregulated") || oc.isInStringVector("keep-nodes-unregulated.explicit", getID()) 00549 || (oc.getBool("keep-nodes-unregulated.district-nodes") && (isNearDistrict() || isDistrict()))) { 00550 myType = NODETYPE_NOJUNCTION; 00551 return; 00552 } 00553 // compute the logic if necessary or split the junction 00554 if (myType != NODETYPE_NOJUNCTION && myType != NODETYPE_DISTRICT) { 00555 // build the request 00556 myRequest = new NBRequest(ec, this, 00557 myAllEdges, myIncomingEdges, myOutgoingEdges, myBlockedConnections); 00558 // check whether it is not too large 00559 unsigned int numConnections = myRequest->getSizes().second; 00560 if (numConnections >= 64) { 00561 // yep -> make it untcontrolled, warn 00562 WRITE_WARNING("Junction '" + getID() + "' is too complicated (#links>64); will be set to unregulated."); 00563 delete myRequest; 00564 myRequest = 0; 00565 myType = NODETYPE_NOJUNCTION; 00566 } else if (numConnections == 0) { 00567 delete myRequest; 00568 myRequest = 0; 00569 myType = NODETYPE_DEAD_END; 00570 } else { 00571 myRequest->buildBitfieldLogic(ec.isLeftHanded()); 00572 } 00573 } 00574 } 00575 00576 00577 bool 00578 NBNode::writeLogic(OutputDevice& into) const { 00579 if (myRequest) { 00580 myRequest->writeLogic(myID, into); 00581 return true; 00582 } 00583 return false; 00584 } 00585 00586 00587 void 00588 NBNode::computeNodeShape(bool leftHand) { 00589 if (myIncomingEdges.size() == 0 && myOutgoingEdges.size() == 0) { 00590 return; 00591 } 00592 try { 00593 NBNodeShapeComputer computer(*this); 00594 myPoly = computer.compute(leftHand); 00595 } catch (InvalidArgument&) { 00596 WRITE_WARNING("For node '" + getID() + "': could not compute shape."); 00597 } 00598 } 00599 00600 00601 void 00602 NBNode::computeLanes2Lanes() { 00603 // special case a): 00604 // one in, one out, the outgoing has one lane more 00605 if (myIncomingEdges.size() == 1 && myOutgoingEdges.size() == 1 00606 && myIncomingEdges[0]->getNumLanes() == myOutgoingEdges[0]->getNumLanes() - 1 00607 && myIncomingEdges[0] != myOutgoingEdges[0] 00608 && myIncomingEdges[0]->isConnectedTo(myOutgoingEdges[0])) { 00609 00610 NBEdge* incoming = myIncomingEdges[0]; 00611 NBEdge* outgoing = myOutgoingEdges[0]; 00612 // check if it's not the turnaround 00613 if (incoming->getTurnDestination() == outgoing) { 00614 // will be added later or not... 00615 return; 00616 } 00617 for (int i = 0; i < (int) incoming->getNumLanes(); ++i) { 00618 incoming->setConnection(i, outgoing, i + 1, NBEdge::L2L_COMPUTED); 00619 } 00620 incoming->setConnection(0, outgoing, 0, NBEdge::L2L_COMPUTED); 00621 return; 00622 } 00623 // special case b): 00624 // two in, one out, the outgoing has the same number of lanes as the sum of the incoming 00625 // and a high speed, too 00626 // --> highway on-ramp 00627 bool check = false; 00628 if (myIncomingEdges.size() == 2 && myOutgoingEdges.size() == 1) { 00629 check = myIncomingEdges[0]->getNumLanes() + myIncomingEdges[1]->getNumLanes() == myOutgoingEdges[0]->getNumLanes(); 00630 check &= (myIncomingEdges[0]->getStep() <= NBEdge::LANES2EDGES); 00631 check &= (myIncomingEdges[1]->getStep() <= NBEdge::LANES2EDGES); 00632 } 00633 if (check 00634 && myIncomingEdges[0] != myOutgoingEdges[0] 00635 && myIncomingEdges[0]->isConnectedTo(myOutgoingEdges[0])) { 00636 NBEdge* inc1 = myIncomingEdges[0]; 00637 NBEdge* inc2 = myIncomingEdges[1]; 00638 // for internal: check which one is the rightmost 00639 SUMOReal a1 = inc1->getAngleAtNode(this); 00640 SUMOReal a2 = inc2->getAngleAtNode(this); 00641 SUMOReal ccw = GeomHelper::getCCWAngleDiff(a1, a2); 00642 SUMOReal cw = GeomHelper::getCWAngleDiff(a1, a2); 00643 if (ccw < cw) { 00644 std::swap(inc1, inc2); 00645 } 00646 // 00647 inc1->addLane2LaneConnections(0, myOutgoingEdges[0], 0, inc1->getNumLanes(), NBEdge::L2L_VALIDATED, true, true); 00648 inc2->addLane2LaneConnections(0, myOutgoingEdges[0], inc1->getNumLanes(), inc2->getNumLanes(), NBEdge::L2L_VALIDATED, true, true); 00649 return; 00650 } 00651 00652 // go through this node's outgoing edges 00653 // for every outgoing edge, compute the distribution of the node's 00654 // incoming edges on this edge when approaching this edge 00655 // the incoming edges' steps will then also be marked as LANE2LANE_RECHECK... 00656 EdgeVector::reverse_iterator i; 00657 for (i = myOutgoingEdges.rbegin(); i != myOutgoingEdges.rend(); i++) { 00658 NBEdge* currentOutgoing = *i; 00659 // get the information about edges that do approach this edge 00660 EdgeVector* approaching = getEdgesThatApproach(currentOutgoing); 00661 if (approaching->size() != 0) { 00662 ApproachingDivider divider(approaching, currentOutgoing); 00663 Bresenham::compute(÷r, static_cast<unsigned int>(approaching->size()), 00664 currentOutgoing->getNumLanes()); 00665 } 00666 delete approaching; 00667 } 00668 // ... but we may have the case that there are no outgoing edges 00669 // In this case, we have to mark the incoming edges as being in state 00670 // LANE2LANE( not RECHECK) by hand 00671 if (myOutgoingEdges.size() == 0) { 00672 for (i = myIncomingEdges.rbegin(); i != myIncomingEdges.rend(); i++) { 00673 (*i)->markAsInLane2LaneState(); 00674 } 00675 } 00676 } 00677 00678 00679 EdgeVector* 00680 NBNode::getEdgesThatApproach(NBEdge* currentOutgoing) { 00681 // get the position of the node to get the approaching nodes of 00682 EdgeVector::const_iterator i = find(myAllEdges.begin(), 00683 myAllEdges.end(), currentOutgoing); 00684 // get the first possible approaching edge 00685 NBContHelper::nextCW(myAllEdges, i); 00686 // go through the list of edges clockwise and add the edges 00687 EdgeVector* approaching = new EdgeVector(); 00688 for (; *i != currentOutgoing;) { 00689 // check only incoming edges 00690 if ((*i)->getToNode() == this && (*i)->getTurnDestination() != currentOutgoing) { 00691 std::vector<int> connLanes = (*i)->getConnectionLanes(currentOutgoing); 00692 if (connLanes.size() != 0) { 00693 approaching->push_back(*i); 00694 } 00695 } 00696 NBContHelper::nextCW(myAllEdges, i); 00697 } 00698 return approaching; 00699 } 00700 00701 00702 void 00703 NBNode::replaceOutgoing(NBEdge* which, NBEdge* by, unsigned int laneOff) { 00704 // replace the edge in the list of outgoing nodes 00705 EdgeVector::iterator i = find(myOutgoingEdges.begin(), myOutgoingEdges.end(), which); 00706 if (i != myOutgoingEdges.end()) { 00707 (*i) = by; 00708 i = find(myAllEdges.begin(), myAllEdges.end(), which); 00709 (*i) = by; 00710 } 00711 // replace the edge in connections of incoming edges 00712 for (i = myIncomingEdges.begin(); i != myIncomingEdges.end(); ++i) { 00713 (*i)->replaceInConnections(which, by, laneOff); 00714 } 00715 // replace within the connetion prohibition dependencies 00716 replaceInConnectionProhibitions(which, by, 0, laneOff); 00717 } 00718 00719 00720 void 00721 NBNode::replaceOutgoing(const EdgeVector& which, NBEdge* by) { 00722 // replace edges 00723 unsigned int laneOff = 0; 00724 for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) { 00725 replaceOutgoing(*i, by, laneOff); 00726 laneOff += (*i)->getNumLanes(); 00727 } 00728 // removed SUMOReal occurences 00729 removeDoubleEdges(); 00730 // check whether this node belongs to a district and the edges 00731 // must here be also remapped 00732 if (myDistrict != 0) { 00733 myDistrict->replaceOutgoing(which, by); 00734 } 00735 } 00736 00737 00738 void 00739 NBNode::replaceIncoming(NBEdge* which, NBEdge* by, unsigned int laneOff) { 00740 // replace the edge in the list of incoming nodes 00741 EdgeVector::iterator i = find(myIncomingEdges.begin(), myIncomingEdges.end(), which); 00742 if (i != myIncomingEdges.end()) { 00743 (*i) = by; 00744 i = find(myAllEdges.begin(), myAllEdges.end(), which); 00745 (*i) = by; 00746 } 00747 // replace within the connetion prohibition dependencies 00748 replaceInConnectionProhibitions(which, by, laneOff, 0); 00749 } 00750 00751 00752 void 00753 NBNode::replaceIncoming(const EdgeVector& which, NBEdge* by) { 00754 // replace edges 00755 unsigned int laneOff = 0; 00756 for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) { 00757 replaceIncoming(*i, by, laneOff); 00758 laneOff += (*i)->getNumLanes(); 00759 } 00760 // removed SUMOReal occurences 00761 removeDoubleEdges(); 00762 // check whether this node belongs to a district and the edges 00763 // must here be also remapped 00764 if (myDistrict != 0) { 00765 myDistrict->replaceIncoming(which, by); 00766 } 00767 } 00768 00769 00770 00771 void 00772 NBNode::replaceInConnectionProhibitions(NBEdge* which, NBEdge* by, 00773 unsigned int whichLaneOff, unsigned int byLaneOff) { 00774 // replace in keys 00775 NBConnectionProhibits::iterator j = myBlockedConnections.begin(); 00776 while (j != myBlockedConnections.end()) { 00777 bool changed = false; 00778 NBConnection c = (*j).first; 00779 if (c.replaceFrom(which, whichLaneOff, by, byLaneOff)) { 00780 changed = true; 00781 } 00782 if (c.replaceTo(which, whichLaneOff, by, byLaneOff)) { 00783 changed = true; 00784 } 00785 if (changed) { 00786 myBlockedConnections[c] = (*j).second; 00787 myBlockedConnections.erase(j); 00788 j = myBlockedConnections.begin(); 00789 } else { 00790 j++; 00791 } 00792 } 00793 // replace in values 00794 for (j = myBlockedConnections.begin(); j != myBlockedConnections.end(); j++) { 00795 NBConnectionVector& prohibiting = (*j).second; 00796 for (NBConnectionVector::iterator k = prohibiting.begin(); k != prohibiting.end(); k++) { 00797 NBConnection& sprohibiting = *k; 00798 sprohibiting.replaceFrom(which, whichLaneOff, by, byLaneOff); 00799 sprohibiting.replaceTo(which, whichLaneOff, by, byLaneOff); 00800 } 00801 } 00802 } 00803 00804 00805 00806 void 00807 NBNode::removeDoubleEdges() { 00808 unsigned int i, j; 00809 // check incoming 00810 for (i = 0; myIncomingEdges.size() > 0 && i < myIncomingEdges.size() - 1; i++) { 00811 j = i + 1; 00812 while (j < myIncomingEdges.size()) { 00813 if (myIncomingEdges[i] == myIncomingEdges[j]) { 00814 myIncomingEdges.erase(myIncomingEdges.begin() + j); 00815 } else { 00816 j++; 00817 } 00818 } 00819 } 00820 // check outgoing 00821 for (i = 0; myOutgoingEdges.size() > 0 && i < myOutgoingEdges.size() - 1; i++) { 00822 j = i + 1; 00823 while (j < myOutgoingEdges.size()) { 00824 if (myOutgoingEdges[i] == myOutgoingEdges[j]) { 00825 myOutgoingEdges.erase(myOutgoingEdges.begin() + j); 00826 } else { 00827 j++; 00828 } 00829 } 00830 } 00831 // check all 00832 for (i = 0; myAllEdges.size() > 0 && i < myAllEdges.size() - 1; i++) { 00833 j = i + 1; 00834 while (j < myAllEdges.size()) { 00835 if (myAllEdges[i] == myAllEdges[j]) { 00836 myAllEdges.erase(myAllEdges.begin() + j); 00837 } else { 00838 j++; 00839 } 00840 } 00841 } 00842 } 00843 00844 00845 bool 00846 NBNode::hasIncoming(const NBEdge* const e) const { 00847 return find(myIncomingEdges.begin(), myIncomingEdges.end(), e) != myIncomingEdges.end(); 00848 } 00849 00850 00851 bool 00852 NBNode::hasOutgoing(const NBEdge* const e) const { 00853 return find(myOutgoingEdges.begin(), myOutgoingEdges.end(), e) != myOutgoingEdges.end(); 00854 } 00855 00856 00857 NBEdge* 00858 NBNode::getOppositeIncoming(NBEdge* e) const { 00859 EdgeVector edges = myIncomingEdges; 00860 if (find(edges.begin(), edges.end(), e) != edges.end()) { 00861 edges.erase(find(edges.begin(), edges.end(), e)); 00862 } 00863 if (e->getToNode() == this) { 00864 sort(edges.begin(), edges.end(), NBContHelper::edge_opposite_direction_sorter(e, this)); 00865 } else { 00866 sort(edges.begin(), edges.end(), NBContHelper::edge_similar_direction_sorter(e)); 00867 } 00868 return edges[0]; 00869 } 00870 00871 00872 void 00873 NBNode::addSortedLinkFoes(const NBConnection& mayDrive, 00874 const NBConnection& mustStop) { 00875 if (mayDrive.getFrom() == 0 || 00876 mayDrive.getTo() == 0 || 00877 mustStop.getFrom() == 0 || 00878 mustStop.getTo() == 0) { 00879 00880 WRITE_WARNING("Something went wrong during the building of a connection..."); 00881 return; // !!! mark to recompute connections 00882 } 00883 NBConnectionVector conn = myBlockedConnections[mustStop]; 00884 conn.push_back(mayDrive); 00885 myBlockedConnections[mustStop] = conn; 00886 } 00887 00888 00889 NBEdge* 00890 NBNode::getPossiblySplittedIncoming(const std::string& edgeid) { 00891 unsigned int size = (unsigned int) edgeid.length(); 00892 for (EdgeVector::iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) { 00893 std::string id = (*i)->getID(); 00894 if (id.substr(0, size) == edgeid) { 00895 return *i; 00896 } 00897 } 00898 return 0; 00899 } 00900 00901 00902 NBEdge* 00903 NBNode::getPossiblySplittedOutgoing(const std::string& edgeid) { 00904 unsigned int size = (unsigned int) edgeid.length(); 00905 for (EdgeVector::iterator i = myOutgoingEdges.begin(); i != myOutgoingEdges.end(); i++) { 00906 std::string id = (*i)->getID(); 00907 if (id.substr(0, size) == edgeid) { 00908 return *i; 00909 } 00910 } 00911 return 0; 00912 } 00913 00914 00915 void 00916 NBNode::removeEdge(NBEdge* edge, bool removeFromConnections) { 00917 EdgeVector::iterator i = find(myAllEdges.begin(), myAllEdges.end(), edge); 00918 if (i != myAllEdges.end()) { 00919 myAllEdges.erase(i); 00920 i = find(myOutgoingEdges.begin(), myOutgoingEdges.end(), edge); 00921 if (i != myOutgoingEdges.end()) { 00922 myOutgoingEdges.erase(i); 00923 } else { 00924 i = find(myIncomingEdges.begin(), myIncomingEdges.end(), edge); 00925 if (i != myIncomingEdges.end()) { 00926 myIncomingEdges.erase(i); 00927 } else { 00928 // edge must have been either incoming or outgoing 00929 assert(false); 00930 } 00931 } 00932 if (removeFromConnections) { 00933 for (i = myAllEdges.begin(); i != myAllEdges.end(); ++i) { 00934 (*i)->removeFromConnections(edge); 00935 } 00936 } 00937 } 00938 } 00939 00940 00941 Position 00942 NBNode::getEmptyDir() const { 00943 Position pos(0, 0); 00944 EdgeVector::const_iterator i; 00945 for (i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) { 00946 NBNode* conn = (*i)->getFromNode(); 00947 Position toAdd = conn->getPosition(); 00948 toAdd.sub(myPosition); 00949 toAdd.mul((SUMOReal) 1.0 / sqrt(toAdd.x()*toAdd.x() + toAdd.y()*toAdd.y())); 00950 pos.add(toAdd); 00951 } 00952 for (i = myOutgoingEdges.begin(); i != myOutgoingEdges.end(); i++) { 00953 NBNode* conn = (*i)->getToNode(); 00954 Position toAdd = conn->getPosition(); 00955 toAdd.sub(myPosition); 00956 toAdd.mul((SUMOReal) 1.0 / sqrt(toAdd.x()*toAdd.x() + toAdd.y()*toAdd.y())); 00957 pos.add(toAdd); 00958 } 00959 pos.mul((SUMOReal) - 1.0 / (myIncomingEdges.size() + myOutgoingEdges.size())); 00960 if (pos.x() == 0 && pos.y() == 0) { 00961 pos = Position(1, 0); 00962 } 00963 pos.norm2d(); 00964 return pos; 00965 } 00966 00967 00968 00969 void 00970 NBNode::invalidateIncomingConnections() { 00971 for (EdgeVector::const_iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) { 00972 (*i)->invalidateConnections(); 00973 } 00974 } 00975 00976 00977 void 00978 NBNode::invalidateOutgoingConnections() { 00979 for (EdgeVector::const_iterator i = myOutgoingEdges.begin(); i != myOutgoingEdges.end(); i++) { 00980 (*i)->invalidateConnections(); 00981 } 00982 } 00983 00984 00985 bool 00986 NBNode::mustBrake(const NBEdge* const from, const NBEdge* const to, int toLane) const { 00987 // check whether it is participant to a traffic light 00988 // - controlled links are set by the traffic lights, not the normal 00989 // right-of-way rules 00990 // - uncontrolled participants (spip lanes etc.) should always break 00991 if (myTrafficLights.size() != 0) { 00992 // ok, we have a traffic light, return true by now, it will be later 00993 // controlled by the tls 00994 return true; 00995 } 00996 // unregulated->does not need to brake 00997 if (myRequest == 0) { 00998 return false; 00999 } 01000 // vehicles which do not have a following lane must always decelerate to the end 01001 if (to == 0) { 01002 return true; 01003 } 01004 // check whether any other connection on this node prohibits this connection 01005 bool try1 = myRequest->mustBrake(from, to); 01006 if (!try1 || toLane == -1) { 01007 return try1; 01008 } 01009 if (from->getSpeed() < 70. / 3.6) { 01010 return try1; 01011 } 01012 // on highways (on-ramps, in fact): 01013 // check whether any other connection uses the same destination edge 01014 for (EdgeVector::const_iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) { 01015 if ((*i) == from) { 01016 continue; 01017 } 01018 const std::vector<NBEdge::Connection> &connections = (*i)->getConnections(); 01019 for (std::vector<NBEdge::Connection>::const_iterator j = connections.begin(); j != connections.end(); ++j) { 01020 if ((*j).toEdge == to && ((*j).toLane < 0 || (*j).toLane == toLane)) { 01021 return true; 01022 } 01023 } 01024 } 01025 return false; 01026 } 01027 01028 01029 bool 01030 NBNode::isLeftMover(const NBEdge* const from, const NBEdge* const to) const { 01031 // when the junction has only one incoming edge, there are no 01032 // problems caused by left blockings 01033 if (myIncomingEdges.size() == 1 || myOutgoingEdges.size() == 1) { 01034 return false; 01035 } 01036 SUMOReal fromAngle = from->getAngleAtNode(this); 01037 SUMOReal toAngle = to->getAngleAtNode(this); 01038 SUMOReal cw = GeomHelper::getCWAngleDiff(fromAngle, toAngle); 01039 SUMOReal ccw = GeomHelper::getCCWAngleDiff(fromAngle, toAngle); 01040 std::vector<NBEdge*>::const_iterator i = std::find(myAllEdges.begin(), myAllEdges.end(), from); 01041 do { 01042 NBContHelper::nextCW(myAllEdges, i); 01043 } while ((!hasOutgoing(*i) || from->isTurningDirectionAt(this, *i)) && *i != from); 01044 return cw < ccw && (*i) == to && myOutgoingEdges.size() > 2; 01045 } 01046 01047 01048 bool 01049 NBNode::forbids(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo, 01050 const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo, 01051 bool regardNonSignalisedLowerPriority) const { 01052 return myRequest != 0 && myRequest->forbids(possProhibitorFrom, possProhibitorTo, 01053 possProhibitedFrom, possProhibitedTo, 01054 regardNonSignalisedLowerPriority); 01055 } 01056 01057 01058 bool 01059 NBNode::foes(const NBEdge* const from1, const NBEdge* const to1, 01060 const NBEdge* const from2, const NBEdge* const to2) const { 01061 return myRequest != 0 && myRequest->foes(from1, to1, from2, to2); 01062 } 01063 01064 01065 void 01066 NBNode::remapRemoved(NBTrafficLightLogicCont& tc, 01067 NBEdge* removed, const EdgeVector& incoming, 01068 const EdgeVector& outgoing) { 01069 assert(find(incoming.begin(), incoming.end(), removed) == incoming.end()); 01070 bool changed = true; 01071 while (changed) { 01072 changed = false; 01073 NBConnectionProhibits blockedConnectionsTmp = myBlockedConnections; 01074 NBConnectionProhibits blockedConnectionsNew; 01075 // remap in connections 01076 for (NBConnectionProhibits::iterator i = blockedConnectionsTmp.begin(); i != blockedConnectionsTmp.end(); i++) { 01077 const NBConnection& blocker = (*i).first; 01078 const NBConnectionVector& blocked = (*i).second; 01079 // check the blocked connections first 01080 // check whether any of the blocked must be changed 01081 bool blockedChanged = false; 01082 NBConnectionVector newBlocked; 01083 NBConnectionVector::const_iterator j; 01084 for (j = blocked.begin(); j != blocked.end(); j++) { 01085 const NBConnection& sblocked = *j; 01086 if (sblocked.getFrom() == removed || sblocked.getTo() == removed) { 01087 blockedChanged = true; 01088 } 01089 } 01090 // adapt changes if so 01091 for (j = blocked.begin(); blockedChanged && j != blocked.end(); j++) { 01092 const NBConnection& sblocked = *j; 01093 if (sblocked.getFrom() == removed && sblocked.getTo() == removed) { 01094 /* for(EdgeVector::const_iterator k=incoming.begin(); k!=incoming.end(); k++) { 01095 !!! newBlocked.push_back(NBConnection(*k, *k)); 01096 }*/ 01097 } else if (sblocked.getFrom() == removed) { 01098 assert(sblocked.getTo() != removed); 01099 for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) { 01100 newBlocked.push_back(NBConnection(*k, sblocked.getTo())); 01101 } 01102 } else if (sblocked.getTo() == removed) { 01103 assert(sblocked.getFrom() != removed); 01104 for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) { 01105 newBlocked.push_back(NBConnection(sblocked.getFrom(), *k)); 01106 } 01107 } else { 01108 newBlocked.push_back(NBConnection(sblocked.getFrom(), sblocked.getTo())); 01109 } 01110 } 01111 if (blockedChanged) { 01112 blockedConnectionsNew[blocker] = newBlocked; 01113 changed = true; 01114 } 01115 // if the blocked were kept 01116 else { 01117 if (blocker.getFrom() == removed && blocker.getTo() == removed) { 01118 changed = true; 01119 /* for(EdgeVector::const_iterator k=incoming.begin(); k!=incoming.end(); k++) { 01120 !!! blockedConnectionsNew[NBConnection(*k, *k)] = blocked; 01121 }*/ 01122 } else if (blocker.getFrom() == removed) { 01123 assert(blocker.getTo() != removed); 01124 changed = true; 01125 for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) { 01126 blockedConnectionsNew[NBConnection(*k, blocker.getTo())] = blocked; 01127 } 01128 } else if (blocker.getTo() == removed) { 01129 assert(blocker.getFrom() != removed); 01130 changed = true; 01131 for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) { 01132 blockedConnectionsNew[NBConnection(blocker.getFrom(), *k)] = blocked; 01133 } 01134 } else { 01135 blockedConnectionsNew[blocker] = blocked; 01136 } 01137 } 01138 } 01139 myBlockedConnections = blockedConnectionsNew; 01140 } 01141 // remap in traffic lights 01142 tc.remapRemoved(removed, incoming, outgoing); 01143 } 01144 01145 01146 LinkDirection 01147 NBNode::getDirection(const NBEdge* const incoming, const NBEdge* const outgoing) const { 01148 // ok, no connection at all -> dead end 01149 if (outgoing == 0) { 01150 return LINKDIR_NODIR; 01151 } 01152 // turning direction 01153 if (incoming->isTurningDirectionAt(this, outgoing)) { 01154 return LINKDIR_TURN; 01155 } 01156 // get the angle between incoming/outgoing at the junction 01157 SUMOReal angle = 01158 NBHelpers::normRelAngle(incoming->getAngleAtNode(this), outgoing->getAngleAtNode(this)); 01159 // ok, should be a straight connection 01160 if (abs((int) angle) + 1 < 45) { 01161 return LINKDIR_STRAIGHT; 01162 } 01163 01164 // check for left and right, first 01165 if (angle > 0) { 01166 // check whether any other edge goes further to the right 01167 EdgeVector::const_iterator i = 01168 find(myAllEdges.begin(), myAllEdges.end(), outgoing); 01169 NBContHelper::nextCW(myAllEdges, i); 01170 while ((*i) != incoming) { 01171 if ((*i)->getFromNode() == this) { 01172 return LINKDIR_PARTRIGHT; 01173 } 01174 NBContHelper::nextCW(myAllEdges, i); 01175 } 01176 return LINKDIR_RIGHT; 01177 } 01178 // check whether any other edge goes further to the left 01179 EdgeVector::const_iterator i = 01180 find(myAllEdges.begin(), myAllEdges.end(), outgoing); 01181 NBContHelper::nextCCW(myAllEdges, i); 01182 while ((*i) != incoming) { 01183 if ((*i)->getFromNode() == this && !incoming->isTurningDirectionAt(this, *i)) { 01184 return LINKDIR_PARTLEFT; 01185 } 01186 NBContHelper::nextCCW(myAllEdges, i); 01187 } 01188 return LINKDIR_LEFT; 01189 } 01190 01191 01192 std::string 01193 NBNode::stateCode(const NBEdge* incoming, NBEdge* outgoing, int fromlane, bool mayDefinitelyPass) const { 01194 if (outgoing == 0) { // always off 01195 return toString(LINKSTATE_TL_OFF_NOSIGNAL); 01196 } 01197 if (myType == NODETYPE_RIGHT_BEFORE_LEFT) { 01198 return toString(LINKSTATE_EQUAL); // all the same 01199 } 01200 if ((!incoming->isInnerEdge() && mustBrake(incoming, outgoing, fromlane)) && !mayDefinitelyPass) { 01201 return toString(LINKSTATE_MINOR); // minor road 01202 } 01203 // traffic lights are not regardedm here 01204 return toString(LINKSTATE_MAJOR); 01205 } 01206 01207 01208 bool 01209 NBNode::checkIsRemovable() const { 01210 // check whether this node is included in a traffic light 01211 if (myTrafficLights.size() != 0) { 01212 return false; 01213 } 01214 EdgeVector::const_iterator i; 01215 // one in, one out -> just a geometry ... 01216 if (myOutgoingEdges.size() == 1 && myIncomingEdges.size() == 1) { 01217 // ... if types match ... 01218 if (!myIncomingEdges[0]->expandableBy(myOutgoingEdges[0])) { 01219 return false; 01220 } 01221 // 01222 return myIncomingEdges[0]->getFromNode() != myOutgoingEdges[0]->getToNode(); 01223 } 01224 // two in, two out -> may be something else 01225 if (myOutgoingEdges.size() == 2 && myIncomingEdges.size() == 2) { 01226 // check whether the origin nodes of the incoming edges differ 01227 std::set<NBNode*> origSet; 01228 for (i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) { 01229 origSet.insert((*i)->getFromNode()); 01230 } 01231 if (origSet.size() < 2) { 01232 return false; 01233 } 01234 // check whether this node is an intermediate node of 01235 // a two-directional street 01236 for (i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) { 01237 // try to find the opposite direction 01238 NBNode* origin = (*i)->getFromNode(); 01239 // find the back direction of the current edge 01240 EdgeVector::const_iterator j = 01241 find_if(myOutgoingEdges.begin(), myOutgoingEdges.end(), 01242 NBContHelper::edge_with_destination_finder(origin)); 01243 // check whether the back direction exists 01244 if (j != myOutgoingEdges.end()) { 01245 // check whether the edge from the backdirection (must be 01246 // the counter-clockwise one) may be joined with the current 01247 NBContHelper::nextCCW(myOutgoingEdges, j); 01248 // check whether the types allow joining 01249 if (!(*i)->expandableBy(*j)) { 01250 return false; 01251 } 01252 } else { 01253 // ok, at least one outgoing edge is not an opposite 01254 // of an incoming one 01255 return false; 01256 } 01257 } 01258 return true; 01259 } 01260 // ok, a real node 01261 return false; 01262 } 01263 01264 01265 std::vector<std::pair<NBEdge*, NBEdge*> > 01266 NBNode::getEdgesToJoin() const { 01267 assert(checkIsRemovable()); 01268 std::vector<std::pair<NBEdge*, NBEdge*> > ret; 01269 // one in, one out-case 01270 if (myOutgoingEdges.size() == 1 && myIncomingEdges.size() == 1) { 01271 ret.push_back( 01272 std::pair<NBEdge*, NBEdge*>( 01273 myIncomingEdges[0], myOutgoingEdges[0])); 01274 return ret; 01275 } 01276 // two in, two out-case 01277 for (EdgeVector::const_iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) { 01278 NBNode* origin = (*i)->getFromNode(); 01279 EdgeVector::const_iterator j = 01280 find_if(myOutgoingEdges.begin(), myOutgoingEdges.end(), 01281 NBContHelper::edge_with_destination_finder(origin)); 01282 NBContHelper::nextCCW(myOutgoingEdges, j); 01283 ret.push_back(std::pair<NBEdge*, NBEdge*>(*i, *j)); 01284 } 01285 return ret; 01286 } 01287 01288 01289 const PositionVector& 01290 NBNode::getShape() const { 01291 return myPoly; 01292 } 01293 01294 01295 SUMOReal 01296 NBNode::getMaxEdgeWidth() const { 01297 EdgeVector::const_iterator i = myAllEdges.begin(); 01298 assert(i != myAllEdges.end()); 01299 SUMOReal ret = (*i)->width(); 01300 ++i; 01301 for (; i != myAllEdges.end(); i++) { 01302 ret = ret > (*i)->width() ? ret : (*i)->width(); 01303 } 01304 return ret; 01305 } 01306 01307 01308 NBEdge* 01309 NBNode::getConnectionTo(NBNode* n) const { 01310 for (EdgeVector::const_iterator i = myOutgoingEdges.begin(); i != myOutgoingEdges.end(); i++) { 01311 if ((*i)->getToNode() == n) { 01312 return (*i); 01313 } 01314 } 01315 return 0; 01316 } 01317 01318 01319 bool 01320 NBNode::isNearDistrict() const { 01321 if (isDistrict()) { 01322 return false; 01323 } 01324 EdgeVector edges; 01325 copy(getIncomingEdges().begin(), getIncomingEdges().end(), 01326 back_inserter(edges)); 01327 copy(getOutgoingEdges().begin(), getOutgoingEdges().end(), 01328 back_inserter(edges)); 01329 for (EdgeVector::const_iterator j = edges.begin(); j != edges.end(); ++j) { 01330 NBEdge* t = *j; 01331 NBNode* other = 0; 01332 if (t->getToNode() == this) { 01333 other = t->getFromNode(); 01334 } else { 01335 other = t->getToNode(); 01336 } 01337 EdgeVector edges2; 01338 copy(other->getIncomingEdges().begin(), other->getIncomingEdges().end(), back_inserter(edges2)); 01339 copy(other->getOutgoingEdges().begin(), other->getOutgoingEdges().end(), back_inserter(edges2)); 01340 for (EdgeVector::const_iterator k = edges2.begin(); k != edges2.end(); ++k) { 01341 if ((*k)->getFromNode()->isDistrict() || (*k)->getToNode()->isDistrict()) { 01342 return true; 01343 } 01344 } 01345 } 01346 return false; 01347 } 01348 01349 01350 bool 01351 NBNode::isDistrict() const { 01352 return myType == NODETYPE_DISTRICT; 01353 } 01354 01355 01356 void 01357 NBNode::buildInnerEdges() { 01358 unsigned int noInternalNoSplits = 0; 01359 for (EdgeVector::const_iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) { 01360 const std::vector<NBEdge::Connection> &elv = (*i)->getConnections(); 01361 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) { 01362 if ((*k).toEdge == 0) { 01363 continue; 01364 } 01365 noInternalNoSplits++; 01366 } 01367 } 01368 unsigned int lno = 0; 01369 unsigned int splitNo = 0; 01370 for (EdgeVector::const_iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) { 01371 (*i)->buildInnerEdges(*this, noInternalNoSplits, lno, splitNo); 01372 } 01373 } 01374 01375 01376 /****************************************************************************/ 01377