NBNodeShapeComputer.cpp

Go to the documentation of this file.
00001 /****************************************************************************/
00007 // This class computes shapes of junctions
00008 /****************************************************************************/
00009 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00010 // Copyright 2001-2010 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/Position2DVector.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 Position2DVector
00057 NBNodeShapeComputer::compute(bool leftHand) {
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 }
00114 
00115 
00116 void
00117 computeSameEnd(Position2DVector& l1, Position2DVector &l2) {
00118     Line2D sub(l1.lineAt(0).getPositionAtDistance(100), l1[1]);
00119     Line2D tmp(sub);
00120     tmp.rotateAtP1(PI/2);
00121     tmp.extrapolateBy(100);
00122     if (l1.intersects(tmp.p1(), tmp.p2())) {
00123         SUMOReal offset1 = l1.intersectsAtLengths(tmp)[0];
00124         Line2D tl1 = Line2D(
00125                          l1.lineAt(0).getPositionAtDistance(offset1),
00126                          l1[1]);
00127         tl1.extrapolateBy(100);
00128         l1.replaceAt(0, tl1.p1());
00129     }
00130     if (l2.intersects(tmp.p1(), tmp.p2())) {
00131         SUMOReal offset2 = l2.intersectsAtLengths(tmp)[0];
00132         Line2D tl2 = Line2D(
00133                          l2.lineAt(0).getPositionAtDistance(offset2),
00134                          l2[1]);
00135         tl2.extrapolateBy(100);
00136         l2.replaceAt(0, tl2.p1());
00137     }
00138 }
00139 
00140 
00141 void
00142 NBNodeShapeComputer::replaceLastChecking(Position2DVector &g, bool decenter,
00143         Position2DVector counter,
00144         size_t counterLanes, SUMOReal counterDist,
00145         int laneDiff) {
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 }
00166 
00167 
00168 void
00169 NBNodeShapeComputer::replaceFirstChecking(Position2DVector &g, bool decenter,
00170         Position2DVector counter,
00171         size_t counterLanes, SUMOReal counterDist,
00172         int laneDiff) {
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 }
00193 
00194 
00195 
00196 Position2DVector
00197 NBNodeShapeComputer::computeContinuationNodeShape(bool simpleContinuation) {
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 }
00607 
00608 
00609 
00610 void
00611 NBNodeShapeComputer::joinSameDirectionEdges(std::map<NBEdge*, std::vector<NBEdge*> > &same,
00612         std::map<NBEdge*, Position2DVector> &geomsCCW,
00613         std::map<NBEdge*, Position2DVector> &geomsCW) {
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 }
00663 
00664 
00665 std::vector<NBEdge*>
00666 NBNodeShapeComputer::computeUniqueDirectionList(
00667     const std::map<NBEdge*, std::vector<NBEdge*> > &same,
00668     std::map<NBEdge*, Position2DVector> &geomsCCW,
00669     std::map<NBEdge*, Position2DVector> &geomsCW,
00670     std::map<NBEdge*, NBEdge*> &ccwBoundary,
00671     std::map<NBEdge*, NBEdge*> &cwBoundary) {
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 }
00711 
00712 
00713 Position2DVector
00714 NBNodeShapeComputer::computeNodeShapeByCrosses() {
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 }
00745 
00746 
00747 
00748 /****************************************************************************/
00749 

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