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