SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00009 // This class computes shapes of junctions 00010 /****************************************************************************/ 00011 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/ 00012 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors 00013 /****************************************************************************/ 00014 // 00015 // This file is part of SUMO. 00016 // SUMO is free software: you can redistribute it and/or modify 00017 // it under the terms of the GNU General Public License as published by 00018 // the Free Software Foundation, either version 3 of the License, or 00019 // (at your option) any later version. 00020 // 00021 /****************************************************************************/ 00022 00023 00024 // =========================================================================== 00025 // included modules 00026 // =========================================================================== 00027 #ifdef _MSC_VER 00028 #include <windows_config.h> 00029 #else 00030 #include <config.h> 00031 #endif 00032 00033 #include <algorithm> 00034 #include <utils/geom/PositionVector.h> 00035 #include <utils/options/OptionsCont.h> 00036 #include <utils/geom/GeomHelper.h> 00037 #include <utils/common/StdDefs.h> 00038 #include <utils/common/UtilExceptions.h> 00039 #include <utils/common/ToString.h> 00040 #include <utils/iodevices/OutputDevice.h> 00041 #include "NBNode.h" 00042 #include "NBNodeShapeComputer.h" 00043 00044 #ifdef CHECK_MEMORY_LEAKS 00045 #include <foreign/nvwa/debug_new.h> 00046 #endif // CHECK_MEMORY_LEAKS 00047 00048 00049 // =========================================================================== 00050 // method definitions 00051 // =========================================================================== 00052 NBNodeShapeComputer::NBNodeShapeComputer(const NBNode& node) 00053 : myNode(node) {} 00054 00055 00056 NBNodeShapeComputer::~NBNodeShapeComputer() {} 00057 00058 00059 PositionVector 00060 NBNodeShapeComputer::compute(bool leftHand) { 00061 UNUSED_PARAMETER(leftHand); 00062 PositionVector ret; 00063 // check whether the node is a dead end node or a node where only turning is possible 00064 // in this case, we will use "computeNodeShapeByCrosses" 00065 bool singleDirection = false; 00066 if (myNode.myAllEdges.size() == 1) { 00067 singleDirection = true; 00068 } 00069 if (myNode.myAllEdges.size() == 2 && myNode.getIncomingEdges().size() == 1) { 00070 if (myNode.getIncomingEdges()[0]->isTurningDirectionAt(&myNode, myNode.getOutgoingEdges()[0])) { 00071 singleDirection = true; 00072 } 00073 } 00074 if (singleDirection) { 00075 return computeNodeShapeByCrosses(); 00076 } 00077 // check whether the node is a just something like a geometry 00078 // node (one in and one out or two in and two out, pair-wise continuations) 00079 // also in this case "computeNodeShapeByCrosses" is used 00080 bool geometryLike = myNode.isSimpleContinuation(); 00081 if (geometryLike) { 00082 // additionally, the angle between the edges must not be larger than 45 degrees 00083 // (otherwise, we will try to compute the shape in a different way) 00084 const EdgeVector& incoming = myNode.getIncomingEdges(); 00085 const EdgeVector& outgoing = myNode.getOutgoingEdges(); 00086 SUMOReal maxAngle = SUMOReal(0); 00087 for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); ++i) { 00088 SUMOReal ia = (*i)->getAngleAtNode(&myNode); 00089 for (EdgeVector::const_iterator j = outgoing.begin(); j != outgoing.end(); ++j) { 00090 SUMOReal oa = (*j)->getAngleAtNode(&myNode); 00091 SUMOReal ad = GeomHelper::getMinAngleDiff(ia, oa); 00092 if (22.5 >= ad) { 00093 maxAngle = MAX2(ad, maxAngle); 00094 } 00095 } 00096 } 00097 if (maxAngle > 22.5) { 00098 return computeNodeShapeByCrosses(); 00099 } 00100 } 00101 00102 // 00103 ret = computeContinuationNodeShape(geometryLike); 00104 // fail fall-back: use "computeNodeShapeByCrosses" 00105 if (ret.size() < 3) { 00106 ret = computeNodeShapeByCrosses(); 00107 } 00108 return ret; 00109 } 00110 00111 00112 void 00113 computeSameEnd(PositionVector& l1, PositionVector& l2) { 00114 Line sub(l1.lineAt(0).getPositionAtDistance(100), l1[1]); 00115 Line tmp(sub); 00116 tmp.rotateAtP1(PI / 2); 00117 tmp.extrapolateBy(100); 00118 if (l1.intersects(tmp.p1(), tmp.p2())) { 00119 SUMOReal offset1 = l1.intersectsAtLengths2D(tmp)[0]; 00120 Line tl1 = Line( 00121 l1.lineAt(0).getPositionAtDistance(offset1), 00122 l1[1]); 00123 tl1.extrapolateBy(100); 00124 l1.replaceAt(0, tl1.p1()); 00125 } 00126 if (l2.intersects(tmp.p1(), tmp.p2())) { 00127 SUMOReal offset2 = l2.intersectsAtLengths2D(tmp)[0]; 00128 Line tl2 = Line( 00129 l2.lineAt(0).getPositionAtDistance(offset2), 00130 l2[1]); 00131 tl2.extrapolateBy(100); 00132 l2.replaceAt(0, tl2.p1()); 00133 } 00134 } 00135 00136 00137 void 00138 NBNodeShapeComputer::replaceLastChecking(PositionVector& g, bool decenter, 00139 PositionVector counter, 00140 size_t counterLanes, SUMOReal counterDist, 00141 int laneDiff) { 00142 counter.extrapolate(100); 00143 Position counterPos = counter.positionAtLengthPosition2D(counterDist); 00144 PositionVector t = g; 00145 t.extrapolate(100); 00146 SUMOReal p = t.nearest_position_on_line_to_point2D(counterPos); 00147 if (p >= 0) { 00148 counterPos = t.positionAtLengthPosition2D(p); 00149 } 00150 if (g[-1].distanceTo(counterPos) < SUMO_const_laneWidth * (SUMOReal) counterLanes) { 00151 g.replaceAt(g.size() - 1, counterPos); 00152 } else { 00153 g.push_back_noDoublePos(counterPos); 00154 } 00155 if (decenter) { 00156 Line l(g[-2], g[-1]); 00157 SUMOReal factor = laneDiff % 2 != 0 ? SUMO_const_halfLaneAndOffset : SUMO_const_laneWidthAndOffset; 00158 l.move2side(-factor);//SUMO_const_laneWidthAndOffset); 00159 g.replaceAt(g.size() - 1, l.p2()); 00160 } 00161 } 00162 00163 00164 void 00165 NBNodeShapeComputer::replaceFirstChecking(PositionVector& g, bool decenter, 00166 PositionVector counter, 00167 size_t counterLanes, SUMOReal counterDist, 00168 int laneDiff) { 00169 counter.extrapolate(100); 00170 Position counterPos = counter.positionAtLengthPosition2D(counterDist); 00171 PositionVector t = g; 00172 t.extrapolate(100); 00173 SUMOReal p = t.nearest_position_on_line_to_point2D(counterPos); 00174 if (p >= 0) { 00175 counterPos = t.positionAtLengthPosition2D(p); 00176 } 00177 if (g[0].distanceTo(counterPos) < SUMO_const_laneWidth * (SUMOReal) counterLanes) { 00178 g.replaceAt(0, counterPos); 00179 } else { 00180 g.push_front_noDoublePos(counterPos); 00181 } 00182 if (decenter) { 00183 Line l(g[0], g[1]); 00184 SUMOReal factor = laneDiff % 2 != 0 ? SUMO_const_halfLaneAndOffset : SUMO_const_laneWidthAndOffset; 00185 l.move2side(-factor); 00186 g.replaceAt(0, l.p1()); 00187 } 00188 } 00189 00190 00191 00192 PositionVector 00193 NBNodeShapeComputer::computeContinuationNodeShape(bool simpleContinuation) { 00194 // if we have less than two edges, we can not compute the node's shape this way 00195 if (myNode.myAllEdges.size() < 2) { 00196 return PositionVector(); 00197 } 00198 // initialise 00199 EdgeVector::const_iterator i; 00200 // edges located in the value-vector have the same direction as the key edge 00201 std::map<NBEdge*, EdgeVector > same; 00202 // the counter-clockwise boundary of the edge regarding possible same-direction edges 00203 std::map<NBEdge*, PositionVector> geomsCCW; 00204 // the clockwise boundary of the edge regarding possible same-direction edges 00205 std::map<NBEdge*, PositionVector> geomsCW; 00206 // store relationships 00207 std::map<NBEdge*, NBEdge*> ccwBoundary; 00208 std::map<NBEdge*, NBEdge*> cwBoundary; 00209 for (i = myNode.myAllEdges.begin(); i != myNode.myAllEdges.end(); i++) { 00210 cwBoundary[*i] = *i; 00211 ccwBoundary[*i] = *i; 00212 } 00213 // check which edges are parallel 00214 joinSameDirectionEdges(same, geomsCCW, geomsCW); 00215 // compute unique direction list 00216 EdgeVector newAll = computeUniqueDirectionList(same, geomsCCW, geomsCW, ccwBoundary, cwBoundary); 00217 // if we have only two "directions", let's not compute the geometry using this method 00218 if (newAll.size() < 2) { 00219 return PositionVector(); 00220 } 00221 // combine all geoms 00222 std::map<NBEdge*, bool> myExtended; 00223 std::map<NBEdge*, SUMOReal> distances; 00224 for (i = newAll.begin(); i != newAll.end(); ++i) { 00225 EdgeVector::const_iterator cwi = i; 00226 cwi++; 00227 if (cwi == newAll.end()) { 00228 cwi = newAll.begin(); 00229 } 00230 EdgeVector::const_iterator ccwi = i; 00231 if (ccwi == newAll.begin()) { 00232 ccwi = newAll.end() - 1; 00233 } else { 00234 ccwi--; 00235 } 00236 00237 assert(geomsCCW.find(*i) != geomsCCW.end()); 00238 assert(geomsCW.find(*ccwi) != geomsCW.end()); 00239 assert(geomsCW.find(*cwi) != geomsCW.end()); 00240 SUMOReal angleI = geomsCCW[*i].lineAt(0).atan2PositiveAngle(); 00241 SUMOReal angleCCW = geomsCW[*ccwi].lineAt(0).atan2PositiveAngle(); 00242 SUMOReal angleCW = geomsCW[*cwi].lineAt(0).atan2PositiveAngle(); 00243 SUMOReal ccad; 00244 SUMOReal cad; 00245 SUMOReal twoPI = (SUMOReal)(2 * PI); 00246 if (angleI > angleCCW) { 00247 ccad = angleI - angleCCW; 00248 } else { 00249 ccad = twoPI - angleCCW + angleI; 00250 } 00251 00252 if (angleI > angleCW) { 00253 cad = twoPI - angleI + angleCW; 00254 } else { 00255 cad = angleCW - angleI; 00256 } 00257 if (ccad < 0) { 00258 ccad += twoPI; 00259 } 00260 if (ccad > twoPI) { 00261 ccad -= twoPI; 00262 } 00263 if (cad < 0) { 00264 cad += twoPI; 00265 } 00266 if (cad > twoPI) { 00267 cad -= twoPI; 00268 } 00269 00270 if (simpleContinuation && ccad < (SUMOReal)(45. / 180.*PI)) { 00271 ccad += twoPI; 00272 } 00273 if (simpleContinuation && cad < (SUMOReal)(45. / 180.*PI)) { 00274 cad += twoPI; 00275 } 00276 00277 if (fabs(ccad - cad) < (SUMOReal) 0.1 && *cwi == *ccwi) { 00278 // compute the mean position between both edges ends ... 00279 Position p; 00280 if (myExtended.find(*ccwi) != myExtended.end()) { 00281 p = geomsCCW[*ccwi][0]; 00282 p.add(geomsCW[*ccwi][0]); 00283 p.mul(0.5); 00284 } else { 00285 p = geomsCCW[*ccwi][0]; 00286 p.add(geomsCW[*ccwi][0]); 00287 p.add(geomsCCW[*i][0]); 00288 p.add(geomsCW[*i][0]); 00289 p.mul(0.25); 00290 } 00291 // ... compute the distance to this point ... 00292 SUMOReal dist = geomsCCW[*i].nearest_position_on_line_to_point2D(p); 00293 if (dist < 0) { 00294 // ok, we have the problem that even the extrapolated geometry 00295 // does not reach the point 00296 // in this case, the geometry has to be extenden... too bad ... 00297 // ... let's append the mean position to the geometry 00298 PositionVector g = (*i)->getGeometry(); 00299 if (myNode.hasIncoming(*i)) { 00300 g.push_back_noDoublePos(p); 00301 } else { 00302 g.push_front_noDoublePos(p); 00303 } 00304 (*i)->setGeometry(g); 00305 // and rebuild previous information 00306 geomsCCW[*i] = (*i)->getCCWBoundaryLine(myNode, SUMO_const_halfLaneWidth); 00307 geomsCCW[*i].extrapolate(100); 00308 geomsCW[*i] = (*i)->getCWBoundaryLine(myNode, SUMO_const_halfLaneWidth); 00309 geomsCW[*i].extrapolate(100); 00310 // the distance is now = zero (the point we have appended) 00311 distances[*i] = 100; 00312 myExtended[*i] = true; 00313 } else { 00314 if (!simpleContinuation) { 00315 // let us put some geometry stuff into it 00316 dist = (SUMOReal) 1.5 + dist; 00317 } 00318 distances[*i] = dist; 00319 } 00320 00321 } else { 00322 if (ccad < cad) { 00323 if (!simpleContinuation) { 00324 if (geomsCCW[*i].intersects(geomsCW[*ccwi])) { 00325 distances[*i] = (SUMOReal) 1.5 + geomsCCW[*i].intersectsAtLengths2D(geomsCW[*ccwi])[0]; 00326 if (*cwi != *ccwi && geomsCW[*i].intersects(geomsCCW[*cwi])) { 00327 SUMOReal a1 = distances[*i]; 00328 SUMOReal a2 = (SUMOReal) 1.5 + geomsCW[*i].intersectsAtLengths2D(geomsCCW[*cwi])[0]; 00329 if (ccad > (SUMOReal)((90. + 45.) / 180.*PI) && cad > (SUMOReal)((90. + 45.) / 180.*PI)) { 00330 SUMOReal mmin = MIN2(distances[*cwi], distances[*ccwi]); 00331 if (mmin > 100) { 00332 distances[*i] = (SUMOReal) 5. + (SUMOReal) 100. - (SUMOReal)(mmin - 100); //100 + 1.5; 00333 } 00334 } else if (a2 > a1 + POSITION_EPS && a2 - a1 < (SUMOReal) 10) { 00335 distances[*i] = a2; 00336 } 00337 } 00338 } else { 00339 if (*cwi != *ccwi && geomsCW[*i].intersects(geomsCCW[*cwi])) { 00340 distances[*i] = (SUMOReal) 1.5 + geomsCW[*i].intersectsAtLengths2D(geomsCCW[*cwi])[0]; 00341 } else { 00342 distances[*i] = (SUMOReal)(100. + 1.5); 00343 } 00344 } 00345 } else { 00346 if (geomsCCW[*i].intersects(geomsCW[*ccwi])) { 00347 distances[*i] = geomsCCW[*i].intersectsAtLengths2D(geomsCW[*ccwi])[0]; 00348 } else { 00349 distances[*i] = (SUMOReal) 100.; 00350 } 00351 } 00352 } else { 00353 if (!simpleContinuation) { 00354 if (geomsCW[*i].intersects(geomsCCW[*cwi])) { 00355 distances[*i] = (SUMOReal)(1.5 + geomsCW[*i].intersectsAtLengths2D(geomsCCW[*cwi])[0]); 00356 if (*cwi != *ccwi && geomsCCW[*i].intersects(geomsCW[*ccwi])) { 00357 SUMOReal a1 = distances[*i]; 00358 SUMOReal a2 = (SUMOReal)(1.5 + geomsCCW[*i].intersectsAtLengths2D(geomsCW[*ccwi])[0]); 00359 if (ccad > (SUMOReal)((90. + 45.) / 180.*PI) && cad > (SUMOReal)((90. + 45.) / 180.*PI)) { 00360 SUMOReal mmin = MIN2(distances[*cwi], distances[*ccwi]); 00361 if (mmin > 100) { 00362 distances[*i] = (SUMOReal) 5. + (SUMOReal) 100. - (SUMOReal)(mmin - 100); //100 + 1.5; 00363 } 00364 } else if (a2 > a1 + POSITION_EPS && a2 - a1 < (SUMOReal) 10) { 00365 distances[*i] = a2; 00366 } 00367 } 00368 } else { 00369 if (*cwi != *ccwi && geomsCCW[*i].intersects(geomsCW[*ccwi])) { 00370 distances[*i] = (SUMOReal) 1.5 + geomsCCW[*i].intersectsAtLengths2D(geomsCW[*ccwi])[0]; 00371 } else { 00372 distances[*i] = (SUMOReal)(100. + 1.5); 00373 } 00374 } 00375 } else { 00376 if (geomsCW[*i].intersects(geomsCCW[*cwi])) { 00377 distances[*i] = geomsCW[*i].intersectsAtLengths2D(geomsCCW[*cwi])[0]; 00378 } else { 00379 distances[*i] = (SUMOReal) 100; 00380 } 00381 } 00382 } 00383 } 00384 } 00385 00386 for (i = newAll.begin(); i != newAll.end(); ++i) { 00387 if (distances.find(*i) != distances.end()) { 00388 continue; 00389 } 00390 EdgeVector::const_iterator cwi = i; 00391 cwi++; 00392 if (cwi == newAll.end()) { 00393 cwi = newAll.begin(); 00394 } 00395 EdgeVector::const_iterator ccwi = i; 00396 if (ccwi == newAll.begin()) { 00397 ccwi = newAll.end() - 1; 00398 } else { 00399 ccwi--; 00400 } 00401 00402 assert(geomsCW.find(*ccwi) != geomsCW.end()); 00403 assert(geomsCW.find(*cwi) != geomsCW.end()); 00404 Position p1 = distances.find(*cwi) != distances.end() && distances[*cwi] != -1 00405 ? geomsCCW[*cwi].positionAtLengthPosition2D(distances[*cwi]) 00406 : geomsCCW[*cwi].positionAtLengthPosition2D((SUMOReal) - .1); 00407 Position p2 = distances.find(*ccwi) != distances.end() && distances[*ccwi] != -1 00408 ? geomsCW[*ccwi].positionAtLengthPosition2D(distances[*ccwi]) 00409 : geomsCW[*ccwi].positionAtLengthPosition2D((SUMOReal) - .1); 00410 Line l(p1, p2); 00411 l.extrapolateBy(1000); 00412 SUMOReal angleI = geomsCCW[*i].lineAt(0).atan2PositiveAngle(); 00413 SUMOReal angleCCW = geomsCW[*ccwi].lineAt(0).atan2PositiveAngle(); 00414 SUMOReal angleCW = geomsCW[*cwi].lineAt(0).atan2PositiveAngle(); 00415 SUMOReal ccad; 00416 SUMOReal cad; 00417 SUMOReal twoPI = (SUMOReal)(2 * PI); 00418 if (angleI > angleCCW) { 00419 ccad = angleI - angleCCW; 00420 } else { 00421 ccad = twoPI - angleCCW + angleI; 00422 } 00423 00424 if (angleI > angleCW) { 00425 cad = twoPI - angleI + angleCW; 00426 } else { 00427 cad = angleCW - angleI; 00428 } 00429 00430 if (ccad < 0) { 00431 ccad += twoPI; 00432 } 00433 if (ccad > twoPI) { 00434 ccad -= twoPI; 00435 } 00436 if (cad < 0) { 00437 cad += twoPI; 00438 } 00439 if (cad > twoPI) { 00440 cad -= twoPI; 00441 } 00442 SUMOReal offset = 0; 00443 int laneDiff = (*i)->getNumLanes() - (*ccwi)->getNumLanes(); 00444 if (*ccwi != *cwi) { 00445 laneDiff -= (*cwi)->getNumLanes(); 00446 } 00447 laneDiff = 0; 00448 if (myNode.hasIncoming(*i) && (*ccwi)->getNumLanes() % 2 == 1) { 00449 laneDiff = 1; 00450 } 00451 if (myNode.hasOutgoing(*i) && (*cwi)->getNumLanes() % 2 == 1) { 00452 laneDiff = 1; 00453 } 00454 00455 PositionVector g = (*i)->getGeometry(); 00456 PositionVector counter; 00457 if (myNode.hasIncoming(*i)) { 00458 if (myNode.hasOutgoing(*ccwi) && myNode.hasOutgoing(*cwi)) { 00459 if (distances.find(*cwi) == distances.end()) { 00460 return PositionVector(); 00461 } 00462 replaceLastChecking(g, (*i)->getLaneSpreadFunction() == LANESPREAD_CENTER, 00463 (*cwi)->getGeometry(), (*cwi)->getNumLanes(), distances[*cwi], 00464 laneDiff); 00465 } else { 00466 if (distances.find(*ccwi) == distances.end()) { 00467 return PositionVector(); 00468 } 00469 counter = (*ccwi)->getGeometry(); 00470 if (myNode.hasIncoming(*ccwi)) { 00471 counter = counter.reverse(); 00472 } 00473 replaceLastChecking(g, (*i)->getLaneSpreadFunction() == LANESPREAD_CENTER, 00474 counter, (*ccwi)->getNumLanes(), distances[*ccwi], 00475 laneDiff); 00476 } 00477 } else { 00478 if (myNode.hasIncoming(*ccwi) && myNode.hasIncoming(*cwi)) { 00479 if (distances.find(*ccwi) == distances.end()) { 00480 return PositionVector(); 00481 } 00482 replaceFirstChecking(g, (*i)->getLaneSpreadFunction() == LANESPREAD_CENTER, 00483 (*ccwi)->getGeometry().reverse(), (*ccwi)->getNumLanes(), distances[*ccwi], 00484 laneDiff); 00485 } else { 00486 if (distances.find(*cwi) == distances.end()) { 00487 return PositionVector(); 00488 } 00489 counter = (*cwi)->getGeometry(); 00490 if (myNode.hasIncoming(*cwi)) { 00491 counter = counter.reverse(); 00492 } 00493 replaceFirstChecking(g, (*i)->getLaneSpreadFunction() == LANESPREAD_CENTER, 00494 counter, (*cwi)->getNumLanes(), distances[*cwi], 00495 laneDiff); 00496 } 00497 } 00498 (*i)->setGeometry(g); 00499 00500 if (cwBoundary[*i] != *i) { 00501 PositionVector g = cwBoundary[*i]->getGeometry(); 00502 PositionVector counter = (*cwi)->getGeometry(); 00503 if (myNode.hasIncoming(*cwi)) { 00504 counter = counter.reverse(); 00505 } 00506 if (myNode.hasIncoming(cwBoundary[*i])) { 00507 if (distances.find(*cwi) == distances.end()) { 00508 return PositionVector(); 00509 } 00510 replaceLastChecking(g, (*i)->getLaneSpreadFunction() == LANESPREAD_CENTER, 00511 counter, (*cwi)->getNumLanes(), distances[*cwi], 00512 laneDiff); 00513 } else { 00514 if (distances.find(*cwi) == distances.end()) { 00515 return PositionVector(); 00516 } 00517 replaceFirstChecking(g, (*i)->getLaneSpreadFunction() == LANESPREAD_CENTER, 00518 counter, (*cwi)->getNumLanes(), distances[*cwi], 00519 laneDiff); 00520 } 00521 cwBoundary[*i]->setGeometry(g); 00522 myExtended[cwBoundary[*i]] = true; 00523 geomsCW[*i] = cwBoundary[*i]->getCWBoundaryLine(myNode, SUMO_const_halfLaneWidth); 00524 } else { 00525 geomsCW[*i] = (*i)->getCWBoundaryLine(myNode, SUMO_const_halfLaneWidth); 00526 00527 } 00528 00529 geomsCW[*i].extrapolate(100); 00530 00531 if (ccwBoundary[*i] != *i) { 00532 PositionVector g = ccwBoundary[*i]->getGeometry(); 00533 PositionVector counter = (*ccwi)->getGeometry(); 00534 if (myNode.hasIncoming(*ccwi)) { 00535 counter = counter.reverse(); 00536 } 00537 if (myNode.hasIncoming(ccwBoundary[*i])) { 00538 if (distances.find(*ccwi) == distances.end()) { 00539 return PositionVector(); 00540 } 00541 replaceLastChecking(g, (*i)->getLaneSpreadFunction() == LANESPREAD_CENTER, 00542 counter, (*ccwi)->getNumLanes(), distances[*ccwi], 00543 laneDiff); 00544 } else { 00545 if (distances.find(*cwi) == distances.end()) { 00546 return PositionVector(); 00547 } 00548 replaceFirstChecking(g, (*i)->getLaneSpreadFunction() == LANESPREAD_CENTER, 00549 counter, (*cwi)->getNumLanes(), distances[*cwi], 00550 laneDiff); 00551 } 00552 ccwBoundary[*i]->setGeometry(g); 00553 myExtended[ccwBoundary[*i]] = true; 00554 geomsCCW[*i] = ccwBoundary[*i]->getCCWBoundaryLine(myNode, SUMO_const_halfLaneWidth); 00555 } else { 00556 geomsCCW[*i] = (*i)->getCCWBoundaryLine(myNode, SUMO_const_halfLaneWidth); 00557 00558 } 00559 geomsCCW[*i].extrapolate(100); 00560 00561 computeSameEnd(geomsCW[*i], geomsCCW[*i]); 00562 00563 // and rebuild previous information 00564 if (((*cwi)->getNumLanes() + (*ccwi)->getNumLanes()) > (*i)->getNumLanes()) { 00565 offset = 5; 00566 } 00567 if (ccwBoundary[*i] != cwBoundary[*i]) { 00568 offset = 5; 00569 } 00570 00571 myExtended[*i] = true; 00572 distances[*i] = 100 + offset; 00573 } 00574 00575 // build 00576 PositionVector ret; 00577 for (i = newAll.begin(); i != newAll.end(); ++i) { 00578 PositionVector l = geomsCCW[*i]; 00579 SUMOReal len = l.length(); 00580 SUMOReal offset = distances[*i]; 00581 if (offset == -1) { 00582 offset = (SUMOReal) - .1; 00583 } 00584 Position p; 00585 if (len >= offset) { 00586 p = l.positionAtLengthPosition2D(offset); 00587 } else { 00588 p = l.positionAtLengthPosition2D(len); 00589 } 00590 ret.push_back_noDoublePos(p); 00591 // 00592 l = geomsCW[*i]; 00593 len = l.length(); 00594 if (len >= offset) { 00595 p = l.positionAtLengthPosition2D(offset); 00596 } else { 00597 p = l.positionAtLengthPosition2D(len); 00598 } 00599 ret.push_back_noDoublePos(p); 00600 } 00601 return ret; 00602 } 00603 00604 00605 00606 void 00607 NBNodeShapeComputer::joinSameDirectionEdges(std::map<NBEdge*, EdgeVector > &same, 00608 std::map<NBEdge*, PositionVector> &geomsCCW, 00609 std::map<NBEdge*, PositionVector> &geomsCW) { 00610 EdgeVector::const_iterator i, j; 00611 for (i = myNode.myAllEdges.begin(); i != myNode.myAllEdges.end() - 1; i++) { 00612 // store current edge's boundary as current ccw/cw boundary 00613 geomsCCW[*i] = (*i)->getCCWBoundaryLine(myNode, SUMO_const_halfLaneWidth); 00614 geomsCW[*i] = (*i)->getCWBoundaryLine(myNode, SUMO_const_halfLaneWidth); 00615 // extend the boundary by extroplating it by 100m 00616 PositionVector g1 = 00617 myNode.hasIncoming(*i) 00618 ? (*i)->getCCWBoundaryLine(myNode, SUMO_const_halfLaneWidth) 00619 : (*i)->getCWBoundaryLine(myNode, SUMO_const_halfLaneWidth); 00620 Line l1 = g1.lineAt(0); 00621 Line tmp = geomsCCW[*i].lineAt(0); 00622 tmp.extrapolateBy(100); 00623 geomsCCW[*i].replaceAt(0, tmp.p1()); 00624 tmp = geomsCW[*i].lineAt(0); 00625 tmp.extrapolateBy(100); 00626 geomsCW[*i].replaceAt(0, tmp.p1()); 00627 // 00628 for (j = i + 1; j != myNode.myAllEdges.end(); j++) { 00629 geomsCCW[*j] = (*j)->getCCWBoundaryLine(myNode, SUMO_const_halfLaneWidth); 00630 geomsCW[*j] = (*j)->getCWBoundaryLine(myNode, SUMO_const_halfLaneWidth); 00631 PositionVector g2 = 00632 myNode.hasIncoming(*j) 00633 ? (*j)->getCCWBoundaryLine(myNode, SUMO_const_halfLaneWidth) 00634 : (*j)->getCWBoundaryLine(myNode, SUMO_const_halfLaneWidth); 00635 Line l2 = g2.lineAt(0); 00636 tmp = geomsCCW[*j].lineAt(0); 00637 tmp.extrapolateBy(100); 00638 geomsCCW[*j].replaceAt(0, tmp.p1()); 00639 tmp = geomsCW[*j].lineAt(0); 00640 tmp.extrapolateBy(100); 00641 geomsCW[*j].replaceAt(0, tmp.p1()); 00642 if (fabs(l1.atan2DegreeAngle() - l2.atan2DegreeAngle()) < 20) { 00643 if (same.find(*i) == same.end()) { 00644 same[*i] = EdgeVector(); 00645 } 00646 if (same.find(*j) == same.end()) { 00647 same[*j] = EdgeVector(); 00648 } 00649 if (find(same[*i].begin(), same[*i].end(), *j) == same[*i].end()) { 00650 same[*i].push_back(*j); 00651 } 00652 if (find(same[*j].begin(), same[*j].end(), *i) == same[*j].end()) { 00653 same[*j].push_back(*i); 00654 } 00655 } 00656 } 00657 } 00658 } 00659 00660 00661 EdgeVector 00662 NBNodeShapeComputer::computeUniqueDirectionList( 00663 const std::map<NBEdge*, EdgeVector > &same, 00664 std::map<NBEdge*, PositionVector> &geomsCCW, 00665 std::map<NBEdge*, PositionVector> &geomsCW, 00666 std::map<NBEdge*, NBEdge*> &ccwBoundary, 00667 std::map<NBEdge*, NBEdge*> &cwBoundary) { 00668 EdgeVector newAll = myNode.myAllEdges; 00669 EdgeVector::const_iterator j; 00670 EdgeVector::iterator i2; 00671 std::map<NBEdge*, EdgeVector >::iterator k; 00672 bool changed = true; 00673 while (changed) { 00674 changed = false; 00675 for (i2 = newAll.begin(); !changed && i2 != newAll.end();) { 00676 EdgeVector other; 00677 if (same.find(*i2) != same.end()) { 00678 other = same.find(*i2)->second; 00679 } 00680 for (j = other.begin(); j != other.end(); ++j) { 00681 EdgeVector::iterator k = find(newAll.begin(), newAll.end(), *j); 00682 if (k != newAll.end()) { 00683 if (myNode.hasIncoming(*i2)) { 00684 if (myNode.hasIncoming(*j)) {} else { 00685 geomsCW[*i2] = geomsCW[*j]; 00686 cwBoundary[*i2] = *j; 00687 computeSameEnd(geomsCW[*i2], geomsCCW[*i2]); 00688 } 00689 } else { 00690 if (myNode.hasIncoming(*j)) { 00691 ccwBoundary[*i2] = *j; 00692 geomsCCW[*i2] = geomsCCW[*j]; 00693 computeSameEnd(geomsCW[*i2], geomsCCW[*i2]); 00694 } else {} 00695 } 00696 newAll.erase(k); 00697 changed = true; 00698 } 00699 } 00700 if (!changed) { 00701 ++i2; 00702 } 00703 } 00704 } 00705 return newAll; 00706 } 00707 00708 00709 PositionVector 00710 NBNodeShapeComputer::computeNodeShapeByCrosses() { 00711 PositionVector ret; 00712 EdgeVector::const_iterator i; 00713 for (i = myNode.myAllEdges.begin(); i != myNode.myAllEdges.end(); i++) { 00714 // compute crossing with normal 00715 Line edgebound1 = (*i)->getCCWBoundaryLine(myNode, SUMO_const_halfLaneWidth).lineAt(0); 00716 Line edgebound2 = (*i)->getCWBoundaryLine(myNode, SUMO_const_halfLaneWidth).lineAt(0); 00717 Line cross(edgebound1); 00718 cross.rotateAtP1(PI / 2.); 00719 cross.add(myNode.getPosition() - cross.p1()); 00720 cross.extrapolateBy(500); 00721 edgebound1.extrapolateBy(500); 00722 edgebound2.extrapolateBy(500); 00723 if (cross.intersects(edgebound1)) { 00724 ret.push_back_noDoublePos(cross.intersectsAt(edgebound1)); 00725 } 00726 if (cross.intersects(edgebound2)) { 00727 ret.push_back_noDoublePos(cross.intersectsAt(edgebound2)); 00728 } 00729 } 00730 return ret; 00731 } 00732 00733 00734 00735 /****************************************************************************/