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