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