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-2017 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 "NBEdgeCont.h"
39 #include "NBNode.h"
40 #include "NBNodeCont.h"
41 #include "NBContHelper.h"
42 #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 DEBUG_CONNECTION_GUESSING
62 #define DEBUGCOND true
63 
64 // ===========================================================================
65 // static members
66 // ===========================================================================
72 
77 
78 // ===========================================================================
79 // method definitions
80 // ===========================================================================
81 std::string
83  return id + "_" + toString(internalLaneIndex);
84 }
85 
86 
87 std::string
89  return Named::getIDSecure(parent) + "_" + toString(fromLane) + "->" + Named::getIDSecure(toEdge) + "_" + toString(toLane);
90 }
91 
92 
93 NBEdge::Connection::Connection(int fromLane_, NBEdge* toEdge_, int toLane_) :
94  fromLane(fromLane_),
95  toEdge(toEdge_),
96  toLane(toLane_),
97  mayDefinitelyPass(false),
98  keepClear(true),
101  id(toEdge_ == 0 ? "" : toEdge->getFromNode()->getID()),
102  haveVia(false),
104 
105 {}
106 
107 
108 NBEdge::Connection::Connection(int fromLane_, NBEdge* toEdge_, int toLane_, bool mayDefinitelyPass_, bool keepClear_, SUMOReal contPos_, SUMOReal visibility_, bool haveVia_) :
109  fromLane(fromLane_),
110  toEdge(toEdge_),
111  toLane(toLane_),
112  mayDefinitelyPass(mayDefinitelyPass_),
113  keepClear(keepClear_),
114  contPos(contPos_),
115  visibility(visibility_),
116  id(toEdge_ == 0 ? "" : toEdge->getFromNode()->getID()),
117  haveVia(haveVia_),
119 }
120 
121 NBEdge::Lane::Lane(NBEdge* e, const std::string& origID_) :
122  speed(e->getSpeed()),
123  permissions(SVCAll),
124  preferred(0),
125  endOffset(e->getEndOffset()), width(e->getLaneWidth()),
126  origID(origID_) {
127 }
128 
129 
130 /* -------------------------------------------------------------------------
131  * NBEdge::ToEdgeConnectionsAdder-methods
132  * ----------------------------------------------------------------------- */
133 void
134 NBEdge::ToEdgeConnectionsAdder::execute(const int lane, const int virtEdge) {
135  // check
136  assert((int)myTransitions.size() > virtEdge);
137  // get the approached edge
138  NBEdge* succEdge = myTransitions[virtEdge];
139  std::vector<int> lanes;
140 
141  // check whether the currently regarded, approached edge has already
142  // a connection starting at the edge which is currently being build
143  std::map<NBEdge*, std::vector<int> >::iterator i = myConnections.find(succEdge);
144  if (i != myConnections.end()) {
145  // if there were already lanes assigned, get them
146  lanes = (*i).second;
147  }
148 
149  // check whether the current lane was already used to connect the currently
150  // regarded approached edge
151  std::vector<int>::iterator j = find(lanes.begin(), lanes.end(), lane);
152  if (j == lanes.end()) {
153  // if not, add it to the list
154  lanes.push_back(lane);
155  }
156  // set information about connecting lanes
157  myConnections[succEdge] = lanes;
158 }
159 
160 
161 
162 /* -------------------------------------------------------------------------
163  * NBEdge::MainDirections-methods
164  * ----------------------------------------------------------------------- */
166  NBEdge* parent, NBNode* to, int indexOfStraightest) {
167  if (outgoing.size() == 0) {
168  return;
169  }
170  // check whether the right turn has a higher priority
171  assert(outgoing.size() > 0);
172  const LinkDirection straightestDir = to->getDirection(parent, outgoing[indexOfStraightest]);
173 #ifdef DEBUG_CONNECTION_GUESSING
174  if (DEBUGCOND) {
175  std::cout << " MainDirections edge=" << parent->getID() << " straightest=" << outgoing[indexOfStraightest]->getID() << " dir=" << toString(straightestDir) << "\n";
176  }
177 #endif
178  if (NBNode::isTrafficLight(to->getType()) &&
179  (straightestDir == LINKDIR_STRAIGHT || straightestDir == LINKDIR_PARTLEFT || straightestDir == LINKDIR_PARTRIGHT)) {
180  myDirs.push_back(MainDirections::DIR_FORWARD);
181  return;
182  }
183  if (outgoing[0]->getJunctionPriority(to) == 1) {
184  myDirs.push_back(MainDirections::DIR_RIGHTMOST);
185  }
186  // check whether the left turn has a higher priority
187  if (outgoing.back()->getJunctionPriority(to) == 1) {
188  // ok, the left turn belongs to the higher priorised edges on the junction
189  // let's check, whether it has also a higher priority (lane number/speed)
190  // than the current
191  EdgeVector tmp(outgoing);
192  sort(tmp.begin(), tmp.end(), NBContHelper::edge_similar_direction_sorter(parent));
193  if (outgoing.back()->getPriority() > tmp[0]->getPriority()) {
194  myDirs.push_back(MainDirections::DIR_LEFTMOST);
195  } else {
196  if (outgoing.back()->getNumLanes() > tmp[0]->getNumLanes()) {
197  myDirs.push_back(MainDirections::DIR_LEFTMOST);
198  }
199  }
200  }
201  // check whether the forward direction has a higher priority
202  // try to get the forward direction
203  EdgeVector tmp(outgoing);
204  sort(tmp.begin(), tmp.end(), NBContHelper::edge_similar_direction_sorter(parent));
205  NBEdge* edge = *(tmp.begin());
206  // check whether it has a higher priority and is going straight
207  if (edge->getJunctionPriority(to) == 1 && to->getDirection(parent, edge) == LINKDIR_STRAIGHT) {
208  myDirs.push_back(MainDirections::DIR_FORWARD);
209  }
210 }
211 
212 
214 
215 
216 bool
218  return myDirs.empty();
219 }
220 
221 
222 bool
224  return find(myDirs.begin(), myDirs.end(), d) != myDirs.end();
225 }
226 
227 
228 /* -------------------------------------------------------------------------
229  * NBEdge::connections_relative_edgelane_sorter-methods
230  * ----------------------------------------------------------------------- */
231 int
233  if (c1.toEdge != c2.toEdge) {
235  }
236  return c1.toLane < c2.toLane;
237 }
238 
239 
240 /* -------------------------------------------------------------------------
241  * NBEdge-methods
242  * ----------------------------------------------------------------------- */
243 NBEdge::NBEdge(const std::string& id, NBNode* from, NBNode* to,
244  std::string type, SUMOReal speed, int nolanes,
245  int priority, SUMOReal laneWidth, SUMOReal offset,
246  const std::string& streetName,
247  LaneSpreadFunction spread) :
248  Named(StringUtils::convertUmlaute(id)),
249  myStep(INIT),
250  myType(StringUtils::convertUmlaute(type)),
251  myFrom(from), myTo(to),
253  myPriority(priority), mySpeed(speed),
257  myLaneSpreadFunction(spread), myEndOffset(offset), myLaneWidth(laneWidth),
260  myStreetName(streetName),
262  init(nolanes, false, id);
263 }
264 
265 
266 NBEdge::NBEdge(const std::string& id, NBNode* from, NBNode* to,
267  std::string type, SUMOReal speed, int nolanes,
268  int priority, SUMOReal laneWidth, SUMOReal offset,
269  PositionVector geom,
270  const std::string& streetName,
271  const std::string& origID,
272  LaneSpreadFunction spread, bool tryIgnoreNodePositions) :
273  Named(StringUtils::convertUmlaute(id)),
274  myStep(INIT),
275  myType(StringUtils::convertUmlaute(type)),
276  myFrom(from), myTo(to),
278  myPriority(priority), mySpeed(speed),
282  myGeom(geom), myLaneSpreadFunction(spread), myEndOffset(offset), myLaneWidth(laneWidth),
285  myStreetName(streetName),
287  init(nolanes, tryIgnoreNodePositions, origID);
288 }
289 
290 
291 NBEdge::NBEdge(const std::string& id, NBNode* from, NBNode* to, NBEdge* tpl, const PositionVector& geom, int numLanes) :
292  Named(StringUtils::convertUmlaute(id)),
293  myStep(INIT),
294  myType(tpl->getTypeID()),
295  myFrom(from), myTo(to),
297  myPriority(tpl->getPriority()), mySpeed(tpl->getSpeed()),
301  myGeom(geom),
303  myEndOffset(tpl->getEndOffset()),
304  myLaneWidth(tpl->getLaneWidth()),
306  myAmInnerEdge(false),
308  myStreetName(tpl->getStreetName()),
310  init(numLanes > 0 ? numLanes : tpl->getNumLanes(), myGeom.size() > 0, "");
311  for (int i = 0; i < getNumLanes(); i++) {
312  const int tplIndex = MIN2(i, tpl->getNumLanes() - 1);
313  setSpeed(i, tpl->getLaneSpeed(tplIndex));
314  setPermissions(tpl->getPermissions(tplIndex), i);
315  setLaneWidth(i, tpl->myLanes[tplIndex].width);
316  myLanes[i].origID = tpl->myLanes[tplIndex].origID;
317  if (to == tpl->myTo) {
318  setEndOffset(i, tpl->myLanes[tplIndex].endOffset);
319  }
320  }
321 }
322 
323 
324 void
325 NBEdge::reinit(NBNode* from, NBNode* to, const std::string& type,
326  SUMOReal speed, int nolanes, int priority,
327  PositionVector geom, SUMOReal laneWidth, SUMOReal offset,
328  const std::string& streetName,
329  LaneSpreadFunction spread,
330  bool tryIgnoreNodePositions) {
331  if (myFrom != from) {
332  myFrom->removeEdge(this, false);
333  }
334  if (myTo != to) {
335  myTo->removeEdge(this, false);
336  }
338  myFrom = from;
339  myTo = to;
340  myPriority = priority;
341  //?myTurnDestination(0),
342  //?myFromJunctionPriority(-1), myToJunctionPriority(-1),
343  myGeom = geom;
344  myLaneSpreadFunction = spread;
346  myStreetName = streetName;
347  //?, myAmTurningWithAngle(0), myAmTurningOf(0),
348  //?myAmInnerEdge(false), myAmMacroscopicConnector(false)
349 
350  // preserve lane-specific settings (geometry must be recomputed)
351  // if new lanes are added they copy the values from the leftmost lane (if specified)
352  const std::vector<Lane> oldLanes = myLanes;
353  init(nolanes, tryIgnoreNodePositions, oldLanes.empty() ? "" : oldLanes[0].origID);
354  for (int i = 0; i < (int)nolanes; ++i) {
355  PositionVector newShape = myLanes[i].shape;
356  myLanes[i] = oldLanes[MIN2(i, (int)oldLanes.size() - 1)];
357  myLanes[i].shape = newShape;
358  }
359  // however, if the new edge defaults are explicityly given, they override the old settings
360  if (offset != UNSPECIFIED_OFFSET) {
361  setEndOffset(-1, offset);
362  }
363  if (laneWidth != UNSPECIFIED_WIDTH) {
364  setLaneWidth(-1, laneWidth);
365  }
366  if (speed != UNSPECIFIED_SPEED) {
367  setSpeed(-1, speed);
368  }
369 }
370 
371 
372 void
374  // connections may still be valid
375  if (from == 0 || to == 0) {
376  throw ProcessError("At least one of edge's '" + myID + "' nodes is not known.");
377  }
378  if (myFrom != from) {
379  myFrom->removeEdge(this, false);
380  myFrom = from;
381  myFrom->addOutgoingEdge(this);
382  }
383  if (myTo != to) {
384  myTo->removeEdge(this, false);
385  myTo = to;
386  myTo->addIncomingEdge(this);
387  }
388  computeAngle();
389 }
390 
391 
392 void
393 NBEdge::init(int noLanes, bool tryIgnoreNodePositions, const std::string& origID) {
394  if (noLanes == 0) {
395  throw ProcessError("Edge '" + myID + "' needs at least one lane.");
396  }
397  if (myFrom == 0 || myTo == 0) {
398  throw ProcessError("At least one of edge's '" + myID + "' nodes is not known.");
399  }
400  // revisit geometry
401  // should have at least two points at the end...
402  // and in dome cases, the node positions must be added
404  if (!tryIgnoreNodePositions || myGeom.size() < 2) {
405  if (myGeom.size() == 0) {
406  myGeom.push_back(myFrom->getPosition());
407  myGeom.push_back(myTo->getPosition());
408  } else {
411  }
412  }
413  if (myGeom.size() < 2) {
414  myGeom.clear();
415  myGeom.push_back(myFrom->getPosition());
416  myGeom.push_back(myTo->getPosition());
417  }
418  if (myGeom.size() == 2 && myGeom[0] == myGeom[1]) {
419  WRITE_ERROR("Edge's '" + myID + "' from- and to-node are at the same position.");
421  }
422  //
423  myFrom->addOutgoingEdge(this);
424  myTo->addIncomingEdge(this);
425  // prepare container
427  assert(myGeom.size() >= 2);
428  if ((int)myLanes.size() > noLanes) {
429  // remove connections starting at the removed lanes
430  for (int lane = noLanes; lane < (int)myLanes.size(); ++lane) {
431  removeFromConnections(0, lane, -1);
432  }
433  // remove connections targeting the removed lanes
434  const EdgeVector& incoming = myFrom->getIncomingEdges();
435  for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
436  for (int lane = noLanes; lane < (int)myLanes.size(); ++lane) {
437  (*i)->removeFromConnections(this, -1, lane);
438  }
439  }
440  }
441  myLanes.clear();
442  for (int i = 0; i < noLanes; i++) {
443  myLanes.push_back(Lane(this, origID));
444  }
446  computeAngle();
447 }
448 
449 
451 
452 
453 // ----------- Applying offset
454 void
456  myGeom.add(xoff, yoff, 0);
457  for (int i = 0; i < (int)myLanes.size(); i++) {
458  myLanes[i].shape.add(xoff, yoff, 0);
459  }
460  computeAngle(); // update angles because they are numerically sensitive (especially where based on centroids)
461 }
462 
463 
464 void
466  myGeom.mirrorX();
467  for (int i = 0; i < (int)myLanes.size(); i++) {
468  myLanes[i].shape.mirrorX();
469  }
470  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
471  (*i).shape.mirrorX();
472  (*i).viaShape.mirrorX();
473  }
474  computeAngle(); // update angles because they are numerically sensitive (especially where based on centroids)
475 }
476 
477 
478 // ----------- Edge geometry access and computation
479 const PositionVector
481  return myGeom.getSubpartByIndex(1, (int)myGeom.size() - 2);
482 }
483 
484 
485 bool
487  return myGeom.size() == 2 && hasDefaultGeometryEndpoints();
488 }
489 
490 
491 bool
493  return myGeom.front() == myFrom->getPosition() &&
494  myGeom.back() == myTo->getPosition();
495 }
496 
497 
498 void
499 NBEdge::setGeometry(const PositionVector& s, bool inner) {
500  Position begin = myGeom.front(); // may differ from node position
501  Position end = myGeom.back(); // may differ from node position
502  myGeom = s;
503  if (inner) {
504  myGeom.insert(myGeom.begin(), begin);
505  myGeom.push_back(end);
506  }
508  computeAngle();
509 }
510 
511 void
512 NBEdge::setNodeBorder(const NBNode* node, const Position& p) {
513  const SUMOReal extend = 200;
514  const SUMOReal distanceOfClosestThreshold = 1.0; // very rough heuristic, actually depends on angle
515  SUMOReal distanceOfClosest = distanceOfClosestThreshold;
516  PositionVector border = myGeom.getOrthogonal(p, extend, distanceOfClosest);
517  if (distanceOfClosest < distanceOfClosestThreshold) {
518  // shift border forward / backward
519  const SUMOReal shiftDirection = (node == myFrom ? 1.0 : -1.0);
521  if (base != GeomHelper::INVALID_OFFSET) {
522  base += shiftDirection * (distanceOfClosestThreshold - distanceOfClosest);
523  PositionVector tmp = myGeom;
524  tmp.move2side(1.0);
525  border = myGeom.getOrthogonal(tmp.positionAtOffset2D(base), extend, distanceOfClosest);
526  }
527  }
528  if (border.size() == 2) {
529  SUMOReal edgeWidth = 0;
530  for (int i = 0; i < (int)myLanes.size(); i++) {
531  edgeWidth += getLaneWidth(i);
532  }
533  border.extrapolate2D(edgeWidth);
534  if (node == myFrom) {
535  myFromBorder = border;
536  } else {
537  assert(node == myTo);
538  myToBorder = border;
539  }
540  }
541 }
542 
543 
546  PositionVector shape = old;
547  shape = startShapeAt(shape, myFrom, myFromBorder);
548  if (shape.size() < 2) {
549  // only keep the last snippet
550  const SUMOReal oldLength = old.length();
551  shape = old.getSubpart(oldLength - 2 * POSITION_EPS, oldLength);
552  }
553  shape = startShapeAt(shape.reverse(), myTo, myToBorder).reverse();
554  // sanity checks
555  if (shape.length() < POSITION_EPS) {
556  if (old.length() < 2 * POSITION_EPS) {
557  shape = old;
558  } else {
559  const SUMOReal midpoint = old.length() / 2;
560  // EPS*2 because otherwhise shape has only a single point
561  shape = old.getSubpart(midpoint - POSITION_EPS, midpoint + POSITION_EPS);
562  assert(shape.size() >= 2);
563  assert(shape.length() > 0);
564  }
565  } else {
566  // @note If the node shapes are overlapping we may get a shape which goes in the wrong direction
567  // in this case the result shape should shortened
568  if (DEG2RAD(135) < fabs(GeomHelper::angleDiff(shape.beginEndAngle(), old.beginEndAngle()))) {
569  // eliminate intermediate points
570  PositionVector tmp;
571  tmp.push_back(shape[0]);
572  tmp.push_back(shape[-1]);
573  // 3D geometry may be messed up since positions were extrapolated rather than interpolated due to cutting in the wrong direction
574  // make the edge level with one of the intersections (try to pick one that needs to be flat as well)
575  if (myTo->geometryLike()) {
576  tmp[0].setz(myFrom->getPosition().z());
577  tmp[1].setz(myFrom->getPosition().z());
578  } else {
579  tmp[0].setz(myTo->getPosition().z());
580  tmp[1].setz(myTo->getPosition().z());
581  }
582  shape = tmp;
583  if (tmp.length() < POSITION_EPS) {
584  // fall back to original shape
585  if (old.length() < 2 * POSITION_EPS) {
586  shape = old;
587  } else {
588  const SUMOReal midpoint = old.length() / 2;
589  // EPS*2 because otherwhise shape has only a single point
590  shape = old.getSubpart(midpoint - POSITION_EPS, midpoint + POSITION_EPS);
591  assert(shape.size() >= 2);
592  assert(shape.length() > 0);
593  }
594  } else {
595  const SUMOReal midpoint = shape.length() / 2;
596  // cut to size and reverse
597  shape = shape.getSubpart(midpoint - POSITION_EPS, midpoint + POSITION_EPS);
598  if (shape.length() < POSITION_EPS) {
599  assert(false);
600  // the shape has a sharp turn near the midpoint
601  }
602  shape = shape.reverse();
603  }
604  }
605  }
606  return shape;
607 }
608 
609 
610 void
612  for (int i = 0; i < (int)myLanes.size(); i++) {
613  myLanes[i].shape = cutAtIntersection(myLanes[i].shape);
614  }
615  // recompute edge's length as the average of lane lenghts
616  SUMOReal avgLength = 0;
617  for (int i = 0; i < (int)myLanes.size(); i++) {
618  assert(myLanes[i].shape.length() > 0);
619  avgLength += myLanes[i].shape.length();
620  }
621  myLength = avgLength / (SUMOReal) myLanes.size();
622  computeAngle(); // update angles using the finalized node and lane shapes
623 }
624 
625 
627 NBEdge::startShapeAt(const PositionVector& laneShape, const NBNode* startNode, PositionVector nodeShape) const {
628  if (nodeShape.size() == 0) {
629  nodeShape = startNode->getShape();
630  }
631  PositionVector lb(laneShape.begin(), laneShape.begin() + 2);
632  // this doesn't look reasonable @todo use lb.extrapolateFirstBy(100.0);
633  lb.extrapolate(100.0);
634  if (nodeShape.intersects(laneShape)) {
635  // shape intersects directly
636  std::vector<SUMOReal> pbv = laneShape.intersectsAtLengths2D(nodeShape);
637  assert(pbv.size() > 0);
638  // ensure that the subpart has at least two points
640  if (pb < 0) {
641  return laneShape;
642  }
643  PositionVector ns = laneShape.getSubpart2D(pb, laneShape.length2D());
644  //PositionVector ns = pb < (laneShape.length() - POSITION_EPS) ? laneShape.getSubpart2D(pb, laneShape.length()) : laneShape;
645  if (!startNode->geometryLike() || pb < 1) {
646  // make "real" intersections and small intersections flat
647  ns[0].setz(startNode->getPosition().z());
648  // cutting and patching z-coordinate may cause steep grades which should be smoothed
649  ns = ns.smoothedZFront(pb * 2);
650  }
651  assert(ns.size() >= 2);
652  return ns;
653  } else if (nodeShape.intersects(lb)) {
654  // extension of first segment intersects
655  std::vector<SUMOReal> pbv = lb.intersectsAtLengths2D(nodeShape);
656  assert(pbv.size() > 0);
658  assert(pb >= 0);
659  PositionVector result = laneShape.getSubpartByIndex(1, (int)laneShape.size() - 1);
660  Position np = PositionVector::positionAtOffset2D(lb[0], lb[1], pb);
661  if (!startNode->geometryLike()) {
662  // make "real" intersections flat
663  np.setz(startNode->getPosition().z());
664  }
665  result.push_front_noDoublePos(np);
666  return result;
667  //if (result.size() >= 2) {
668  // return result;
669  //} else {
670  // WRITE_WARNING(error + " (resulting shape is too short)");
671  // return laneShape;
672  //}
673  } else {
674  // could not find proper intersection. Probably the edge is very short
675  // and lies within nodeShape
676  // @todo enable warning WRITE_WARNING(error + " (laneShape lies within nodeShape)");
677  return laneShape;
678  }
679 }
680 
681 
682 const PositionVector&
683 NBEdge::getLaneShape(int i) const {
684  return myLanes[i].shape;
685 }
686 
687 
688 void
690  myLaneSpreadFunction = spread;
691 }
692 
693 
694 void
695 NBEdge::addGeometryPoint(int index, const Position& p) {
696  if (index >= 0) {
697  myGeom.insert(myGeom.begin() + index, p);
698  } else {
699  myGeom.insert(myGeom.end() + index, p);
700  }
701 }
702 
703 
704 bool
706  // check whether there any splits to perform
707  if (myGeom.size() < 3) {
708  return false;
709  }
710  // ok, split
711  NBNode* newFrom = myFrom;
712  NBNode* myLastNode = myTo;
713  NBNode* newTo = 0;
714  NBEdge* currentEdge = this;
715  for (int i = 1; i < (int) myGeom.size() - 1; i++) {
716  // build the node first
717  if (i != (int)myGeom.size() - 2) {
718  std::string nodename = myID + "_in_between#" + toString(i);
719  if (!nc.insert(nodename, myGeom[i])) {
720  throw ProcessError("Error on adding in-between node '" + nodename + "'.");
721  }
722  newTo = nc.retrieve(nodename);
723  } else {
724  newTo = myLastNode;
725  }
726  if (i == 1) {
727  currentEdge->myTo->removeEdge(this);
728  currentEdge->myTo = newTo;
729  newTo->addIncomingEdge(currentEdge);
730  } else {
731  std::string edgename = myID + "[" + toString(i - 1) + "]";
732  // @bug lane-specific width, speed, overall offset and restrictions are ignored
733  currentEdge = new NBEdge(edgename, newFrom, newTo, myType, mySpeed, (int) myLanes.size(),
735  if (!ec.insert(currentEdge, true)) {
736  throw ProcessError("Error on adding splitted edge '" + edgename + "'.");
737  }
738  }
739  newFrom = newTo;
740  }
741  myGeom.clear();
742  myGeom.push_back(myFrom->getPosition());
743  myGeom.push_back(myTo->getPosition());
744  myStep = INIT;
745  return true;
746 }
747 
748 
749 void
751  myGeom.removeDoublePoints(minDist, true);
752 }
753 
754 
755 void
756 NBEdge::checkGeometry(const SUMOReal maxAngle, const SUMOReal minRadius, bool fix) {
757  if (myGeom.size() < 3) {
758  return;
759  }
760  //std::cout << "checking geometry of " << getID() << " geometry = " << toString(myGeom) << "\n";
761  std::vector<SUMOReal> angles; // absolute segment angles
762  //std::cout << " absolute angles:";
763  for (int i = 0; i < (int)myGeom.size() - 1; ++i) {
764  angles.push_back(myGeom.angleAt2D(i));
765  //std::cout << " " << angles.back();
766  }
767  //std::cout << "\n relative angles: ";
768  for (int i = 0; i < (int)angles.size() - 1; ++i) {
769  const SUMOReal relAngle = fabs(GeomHelper::angleDiff(angles[i], angles[i + 1]));
770  //std::cout << relAngle << " ";
771  if (maxAngle > 0 && relAngle > maxAngle) {
772  WRITE_WARNING("Found angle of " + toString(RAD2DEG(relAngle)) + " degrees at edge '" + getID() + "', segment " + toString(i));
773  }
774  if (relAngle < DEG2RAD(1)) {
775  continue;
776  }
777  if (i == 0 || i == (int)angles.size() - 2) {
778  const bool start = i == 0;
779  const SUMOReal dist = (start ? myGeom[0].distanceTo2D(myGeom[1]) : myGeom[-2].distanceTo2D(myGeom[-1]));
780  const SUMOReal r = tan(0.5 * (M_PI - relAngle)) * dist;
781  //std::cout << (start ? " start" : " end") << " length=" << dist << " radius=" << r << " ";
782  if (minRadius > 0 && r < minRadius) {
783  if (fix) {
784  WRITE_MESSAGE("Removing sharp turn with radius " + toString(r) + " at the " +
785  (start ? "start" : "end") + " of edge '" + getID() + "'.");
786  myGeom.erase(myGeom.begin() + (start ? 1 : i + 1));
787  checkGeometry(maxAngle, minRadius, fix);
788  return;
789  } else {
790  WRITE_WARNING("Found sharp turn with radius " + toString(r) + " at the " +
791  (start ? "start" : "end") + " of edge '" + getID() + "'.");
792  }
793  }
794  }
795  }
796  //std::cout << "\n";
797 }
798 
799 
800 // ----------- Setting and getting connections
801 bool
804  return true;
805  }
806  // check whether the node was merged and now a connection between
807  // not matching edges is tried to be added
808  // This happens f.e. within the ptv VISSIM-example "Beijing"
809  if (dest != 0 && myTo != dest->myFrom) {
810  return false;
811  }
812  if (dest == 0) {
814  myConnections.push_back(Connection(-1, dest, -1));
815  } else if (find_if(myConnections.begin(), myConnections.end(), connections_toedge_finder(dest)) == myConnections.end()) {
816  myConnections.push_back(Connection(-1, dest, -1));
817  }
818  if (myStep < EDGE2EDGES) {
819  myStep = EDGE2EDGES;
820  }
821  return true;
822 }
823 
824 
825 bool
827  int toLane, Lane2LaneInfoType type,
828  bool mayUseSameDestination,
829  bool mayDefinitelyPass,
830  bool keepClear,
831  SUMOReal contPos,
832  SUMOReal visibility) {
834  return true;
835  }
836  // check whether the node was merged and now a connection between
837  // not matching edges is tried to be added
838  // This happens f.e. within the ptv VISSIM-example "Beijing"
839  if (myTo != dest->myFrom) {
840  return false;
841  }
842  if (!addEdge2EdgeConnection(dest)) {
843  return false;
844  }
845  return setConnection(from, dest, toLane, type, mayUseSameDestination, mayDefinitelyPass, keepClear, contPos, visibility);
846 }
847 
848 
849 bool
851  NBEdge* dest, int toLane,
852  int no, Lane2LaneInfoType type,
853  bool invalidatePrevious,
854  bool mayDefinitelyPass) {
855  if (invalidatePrevious) {
856  invalidateConnections(true);
857  }
858  bool ok = true;
859  for (int i = 0; i < no && ok; i++) {
860  ok &= addLane2LaneConnection(fromLane + i, dest, toLane + i, type, false, mayDefinitelyPass);
861  }
862  return ok;
863 }
864 
865 
866 bool
867 NBEdge::setConnection(int lane, NBEdge* destEdge,
868  int destLane, Lane2LaneInfoType type,
869  bool mayUseSameDestination,
870  bool mayDefinitelyPass,
871  bool keepClear,
872  SUMOReal contPos,
873  SUMOReal visibility) {
875  return false;
876  }
877  // some kind of a misbehaviour which may occure when the junction's outgoing
878  // edge priorities were not properly computed, what may happen due to
879  // an incomplete or not proper input
880  // what happens is that under some circumstances a single lane may set to
881  // be approached more than once by the one of our lanes.
882  // This must not be!
883  // we test whether it is the case and do nothing if so - the connection
884  // will be refused
885  //
886  if (!mayUseSameDestination && hasConnectionTo(destEdge, destLane)) {
887  return false;
888  }
889  if (find_if(myConnections.begin(), myConnections.end(), connections_finder(lane, destEdge, destLane)) != myConnections.end()) {
890  return true;
891  }
892  if ((int)myLanes.size() <= lane || destEdge->getNumLanes() <= (int)destLane) {
893  // problem might be corrigible in post-processing
894  WRITE_WARNING("Could not set connection from '" + getLaneIDInsecure(lane) + "' to '" + destEdge->getLaneIDInsecure(destLane) + "'.");
895  return false;
896  }
897  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end();) {
898  if ((*i).toEdge == destEdge && ((*i).fromLane == -1 || (*i).toLane == -1)) {
899  i = myConnections.erase(i);
900  } else {
901  ++i;
902  }
903  }
904  myConnections.push_back(Connection(lane, destEdge, destLane));
905  if (mayDefinitelyPass) {
906  myConnections.back().mayDefinitelyPass = true;
907  }
908  myConnections.back().keepClear = keepClear;
909  myConnections.back().contPos = contPos;
910  myConnections.back().visibility = visibility;
911  if (type == L2L_USER) {
913  } else {
914  // check whether we have to take another look at it later
915  if (type == L2L_COMPUTED) {
916  // yes, the connection was set using an algorithm which requires a recheck
918  } else {
919  // ok, let's only not recheck it if we did no add something that has to be recheked
920  if (myStep != LANES2LANES_RECHECK) {
922  }
923  }
924  }
925  return true;
926 }
927 
928 
929 void
931  myConnections.push_back(connection);
932 }
933 
934 
935 std::vector<NBEdge::Connection>
937  std::vector<NBEdge::Connection> ret;
938  for (std::vector<Connection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
939  if ((*i).fromLane == lane) {
940  ret.push_back(*i);
941  }
942  }
943  return ret;
944 }
945 
946 
948 NBEdge::getConnection(int fromLane, const NBEdge* to, int toLane) const {
949  for (std::vector<Connection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
950  if (
951  (*i).fromLane == fromLane
952  && (*i).toEdge == to
953  && (*i).toLane == toLane) {
954  return *i;
955  }
956  }
957  throw ProcessError("Connection from " + getID() + "_" + toString(fromLane)
958  + " to " + to->getID() + "_" + toString(toLane) + " not found");
959 }
960 
962 NBEdge::getConnectionRef(int fromLane, const NBEdge* to, int toLane) {
963  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
964  if (
965  (*i).fromLane == fromLane
966  && (*i).toEdge == to
967  && (*i).toLane == toLane) {
968  return *i;
969  }
970  }
971  throw ProcessError("Connection from " + getID() + "_" + toString(fromLane)
972  + " to " + to->getID() + "_" + toString(toLane) + " not found");
973 }
974 
975 
976 bool
977 NBEdge::hasConnectionTo(NBEdge* destEdge, int destLane, int fromLane) const {
978  return destEdge != 0 && find_if(myConnections.begin(), myConnections.end(), connections_toedgelane_finder(destEdge, destLane, fromLane)) != myConnections.end();
979 }
980 
981 
982 bool
983 NBEdge::isConnectedTo(const NBEdge* e) const {
984  if (e == myTurnDestination) {
985  return true;
986  }
987  return
988  find_if(myConnections.begin(), myConnections.end(), connections_toedge_finder(e))
989  !=
990  myConnections.end();
991 
992 }
993 
994 
995 const EdgeVector*
997  // check whether connections exist and if not, use edges from the node
998  EdgeVector outgoing;
999  if (myConnections.size() == 0) {
1000  outgoing = myTo->getOutgoingEdges();
1001  } else {
1002  for (std::vector<Connection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
1003  if (find(outgoing.begin(), outgoing.end(), (*i).toEdge) == outgoing.end()) {
1004  outgoing.push_back((*i).toEdge);
1005  }
1006  }
1007  }
1008  for (std::vector<Connection>::iterator it = myConnectionsToDelete.begin(); it != myConnectionsToDelete.end(); ++it) {
1009  if (it->fromLane < 0 && it->toLane < 0) {
1010  // found an edge that shall not be connected
1011  EdgeVector::iterator forbidden = find(outgoing.begin(), outgoing.end(), it->toEdge);
1012  if (forbidden != outgoing.end()) {
1013  outgoing.erase(forbidden);
1014  }
1015  }
1016  }
1017  // allocate the sorted container
1018  int size = (int) outgoing.size();
1019  EdgeVector* edges = new EdgeVector();
1020  edges->reserve(size);
1021  for (EdgeVector::const_iterator i = outgoing.begin(); i != outgoing.end(); i++) {
1022  NBEdge* outedge = *i;
1023  if (outedge != 0 && outedge != myTurnDestination) {
1024  edges->push_back(outedge);
1025  }
1026  }
1027  sort(edges->begin(), edges->end(), NBContHelper::relative_outgoing_edge_sorter(this));
1028  return edges;
1029 }
1030 
1031 
1032 EdgeVector
1034  EdgeVector ret;
1035  for (std::vector<Connection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
1036  if (find(ret.begin(), ret.end(), (*i).toEdge) == ret.end()) {
1037  ret.push_back((*i).toEdge);
1038  }
1039  }
1040  return ret;
1041 }
1042 
1043 
1044 EdgeVector
1046  EdgeVector ret;
1047  const EdgeVector& candidates = myFrom->getIncomingEdges();
1048  for (EdgeVector::const_iterator i = candidates.begin(); i != candidates.end(); i++) {
1049  if ((*i)->isConnectedTo(this)) {
1050  ret.push_back(*i);
1051  }
1052  }
1053  return ret;
1054 }
1055 
1056 
1057 std::vector<int>
1058 NBEdge::getConnectionLanes(NBEdge* currentOutgoing) const {
1059  std::vector<int> ret;
1060  if (currentOutgoing != myTurnDestination) {
1061  for (std::vector<Connection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
1062  if ((*i).toEdge == currentOutgoing) {
1063  ret.push_back((*i).fromLane);
1064  }
1065  }
1066  }
1067  return ret;
1068 }
1069 
1070 
1071 void
1074 }
1075 
1076 
1077 void
1079  sort(myConnections.begin(), myConnections.end(), connections_sorter);
1080 }
1081 
1082 
1083 void
1085  EdgeVector connected = getConnectedEdges();
1086  for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
1087  NBEdge* inc = *i;
1088  // We have to do this
1089  inc->myStep = EDGE2EDGES;
1090  // add all connections
1091  for (EdgeVector::iterator j = connected.begin(); j != connected.end(); j++) {
1092  inc->addEdge2EdgeConnection(*j);
1093  }
1094  inc->removeFromConnections(this);
1095  }
1096 }
1097 
1098 
1099 void
1100 NBEdge::removeFromConnections(NBEdge* toEdge, int fromLane, int toLane, bool tryLater) {
1101  // remove from "myConnections"
1102  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end();) {
1103  Connection& c = *i;
1104  if ((toEdge == 0 || c.toEdge == toEdge)
1105  && (fromLane < 0 || c.fromLane == fromLane)
1106  && (toLane < 0 || c.toLane == toLane)) {
1107  if (myTo->isTLControlled()) {
1108  std::set<NBTrafficLightDefinition*> tldefs = myTo->getControllingTLS();
1109  for (std::set<NBTrafficLightDefinition*>::iterator it = tldefs.begin(); it != tldefs.end(); it++) {
1110  (*it)->removeConnection(NBConnection(this, c.fromLane, c.toEdge, c.toLane));
1111  }
1112  }
1113  i = myConnections.erase(i);
1114  tryLater = false;
1115  } else {
1116  ++i;
1117  }
1118  }
1119  // check whether it was the turn destination
1120  if (myTurnDestination == toEdge && fromLane < 0) {
1121  myTurnDestination = 0;
1122  }
1123  if (myPossibleTurnDestination == toEdge && fromLane < 0) {
1125  }
1126  if (tryLater) {
1127  myConnectionsToDelete.push_back(Connection(fromLane, toEdge, toLane));
1128  }
1129 }
1130 
1131 
1132 bool
1134  // iterate over connections
1135  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end(); i++) {
1136  if (((*i).toEdge == connectionToRemove.toEdge) && ((*i).fromLane == connectionToRemove.fromLane) && ((*i).toLane == connectionToRemove.toLane)) {
1137  // remove connection
1138  myConnections.erase(i);
1139  return true;
1140  }
1141  }
1142  assert(false);
1143  return false;
1144 }
1145 
1146 
1147 void
1148 NBEdge::invalidateConnections(bool reallowSetting) {
1149  myTurnDestination = 0;
1150  myConnections.clear();
1151  if (reallowSetting) {
1152  myStep = INIT;
1153  } else {
1155  }
1156 }
1157 
1158 
1159 void
1160 NBEdge::replaceInConnections(NBEdge* which, NBEdge* by, int laneOff) {
1161  // replace in "_connectedEdges"
1162  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
1163  if ((*i).toEdge == which) {
1164  (*i).toEdge = by;
1165  (*i).toLane += laneOff;
1166  }
1167  }
1168  // check whether it was the turn destination
1169  if (myTurnDestination == which) {
1170  myTurnDestination = by;
1171  }
1172 }
1173 
1174 void
1175 NBEdge::replaceInConnections(NBEdge* which, const std::vector<NBEdge::Connection>& origConns) {
1176  std::map<int, int> laneMap;
1177  int minLane = -1;
1178  int maxLane = -1;
1179  // get lanes used to approach the edge to remap
1180  bool wasConnected = false;
1181  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
1182  if ((*i).toEdge != which) {
1183  continue;
1184  }
1185  wasConnected = true;
1186  if ((*i).fromLane != -1) {
1187  int fromLane = (*i).fromLane;
1188  laneMap[(*i).toLane] = fromLane;
1189  if (minLane == -1 || minLane > fromLane) {
1190  minLane = fromLane;
1191  }
1192  if (maxLane == -1 || maxLane < fromLane) {
1193  maxLane = fromLane;
1194  }
1195  }
1196  }
1197  if (!wasConnected) {
1198  return;
1199  }
1200  // remove the remapped edge from connections
1201  removeFromConnections(which);
1202  // add new connections
1203  std::vector<NBEdge::Connection> conns = origConns;
1204  for (std::vector<NBEdge::Connection>::iterator i = conns.begin(); i != conns.end(); ++i) {
1205  if ((*i).toEdge == which) {
1206  continue;
1207  }
1208  int fromLane = (*i).fromLane;
1209  int toUse = -1;
1210  if (laneMap.find(fromLane) == laneMap.end()) {
1211  if (fromLane >= 0 && fromLane <= minLane) {
1212  toUse = minLane;
1213  }
1214  if (fromLane >= 0 && fromLane >= maxLane) {
1215  toUse = maxLane;
1216  }
1217  } else {
1218  toUse = laneMap[fromLane];
1219  }
1220  if (toUse == -1) {
1221  toUse = 0;
1222  }
1223  setConnection(toUse, (*i).toEdge, (*i).toLane, L2L_COMPUTED, false, (*i).mayDefinitelyPass);
1224  }
1225 }
1226 
1227 
1228 void
1230  myStep = src->myStep;
1232 }
1233 
1234 
1235 bool
1236 NBEdge::canMoveConnection(const Connection& con, int newFromLane) const {
1237  // only allow using newFromLane if at least 1 vClass is permitted to use
1238  // this connection. If the connection shall be moved to a sidewalk, only create the connection if there is no walking area
1239  const SVCPermissions common = (getPermissions(newFromLane) & con.toEdge->getPermissions(con.toLane));
1240  return (common > 0 && common != SVC_PEDESTRIAN);
1241 }
1242 
1243 
1244 void
1246  int index = 0;
1247  for (int i = 0; i < (int)myConnections.size(); ++i) {
1248  if (myConnections[i].fromLane == (int)(lane) && canMoveConnection(myConnections[i], lane + 1)) {
1249  index = i;
1250  }
1251  }
1252  std::vector<Connection>::iterator i = myConnections.begin() + index;
1253  Connection c = *i;
1254  myConnections.erase(i);
1255  setConnection(lane + 1, c.toEdge, c.toLane, L2L_VALIDATED, false);
1256 }
1257 
1258 
1259 void
1261  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
1262  if ((*i).fromLane == (int)lane && canMoveConnection(*i, lane - 1)) {
1263  Connection c = *i;
1264  i = myConnections.erase(i);
1265  setConnection(lane - 1, c.toEdge, c.toLane, L2L_VALIDATED, false);
1266  return;
1267  }
1268  }
1269 }
1270 
1271 
1272 void
1273 NBEdge::buildInnerEdges(const NBNode& n, int noInternalNoSplits, int& linkIndex, int& splitIndex) {
1274  const int numPoints = OptionsCont::getOptions().getInt("junctions.internal-link-detail");
1275  std::string innerID = ":" + n.getID();
1276  NBEdge* toEdge = 0;
1277  int edgeIndex = linkIndex;
1278  int internalLaneIndex = 0;
1279  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
1280  Connection& con = *i;
1281  con.haveVia = false; // reset first since this may be called multiple times
1282  if (con.toEdge == 0) {
1283  continue;
1284  }
1285  if (con.toEdge != toEdge) {
1286  // skip indices to keep some correspondence between edge ids and link indices:
1287  // internalEdgeIndex + internalLaneIndex = linkIndex
1288  edgeIndex = linkIndex;
1289  toEdge = (*i).toEdge;
1290  internalLaneIndex = 0;
1291  }
1292  PositionVector shape = n.computeInternalLaneShape(this, con, numPoints, myTo);
1293  std::vector<int> foeInternalLinks;
1294 
1295  LinkDirection dir = n.getDirection(this, con.toEdge);
1296  const bool isRightTurn = (dir == LINKDIR_RIGHT || dir == LINKDIR_PARTRIGHT);
1297  const bool isTurn = (isRightTurn || dir == LINKDIR_LEFT || dir == LINKDIR_PARTLEFT);
1298  if (dir != LINKDIR_STRAIGHT && shape.length() < POSITION_EPS) {
1299  WRITE_WARNING("Connection '" + getID() + "_" + toString(con.fromLane) + "->" + con.toEdge->getID() + "_" + toString(con.toLane) + "' is only " + toString(shape.length()) + " short.");
1300  }
1301 
1302  // crossingPosition, list of foe link indices
1303  std::pair<SUMOReal, std::vector<int> > crossingPositions(-1, std::vector<int>());
1304  std::set<std::string> tmpFoeIncomingLanes;
1305  switch (dir) {
1306  case LINKDIR_RIGHT:
1307  case LINKDIR_PARTRIGHT:
1308  case LINKDIR_LEFT:
1309  case LINKDIR_PARTLEFT:
1310  case LINKDIR_TURN: {
1311  int index = 0;
1312  const std::vector<NBEdge*>& incoming = n.getIncomingEdges();
1313  for (EdgeVector::const_iterator i2 = incoming.begin(); i2 != incoming.end(); ++i2) {
1314  const std::vector<Connection>& elv = (*i2)->getConnections();
1315  for (std::vector<NBEdge::Connection>::const_iterator k2 = elv.begin(); k2 != elv.end(); k2++) {
1316  if ((*k2).toEdge == 0) {
1317  continue;
1318  }
1319  bool needsCont = n.needsCont(this, *i2, con, *k2);
1320  // compute the crossing point
1321  if (needsCont) {
1322  crossingPositions.second.push_back(index);
1323  const PositionVector otherShape = n.computeInternalLaneShape(*i2, *k2, numPoints);
1324  // vehicles are typically less wide than the lane
1325  // they drive on but but bicycle lanes should be kept clear for their whole width
1326  SUMOReal width2 = (*k2).toEdge->getLaneWidth((*k2).toLane);
1327  if ((*k2).toEdge->getPermissions((*k2).toLane) != SVC_BICYCLE) {
1328  width2 *= 0.5;
1329  }
1330  const SUMOReal minDV = firstIntersection(shape, otherShape, width2);
1331  if (minDV < shape.length() - POSITION_EPS && minDV > POSITION_EPS) { // !!!?
1332  assert(minDV >= 0);
1333  if (crossingPositions.first < 0 || crossingPositions.first > minDV) {
1334  crossingPositions.first = minDV;
1335  }
1336  }
1337  }
1338  const bool rightTurnConflict = NBNode::rightTurnConflict(
1339  this, con.toEdge, con.fromLane, (*i2), (*k2).toEdge, (*k2).fromLane);
1340  // compute foe internal lanes
1341  if (n.foes(this, con.toEdge, *i2, (*k2).toEdge) || rightTurnConflict) {
1342  foeInternalLinks.push_back(index);
1343  }
1344  // compute foe incoming lanes
1345  const bool signalised = hasSignalisedConnectionTo(con.toEdge);
1346  if ((n.forbids(*i2, (*k2).toEdge, this, con.toEdge, signalised) || rightTurnConflict) && (needsCont || dir == LINKDIR_TURN)) {
1347  tmpFoeIncomingLanes.insert((*i2)->getID() + "_" + toString((*k2).fromLane));
1348  }
1349  index++;
1350  }
1351  }
1352  // foe pedestrian crossings
1353  const std::vector<NBNode::Crossing>& crossings = n.getCrossings();
1354  for (std::vector<NBNode::Crossing>::const_iterator it_c = crossings.begin(); it_c != crossings.end(); ++it_c) {
1355  const NBNode::Crossing& crossing = *it_c;
1356  for (EdgeVector::const_iterator it_e = crossing.edges.begin(); it_e != crossing.edges.end(); ++it_e) {
1357  const NBEdge* edge = *it_e;
1358  // compute foe internal lanes
1359  if (this == edge || con.toEdge == edge) {
1360  foeInternalLinks.push_back(index);
1361  if (con.toEdge == edge &&
1362  ((isRightTurn && getJunctionPriority(&n) > 0) || (isTurn && n.isTLControlled()))) {
1363  // build internal junctions (not for left turns at uncontrolled intersections)
1364  PositionVector crossingShape = crossing.shape;
1365  crossingShape.extrapolate(1.0); // sometimes shapes miss each other by a small margin
1366  const SUMOReal minDV = firstIntersection(shape, crossingShape, crossing.width / 2);
1367  if (minDV < shape.length() - POSITION_EPS && minDV > POSITION_EPS) {
1368  assert(minDV >= 0);
1369  if (crossingPositions.first < 0 || crossingPositions.first > minDV) {
1370  crossingPositions.first = minDV;
1371  }
1372  }
1373  }
1374  }
1375  }
1376  index++;
1377  }
1378 
1379  if (dir == LINKDIR_TURN && crossingPositions.first < 0 && crossingPositions.second.size() != 0 && shape.length() > 2. * POSITION_EPS) {
1380  // let turnarounds wait in the middle if no other crossing point was found and it has a sensible length
1381  // (if endOffset is used, the crossing point is in the middle of the part within the junction shape)
1382  crossingPositions.first = (SUMOReal)(shape.length() + getEndOffset(con.fromLane)) / 2.;
1383  }
1384  }
1385  break;
1386  default:
1387  break;
1388  }
1389  if (con.contPos != UNSPECIFIED_CONTPOS) {
1390  // apply custom internal junction position
1391  if (con.contPos <= 0 || con.contPos >= shape.length()) {
1392  // disable internal junction
1393  crossingPositions.first = -1;
1394  } else {
1395  // set custom position
1396  crossingPositions.first = con.contPos;
1397  }
1398  }
1399 
1400  // @todo compute the maximum speed allowed based on angular velocity
1401  // see !!! for an explanation (with a_lat_mean ~0.3)
1402  /*
1403  SUMOReal vmax = (SUMOReal) 0.3 * (SUMOReal) 9.80778 *
1404  getLaneShape(con.fromLane).back().distanceTo(
1405  con.toEdge->getLaneShape(con.toLane).front())
1406  / (SUMOReal) 2.0 / (SUMOReal) M_PI;
1407  vmax = MIN2(vmax, ((getSpeed() + con.toEdge->getSpeed()) / (SUMOReal) 2.0));
1408  */
1409  SUMOReal vmax = (getSpeed() + con.toEdge->getSpeed()) / (SUMOReal) 2.0;
1410  //
1411  Position end = con.toEdge->getLaneShape(con.toLane).front();
1412  Position beg = getLaneShape(con.fromLane).back();
1413 
1414  assert(shape.size() >= 2);
1415  // get internal splits if any
1416  if (crossingPositions.first >= 0) {
1417  std::pair<PositionVector, PositionVector> split = shape.splitAt(crossingPositions.first);
1418  con.id = innerID + "_" + toString(edgeIndex);
1419  con.shape = split.first;
1420  con.foeIncomingLanes = joinToString(tmpFoeIncomingLanes, " ");
1421  con.foeInternalLinks = foeInternalLinks; // resolve link indices to lane ids later
1422  con.viaID = innerID + "_" + toString(splitIndex + noInternalNoSplits);
1423  ++splitIndex;
1424  con.viaVmax = vmax;
1425  con.viaShape = split.second;
1426  con.haveVia = true;
1427  } else {
1428  con.id = innerID + "_" + toString(edgeIndex);
1429  con.shape = shape;
1430  }
1431  con.vmax = vmax;
1432  con.internalLaneIndex = internalLaneIndex;
1433  ++internalLaneIndex;
1434  ++linkIndex;
1435  }
1436 }
1437 
1438 
1439 SUMOReal
1442  if (v2.length() < POSITION_EPS) {
1443  return intersect;
1444  }
1445  PositionVector v2Right = v2;
1446  v2Right.move2side(width2);
1447 
1448  PositionVector v2Left = v2;
1449  v2Left.move2side(-width2);
1450 
1451  // intersect center line of v1 with left and right border of v2
1452  std::vector<SUMOReal> tmp = v1.intersectsAtLengths2D(v2Right);
1453  if (tmp.size() > 0) {
1454  intersect = MIN2(intersect, tmp[0]);
1455  }
1456  tmp = v1.intersectsAtLengths2D(v2Left);
1457  if (tmp.size() > 0) {
1458  intersect = MIN2(intersect, tmp[0]);
1459  }
1460  return intersect;
1461 }
1462 
1463 
1464 // -----------
1465 int
1466 NBEdge::getJunctionPriority(const NBNode* const node) const {
1467  if (node == myFrom) {
1468  return myFromJunctionPriority;
1469  } else {
1470  return myToJunctionPriority;
1471  }
1472 }
1473 
1474 
1475 void
1476 NBEdge::setJunctionPriority(const NBNode* const node, int prio) {
1477  if (node == myFrom) {
1478  myFromJunctionPriority = prio;
1479  } else {
1480  myToJunctionPriority = prio;
1481  }
1482 }
1483 
1484 
1485 SUMOReal
1486 NBEdge::getAngleAtNode(const NBNode* const atNode) const {
1487  // myStartAngle, myEndAngle are in [0,360] and this returns results in [-180,180]
1488  if (atNode == myFrom) {
1490  } else {
1491  assert(atNode == myTo);
1493  }
1494 }
1495 
1496 
1497 SUMOReal
1498 NBEdge::getAngleAtNodeToCenter(const NBNode* const atNode) const {
1499  if (atNode == myFrom) {
1500  SUMOReal res = myStartAngle - 180;
1501  if (res < 0) {
1502  res += 360;
1503  }
1504  return res;
1505  } else {
1506  assert(atNode == myTo);
1507  return myEndAngle;
1508  }
1509 }
1510 
1511 
1512 void
1513 NBEdge::setTurningDestination(NBEdge* e, bool onlyPossible) {
1514  if (!onlyPossible) {
1515  myTurnDestination = e;
1516  }
1518 }
1519 
1520 
1521 SUMOReal
1522 NBEdge::getLaneSpeed(int lane) const {
1523  return myLanes[lane].speed;
1524 }
1525 
1526 
1527 void
1529  // vissim needs this
1530  if (myFrom == myTo) {
1531  return;
1532  }
1533  // compute lane offset, first
1534  std::vector<SUMOReal> offsets(myLanes.size(), 0.);
1535  SUMOReal offset = 0;
1536  for (int i = (int)myLanes.size() - 2; i >= 0; --i) {
1537  offset += (getLaneWidth(i) + getLaneWidth(i + 1)) / 2. + SUMO_const_laneOffset;
1538  offsets[i] = offset;
1539  }
1541  SUMOReal laneWidth = myLanes.back().width != UNSPECIFIED_WIDTH ? myLanes.back().width : SUMO_const_laneWidth;
1542  offset = (laneWidth + SUMO_const_laneOffset) / 2.; // @todo: why is the lane offset counted in here?
1543  } else {
1544  SUMOReal width = 0;
1545  for (int i = 0; i < (int)myLanes.size(); ++i) {
1546  width += getLaneWidth(i);
1547  }
1548  width += SUMO_const_laneOffset * SUMOReal(myLanes.size() - 1);
1549  offset = -width / 2. + getLaneWidth((int)myLanes.size() - 1) / 2.;
1550  }
1551  for (int i = 0; i < (int)myLanes.size(); ++i) {
1552  offsets[i] += offset;
1553  }
1554 
1555  // build the shape of each lane
1556  for (int i = 0; i < (int)myLanes.size(); ++i) {
1557  try {
1558  myLanes[i].shape = computeLaneShape(i, offsets[i]);
1559  } catch (InvalidArgument& e) {
1560  WRITE_WARNING("In edge '" + getID() + "': lane shape could not be determined (" + e.what() + ").");
1561  myLanes[i].shape = myGeom;
1562  }
1563  }
1564 }
1565 
1566 
1568 NBEdge::computeLaneShape(int lane, SUMOReal offset) const {
1569  PositionVector shape = myGeom;
1570  try {
1571  shape.move2side(offset);
1572  } catch (InvalidArgument& e) {
1573  WRITE_WARNING("In lane '" + getLaneID(lane) + "': Could not build shape (" + e.what() + ").");
1574  }
1575  return shape;
1576 }
1577 
1578 
1579 void
1581  // taking the angle at the first might be unstable, thus we take the angle
1582  // at a certain distance. (To compare two edges, additional geometry
1583  // segments are considered to resolve ambiguities)
1584  const bool hasFromShape = myFrom->getShape().size() > 0;
1585  const bool hasToShape = myTo->getShape().size() > 0;
1586  Position fromCenter = (hasFromShape ? myFrom->getShape().getCentroid() : myFrom->getPosition());
1587  Position toCenter = (hasToShape ? myTo->getShape().getCentroid() : myTo->getPosition());
1588  PositionVector shape = ((hasFromShape || hasToShape) && getNumLanes() > 0 ?
1590  myLanes[getNumLanes() - 1].shape
1591  : myLanes[getNumLanes() / 2].shape)
1592  : myGeom);
1593 
1594  // if the junction shape is suspicious we cannot trust the angle to the centroid
1595  if (hasFromShape && (myFrom->getShape().distance2D(shape[0]) > 2 * POSITION_EPS
1596  || myFrom->getShape().around(shape[-1])
1597  || !(myFrom->getShape().around(fromCenter)))) {
1598  fromCenter = myFrom->getPosition();
1599  }
1600  if (hasToShape && (myTo->getShape().distance2D(shape[-1]) > 2 * POSITION_EPS
1601  || myTo->getShape().around(shape[0])
1602  || !(myTo->getShape().around(toCenter)))) {
1603  toCenter = myTo->getPosition();
1604  }
1605 
1606  const SUMOReal angleLookahead = MIN2(shape.length2D() / 2, ANGLE_LOOKAHEAD);
1607  const Position referencePosStart = shape.positionAtOffset2D(angleLookahead);
1608  myStartAngle = GeomHelper::legacyDegree(fromCenter.angleTo2D(referencePosStart), true);
1609  const Position referencePosEnd = shape.positionAtOffset2D(shape.length() - angleLookahead);
1610  myEndAngle = GeomHelper::legacyDegree(referencePosEnd.angleTo2D(toCenter), true);
1612 }
1613 
1614 
1615 SUMOReal
1617  const SUMOReal angleLookahead = MIN2(myGeom.length2D() / 2, ANGLE_LOOKAHEAD);
1618  const Position referencePosStart = myGeom.positionAtOffset2D(angleLookahead);
1619  return GeomHelper::legacyDegree(myGeom.front().angleTo2D(referencePosStart), true);
1620 }
1621 
1622 
1623 SUMOReal
1625  const SUMOReal angleLookahead = MIN2(myGeom.length2D() / 2, ANGLE_LOOKAHEAD);
1626  const Position referencePosEnd = myGeom.positionAtOffset2D(myGeom.length() - angleLookahead);
1627  return GeomHelper::legacyDegree(referencePosEnd.angleTo2D(myGeom.back()), true);
1628 }
1629 
1630 
1631 bool
1633  for (std::vector<Lane>::const_iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
1634  if ((*i).permissions != SVCAll) {
1635  return true;
1636  }
1637  }
1638  return false;
1639 }
1640 
1641 
1642 bool
1644  std::vector<Lane>::const_iterator i = myLanes.begin();
1645  SVCPermissions firstLanePermissions = i->permissions;
1646  i++;
1647  for (; i != myLanes.end(); ++i) {
1648  if (i->permissions != firstLanePermissions) {
1649  return true;
1650  }
1651  }
1652  return false;
1653 }
1654 
1655 
1656 bool
1658  for (std::vector<Lane>::const_iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
1659  if (i->speed != getSpeed()) {
1660  return true;
1661  }
1662  }
1663  return false;
1664 }
1665 
1666 
1667 bool
1669  for (std::vector<Lane>::const_iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
1670  if (i->width != myLanes.begin()->width) {
1671  return true;
1672  }
1673  }
1674  return false;
1675 }
1676 
1677 
1678 bool
1680  for (std::vector<Lane>::const_iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
1681  if (i->endOffset != myLanes.begin()->endOffset) {
1682  return true;
1683  }
1684  }
1685  return false;
1686 }
1687 
1688 
1689 bool
1691  return hasLaneSpecificPermissions() || hasLaneSpecificSpeed() || hasLaneSpecificWidth() || hasLaneSpecificEndOffset() || (!myLanes.empty() && myLanes.back().oppositeID != "");
1692 }
1693 
1694 
1695 
1696 bool
1697 NBEdge::computeEdge2Edges(bool noLeftMovers) {
1698  // return if this relationship has been build in previous steps or
1699  // during the import
1700  if (myStep >= EDGE2EDGES) {
1701  return true;
1702  }
1703  if (myConnections.size() == 0) {
1704  const EdgeVector& o = myTo->getOutgoingEdges();
1705  for (EdgeVector::const_iterator i = o.begin(); i != o.end(); ++i) {
1706  if (noLeftMovers && myTo->isLeftMover(this, *i)) {
1707  continue;
1708  }
1709  myConnections.push_back(Connection(-1, *i, -1));
1710  }
1711  }
1712  myStep = EDGE2EDGES;
1713  return true;
1714 }
1715 
1716 
1717 bool
1719  // return if this relationship has been build in previous steps or
1720  // during the import
1721  if (myStep >= LANES2EDGES) {
1722  return true;
1723  }
1724  assert(myStep == EDGE2EDGES);
1725  // get list of possible outgoing edges sorted by direction clockwise
1726  // the edge in the backward direction (turnaround) is not in the list
1727  const EdgeVector* edges = getConnectedSorted();
1728  if (myConnections.size() != 0 && edges->size() == 0) {
1729  // dead end per definition!?
1730  myConnections.clear();
1731  } else {
1732  // divide the lanes on reachable edges
1733  divideOnEdges(edges);
1734  }
1735  delete edges;
1736  myStep = LANES2EDGES;
1737  return true;
1738 }
1739 
1740 
1741 bool
1743  std::vector<int> connNumbersPerLane(myLanes.size(), 0);
1744  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end();) {
1745  if ((*i).toEdge == 0 || (*i).fromLane < 0 || (*i).toLane < 0) {
1746  i = myConnections.erase(i);
1747  } else {
1748  if ((*i).fromLane >= 0) {
1749  ++connNumbersPerLane[(*i).fromLane];
1750  }
1751  ++i;
1752  }
1753  }
1755  // check #1:
1756  // If there is a lane with no connections and any neighbour lane has
1757  // more than one connections, try to move one of them.
1758  // This check is only done for edges which connections were assigned
1759  // using the standard algorithm.
1760  for (int i = 0; i < (int)myLanes.size(); i++) {
1761  if (connNumbersPerLane[i] == 0 && !isForbidden(getPermissions((int)i))) {
1762  if (i > 0 && connNumbersPerLane[i - 1] > 1 && getPermissions(i) == getPermissions(i - 1)) {
1763  moveConnectionToLeft(i - 1);
1764  } else if (i < (int)myLanes.size() - 1 && connNumbersPerLane[i + 1] > 1 && getPermissions(i) == getPermissions(i + 1)) {
1765  moveConnectionToRight(i + 1);
1766  }
1767  }
1768  }
1769  // check restrictions
1770  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end();) {
1771  Connection& c = *i;
1773  if (common == SVC_PEDESTRIAN || getPermissions(c.fromLane) == SVC_PEDESTRIAN) {
1774  // these are computed in NBNode::buildWalkingAreas
1775  i = myConnections.erase(i);
1776  } else if (common == 0) {
1777  // no common permissions.
1778  // try to find a suitable target lane to the right
1779  const int origToLane = c.toLane;
1780  c.toLane = -1; // ignore this connection when calling hasConnectionTo
1781  int toLane = origToLane;
1782  while (toLane > 0
1783  && (getPermissions(c.fromLane) & c.toEdge->getPermissions(toLane)) == 0
1784  && !hasConnectionTo(c.toEdge, toLane)
1785  ) {
1786  toLane--;
1787  }
1788  if ((getPermissions(c.fromLane) & c.toEdge->getPermissions(toLane)) != 0
1789  && !hasConnectionTo(c.toEdge, toLane)) {
1790  c.toLane = toLane;
1791  ++i;
1792  } else {
1793  // try to find a suitable target lane to the left
1794  int toLane = origToLane;
1795  while (toLane < (int)c.toEdge->getNumLanes() - 1
1796  && (getPermissions(c.fromLane) & c.toEdge->getPermissions(toLane)) == 0
1797  && !hasConnectionTo(c.toEdge, toLane)
1798  ) {
1799  toLane++;
1800  }
1801  if ((getPermissions(c.fromLane) & c.toEdge->getPermissions(toLane)) != 0
1802  && !hasConnectionTo(c.toEdge, toLane)) {
1803  c.toLane = toLane;
1804  ++i;
1805  } else {
1806  // no alternative target found
1807  i = myConnections.erase(i);
1808  }
1809  }
1811  && isTurningDirectionAt(c.toEdge)) {
1812  // do not allow sharp rail turns
1813  i = myConnections.erase(i);
1814  } else {
1815  ++i;
1816  }
1817  }
1818  }
1819  // check delayed removals
1820  for (std::vector<Connection>::iterator it = myConnectionsToDelete.begin(); it != myConnectionsToDelete.end(); ++it) {
1821  removeFromConnections(it->toEdge, it->fromLane, it->toLane);
1822  }
1823  return true;
1824 }
1825 
1826 
1827 void
1829  if (outgoing->size() == 0) {
1830  // we have to do this, because the turnaround may have been added before
1831  myConnections.clear();
1832  return;
1833  }
1834  // precompute edge priorities; needed as some kind of assumptions for
1835  // priorities of directions (see preparePriorities)
1836  std::vector<int>* priorities = prepareEdgePriorities(outgoing);
1837  // compute the indices of lanes that should have connections (excluding
1838  // forbidden lanes and pedestrian lanes that will be connected via walkingAreas)
1839 
1840 
1841 #ifdef DEBUG_CONNECTION_GUESSING
1842  if (DEBUGCOND) {
1843  std::cout << " divideOnEdges " << getID() << " outgoing=" << toString(*outgoing) << " prios=" << toString(*priorities) << "\n";
1844  }
1845 #endif
1846 
1847  // build connections for miv lanes
1848  std::vector<int> availableLanes;
1849  for (int i = 0; i < (int)myLanes.size(); ++i) {
1850  if ((getPermissions(i) & SVC_PASSENGER) != 0) {
1851  availableLanes.push_back(i);
1852  }
1853  }
1854  if (availableLanes.size() > 0) {
1855  divideSelectedLanesOnEdges(outgoing, availableLanes, priorities);
1856  }
1857  // build connections for miscellaneous further modes (more than bike,peds,bus and without passenger)
1858  availableLanes.clear();
1859  for (int i = 0; i < (int)myLanes.size(); ++i) {
1860  const SVCPermissions perms = getPermissions(i);
1861  if ((perms & ~(SVC_PEDESTRIAN | SVC_BICYCLE | SVC_BUS)) == 0 || (perms & SVC_PASSENGER) != 0 || isForbidden(perms)) {
1862  continue;
1863  }
1864  availableLanes.push_back(i);
1865  }
1866  if (availableLanes.size() > 0) {
1867  divideSelectedLanesOnEdges(outgoing, availableLanes, priorities);
1868  }
1869  // build connections for busses (possibly combined with bicycles)
1870  availableLanes.clear();
1871  for (int i = 0; i < (int)myLanes.size(); ++i) {
1872  const SVCPermissions perms = getPermissions(i);
1873  if (perms != SVC_BUS && perms != (SVC_BUS | SVC_BICYCLE)) {
1874  continue;
1875  }
1876  availableLanes.push_back(i);
1877  }
1878  if (availableLanes.size() > 0) {
1879  divideSelectedLanesOnEdges(outgoing, availableLanes, priorities);
1880  }
1881  // build connections for bicycles (possibly combined with pedestrians)
1882  availableLanes.clear();
1883  for (int i = 0; i < (int)myLanes.size(); ++i) {
1884  const SVCPermissions perms = getPermissions(i);
1885  if (perms != SVC_BICYCLE && perms != (SVC_BICYCLE | SVC_PEDESTRIAN)) {
1886  continue;
1887  }
1888  availableLanes.push_back(i);
1889  }
1890  if (availableLanes.size() > 0) {
1891  divideSelectedLanesOnEdges(outgoing, availableLanes, priorities);
1892  }
1893  // clean up unassigned fromLanes
1894  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end();) {
1895  if ((*i).fromLane == -1) {
1896  i = myConnections.erase(i);
1897  } else {
1898  ++i;
1899  }
1900  }
1902 
1903  delete priorities;
1904 }
1905 
1906 
1907 void
1908 NBEdge::divideSelectedLanesOnEdges(const EdgeVector* outgoing, const std::vector<int>& availableLanes, const std::vector<int>* priorities) {
1909  //std::cout << "divideSelectedLanesOnEdges " << getID() << " out=" << toString(*outgoing) << " prios=" << toString(*priorities) << " avail=" << toString(availableLanes) << "\n";
1910  // compute the sum of priorities (needed for normalisation)
1911  int prioSum = computePrioritySum(*priorities);
1912  // compute the resulting number of lanes that should be used to
1913  // reach the following edge
1914  const int numOutgoing = (int) outgoing->size();
1915  std::vector<SUMOReal> resultingLanes;
1916  resultingLanes.reserve(numOutgoing);
1917  SUMOReal sumResulting = 0.; // the sum of resulting lanes
1918  SUMOReal minResulting = 10000.; // the least number of lanes to reach an edge
1919  for (int i = 0; i < numOutgoing; i++) {
1920  // res will be the number of lanes which are meant to reach the
1921  // current outgoing edge
1922  SUMOReal res =
1923  (SUMOReal)(*priorities)[i] *
1924  (SUMOReal) availableLanes.size() / (SUMOReal) prioSum;
1925  // do not let this number be greater than the number of available lanes
1926  if (res > availableLanes.size()) {
1927  res = (SUMOReal) availableLanes.size();
1928  }
1929  // add it to the list
1930  resultingLanes.push_back(res);
1931  sumResulting += res;
1932  if (minResulting > res && res > 0) {
1933  // prevent minResulting from becoming 0
1934  minResulting = res;
1935  }
1936  }
1937  // compute the number of virtual edges
1938  // a virtual edge is used as a replacement for a real edge from now on
1939  // it shall allow to divide the existing lanes on this structure without
1940  // regarding the structure of outgoing edges
1941  int numVirtual = 0;
1942  // compute the transition from virtual to real edges
1943  EdgeVector transition;
1944  transition.reserve(numOutgoing);
1945  for (int i = 0; i < numOutgoing; i++) {
1946  // tmpNo will be the number of connections from this edge
1947  // to the next edge
1948  assert(i < (int)resultingLanes.size());
1949  const int tmpNum = (int)std::ceil(resultingLanes[i] / minResulting);
1950  numVirtual += tmpNum;
1951  for (SUMOReal j = 0; j < tmpNum; j++) {
1952  transition.push_back((*outgoing)[i]);
1953  }
1954  }
1955 #ifdef DEBUG_CONNECTION_GUESSING
1956  if (DEBUGCOND) {
1957  std::cout << " prioSum=" << prioSum << " sumResulting=" << sumResulting << " minResulting=" << minResulting << " numVirtual=" << numVirtual << " availLanes=" << toString(availableLanes) << " resLanes=" << toString(resultingLanes) << " transition=" << toString(transition) << "\n";
1958  }
1959 #endif
1960 
1961  // assign lanes to edges
1962  // (conversion from virtual to real edges is done)
1963  ToEdgeConnectionsAdder adder(transition);
1964  Bresenham::compute(&adder, static_cast<int>(availableLanes.size()), numVirtual);
1965  const std::map<NBEdge*, std::vector<int> >& l2eConns = adder.getBuiltConnections();
1966  for (EdgeVector::const_iterator i = outgoing->begin(); i != outgoing->end(); ++i) {
1967  NBEdge* target = (*i);
1968  assert(l2eConns.find(target) != l2eConns.end());
1969  const std::vector<int> lanes = (l2eConns.find(target))->second;
1970  for (std::vector<int>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
1971  const int fromIndex = availableLanes[*j];
1972  if ((getPermissions(fromIndex) & target->getPermissions()) == 0) {
1973  // exclude connection if fromLane and toEdge have no common permissions
1974  continue;
1975  }
1976  if ((getPermissions(fromIndex) & target->getPermissions()) == SVC_PEDESTRIAN) {
1977  // exclude connection if the only commonly permitted class are pedestrians
1978  // these connections are later built in NBNode::buildWalkingAreas
1979  continue;
1980  }
1981  // avoid building more connections than the edge has viable lanes (earlier
1982  // ones have precedence). This is necessary when running divideSelectedLanesOnEdges more than once.
1983  // @todo To decide which target lanes are still available we need to do a
1984  // preliminary lane-to-lane assignment in regard to permissions (rather than to ordering)
1985  const int numConsToTarget = (int)count_if(myConnections.begin(), myConnections.end(), connections_toedge_finder(target, true));
1986  int targetLanes = (int)target->getNumLanes();
1987  if (target->getPermissions(0) == SVC_PEDESTRIAN) {
1988  --targetLanes;
1989  }
1990  if (numConsToTarget >= targetLanes) {
1991  // let bicycles move onto the road to allow continuation
1992  // the speed limit is taken from rural roads (which allow cycles)
1993  // (pending implementation of #1859)
1994  if (getPermissions(fromIndex) == SVC_BICYCLE && getSpeed() <= (101 / 3.6)) {
1995  for (int ii = 0; ii < (int)myLanes.size(); ++ii) {
1996  if (myLanes[ii].permissions != SVC_PEDESTRIAN) {
1997  myLanes[ii].permissions |= SVC_BICYCLE;
1998  }
1999  }
2000  }
2001  continue;
2002  }
2003 
2004  myConnections.push_back(Connection(fromIndex, target, -1));
2005 #ifdef DEBUG_CONNECTION_GUESSING
2006  if (DEBUGCOND) {
2007  std::cout << " request connection from " << getID() << "_" << fromIndex << " to " << target->getID() << "\n";
2008  }
2009 #endif
2010  }
2011  }
2012 
2013  addStraightConnections(outgoing, availableLanes, priorities);
2014 }
2015 
2016 
2017 void
2018 NBEdge::addStraightConnections(const EdgeVector* outgoing, const std::vector<int>& availableLanes, const std::vector<int>* priorities) {
2019  // ensure sufficient straight connections for the (hightest-priority straight target)
2020  const int numOutgoing = (int) outgoing->size();
2021  NBEdge* target = 0;
2022  NBEdge* rightOfTarget = 0;
2023  NBEdge* leftOfTarget = 0;
2024  int maxPrio = 0;
2025  for (int i = 0; i < numOutgoing; i++) {
2026  if (maxPrio < (*priorities)[i]) {
2027  const LinkDirection dir = myTo->getDirection(this, (*outgoing)[i]);
2028  if (dir == LINKDIR_STRAIGHT) {
2029  maxPrio = (*priorities)[i];
2030  target = (*outgoing)[i];
2031  rightOfTarget = i == 0 ? outgoing->back() : (*outgoing)[i - 1];
2032  leftOfTarget = i + 1 == numOutgoing ? outgoing->front() : (*outgoing)[i + 1];
2033  }
2034  }
2035  }
2036  if (target == 0) {
2037  return;
2038  }
2039  int numConsToTarget = (int)count_if(myConnections.begin(), myConnections.end(), connections_toedge_finder(target, true));
2040  int targetLanes = (int)target->getNumLanes();
2041  if (target->getPermissions(0) == SVC_PEDESTRIAN) {
2042  --targetLanes;
2043  }
2044  const int numDesiredConsToTarget = MIN2(targetLanes, (int)availableLanes.size());
2045 #ifdef DEBUG_CONNECTION_GUESSING
2046  if (DEBUGCOND) {
2047  std::cout << " checking extra lanes for target=" << target->getID() << " cons=" << numConsToTarget << " desired=" << numDesiredConsToTarget << "\n";
2048  }
2049 #endif
2050  std::vector<int>::const_iterator it_avail = availableLanes.begin();
2051  while (numConsToTarget < numDesiredConsToTarget && it_avail != availableLanes.end()) {
2052  const int fromIndex = *it_avail;
2053  if (
2054  // not yet connected
2055  (count_if(myConnections.begin(), myConnections.end(), connections_finder(fromIndex, target, -1)) == 0)
2056  // matching permissions
2057  && ((getPermissions(fromIndex) & target->getPermissions()) != 0)
2058  // more than pedestrians
2059  && ((getPermissions(fromIndex) & target->getPermissions()) != SVC_PEDESTRIAN)
2060  ) {
2061 #ifdef DEBUG_CONNECTION_GUESSING
2062  if (DEBUGCOND) {
2063  std::cout << " candidate from " << getID() << "_" << fromIndex << " to " << target->getID() << "\n";
2064  }
2065 #endif
2066  // prevent same-edge conflicts
2067  if (
2068  // no outgoing connections to the right from further left
2069  ((it_avail + 1) == availableLanes.end() || count_if(myConnections.begin(), myConnections.end(), connections_conflict_finder(fromIndex, rightOfTarget, false)) == 0)
2070  // no outgoing connections to the left from further right
2071  && (it_avail == availableLanes.begin() || count_if(myConnections.begin(), myConnections.end(), connections_conflict_finder(fromIndex, leftOfTarget, true)) == 0)) {
2072 #ifdef DEBUG_CONNECTION_GUESSING
2073  if (DEBUGCOND) {
2074  std::cout << " request additional connection from " << getID() << "_" << fromIndex << " to " << target->getID() << "\n";
2075  }
2076 #endif
2077  myConnections.push_back(Connection(fromIndex, target, -1));
2078  numConsToTarget++;
2079  } else {
2080 #ifdef DEBUG_CONNECTION_GUESSING
2081  if (DEBUGCOND) std::cout
2082  << " fail check1="
2083  << ((it_avail + 1) == availableLanes.end() || count_if(myConnections.begin(), myConnections.end(), connections_conflict_finder(fromIndex, rightOfTarget, false)) == 0)
2084  << " check2=" << (it_avail == availableLanes.begin() || count_if(myConnections.begin(), myConnections.end(), connections_conflict_finder(fromIndex, leftOfTarget, true)) == 0)
2085  << " rightOfTarget=" << rightOfTarget->getID()
2086  << " leftOfTarget=" << leftOfTarget->getID()
2087  << "\n";
2088 #endif
2089 
2090  }
2091  }
2092  ++it_avail;
2093  }
2094 }
2095 
2096 
2097 std::vector<int>*
2099  // copy the priorities first
2100  std::vector<int>* priorities = new std::vector<int>();
2101  if (outgoing->size() == 0) {
2102  return priorities;
2103  }
2104  priorities->reserve(outgoing->size());
2105  EdgeVector::const_iterator i;
2106  for (i = outgoing->begin(); i != outgoing->end(); i++) {
2107  //int prio = (*i)->getJunctionPriority(myTo);
2108  int prio = NBNode::isTrafficLight(myTo->getType()) ? 0 : (*i)->getJunctionPriority(myTo);
2109  assert((prio + 1) * 2 > 0);
2110  prio = (prio + 1) * 2;
2111  priorities->push_back(prio);
2112  }
2113  // when the right turning direction has not a higher priority, divide
2114  // the importance by 2 due to the possibility to leave the junction
2115  // faster from this lane
2116  EdgeVector tmp(*outgoing);
2117  sort(tmp.begin(), tmp.end(), NBContHelper::straightness_sorter(myTo, this));
2118  i = find(outgoing->begin(), outgoing->end(), *(tmp.begin()));
2119  int dist = (int) distance(outgoing->begin(), i);
2120  MainDirections mainDirections(*outgoing, this, myTo, dist);
2121 #ifdef DEBUG_CONNECTION_GUESSING
2122  if (DEBUGCOND) std::cout << " prepareEdgePriorities " << getID()
2123  << " outgoing=" << toString(*outgoing)
2124  << " priorities1=" << toString(*priorities)
2125  << " tmp=" << toString(tmp)
2126  << " mainDirs=" << toString(mainDirections.myDirs)
2127  << " dist=" << dist
2128  << "\n";
2129 #endif
2130  if (dist != 0 && !mainDirections.includes(MainDirections::DIR_RIGHTMOST)) {
2131  assert(priorities->size() > 0);
2132  (*priorities)[0] /= 2;
2133 #ifdef DEBUG_CONNECTION_GUESSING
2134  if (DEBUGCOND) {
2135  std::cout << " priorities2=" << toString(*priorities) << "\n";
2136  }
2137 #endif
2138  }
2139  // HEURISTIC:
2140  // when no higher priority exists, let the forward direction be
2141  // the main direction
2142  if (mainDirections.empty()) {
2143  assert(dist < (int)priorities->size());
2144  (*priorities)[dist] *= 2;
2145 #ifdef DEBUG_CONNECTION_GUESSING
2146  if (DEBUGCOND) {
2147  std::cout << " priorities3=" << toString(*priorities) << "\n";
2148  }
2149 #endif
2150  }
2152  (*priorities)[dist] += 1;
2153  } else {
2154  // try to ensure separation of left turns
2155  if (mainDirections.includes(MainDirections::DIR_RIGHTMOST) && mainDirections.includes(MainDirections::DIR_LEFTMOST)) {
2156  (*priorities)[0] /= 4;
2157  (*priorities)[(int)priorities->size() - 1] /= 2;
2158 #ifdef DEBUG_CONNECTION_GUESSING
2159  if (DEBUGCOND) {
2160  std::cout << " priorities6=" << toString(*priorities) << "\n";
2161  }
2162 #endif
2163  }
2164  }
2165  if (mainDirections.includes(MainDirections::DIR_FORWARD)) {
2166  if (myLanes.size() > 2) {
2167  (*priorities)[dist] *= 2;
2168 #ifdef DEBUG_CONNECTION_GUESSING
2169  if (DEBUGCOND) {
2170  std::cout << " priorities4=" << toString(*priorities) << "\n";
2171  }
2172 #endif
2173  } else {
2174  (*priorities)[dist] *= 3;
2175 #ifdef DEBUG_CONNECTION_GUESSING
2176  if (DEBUGCOND) {
2177  std::cout << " priorities5=" << toString(*priorities) << "\n";
2178  }
2179 #endif
2180  }
2181  }
2182  // return
2183  return priorities;
2184 }
2185 
2186 
2187 int
2188 NBEdge::computePrioritySum(const std::vector<int>& priorities) {
2189  int sum = 0;
2190  for (std::vector<int>::const_iterator i = priorities.begin(); i != priorities.end(); i++) {
2191  sum += *i;
2192  }
2193  return sum;
2194 }
2195 
2196 
2197 void
2198 NBEdge::appendTurnaround(bool noTLSControlled, bool checkPermissions) {
2199  // do nothing if no turnaround is known
2201  return;
2202  }
2203  // do nothing if the destination node is controlled by a tls and no turnarounds
2204  // shall be appended for such junctions
2205  if (noTLSControlled && myTo->isTLControlled()) {
2206  return;
2207  }
2208  const int fromLane = (int)myLanes.size() - 1;
2209  const int toLane = (int)myTurnDestination->getNumLanes() - 1;
2210  if (checkPermissions) {
2211  if ((getPermissions(fromLane) & myTurnDestination->getPermissions(toLane)) == 0) {
2212  // exclude connection if fromLane and toEdge have no common permissions
2213  return;
2214  }
2215  if ((getPermissions(fromLane) & myTurnDestination->getPermissions(toLane)) == SVC_PEDESTRIAN) {
2216  // exclude connection if the only commonly permitted class are pedestrians
2217  // these connections are later built in NBNode::buildWalkingAreas
2218  return;
2219  }
2220  }
2221  setConnection(fromLane, myTurnDestination, toLane, L2L_VALIDATED);
2222 }
2223 
2224 
2225 bool
2226 NBEdge::isTurningDirectionAt(const NBEdge* const edge) const {
2227  // maybe it was already set as the turning direction
2228  if (edge == myTurnDestination) {
2229  return true;
2230  } else if (myTurnDestination != 0) {
2231  // otherwise - it's not if a turning direction exists
2232  return false;
2233  }
2234  return edge == myPossibleTurnDestination;
2235 }
2236 
2237 
2238 NBNode*
2240  // return the from-node when the position is at the begin of the edge
2241  if (pos < tolerance) {
2242  return myFrom;
2243  }
2244  // return the to-node when the position is at the end of the edge
2245  if (pos > myLength - tolerance) {
2246  return myTo;
2247  }
2248  return 0;
2249 }
2250 
2251 
2252 void
2254  int lanes = e->getNumLanes();
2255  for (int i = 0; i < lanes; i++) {
2256  std::vector<NBEdge::Connection> elv = e->getConnectionsFromLane(i);
2257  for (std::vector<NBEdge::Connection>::iterator j = elv.begin(); j != elv.end(); j++) {
2258  NBEdge::Connection el = *j;
2259  assert(el.tlID == "");
2260  addLane2LaneConnection(i + laneOff, el.toEdge, el.toLane, L2L_COMPUTED);
2261  }
2262  }
2263 }
2264 
2265 
2266 bool
2269 }
2270 
2271 
2272 SUMOReal
2275 }
2276 
2277 
2278 bool
2279 NBEdge::mayBeTLSControlled(int fromLane, NBEdge* toEdge, int toLane) const {
2281  tpl.fromLane = fromLane;
2282  tpl.to = toEdge;
2283  tpl.toLane = toLane;
2284  std::vector<TLSDisabledConnection>::const_iterator i = find_if(myTLSDisabledConnections.begin(), myTLSDisabledConnections.end(), tls_disable_finder(tpl));
2285  return i == myTLSDisabledConnections.end();
2286 }
2287 
2288 
2289 bool
2290 NBEdge::setControllingTLInformation(const NBConnection& c, const std::string& tlID) {
2291  const int fromLane = c.getFromLane();
2292  NBEdge* toEdge = c.getTo();
2293  const int toLane = c.getToLane();
2294  const int tlIndex = c.getTLIndex();
2295  // check whether the connection was not set as not to be controled previously
2297  tpl.fromLane = fromLane;
2298  tpl.to = toEdge;
2299  tpl.toLane = toLane;
2300  std::vector<TLSDisabledConnection>::iterator i = find_if(myTLSDisabledConnections.begin(), myTLSDisabledConnections.end(), tls_disable_finder(tpl));
2301  if (i != myTLSDisabledConnections.end()) {
2302  return false;
2303  }
2304 
2305  assert(fromLane < 0 || fromLane < (int) myLanes.size());
2306  // try to use information about the connections if given
2307  if (fromLane >= 0 && toLane >= 0) {
2308  // find the specified connection
2309  std::vector<Connection>::iterator i =
2310  find_if(myConnections.begin(), myConnections.end(), connections_finder(fromLane, toEdge, toLane));
2311  // ok, we have to test this as on the removal of self-loop edges some connections
2312  // will be reassigned
2313  if (i != myConnections.end()) {
2314  // get the connection
2315  Connection& connection = *i;
2316  // set the information about the tl
2317  connection.tlID = tlID;
2318  connection.tlLinkNo = tlIndex;
2319  return true;
2320  }
2321  }
2322  // if the original connection was not found, set the information for all
2323  // connections
2324  int no = 0;
2325  bool hadError = false;
2326  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
2327  if ((*i).toEdge != toEdge) {
2328  continue;
2329  }
2330  if (fromLane >= 0 && fromLane != (*i).fromLane) {
2331  continue;
2332  }
2333  if (toLane >= 0 && toLane != (*i).toLane) {
2334  continue;
2335  }
2336  if ((*i).tlID == "") {
2337  (*i).tlID = tlID;
2338  (*i).tlLinkNo = tlIndex;
2339  no++;
2340  } else {
2341  if ((*i).tlID != tlID && (*i).tlLinkNo == tlIndex) {
2342  WRITE_WARNING("The lane '" + toString<int>((*i).fromLane) + "' on edge '" + getID() + "' already had a traffic light signal.");
2343  hadError = true;
2344  }
2345  }
2346  }
2347  if (hadError && no == 0) {
2348  WRITE_WARNING("Could not set any signal of the tlLogic '" + tlID + "' (unknown group)");
2349  }
2350  return true;
2351 }
2352 
2353 
2354 void
2356  for (std::vector<Connection>::iterator it = myConnections.begin(); it != myConnections.end(); it++) {
2357  it->tlID = "";
2358  }
2359 }
2360 
2361 
2362 void
2363 NBEdge::disableConnection4TLS(int fromLane, NBEdge* toEdge, int toLane) {
2365  c.fromLane = fromLane;
2366  c.to = toEdge;
2367  c.toLane = toLane;
2368  myTLSDisabledConnections.push_back(c);
2369 }
2370 
2371 
2374  PositionVector ret;
2375  SUMOReal width;
2376  if (myFrom == (&n)) {
2377  // outgoing
2378  ret = myLanes[0].shape;
2379  width = getLaneWidth(0);
2380  } else {
2381  // incoming
2382  ret = myLanes.back().shape.reverse();
2383  width = getLaneWidth((int)getNumLanes() - 1);
2384  }
2385  ret.move2side(width * 0.5);
2386  return ret;
2387 }
2388 
2389 
2392  PositionVector ret;
2393  SUMOReal width;
2394  if (myFrom == (&n)) {
2395  // outgoing
2396  ret = myLanes.back().shape;
2397  width = getLaneWidth((int)getNumLanes() - 1);
2398  } else {
2399  // incoming
2400  ret = myLanes[0].shape.reverse();
2401  width = getLaneWidth(0);
2402  }
2403  ret.move2side(-width * 0.5);
2404  return ret;
2405 }
2406 
2407 
2408 bool
2409 NBEdge::expandableBy(NBEdge* possContinuation) const {
2410  // ok, the number of lanes must match
2411  if (myLanes.size() != possContinuation->myLanes.size()) {
2412  return false;
2413  }
2414  // the priority, too (?)
2415  if (getPriority() != possContinuation->getPriority()) {
2416  return false;
2417  }
2418  // the speed allowed
2419  if (mySpeed != possContinuation->mySpeed) {
2420  return false;
2421  }
2422  // spreadtype should match or it will look ugly
2423  if (myLaneSpreadFunction != possContinuation->myLaneSpreadFunction) {
2424  return false;
2425  }
2426  // do not create self loops
2427  if (myFrom == possContinuation->myTo) {
2428  return false;
2429  }
2430  // matching lanes must have identical properties
2431  for (int i = 0; i < (int)myLanes.size(); i++) {
2432  if (myLanes[i].speed != possContinuation->myLanes[i].speed ||
2433  myLanes[i].permissions != possContinuation->myLanes[i].permissions ||
2434  myLanes[i].width != possContinuation->myLanes[i].width
2435  ) {
2436  return false;
2437  }
2438  }
2439 
2440  // the vehicle class constraints, too
2448  // also, check whether the connections - if any exit do allow to join
2449  // both edges
2450  // This edge must have a one-to-one connection to the following lanes
2451  switch (myStep) {
2453  break;
2454  case INIT:
2455  break;
2456  case EDGE2EDGES: {
2457  // the following edge must be connected
2458  const EdgeVector& conn = getConnectedEdges();
2459  if (find(conn.begin(), conn.end(), possContinuation) == conn.end()) {
2460  return false;
2461  }
2462  }
2463  break;
2464  case LANES2EDGES:
2465  case LANES2LANES_RECHECK:
2466  case LANES2LANES_DONE:
2467  case LANES2LANES_USER: {
2468  // the possible continuation must be connected
2469  if (find_if(myConnections.begin(), myConnections.end(), connections_toedge_finder(possContinuation)) == myConnections.end()) {
2470  return false;
2471  }
2472  // all lanes must go to the possible continuation
2473  std::vector<int> conns = getConnectionLanes(possContinuation);
2474  const int offset = MAX2(0, getFirstNonPedestrianLaneIndex(NBNode::FORWARD, true));
2475  if (conns.size() != myLanes.size() - offset) {
2476  return false;
2477  }
2478  }
2479  break;
2480  default:
2481  break;
2482  }
2483  return true;
2484 }
2485 
2486 
2487 void
2489  // append geometry
2490  myGeom.append(e->myGeom);
2491  for (int i = 0; i < (int)myLanes.size(); i++) {
2492  myLanes[i].shape.append(e->myLanes[i].shape);
2493  if (myLanes[i].origID != e->myLanes[i].origID) {
2494  myLanes[i].origID += " " + e->myLanes[i].origID;
2495  }
2496  }
2497  // recompute length
2498  myLength += e->myLength;
2499  // copy the connections and the building step if given
2500  myStep = e->myStep;
2504  // set the node
2505  myTo = e->myTo;
2508  } else {
2509  mySignalOffset += e->getLength();
2510  }
2511  computeAngle(); // myEndAngle may be different now
2512 }
2513 
2514 
2515 bool
2517  for (std::vector<Connection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
2518  if ((*i).toEdge == e && (*i).tlID != "") {
2519  return true;
2520  }
2521  }
2522  return false;
2523 }
2524 
2525 
2526 NBEdge*
2527 NBEdge::getTurnDestination(bool possibleDestination) const {
2528  if (myTurnDestination == 0 && possibleDestination) {
2530  }
2531  return myTurnDestination;
2532 }
2533 
2534 
2535 std::string
2536 NBEdge::getLaneID(int lane) const {
2537  return myID + "_" + toString(lane);
2538 }
2539 
2540 
2541 std::string
2542 NBEdge::getLaneIDInsecure(int lane) const {
2543  return myID + "_" + toString(lane);
2544 }
2545 
2546 
2547 bool
2549  std::vector<SUMOReal> distances = myGeom.distances(e->getGeometry());
2550  assert(distances.size() > 0);
2551  return VectorHelper<SUMOReal>::maxValue(distances) < threshold;
2552 }
2553 
2554 
2555 void
2556 NBEdge::addLane(int index, bool recompute) {
2557  assert(index <= (int)myLanes.size());
2558  myLanes.insert(myLanes.begin() + index, Lane(this, ""));
2559  // copy attributes
2560  if (myLanes.size() > 1) {
2561  int templateIndex = index > 0 ? index - 1 : index + 1;
2562  myLanes[index].speed = myLanes[templateIndex].speed;
2563  myLanes[index].permissions = myLanes[templateIndex].permissions;
2564  myLanes[index].preferred = myLanes[templateIndex].preferred;
2565  myLanes[index].endOffset = myLanes[templateIndex].endOffset;
2566  myLanes[index].width = myLanes[templateIndex].width;
2567  myLanes[index].origID = myLanes[templateIndex].origID;
2568  }
2569  const EdgeVector& incs = myFrom->getIncomingEdges();
2570  if (recompute) {
2572  for (EdgeVector::const_iterator i = incs.begin(); i != incs.end(); ++i) {
2573  (*i)->invalidateConnections(true);
2574  }
2575  invalidateConnections(true);
2576  }
2577 }
2578 
2579 void
2581  int newLaneNo = (int)myLanes.size() + by;
2582  while ((int)myLanes.size() < newLaneNo) {
2583  // recompute shapes on last addition
2584  const bool recompute = ((int)myLanes.size() == newLaneNo - 1) && myStep < LANES2LANES_USER;
2585  addLane((int)myLanes.size(), recompute);
2586  }
2587 }
2588 
2589 
2590 void
2591 NBEdge::deleteLane(int index, bool recompute) {
2592  assert(index < (int)myLanes.size());
2593  myLanes.erase(myLanes.begin() + index);
2594  const EdgeVector& incs = myFrom->getIncomingEdges();
2595  if (recompute) {
2597  for (EdgeVector::const_iterator i = incs.begin(); i != incs.end(); ++i) {
2598  (*i)->invalidateConnections(true);
2599  }
2600  invalidateConnections(true);
2601  }
2602 }
2603 
2604 
2605 void
2607  int newLaneNo = (int) myLanes.size() - by;
2608  assert(newLaneNo > 0);
2609  while ((int)myLanes.size() > newLaneNo) {
2610  // recompute shapes on last removal
2611  const bool recompute = (int)myLanes.size() == newLaneNo + 1 && myStep < LANES2LANES_USER;
2612  deleteLane((int)myLanes.size() - 1, recompute);
2613  }
2614 }
2615 
2616 
2617 void
2619  assert(myTo->getOutgoingEdges().size() == 0);
2621 }
2622 
2623 
2624 void
2626  if (lane < 0) { // all lanes are meant...
2627  for (int i = 0; i < (int)myLanes.size(); i++) {
2628  allowVehicleClass(i, vclass);
2629  }
2630  } else {
2631  assert(lane < (int)myLanes.size());
2632  myLanes[lane].permissions |= vclass;
2633  }
2634 }
2635 
2636 
2637 void
2639  if (lane < 0) { // all lanes are meant...
2640  for (int i = 0; i < (int)myLanes.size(); i++) {
2641  disallowVehicleClass((int) i, vclass);
2642  }
2643  } else {
2644  assert(lane < (int)myLanes.size());
2645  myLanes[lane].permissions &= ~vclass;
2646  }
2647 }
2648 
2649 
2650 void
2652  if (lane < 0) { // all lanes are meant...
2653  for (int i = 0; i < (int)myLanes.size(); i++) {
2654  allowVehicleClass(i, vclass);
2655  }
2656  } else {
2657  assert(lane < (int)myLanes.size());
2658  myLanes[lane].preferred |= vclass;
2659  }
2660 }
2661 
2662 
2663 void
2664 NBEdge::setLaneWidth(int lane, SUMOReal width) {
2665  if (lane < 0) {
2666  // all lanes are meant...
2667  myLaneWidth = width;
2668  for (int i = 0; i < (int)myLanes.size(); i++) {
2669  // ... do it for each lane
2670  setLaneWidth(i, width);
2671  }
2672  return;
2673  }
2674  assert(lane < (int)myLanes.size());
2675  myLanes[lane].width = width;
2676 }
2677 
2678 
2679 SUMOReal
2680 NBEdge::getLaneWidth(int lane) const {
2681  return myLanes[lane].width != UNSPECIFIED_WIDTH
2682  ? myLanes[lane].width
2684 }
2685 
2686 
2687 SUMOReal
2689  SUMOReal result = 0;
2690  for (int i = 0; i < (int)myLanes.size(); i++) {
2691  result += getLaneWidth(i);
2692  }
2693  return result;
2694 }
2695 
2696 SUMOReal
2697 NBEdge::getEndOffset(int lane) const {
2698  return myLanes[lane].endOffset != UNSPECIFIED_OFFSET ? myLanes[lane].endOffset : getEndOffset();
2699 }
2700 
2701 
2702 void
2703 NBEdge::setEndOffset(int lane, SUMOReal offset) {
2704  if (lane < 0) {
2705  // all lanes are meant...
2706  myEndOffset = offset;
2707  for (int i = 0; i < (int)myLanes.size(); i++) {
2708  // ... do it for each lane
2709  setEndOffset(i, offset);
2710  }
2711  return;
2712  }
2713  assert(lane < (int)myLanes.size());
2714  myLanes[lane].endOffset = offset;
2715 }
2716 
2717 
2718 void
2719 NBEdge::setSpeed(int lane, SUMOReal speed) {
2720  if (lane < 0) {
2721  // all lanes are meant...
2722  mySpeed = speed;
2723  for (int i = 0; i < (int)myLanes.size(); i++) {
2724  // ... do it for each lane
2725  setSpeed(i, speed);
2726  }
2727  return;
2728  }
2729  assert(lane < (int)myLanes.size());
2730  myLanes[lane].speed = speed;
2731 }
2732 
2733 
2734 void
2735 NBEdge::setPermissions(SVCPermissions permissions, int lane) {
2736  if (lane < 0) {
2737  for (int i = 0; i < (int)myLanes.size(); i++) {
2738  // ... do it for each lane
2739  setPermissions(permissions, i);
2740  }
2741  } else {
2742  assert(lane < (int)myLanes.size());
2743  myLanes[lane].permissions = permissions;
2744  }
2745 }
2746 
2747 
2748 void
2750  if (lane < 0) {
2751  for (int i = 0; i < (int)myLanes.size(); i++) {
2752  // ... do it for each lane
2753  setPreferredVehicleClass(permissions, i);
2754  }
2755  } else {
2756  assert(lane < (int)myLanes.size());
2757  myLanes[lane].preferred = permissions;
2758  }
2759 }
2760 
2761 
2763 NBEdge::getPermissions(int lane) const {
2764  if (lane < 0) {
2765  SVCPermissions result = 0;
2766  for (int i = 0; i < (int)myLanes.size(); i++) {
2767  result |= getPermissions(i);
2768  }
2769  return result;
2770  } else {
2771  assert(lane < (int)myLanes.size());
2772  return myLanes[lane].permissions;
2773  }
2774 }
2775 
2776 
2777 void
2779  myLoadedLength = val;
2780 }
2781 
2782 
2783 void
2785  for (std::vector<Lane>::iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
2786  (*i).permissions = SVCAll;
2787  (*i).preferred = 0;
2788  }
2789 }
2790 
2791 
2792 bool
2794  if (c1.fromLane != c2.fromLane) {
2795  return c1.fromLane < c2.fromLane;
2796  }
2797  if (c1.toEdge != c2.toEdge) {
2798  return false; // do not change ordering among toEdges as this is determined by angle in an earlier step
2799  }
2800  return c1.toLane < c2.toLane;
2801 }
2802 
2803 
2804 int
2805 NBEdge::getFirstNonPedestrianLaneIndex(int direction, bool exclusive) const {
2806  assert(direction == NBNode::FORWARD || direction == NBNode::BACKWARD);
2807  const int start = (direction == NBNode::FORWARD ? 0 : (int)myLanes.size() - 1);
2808  const int end = (direction == NBNode::FORWARD ? (int)myLanes.size() : - 1);
2809  for (int i = start; i != end; i += direction) {
2810  // SVCAll, does not count as a sidewalk, green verges (permissions = 0) do not count as road
2811  // in the exclusive case, lanes that allow pedestrians along with any other class also count as road
2812  if ((exclusive && myLanes[i].permissions != SVC_PEDESTRIAN && myLanes[i].permissions != 0)
2813  || (myLanes[i].permissions == SVCAll || ((myLanes[i].permissions & SVC_PEDESTRIAN) == 0 && myLanes[i].permissions != 0))) {
2814  return i;
2815  }
2816  }
2817  return -1;
2818 }
2819 
2820 
2821 std::set<SVCPermissions>
2822 NBEdge::getPermissionVariants(int iStart, int iEnd) const {
2823  std::set<SVCPermissions> result;
2824  if (iStart < 0 || iStart >= getNumLanes() || iEnd > getNumLanes()) {
2825  throw ProcessError("invalid indices iStart " + toString(iStart) + " iEnd " + toString(iEnd) + " for edge with " + toString(getNumLanes()) + " lanes.");
2826  }
2827  for (int i = iStart; i < iEnd; ++i) {
2828  result.insert(getPermissions(i));
2829  }
2830  return result;
2831 }
2832 
2833 
2834 SUMOReal
2836  SUMOReal angle = getAngleAtNode(node) + (getFromNode() == node ? 180.0 : 0.0);
2837  if (angle < 0) {
2838  angle += 360.0;
2839  }
2840  if (angle >= 360) {
2841  angle -= 360.0;
2842  }
2843  if (gDebugFlag1) {
2844  std::cout << getID() << " angle=" << getAngleAtNode(node) << " convAngle=" << angle << "\n";
2845  }
2846  return angle;
2847 }
2848 
2849 
2852  int index = getFirstNonPedestrianLaneIndex(direction);
2853  if (index < 0) {
2854  throw ProcessError("Edge " + getID() + " allows pedestrians on all lanes");
2855  }
2856  return myLanes[index];
2857 }
2858 
2859 
2860 void
2863 }
2864 
2865 
2866 void
2867 NBEdge::restoreSidewalk(std::vector<NBEdge::Lane> oldLanes, PositionVector oldGeometry, std::vector<NBEdge::Connection> oldConnections) {
2868  restoreRestrictedLane(SVC_PEDESTRIAN, oldLanes, oldGeometry, oldConnections);
2869 }
2870 
2871 
2872 void
2875 }
2876 
2877 
2878 void
2879 NBEdge::restoreBikelane(std::vector<NBEdge::Lane> oldLanes, PositionVector oldGeometry, std::vector<NBEdge::Connection> oldConnections) {
2880  restoreRestrictedLane(SVC_BICYCLE, oldLanes, oldGeometry, oldConnections);
2881 }
2882 
2883 
2884 void
2886  if (myLanes[0].permissions == vclass) {
2887  WRITE_WARNING("Edge '" + getID() + "' already has a dedicated lane for " + toString(vclass) + "s. Not adding another one.");
2888  return;
2889  }
2891  myGeom.move2side(width / 2);
2892  }
2893  // disallow pedestrians on all lanes to ensure that sidewalks are used and
2894  // crossings can be guessed
2895  disallowVehicleClass(-1, vclass);
2896  // add new lane
2897  myLanes.insert(myLanes.begin(), Lane(this, myLanes[0].origID));
2898  myLanes[0].permissions = vclass;
2899  myLanes[0].width = width;
2900  // shift outgoing connections to the left
2901  for (std::vector<Connection>::iterator it = myConnections.begin(); it != myConnections.end(); ++it) {
2902  Connection& c = *it;
2903  if (c.fromLane >= 0) {
2904  c.fromLane += 1;
2905  }
2906  }
2907  // shift incoming connections to the left
2908  const EdgeVector& incoming = myFrom->getIncomingEdges();
2909  for (EdgeVector::const_iterator it = incoming.begin(); it != incoming.end(); ++it) {
2910  (*it)->shiftToLanesToEdge(this, 1);
2911  }
2913  myTo->shiftTLConnectionLaneIndex(this, 1);
2915 }
2916 
2917 
2918 void
2919 NBEdge::restoreRestrictedLane(SUMOVehicleClass vclass, std::vector<NBEdge::Lane> oldLanes, PositionVector oldGeometry, std::vector<NBEdge::Connection> oldConnections) {
2920  // check that previously lane was transformed
2921  if (myLanes[0].permissions != vclass) {
2922  WRITE_WARNING("Edge '" + getID() + "' don't have a dedicated lane for " + toString(vclass) + "s. Cannot be restored");
2923  return;
2924  }
2925  // restore old values
2926  myGeom = oldGeometry;
2927  myLanes = oldLanes;
2928  myConnections = oldConnections;
2929  // shift incoming connections to the right
2930  const EdgeVector& incoming = myFrom->getIncomingEdges();
2931  for (EdgeVector::const_iterator it = incoming.begin(); it != incoming.end(); ++it) {
2932  (*it)->shiftToLanesToEdge(this, 0);
2933  }
2934  // Shift TL conections
2936  myTo->shiftTLConnectionLaneIndex(this, 0);
2938 }
2939 
2940 
2941 void
2944  for (std::vector<Connection>::iterator it = myConnections.begin(); it != myConnections.end(); ++it) {
2945  if ((*it).toEdge == to && (*it).toLane >= 0) {
2946  (*it).toLane += laneOff;
2947  }
2948  }
2949 }
2950 
2951 
2952 void
2955  const int i = (node == myTo ? -1 : 0);
2956  const int i2 = (node == myTo ? 0 : -1);
2957  const SUMOReal dist = myGeom[i].distanceTo2D(node->getPosition());
2958  const SUMOReal neededOffset = (getTotalWidth() + getNumLanes() * SUMO_const_laneOffset) / 2;
2959  const SUMOReal dist2 = MIN2(myGeom.distance2D(other->getGeometry()[i2]),
2960  other->getGeometry().distance2D(myGeom[i]));
2961  const SUMOReal neededOffset2 = neededOffset + (other->getTotalWidth() + other->getNumLanes() * SUMO_const_laneOffset) / 2;
2962  if (dist < neededOffset && dist2 < neededOffset2) {
2963  PositionVector tmp = myGeom;
2964  // @note this doesn't work well for vissim networks
2965  //tmp.move2side(MIN2(neededOffset - dist, neededOffset2 - dist2));
2966  try {
2967  tmp.move2side(neededOffset - dist);
2968  myGeom[i] = tmp[i];
2969  } catch (InvalidArgument&) {
2970  WRITE_WARNING("Could not avoid overlapping shape at node '" + node->getID() + "' for edge '" + getID() + "'");
2971  }
2972  }
2973  }
2974 }
2975 
2976 
2977 SUMOReal
2979  SUMOReal result = getLoadedLength();
2980  if (OptionsCont::getOptions().getBool("no-internal-links") && !hasLoadedLength()) {
2981  // use length to junction center even if a modified geometry was given
2983  geom.push_back_noDoublePos(getToNode()->getCenter());
2984  geom.push_front_noDoublePos(getFromNode()->getCenter());
2985  result = geom.length();
2986  }
2987  if (result <= 0) {
2988  result = POSITION_EPS;
2989  }
2990  return result;
2991 }
2992 
2993 /****************************************************************************/
NBEdge::Lane getFirstNonPedestrianLane(int direction) const
get first non-pedestrian lane
Definition: NBEdge.cpp:2851
bool gDebugFlag1
global utility flags for debugging
Definition: StdDefs.cpp:37
std::string id
id of Connection
Definition: NBEdge.h:206
void moveConnectionToRight(int lane)
Definition: NBEdge.cpp:1260
void invalidateConnections(bool reallowSetting=false)
invalidate current connections of edge
Definition: NBEdge.cpp:1148
int tlLinkNo
The index of this connection within the controlling traffic light.
Definition: NBEdge.h:188
void init(int noLanes, bool tryIgnoreNodePositions, const std::string &origID)
Initialization routines common to all constructors.
Definition: NBEdge.cpp:393
The link is a partial left direction.
std::vector< Lane > myLanes
Lane information.
Definition: NBEdge.h:1374
bool includes(Direction d) const
returns the information whether the street in the given direction has a higher priority ...
Definition: NBEdge.cpp:223
PositionVector cutAtIntersection(const PositionVector &old) const
cut shape at the intersection shapes
Definition: NBEdge.cpp:545
const EdgeVector & getIncomingEdges() const
Returns this node&#39;s incoming edges (The edges which yield in this node)
Definition: NBNode.h:240
const std::string & getTypeID() const
get ID of type
Definition: NBEdge.h:946
bool setControllingTLInformation(const NBConnection &c, const std::string &tlID)
Returns if the link could be set as to be controlled.
Definition: NBEdge.cpp:2290
void divideOnEdges(const EdgeVector *outgoing)
divides the lanes on the outgoing edges
Definition: NBEdge.cpp:1828
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:157
int toLane
The lane the connections yields in.
Definition: NBEdge.h:182
static const SUMOReal UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:244
SUMOReal width
This lane&#39;s width.
Definition: NBNode.h:151
SUMOReal myTotalAngle
Definition: NBEdge.h:1330
std::string foeIncomingLanes
FOE Incomings lanes.
Definition: NBEdge.h:230
const SUMOReal SUMO_const_laneWidth
Definition: StdDefs.h:48
is a pedestrian
int getTLIndex() const
returns the index within the controlling tls or InvalidTLIndex if this link is unontrolled ...
Definition: NBConnection.h:100
SUMOReal myEndOffset
This edges&#39;s offset to the intersection begin (will be applied to all lanes)
Definition: NBEdge.h:1366
std::vector< TLSDisabledConnection > myTLSDisabledConnections
vector with the disabled connections
Definition: NBEdge.h:1393
SUMOReal nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
~NBEdge()
Destructor.
Definition: NBEdge.cpp:450
static const SUMOReal UNSPECIFIED_SIGNAL_OFFSET
unspecified signal offset
Definition: NBEdge.h:262
LaneSpreadFunction myLaneSpreadFunction
The information about how to spread the lanes.
Definition: NBEdge.h:1363
PositionVector getSubpart2D(SUMOReal beginOffset, SUMOReal endOffset) const
get subpart of a position vector in two dimensions (Z is ignored)
SUMOReal viaVmax
Maximun velocity of via.
Definition: NBEdge.h:221
void sortOutgoingConnectionsByAngle()
sorts the outgoing connections by their angle relative to their junction
Definition: NBEdge.cpp:1072
std::string viaID
if Connection have a via, ID of it
Definition: NBEdge.h:218
NBEdge * toEdge
The edge the connections yields in.
Definition: NBEdge.h:179
bool hasDefaultGeometry() const
Returns whether the geometry consists only of the node positions.
Definition: NBEdge.cpp:486
void shiftTLConnectionLaneIndex(NBEdge *edge, int offset)
patches loaded signal plans by modifying lane indices
Definition: NBNode.cpp:375
void mirrorX()
mirror coordinates along the x-axis
Definition: NBEdge.cpp:465
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types...
NBNode * myTo
Definition: NBEdge.h:1321
PositionVector getOrthogonal(const Position &p, SUMOReal extend, SUMOReal &distToClosest) const
return orthogonal through p (extending this vector if necessary)
The relationships between edges are computed/loaded.
Definition: NBEdge.h:96
bool empty() const
returns the information whether no following street has a higher priority
Definition: NBEdge.cpp:217
std::vector< Connection > getConnectionsFromLane(int lane) const
Returns connections from a given lane.
Definition: NBEdge.cpp:936
void setNodeBorder(const NBNode *node, const Position &p)
Set Node border.
Definition: NBEdge.cpp:512
#define M_PI
Definition: angles.h:37
bool hasLaneSpecificEndOffset() const
whether lanes differ in offset
Definition: NBEdge.cpp:1679
void setLaneWidth(int lane, SUMOReal width)
set lane specific width (negative lane implies set for all lanes)
Definition: NBEdge.cpp:2664
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition: NBNode.h:288
Holds (- relative to the edge it is build from -!!!) the list of main directions a vehicle that drive...
Definition: NBEdge.h:1209
void setSpeed(int lane, SUMOReal speed)
set lane specific speed (negative lane implies set for all lanes)
Definition: NBEdge.cpp:2719
Some static methods for string processing.
Definition: StringUtils.h:45
void moveConnectionToLeft(int lane)
Definition: NBEdge.cpp:1245
const SUMOReal SUMO_const_laneWidthAndOffset
Definition: StdDefs.h:52
void addSidewalk(SUMOReal width)
add a pedestrian sidewalk of the given width and shift existing connctions
Definition: NBEdge.cpp:2861
void removeEdge(NBEdge *edge, bool removeFromConnections=true)
Removes edge from this node and optionally removes connections as well.
Definition: NBNode.cpp:1295
vehicle is a bicycle
void addIncomingEdge(NBEdge *edge)
adds an incoming edge
Definition: NBNode.cpp:416
int SVCPermissions
The representation of a single edge during network building.
Definition: NBEdge.h:71
void reinitNodes(NBNode *from, NBNode *to)
Resets nodes but keeps all other values the same (used when joining)
Definition: NBEdge.cpp:373
void clearControllingTLInformation()
clears tlID for all connections
Definition: NBEdge.cpp:2355
Lane2LaneInfoType
Modes of setting connections between lanes.
Definition: NBEdge.h:111
std::vector< int > * prepareEdgePriorities(const EdgeVector *outgoing)
recomputes the edge priorities and manipulates them for a distribution of lanes on edges which is mor...
Definition: NBEdge.cpp:2098
bool mayBeTLSControlled(int fromLane, NBEdge *toEdge, int toLane) const
return true if certain connection must be controlled by TLS
Definition: NBEdge.cpp:2279
bool hasDefaultGeometryEndpoints() const
Returns whether the geometry is terminated by the node positions This default may be violated by init...
Definition: NBEdge.cpp:492
Lane(NBEdge *e, const std::string &_origID)
constructor
Definition: NBEdge.cpp:121
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
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:2391
bool intersects(const Position &p1, const Position &p2) const
Returns the information whether this list of points interesects the given line.
std::string getDescription(const NBEdge *parent) const
get string describing this connection
Definition: NBEdge.cpp:88
const std::vector< Crossing > & getCrossings() const
return this junctions pedestrian crossings
Definition: NBNode.h:620
EdgeVector getIncomingEdges() const
Returns the list of incoming edges unsorted.
Definition: NBEdge.cpp:1045
static const SUMOReal UNSPECIFIED_SPEED
unspecified lane speed
Definition: NBEdge.h:250
std::vector< Direction > myDirs
list of the main direction within the following junction relative to the edge
Definition: NBEdge.h:1215
void markAsInLane2LaneState()
mark edge as in lane to state lane
Definition: NBEdge.cpp:2618
SUMOReal getTotalWidth() const
Returns the combined width of all lanes of this edge.
Definition: NBEdge.cpp:2688
PositionVector computeInternalLaneShape(NBEdge *fromE, const NBEdge::Connection &con, int numPoints, NBNode *recordError=0) const
Compute the shape for an internal lane.
Definition: NBNode.cpp:631
TLS Disabled Connections.
Definition: NBEdge.h:1386
Lanes to lanes - relationships are computed; should be recheked.
Definition: NBEdge.h:100
T MAX2(T a, T b)
Definition: StdDefs.h:70
SUMOReal getLaneWidth() const
Returns the default width of lanes of this edge.
Definition: NBEdge.h:512
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:2735
PositionVector shape
The lane&#39;s shape.
Definition: NBNode.h:149
int myFromJunctionPriority
The priority normalised for the node the edge is outgoing of.
Definition: NBEdge.h:1354
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
Definition: Named.h:59
void computeLaneShapes()
compute lane shapes
Definition: NBEdge.cpp:1528
bool mayDefinitelyPass
Information about being definitely free to drive (on-ramps)
Definition: NBEdge.h:191
PositionVector getSubpartByIndex(int beginIndex, int count) const
get subpart of a position vector using index and a cout
SUMOReal getShapeStartAngle() const
Returns the angle at the start of the edge.
Definition: NBEdge.cpp:1616
PositionVector myGeom
The geometry for the edge.
Definition: NBEdge.h:1360
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:1084
#define RAD2DEG(x)
Definition: GeomHelper.h:46
SUMOReal distanceTo(const Position &p2) const
returns the euclidean distance in 3 dimension
Definition: Position.h:240
static const SUMOReal UNSPECIFIED_CONTPOS
unspecified internal junction position
Definition: NBEdge.h:253
const SUMOReal SUMO_const_laneOffset
Definition: StdDefs.h:51
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 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:247
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
PositionVector myFromBorder
intersection borders (because the node shape might be invalid)
Definition: NBEdge.h:1406
void restoreBikelane(std::vector< NBEdge::Lane > oldLanes, PositionVector oldGeometry, std::vector< NBEdge::Connection > oldConnections)
restore an previously added BikeLane
Definition: NBEdge.cpp:2879
void addOutgoingEdge(NBEdge *edge)
adds an outgoing edge
Definition: NBNode.cpp:426
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:499
static SUMOReal firstIntersection(const PositionVector &v1, const PositionVector &v2, SUMOReal width2)
compute the first intersection point between the given lane geometries considering their rspective wi...
Definition: NBEdge.cpp:1440
SUMOReal getLaneSpeed(int lane) const
get lane speed
Definition: NBEdge.cpp:1522
The link is a (hard) left direction.
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
void setz(SUMOReal z)
set position z
Definition: Position.h:88
bool isConnectedTo(const NBEdge *e) const
Returns the information whethe a connection to the given edge has been added (or computed) ...
Definition: NBEdge.cpp:983
The connection was computed and validated.
Definition: NBEdge.h:117
#define DEBUGCOND
Definition: NBEdge.cpp:62
SUMOReal distance2D(const Position &p, bool perpendicular=false) const
closest 2D-distance to point p (or -1 if perpendicular is true and the point is beyond this vector) ...
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:69
void reinit(NBNode *from, NBNode *to, const std::string &type, SUMOReal speed, 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:325
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:1389
SUMOReal vmax
maximun velocity
Definition: NBEdge.h:212
PositionVector reverse() const
reverse position vector
The edge has been loaded, nothing is computed yet.
Definition: NBEdge.h:94
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:1357
EdgeVector getConnectedEdges() const
Returns the list of outgoing edges unsorted.
Definition: NBEdge.cpp:1033
The link is a straight direction.
PositionVector shape
shape of Connection
Definition: NBEdge.h:209
void restoreSidewalk(std::vector< NBEdge::Lane > oldLanes, PositionVector oldGeometry, std::vector< NBEdge::Connection > oldConnections)
restore an previously added sidewalk
Definition: NBEdge.cpp:2867
SUMOReal speed
The speed allowed on this lane.
Definition: NBEdge.h:132
bool keepClear
whether the junction must be kept clear when using this connection
Definition: NBEdge.h:194
const EdgeVector & getOutgoingEdges() const
Returns this node&#39;s outgoing edges (The edges which start at this node)
Definition: NBNode.h:245
void extrapolate2D(const SUMOReal val, const bool onlyFirst=false)
extrapolate position vector in two dimensions (Z is ignored)
bool hasPermissions() const
whether at least one lane has restrictions
Definition: NBEdge.cpp:1632
SUMOReal getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn&#39;t set.
Definition: NBEdge.h:479
An (internal) definition of a single lane of an edge.
Definition: NBEdge.h:124
const std::string & getID() const
Returns the id.
Definition: Named.h:66
SUMOReal length2D() const
Returns the length.
SUMOReal mySpeed
The maximal speed.
Definition: NBEdge.h:1337
std::vector< SUMOReal > distances(const PositionVector &s, bool perpendicular=false) const
distances of all my points to s and all of s points to myself
void addLane(int index, bool recompute=true)
add lane
Definition: NBEdge.cpp:2556
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:672
bool addEdge2EdgeConnection(NBEdge *dest)
Adds a connection to another edge.
Definition: NBEdge.cpp:802
void incLaneNo(int by)
increment lane
Definition: NBEdge.cpp:2580
bool myAmMacroscopicConnector
Information whether this edge is a (macroscopic) connector.
Definition: NBEdge.h:1383
const PositionVector getInnerGeometry() const
Returns the geometry of the edge without the endpoints.
Definition: NBEdge.cpp:480
void push_front_noDoublePos(const Position &p)
insert in front a non double position
void reshiftPosition(SUMOReal xoff, SUMOReal yoff)
Applies an offset to the edge.
Definition: NBEdge.cpp:455
const Position & getPosition() const
Definition: NBNode.h:232
bool computeLanes2Edges()
computes the edge, step2: computation of which lanes approach the edges)
Definition: NBEdge.cpp:1718
#define max(a, b)
Definition: polyfonts.c:65
NBEdge * myTurnDestination
The turn destination edge (if a connection exists)
Definition: NBEdge.h:1348
Lanes to lanes - relationships are loaded; no recheck is necessary/wished.
Definition: NBEdge.h:104
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:948
int operator()(const Connection &c1, const Connection &c2) const
comparing operation
Definition: NBEdge.cpp:232
bool hasConnectionTo(NBEdge *destEdge, int destLane, int fromLane=-1) const
Retrieves info about a connection to a certain lane of a certain edge.
Definition: NBEdge.cpp:977
const std::set< NBTrafficLightDefinition * > & getControllingTLS() const
Returns the traffic lights that were assigned to this node (The set of tls that control this node) ...
Definition: NBNode.h:298
bool hasLaneSpecificSpeed() const
whether lanes differ in speed
Definition: NBEdge.cpp:1657
int getPriority() const
Returns the priority of the edge.
Definition: NBEdge.h:409
bool insert(NBEdge *edge, bool ignorePrunning=false)
Adds an edge to the dictionary.
Definition: NBEdgeCont.cpp:162
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:55
void checkGeometry(const SUMOReal maxAngle, const SUMOReal minRadius, bool fix)
Check the angles of successive geometry segments.
Definition: NBEdge.cpp:756
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:194
void decLaneNo(int by)
decrement lane
Definition: NBEdge.cpp:2606
NBEdge(const std::string &id, NBNode *from, NBNode *to, std::string type, SUMOReal speed, int nolanes, int priority, SUMOReal width, SUMOReal offset, const std::string &streetName="", LaneSpreadFunction spread=LANESPREAD_RIGHT)
Constructor.
Definition: NBEdge.cpp:243
std::string tlID
The id of the traffic light that controls this connection.
Definition: NBEdge.h:185
std::string getInternalLaneID() const
get ID of internal lane
Definition: NBEdge.cpp:82
int fromLane
The lane the connections starts at.
Definition: NBEdge.h:176
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:46
void deleteLane(int index, bool recompute=true)
delete lane
Definition: NBEdge.cpp:2591
A list of positions.
void add(SUMOReal xoff, SUMOReal yoff, SUMOReal zoff)
SUMOReal myEndAngle
Definition: NBEdge.h:1329
bool addLane2LaneConnections(int fromLane, NBEdge *dest, int toLane, int no, Lane2LaneInfoType type, bool invalidatePrevious=false, bool mayDefinitelyPass=false)
Builds no connections starting at the given lanes.
Definition: NBEdge.cpp:850
void moveOutgoingConnectionsFrom(NBEdge *e, int laneOff)
move outgoing connection
Definition: NBEdge.cpp:2253
bool hasLaneSpecificPermissions() const
whether lanes differ in allowed vehicle classes
Definition: NBEdge.cpp:1643
bool lanesWereAssigned() const
Check if lanes were assigned.
Definition: NBEdge.cpp:2267
static int computePrioritySum(const std::vector< int > &priorities)
computes the sum of the given list&#39;s entries (sic!)
Definition: NBEdge.cpp:2188
static const SUMOReal UNSPECIFIED_VISIBILITY_DISTANCE
unspecified foe visibility for connections
Definition: NBEdge.h:256
static bool connections_sorter(const Connection &c1, const Connection &c2)
connections_sorter sort by fromLane, toEdge and toLane
Definition: NBEdge.cpp:2793
const std::map< NBEdge *, std::vector< int > > & getBuiltConnections() const
get built connections
Definition: NBEdge.h:1189
SUMOReal z() const
Returns the z-position.
Definition: Position.h:73
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:257
bool geometryLike() const
whether this is structurally similar to a geometry node
Definition: NBNode.cpp:2515
NBEdge * myPossibleTurnDestination
The edge that would be the turn destination if there was one.
Definition: NBEdge.h:1351
PositionVector getCWBoundaryLine(const NBNode &n) const
get the outer boundary of this edge when going clock-wise around the given node
Definition: NBEdge.cpp:2373
bool addLane2LaneConnection(int fromLane, NBEdge *dest, int toLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, bool keepClear=true, SUMOReal contPos=UNSPECIFIED_CONTPOS, SUMOReal visibility=UNSPECIFIED_VISIBILITY_DISTANCE)
Adds a connection between the specified this edge&#39;s lane and an approached one.
Definition: NBEdge.cpp:826
bool hasLoadedLength() const
Returns whether a length was set explicitly.
Definition: NBEdge.h:489
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:402
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition: NBEdge.cpp:2226
SUMOReal contPos
custom position for internal junction on this connection
Definition: NBEdge.h:197
SUMOReal myLaneWidth
This width of this edge&#39;s lanes.
Definition: NBEdge.h:1369
int myPriority
The priority of the edge.
Definition: NBEdge.h:1334
int getFirstNonPedestrianLaneIndex(int direction, bool exclusive=false) const
return the first lane with permissions other than SVC_PEDESTRIAN and 0
Definition: NBEdge.cpp:2805
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:66
T MIN2(T a, T b)
Definition: StdDefs.h:64
std::string origID
origin ID
Definition: NBEdge.h:203
bool needsLaneSpecificOutput() const
whether at least one lane has values differing from the edges values
Definition: NBEdge.cpp:1690
std::vector< std::string > & split(const std::string &s, char delim, std::vector< std::string > &elems)
The link is a (hard) right direction.
Connection(int fromLane_, NBEdge *toEdge_, int toLane_)
Constructor.
Definition: NBEdge.cpp:93
EdgeBuildingStep myStep
The building step.
Definition: NBEdge.h:1315
bool canMoveConnection(const Connection &con, int newFromLane) const
whether the connection can originate on newFromLane
Definition: NBEdge.cpp:1236
#define POSITION_EPS
Definition: config.h:182
std::string getLaneIDInsecure(int lane) const
get Lane ID (Insecure)
Definition: NBEdge.cpp:2542
Class to sort edges by their angle.
Definition: NBEdge.h:1587
void buildInnerEdges(const NBNode &n, int noInternalNoSplits, int &linkIndex, int &splitIndex)
Definition: NBEdge.cpp:1273
#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:1498
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:1553
std::vector< Connection > myConnections
List of connections to following edges.
Definition: NBEdge.h:1342
void setLoadedLength(SUMOReal val)
set loaded lenght
Definition: NBEdge.cpp:2778
void execute(const int lane, const int virtEdge)
executes a bresenham - step
Definition: NBEdge.cpp:134
The connection was given by the user.
Definition: NBEdge.h:115
const PositionVector & getShape() const
retrieve the junction shape
Definition: NBNode.cpp:1720
SUMOReal getSignalOffset() const
Returns the offset of a traffic signal from the end of this edge.
Definition: NBEdge.h:547
void removeFromConnections(NBEdge *toEdge, int fromLane=-1, int toLane=-1, bool tryLater=false)
Removes the specified connection(s)
Definition: NBEdge.cpp:1100
The link is a partial right direction.
SUMOReal getEndOffset() const
Returns the offset to the destination node.
Definition: NBEdge.h:537
vehicle is a passenger car (a "normal" car)
bool myAmInnerEdge
Information whether this is a junction-inner edge.
Definition: NBEdge.h:1380
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:1436
Base class for objects which have an id.
Definition: Named.h:46
bool recheckLanes()
recheck whether all lanes within the edge are all right and optimises the connections once again ...
Definition: NBEdge.cpp:1742
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
Definition: NBEdge.cpp:1466
SUMOReal myLoadedLength
An optional length to use (-1 if not valid)
Definition: NBEdge.h:1377
PositionVector startShapeAt(const PositionVector &laneShape, const NBNode *startNode, PositionVector nodeShape) const
Definition: NBEdge.cpp:627
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
int internalLaneIndex
The lane index of this internal lane within the internal edge.
Definition: NBEdge.h:233
#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:2763
SUMOReal getCrossingAngle(NBNode *node)
return the angle for computing pedestrian crossings at the given node
Definition: NBEdge.cpp:2835
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 connections ...
Definition: NBEdge.cpp:2885
void setTurningDestination(NBEdge *e, bool onlyPossible=false)
Sets the turing destination at the given edge.
Definition: NBEdge.cpp:1513
static const int BACKWARD
Definition: NBNode.h:195
void addBikeLane(SUMOReal width)
add a bicycle lane of the given width and shift existing connctions
Definition: NBEdge.cpp:2873
std::string myID
The name of the object.
Definition: Named.h:136
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:423
std::vector< int > getConnectionLanes(NBEdge *currentOutgoing) const
Returns the list of lanes that may be used to reach the given edge.
Definition: NBEdge.cpp:1058
void removeDoublePoints(SUMOReal minDist=POSITION_EPS, bool assertLength=false)
Removes positions if too near.
void computeEdgeShape()
Recomputeds the lane shapes to terminate at the node shape For every lane the intersection with the f...
Definition: NBEdge.cpp:611
void addStraightConnections(const EdgeVector *outgoing, const std::vector< int > &availableLanes, const std::vector< int > *priorities)
add some straight connections
Definition: NBEdge.cpp:2018
PositionVector smoothedZFront(SUMOReal dist=std::numeric_limits< SUMOReal >::max()) const
returned vector that is smoothed at the front (within dist)
void disableConnection4TLS(int fromLane, NBEdge *toEdge, int toLane)
disable connections for TLS
Definition: NBEdge.cpp:2363
PositionVector viaShape
shape of via
Definition: NBEdge.h:224
SUMOReal angleAt2D(int pos) const
get angle in certain position of position vector
SUMOReal getMaxLaneOffset()
get max lane offset
Definition: NBEdge.cpp:2273
PositionVector myToBorder
Definition: NBEdge.h:1407
static const SUMOReal UNSPECIFIED_LOADED_LENGTH
no length override given
Definition: NBEdge.h:259
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:41
static const int UNSPECIFIED_INTERNAL_LANE_INDEX
internal lane computation not yet done
Definition: NBEdge.h:267
SUMOReal myLength
The length of the edge.
Definition: NBEdge.h:1324
void setPreferredVehicleClass(SVCPermissions permissions, int lane=-1)
set preferred Vehicle Class
Definition: NBEdge.cpp:2749
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:584
The edge has been loaded and connections shall not be added.
Definition: NBEdge.h:92
int getToLane() const
returns the to-lane
std::vector< Connection > myConnectionsToDelete
List of connections marked for delayed removal.
Definition: NBEdge.h:1345
void reduceGeometry(const SUMOReal minDist)
Removes points with a distance lesser than the given.
Definition: NBEdge.cpp:750
void setJunctionPriority(const NBNode *const node, int prio)
Sets the junction priority of the edge.
Definition: NBEdge.cpp:1476
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
Definition: NBNodeCont.cpp:81
const EdgeVector * getConnectedSorted()
Returns the list of outgoing edges without the turnaround sorted in clockwise direction.
Definition: NBEdge.cpp:996
void restoreRestrictedLane(SUMOVehicleClass vclass, std::vector< NBEdge::Lane > oldLanes, PositionVector oldGeometry, std::vector< NBEdge::Connection > oldConnections)
restore a restricted lane
Definition: NBEdge.cpp:2919
void sortOutgoingConnectionsByIndex()
sorts the outgoing connections by their from-lane-index and their to-lane-index
Definition: NBEdge.cpp:1078
SUMOReal mySignalOffset
the offset of a traffic light signal from the end of this edge (-1 for None)
Definition: NBEdge.h:1402
std::string myType
The type of the edge.
Definition: NBEdge.h:1318
LaneSpreadFunction
Numbers representing special SUMO-XML-attribute values Information how the edge&#39;s lateral offset shal...
void append(NBEdge *continuation)
append another edge
Definition: NBEdge.cpp:2488
NBEdge * getTo() const
returns the to-edge (end of the connection)
NBNode * tryGetNodeAtPosition(SUMOReal pos, SUMOReal tolerance=5.0) const
Returns the node at the given edges length (using an epsilon)
Definition: NBEdge.cpp:2239
The connection was computed.
Definition: NBEdge.h:113
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge&#39;s lanes&#39; lateral offset is computed.
Definition: NBEdge.h:653
SUMOReal myStartAngle
The angles of the edge.
Definition: NBEdge.h:1328
EdgeVector edges
The edges being crossed.
Definition: NBNode.h:147
Represents a single node (junction) during network building.
Definition: NBNode.h:75
PositionVector computeLaneShape(int lane, SUMOReal offset) const
Computes the shape for the given lane.
Definition: NBEdge.cpp:1568
MainDirections(const EdgeVector &outgoing, NBEdge *parent, NBNode *to, int indexOfStraightest)
constructor
Definition: NBEdge.cpp:165
void dismissVehicleClassInformation()
dimiss vehicle class information
Definition: NBEdge.cpp:2784
bool hasSignalisedConnectionTo(const NBEdge *const e) const
Check if edge has signalised connections.
Definition: NBEdge.cpp:2516
Lanes to lanes - relationships are computed; no recheck is necessary/wished.
Definition: NBEdge.h:102
A definition of a pedestrian crossing.
Definition: NBNode.h:135
void move2side(SUMOReal amount)
move position vector to side using certain ammount
void replaceInConnections(NBEdge *which, NBEdge *by, int laneOff)
replace in current connections of edge
Definition: NBEdge.cpp:1160
bool hasLaneSpecificWidth() const
whether lanes differ in width
Definition: NBEdge.cpp:1668
void setEndOffset(int lane, SUMOReal offset)
set lane specific end-offset (negative lane implies set for all lanes)
Definition: NBEdge.cpp:2703
void appendTurnaround(bool noTLSControlled, bool checkPermissions)
Add a connection to the previously computed turnaround, if wished.
Definition: NBEdge.cpp:2198
static void compute(BresenhamCallBack *callBack, const int val1, const int val2)
Definition: Bresenham.cpp:45
Direction
enum of possible directions
Definition: NBEdge.h:1212
#define SUMOReal
Definition: config.h:208
bool isNearEnough2BeJoined2(NBEdge *e, SUMOReal threshold) const
Check if edge is near enought to be joined to another edge.
Definition: NBEdge.cpp:2548
void preferVehicleClass(int lane, SUMOVehicleClass vclass)
prefer certain vehicle class
Definition: NBEdge.cpp:2651
#define NUMERICAL_EPS
Definition: config.h:158
void push_back_noDoublePos(const Position &p)
insert in back a non double position
std::string getLaneID(int lane) const
get Lane ID (Secure)
Definition: NBEdge.cpp:2536
void allowVehicleClass(int lane, SUMOVehicleClass vclass)
set allowed class for the given lane or for all lanes if -1 is given
Definition: NBEdge.cpp:2625
void insertConnection(NBEdge::Connection connection)
insert a previously created NBEdge::connection
Definition: NBEdge.cpp:930
void addGeometryPoint(int index, const Position &p)
Adds a further geometry point.
Definition: NBEdge.cpp:695
void shiftToLanesToEdge(NBEdge *to, int laneOff)
modifify the toLane for all connections to the given edge
Definition: NBEdge.cpp:2942
SUMOReal getShapeEndAngle() const
Returns the angle at the end of the edge.
Definition: NBEdge.cpp:1624
void computeAngle()
computes the angle of this edge and stores it in myAngle
Definition: NBEdge.cpp:1580
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
Definition: NBNodeCont.cpp:110
SUMOReal getSpeed() const
Returns the speed allowed on this edge.
Definition: NBEdge.h:496
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:63
SUMOReal getFinalLength() const
get length that will be assigned to the lanes in the final network
Definition: NBEdge.cpp:2978
bool computeEdge2Edges(bool noLeftMovers)
computes the edge (step1: computation of approached edges)
Definition: NBEdge.cpp:1697
static T maxValue(const std::vector< T > &v)
Definition: VectorHelper.h:98
bool haveVia
check if Connection have a Via
Definition: NBEdge.h:215
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:1465
void setLaneSpreadFunction(LaneSpreadFunction spread)
(Re)sets how the lanes lateral offset shall be computed
Definition: NBEdge.cpp:689
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:201
void divideSelectedLanesOnEdges(const EdgeVector *outgoing, const std::vector< int > &availableLanes, const std::vector< int > *priorities)
divide selected lanes on edges
Definition: NBEdge.cpp:1908
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 ...
std::set< SVCPermissions > getPermissionVariants(int iStart, int iEnd) const
return all permission variants within the specified lane range [iStart, iEnd[
Definition: NBEdge.cpp:2822
Lanes to edges - relationships are computed/loaded.
Definition: NBEdge.h:98
std::string myStreetName
The street name (or whatever arbitrary string you wish to attach)
Definition: NBEdge.h:1396
const std::string & getStreetName() const
Returns the street name of this edge.
Definition: NBEdge.h:525
NBNode * myFrom
The source and the destination node.
Definition: NBEdge.h:1321
bool expandableBy(NBEdge *possContinuation) const
Check if Node is expandable.
Definition: NBEdge.cpp:2409
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition: NBEdge.cpp:2527
Connection & getConnectionRef(int fromLane, const NBEdge *to, int toLane)
Returns reference to the specified connection This method goes through "myConnections" and returns th...
Definition: NBEdge.cpp:962
bool setConnection(int lane, NBEdge *destEdge, int destLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, bool keepClear=true, SUMOReal contPos=UNSPECIFIED_CONTPOS, SUMOReal visibility=UNSPECIFIED_VISIBILITY_DISTANCE)
Adds a connection to a certain lane of a certain edge.
Definition: NBEdge.cpp:867
std::vector< int > foeInternalLinks
FOE Internal links.
Definition: NBEdge.h:227
PositionVector getSubpart(SUMOReal beginOffset, SUMOReal endOffset) const
get subpart of a position vector
~MainDirections()
destructor
Definition: NBEdge.cpp:213
const PositionVector & getLaneShape(int i) const
Returns the shape of the nth lane.
Definition: NBEdge.cpp:683
static bool isTrafficLight(SumoXMLNodeType type)
return whether the given type is a traffic light
Definition: NBNode.cpp:2682
void shiftPositionAtNode(NBNode *node, NBEdge *opposite)
shift geometry at the given node to avoid overlap
Definition: NBEdge.cpp:2953
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
Definition: ToString.h:188
void disallowVehicleClass(int lane, SUMOVehicleClass vclass)
set disallowed class for the given lane or for all lanes if -1 is given
Definition: NBEdge.cpp:2638
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:260
void append(const PositionVector &v, SUMOReal sameThreshold=2.0)
void extrapolate(const SUMOReal val, const bool onlyFirst=false)
extrapolate position vector
static const SUMOReal INVALID_OFFSET
a value to signify offsets outside the range of [0, Line.length()]
Definition: GeomHelper.h:59
void copyConnectionsFrom(NBEdge *src)
copy connections from antoher edge
Definition: NBEdge.cpp:1229
A class that being a bresenham-callback assigns the incoming lanes to the edges.
Definition: NBEdge.h:1169
static const SUMOReal ANGLE_LOOKAHEAD
the distance at which to take the default angle
Definition: NBEdge.h:265
SUMOReal getLength() const
Returns the computed length of the edge.
Definition: NBEdge.h:470
SUMOReal getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge&#39;s geometry at the given node.
Definition: NBEdge.cpp:1486
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:1455
SUMOReal visibility
custom foe visiblity for connection
Definition: NBEdge.h:200
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:416
bool splitGeometry(NBEdgeCont &ec, NBNodeCont &nc)
Splits this edge at geometry points.
Definition: NBEdge.cpp:705