00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
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
00060
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
00074
00075
00076 bool geometryLike = myNode.isSimpleContinuation();
00077 if (geometryLike) {
00078
00079
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
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);
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
00199 if (myNode.myAllEdges.size()<2) {
00200 return Position2DVector();
00201 }
00202
00203 EdgeVector::const_iterator i;
00204
00205 std::map<NBEdge*, std::vector<NBEdge*> > same;
00206
00207 std::map<NBEdge*, Position2DVector> geomsCCW;
00208
00209 std::map<NBEdge*, Position2DVector> geomsCW;
00210
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
00218 joinSameDirectionEdges(same, geomsCCW, geomsCW);
00219
00220 std::vector<NBEdge*> newAll = computeUniqueDirectionList(same, geomsCCW, geomsCW, ccwBoundary, cwBoundary);
00221
00222 if (newAll.size()<2) {
00223 return Position2DVector();
00224 }
00225
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
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
00296 SUMOReal dist = geomsCCW[*i].nearest_position_on_line_to_point(p);
00297 if (dist<0) {
00298
00299
00300
00301
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
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
00315 distances[*i] = 100;
00316 myExtended[*i] = true;
00317 } else {
00318 if (!simpleContinuation) {
00319
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);
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);
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
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
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
00617 geomsCCW[*i] = (*i)->getCCWBoundaryLine(myNode, SUMO_const_halfLaneWidth);
00618 geomsCW[*i] = (*i)->getCWBoundaryLine(myNode, SUMO_const_halfLaneWidth);
00619
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
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