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