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