SUMO - Simulation of Urban MObility

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