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