SUMO - Simulation of Urban MObility
NBEdge.cpp
Go to the documentation of this file.
1 /****************************************************************************/
11 // Methods for the representation of a single edge
12 /****************************************************************************/
13 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
14 // Copyright (C) 2001-2016 DLR (http://www.dlr.de/) and contributors
15 /****************************************************************************/
16 //
17 // This file is part of SUMO.
18 // SUMO is free software: you can redistribute it and/or modify
19 // it under the terms of the GNU General Public License as published by
20 // the Free Software Foundation, either version 3 of the License, or
21 // (at your option) any later version.
22 //
23 /****************************************************************************/
24 
25 
26 // ===========================================================================
27 // included modules
28 // ===========================================================================
29 #ifdef _MSC_VER
30 #include <windows_config.h>
31 #else
32 #include <config.h>
33 #endif
34 
35 #include <vector>
36 #include <string>
37 #include <algorithm>
38 #include <cassert>
39 #include "NBEdgeCont.h"
40 #include "NBNode.h"
41 #include "NBNodeCont.h"
42 #include "NBContHelper.h"
43 #include "NBHelpers.h"
44 #include <cmath>
45 #include <iomanip>
46 #include "NBTypeCont.h"
47 #include <utils/geom/GeomHelper.h>
50 #include <utils/common/ToString.h>
52 #include <utils/common/StdDefs.h>
53 #include "NBEdge.h"
56 
57 #ifdef CHECK_MEMORY_LEAKS
58 #include <foreign/nvwa/debug_new.h>
59 #endif // CHECK_MEMORY_LEAKS
60 
61 #define DEBUGID "disabled"
62 
63 // ===========================================================================
64 // static members
65 // ===========================================================================
70 
74 
75 // ===========================================================================
76 // method definitions
77 // ===========================================================================
78 std::string
80  return id + "_" + toString(internalLaneIndex);
81 }
82 
83 /* -------------------------------------------------------------------------
84  * NBEdge::ToEdgeConnectionsAdder-methods
85  * ----------------------------------------------------------------------- */
86 void
87 NBEdge::ToEdgeConnectionsAdder::execute(const unsigned int lane, const unsigned int virtEdge) {
88  // check
89  assert(myTransitions.size() > virtEdge);
90  // get the approached edge
91  NBEdge* succEdge = myTransitions[virtEdge];
92  std::vector<unsigned int> lanes;
93 
94  // check whether the currently regarded, approached edge has already
95  // a connection starting at the edge which is currently being build
96  std::map<NBEdge*, std::vector<unsigned int> >::iterator i = myConnections.find(succEdge);
97  if (i != myConnections.end()) {
98  // if there were already lanes assigned, get them
99  lanes = (*i).second;
100  }
101 
102  // check whether the current lane was already used to connect the currently
103  // regarded approached edge
104  std::vector<unsigned int>::iterator j = find(lanes.begin(), lanes.end(), lane);
105  if (j == lanes.end()) {
106  // if not, add it to the list
107  lanes.push_back(lane);
108  }
109  // set information about connecting lanes
110  myConnections[succEdge] = lanes;
111 }
112 
113 
114 
115 /* -------------------------------------------------------------------------
116  * NBEdge::MainDirections-methods
117  * ----------------------------------------------------------------------- */
119  NBEdge* parent, NBNode* to) {
120  if (outgoing.size() == 0) {
121  return;
122  }
123  // check whether the right turn has a higher priority
124  assert(outgoing.size() > 0);
125  if (outgoing[0]->getJunctionPriority(to) == 1) {
126  myDirs.push_back(MainDirections::DIR_RIGHTMOST);
127  }
128  // check whether the left turn has a higher priority
129  if (outgoing.back()->getJunctionPriority(to) == 1) {
130  // ok, the left turn belongs to the higher priorised edges on the junction
131  // let's check, whether it has also a higher priority (lane number/speed)
132  // than the current
133  EdgeVector tmp(outgoing);
134  sort(tmp.begin(), tmp.end(), NBContHelper::edge_similar_direction_sorter(parent));
135  if (outgoing.back()->getPriority() > tmp[0]->getPriority()) {
136  myDirs.push_back(MainDirections::DIR_LEFTMOST);
137  } else {
138  if (outgoing.back()->getNumLanes() > tmp[0]->getNumLanes()) {
139  myDirs.push_back(MainDirections::DIR_LEFTMOST);
140  }
141  }
142  }
143  // check whether the forward direction has a higher priority
144  // try to get the forward direction
145  EdgeVector tmp(outgoing);
146  sort(tmp.begin(), tmp.end(), NBContHelper::edge_similar_direction_sorter(parent));
147  NBEdge* edge = *(tmp.begin());
148  // check whether it has a higher priority and is going straight
149  if (edge->getJunctionPriority(to) == 1 && to->getDirection(parent, edge) == LINKDIR_STRAIGHT) {
150  myDirs.push_back(MainDirections::DIR_FORWARD);
151  }
152 }
153 
154 
156 
157 
158 bool
160  return myDirs.empty();
161 }
162 
163 
164 bool
166  return find(myDirs.begin(), myDirs.end(), d) != myDirs.end();
167 }
168 
169 
170 /* -------------------------------------------------------------------------
171  * NBEdge::connections_relative_edgelane_sorter-methods
172  * ----------------------------------------------------------------------- */
173 int
175  if (c1.toEdge != c2.toEdge) {
177  }
178  return c1.toLane < c2.toLane;
179 }
180 
181 
182 /* -------------------------------------------------------------------------
183  * NBEdge-methods
184  * ----------------------------------------------------------------------- */
185 NBEdge::NBEdge(const std::string& id, NBNode* from, NBNode* to,
186  std::string type, SUMOReal speed, unsigned int nolanes,
187  int priority, SUMOReal laneWidth, SUMOReal offset,
188  const std::string& streetName,
189  LaneSpreadFunction spread) :
190  Named(StringUtils::convertUmlaute(id)),
191  myStep(INIT),
192  myType(StringUtils::convertUmlaute(type)),
193  myFrom(from), myTo(to),
195  myPriority(priority), mySpeed(speed),
199  myLaneSpreadFunction(spread), myEndOffset(offset), myLaneWidth(laneWidth),
202  myStreetName(streetName),
204  init(nolanes, false, "");
205 }
206 
207 
208 NBEdge::NBEdge(const std::string& id, NBNode* from, NBNode* to,
209  std::string type, SUMOReal speed, unsigned int nolanes,
210  int priority, SUMOReal laneWidth, SUMOReal offset,
211  PositionVector geom,
212  const std::string& streetName,
213  const std::string& origID,
214  LaneSpreadFunction spread, bool tryIgnoreNodePositions) :
215  Named(StringUtils::convertUmlaute(id)),
216  myStep(INIT),
217  myType(StringUtils::convertUmlaute(type)),
218  myFrom(from), myTo(to),
220  myPriority(priority), mySpeed(speed),
224  myGeom(geom), myLaneSpreadFunction(spread), myEndOffset(offset), myLaneWidth(laneWidth),
227  myStreetName(streetName),
229  init(nolanes, tryIgnoreNodePositions, origID);
230 }
231 
232 
233 NBEdge::NBEdge(const std::string& id, NBNode* from, NBNode* to, NBEdge* tpl, const PositionVector& geom, int numLanes) :
234  Named(StringUtils::convertUmlaute(id)),
235  myStep(INIT),
236  myType(tpl->getTypeID()),
237  myFrom(from), myTo(to),
239  myPriority(tpl->getPriority()), mySpeed(tpl->getSpeed()),
243  myGeom(geom),
245  myEndOffset(tpl->getEndOffset()),
246  myLaneWidth(tpl->getLaneWidth()),
248  myAmInnerEdge(false),
250  myStreetName(tpl->getStreetName()),
252  init(numLanes > 0 ? numLanes : tpl->getNumLanes(), myGeom.size() > 0, "");
253  for (unsigned int i = 0; i < getNumLanes(); i++) {
254  const unsigned int tplIndex = MIN2(i, tpl->getNumLanes() - 1);
255  setSpeed(i, tpl->getLaneSpeed(tplIndex));
256  setPermissions(tpl->getPermissions(tplIndex), i);
257  setLaneWidth(i, tpl->myLanes[tplIndex].width);
258  if (to == tpl->myTo) {
259  setEndOffset(i, tpl->myLanes[tplIndex].endOffset);
260  }
261  }
262 }
263 
264 
265 void
266 NBEdge::reinit(NBNode* from, NBNode* to, const std::string& type,
267  SUMOReal speed, unsigned int nolanes, int priority,
268  PositionVector geom, SUMOReal laneWidth, SUMOReal offset,
269  const std::string& streetName,
270  LaneSpreadFunction spread,
271  bool tryIgnoreNodePositions) {
272  if (myFrom != from) {
273  myFrom->removeEdge(this, false);
274  }
275  if (myTo != to) {
276  myTo->removeEdge(this, false);
277  }
279  myFrom = from;
280  myTo = to;
281  myPriority = priority;
282  //?myTurnDestination(0),
283  //?myFromJunctionPriority(-1), myToJunctionPriority(-1),
284  myGeom = geom;
285  myLaneSpreadFunction = spread;
287  myStreetName = streetName;
288  //?, myAmTurningWithAngle(0), myAmTurningOf(0),
289  //?myAmInnerEdge(false), myAmMacroscopicConnector(false)
290 
291  // preserve lane-specific settings (geometry must be recomputed)
292  // if new lanes are added they copy the values from the leftmost lane (if specified)
293  const std::vector<Lane> oldLanes = myLanes;
294  init(nolanes, tryIgnoreNodePositions, oldLanes.empty() ? "" : oldLanes[0].origID);
295  for (int i = 0; i < (int)nolanes; ++i) {
296  PositionVector newShape = myLanes[i].shape;
297  myLanes[i] = oldLanes[MIN2(i, (int)oldLanes.size() - 1)];
298  myLanes[i].shape = newShape;
299  }
300  // however, if the new edge defaults are explicityly given, they override the old settings
301  if (offset != UNSPECIFIED_OFFSET) {
302  setEndOffset(-1, offset);
303  }
304  if (laneWidth != UNSPECIFIED_WIDTH) {
305  setLaneWidth(-1, laneWidth);
306  }
307  if (speed != UNSPECIFIED_SPEED) {
308  setSpeed(-1, speed);
309  }
310 }
311 
312 
313 void
315  // connections may still be valid
316  if (from == 0 || to == 0) {
317  throw ProcessError("At least one of edge's '" + myID + "' nodes is not known.");
318  }
319  if (myFrom != from) {
320  myFrom->removeEdge(this, false);
321  myFrom = from;
322  myFrom->addOutgoingEdge(this);
323  }
324  if (myTo != to) {
325  myTo->removeEdge(this, false);
326  myTo = to;
327  myTo->addIncomingEdge(this);
328  }
329  computeAngle();
330 }
331 
332 
333 void
334 NBEdge::init(unsigned int noLanes, bool tryIgnoreNodePositions, const std::string& origID) {
335  if (noLanes == 0) {
336  throw ProcessError("Edge '" + myID + "' needs at least one lane.");
337  }
338  if (myFrom == 0 || myTo == 0) {
339  throw ProcessError("At least one of edge's '" + myID + "' nodes is not known.");
340  }
341  // revisit geometry
342  // should have at least two points at the end...
343  // and in dome cases, the node positions must be added
345  if (!tryIgnoreNodePositions || myGeom.size() < 2) {
346  if (myGeom.size() == 0) {
347  myGeom.push_back(myFrom->getPosition());
348  myGeom.push_back(myTo->getPosition());
349  } else {
352  }
353  }
354  if (myGeom.size() < 2) {
355  myGeom.clear();
356  myGeom.push_back(myFrom->getPosition());
357  myGeom.push_back(myTo->getPosition());
358  }
359  if (myGeom.size() == 2 && myGeom[0] == myGeom[1]) {
360  WRITE_ERROR("Edge's '" + myID + "' from- and to-node are at the same position.");
362  }
363  //
364  myFrom->addOutgoingEdge(this);
365  myTo->addIncomingEdge(this);
366  // prepare container
368  assert(myGeom.size() >= 2);
369  if (myLanes.size() > noLanes) {
370  // remove connections targeting the removed lanes
371  const EdgeVector& incoming = myFrom->getIncomingEdges();
372  for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
373  for (int lane = noLanes; lane < (int)myLanes.size(); ++lane) {
374  (*i)->removeFromConnections(this, -1, lane);
375  }
376  }
377  }
378  myLanes.clear();
379  for (unsigned int i = 0; i < noLanes; i++) {
380  myLanes.push_back(Lane(this, origID));
381  }
383  computeAngle();
384 }
385 
386 
388 
389 
390 // ----------- Applying offset
391 void
393  myGeom.add(xoff, yoff, 0);
394  for (unsigned int i = 0; i < myLanes.size(); i++) {
395  myLanes[i].shape.add(xoff, yoff, 0);
396  }
397  computeAngle(); // update angles because they are numerically sensitive (especially where based on centroids)
398 }
399 
400 
401 void
403  myGeom.mirrorX();
404  for (unsigned int i = 0; i < myLanes.size(); i++) {
405  myLanes[i].shape.mirrorX();
406  }
407  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
408  (*i).shape.mirrorX();
409  (*i).viaShape.mirrorX();
410  }
411  computeAngle(); // update angles because they are numerically sensitive (especially where based on centroids)
412 }
413 
414 
415 // ----------- Edge geometry access and computation
416 const PositionVector
418  return myGeom.getSubpartByIndex(1, (int)myGeom.size() - 2);
419 }
420 
421 
422 bool
424  return myGeom.size() == 2 && hasDefaultGeometryEndpoints();
425 }
426 
427 
428 bool
430  return myGeom.front() == myFrom->getPosition() &&
431  myGeom.back() == myTo->getPosition();
432 }
433 
434 
435 void
436 NBEdge::setGeometry(const PositionVector& s, bool inner) {
437  Position begin = myGeom.front(); // may differ from node position
438  Position end = myGeom.back(); // may differ from node position
439  myGeom = s;
440  if (inner) {
441  myGeom.insert(myGeom.begin(), begin);
442  myGeom.push_back(end);
443  }
445  computeAngle();
446 }
447 
448 
451  PositionVector shape = old;
452  shape = startShapeAt(shape, myFrom);
453  if (shape.size() >= 2) {
454  shape = startShapeAt(shape.reverse(), myTo).reverse();
455  }
456  // sanity checks
457  if (shape.length() < POSITION_EPS) {
458  if (old.length() < 2 * POSITION_EPS) {
459  shape = old;
460  } else {
461  const SUMOReal midpoint = old.length() / 2;
462  // EPS*2 because otherwhise shape has only a single point
463  shape = old.getSubpart(midpoint - POSITION_EPS, midpoint + POSITION_EPS);
464  assert(shape.size() >= 2);
465  assert(shape.length() > 0);
466  }
467  } else {
468  // @note If the node shapes are overlapping we may get a shape which goes in the wrong direction
469  // in this case the result shape should shortened
470  if (DEG2RAD(135) < fabs(GeomHelper::angleDiff(shape.beginEndAngle(), old.beginEndAngle()))) {
471  shape = shape.reverse();
472  shape = shape.getSubpart(0, 2 * POSITION_EPS); // *2 because otherwhise shape has only a single point
473  }
474  }
475  return shape;
476 }
477 
478 
479 void
481  for (unsigned int i = 0; i < myLanes.size(); i++) {
482  myLanes[i].shape = cutAtIntersection(myLanes[i].shape);
483  }
484  // recompute edge's length as the average of lane lenghts
485  SUMOReal avgLength = 0;
486  for (unsigned int i = 0; i < myLanes.size(); i++) {
487  assert(myLanes[i].shape.length() > 0);
488  avgLength += myLanes[i].shape.length();
489  }
490  myLength = avgLength / (SUMOReal) myLanes.size();
491  computeAngle(); // update angles using the finalized node and lane shapes
492 }
493 
494 
496 NBEdge::startShapeAt(const PositionVector& laneShape, const NBNode* startNode) const {
497  const PositionVector& nodeShape = startNode->getShape();
498  PositionVector lb(laneShape.begin(), laneShape.begin() + 2);
499  // this doesn't look reasonable @todo use lb.extrapolateFirstBy(100.0);
500  lb.extrapolate(100.0);
501  if (nodeShape.intersects(laneShape)) {
502  // shape intersects directly
503  std::vector<SUMOReal> pbv = laneShape.intersectsAtLengths2D(nodeShape);
504  assert(pbv.size() > 0);
505  // ensure that the subpart has at least two points
507  if (pb < 0) {
508  return laneShape;
509  }
510  PositionVector ns = laneShape.getSubpart2D(pb, laneShape.length2D());
511  //PositionVector ns = pb < (laneShape.length() - POSITION_EPS) ? laneShape.getSubpart2D(pb, laneShape.length()) : laneShape;
512  ns[0].set(ns[0].x(), ns[0].y(), startNode->getPosition().z());
513  assert(ns.size() >= 2);
514  return ns;
515  } else if (nodeShape.intersects(lb)) {
516  // extension of first segment intersects
517  std::vector<SUMOReal> pbv = lb.intersectsAtLengths2D(nodeShape);
518  assert(pbv.size() > 0);
520  assert(pb >= 0);
521  PositionVector result = laneShape.getSubpartByIndex(1, (int)laneShape.size() - 1);
522  Position np = PositionVector::positionAtOffset2D(lb[0], lb[1], pb);
523  result.push_front_noDoublePos(Position(np.x(), np.y(), startNode->getPosition().z()));
524  return result;
525  //if (result.size() >= 2) {
526  // return result;
527  //} else {
528  // WRITE_WARNING(error + " (resulting shape is too short)");
529  // return laneShape;
530  //}
531  } else {
532  // could not find proper intersection. Probably the edge is very short
533  // and lies within nodeShape
534  // @todo enable warning WRITE_WARNING(error + " (laneShape lies within nodeShape)");
535  return laneShape;
536  }
537 }
538 
539 
540 const PositionVector&
541 NBEdge::getLaneShape(unsigned int i) const {
542  return myLanes[i].shape;
543 }
544 
545 
546 void
548  myLaneSpreadFunction = spread;
549 }
550 
551 
552 void
553 NBEdge::addGeometryPoint(int index, const Position& p) {
554  if (index >= 0) {
555  myGeom.insert(myGeom.begin() + index, p);
556  } else {
557  myGeom.insert(myGeom.end() + index, p);
558  }
559 }
560 
561 
562 bool
564  // check whether there any splits to perform
565  if (myGeom.size() < 3) {
566  return false;
567  }
568  // ok, split
569  NBNode* newFrom = myFrom;
570  NBNode* myLastNode = myTo;
571  NBNode* newTo = 0;
572  NBEdge* currentEdge = this;
573  for (int i = 1; i < (int) myGeom.size() - 1; i++) {
574  // build the node first
575  if (i != (int)myGeom.size() - 2) {
576  std::string nodename = myID + "_in_between#" + toString(i);
577  if (!nc.insert(nodename, myGeom[i])) {
578  throw ProcessError("Error on adding in-between node '" + nodename + "'.");
579  }
580  newTo = nc.retrieve(nodename);
581  } else {
582  newTo = myLastNode;
583  }
584  if (i == 1) {
585  currentEdge->myTo->removeEdge(this);
586  currentEdge->myTo = newTo;
587  newTo->addIncomingEdge(currentEdge);
588  } else {
589  std::string edgename = myID + "[" + toString(i - 1) + "]";
590  // @bug lane-specific width, speed, overall offset and restrictions are ignored
591  currentEdge = new NBEdge(edgename, newFrom, newTo, myType, mySpeed, (unsigned int) myLanes.size(),
593  if (!ec.insert(currentEdge, true)) {
594  throw ProcessError("Error on adding splitted edge '" + edgename + "'.");
595  }
596  }
597  newFrom = newTo;
598  }
599  myGeom.clear();
600  myGeom.push_back(myFrom->getPosition());
601  myGeom.push_back(myTo->getPosition());
602  myStep = INIT;
603  return true;
604 }
605 
606 
607 void
609  myGeom.removeDoublePoints(minDist, true);
610 }
611 
612 
613 void
614 NBEdge::checkGeometry(const SUMOReal maxAngle, const SUMOReal minRadius, bool fix) {
615  if (myGeom.size() < 3) {
616  return;
617  }
618  //std::cout << "checking geometry of " << getID() << " geometry = " << toString(myGeom) << "\n";
619  std::vector<SUMOReal> angles; // absolute segment angles
620  //std::cout << " absolute angles:";
621  for (int i = 0; i < (int)myGeom.size() - 1; ++i) {
622  angles.push_back(myGeom.angleAt2D(i));
623  //std::cout << " " << angles.back();
624  }
625  //std::cout << "\n relative angles: ";
626  for (int i = 0; i < (int)angles.size() - 1; ++i) {
627  const SUMOReal relAngle = fabs(GeomHelper::angleDiff(angles[i], angles[i + 1]));
628  //std::cout << relAngle << " ";
629  if (maxAngle > 0 && relAngle > maxAngle) {
630  WRITE_WARNING("Found angle of " + toString(RAD2DEG(relAngle)) + " degrees at edge '" + getID() + "', segment " + toString(i));
631  }
632  if (relAngle < DEG2RAD(1)) {
633  continue;
634  }
635  if (i == 0 || i == (int)angles.size() - 2) {
636  const bool start = i == 0;
637  const SUMOReal dist = (start ? myGeom[0].distanceTo2D(myGeom[1]) : myGeom[-2].distanceTo2D(myGeom[-1]));
638  const SUMOReal r = tan(0.5 * (M_PI - relAngle)) * dist;
639  //std::cout << (start ? " start" : " end") << " length=" << dist << " radius=" << r << " ";
640  if (minRadius > 0 && r < minRadius) {
641  if (fix) {
642  WRITE_MESSAGE("Removing sharp turn with radius " + toString(r) + " at the " +
643  (start ? "start" : "end") + " of edge '" + getID() + "'.");
644  myGeom.erase(myGeom.begin() + (start ? 1 : i + 1));
645  checkGeometry(maxAngle, minRadius, fix);
646  return;
647  } else {
648  WRITE_WARNING("Found sharp turn with radius " + toString(r) + " at the " +
649  (start ? "start" : "end") + " of edge '" + getID() + "'.");
650  }
651  }
652  }
653  }
654  //std::cout << "\n";
655 }
656 
657 
658 // ----------- Setting and getting connections
659 bool
662  return true;
663  }
664  // check whether the node was merged and now a connection between
665  // not matching edges is tried to be added
666  // This happens f.e. within the ptv VISSIM-example "Beijing"
667  if (dest != 0 && myTo != dest->myFrom) {
668  return false;
669  }
670  if (dest == 0) {
672  myConnections.push_back(Connection(-1, dest, -1));
673  } else if (find_if(myConnections.begin(), myConnections.end(), connections_toedge_finder(dest)) == myConnections.end()) {
674  myConnections.push_back(Connection(-1, dest, -1));
675  }
676  if (myStep < EDGE2EDGES) {
677  myStep = EDGE2EDGES;
678  }
679  return true;
680 }
681 
682 
683 bool
684 NBEdge::addLane2LaneConnection(unsigned int from, NBEdge* dest,
685  unsigned int toLane, Lane2LaneInfoType type,
686  bool mayUseSameDestination,
687  bool mayDefinitelyPass,
688  bool keepClear,
689  SUMOReal contPos) {
691  return true;
692  }
693  // check whether the node was merged and now a connection between
694  // not matching edges is tried to be added
695  // This happens f.e. within the ptv VISSIM-example "Beijing"
696  if (myTo != dest->myFrom) {
697  return false;
698  }
699  if (!addEdge2EdgeConnection(dest)) {
700  return false;
701  }
702  return setConnection(from, dest, toLane, type, mayUseSameDestination, mayDefinitelyPass, keepClear, contPos);
703 }
704 
705 
706 bool
707 NBEdge::addLane2LaneConnections(unsigned int fromLane,
708  NBEdge* dest, unsigned int toLane,
709  unsigned int no, Lane2LaneInfoType type,
710  bool invalidatePrevious,
711  bool mayDefinitelyPass) {
712  if (invalidatePrevious) {
713  invalidateConnections(true);
714  }
715  bool ok = true;
716  for (unsigned int i = 0; i < no && ok; i++) {
717  ok &= addLane2LaneConnection(fromLane + i, dest, toLane + i, type, false, mayDefinitelyPass);
718  }
719  return ok;
720 }
721 
722 
723 bool
724 NBEdge::setConnection(unsigned int lane, NBEdge* destEdge,
725  unsigned int destLane, Lane2LaneInfoType type,
726  bool mayUseSameDestination,
727  bool mayDefinitelyPass,
728  bool keepClear,
729  SUMOReal contPos) {
731  return false;
732  }
733  // some kind of a misbehaviour which may occure when the junction's outgoing
734  // edge priorities were not properly computed, what may happen due to
735  // an incomplete or not proper input
736  // what happens is that under some circumstances a single lane may set to
737  // be approached more than once by the one of our lanes.
738  // This must not be!
739  // we test whether it is the case and do nothing if so - the connection
740  // will be refused
741  //
742  if (!mayUseSameDestination && hasConnectionTo(destEdge, destLane)) {
743  return false;
744  }
745  if (find_if(myConnections.begin(), myConnections.end(), connections_finder(lane, destEdge, destLane)) != myConnections.end()) {
746  return true;
747  }
748  if (myLanes.size() <= lane || destEdge->getNumLanes() <= destLane) {
749  // problem might be corrigible in post-processing
750  WRITE_WARNING("Could not set connection from '" + getLaneIDInsecure(lane) + "' to '" + destEdge->getLaneIDInsecure(destLane) + "'.");
751  return false;
752  }
753  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end();) {
754  if ((*i).toEdge == destEdge && ((*i).fromLane == -1 || (*i).toLane == -1)) {
755  i = myConnections.erase(i);
756  } else {
757  ++i;
758  }
759  }
760  myConnections.push_back(Connection(lane, destEdge, destLane));
761  if (mayDefinitelyPass) {
762  myConnections.back().mayDefinitelyPass = true;
763  }
764  myConnections.back().keepClear = keepClear;
765  myConnections.back().contPos = contPos;
766  if (type == L2L_USER) {
768  } else {
769  // check whether we have to take another look at it later
770  if (type == L2L_COMPUTED) {
771  // yes, the connection was set using an algorithm which requires a recheck
773  } else {
774  // ok, let's only not recheck it if we did no add something that has to be recheked
775  if (myStep != LANES2LANES_RECHECK) {
777  }
778  }
779  }
780  return true;
781 }
782 
783 
784 std::vector<NBEdge::Connection>
785 NBEdge::getConnectionsFromLane(unsigned int lane) const {
786  std::vector<NBEdge::Connection> ret;
787  for (std::vector<Connection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
788  if ((*i).fromLane == static_cast<int>(lane)) {
789  ret.push_back(*i);
790  }
791  }
792  return ret;
793 }
794 
795 
797 NBEdge::getConnection(int fromLane, const NBEdge* to, int toLane) const {
798  for (std::vector<Connection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
799  if (
800  (*i).fromLane == fromLane
801  && (*i).toEdge == to
802  && (*i).toLane == toLane) {
803  return *i;
804  }
805  }
806  throw ProcessError("Connection from " + getID() + "_" + toString(fromLane)
807  + " to " + to->getID() + "_" + toString(toLane) + " not found");
808 }
809 
810 
811 bool
812 NBEdge::hasConnectionTo(NBEdge* destEdge, unsigned int destLane, int fromLane) const {
813  return destEdge != 0 && find_if(myConnections.begin(), myConnections.end(), connections_toedgelane_finder(destEdge, destLane, fromLane)) != myConnections.end();
814 }
815 
816 
817 bool
819  if (e == myTurnDestination) {
820  return true;
821  }
822  return
823  find_if(myConnections.begin(), myConnections.end(), connections_toedge_finder(e))
824  !=
825  myConnections.end();
826 
827 }
828 
829 
830 const EdgeVector*
832  // check whether connections exist and if not, use edges from the node
833  EdgeVector outgoing;
834  if (myConnections.size() == 0) {
835  outgoing = myTo->getOutgoingEdges();
836  } else {
837  for (std::vector<Connection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
838  if (find(outgoing.begin(), outgoing.end(), (*i).toEdge) == outgoing.end()) {
839  outgoing.push_back((*i).toEdge);
840  }
841  }
842  }
843  for (std::vector<Connection>::iterator it = myConnectionsToDelete.begin(); it != myConnectionsToDelete.end(); ++it) {
844  if (it->fromLane < 0 && it->toLane < 0) {
845  // found an edge that shall not be connected
846  EdgeVector::iterator forbidden = find(outgoing.begin(), outgoing.end(), it->toEdge);
847  if (forbidden != outgoing.end()) {
848  outgoing.erase(forbidden);
849  }
850  }
851  }
852  // allocate the sorted container
853  unsigned int size = (unsigned int) outgoing.size();
854  EdgeVector* edges = new EdgeVector();
855  edges->reserve(size);
856  for (EdgeVector::const_iterator i = outgoing.begin(); i != outgoing.end(); i++) {
857  NBEdge* outedge = *i;
858  if (outedge != 0 && outedge != myTurnDestination) {
859  edges->push_back(outedge);
860  }
861  }
862  sort(edges->begin(), edges->end(), NBContHelper::relative_outgoing_edge_sorter(this));
863  return edges;
864 }
865 
866 
869  EdgeVector ret;
870  for (std::vector<Connection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
871  if (find(ret.begin(), ret.end(), (*i).toEdge) == ret.end()) {
872  ret.push_back((*i).toEdge);
873  }
874  }
875  return ret;
876 }
877 
878 
879 std::vector<int>
880 NBEdge::getConnectionLanes(NBEdge* currentOutgoing) const {
881  std::vector<int> ret;
882  if (currentOutgoing != myTurnDestination) {
883  for (std::vector<Connection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
884  if ((*i).toEdge == currentOutgoing) {
885  ret.push_back((*i).fromLane);
886  }
887  }
888  }
889  return ret;
890 }
891 
892 
893 void
896 }
897 
898 
899 void
901  sort(myConnections.begin(), myConnections.end(), connections_sorter);
902 }
903 
904 
905 void
907  EdgeVector connected = getConnectedEdges();
908  for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
909  NBEdge* inc = *i;
910  // We have to do this
911  inc->myStep = EDGE2EDGES;
912  // add all connections
913  for (EdgeVector::iterator j = connected.begin(); j != connected.end(); j++) {
914  inc->addEdge2EdgeConnection(*j);
915  }
916  inc->removeFromConnections(this);
917  }
918 }
919 
920 
921 void
922 NBEdge::removeFromConnections(NBEdge* toEdge, int fromLane, int toLane, bool tryLater) {
923  // remove from "myConnections"
924  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end();) {
925  Connection& c = *i;
926  if (c.toEdge == toEdge
927  && (fromLane < 0 || c.fromLane == fromLane)
928  && (toLane < 0 || c.toLane == toLane)) {
929  i = myConnections.erase(i);
930  tryLater = false;
931  } else {
932  ++i;
933  }
934  }
935  // check whether it was the turn destination
936  if (myTurnDestination == toEdge && fromLane < 0) {
937  myTurnDestination = 0;
938  }
939  if (myPossibleTurnDestination == toEdge && fromLane < 0) {
941  }
942  if (tryLater) {
943  myConnectionsToDelete.push_back(Connection(fromLane, toEdge, toLane));
944  }
945 }
946 
947 
948 void
949 NBEdge::invalidateConnections(bool reallowSetting) {
950  myTurnDestination = 0;
951  myConnections.clear();
952  if (reallowSetting) {
953  myStep = INIT;
954  } else {
956  }
957 }
958 
959 
960 void
961 NBEdge::replaceInConnections(NBEdge* which, NBEdge* by, unsigned int laneOff) {
962  // replace in "_connectedEdges"
963  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
964  if ((*i).toEdge == which) {
965  (*i).toEdge = by;
966  (*i).toLane += laneOff;
967  }
968  }
969  // check whether it was the turn destination
970  if (myTurnDestination == which) {
971  myTurnDestination = by;
972  }
973 }
974 
975 void
976 NBEdge::replaceInConnections(NBEdge* which, const std::vector<NBEdge::Connection>& origConns) {
977  std::map<int, int> laneMap;
978  int minLane = -1;
979  int maxLane = -1;
980  // get lanes used to approach the edge to remap
981  bool wasConnected = false;
982  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
983  if ((*i).toEdge != which) {
984  continue;
985  }
986  wasConnected = true;
987  if ((*i).fromLane != -1) {
988  int fromLane = (*i).fromLane;
989  laneMap[(*i).toLane] = fromLane;
990  if (minLane == -1 || minLane > fromLane) {
991  minLane = fromLane;
992  }
993  if (maxLane == -1 || maxLane < fromLane) {
994  maxLane = fromLane;
995  }
996  }
997  }
998  if (!wasConnected) {
999  return;
1000  }
1001  // remove the remapped edge from connections
1002  removeFromConnections(which);
1003  // add new connections
1004  std::vector<NBEdge::Connection> conns = origConns;
1005  for (std::vector<NBEdge::Connection>::iterator i = conns.begin(); i != conns.end(); ++i) {
1006  if ((*i).toEdge == which) {
1007  continue;
1008  }
1009  int fromLane = (*i).fromLane;
1010  int toUse = -1;
1011  if (laneMap.find(fromLane) == laneMap.end()) {
1012  if (fromLane >= 0 && fromLane <= minLane) {
1013  toUse = minLane;
1014  }
1015  if (fromLane >= 0 && fromLane >= maxLane) {
1016  toUse = maxLane;
1017  }
1018  } else {
1019  toUse = laneMap[fromLane];
1020  }
1021  if (toUse == -1) {
1022  toUse = 0;
1023  }
1024  setConnection(toUse, (*i).toEdge, (*i).toLane, L2L_COMPUTED, false, (*i).mayDefinitelyPass);
1025  }
1026 }
1027 
1028 
1029 void
1031  myStep = src->myStep;
1033 }
1034 
1035 
1036 bool
1037 NBEdge::canMoveConnection(const Connection& con, unsigned int newFromLane) const {
1038  // only allow using newFromLane if at least 1 vClass is permitted to use
1039  // this connection. If the connection shall be moved to a sidewalk, only create the connection if there is no walking area
1040  const SVCPermissions common = (getPermissions(newFromLane) & con.toEdge->getPermissions(con.toLane));
1041  return (common > 0 && common != SVC_PEDESTRIAN);
1042 }
1043 
1044 
1045 void
1046 NBEdge::moveConnectionToLeft(unsigned int lane) {
1047  unsigned int index = 0;
1048  for (unsigned int i = 0; i < myConnections.size(); ++i) {
1049  if (myConnections[i].fromLane == (int)(lane) && canMoveConnection(myConnections[i], lane + 1)) {
1050  index = i;
1051  }
1052  }
1053  std::vector<Connection>::iterator i = myConnections.begin() + index;
1054  Connection c = *i;
1055  myConnections.erase(i);
1056  setConnection(lane + 1, c.toEdge, c.toLane, L2L_VALIDATED, false);
1057 }
1058 
1059 
1060 void
1061 NBEdge::moveConnectionToRight(unsigned int lane) {
1062  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
1063  if ((*i).fromLane == (int)lane && canMoveConnection(*i, lane - 1)) {
1064  Connection c = *i;
1065  i = myConnections.erase(i);
1066  setConnection(lane - 1, c.toEdge, c.toLane, L2L_VALIDATED, false);
1067  return;
1068  }
1069  }
1070 }
1071 
1072 
1073 void
1074 NBEdge::buildInnerEdges(const NBNode& n, unsigned int noInternalNoSplits, unsigned int& linkIndex, unsigned int& splitIndex) {
1075  const int numPoints = OptionsCont::getOptions().getInt("junctions.internal-link-detail");
1076  std::string innerID = ":" + n.getID();
1077  NBEdge* toEdge = 0;
1078  unsigned int edgeIndex = linkIndex;
1079  unsigned int internalLaneIndex = 0;
1080  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
1081  Connection& con = *i;
1082  con.haveVia = false; // reset first since this may be called multiple times
1083  if (con.toEdge == 0) {
1084  continue;
1085  }
1086  if (con.toEdge != toEdge) {
1087  // skip indices to keep some correspondence between edge ids and link indices:
1088  // internalEdgeIndex + internalLaneIndex = linkIndex
1089  edgeIndex = linkIndex;
1090  toEdge = (*i).toEdge;
1091  internalLaneIndex = 0;
1092  }
1093  PositionVector shape = n.computeInternalLaneShape(this, con, numPoints);
1094  std::vector<unsigned int> foeInternalLinks;
1095 
1096  LinkDirection dir = n.getDirection(this, con.toEdge);
1097  const bool isRightTurn = (dir == LINKDIR_RIGHT || dir == LINKDIR_PARTRIGHT);
1098  const bool isTurn = (isRightTurn || dir == LINKDIR_LEFT || dir == LINKDIR_PARTLEFT);
1099  if (dir != LINKDIR_STRAIGHT && shape.length() < POSITION_EPS) {
1100  WRITE_WARNING("Connection '" + getID() + "_" + toString(con.fromLane) + "->" + con.toEdge->getID() + "_" + toString(con.toLane) + "' is only " + toString(shape.length()) + " short.");
1101  }
1102 
1103  // crossingPosition, list of foe link indices
1104  std::pair<SUMOReal, std::vector<unsigned int> > crossingPositions(-1, std::vector<unsigned int>());
1105  std::set<std::string> tmpFoeIncomingLanes;
1106  switch (dir) {
1107  case LINKDIR_RIGHT:
1108  case LINKDIR_PARTRIGHT:
1109  case LINKDIR_LEFT:
1110  case LINKDIR_PARTLEFT:
1111  case LINKDIR_TURN: {
1112  unsigned int index = 0;
1113  const std::vector<NBEdge*>& incoming = n.getIncomingEdges();
1114  for (EdgeVector::const_iterator i2 = incoming.begin(); i2 != incoming.end(); ++i2) {
1115  const std::vector<Connection>& elv = (*i2)->getConnections();
1116  for (std::vector<NBEdge::Connection>::const_iterator k2 = elv.begin(); k2 != elv.end(); k2++) {
1117  if ((*k2).toEdge == 0) {
1118  continue;
1119  }
1120  bool needsCont = n.needsCont(this, *i2, con, *k2);
1121  // compute the crossing point
1122  if (needsCont) {
1123  crossingPositions.second.push_back(index);
1124  const PositionVector otherShape = n.computeInternalLaneShape(*i2, *k2, numPoints);
1125  // vehicles are typically less wide than the lane
1126  // they drive on but but bicycle lanes should be kept clear for their whole width
1127  SUMOReal width2 = (*k2).toEdge->getLaneWidth((*k2).toLane);
1128  if ((*k2).toEdge->getPermissions((*k2).toLane) != SVC_BICYCLE) {
1129  width2 *= 0.5;
1130  }
1131  const SUMOReal minDV = firstIntersection(shape, otherShape, width2);
1132  if (minDV < shape.length() - POSITION_EPS && minDV > POSITION_EPS) { // !!!?
1133  assert(minDV >= 0);
1134  if (crossingPositions.first < 0 || crossingPositions.first > minDV) {
1135  crossingPositions.first = minDV;
1136  }
1137  }
1138  }
1139  const bool rightTurnConflict = NBNode::rightTurnConflict(
1140  this, con.toEdge, con.fromLane, (*i2), (*k2).toEdge, (*k2).fromLane);
1141  // compute foe internal lanes
1142  if (n.foes(this, con.toEdge, *i2, (*k2).toEdge) || rightTurnConflict) {
1143  foeInternalLinks.push_back(index);
1144  }
1145  // compute foe incoming lanes
1146  const bool signalised = hasSignalisedConnectionTo(con.toEdge);
1147  if ((n.forbids(*i2, (*k2).toEdge, this, con.toEdge, signalised) || rightTurnConflict) && (needsCont || dir == LINKDIR_TURN)) {
1148  tmpFoeIncomingLanes.insert((*i2)->getID() + "_" + toString((*k2).fromLane));
1149  }
1150  index++;
1151  }
1152  }
1153  // foe pedestrian crossings
1154  const std::vector<NBNode::Crossing>& crossings = n.getCrossings();
1155  for (std::vector<NBNode::Crossing>::const_iterator it_c = crossings.begin(); it_c != crossings.end(); ++it_c) {
1156  const NBNode::Crossing& crossing = *it_c;
1157  for (EdgeVector::const_iterator it_e = crossing.edges.begin(); it_e != crossing.edges.end(); ++it_e) {
1158  const NBEdge* edge = *it_e;
1159  // compute foe internal lanes
1160  if (this == edge || con.toEdge == edge) {
1161  foeInternalLinks.push_back(index);
1162  if (con.toEdge == edge &&
1163  ((isRightTurn && getJunctionPriority(&n) > 0) || (isTurn && n.isTLControlled()))) {
1164  // build internal junctions (not for left turns at uncontrolled intersections)
1165  PositionVector crossingShape = crossing.shape;
1166  crossingShape.extrapolate(1.0); // sometimes shapes miss each other by a small margin
1167  const SUMOReal minDV = firstIntersection(shape, crossingShape, crossing.width / 2);
1168  if (minDV < shape.length() - POSITION_EPS && minDV > POSITION_EPS) {
1169  assert(minDV >= 0);
1170  if (crossingPositions.first < 0 || crossingPositions.first > minDV) {
1171  crossingPositions.first = minDV;
1172  }
1173  }
1174  }
1175  }
1176  }
1177  index++;
1178  }
1179 
1180  if (dir == LINKDIR_TURN && crossingPositions.first < 0 && crossingPositions.second.size() != 0 && shape.length() > 2. * POSITION_EPS) {
1181  // let turnarounds wait in the middle if no other crossing point was found and it has a sensible length
1182  // (if endOffset is used, the crossing point is in the middle of the part within the junction shape)
1183  crossingPositions.first = (SUMOReal)(shape.length() + getEndOffset(con.fromLane)) / 2.;
1184  }
1185  }
1186  break;
1187  default:
1188  break;
1189  }
1190  if (con.contPos != UNSPECIFIED_CONTPOS) {
1191  // apply custom internal junction position
1192  if (con.contPos <= 0 || con.contPos >= shape.length()) {
1193  // disable internal junction
1194  crossingPositions.first = -1;
1195  } else {
1196  // set custom position
1197  crossingPositions.first = con.contPos;
1198  }
1199  }
1200 
1201  // @todo compute the maximum speed allowed based on angular velocity
1202  // see !!! for an explanation (with a_lat_mean ~0.3)
1203  /*
1204  SUMOReal vmax = (SUMOReal) 0.3 * (SUMOReal) 9.80778 *
1205  getLaneShape(con.fromLane).back().distanceTo(
1206  con.toEdge->getLaneShape(con.toLane).front())
1207  / (SUMOReal) 2.0 / (SUMOReal) M_PI;
1208  vmax = MIN2(vmax, ((getSpeed() + con.toEdge->getSpeed()) / (SUMOReal) 2.0));
1209  */
1210  SUMOReal vmax = (getSpeed() + con.toEdge->getSpeed()) / (SUMOReal) 2.0;
1211  //
1212  Position end = con.toEdge->getLaneShape(con.toLane).front();
1213  Position beg = getLaneShape(con.fromLane).back();
1214 
1215  assert(shape.size() >= 2);
1216  // get internal splits if any
1217  if (crossingPositions.first >= 0) {
1218  std::pair<PositionVector, PositionVector> split = shape.splitAt(crossingPositions.first);
1219  con.id = innerID + "_" + toString(edgeIndex);
1220  con.shape = split.first;
1221  con.foeIncomingLanes = joinToString(tmpFoeIncomingLanes, " ");
1222  con.foeInternalLinks = foeInternalLinks; // resolve link indices to lane ids later
1223  con.viaID = innerID + "_" + toString(splitIndex + noInternalNoSplits);
1224  ++splitIndex;
1225  con.viaVmax = vmax;
1226  con.viaShape = split.second;
1227  con.haveVia = true;
1228  } else {
1229  con.id = innerID + "_" + toString(edgeIndex);
1230  con.shape = shape;
1231  }
1232  con.vmax = vmax;
1233  con.internalLaneIndex = internalLaneIndex;
1234  ++internalLaneIndex;
1235  ++linkIndex;
1236  }
1237 }
1238 
1239 
1240 SUMOReal
1243  if (v2.length() < POSITION_EPS) {
1244  return intersect;
1245  }
1246  PositionVector v2Right = v2;
1247  v2Right.move2side(width2);
1248 
1249  PositionVector v2Left = v2;
1250  v2Left.move2side(-width2);
1251 
1252  // intersect center line of v1 with left and right border of v2
1253  std::vector<SUMOReal> tmp = v1.intersectsAtLengths2D(v2Right);
1254  if (tmp.size() > 0) {
1255  intersect = MIN2(intersect, tmp[0]);
1256  }
1257  tmp = v1.intersectsAtLengths2D(v2Left);
1258  if (tmp.size() > 0) {
1259  intersect = MIN2(intersect, tmp[0]);
1260  }
1261  return intersect;
1262 }
1263 
1264 
1265 // -----------
1266 int
1267 NBEdge::getJunctionPriority(const NBNode* const node) const {
1268  if (node == myFrom) {
1269  return myFromJunctionPriority;
1270  } else {
1271  return myToJunctionPriority;
1272  }
1273 }
1274 
1275 
1276 void
1277 NBEdge::setJunctionPriority(const NBNode* const node, int prio) {
1278  if (node == myFrom) {
1279  myFromJunctionPriority = prio;
1280  } else {
1281  myToJunctionPriority = prio;
1282  }
1283 }
1284 
1285 
1286 SUMOReal
1287 NBEdge::getAngleAtNode(const NBNode* const atNode) const {
1288  // myStartAngle, myEndAngle are in [0,360] and this returns results in [-180,180]
1289  if (atNode == myFrom) {
1291  } else {
1292  assert(atNode == myTo);
1294  }
1295 }
1296 
1297 
1298 SUMOReal
1299 NBEdge::getAngleAtNodeToCenter(const NBNode* const atNode) const {
1300  if (atNode == myFrom) {
1301  SUMOReal res = myStartAngle - 180;
1302  if (res < 0) {
1303  res += 360;
1304  }
1305  return res;
1306  } else {
1307  assert(atNode == myTo);
1308  return myEndAngle;
1309  }
1310 }
1311 
1312 
1313 void
1314 NBEdge::setTurningDestination(NBEdge* e, bool onlyPossible) {
1315  if (!onlyPossible) {
1316  myTurnDestination = e;
1317  }
1319 }
1320 
1321 
1322 SUMOReal
1323 NBEdge::getLaneSpeed(unsigned int lane) const {
1324  return myLanes[lane].speed;
1325 }
1326 
1327 
1328 void
1330  // vissim needs this
1331  if (myFrom == myTo) {
1332  return;
1333  }
1334  // compute lane offset, first
1335  std::vector<SUMOReal> offsets;
1336  for (unsigned int i = 0; i < myLanes.size(); ++i) {
1337  offsets.push_back(0);
1338  }
1339  SUMOReal offset = 0;
1340  for (int i = (int)myLanes.size() - 2; i >= 0; --i) {
1341  offset += (getLaneWidth(i) + getLaneWidth(i + 1)) / 2. + SUMO_const_laneOffset;
1342  offsets[i] = offset;
1343  }
1345  SUMOReal laneWidth = myLanes.back().width != UNSPECIFIED_WIDTH ? myLanes.back().width : SUMO_const_laneWidth;
1346  offset = (laneWidth + SUMO_const_laneOffset) / 2.; // @todo: why is the lane offset counted in here?
1347  } else {
1348  SUMOReal width = 0;
1349  for (unsigned int i = 0; i < myLanes.size(); ++i) {
1350  width += getLaneWidth(i);
1351  }
1352  width += SUMO_const_laneOffset * SUMOReal(myLanes.size() - 1);
1353  offset = -width / 2. + getLaneWidth((int)myLanes.size() - 1) / 2.;
1354  }
1355  for (unsigned int i = 0; i < myLanes.size(); ++i) {
1356  offsets[i] += offset;
1357  }
1358 
1359  // build the shape of each lane
1360  for (unsigned int i = 0; i < myLanes.size(); ++i) {
1361  try {
1362  myLanes[i].shape = computeLaneShape(i, offsets[i]);
1363  } catch (InvalidArgument& e) {
1364  WRITE_WARNING("In edge '" + getID() + "': lane shape could not be determined (" + e.what() + ").");
1365  myLanes[i].shape = myGeom;
1366  }
1367  }
1368 }
1369 
1370 
1372 NBEdge::computeLaneShape(unsigned int lane, SUMOReal offset) const {
1373  PositionVector shape = myGeom;
1374  try {
1375  shape.move2side(offset);
1376  } catch (InvalidArgument& e) {
1377  WRITE_WARNING("In lane '" + getLaneID(lane) + "': Could not build shape (" + e.what() + ").");
1378  }
1379  return shape;
1380 }
1381 
1382 
1383 void
1385  // taking the angle at the first might be unstable, thus we take the angle
1386  // at a certain distance. (To compare two edges, additional geometry
1387  // segments are considered to resolve ambiguities)
1388  const bool hasFromShape = myFrom->getShape().size() > 0;
1389  const bool hasToShape = myTo->getShape().size() > 0;
1390  Position fromCenter = (hasFromShape ? myFrom->getShape().getCentroid() : myFrom->getPosition());
1391  Position toCenter = (hasToShape ? myTo->getShape().getCentroid() : myTo->getPosition());
1392  PositionVector shape = ((hasFromShape || hasToShape) && getNumLanes() > 0 ?
1394  myLanes[getNumLanes() - 1].shape
1395  : myLanes[getNumLanes() / 2].shape)
1396  : myGeom);
1397 
1398  // if the junction shape is suspicious we cannot trust the angle to the centroid
1399  if ((hasFromShape && (myFrom->getShape().distance(shape[0]) > 2 * POSITION_EPS
1400  || myFrom->getShape().around(shape[-1])))
1401  || (hasToShape && (myTo->getShape().distance(shape[-1]) > 2 * POSITION_EPS
1402  || myTo->getShape().around(shape[0])))) {
1403  fromCenter = myFrom->getPosition();
1404  toCenter = myTo->getPosition();
1405  shape = myGeom;
1406  }
1407 
1408  const SUMOReal angleLookahead = MIN2(shape.length2D() / 2, ANGLE_LOOKAHEAD);
1409  const Position referencePosStart = shape.positionAtOffset2D(angleLookahead);
1410  myStartAngle = GeomHelper::legacyDegree(fromCenter.angleTo2D(referencePosStart), true);
1411  const Position referencePosEnd = shape.positionAtOffset2D(shape.length() - angleLookahead);
1412  myEndAngle = GeomHelper::legacyDegree(referencePosEnd.angleTo2D(toCenter), true);
1414 }
1415 
1416 
1417 bool
1419  for (std::vector<Lane>::const_iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
1420  if ((*i).permissions != SVCAll) {
1421  return true;
1422  }
1423  }
1424  return false;
1425 }
1426 
1427 
1428 bool
1430  std::vector<Lane>::const_iterator i = myLanes.begin();
1431  SVCPermissions firstLanePermissions = i->permissions;
1432  i++;
1433  for (; i != myLanes.end(); ++i) {
1434  if (i->permissions != firstLanePermissions) {
1435  return true;
1436  }
1437  }
1438  return false;
1439 }
1440 
1441 
1442 bool
1444  for (std::vector<Lane>::const_iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
1445  if (i->width != myLanes.begin()->width) {
1446  return true;
1447  }
1448  }
1449  return false;
1450 }
1451 
1452 
1453 bool
1455  for (std::vector<Lane>::const_iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
1456  if (i->speed != getSpeed()) {
1457  return true;
1458  }
1459  }
1460  return false;
1461 }
1462 
1463 
1464 bool
1466  for (std::vector<Lane>::const_iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
1467  if (i->endOffset != myLanes.begin()->endOffset) {
1468  return true;
1469  }
1470  }
1471  return false;
1472 }
1473 
1474 
1475 bool
1478 }
1479 
1480 
1481 
1482 bool
1483 NBEdge::computeEdge2Edges(bool noLeftMovers) {
1484  // return if this relationship has been build in previous steps or
1485  // during the import
1486  if (myStep >= EDGE2EDGES) {
1487  return true;
1488  }
1489  if (myConnections.size() == 0) {
1490  const EdgeVector& o = myTo->getOutgoingEdges();
1491  for (EdgeVector::const_iterator i = o.begin(); i != o.end(); ++i) {
1492  if (noLeftMovers && myTo->isLeftMover(this, *i)) {
1493  continue;
1494  }
1495  myConnections.push_back(Connection(-1, *i, -1));
1496  }
1497  }
1498  myStep = EDGE2EDGES;
1499  return true;
1500 }
1501 
1502 
1503 bool
1505  // return if this relationship has been build in previous steps or
1506  // during the import
1507  if (myStep >= LANES2EDGES) {
1508  return true;
1509  }
1510  assert(myStep == EDGE2EDGES);
1511  // get list of possible outgoing edges sorted by direction clockwise
1512  // the edge in the backward direction (turnaround) is not in the list
1513  const EdgeVector* edges = getConnectedSorted();
1514  if (myConnections.size() != 0 && edges->size() == 0) {
1515  // dead end per definition!?
1516  myConnections.clear();
1517  } else {
1518  // divide the lanes on reachable edges
1519  divideOnEdges(edges);
1520  }
1521  delete edges;
1522  myStep = LANES2EDGES;
1523  return true;
1524 }
1525 
1526 
1527 bool
1529  std::vector<unsigned int> connNumbersPerLane(myLanes.size(), 0);
1530  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end();) {
1531  if ((*i).toEdge == 0 || (*i).fromLane < 0 || (*i).toLane < 0) {
1532  i = myConnections.erase(i);
1533  } else {
1534  if ((*i).fromLane >= 0) {
1535  ++connNumbersPerLane[(*i).fromLane];
1536  }
1537  ++i;
1538  }
1539  }
1541  // check #1:
1542  // If there is a lane with no connections and any neighbour lane has
1543  // more than one connections, try to move one of them.
1544  // This check is only done for edges which connections were assigned
1545  // using the standard algorithm.
1546  for (unsigned int i = 0; i < myLanes.size(); i++) {
1547  if (connNumbersPerLane[i] == 0 && !isForbidden(getPermissions((int)i))) {
1548  if (i > 0 && connNumbersPerLane[i - 1] > 1 && getPermissions(i) == getPermissions(i - 1)) {
1549  moveConnectionToLeft(i - 1);
1550  } else if (i < myLanes.size() - 1 && connNumbersPerLane[i + 1] > 1 && getPermissions(i) == getPermissions(i + 1)) {
1551  moveConnectionToRight(i + 1);
1552  }
1553  }
1554  }
1555  // check restrictions
1556  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end();) {
1557  Connection& c = *i;
1559  if (common == SVC_PEDESTRIAN || getPermissions(c.fromLane) == SVC_PEDESTRIAN) {
1560  // these are computed in NBNode::buildWalkingAreas
1561  i = myConnections.erase(i);
1562  } else if (common == 0) {
1563  // no common permissions.
1564  // try to find a suitable target lane to the right
1565  const int origToLane = c.toLane;
1566  c.toLane = -1; // ignore this connection when calling hasConnectionTo
1567  int toLane = origToLane;
1568  while (toLane > 0
1569  && (getPermissions(c.fromLane) & c.toEdge->getPermissions(toLane)) == 0
1570  && !hasConnectionTo(c.toEdge, toLane)
1571  ) {
1572  toLane--;
1573  }
1574  if ((getPermissions(c.fromLane) & c.toEdge->getPermissions(toLane)) != 0
1575  && !hasConnectionTo(c.toEdge, toLane)) {
1576  c.toLane = toLane;
1577  ++i;
1578  } else {
1579  // try to find a suitable target lane to the left
1580  int toLane = origToLane;
1581  while (toLane < (int)c.toEdge->getNumLanes() - 1
1582  && (getPermissions(c.fromLane) & c.toEdge->getPermissions(toLane)) == 0
1583  && !hasConnectionTo(c.toEdge, toLane)
1584  ) {
1585  toLane++;
1586  }
1587  if ((getPermissions(c.fromLane) & c.toEdge->getPermissions(toLane)) != 0
1588  && !hasConnectionTo(c.toEdge, toLane)) {
1589  c.toLane = toLane;
1590  ++i;
1591  } else {
1592  // no alternative target found
1593  i = myConnections.erase(i);
1594  }
1595  }
1597  && isTurningDirectionAt(c.toEdge)) {
1598  // do not allow sharp rail turns
1599  i = myConnections.erase(i);
1600  } else {
1601  ++i;
1602  }
1603  }
1604  }
1605  // check delayed removals
1606  for (std::vector<Connection>::iterator it = myConnectionsToDelete.begin(); it != myConnectionsToDelete.end(); ++it) {
1607  removeFromConnections(it->toEdge, it->fromLane, it->toLane);
1608  }
1609  return true;
1610 }
1611 
1612 
1613 void
1615  if (outgoing->size() == 0) {
1616  // we have to do this, because the turnaround may have been added before
1617  myConnections.clear();
1618  return;
1619  }
1620  // precompute edge priorities; needed as some kind of assumptions for
1621  // priorities of directions (see preparePriorities)
1622  std::vector<unsigned int>* priorities = prepareEdgePriorities(outgoing);
1623  // compute the indices of lanes that should have connections (excluding
1624  // forbidden lanes and pedestrian lanes that will be connected via walkingAreas)
1625 
1626 
1627  // build connections for miv lanes
1628  std::vector<int> availableLanes;
1629  for (int i = 0; i < (int)myLanes.size(); ++i) {
1630  if ((getPermissions(i) & SVC_PASSENGER) != 0) {
1631  availableLanes.push_back(i);
1632  }
1633  }
1634  if (availableLanes.size() > 0) {
1635  divideSelectedLanesOnEdges(outgoing, availableLanes, priorities);
1636  }
1637  // build connections for miscellaneous further modes (more than bike,peds,bus and without passenger)
1638  availableLanes.clear();
1639  for (int i = 0; i < (int)myLanes.size(); ++i) {
1640  const SVCPermissions perms = getPermissions(i);
1641  if ((perms & ~(SVC_PEDESTRIAN | SVC_BICYCLE | SVC_BUS)) == 0 || (perms & SVC_PASSENGER) != 0 || isForbidden(perms)) {
1642  continue;
1643  }
1644  availableLanes.push_back(i);
1645  }
1646  if (availableLanes.size() > 0) {
1647  divideSelectedLanesOnEdges(outgoing, availableLanes, priorities);
1648  }
1649  // build connections for busses (possibly combined with bicycles)
1650  availableLanes.clear();
1651  for (int i = 0; i < (int)myLanes.size(); ++i) {
1652  const SVCPermissions perms = getPermissions(i);
1653  if (perms != SVC_BUS && perms != (SVC_BUS | SVC_BICYCLE)) {
1654  continue;
1655  }
1656  availableLanes.push_back(i);
1657  }
1658  if (availableLanes.size() > 0) {
1659  divideSelectedLanesOnEdges(outgoing, availableLanes, priorities);
1660  }
1661  // build connections for bicycles (possibly combined with pedestrians)
1662  availableLanes.clear();
1663  for (int i = 0; i < (int)myLanes.size(); ++i) {
1664  const SVCPermissions perms = getPermissions(i);
1665  if (perms != SVC_BICYCLE && perms != (SVC_BICYCLE | SVC_PEDESTRIAN)) {
1666  continue;
1667  }
1668  availableLanes.push_back(i);
1669  }
1670  if (availableLanes.size() > 0) {
1671  divideSelectedLanesOnEdges(outgoing, availableLanes, priorities);
1672  }
1673  // clean up unassigned fromLanes
1674  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end();) {
1675  if ((*i).fromLane == -1) {
1676  i = myConnections.erase(i);
1677  } else {
1678  ++i;
1679  }
1680  }
1682 
1683  delete priorities;
1684 }
1685 
1686 
1687 void
1688 NBEdge::divideSelectedLanesOnEdges(const EdgeVector* outgoing, const std::vector<int>& availableLanes, const std::vector<unsigned int>* priorities) {
1689  //std::cout << "divideSelectedLanesOnEdges " << getID() << " out=" << toString(*outgoing) << " prios=" << toString(*priorities) << " avail=" << toString(availableLanes) << "\n";
1690  // compute the sum of priorities (needed for normalisation)
1691  unsigned int prioSum = computePrioritySum(*priorities);
1692  // compute the resulting number of lanes that should be used to
1693  // reach the following edge
1694  const int numOutgoing = (int) outgoing->size();
1695  std::vector<SUMOReal> resultingLanes;
1696  resultingLanes.reserve(numOutgoing);
1697  SUMOReal sumResulting = 0.; // the sum of resulting lanes
1698  SUMOReal minResulting = 10000.; // the least number of lanes to reach an edge
1699  for (int i = 0; i < numOutgoing; i++) {
1700  // res will be the number of lanes which are meant to reach the
1701  // current outgoing edge
1702  SUMOReal res =
1703  (SUMOReal)(*priorities)[i] *
1704  (SUMOReal) availableLanes.size() / (SUMOReal) prioSum;
1705  // do not let this number be greater than the number of available lanes
1706  if (res > availableLanes.size()) {
1707  res = (SUMOReal) availableLanes.size();
1708  }
1709  // add it to the list
1710  resultingLanes.push_back(res);
1711  sumResulting += res;
1712  if (minResulting > res && res > 0) {
1713  // prevent minResulting from becoming 0
1714  minResulting = res;
1715  }
1716  }
1717  // compute the number of virtual edges
1718  // a virtual edge is used as a replacement for a real edge from now on
1719  // it shall allow to divide the existing lanes on this structure without
1720  // regarding the structure of outgoing edges
1721  const int numVirtual = (int)(sumResulting / minResulting + 0.5);
1722  // compute the transition from virtual to real edges
1723  EdgeVector transition;
1724  transition.reserve(numOutgoing);
1725  for (int i = 0; i < numOutgoing; i++) {
1726  // tmpNo will be the number of connections from this edge
1727  // to the next edge
1728  assert(i < (int)resultingLanes.size());
1729  const SUMOReal tmpNum = resultingLanes[i] / minResulting;
1730  for (SUMOReal j = 0; j < tmpNum; j++) {
1731  transition.push_back((*outgoing)[i]);
1732  }
1733  }
1734  // assign lanes to edges
1735  // (conversion from virtual to real edges is done)
1736  ToEdgeConnectionsAdder adder(transition);
1737  Bresenham::compute(&adder, static_cast<unsigned int>(availableLanes.size()), numVirtual);
1738  const std::map<NBEdge*, std::vector<unsigned int> >& l2eConns = adder.getBuiltConnections();
1739  for (std::map<NBEdge*, std::vector<unsigned int> >::const_iterator i = l2eConns.begin(); i != l2eConns.end(); ++i) {
1740  NBEdge* target = (*i).first;
1741  const std::vector<unsigned int> lanes = (*i).second;
1742  for (std::vector<unsigned int>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
1743  const int fromIndex = availableLanes[*j];
1744  if ((getPermissions(fromIndex) & target->getPermissions()) == 0) {
1745  // exclude connection if fromLane and toEdge have no common permissions
1746  continue;
1747  }
1748  if ((getPermissions(fromIndex) & target->getPermissions()) == SVC_PEDESTRIAN) {
1749  // exclude connection if the only commonly permitted class are pedestrians
1750  // these connections are later built in NBNode::buildWalkingAreas
1751  continue;
1752  }
1753  // avoid building more connections than the edge has viable lanes (earlier
1754  // ones have precedence). This is necessary when running divideSelectedLanesOnEdges more than once.
1755  // @todo To decide which target lanes are still available we need to do a
1756  // preliminary lane-to-lane assignment in regard to permisions (rather than to ordering)
1757  const int numConsToTarget = (int)count_if(myConnections.begin(), myConnections.end(), connections_toedge_finder(target, true));
1758  int targetLanes = (int)target->getNumLanes();
1759  if (target->getPermissions(0) == SVC_PEDESTRIAN) {
1760  --targetLanes;
1761  }
1762  if (numConsToTarget >= targetLanes) {
1763  // let bicycles move onto the road to allow continuation
1764  // the speed limit is taken from rural roads (which allow cycles)
1765  // (pending implementation of #1859)
1766  if (getPermissions(fromIndex) == SVC_BICYCLE && getSpeed() <= (101 / 3.6)) {
1767  for (unsigned int ii = 0; ii < myLanes.size(); ++ii) {
1768  if (myLanes[ii].permissions != SVC_PEDESTRIAN) {
1769  myLanes[ii].permissions |= SVC_BICYCLE;
1770  }
1771  }
1772  }
1773  continue;
1774  }
1775 
1776  myConnections.push_back(Connection(fromIndex, target, -1));
1777  }
1778  }
1779 }
1780 
1781 
1782 std::vector<unsigned int>*
1784  // copy the priorities first
1785  std::vector<unsigned int>* priorities = new std::vector<unsigned int>();
1786  if (outgoing->size() == 0) {
1787  return priorities;
1788  }
1789  priorities->reserve(outgoing->size());
1790  EdgeVector::const_iterator i;
1791  for (i = outgoing->begin(); i != outgoing->end(); i++) {
1792  int prio = (*i)->getJunctionPriority(myTo);
1793  assert((prio + 1) * 2 > 0);
1794  prio = (prio + 1) * 2;
1795  priorities->push_back(prio);
1796  }
1797  // when the right turning direction has not a higher priority, divide
1798  // the importance by 2 due to the possibility to leave the junction
1799  // faster from this lane
1800  MainDirections mainDirections(*outgoing, this, myTo);
1801  EdgeVector tmp(*outgoing);
1802  sort(tmp.begin(), tmp.end(), NBContHelper::edge_similar_direction_sorter(this));
1803  i = find(outgoing->begin(), outgoing->end(), *(tmp.begin()));
1804  unsigned int dist = (unsigned int) distance(outgoing->begin(), i);
1805  if (dist != 0 && !mainDirections.includes(MainDirections::DIR_RIGHTMOST)) {
1806  assert(priorities->size() > 0);
1807  (*priorities)[0] /= 2;
1808  }
1809  // HEURISTIC:
1810  // when no higher priority exists, let the forward direction be
1811  // the main direction
1812  if (mainDirections.empty()) {
1813  assert(dist < priorities->size());
1814  (*priorities)[dist] *= 2;
1815  }
1816  if (mainDirections.includes(MainDirections::DIR_FORWARD)) {
1817  if (myLanes.size() > 2) {
1818  (*priorities)[dist] *= 2;
1819  } else {
1820  (*priorities)[dist] *= 3;
1821  }
1822  }
1823  // return
1824  return priorities;
1825 }
1826 
1827 
1828 unsigned int
1829 NBEdge::computePrioritySum(const std::vector<unsigned int>& priorities) {
1830  unsigned int sum = 0;
1831  for (std::vector<unsigned int>::const_iterator i = priorities.begin(); i != priorities.end(); i++) {
1832  sum += (int) * i;
1833  }
1834  return sum;
1835 }
1836 
1837 
1838 void
1839 NBEdge::appendTurnaround(bool noTLSControlled, bool checkPermissions) {
1840  // do nothing if no turnaround is known
1842  return;
1843  }
1844  // do nothing if the destination node is controlled by a tls and no turnarounds
1845  // shall be appended for such junctions
1846  if (noTLSControlled && myTo->isTLControlled()) {
1847  return;
1848  }
1849  const int fromLane = (int)myLanes.size() - 1;
1850  const int toLane = (int)myTurnDestination->getNumLanes() - 1;
1851  if (checkPermissions) {
1852  if ((getPermissions(fromLane) & myTurnDestination->getPermissions(toLane)) == 0) {
1853  // exclude connection if fromLane and toEdge have no common permissions
1854  return;
1855  }
1856  if ((getPermissions(fromLane) & myTurnDestination->getPermissions(toLane)) == SVC_PEDESTRIAN) {
1857  // exclude connection if the only commonly permitted class are pedestrians
1858  // these connections are later built in NBNode::buildWalkingAreas
1859  return;
1860  }
1861  }
1862  setConnection(fromLane, myTurnDestination, toLane, L2L_VALIDATED);
1863 }
1864 
1865 
1866 bool
1867 NBEdge::isTurningDirectionAt(const NBEdge* const edge) const {
1868  // maybe it was already set as the turning direction
1869  if (edge == myTurnDestination) {
1870  return true;
1871  } else if (myTurnDestination != 0) {
1872  // otherwise - it's not if a turning direction exists
1873  return false;
1874  }
1875  return edge == myPossibleTurnDestination;
1876 }
1877 
1878 
1879 NBNode*
1881  // return the from-node when the position is at the begin of the edge
1882  if (pos < tolerance) {
1883  return myFrom;
1884  }
1885  // return the to-node when the position is at the end of the edge
1886  if (pos > myLength - tolerance) {
1887  return myTo;
1888  }
1889  return 0;
1890 }
1891 
1892 
1893 void
1894 NBEdge::moveOutgoingConnectionsFrom(NBEdge* e, unsigned int laneOff) {
1895  unsigned int lanes = e->getNumLanes();
1896  for (unsigned int i = 0; i < lanes; i++) {
1897  std::vector<NBEdge::Connection> elv = e->getConnectionsFromLane(i);
1898  for (std::vector<NBEdge::Connection>::iterator j = elv.begin(); j != elv.end(); j++) {
1899  NBEdge::Connection el = *j;
1900  assert(el.tlID == "");
1901  addLane2LaneConnection(i + laneOff, el.toEdge, el.toLane, L2L_COMPUTED);
1902  }
1903  }
1904 }
1905 
1906 
1907 bool
1910 }
1911 
1912 
1913 SUMOReal
1916 }
1917 
1918 
1919 bool
1920 NBEdge::mayBeTLSControlled(int fromLane, NBEdge* toEdge, int toLane) const {
1922  tpl.fromLane = fromLane;
1923  tpl.to = toEdge;
1924  tpl.toLane = toLane;
1925  std::vector<TLSDisabledConnection>::const_iterator i = find_if(myTLSDisabledConnections.begin(), myTLSDisabledConnections.end(), tls_disable_finder(tpl));
1926  return i == myTLSDisabledConnections.end();
1927 }
1928 
1929 
1930 bool
1931 NBEdge::setControllingTLInformation(const NBConnection& c, const std::string& tlID) {
1932  const int fromLane = c.getFromLane();
1933  NBEdge* toEdge = c.getTo();
1934  const int toLane = c.getToLane();
1935  const int tlIndex = c.getTLIndex();
1936  // check whether the connection was not set as not to be controled previously
1938  tpl.fromLane = fromLane;
1939  tpl.to = toEdge;
1940  tpl.toLane = toLane;
1941  std::vector<TLSDisabledConnection>::iterator i = find_if(myTLSDisabledConnections.begin(), myTLSDisabledConnections.end(), tls_disable_finder(tpl));
1942  if (i != myTLSDisabledConnections.end()) {
1943  return false;
1944  }
1945 
1946  assert(fromLane < 0 || fromLane < (int) myLanes.size());
1947  // try to use information about the connections if given
1948  if (fromLane >= 0 && toLane >= 0) {
1949  // find the specified connection
1950  std::vector<Connection>::iterator i =
1951  find_if(myConnections.begin(), myConnections.end(), connections_finder(fromLane, toEdge, toLane));
1952  // ok, we have to test this as on the removal of self-loop edges some connections
1953  // will be reassigned
1954  if (i != myConnections.end()) {
1955  // get the connection
1956  Connection& connection = *i;
1957  // set the information about the tl
1958  connection.tlID = tlID;
1959  connection.tlLinkNo = tlIndex;
1960  return true;
1961  }
1962  }
1963  // if the original connection was not found, set the information for all
1964  // connections
1965  unsigned int no = 0;
1966  bool hadError = false;
1967  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
1968  if ((*i).toEdge != toEdge) {
1969  continue;
1970  }
1971  if (fromLane >= 0 && fromLane != (*i).fromLane) {
1972  continue;
1973  }
1974  if (toLane >= 0 && toLane != (*i).toLane) {
1975  continue;
1976  }
1977  if ((*i).tlID == "") {
1978  (*i).tlID = tlID;
1979  (*i).tlLinkNo = tlIndex;
1980  no++;
1981  } else {
1982  if ((*i).tlID != tlID && (*i).tlLinkNo == tlIndex) {
1983  WRITE_WARNING("The lane '" + toString<int>((*i).fromLane) + "' on edge '" + getID() + "' already had a traffic light signal.");
1984  hadError = true;
1985  }
1986  }
1987  }
1988  if (hadError && no == 0) {
1989  WRITE_WARNING("Could not set any signal of the tlLogic '" + tlID + "' (unknown group)");
1990  }
1991  return true;
1992 }
1993 
1994 
1995 void
1997  for (std::vector<Connection>::iterator it = myConnections.begin(); it != myConnections.end(); it++) {
1998  it->tlID = "";
1999  }
2000 }
2001 
2002 
2003 void
2004 NBEdge::disableConnection4TLS(int fromLane, NBEdge* toEdge, int toLane) {
2006  c.fromLane = fromLane;
2007  c.to = toEdge;
2008  c.toLane = toLane;
2009  myTLSDisabledConnections.push_back(c);
2010 }
2011 
2012 
2015  PositionVector ret;
2016  SUMOReal width;
2017  if (myFrom == (&n)) {
2018  // outgoing
2019  ret = myLanes[0].shape;
2020  width = getLaneWidth(0);
2021  } else {
2022  // incoming
2023  ret = myLanes.back().shape.reverse();
2024  width = getLaneWidth((int)getNumLanes() - 1);
2025  }
2026  ret.move2side(width * 0.5);
2027  return ret;
2028 }
2029 
2030 
2033  PositionVector ret;
2034  SUMOReal width;
2035  if (myFrom == (&n)) {
2036  // outgoing
2037  ret = myLanes.back().shape;
2038  width = getLaneWidth((int)getNumLanes() - 1);
2039  } else {
2040  // incoming
2041  ret = myLanes[0].shape.reverse();
2042  width = getLaneWidth(0);
2043  }
2044  ret.move2side(-width * 0.5);
2045  return ret;
2046 }
2047 
2048 
2049 bool
2050 NBEdge::expandableBy(NBEdge* possContinuation) const {
2051  // ok, the number of lanes must match
2052  if (myLanes.size() != possContinuation->myLanes.size()) {
2053  return false;
2054  }
2055  // the priority, too (?)
2056  if (getPriority() != possContinuation->getPriority()) {
2057  return false;
2058  }
2059  // the speed allowed
2060  if (mySpeed != possContinuation->mySpeed) {
2061  return false;
2062  }
2063  // spreadtype should match or it will look ugly
2064  if (myLaneSpreadFunction != possContinuation->myLaneSpreadFunction) {
2065  return false;
2066  }
2067  // do not create self loops
2068  if (myFrom == possContinuation->myTo) {
2069  return false;
2070  }
2071 
2072  // the vehicle class constraints, too
2080  // also, check whether the connections - if any exit do allow to join
2081  // both edges
2082  // This edge must have a one-to-one connection to the following lanes
2083  switch (myStep) {
2085  break;
2086  case INIT:
2087  break;
2088  case EDGE2EDGES: {
2089  // the following edge must be connected
2090  const EdgeVector& conn = getConnectedEdges();
2091  if (find(conn.begin(), conn.end(), possContinuation)
2092  == conn.end()) {
2093 
2094  return false;
2095  }
2096  }
2097  break;
2098  case LANES2EDGES:
2099  case LANES2LANES_RECHECK:
2100  case LANES2LANES_DONE:
2101  case LANES2LANES_USER: {
2102  // the possible continuation must be connected
2103  if (find_if(myConnections.begin(), myConnections.end(), connections_toedge_finder(possContinuation)) == myConnections.end()) {
2104  return false;
2105  }
2106  // all lanes must go to the possible continuation
2107  std::vector<int> conns = getConnectionLanes(possContinuation);
2108  if (conns.size() != myLanes.size()) {
2109  return false;
2110  }
2111  }
2112  break;
2113  default:
2114  break;
2115  }
2116  return true;
2117 }
2118 
2119 
2120 void
2122  // append geometry
2123  myGeom.append(e->myGeom);
2124  for (unsigned int i = 0; i < myLanes.size(); i++) {
2125  myLanes[i].shape.append(e->myLanes[i].shape);
2126  }
2127  // recompute length
2128  myLength += e->myLength;
2129  // copy the connections and the building step if given
2130  myStep = e->myStep;
2134  // set the node
2135  myTo = e->myTo;
2138  } else {
2139  mySignalOffset += e->getLength();
2140  }
2141  computeAngle(); // myEndAngle may be different now
2142 }
2143 
2144 
2145 bool
2147  for (std::vector<Connection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
2148  if ((*i).toEdge == e && (*i).tlID != "") {
2149  return true;
2150  }
2151  }
2152  return false;
2153 }
2154 
2155 
2156 NBEdge*
2157 NBEdge::getTurnDestination(bool possibleDestination) const {
2158  if (myTurnDestination == 0 && possibleDestination) {
2160  }
2161  return myTurnDestination;
2162 }
2163 
2164 
2165 std::string
2166 NBEdge::getLaneID(unsigned int lane) const {
2167  return myID + "_" + toString(lane);
2168 }
2169 
2170 
2171 std::string
2172 NBEdge::getLaneIDInsecure(unsigned int lane) const {
2173  return myID + "_" + toString(lane);
2174 }
2175 
2176 
2177 bool
2179  std::vector<SUMOReal> distances = myGeom.distances(e->getGeometry());
2180  assert(distances.size() > 0);
2181  return VectorHelper<SUMOReal>::maxValue(distances) < threshold;
2182 }
2183 
2184 
2185 void
2186 NBEdge::addLane(unsigned int index, bool recompute) {
2187  assert(index <= myLanes.size());
2188  myLanes.insert(myLanes.begin() + index, Lane(this, ""));
2189  // copy attributes
2190  if (myLanes.size() > 1) {
2191  int templateIndex = index > 0 ? index - 1 : index + 1;
2192  myLanes[index].speed = myLanes[templateIndex].speed;
2193  myLanes[index].permissions = myLanes[templateIndex].permissions;
2194  myLanes[index].preferred = myLanes[templateIndex].preferred;
2195  myLanes[index].endOffset = myLanes[templateIndex].endOffset;
2196  myLanes[index].width = myLanes[templateIndex].width;
2197  myLanes[index].origID = myLanes[templateIndex].origID;
2198  }
2199  const EdgeVector& incs = myFrom->getIncomingEdges();
2200  if (recompute) {
2202  for (EdgeVector::const_iterator i = incs.begin(); i != incs.end(); ++i) {
2203  (*i)->invalidateConnections(true);
2204  }
2205  invalidateConnections(true);
2206  }
2207 }
2208 
2209 void
2210 NBEdge::incLaneNo(unsigned int by) {
2211  unsigned int newLaneNo = (unsigned int) myLanes.size() + by;
2212  while (myLanes.size() < newLaneNo) {
2213  // recompute shapes on last addition
2214  const bool recompute = (myLanes.size() == newLaneNo - 1) && myStep < LANES2LANES_USER;
2215  addLane((unsigned int)myLanes.size(), recompute);
2216  }
2217 }
2218 
2219 
2220 void
2221 NBEdge::deleteLane(unsigned int index, bool recompute) {
2222  assert(index < myLanes.size());
2223  myLanes.erase(myLanes.begin() + index);
2224  const EdgeVector& incs = myFrom->getIncomingEdges();
2225  if (recompute) {
2227  for (EdgeVector::const_iterator i = incs.begin(); i != incs.end(); ++i) {
2228  (*i)->invalidateConnections(true);
2229  }
2230  invalidateConnections(true);
2231  }
2232 }
2233 
2234 
2235 void
2236 NBEdge::decLaneNo(unsigned int by) {
2237  unsigned int newLaneNo = (unsigned int) myLanes.size() - by;
2238  assert(newLaneNo > 0);
2239  while (myLanes.size() > newLaneNo) {
2240  // recompute shapes on last removal
2241  const bool recompute = myLanes.size() == newLaneNo + 1 && myStep < LANES2LANES_USER;
2242  deleteLane((unsigned int)((int)myLanes.size() - 1), recompute);
2243  }
2244 }
2245 
2246 
2247 void
2249  assert(myTo->getOutgoingEdges().size() == 0);
2251 }
2252 
2253 
2254 void
2256  if (lane < 0) { // all lanes are meant...
2257  for (unsigned int i = 0; i < myLanes.size(); i++) {
2258  allowVehicleClass((int) i, vclass);
2259  }
2260  } else {
2261  assert(lane < (int) myLanes.size());
2262  myLanes[lane].permissions |= vclass;
2263  }
2264 }
2265 
2266 
2267 void
2269  if (lane < 0) { // all lanes are meant...
2270  for (unsigned int i = 0; i < myLanes.size(); i++) {
2271  disallowVehicleClass((int) i, vclass);
2272  }
2273  } else {
2274  assert(lane < (int) myLanes.size());
2275  myLanes[lane].permissions &= ~vclass;
2276  }
2277 }
2278 
2279 
2280 void
2282  if (lane < 0) { // all lanes are meant...
2283  for (unsigned int i = 0; i < myLanes.size(); i++) {
2284  allowVehicleClass((int) i, vclass);
2285  }
2286  } else {
2287  assert(lane < (int) myLanes.size());
2288  myLanes[lane].preferred |= vclass;
2289  }
2290 }
2291 
2292 
2293 void
2294 NBEdge::setLaneWidth(int lane, SUMOReal width) {
2295  if (lane < 0) {
2296  // all lanes are meant...
2297  myLaneWidth = width;
2298  for (unsigned int i = 0; i < myLanes.size(); i++) {
2299  // ... do it for each lane
2300  setLaneWidth((int) i, width);
2301  }
2302  return;
2303  }
2304  assert(lane < (int) myLanes.size());
2305  myLanes[lane].width = width;
2306 }
2307 
2308 
2309 SUMOReal
2310 NBEdge::getLaneWidth(int lane) const {
2311  return myLanes[lane].width != UNSPECIFIED_WIDTH
2312  ? myLanes[lane].width
2314 }
2315 
2316 
2317 SUMOReal
2319  SUMOReal result = 0;
2320  for (unsigned int i = 0; i < myLanes.size(); i++) {
2321  result += getLaneWidth(i);
2322  }
2323  return result;
2324 }
2325 
2326 SUMOReal
2327 NBEdge::getEndOffset(int lane) const {
2328  return myLanes[lane].endOffset != UNSPECIFIED_OFFSET ? myLanes[lane].endOffset : getEndOffset();
2329 }
2330 
2331 
2332 void
2333 NBEdge::setEndOffset(int lane, SUMOReal offset) {
2334  if (lane < 0) {
2335  // all lanes are meant...
2336  myEndOffset = offset;
2337  for (unsigned int i = 0; i < myLanes.size(); i++) {
2338  // ... do it for each lane
2339  setEndOffset((int) i, offset);
2340  }
2341  return;
2342  }
2343  assert(lane < (int) myLanes.size());
2344  myLanes[lane].endOffset = offset;
2345 }
2346 
2347 
2348 void
2349 NBEdge::setSpeed(int lane, SUMOReal speed) {
2350  if (lane < 0) {
2351  // all lanes are meant...
2352  mySpeed = speed;
2353  for (unsigned int i = 0; i < myLanes.size(); i++) {
2354  // ... do it for each lane
2355  setSpeed((int) i, speed);
2356  }
2357  return;
2358  }
2359  assert(lane < (int) myLanes.size());
2360  myLanes[lane].speed = speed;
2361 }
2362 
2363 
2364 void
2365 NBEdge::setPermissions(SVCPermissions permissions, int lane) {
2366  if (lane < 0) {
2367  for (unsigned int i = 0; i < myLanes.size(); i++) {
2368  // ... do it for each lane
2369  setPermissions(permissions, i);
2370  }
2371  } else {
2372  assert(lane < (int) myLanes.size());
2373  myLanes[lane].permissions = permissions;
2374  }
2375 }
2376 
2377 
2378 void
2380  if (lane < 0) {
2381  for (unsigned int i = 0; i < myLanes.size(); i++) {
2382  // ... do it for each lane
2383  setPreferredVehicleClass(permissions, i);
2384  }
2385  } else {
2386  assert(lane < (int) myLanes.size());
2387  myLanes[lane].preferred = permissions;
2388  }
2389 }
2390 
2391 
2393 NBEdge::getPermissions(int lane) const {
2394  if (lane < 0) {
2395  SVCPermissions result = 0;
2396  for (unsigned int i = 0; i < myLanes.size(); i++) {
2397  result |= getPermissions(i);
2398  }
2399  return result;
2400  } else {
2401  assert(lane < (int) myLanes.size());
2402  return myLanes[lane].permissions;
2403  }
2404 }
2405 
2406 
2407 void
2409  myLoadedLength = val;
2410 }
2411 
2412 
2413 void
2415  for (std::vector<Lane>::iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
2416  (*i).permissions = SVCAll;
2417  (*i).preferred = 0;
2418  }
2419 }
2420 
2421 
2422 bool
2424  if (c1.fromLane != c2.fromLane) {
2425  return c1.fromLane < c2.fromLane;
2426  }
2427  if (c1.toEdge != c2.toEdge) {
2428  return false; // do not change ordering among toEdges as this is determined by angle in an earlier step
2429  }
2430  return c1.toLane < c2.toLane;
2431 }
2432 
2433 
2434 int
2435 NBEdge::getFirstNonPedestrianLaneIndex(int direction, bool exclusive) const {
2436  assert(direction == NBNode::FORWARD || direction == NBNode::BACKWARD);
2437  const int start = (direction == NBNode::FORWARD ? 0 : (int)myLanes.size() - 1);
2438  const int end = (direction == NBNode::FORWARD ? (int)myLanes.size() : - 1);
2439  for (int i = start; i != end; i += direction) {
2440  // SVCAll, does not count as a sidewalk, green verges (permissions = 0) do not count as road
2441  // in the exclusive case, lanes that allow pedestrians along with any other class also count as road
2442  if ((exclusive && myLanes[i].permissions != SVC_PEDESTRIAN && myLanes[i].permissions != 0)
2443  || (myLanes[i].permissions == SVCAll || ((myLanes[i].permissions & SVC_PEDESTRIAN) == 0 && myLanes[i].permissions != 0))) {
2444  return i;
2445  }
2446  }
2447  return -1;
2448 }
2449 
2450 
2451 SUMOReal
2453  SUMOReal angle = getAngleAtNode(node) + (getFromNode() == node ? 180.0 : 0.0);
2454  if (angle < 0) {
2455  angle += 360.0;
2456  }
2457  if (angle >= 360) {
2458  angle -= 360.0;
2459  }
2460  if (gDebugFlag1) {
2461  std::cout << getID() << " angle=" << getAngleAtNode(node) << " convAngle=" << angle << "\n";
2462  }
2463  return angle;
2464 }
2465 
2466 
2469  int index = getFirstNonPedestrianLaneIndex(direction);
2470  if (index < 0) {
2471  throw ProcessError("Edge " + getID() + " allows pedestrians on all lanes");
2472  }
2473  return myLanes[index];
2474 }
2475 
2476 
2477 void
2480 }
2481 
2482 
2483 void
2486 }
2487 
2488 
2489 void
2491  if (myLanes[0].permissions == vclass) {
2492  WRITE_WARNING("Edge '" + getID() + "' already has a dedicated lane for " + toString(vclass) + "s. Not adding another one.");
2493  return;
2494  }
2496  myGeom.move2side(width / 2);
2497  }
2498  // disallow pedestrians on all lanes to ensure that sidewalks are used and
2499  // crossings can be guessed
2500  disallowVehicleClass(-1, vclass);
2501  // add new lane
2502  myLanes.insert(myLanes.begin(), Lane(this, myLanes[0].origID));
2503  myLanes[0].permissions = vclass;
2504  myLanes[0].width = width;
2505  // shift outgoing connections to the left
2506  for (std::vector<Connection>::iterator it = myConnections.begin(); it != myConnections.end(); ++it) {
2507  Connection& c = *it;
2508  if (c.fromLane >= 0) {
2509  c.fromLane += 1;
2510  }
2511  }
2512  // shift incoming connections to the left
2513  const EdgeVector& incoming = myFrom->getIncomingEdges();
2514  for (EdgeVector::const_iterator it = incoming.begin(); it != incoming.end(); ++it) {
2515  (*it)->shiftToLanesToEdge(this, 1);
2516  }
2518  myTo->shiftTLConnectionLaneIndex(this, 1);
2520 }
2521 
2522 
2523 void
2524 NBEdge::shiftToLanesToEdge(NBEdge* to, unsigned int laneOff) {
2526  for (std::vector<Connection>::iterator it = myConnections.begin(); it != myConnections.end(); ++it) {
2527  if ((*it).toEdge == to && (*it).toLane >= 0) {
2528  (*it).toLane += laneOff;
2529  }
2530  }
2531 }
2532 
2533 
2534 void
2537  const int i = (node == myTo ? -1 : 0);
2538  const int i2 = (node == myTo ? 0 : -1);
2539  const SUMOReal dist = myGeom[i].distanceTo2D(node->getPosition());
2540  const SUMOReal neededOffset = (getTotalWidth() + getNumLanes() * SUMO_const_laneOffset) / 2;
2541  const SUMOReal dist2 = MIN2(myGeom.distance(other->getGeometry()[i2]),
2542  other->getGeometry().distance(myGeom[i]));
2543  const SUMOReal neededOffset2 = neededOffset + (other->getTotalWidth() + other->getNumLanes() * SUMO_const_laneOffset) / 2;
2544  if (dist < neededOffset && dist2 < neededOffset2) {
2545  PositionVector tmp = myGeom;
2546  // @note this doesn't work well for vissim networks
2547  //tmp.move2side(MIN2(neededOffset - dist, neededOffset2 - dist2));
2548  try {
2549  tmp.move2side(neededOffset - dist);
2550  myGeom[i] = tmp[i];
2551  } catch (InvalidArgument&) {
2552  WRITE_WARNING("Could not avoid overlapping shape at node '" + node->getID() + "' for edge '" + getID() + "'");
2553  }
2554  }
2555  }
2556 }
2557 
2558 
2559 SUMOReal
2561  SUMOReal result = getLoadedLength();
2562  if (OptionsCont::getOptions().getBool("no-internal-links") && !hasLoadedLength()) {
2563  // use length to junction center even if a modified geometry was given
2565  geom.push_back_noDoublePos(getToNode()->getCenter());
2566  geom.push_front_noDoublePos(getFromNode()->getCenter());
2567  result = geom.length();
2568  }
2569  if (result <= 0) {
2570  result = POSITION_EPS;
2571  }
2572  return result;
2573 }
2574 
2575 /****************************************************************************/
NBEdge::Lane getFirstNonPedestrianLane(int direction) const
Definition: NBEdge.cpp:2468
bool gDebugFlag1
global utility flags for debugging
Definition: StdDefs.cpp:91
std::string id
Definition: NBEdge.h:181
void invalidateConnections(bool reallowSetting=false)
Definition: NBEdge.cpp:949
int tlLinkNo
The index of this connection within the controlling traffic light.
Definition: NBEdge.h:170
The link is a partial left direction.
const PositionVector & getLaneShape(unsigned int i) const
Returns the shape of the nth lane.
Definition: NBEdge.cpp:541
std::vector< Lane > myLanes
Lane information.
Definition: NBEdge.h:1317
bool includes(Direction d) const
Definition: NBEdge.cpp:165
PositionVector cutAtIntersection(const PositionVector &old) const
cut shape at the intersection shapes
Definition: NBEdge.cpp:450
bool hasConnectionTo(NBEdge *destEdge, unsigned int destLane, int fromLane=-1) const
Retrieves info about a connection to a certain lane of a certain edge.
Definition: NBEdge.cpp:812
const EdgeVector & getIncomingEdges() const
Returns this node&#39;s incoming edges.
Definition: NBNode.h:240
const std::string & getTypeID() const
Definition: NBEdge.h:907
bool setControllingTLInformation(const NBConnection &c, const std::string &tlID)
Returns if the link could be set as to be controlled.
Definition: NBEdge.cpp:1931
void divideOnEdges(const EdgeVector *outgoing)
Definition: NBEdge.cpp:1614
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:148
int toLane
The lane the connections yields in.
Definition: NBEdge.h:166
static const SUMOReal UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:201
SUMOReal width
This lane&#39;s width.
Definition: NBNode.h:143
SUMOReal myTotalAngle
Definition: NBEdge.h:1274
SUMOReal distance(const Position &p, bool perpendicular=false) const
std::string foeIncomingLanes
Definition: NBEdge.h:191
const SUMOReal SUMO_const_laneWidth
Definition: StdDefs.h:49
is a pedestrian
int getTLIndex() const
Definition: NBConnection.h:101
SUMOReal myEndOffset
This edges&#39;s offset to the intersection begin (will be applied to all lanes)
Definition: NBEdge.h:1309
std::vector< TLSDisabledConnection > myTLSDisabledConnections
Definition: NBEdge.h:1334
~NBEdge()
Destructor.
Definition: NBEdge.cpp:387
static const SUMOReal UNSPECIFIED_SIGNAL_OFFSET
unspecified signal offset
Definition: NBEdge.h:212
LaneSpreadFunction myLaneSpreadFunction
The information about how to spread the lanes.
Definition: NBEdge.h:1306
PositionVector getSubpart2D(SUMOReal beginOffset, SUMOReal endOffset) const
SUMOReal viaVmax
Definition: NBEdge.h:187
void sortOutgoingConnectionsByAngle()
sorts the outgoing connections by their angle relative to their junction
Definition: NBEdge.cpp:894
std::string viaID
Definition: NBEdge.h:186
NBEdge * toEdge
The edge the connections yields in.
Definition: NBEdge.h:164
bool hasDefaultGeometry() const
Returns whether the geometry consists only of the node positions.
Definition: NBEdge.cpp:423
void shiftTLConnectionLaneIndex(NBEdge *edge, int offset)
patches loaded signal plans by modifying lane indices
Definition: NBNode.cpp:373
void mirrorX()
mirror coordinates along the x-axis
Definition: NBEdge.cpp:402
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types...
NBNode * myTo
Definition: NBEdge.h:1266
The relationships between edges are computed/loaded.
Definition: NBEdge.h:94
bool empty() const
Definition: NBEdge.cpp:159
#define M_PI
Definition: angles.h:37
bool hasLaneSpecificEndOffset() const
whether lanes differ in offset
Definition: NBEdge.cpp:1465
void setLaneWidth(int lane, SUMOReal width)
set lane specific width (negative lane implies set for all lanes)
Definition: NBEdge.cpp:2294
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition: NBNode.h:304
void setSpeed(int lane, SUMOReal speed)
set lane specific speed (negative lane implies set for all lanes)
Definition: NBEdge.cpp:2349
Some static methods for string processing.
Definition: StringUtils.h:45
void moveOutgoingConnectionsFrom(NBEdge *e, unsigned int laneOff)
Definition: NBEdge.cpp:1894
const SUMOReal SUMO_const_laneWidthAndOffset
Definition: StdDefs.h:53
void addSidewalk(SUMOReal width)
add a pedestrian sidewalk of the given width and shift existing connctions
Definition: NBEdge.cpp:2478
void removeEdge(NBEdge *edge, bool removeFromConnections=true)
Removes edge from this node and optionally removes connections as well.
Definition: NBNode.cpp:1213
vehicle is a bicycle
void addIncomingEdge(NBEdge *edge)
adds an incoming edge
Definition: NBNode.cpp:424
int SVCPermissions
The representation of a single edge during network building.
Definition: NBEdge.h:70
void reinitNodes(NBNode *from, NBNode *to)
Resets nodes but keeps all other values the same (used when joining)
Definition: NBEdge.cpp:314
void clearControllingTLInformation()
clears tlID for all connections
Definition: NBEdge.cpp:1996
Lane2LaneInfoType
Modes of setting connections between lanes.
Definition: NBEdge.h:109
bool mayBeTLSControlled(int fromLane, NBEdge *toEdge, int toLane) const
Definition: NBEdge.cpp:1920
bool hasDefaultGeometryEndpoints() const
Returns whether the geometry is terminated by the node positions This default may be violated by init...
Definition: NBEdge.cpp:429
The link is a 180 degree turn.
Position getCentroid() const
Returns the centroid (closes the polygon if unclosed)
int getFromLane() const
returns the from-lane
void incLaneNo(unsigned int by)
Definition: NBEdge.cpp:2210
PositionVector getCCWBoundaryLine(const NBNode &n) const
get the outer boundary of this edge when going counter-clock-wise around the given node ...
Definition: NBEdge.cpp:2032
bool intersects(const Position &p1, const Position &p2) const
bool addLane2LaneConnection(unsigned int fromLane, NBEdge *dest, unsigned int toLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, bool keepClear=true, SUMOReal contPos=UNSPECIFIED_CONTPOS)
Adds a connection between the specified this edge&#39;s lane and an approached one.
Definition: NBEdge.cpp:684
const std::vector< Crossing > & getCrossings() const
return this junctions pedestrian crossings
Definition: NBNode.h:640
bool addLane2LaneConnections(unsigned int fromLane, NBEdge *dest, unsigned int toLane, unsigned int no, Lane2LaneInfoType type, bool invalidatePrevious=false, bool mayDefinitelyPass=false)
Builds no connections starting at the given lanes.
Definition: NBEdge.cpp:707
static const SUMOReal UNSPECIFIED_SPEED
unspecified lane speed
Definition: NBEdge.h:205
void buildInnerEdges(const NBNode &n, unsigned int noInternalNoSplits, unsigned int &linkIndex, unsigned int &splitIndex)
Definition: NBEdge.cpp:1074
void markAsInLane2LaneState()
Definition: NBEdge.cpp:2248
SUMOReal getTotalWidth() const
Returns the combined width of all lanes of this edge.
Definition: NBEdge.cpp:2318
Lanes to lanes - relationships are computed; should be recheked.
Definition: NBEdge.h:98
SUMOReal getLaneWidth() const
Returns the default width of lanes of this edge.
Definition: NBEdge.h:449
std::string getLaneIDInsecure(unsigned int lane) const
Definition: NBEdge.cpp:2172
void setPermissions(SVCPermissions permissions, int lane=-1)
set allowed/disallowed classes for the given lane or for all lanes if -1 is given ...
Definition: NBEdge.cpp:2365
PositionVector shape
The lane&#39;s shape.
Definition: NBNode.h:141
int myFromJunctionPriority
The priority normalised for the node the edge is outgoing of.
Definition: NBEdge.h:1297
void computeLaneShapes()
Definition: NBEdge.cpp:1329
PositionVector getSubpartByIndex(int beginIndex, int count) const
PositionVector myGeom
The geometry for the edge.
Definition: NBEdge.h:1303
bool isForbidden(SVCPermissions permissions)
Returns whether an edge with the given permission is a forbidden edge.
void remapConnections(const EdgeVector &incoming)
Remaps the connection in a way that allows the removal of it.
Definition: NBEdge.cpp:906
#define RAD2DEG(x)
Definition: GeomHelper.h:46
SUMOReal distanceTo(const Position &p2) const
returns the euclidean distance in 3 dimension
Definition: Position.h:221
static const SUMOReal UNSPECIFIED_CONTPOS
unspecified internal junction position
Definition: NBEdge.h:207
const SUMOReal SUMO_const_laneOffset
Definition: StdDefs.h:52
bool around(const Position &p, SUMOReal offset=0) const
Returns the information whether the position vector describes a polygon lying around the given point ...
bool setConnection(unsigned int lane, NBEdge *destEdge, unsigned int destLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, bool keepClear=true, SUMOReal contPos=UNSPECIFIED_CONTPOS)
Adds a connection to a certain lane of a certain edge.
Definition: NBEdge.cpp:724
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permission is a railway edge.
const SVCPermissions SVCAll
static const SUMOReal UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:203
SUMOReal beginEndAngle() const
returns the angle in radians of the line connecting the first and the last position ...
static SUMOReal angleDiff(const SUMOReal angle1, const SUMOReal angle2)
Returns the difference of the second angle to the first angle in radiants.
Definition: GeomHelper.cpp:178
std::vector< Connection > getConnectionsFromLane(unsigned int lane) const
Returns connections from a given lane.
Definition: NBEdge.cpp:785
SUMOReal x() const
Returns the x-position.
Definition: Position.h:63
void addOutgoingEdge(NBEdge *edge)
adds an outgoing edge
Definition: NBNode.cpp:434
Position positionAtOffset2D(SUMOReal pos, SUMOReal lateralOffset=0) const
Returns the position at the given length.
void setGeometry(const PositionVector &g, bool inner=false)
(Re)sets the edge&#39;s geometry
Definition: NBEdge.cpp:436
static SUMOReal firstIntersection(const PositionVector &v1, const PositionVector &v2, SUMOReal width2)
Definition: NBEdge.cpp:1241
The link is a (hard) left direction.
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
The connection was computed and validated.
Definition: NBEdge.h:115
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:69
PositionVector startShapeAt(const PositionVector &laneShape, const NBNode *startNode) const
Definition: NBEdge.cpp:496
static bool rightTurnConflict(const NBEdge *from, const NBEdge *to, int fromLane, const NBEdge *prohibitorFrom, const NBEdge *prohibitorTo, int prohibitorFromLane, bool lefthand=false)
return whether the given laneToLane connection is a right turn which must yield to a bicycle crossing...
Definition: NBNode.cpp:1307
SUMOReal vmax
Definition: NBEdge.h:183
PositionVector reverse() const
The edge has been loaded, nothing is computed yet.
Definition: NBEdge.h:92
LinkDirection
The different directions a link between two lanes may take (or a stream between two edges)...
int myToJunctionPriority
The priority normalised for the node the edge is incoming in.
Definition: NBEdge.h:1300
EdgeVector getConnectedEdges() const
Returns the list of outgoing edges unsorted.
Definition: NBEdge.cpp:868
The link is a straight direction.
PositionVector shape
Definition: NBEdge.h:182
const EdgeVector & getOutgoingEdges() const
Returns this node&#39;s outgoing edges.
Definition: NBNode.h:248
void moveConnectionToRight(unsigned int lane)
Definition: NBEdge.cpp:1061
bool hasPermissions() const
whether at least one lane has restrictions
Definition: NBEdge.cpp:1418
SUMOReal getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn&#39;t set.
Definition: NBEdge.h:413
An (internal) definition of a single lane of an edge.
Definition: NBEdge.h:122
const std::string & getID() const
Returns the id.
Definition: Named.h:65
SUMOReal length2D() const
Returns the length.
SUMOReal mySpeed
The maximal speed.
Definition: NBEdge.h:1280
std::vector< SUMOReal > distances(const PositionVector &s, bool perpendicular=false) const
bool needsCont(const NBEdge *fromE, const NBEdge *otherFromE, const NBEdge::Connection &c, const NBEdge::Connection &otherC) const
whether an internal junction should be built at from and respect other
Definition: NBNode.cpp:600
bool addEdge2EdgeConnection(NBEdge *dest)
Adds a connection to another edge.
Definition: NBEdge.cpp:660
bool myAmMacroscopicConnector
Information whether this edge is a (macroscopic) connector.
Definition: NBEdge.h:1326
bool isConnectedTo(NBEdge *e)
Returns the information whethe a connection to the given edge has been added (or computed) ...
Definition: NBEdge.cpp:818
const PositionVector getInnerGeometry() const
Returns the geometry of the edge without the endpoints.
Definition: NBEdge.cpp:417
void push_front_noDoublePos(const Position &p)
void reshiftPosition(SUMOReal xoff, SUMOReal yoff)
Applies an offset to the edge.
Definition: NBEdge.cpp:392
const Position & getPosition() const
Returns the position of this node.
Definition: NBNode.h:228
void divideSelectedLanesOnEdges(const EdgeVector *outgoing, const std::vector< int > &availableLanes, const std::vector< unsigned int > *priorities)
Definition: NBEdge.cpp:1688
static unsigned int computePrioritySum(const std::vector< unsigned int > &priorities)
Definition: NBEdge.cpp:1829
bool computeLanes2Edges()
computes the edge, step2: computation of which lanes approach the edges)
Definition: NBEdge.cpp:1504
#define max(a, b)
Definition: polyfonts.c:65
NBEdge * myTurnDestination
The turn destination edge (if a connection exists)
Definition: NBEdge.h:1292
const std::map< NBEdge *, std::vector< unsigned int > > & getBuiltConnections() const
Definition: NBEdge.h:1126
Lanes to lanes - relationships are loaded; no recheck is necessary/wished.
Definition: NBEdge.h:102
Connection getConnection(int fromLane, const NBEdge *to, int toLane) const
Returns the specified connection This method goes through "myConnections" and returns the specified o...
Definition: NBEdge.cpp:797
int operator()(const Connection &c1, const Connection &c2) const
comparing operation
Definition: NBEdge.cpp:174
bool hasLaneSpecificSpeed() const
whether lanes differ in speed
Definition: NBEdge.cpp:1454
int getPriority() const
Returns the priority of the edge.
Definition: NBEdge.h:353
bool insert(NBEdge *edge, bool ignorePrunning=false)
Adds an edge to the dictionary.
Definition: NBEdgeCont.cpp:161
void checkGeometry(const SUMOReal maxAngle, const SUMOReal minRadius, bool fix)
Check the angles of successive geometry segments.
Definition: NBEdge.cpp:614
std::string getLaneID(unsigned int lane) const
Definition: NBEdge.cpp:2166
void moveConnectionToLeft(unsigned int lane)
Definition: NBEdge.cpp:1046
static SUMOReal legacyDegree(const SUMOReal angle, const bool positive=false)
Definition: GeomHelper.cpp:204
static const int FORWARD
edge directions (for pedestrian related stuff)
Definition: NBNode.h:183
void mirrorX()
mirror coordinates along the x-axis
std::string tlID
The id of the traffic light that controls this connection.
Definition: NBEdge.h:168
std::string getInternalLaneID() const
Definition: NBEdge.cpp:79
int fromLane
The lane the connections starts at.
Definition: NBEdge.h:162
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:46
A list of positions.
void add(SUMOReal xoff, SUMOReal yoff, SUMOReal zoff)
SUMOReal myEndAngle
Definition: NBEdge.h:1273
bool hasLaneSpecificPermissions() const
whether lanes differ in allowed vehicle classes
Definition: NBEdge.cpp:1429
bool lanesWereAssigned() const
Definition: NBEdge.cpp:1908
static bool connections_sorter(const Connection &c1, const Connection &c2)
Definition: NBEdge.cpp:2423
std::vector< unsigned int > foeInternalLinks
Definition: NBEdge.h:190
unsigned int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:345
SUMOReal z() const
Returns the z-position.
Definition: Position.h:73
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:265
NBEdge * myPossibleTurnDestination
The edge that would be the turn destination if there was one.
Definition: NBEdge.h:1294
PositionVector getCWBoundaryLine(const NBNode &n) const
get the outer boundary of this edge when going clock-wise around the given node
Definition: NBEdge.cpp:2014
bool hasLoadedLength() const
Returns whether a length was set explicitly.
Definition: NBEdge.h:423
bool canMoveConnection(const Connection &con, unsigned int newFromLane) const
whether the connection can originate on newFromLane
Definition: NBEdge.cpp:1037
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition: NBEdge.cpp:1867
SUMOReal contPos
custom position for internal junction on this connection
Definition: NBEdge.h:176
SUMOReal myLaneWidth
This width of this edge&#39;s lanes.
Definition: NBEdge.h:1312
int myPriority
The priority of the edge.
Definition: NBEdge.h:1277
int getFirstNonPedestrianLaneIndex(int direction, bool exclusive=false) const
return the first lane with permissions other than SVC_PEDESTRIAN and 0
Definition: NBEdge.cpp:2435
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:66
T MIN2(T a, T b)
Definition: StdDefs.h:69
bool needsLaneSpecificOutput() const
whether at least one lane has values differing from the edges values
Definition: NBEdge.cpp:1476
std::vector< std::string > & split(const std::string &s, char delim, std::vector< std::string > &elems)
The link is a (hard) right direction.
EdgeBuildingStep myStep
The building step.
Definition: NBEdge.h:1260
#define POSITION_EPS
Definition: config.h:187
#define DEG2RAD(x)
Definition: GeomHelper.h:45
SUMOReal getAngleAtNodeToCenter(const NBNode *const node) const
Returns the angle of from the node shape center to where the edge meets the node shape.
Definition: NBEdge.cpp:1299
LinkDirection getDirection(const NBEdge *const incoming, const NBEdge *const outgoing, bool leftHand=false) const
Returns the representation of the described stream&#39;s direction.
Definition: NBNode.cpp:1471
std::vector< Connection > myConnections
List of connections to following edges.
Definition: NBEdge.h:1285
void setLoadedLength(SUMOReal val)
Definition: NBEdge.cpp:2408
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:54
The connection was given by the user.
Definition: NBEdge.h:113
const PositionVector & getShape() const
retrieve the junction shape
Definition: NBNode.cpp:1638
SUMOReal getSignalOffset() const
Returns the offset of a traffic signal from the end of this edge.
Definition: NBEdge.h:489
void removeFromConnections(NBEdge *toEdge, int fromLane=-1, int toLane=-1, bool tryLater=false)
Removes the specified connection(s)
Definition: NBEdge.cpp:922
The link is a partial right direction.
static void compute(BresenhamCallBack *callBack, const unsigned int val1, const unsigned int val2)
Definition: Bresenham.cpp:45
SUMOReal getEndOffset() const
Returns the offset to the destination node.
Definition: NBEdge.h:478
vehicle is a passenger car (a "normal" car)
bool myAmInnerEdge
Information whether this is a junction-inner edge.
Definition: NBEdge.h:1323
bool isLeftMover(const NBEdge *const from, const NBEdge *const to) const
Computes whether the given connection is a left mover across the junction.
Definition: NBNode.cpp:1354
Base class for objects which have an id.
Definition: Named.h:45
bool recheckLanes()
Definition: NBEdge.cpp:1528
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
Definition: NBEdge.cpp:1267
SUMOReal myLoadedLength
An optional length to use (-1 if not valid)
Definition: NBEdge.h:1320
std::pair< PositionVector, PositionVector > splitAt(SUMOReal where) const
Returns the two lists made when this list vector is splitted at the given point.
static std::string convertUmlaute(std::string str)
Converts german "Umlaute" to their latin-version.
Definition: StringUtils.cpp:95
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:206
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition: NBEdge.cpp:2393
SUMOReal getCrossingAngle(NBNode *node)
return the angle for computing pedestrian crossings at the given node
Definition: NBEdge.cpp:2452
SUMOReal length() const
Returns the length.
vehicle is a bus
void addRestrictedLane(SUMOReal width, SUMOVehicleClass vclass)
add a lane of the given width, restricted to the given class and shift existing connctions ...
Definition: NBEdge.cpp:2490
void setTurningDestination(NBEdge *e, bool onlyPossible=false)
Sets the turing destination at the given edge.
Definition: NBEdge.cpp:1314
static const int BACKWARD
Definition: NBNode.h:184
void addBikeLane(SUMOReal width)
add a bicycle lane of the given width and shift existing connctions
Definition: NBEdge.cpp:2484
void decLaneNo(unsigned int by)
Definition: NBEdge.cpp:2236
std::string myID
The name of the object.
Definition: Named.h:133
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:369
PositionVector computeInternalLaneShape(NBEdge *fromE, const NBEdge::Connection &con, int numPoints) const
Compute the shape for an internal lane.
Definition: NBNode.cpp:559
std::vector< int > getConnectionLanes(NBEdge *currentOutgoing) const
Returns the list of lanes that may be used to reach the given edge.
Definition: NBEdge.cpp:880
void removeDoublePoints(SUMOReal minDist=POSITION_EPS, bool assertLength=false)
Removes positions if too near.
void execute(const unsigned int lane, const unsigned int virtEdge)
executes a bresenham - step
Definition: NBEdge.cpp:87
void computeEdgeShape()
Recomputeds the lane shapes to terminate at the node shape For every lane the intersection with the f...
Definition: NBEdge.cpp:480
void disableConnection4TLS(int fromLane, NBEdge *toEdge, int toLane)
Definition: NBEdge.cpp:2004
PositionVector viaShape
Definition: NBEdge.h:188
SUMOReal angleAt2D(int pos) const
SUMOReal getMaxLaneOffset()
Definition: NBEdge.cpp:1914
static const SUMOReal UNSPECIFIED_LOADED_LENGTH
no length override given
Definition: NBEdge.h:210
void deleteLane(unsigned int index, bool recompute=true)
Definition: NBEdge.cpp:2221
std::vector< NBEdge * > EdgeVector
Definition: NBCont.h:41
std::vector< unsigned int > * prepareEdgePriorities(const EdgeVector *outgoing)
Definition: NBEdge.cpp:1783
SUMOReal myLength
The length of the edge.
Definition: NBEdge.h:1269
void setPreferredVehicleClass(SVCPermissions permissions, int lane=-1)
Definition: NBEdge.cpp:2379
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:523
The edge has been loaded and connections shall not be added.
Definition: NBEdge.h:90
int getToLane() const
returns the to-lane
SUMOReal y() const
Returns the y-position.
Definition: Position.h:68
std::vector< Connection > myConnectionsToDelete
List of connections marked for delayed removal.
Definition: NBEdge.h:1289
PositionVector computeLaneShape(unsigned int lane, SUMOReal offset) const
Computes the shape for the given lane.
Definition: NBEdge.cpp:1372
void reduceGeometry(const SUMOReal minDist)
Removes points with a distance lesser than the given.
Definition: NBEdge.cpp:608
void setJunctionPriority(const NBNode *const node, int prio)
Sets the junction priority of the edge.
Definition: NBEdge.cpp:1277
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
Definition: NBNodeCont.cpp:80
void replaceInConnections(NBEdge *which, NBEdge *by, unsigned int laneOff)
Definition: NBEdge.cpp:961
const EdgeVector * getConnectedSorted()
Returns the list of outgoing edges without the turnaround sorted in clockwise direction.
Definition: NBEdge.cpp:831
void sortOutgoingConnectionsByIndex()
sorts the outgoing connections by their from-lane-index and their to-lane-index
Definition: NBEdge.cpp:900
SUMOReal mySignalOffset
the offset of a traffic light signal from the end of this edge (-1 for None)
Definition: NBEdge.h:1345
std::string myType
The type of the edge.
Definition: NBEdge.h:1263
LaneSpreadFunction
Numbers representing special SUMO-XML-attribute values Information how the edge&#39;s lateral offset shal...
void append(NBEdge *continuation)
Definition: NBEdge.cpp:2121
NBEdge * getTo() const
returns the to-edge (end of the connection)
SUMOReal getLaneSpeed(unsigned int lane) const
Definition: NBEdge.cpp:1323
void shiftToLanesToEdge(NBEdge *to, unsigned int laneOff)
modifify the toLane for all connections to the given edge
Definition: NBEdge.cpp:2524
NBNode * tryGetNodeAtPosition(SUMOReal pos, SUMOReal tolerance=5.0) const
Returns the node at the given edges length (using an epsilon) When no node is existing at the given p...
Definition: NBEdge.cpp:1880
The connection was computed.
Definition: NBEdge.h:111
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge&#39;s lanes&#39; lateral offset is computed.
Definition: NBEdge.h:603
SUMOReal myStartAngle
The angles of the edge.
Definition: NBEdge.h:1272
EdgeVector edges
The edges being crossed.
Definition: NBNode.h:139
Represents a single node (junction) during network building.
Definition: NBNode.h:74
void dismissVehicleClassInformation()
Definition: NBEdge.cpp:2414
bool hasSignalisedConnectionTo(const NBEdge *const e) const
Definition: NBEdge.cpp:2146
Lanes to lanes - relationships are computed; no recheck is necessary/wished.
Definition: NBEdge.h:100
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:160
A definition of a pedestrian crossing.
Definition: NBNode.h:132
void move2side(SUMOReal amount)
bool hasLaneSpecificWidth() const
whether lanes differ in width
Definition: NBEdge.cpp:1443
void setEndOffset(int lane, SUMOReal offset)
set lane specific end-offset (negative lane implies set for all lanes)
Definition: NBEdge.cpp:2333
void appendTurnaround(bool noTLSControlled, bool checkPermissions)
Add a connection to the previously computed turnaround, if wished.
Definition: NBEdge.cpp:1839
Direction
enum of possible directions
Definition: NBEdge.h:1150
#define SUMOReal
Definition: config.h:213
bool isNearEnough2BeJoined2(NBEdge *e, SUMOReal threshold) const
Definition: NBEdge.cpp:2178
void preferVehicleClass(int lane, SUMOVehicleClass vclass)
Definition: NBEdge.cpp:2281
#define NUMERICAL_EPS
Definition: config.h:160
void push_back_noDoublePos(const Position &p)
void allowVehicleClass(int lane, SUMOVehicleClass vclass)
set allowed class for the given lane or for all lanes if -1 is given
Definition: NBEdge.cpp:2255
void addGeometryPoint(int index, const Position &p)
Adds a further geometry point.
Definition: NBEdge.cpp:553
void computeAngle()
computes the angle of this edge and stores it in myAngle
Definition: NBEdge.cpp:1384
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
Definition: NBNodeCont.cpp:109
SUMOReal getSpeed() const
Returns the speed allowed on this edge.
Definition: NBEdge.h:431
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:64
SUMOReal getFinalLength() const
length that will be assigned to the lanes in the final network
Definition: NBEdge.cpp:2560
bool computeEdge2Edges(bool noLeftMovers)
computes the edge (step1: computation of approached edges)
Definition: NBEdge.cpp:1483
static T maxValue(const std::vector< T > &v)
Definition: VectorHelper.h:98
unsigned int internalLaneIndex
The lane index of this internal lane within the internal edge.
Definition: NBEdge.h:194
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
bool foes(const NBEdge *const from1, const NBEdge *const to1, const NBEdge *const from2, const NBEdge *const to2) const
Returns the information whether the given flows cross.
Definition: NBNode.cpp:1383
void setLaneSpreadFunction(LaneSpreadFunction spread)
(Re)sets how the lanes lateral offset shall be computed
Definition: NBEdge.cpp:547
NBEdge(const std::string &id, NBNode *from, NBNode *to, std::string type, SUMOReal speed, unsigned int nolanes, int priority, SUMOReal width, SUMOReal offset, const std::string &streetName="", LaneSpreadFunction spread=LANESPREAD_RIGHT)
Constructor.
Definition: NBEdge.cpp:185
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:201
std::vector< SUMOReal > intersectsAtLengths2D(const PositionVector &other) const
For all intersections between this vector and other, return the 2D-length of the subvector from this ...
Lanes to edges - relationships are computed/loaded.
Definition: NBEdge.h:96
std::string myStreetName
The street name (or whatever arbitrary string you wish to attach)
Definition: NBEdge.h:1338
const std::string & getStreetName() const
Returns the street name of this edge.
Definition: NBEdge.h:465
void addLane(unsigned int index, bool recompute=true)
Definition: NBEdge.cpp:2186
NBNode * myFrom
The source and the destination node.
Definition: NBEdge.h:1266
bool expandableBy(NBEdge *possContinuation) const
Definition: NBEdge.cpp:2050
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition: NBEdge.cpp:2157
void init(unsigned int noLanes, bool tryIgnoreNodePositions, const std::string &origID)
Initialization routines common to all constructors.
Definition: NBEdge.cpp:334
PositionVector getSubpart(SUMOReal beginOffset, SUMOReal endOffset) const
~MainDirections()
destructor
Definition: NBEdge.cpp:155
void shiftPositionAtNode(NBNode *node, NBEdge *opposite)
shift geometry at the given node to avoid overlap
Definition: NBEdge.cpp:2535
void disallowVehicleClass(int lane, SUMOVehicleClass vclass)
set disallowed class for the given lane or for all lanes if -1 is given
Definition: NBEdge.cpp:2268
SUMOReal angleTo2D(const Position &other) const
returns the angle in the plane of the vector pointing from here to the other position ...
Definition: Position.h:243
void append(const PositionVector &v, SUMOReal sameThreshold=2.0)
MainDirections(const EdgeVector &outgoing, NBEdge *parent, NBNode *to)
constructor
Definition: NBEdge.cpp:118
void extrapolate(const SUMOReal val, const bool onlyFirst=false)
void copyConnectionsFrom(NBEdge *src)
Definition: NBEdge.cpp:1030
void reinit(NBNode *from, NBNode *to, const std::string &type, SUMOReal speed, unsigned int nolanes, int priority, PositionVector geom, SUMOReal width, SUMOReal offset, const std::string &streetName, LaneSpreadFunction spread=LANESPREAD_RIGHT, bool tryIgnoreNodePositions=false)
Resets initial values.
Definition: NBEdge.cpp:266
static const SUMOReal ANGLE_LOOKAHEAD
the distance at which to take the default angle
Definition: NBEdge.h:214
SUMOReal getLength() const
Returns the computed length of the edge.
Definition: NBEdge.h:404
SUMOReal getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge&#39;s geometry at the given node.
Definition: NBEdge.cpp:1287
bool forbids(const NBEdge *const possProhibitorFrom, const NBEdge *const possProhibitorTo, const NBEdge *const possProhibitedFrom, const NBEdge *const possProhibitedTo, bool regardNonSignalisedLowerPriority) const
Returns the information whether "prohibited" flow must let "prohibitor" flow pass.
Definition: NBNode.cpp:1373
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:361
bool splitGeometry(NBEdgeCont &ec, NBNodeCont &nc)
Splits this edge at geometry points.
Definition: NBEdge.cpp:563