NBNodeShapeComputer Class Reference

#include <NBNodeShapeComputer.h>


Detailed Description

This class computes shapes of junctions.

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 NBNodemyNode
 The node to compute the geometry for.

Constructor & Destructor Documentation

NBNodeShapeComputer::NBNodeShapeComputer ( const NBNode node  ) 

Constructor.

Definition at line 49 of file NBNodeShapeComputer.cpp.

00050         : myNode(node) {}

NBNodeShapeComputer::~NBNodeShapeComputer (  ) 

Destructor.

Definition at line 53 of file NBNodeShapeComputer.cpp.

00053 {}


Member Function Documentation

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 }


Field Documentation

The node to compute the geometry for.

Definition at line 113 of file NBNodeShapeComputer.h.

Referenced by compute(), computeContinuationNodeShape(), computeNodeShapeByCrosses(), computeUniqueDirectionList(), and joinSameDirectionEdges().


The documentation for this class was generated from the following files:

Generated on Wed May 5 00:06:52 2010 for Sumo - Simulation of Urban MObility by  doxygen 1.5.6