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