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-sim.org/
14 // Copyright (C) 2001-2013 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 // ===========================================================================
62 // static members
63 // ===========================================================================
68 
69 // ===========================================================================
70 // method definitions
71 // ===========================================================================
72 std::string
74  return id + "_" + toString(internalLaneIndex);
75 }
76 
77 /* -------------------------------------------------------------------------
78  * NBEdge::ToEdgeConnectionsAdder-methods
79  * ----------------------------------------------------------------------- */
80 void
81 NBEdge::ToEdgeConnectionsAdder::execute(const unsigned int lane, const unsigned int virtEdge) {
82  // check
83  assert(myTransitions.size() > virtEdge);
84  // get the approached edge
85  NBEdge* succEdge = myTransitions[virtEdge];
86  std::vector<unsigned int> lanes;
87 
88  // check whether the currently regarded, approached edge has already
89  // a connection starting at the edge which is currently being build
90  std::map<NBEdge*, std::vector<unsigned int> >::iterator i = myConnections.find(succEdge);
91  if (i != myConnections.end()) {
92  // if there were already lanes assigned, get them
93  lanes = (*i).second;
94  }
95 
96  // check whether the current lane was already used to connect the currently
97  // regarded approached edge
98  std::vector<unsigned int>::iterator j = find(lanes.begin(), lanes.end(), lane);
99  if (j == lanes.end()) {
100  // if not, add it to the list
101  lanes.push_back(lane);
102  }
103  // set information about connecting lanes
104  myConnections[succEdge] = lanes;
105 }
106 
107 
108 
109 /* -------------------------------------------------------------------------
110  * NBEdge::MainDirections-methods
111  * ----------------------------------------------------------------------- */
113  NBEdge* parent, NBNode* to) {
114  if (outgoing.size() == 0) {
115  return;
116  }
117  // check whether the right turn has a higher priority
118  assert(outgoing.size() > 0);
119  if (outgoing[0]->getJunctionPriority(to) == 1) {
120  myDirs.push_back(MainDirections::DIR_RIGHTMOST);
121  }
122  // check whether the left turn has a higher priority
123  if (outgoing.back()->getJunctionPriority(to) == 1) {
124  // ok, the left turn belongs to the higher priorised edges on the junction
125  // let's check, whether it has also a higher priority (lane number/speed)
126  // than the current
127  EdgeVector tmp(outgoing);
128  sort(tmp.begin(), tmp.end(), NBContHelper::edge_similar_direction_sorter(parent));
129  if (outgoing.back()->getPriority() > tmp[0]->getPriority()) {
130  myDirs.push_back(MainDirections::DIR_LEFTMOST);
131  } else {
132  if (outgoing.back()->getNumLanes() > tmp[0]->getNumLanes()) {
133  myDirs.push_back(MainDirections::DIR_LEFTMOST);
134  }
135  }
136  }
137  // check whether the forward direction has a higher priority
138  // try to get the forward direction
139  EdgeVector tmp(outgoing);
140  sort(tmp.begin(), tmp.end(), NBContHelper::edge_similar_direction_sorter(parent));
141  NBEdge* edge = *(tmp.begin());
142  // check whether it has a higher priority and is going straight
143  if (edge->getJunctionPriority(to) == 1 && to->getDirection(parent, edge) == LINKDIR_STRAIGHT) {
144  myDirs.push_back(MainDirections::DIR_FORWARD);
145  }
146 }
147 
148 
150 
151 
152 bool
154  return myDirs.empty();
155 }
156 
157 
158 bool
160  return find(myDirs.begin(), myDirs.end(), d) != myDirs.end();
161 }
162 
163 
164 /* -------------------------------------------------------------------------
165  * NBEdge::connections_relative_edgelane_sorter-methods
166  * ----------------------------------------------------------------------- */
167 int
169  if (c1.toEdge != c2.toEdge) {
171  }
172  return c1.toLane < c2.toLane;
173 }
174 
175 
176 /* -------------------------------------------------------------------------
177  * NBEdge-methods
178  * ----------------------------------------------------------------------- */
179 NBEdge::NBEdge(const std::string& id, NBNode* from, NBNode* to,
180  std::string type, SUMOReal speed, unsigned int nolanes,
181  int priority, SUMOReal laneWidth, SUMOReal offset,
182  const std::string& streetName,
183  LaneSpreadFunction spread) :
184  Named(StringUtils::convertUmlaute(id)),
185  myStep(INIT),
186  myType(StringUtils::convertUmlaute(type)),
187  myFrom(from), myTo(to),
189  myPriority(priority), mySpeed(speed),
192  myLaneSpreadFunction(spread), myOffset(offset), myLaneWidth(laneWidth),
195  myStreetName(streetName) {
196  init(nolanes, false);
197 }
198 
199 
200 NBEdge::NBEdge(const std::string& id, NBNode* from, NBNode* to,
201  std::string type, SUMOReal speed, unsigned int nolanes,
202  int priority, SUMOReal laneWidth, SUMOReal offset,
203  PositionVector geom,
204  const std::string& streetName,
205  LaneSpreadFunction spread, bool tryIgnoreNodePositions) :
206  Named(StringUtils::convertUmlaute(id)),
207  myStep(INIT),
208  myType(StringUtils::convertUmlaute(type)),
209  myFrom(from), myTo(to),
210  myStartAngle(0), myEndAngle(0), myTotalAngle(0),
211  myPriority(priority), mySpeed(speed),
212  myTurnDestination(0),
213  myFromJunctionPriority(-1), myToJunctionPriority(-1),
214  myGeom(geom), myLaneSpreadFunction(spread), myOffset(offset), myLaneWidth(laneWidth),
215  myLoadedLength(UNSPECIFIED_LOADED_LENGTH), myAmLeftHand(false),
216  myAmInnerEdge(false), myAmMacroscopicConnector(false),
217  myStreetName(streetName) {
218  init(nolanes, tryIgnoreNodePositions);
219 }
220 
221 
222 NBEdge::NBEdge(const std::string& id, NBNode* from, NBNode* to, NBEdge* tpl) :
223  Named(StringUtils::convertUmlaute(id)),
224  myStep(INIT),
225  myType(tpl->getTypeID()),
226  myFrom(from), myTo(to),
227  myStartAngle(0), myEndAngle(0), myTotalAngle(0),
228  myPriority(tpl->getPriority()), mySpeed(tpl->getSpeed()),
229  myTurnDestination(0),
230  myFromJunctionPriority(-1), myToJunctionPriority(-1),
231  myLaneSpreadFunction(tpl->getLaneSpreadFunction()),
232  myOffset(tpl->getOffset()),
233  myLaneWidth(tpl->getLaneWidth()),
234  myLoadedLength(UNSPECIFIED_LOADED_LENGTH), myAmLeftHand(false),
235  myAmInnerEdge(false), myAmMacroscopicConnector(false),
236  myStreetName(tpl->getStreetName()) {
237  init(tpl->getNumLanes(), false);
238  for (unsigned int i = 0; i < getNumLanes(); i++) {
239  setSpeed(i, tpl->getLaneSpeed(i));
240  setPermissions(tpl->getPermissions(i), i);
241  }
242 }
243 
244 
245 void
246 NBEdge::reinit(NBNode* from, NBNode* to, const std::string& type,
247  SUMOReal speed, unsigned int nolanes, int priority,
248  PositionVector geom, SUMOReal laneWidth, SUMOReal offset,
249  const std::string& streetName,
250  LaneSpreadFunction spread,
251  bool tryIgnoreNodePositions) {
252  if (myFrom != from) {
253  myFrom->removeEdge(this, false);
254  }
255  if (myTo != to) {
256  myTo->removeEdge(this, false);
257  }
259  myFrom = from;
260  myTo = to;
261  myPriority = priority;
262  mySpeed = speed;
263  //?myTurnDestination(0),
264  //?myFromJunctionPriority(-1), myToJunctionPriority(-1),
265  myGeom = geom;
266  myLaneSpreadFunction = spread;
267  myOffset = offset;
268  myLaneWidth = laneWidth;
270  myStreetName = streetName;
271  //?, myAmTurningWithAngle(0), myAmTurningOf(0),
272  //?myAmInnerEdge(false), myAmMacroscopicConnector(false)
273  init(nolanes, tryIgnoreNodePositions);
274 }
275 
276 
277 void
279  // connections may still be valid
280  if (from == 0 || to == 0) {
281  throw ProcessError("At least one of edge's '" + myID + "' nodes is not known.");
282  }
283  if (myFrom != from) {
284  myFrom->removeEdge(this, false);
285  myFrom = from;
286  myFrom->addOutgoingEdge(this);
287  }
288  if (myTo != to) {
289  myTo->removeEdge(this, false);
290  myTo = to;
291  myTo->addIncomingEdge(this);
292  }
293 }
294 
295 
296 void
297 NBEdge::init(unsigned int noLanes, bool tryIgnoreNodePositions) {
298  if (noLanes == 0) {
299  throw ProcessError("Edge '" + myID + "' needs at least one lane.");
300  }
301  if (myFrom == 0 || myTo == 0) {
302  throw ProcessError("At least one of edge's '" + myID + "' nodes is not known.");
303  }
304  // revisit geometry
305  // should have at least two points at the end...
306  // and in dome cases, the node positions must be added
308  if (!tryIgnoreNodePositions || myGeom.size() < 2) {
309  if (myGeom.size() == 0) {
312  } else {
315  }
316  }
317  if (myGeom.size() < 2) {
318  myGeom.clear();
321  }
322  if (myGeom.size() == 2 && myGeom[0] == myGeom[1]) {
323  WRITE_ERROR("Edge's '" + myID + "' from- and to-node are at the same position.");
325  }
326  //
327  myFrom->addOutgoingEdge(this);
328  myTo->addIncomingEdge(this);
329  // prepare container
331  assert(myGeom.size() >= 2);
332  myLanes.clear();
333  for (unsigned int i = 0; i < noLanes; i++) {
334  myLanes.push_back(Lane(this));
335  }
337  computeAngle();
338 }
339 
340 
342 
343 
344 // ----------- Applying offset
345 void
347  myGeom.reshiftRotate(xoff, yoff, 0);
348  for (unsigned int i = 0; i < myLanes.size(); i++) {
349  myLanes[i].shape.reshiftRotate(xoff, yoff, 0);
350  }
351 }
352 
353 
354 // ----------- Edge geometry access and computation
355 const PositionVector
357  PositionVector result = getGeometry();
358  result.pop_front();
359  result.pop_back();
360  return result;
361 }
362 
363 
364 bool
366  return myGeom.size() == 2 && hasDefaultGeometryEndpoints();
367 }
368 
369 
370 bool
372  return myGeom.front() == myFrom->getPosition() &&
373  myGeom.back() == myTo->getPosition();
374 }
375 
376 
377 void
378 NBEdge::setGeometry(const PositionVector& s, bool inner) {
379  Position begin = myGeom.front(); // may differ from node position
380  Position end = myGeom.back(); // may differ from node position
381  myGeom = s;
382  if (inner) {
383  myGeom.push_front(begin);
384  myGeom.push_back(end);
385  }
387  computeAngle();
388 }
389 
390 
391 void
393  for (unsigned int i = 0; i < myLanes.size(); i++) {
394  PositionVector& shape = myLanes[i].shape;
395  PositionVector old = shape;
396  shape = startShapeAt(shape, myFrom);
397  if (shape.size() >= 2) {
398  shape = startShapeAt(shape.reverse(), myTo).reverse();
399  }
400  // sanity checks
401  if (shape.length() < POSITION_EPS) {
402  if (old.length() < 2 * POSITION_EPS) {
403  shape = old;
404  } else {
405  const SUMOReal midpoint = old.length() / 2;
406  // EPS*2 because otherwhise shape has only a single point
407  shape = old.getSubpart(midpoint - POSITION_EPS, midpoint + POSITION_EPS);
408  assert(shape.size() >= 2);
409  assert(shape.length() > 0);
410  }
411  } else {
412  // @note If the node shapes are overlapping we may get a shape which goes in the wrong direction
413  // in this case the result shape should shortened
414  Line lc(shape[0], shape[-1]);
415  Line lo(old[0], old[-1]);
417  shape = shape.reverse();
418  shape = shape.getSubpart(0, 2 * POSITION_EPS); // *2 because otherwhise shape has only a single point
419  }
420  }
421  }
422  // recompute edge's length as the average of lane lenghts
423  SUMOReal avgLength = 0;
424  for (unsigned int i = 0; i < myLanes.size(); i++) {
425  assert(myLanes[i].shape.length() > 0);
426  avgLength += myLanes[i].shape.length();
427  }
428  myLength = avgLength / (SUMOReal) myLanes.size();
429 }
430 
431 
433 NBEdge::startShapeAt(const PositionVector& laneShape, const NBNode* startNode) const {
434  const PositionVector& nodeShape = startNode->getShape();
435  Line lb = laneShape.getBegLine();
436  // this doesn't look reasonable @todo use lb.extrapolateFirstBy(100.0);
437  lb.extrapolateBy(100.0);
438  if (nodeShape.intersects(laneShape)) {
439  // shape intersects directly
440  std::vector<SUMOReal> pbv = laneShape.intersectsAtLengths2D(nodeShape);
441  assert(pbv.size() > 0);
443  assert(pb >= 0);
444  PositionVector ns = pb <= laneShape.length() ? laneShape.getSubpart2D(pb, laneShape.length()) : laneShape;
445  ns[0].set(ns[0].x(), ns[0].y(), startNode->getPosition().z());
446  return ns;
447  } else if (nodeShape.intersects(lb.p1(), lb.p2())) {
448  // extension of first segment intersects
449  std::vector<SUMOReal> pbv = lb.intersectsAtLengths2D(nodeShape);
450  assert(pbv.size() > 0);
452  assert(pb >= 0);
453  PositionVector result = laneShape;
454  result.eraseAt(0);
455  Position np = lb.getPositionAtDistance2D(pb);
456  result.push_front_noDoublePos(Position(np.x(), np.y(), startNode->getPosition().z()));
457  return result;
458  //if (result.size() >= 2) {
459  // return result;
460  //} else {
461  // WRITE_WARNING(error + " (resulting shape is too short)");
462  // return laneShape;
463  //}
464  } else {
465  // could not find proper intersection. Probably the edge is very short
466  // and lies within nodeShape
467  // @todo enable warning WRITE_WARNING(error + " (laneShape lies within nodeShape)");
468  return laneShape;
469  }
470 }
471 
472 
473 const PositionVector&
474 NBEdge::getLaneShape(unsigned int i) const {
475  return myLanes[i].shape;
476 }
477 
478 
479 void
481  myLaneSpreadFunction = spread;
482 }
483 
484 
485 void
486 NBEdge::addGeometryPoint(int index, const Position& p) {
487  myGeom.insertAt(index, p);
488 }
489 
490 
491 bool
493  // check whether there any splits to perform
494  if (myGeom.size() < 3) {
495  return false;
496  }
497  // ok, split
498  NBNode* newFrom = myFrom;
499  NBNode* myLastNode = myTo;
500  NBNode* newTo = 0;
501  NBEdge* currentEdge = this;
502  for (int i = 1; i < (int) myGeom.size() - 1; i++) {
503  // build the node first
504  if (i != (int)myGeom.size() - 2) {
505  std::string nodename = myID + "_in_between#" + toString(i);
506  if (!nc.insert(nodename, myGeom[i])) {
507  throw ProcessError("Error on adding in-between node '" + nodename + "'.");
508  }
509  newTo = nc.retrieve(nodename);
510  } else {
511  newTo = myLastNode;
512  }
513  if (i == 1) {
514  currentEdge->myTo->removeEdge(this);
515  currentEdge->myTo = newTo;
516  newTo->addIncomingEdge(currentEdge);
517  } else {
518  std::string edgename = myID + "[" + toString(i - 1) + "]";
519  // @bug lane-specific width, speed, overall offset and restrictions are ignored
520  currentEdge = new NBEdge(edgename, newFrom, newTo, myType, mySpeed, (unsigned int) myLanes.size(),
522  if (!ec.insert(currentEdge, true)) {
523  throw ProcessError("Error on adding splitted edge '" + edgename + "'.");
524  }
525  }
526  newFrom = newTo;
527  }
528  myGeom.clear();
531  myStep = INIT;
532  return true;
533 }
534 
535 
536 void
538  myGeom.removeDoublePoints(minDist, true);
539 }
540 
541 
542 void
543 NBEdge::checkGeometry(const SUMOReal maxAngle, const SUMOReal minRadius, bool fix) {
544  if (myGeom.size() < 3) {
545  return;
546  }
547  //std::cout << "checking geometry of " << getID() << " geometry = " << toString(myGeom) << "\n";
548  std::vector<SUMOReal> angles; // absolute segment angles
549  //std::cout << " absolute angles:";
550  for (int i = 0; i < (int)myGeom.size() - 1; ++i) {
551  angles.push_back(myGeom.lineAt(i).atan2DegreeAngle());
552  //std::cout << " " << angles.back();
553  }
554  //std::cout << "\n relative angles: ";
555  for (int i = 0; i < (int)angles.size() - 1; ++i) {
556  const SUMOReal relAngle = fabs(NBHelpers::relAngle(angles[i], angles[i + 1]));
557  //std::cout << relAngle << " ";
558  if (maxAngle > 0 && relAngle > maxAngle) {
559  WRITE_WARNING("Found angle of " + toString(relAngle) + " degrees at edge " + getID() + ", segment " + toString(i));
560  }
561  if (relAngle < 1) {
562  continue;
563  }
564  if (i == 0 || i == (int)angles.size() - 2) {
565  const bool start = i == 0;
566  const Line l = (start ? myGeom.getBegLine() : myGeom.getEndLine());
567  const SUMOReal r = tan(DEG2RAD(90 - 0.5 * relAngle)) * l.length2D();
568  //std::cout << (start ? " start" : " end") << " length=" << l.length2D() << " radius=" << r << " ";
569  if (minRadius > 0 && r < minRadius) {
570  if (fix) {
571  WRITE_MESSAGE("Removing sharp turn with radius " + toString(r) + " at the " +
572  (start ? "start" : "end") + " of edge " + getID());
573  myGeom.eraseAt(start ? 1 : i + 1);
574  checkGeometry(maxAngle, minRadius, fix);
575  return;
576  } else {
577  WRITE_WARNING("Found sharp turn with radius " + toString(r) + " at the " +
578  (start ? "start" : "end") + " of edge " + getID());
579  }
580  }
581  }
582  }
583  //std::cout << "\n";
584 }
585 
586 
587 // ----------- Setting and getting connections
588 bool
591  return true;
592  }
593  // check whether the node was merged and now a connection between
594  // not matching edges is tried to be added
595  // This happens f.e. within the ptv VISSIM-example "Beijing"
596  if (dest != 0 && myTo != dest->myFrom) {
597  return false;
598  }
599  if (dest == 0) {
601  myConnections.push_back(Connection(-1, dest, -1));
602  } else if (find_if(myConnections.begin(), myConnections.end(), connections_toedge_finder(dest)) == myConnections.end()) {
603  myConnections.push_back(Connection(-1, dest, -1));
604  }
605  if (myStep < EDGE2EDGES) {
606  myStep = EDGE2EDGES;
607  }
608  return true;
609 }
610 
611 
612 bool
613 NBEdge::addLane2LaneConnection(unsigned int from, NBEdge* dest,
614  unsigned int toLane, Lane2LaneInfoType type,
615  bool mayUseSameDestination,
616  bool mayDefinitelyPass) {
618  return true;
619  }
620  // check whether the node was merged and now a connection between
621  // not matching edges is tried to be added
622  // This happens f.e. within the ptv VISSIM-example "Beijing"
623  if (myTo != dest->myFrom) {
624  return false;
625  }
626  if (!addEdge2EdgeConnection(dest)) {
627  return false;
628  }
629  setConnection(from, dest, toLane, type, mayUseSameDestination, mayDefinitelyPass);
630  return true;
631 }
632 
633 
634 bool
635 NBEdge::addLane2LaneConnections(unsigned int fromLane,
636  NBEdge* dest, unsigned int toLane,
637  unsigned int no, Lane2LaneInfoType type,
638  bool invalidatePrevious,
639  bool mayDefinitelyPass) {
640  if (invalidatePrevious) {
641  invalidateConnections(true);
642  }
643  bool ok = true;
644  for (unsigned int i = 0; i < no && ok; i++) {
645  ok &= addLane2LaneConnection(fromLane + i, dest, toLane + i, type, false, mayDefinitelyPass);
646  }
647  return ok;
648 }
649 
650 
651 void
652 NBEdge::setConnection(unsigned int lane, NBEdge* destEdge,
653  unsigned int destLane, Lane2LaneInfoType type,
654  bool mayUseSameDestination,
655  bool mayDefinitelyPass) {
657  return;
658  }
659  // some kind of a misbehaviour which may occure when the junction's outgoing
660  // edge priorities were not properly computed, what may happen due to
661  // an incomplete or not proper input
662  // what happens is that under some circumstances a single lane may set to
663  // be approached more than once by the one of our lanes.
664  // This must not be!
665  // we test whether it is the case and do nothing if so - the connection
666  // will be refused
667  //
668  if (!mayUseSameDestination && hasConnectionTo(destEdge, destLane)) {
669  return;
670  }
671  if (find_if(myConnections.begin(), myConnections.end(), connections_finder(lane, destEdge, destLane)) != myConnections.end()) {
672  return;
673  }
674  if (myLanes.size() <= lane) {
675  WRITE_ERROR("Could not set connection from '" + getLaneIDInsecure(lane) + "' to '" + destEdge->getLaneIDInsecure(destLane) + "'.");
676  return;
677  }
678  if (destEdge->getNumLanes() <= destLane) {
679  WRITE_ERROR("Could not set connection from '" + getLaneIDInsecure(lane) + "' to '" + destEdge->getLaneIDInsecure(destLane) + "'.");
680  return;
681  }
682  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end();) {
683  if ((*i).toEdge == destEdge && ((*i).fromLane == -1 || (*i).toLane == -1)) {
684  i = myConnections.erase(i);
685  } else {
686  ++i;
687  }
688  }
689  myConnections.push_back(Connection(lane, destEdge, destLane));
690  if (mayDefinitelyPass) {
691  myConnections.back().mayDefinitelyPass = true;
692  }
693  if (type == L2L_USER) {
695  } else {
696  // check whether we have to take another look at it later
697  if (type == L2L_COMPUTED) {
698  // yes, the connection was set using an algorithm which requires a recheck
700  } else {
701  // ok, let's only not recheck it if we did no add something that has to be recheked
702  if (myStep != LANES2LANES_RECHECK) {
704  }
705  }
706  }
707 }
708 
709 
710 std::vector<NBEdge::Connection>
711 NBEdge::getConnectionsFromLane(unsigned int lane) const {
712  std::vector<NBEdge::Connection> ret;
713  for (std::vector<Connection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
714  if ((*i).fromLane == static_cast<int>(lane)) {
715  ret.push_back(*i);
716  }
717  }
718  return ret;
719 }
720 
721 
722 bool
723 NBEdge::hasConnectionTo(NBEdge* destEdge, unsigned int destLane) const {
724  return destEdge != 0 && find_if(myConnections.begin(), myConnections.end(), connections_toedgelane_finder(destEdge, destLane)) != myConnections.end();
725 }
726 
727 
728 bool
730  if (e == myTurnDestination) {
731  return true;
732  }
733  return
734  find_if(myConnections.begin(), myConnections.end(), connections_toedge_finder(e))
735  !=
736  myConnections.end();
737 
738 }
739 
740 
741 const EdgeVector*
743  // check whether connections exist and if not, use edges from the node
744  EdgeVector outgoing;
745  if (myConnections.size() == 0) {
746  outgoing = myTo->getOutgoingEdges();
747  } else {
748  for (std::vector<Connection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
749  if (find(outgoing.begin(), outgoing.end(), (*i).toEdge) == outgoing.end()) {
750  outgoing.push_back((*i).toEdge);
751  }
752  }
753  }
754  // allocate the sorted container
755  unsigned int size = (unsigned int) outgoing.size();
756  EdgeVector* edges = new EdgeVector();
757  edges->reserve(size);
758  for (EdgeVector::const_iterator i = outgoing.begin(); i != outgoing.end(); i++) {
759  NBEdge* outedge = *i;
760  if (outedge != 0 && outedge != myTurnDestination) {
761  edges->push_back(outedge);
762  }
763  }
764  sort(edges->begin(), edges->end(), NBContHelper::relative_outgoing_edge_sorter(this));
765  return edges;
766 }
767 
768 
771  EdgeVector ret;
772  for (std::vector<Connection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
773  if (find(ret.begin(), ret.end(), (*i).toEdge) == ret.end()) {
774  ret.push_back((*i).toEdge);
775  }
776  }
777  return ret;
778 }
779 
780 
781 std::vector<int>
782 NBEdge::getConnectionLanes(NBEdge* currentOutgoing) const {
783  std::vector<int> ret;
784  if (currentOutgoing != myTurnDestination) {
785  for (std::vector<Connection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
786  if ((*i).toEdge == currentOutgoing) {
787  ret.push_back((*i).fromLane);
788  }
789  }
790  }
791  return ret;
792 }
793 
794 
795 void
798 }
799 
800 
801 void
803  sort(myConnections.begin(), myConnections.end(), connections_sorter);
804 }
805 
806 
807 void
809  EdgeVector connected = getConnectedEdges();
810  for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
811  NBEdge* inc = *i;
812  // We have to do this
813  inc->myStep = EDGE2EDGES;
814  // add all connections
815  for (EdgeVector::iterator j = connected.begin(); j != connected.end(); j++) {
816  inc->addEdge2EdgeConnection(*j);
817  }
818  inc->removeFromConnections(this);
819  }
820 }
821 
822 
823 void
824 NBEdge::removeFromConnections(NBEdge* toEdge, int fromLane, int toLane, bool tryLater) {
825  // remove from "myConnections"
826  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end();) {
827  Connection& c = *i;
828  if (c.toEdge == toEdge
829  && (fromLane < 0 || c.fromLane == fromLane)
830  && (toLane < 0 || c.toLane == toLane)) {
831  i = myConnections.erase(i);
832  tryLater = false;
833  } else {
834  ++i;
835  }
836  }
837  // check whether it was the turn destination
838  if (myTurnDestination == toEdge && fromLane < 0) {
839  myTurnDestination = 0;
840  }
841  if (tryLater) {
842  myConnectionsToDelete.push_back(Connection(fromLane, toEdge, toLane));
843  }
844 }
845 
846 
847 void
848 NBEdge::invalidateConnections(bool reallowSetting) {
849  myTurnDestination = 0;
850  myConnections.clear();
851  if (reallowSetting) {
852  myStep = INIT;
853  } else {
855  }
856 }
857 
858 
859 void
860 NBEdge::replaceInConnections(NBEdge* which, NBEdge* by, unsigned int laneOff) {
861  UNUSED_PARAMETER(laneOff);
862  // replace in "_connectedEdges"
863  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
864  if ((*i).toEdge == which) {
865  (*i).toEdge = by;
866  }
867  }
868  // check whether it was the turn destination
869  if (myTurnDestination == which) {
870  myTurnDestination = by;
871  }
872 }
873 
874 void
875 NBEdge::replaceInConnections(NBEdge* which, const std::vector<NBEdge::Connection>& origConns) {
876  std::map<int, int> laneMap;
877  int minLane = -1;
878  int maxLane = -1;
879  // get lanes used to approach the edge to remap
880  bool wasConnected = false;
881  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
882  if ((*i).toEdge != which) {
883  continue;
884  }
885  wasConnected = true;
886  if ((*i).fromLane != -1) {
887  int fromLane = (*i).fromLane;
888  laneMap[(*i).toLane] = fromLane;
889  if (minLane == -1 || minLane > fromLane) {
890  minLane = fromLane;
891  }
892  if (maxLane == -1 || maxLane < fromLane) {
893  maxLane = fromLane;
894  }
895  }
896  }
897  if (!wasConnected) {
898  return;
899  }
900  // remove the remapped edge from connections
901  removeFromConnections(which);
902  // add new connections
903  std::vector<NBEdge::Connection> conns = origConns;
904  for (std::vector<NBEdge::Connection>::iterator i = conns.begin(); i != conns.end(); ++i) {
905  if ((*i).toEdge == which) {
906  continue;
907  }
908  int fromLane = (*i).fromLane;
909  int toUse = -1;
910  if (laneMap.find(fromLane) == laneMap.end()) {
911  if (fromLane >= 0 && fromLane <= minLane) {
912  toUse = minLane;
913  }
914  if (fromLane >= 0 && fromLane >= maxLane) {
915  toUse = maxLane;
916  }
917  } else {
918  toUse = laneMap[fromLane];
919  }
920  if (toUse == -1) {
921  toUse = 0;
922  }
923  setConnection(toUse, (*i).toEdge, (*i).toLane, L2L_COMPUTED, false, (*i).mayDefinitelyPass);
924  }
925 }
926 
927 
928 void
930  myStep = src->myStep;
932 }
933 
934 
935 void
936 NBEdge::moveConnectionToLeft(unsigned int lane) {
937  unsigned int index = 0;
938  if (myAmLeftHand) {
939  for (int i = (int) myConnections.size() - 1; i >= 0; --i) {
940  if (myConnections[i].fromLane == static_cast<int>(lane) && getTurnDestination() != myConnections[i].toEdge) {
941  index = i;
942  }
943  }
944  } else {
945  for (unsigned int i = 0; i < myConnections.size(); ++i) {
946  if (myConnections[i].fromLane == static_cast<int>(lane)) {
947  index = i;
948  }
949  }
950  }
951  std::vector<Connection>::iterator i = myConnections.begin() + index;
952  Connection c = *i;
953  myConnections.erase(i);
954  setConnection(lane + 1, c.toEdge, c.toLane, L2L_VALIDATED, false);
955 }
956 
957 
958 void
959 NBEdge::moveConnectionToRight(unsigned int lane) {
960  if (myAmLeftHand) {
961  for (int i = (int) myConnections.size() - 1; i >= 0; --i) {
962  if (myConnections[i].fromLane == static_cast<int>(lane) && getTurnDestination() != myConnections[i].toEdge) {
963  Connection c = myConnections[i];
964  myConnections.erase(myConnections.begin() + i);
965  setConnection(lane - 1, c.toEdge, c.toLane, L2L_VALIDATED, false);
966  return;
967  }
968  }
969  } else {
970  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
971  if ((*i).fromLane == static_cast<int>(lane)) {
972  Connection c = *i;
973  i = myConnections.erase(i);
974  setConnection(lane - 1, c.toEdge, c.toLane, L2L_VALIDATED, false);
975  return;
976  }
977  }
978  }
979 }
980 
981 
982 void
983 NBEdge::buildInnerEdges(const NBNode& n, unsigned int noInternalNoSplits, unsigned int& linkIndex, unsigned int& splitIndex) {
984  std::string innerID = ":" + n.getID();
985  NBEdge* toEdge = 0;
986  unsigned int edgeIndex = linkIndex;
987  unsigned int internalLaneIndex = 0;
988  // connection index -> list of foe internal lane indices
989  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
990  Connection& con = *i;
991  con.haveVia = false; // reset first since this may be called multiple times
992  if (con.toEdge == 0) {
993  continue;
994  }
995  if (con.toEdge != toEdge) {
996  // skip indices to keep some correspondence between edge ids and link indices
997  edgeIndex = linkIndex;
998  toEdge = (*i).toEdge;
999  internalLaneIndex = 0;
1000  }
1001  PositionVector shape = n.computeInternalLaneShape(this, con.fromLane, con.toEdge, con.toLane);
1002  std::vector<unsigned int> foeInternalLinks;
1003 
1004  LinkDirection dir = n.getDirection(this, con.toEdge);
1005  std::pair<SUMOReal, std::vector<unsigned int> > crossingPositions(-1, std::vector<unsigned int>());
1006  std::set<std::string> tmpFoeIncomingLanes;
1007  switch (dir) {
1008  case LINKDIR_LEFT:
1009  case LINKDIR_PARTLEFT:
1010  case LINKDIR_TURN: {
1011  unsigned int index = 0;
1012  const std::vector<NBEdge*>& incoming = n.getIncomingEdges();
1013  for (EdgeVector::const_iterator i2 = incoming.begin(); i2 != incoming.end(); ++i2) {
1014  const std::vector<Connection>& elv = (*i2)->getConnections();
1015  for (std::vector<NBEdge::Connection>::const_iterator k2 = elv.begin(); k2 != elv.end(); k2++) {
1016  if ((*k2).toEdge == 0) {
1017  continue;
1018  }
1019  bool needsCont = n.needsCont(this, con.toEdge, *i2, (*k2).toEdge, *k2);
1020  // compute the crossing point
1021  if (needsCont) {
1022  crossingPositions.second.push_back(index);
1023  const PositionVector otherShape = n.computeInternalLaneShape(*i2, (*k2).fromLane, (*k2).toEdge, (*k2).toLane);
1024  const std::vector<SUMOReal> dv = shape.intersectsAtLengths2D(otherShape);
1025  if (dv.size() > 0) {
1026  const SUMOReal minDV = dv[0];
1027  if (minDV < shape.length() - .1 && minDV > .1) { // !!!?
1028  assert(minDV >= 0);
1029  if (crossingPositions.first < 0 || crossingPositions.first > minDV) {
1030  crossingPositions.first = minDV;
1031  }
1032  }
1033  }
1034  }
1035  // compute foe internal lanes
1036  if (n.foes(this, con.toEdge, *i2, (*k2).toEdge)) {
1037  foeInternalLinks.push_back(index);
1038  }
1039  // compute foe incoming lanes
1040  const bool signalised = hasSignalisedConnectionTo(con.toEdge);
1041  if (n.forbids(*i2, (*k2).toEdge, this, con.toEdge, signalised) && (needsCont || dir == LINKDIR_TURN)) {
1042  tmpFoeIncomingLanes.insert((*i2)->getID() + "_" + toString((*k2).fromLane));
1043  }
1044  index++;
1045  }
1046  }
1047  if (dir == LINKDIR_TURN && crossingPositions.first < 0 && crossingPositions.second.size() != 0) {
1048  // let turnarounds wait in the middle if no other crossing point was found
1049  crossingPositions.first = (SUMOReal) shape.length() / 2.;
1050  }
1051  }
1052  break;
1053  default:
1054  break;
1055  }
1056 
1057 
1058  // compute the maximum speed allowed
1059  // see !!! for an explanation (with a_lat_mean ~0.3)
1060  SUMOReal vmax = (SUMOReal) 0.3 * (SUMOReal) 9.80778 *
1061  getLaneShape(con.fromLane).back().distanceTo(
1062  con.toEdge->getLaneShape(con.toLane).front())
1063  / (SUMOReal) 2.0 / (SUMOReal) M_PI;
1064  vmax = MIN2(vmax, ((getSpeed() + con.toEdge->getSpeed()) / (SUMOReal) 2.0));
1065  vmax = (getSpeed() + con.toEdge->getSpeed()) / (SUMOReal) 2.0;
1066  //
1067  Position end = con.toEdge->getLaneShape(con.toLane).front();
1068  Position beg = getLaneShape(con.fromLane).back();
1069 
1070  assert(shape.size() >= 2);
1071  // get internal splits if any
1072  if (crossingPositions.first >= 0) {
1073  std::pair<PositionVector, PositionVector> split = shape.splitAt(crossingPositions.first);
1074  con.id = innerID + "_" + toString(edgeIndex);
1075  con.shape = split.first;
1076  con.foeIncomingLanes = joinToString(tmpFoeIncomingLanes, " ");
1077  con.foeInternalLinks = foeInternalLinks; // resolve link indices to lane ids later
1078  con.viaID = innerID + "_" + toString(splitIndex + noInternalNoSplits);
1079  ++splitIndex;
1080  con.viaVmax = vmax;
1081  con.viaShape = split.second;
1082  con.haveVia = true;
1083  } else {
1084  con.id = innerID + "_" + toString(edgeIndex);
1085  con.shape = shape;
1086  }
1087  con.vmax = vmax;
1088  con.internalLaneIndex = internalLaneIndex;
1089  ++internalLaneIndex;
1090  ++linkIndex;
1091  }
1092 }
1093 
1094 // -----------
1095 int
1096 NBEdge::getJunctionPriority(const NBNode* const node) const {
1097  if (node == myFrom) {
1098  return myFromJunctionPriority;
1099  } else {
1100  return myToJunctionPriority;
1101  }
1102 }
1103 
1104 
1105 void
1106 NBEdge::setJunctionPriority(const NBNode* const node, int prio) {
1107  if (node == myFrom) {
1108  myFromJunctionPriority = prio;
1109  } else {
1110  myToJunctionPriority = prio;
1111  }
1112 }
1113 
1114 
1115 SUMOReal
1116 NBEdge::getAngleAtNode(const NBNode* const atNode) const {
1117  // myStartAngle, myEndAngle are in [0,360] and this returns results in [-180,180]
1118  if (atNode == myFrom) {
1119  return myGeom.getBegLine().atan2DegreeAngle();
1120  } else {
1121  assert(atNode == myTo);
1122  return myGeom.getEndLine().atan2DegreeAngle();
1123  }
1124 }
1125 
1126 
1127 void
1129  myTurnDestination = e;
1130 }
1131 
1132 
1133 SUMOReal
1134 NBEdge::getLaneSpeed(unsigned int lane) const {
1135  return myLanes[lane].speed;
1136 }
1137 
1138 
1139 void
1141  // vissim needs this
1142  if (myFrom == myTo) {
1143  return;
1144  }
1145  // compute lane offset, first
1146  std::vector<SUMOReal> offsets;
1147  for (unsigned int i = 0; i < myLanes.size(); ++i) {
1148  offsets.push_back(0);
1149  }
1150  SUMOReal offset = 0;
1151  for (int i = (int)myLanes.size() - 2; i >= 0; --i) {
1152  offset += (getLaneWidth(i) + getLaneWidth(i + 1)) / 2. + SUMO_const_laneOffset;
1153  offsets[i] = offset;
1154  }
1155  offset -= SUMO_const_laneOffset;
1157  SUMOReal laneWidth = myLanes.back().width != UNSPECIFIED_WIDTH ? myLanes.back().width : SUMO_const_laneWidth;
1158  offset = (laneWidth + SUMO_const_laneOffset) / 2.; // @todo: why is the lane offset counted in here?
1159  } else {
1160  SUMOReal width = 0;
1161  for (unsigned int i = 0; i < myLanes.size(); ++i) {
1162  width += getLaneWidth(i);
1163  }
1164  width += SUMO_const_laneOffset * SUMOReal(myLanes.size() - 1);
1165  offset = -width / 2. + getLaneWidth((int)myLanes.size() - 1) / 2.;
1166  }
1167  for (unsigned int i = 0; i < myLanes.size(); ++i) {
1168  offsets[i] += offset;
1169  if (myAmLeftHand) {
1170  offsets[i] *= -1.;
1171  }
1172  }
1173 
1174  // build the shape of each lane
1175  for (unsigned int i = 0; i < myLanes.size(); ++i) {
1176  try {
1177  myLanes[i].shape = computeLaneShape(i, offsets[i]);
1178  } catch (InvalidArgument& e) {
1179  WRITE_WARNING("In edge '" + getID() + "': lane shape could not be determined (" + e.what() + ")");
1180  myLanes[i].shape = myGeom;
1181  }
1182  }
1183 }
1184 
1185 
1187 NBEdge::computeLaneShape(unsigned int lane, SUMOReal offset) {
1188  PositionVector shape;
1189  bool haveWarned = false;
1190  for (int i = 0; i < (int) myGeom.size(); i++) {
1191  if (i == 0) {
1192  Position from = myGeom[i];
1193  Position to = myGeom[i + 1];
1194  std::pair<SUMOReal, SUMOReal> offsets = laneOffset(from, to, offset, false);
1195  shape.push_back(
1196  // (methode umbenennen; was heisst hier "-")
1197  Position(from.x() - offsets.first, from.y() - offsets.second, from.z()));
1198  } else if (i == static_cast<int>(myGeom.size() - 1)) {
1199  Position from = myGeom[i - 1];
1200  Position to = myGeom[i];
1201  std::pair<SUMOReal, SUMOReal> offsets = laneOffset(from, to, offset, false);
1202  shape.push_back(
1203  // (methode umbenennen; was heisst hier "-")
1204  Position(to.x() - offsets.first, to.y() - offsets.second, to.z()));
1205  } else {
1206  Position from = myGeom[i - 1];
1207  Position me = myGeom[i];
1208  Position to = myGeom[i + 1];
1209  std::pair<SUMOReal, SUMOReal> offsets = laneOffset(from, me, offset, false);
1210  std::pair<SUMOReal, SUMOReal> offsets2 = laneOffset(me, to, offset, false);
1211  Line l1(
1212  Position(from.x() - offsets.first, from.y() - offsets.second),
1213  Position(me.x() - offsets.first, me.y() - offsets.second));
1214  l1.extrapolateBy(100);
1215  Line l2(
1216  Position(me.x() - offsets2.first, me.y() - offsets2.second),
1217  Position(to.x() - offsets2.first, to.y() - offsets2.second));
1219  if (angle < 10. || angle > 350.) {
1220  shape.push_back(
1221  // (methode umbenennen; was heisst hier "-")
1222  Position(me.x() - offsets.first, me.y() - offsets.second, me.z()));
1223  continue;
1224  }
1225  l2.extrapolateBy(100);
1226  if (l1.intersects(l2)) {
1227  Position intersetion = l1.intersectsAt(l2);
1228  shape.push_back(Position(intersetion.x(), intersetion.y(), me.z()));
1229  } else {
1230  if (!haveWarned) {
1231  WRITE_WARNING("In lane '" + getLaneID(lane) + "': Could not build shape.");
1232  haveWarned = true;
1233  }
1234  }
1235  }
1236  }
1237  return shape;
1238 }
1239 
1240 
1241 /*std::pair<SUMOReal, SUMOReal>
1242 NBEdge::laneOffset(const Position& from, const Position& to, SUMOReal laneCenterOffset) {
1243  return laneOffset(from, to, laneCenterOffset, myAmLeftHand);
1244 }
1245 */
1246 
1247 std::pair<SUMOReal, SUMOReal>
1248 NBEdge::laneOffset(const Position& from, const Position& to, SUMOReal laneCenterOffset, bool leftHand) {
1249  std::pair<SUMOReal, SUMOReal> offsets = GeomHelper::getNormal90D_CW(from, to, laneCenterOffset);
1250  if (leftHand) {
1251  return std::pair<SUMOReal, SUMOReal>(-offsets.first, -offsets.second);
1252  } else {
1253  return std::pair<SUMOReal, SUMOReal>(offsets.first, offsets.second);
1254  }
1255 }
1256 
1257 
1258 void
1260  // taking the angle at the first might be unstable, thus we take the angle
1261  // at a certain distance. (To compare two edges, additional geometry
1262  // segments are considered to resolve ambiguities)
1263  const Position referencePosStart = myGeom.positionAtOffset2D(ANGLE_LOOKAHEAD);
1265  myFrom->getPosition().x(), myFrom->getPosition().y(),
1266  referencePosStart.x(), referencePosStart.y());
1267  const Position referencePosEnd = myGeom.positionAtOffset2D(myGeom.length() - ANGLE_LOOKAHEAD);
1269  referencePosEnd.x(), referencePosEnd.y(),
1270  myTo->getPosition().x(), myTo->getPosition().y());
1272  myFrom->getPosition().x(), myFrom->getPosition().y(),
1273  myTo->getPosition().x(), myTo->getPosition().y());
1274 }
1275 
1276 
1277 bool
1279  for (std::vector<Lane>::const_iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
1280  if ((*i).permissions != SVCFreeForAll) {
1281  return true;
1282  }
1283  }
1284  return false;
1285 }
1286 
1287 
1288 bool
1290  std::vector<Lane>::const_iterator i = myLanes.begin();
1291  SVCPermissions firstLanePermissions = i->permissions;
1292  i++;
1293  for (; i != myLanes.end(); ++i) {
1294  if (i->permissions != firstLanePermissions) {
1295  return true;
1296  }
1297  }
1298  return false;
1299 }
1300 
1301 
1302 bool
1304  for (std::vector<Lane>::const_iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
1305  if (i->width != myLanes.begin()->width) {
1306  return true;
1307  }
1308  }
1309  return false;
1310 }
1311 
1312 
1313 bool
1315  for (std::vector<Lane>::const_iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
1316  if (i->speed != getSpeed()) {
1317  return true;
1318  }
1319  }
1320  return false;
1321 }
1322 
1323 
1324 bool
1326  for (std::vector<Lane>::const_iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
1327  if (i->offset != myLanes.begin()->offset) {
1328  return true;
1329  }
1330  }
1331  return false;
1332 }
1333 
1334 
1335 bool
1338 }
1339 
1340 
1341 
1342 bool
1343 NBEdge::computeEdge2Edges(bool noLeftMovers) {
1344  // return if this relationship has been build in previous steps or
1345  // during the import
1346  if (myStep >= EDGE2EDGES) {
1347  return true;
1348  }
1349  if (myConnections.size() == 0) {
1350  const EdgeVector& o = myTo->getOutgoingEdges();
1351  for (EdgeVector::const_iterator i = o.begin(); i != o.end(); ++i) {
1352  if (noLeftMovers && myTo->isLeftMover(this, *i)) {
1353  continue;
1354  }
1355  myConnections.push_back(Connection(-1, *i, -1));
1356  }
1357  }
1358  myStep = EDGE2EDGES;
1359  return true;
1360 }
1361 
1362 
1363 bool
1365  // return if this relationship has been build in previous steps or
1366  // during the import
1367  if (myStep >= LANES2EDGES) {
1368  return true;
1369  }
1370  assert(myStep == EDGE2EDGES);
1371  // get list of possible outgoing edges sorted by direction clockwise
1372  // the edge in the backward direction (turnaround) is not in the list
1373  const EdgeVector* edges = getConnectedSorted();
1374  if (myConnections.size() != 0 && edges->size() == 0) {
1375  // dead end per definition!?
1376  myConnections.clear();
1377  } else {
1378  // divide the lanes on reachable edges
1379  divideOnEdges(edges);
1380  }
1381  delete edges;
1382  myStep = LANES2EDGES;
1383  return true;
1384 }
1385 
1386 
1387 bool
1389  std::vector<unsigned int> connNumbersPerLane(myLanes.size(), 0);
1390  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end();) {
1391  if ((*i).toEdge == 0 || (*i).fromLane < 0 || (*i).toLane < 0) {
1392  i = myConnections.erase(i);
1393  } else {
1394  if ((*i).fromLane >= 0) {
1395  ++connNumbersPerLane[(*i).fromLane];
1396  }
1397  ++i;
1398  }
1399  }
1401  // check #1:
1402  // If there is a lane with no connections and any neighbour lane has
1403  // more than one connections, try to move one of them.
1404  // This check is only done for edges which connections were assigned
1405  // using the standard algorithm.
1406  for (unsigned int i = 0; i < myLanes.size(); i++) {
1407  if (connNumbersPerLane[i] == 0) {
1408  if (i > 0 && connNumbersPerLane[i - 1] > 1) {
1409  moveConnectionToLeft(i - 1);
1410  } else if (i < myLanes.size() - 1 && connNumbersPerLane[i + 1] > 1) {
1411  moveConnectionToRight(i + 1);
1412  }
1413  }
1414  }
1415  }
1416  // check delayed removals
1417  for (std::vector<Connection>::iterator it = myConnectionsToDelete.begin(); it != myConnectionsToDelete.end(); ++it) {
1418  removeFromConnections(it->toEdge, it->fromLane, it->toLane);
1419  }
1420  return true;
1421 }
1422 
1423 
1424 void
1426  if (outgoing->size() == 0) {
1427  // we have to do this, because the turnaround may have been added before
1428  myConnections.clear();
1429  return;
1430  }
1431  // precompute priorities; needed as some kind of assumptions for
1432  // priorities of directions (see preparePriorities)
1433  std::vector<unsigned int>* priorities = preparePriorities(outgoing);
1434 
1435  // compute the sum of priorities (needed for normalisation)
1436  unsigned int prioSum = computePrioritySum(priorities);
1437  // compute the resulting number of lanes that should be used to
1438  // reach the following edge
1439  unsigned int size = (unsigned int) outgoing->size();
1440  std::vector<SUMOReal> resultingLanes;
1441  resultingLanes.reserve(size);
1442  SUMOReal sumResulting = 0; // the sum of resulting lanes
1443  SUMOReal minResulting = 10000; // the least number of lanes to reach an edge
1444  unsigned int i;
1445  for (i = 0; i < size; i++) {
1446  // res will be the number of lanes which are meant to reach the
1447  // current outgoing edge
1448  SUMOReal res =
1449  (SUMOReal)(*priorities)[i] *
1450  (SUMOReal) myLanes.size() / (SUMOReal) prioSum;
1451  // do not let this number be greater than the number of available lanes
1452  if (res > myLanes.size()) {
1453  res = (SUMOReal) myLanes.size();
1454  }
1455  // add it to the list
1456  resultingLanes.push_back(res);
1457  sumResulting += res;
1458  if (minResulting > res) {
1459  minResulting = res;
1460  }
1461  }
1462  // compute the number of virtual edges
1463  // a virtual edge is used as a replacement for a real edge from now on
1464  // it shall ollow to divide the existing lanes on this structure without
1465  // regarding the structure of outgoing edges
1466  sumResulting += minResulting / (SUMOReal) 2.;
1467  unsigned int noVirtual = (unsigned int)(sumResulting / minResulting);
1468  // compute the transition from virtual to real edges
1469  EdgeVector transition;
1470  transition.reserve(size);
1471  for (i = 0; i < size; i++) {
1472  // tmpNo will be the number of connections from this edge
1473  // to the next edge
1474  assert(i < resultingLanes.size());
1475  SUMOReal tmpNo = (SUMOReal) resultingLanes[i] / (SUMOReal) minResulting;
1476  for (SUMOReal j = 0; j < tmpNo; j++) {
1477  assert(outgoing->size() > i);
1478  transition.push_back((*outgoing)[i]);
1479  }
1480  }
1481 
1482  // assign lanes to edges
1483  // (conversion from virtual to real edges is done)
1484  ToEdgeConnectionsAdder adder(transition);
1485  Bresenham::compute(&adder, static_cast<unsigned int>(myLanes.size()), noVirtual);
1486  const std::map<NBEdge*, std::vector<unsigned int> >& l2eConns = adder.getBuiltConnections();
1487  myConnections.clear();
1488  for (std::map<NBEdge*, std::vector<unsigned int> >::const_iterator i = l2eConns.begin(); i != l2eConns.end(); ++i) {
1489  const std::vector<unsigned int> lanes = (*i).second;
1490  for (std::vector<unsigned int>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
1491  if (myAmLeftHand) {
1492  myConnections.push_back(Connection(int(myLanes.size() - 1 - *j), (*i).first, -1));
1493  } else {
1494  myConnections.push_back(Connection(int(*j), (*i).first, -1));
1495  }
1496  }
1497  }
1498  delete priorities;
1499 }
1500 
1501 
1502 std::vector<unsigned int>*
1504  // copy the priorities first
1505  std::vector<unsigned int>* priorities = new std::vector<unsigned int>();
1506  if (outgoing->size() == 0) {
1507  return priorities;
1508  }
1509  priorities->reserve(outgoing->size());
1510  EdgeVector::const_iterator i;
1511  for (i = outgoing->begin(); i != outgoing->end(); i++) {
1512  int prio = (*i)->getJunctionPriority(myTo);
1513  assert((prio + 1) * 2 > 0);
1514  prio = (prio + 1) * 2;
1515  priorities->push_back(prio);
1516  }
1517  // when the right turning direction has not a higher priority, divide
1518  // the importance by 2 due to the possibility to leave the junction
1519  // faster from this lane
1520  MainDirections mainDirections(*outgoing, this, myTo);
1521  EdgeVector tmp(*outgoing);
1522  sort(tmp.begin(), tmp.end(), NBContHelper::edge_similar_direction_sorter(this));
1523  i = find(outgoing->begin(), outgoing->end(), *(tmp.begin()));
1524  unsigned int dist = (unsigned int) distance(outgoing->begin(), i);
1525  if (dist != 0 && !mainDirections.includes(MainDirections::DIR_RIGHTMOST)) {
1526  assert(priorities->size() > 0);
1527  (*priorities)[0] = (*priorities)[0] / 2;
1528  }
1529  // HEURISTIC:
1530  // when no higher priority exists, let the forward direction be
1531  // the main direction
1532  if (mainDirections.empty()) {
1533  assert(dist < priorities->size());
1534  (*priorities)[dist] = (*priorities)[dist] * 2;
1535  }
1536  if (mainDirections.includes(MainDirections::DIR_FORWARD) && myLanes.size() > 2) {
1537  (*priorities)[dist] = (*priorities)[dist] * 2;
1538  }
1539  // return
1540  return priorities;
1541 }
1542 
1543 
1544 unsigned int
1545 NBEdge::computePrioritySum(std::vector<unsigned int>* priorities) {
1546  unsigned int sum = 0;
1547  for (std::vector<unsigned int>::iterator i = priorities->begin(); i != priorities->end(); i++) {
1548  sum += int(*i);
1549  }
1550  return sum;
1551 }
1552 
1553 
1554 void
1555 NBEdge::appendTurnaround(bool noTLSControlled) {
1556  // do nothing if no turnaround is known
1557  if (myTurnDestination == 0) {
1558  return;
1559  }
1560  // do nothing if the destination node is controlled by a tls and no turnarounds
1561  // shall be appended for such junctions
1562  if (noTLSControlled && myTo->isTLControlled()) {
1563  return;
1564  }
1565  setConnection((unsigned int)(myLanes.size() - 1), myTurnDestination, myTurnDestination->getNumLanes() - 1, L2L_VALIDATED);
1566 }
1567 
1568 
1569 bool
1570 NBEdge::isTurningDirectionAt(const NBNode* n, const NBEdge* const edge) const {
1571  // maybe it was already set as the turning direction
1572  if (edge == myTurnDestination) {
1573  return true;
1574  } else if (myTurnDestination != 0) {
1575  // otherwise - it's not if a turning direction exists
1576  return false;
1577  }
1578  // if the same nodes are connected
1579  if (myFrom == edge->myTo && myTo == edge->myFrom) {
1580  return true;
1581  }
1582  // we have to check whether the connection between the nodes is
1583  // geometrically similar
1584  SUMOReal thisFromAngle2 = getAngleAtNode(n);
1585  SUMOReal otherToAngle2 = edge->getAngleAtNode(n);
1586  if (thisFromAngle2 < otherToAngle2) {
1587  std::swap(thisFromAngle2, otherToAngle2);
1588  }
1589  if (thisFromAngle2 - otherToAngle2 > 170 && thisFromAngle2 - otherToAngle2 < 190) {
1590  return true;
1591  }
1592  return false;
1593 }
1594 
1595 
1596 
1597 NBNode*
1599  // return the from-node when the position is at the begin of the edge
1600  if (pos < tolerance) {
1601  return myFrom;
1602  }
1603  // return the to-node when the position is at the end of the edge
1604  if (pos > myLength - tolerance) {
1605  return myTo;
1606  }
1607  return 0;
1608 }
1609 
1610 
1611 void
1612 NBEdge::moveOutgoingConnectionsFrom(NBEdge* e, unsigned int laneOff) {
1613  unsigned int lanes = e->getNumLanes();
1614  for (unsigned int i = 0; i < lanes; i++) {
1615  std::vector<NBEdge::Connection> elv = e->getConnectionsFromLane(i);
1616  for (std::vector<NBEdge::Connection>::iterator j = elv.begin(); j != elv.end(); j++) {
1617  NBEdge::Connection el = *j;
1618  assert(el.tlID == "");
1619  bool ok = addLane2LaneConnection(i + laneOff, el.toEdge, el.toLane, L2L_COMPUTED);
1620  assert(ok);
1621  }
1622  }
1623 }
1624 
1625 
1626 bool
1629 }
1630 
1631 
1632 SUMOReal
1635 }
1636 
1637 
1638 bool
1639 NBEdge::mayBeTLSControlled(int fromLane, NBEdge* toEdge, int toLane) const {
1641  tpl.fromLane = fromLane;
1642  tpl.to = toEdge;
1643  tpl.toLane = toLane;
1644  std::vector<TLSDisabledConnection>::const_iterator i = find_if(myTLSDisabledConnections.begin(), myTLSDisabledConnections.end(), tls_disable_finder(tpl));
1645  return i == myTLSDisabledConnections.end();
1646 }
1647 
1648 
1649 bool
1650 NBEdge::setControllingTLInformation(const NBConnection& c, const std::string& tlID) {
1651  const int fromLane = c.getFromLane();
1652  NBEdge* toEdge = c.getTo();
1653  const int toLane = c.getToLane();
1654  const int tlIndex = c.getTLIndex();
1655  // check whether the connection was not set as not to be controled previously
1657  tpl.fromLane = fromLane;
1658  tpl.to = toEdge;
1659  tpl.toLane = toLane;
1660  std::vector<TLSDisabledConnection>::iterator i = find_if(myTLSDisabledConnections.begin(), myTLSDisabledConnections.end(), tls_disable_finder(tpl));
1661  if (i != myTLSDisabledConnections.end()) {
1662  return false;
1663  }
1664 
1665  assert(fromLane < 0 || fromLane < (int) myLanes.size());
1666  // try to use information about the connections if given
1667  if (fromLane >= 0 && toLane >= 0) {
1668  // find the specified connection
1669  std::vector<Connection>::iterator i =
1670  find_if(myConnections.begin(), myConnections.end(), connections_finder(fromLane, toEdge, toLane));
1671  // ok, we have to test this as on the removal of self-loop edges some connections
1672  // will be reassigned
1673  if (i != myConnections.end()) {
1674  // get the connection
1675  Connection& connection = *i;
1676  // set the information about the tl
1677  connection.tlID = tlID;
1678  connection.tlLinkNo = tlIndex;
1679  return true;
1680  }
1681  }
1682  // if the original connection was not found, set the information for all
1683  // connections
1684  unsigned int no = 0;
1685  bool hadError = false;
1686  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
1687  if ((*i).toEdge != toEdge) {
1688  continue;
1689  }
1690  if (fromLane >= 0 && fromLane != (*i).fromLane) {
1691  continue;
1692  }
1693  if (toLane >= 0 && toLane != (*i).toLane) {
1694  continue;
1695  }
1696  if ((*i).tlID == "") {
1697  (*i).tlID = tlID;
1698  (*i).tlLinkNo = tlIndex;
1699  no++;
1700  } else {
1701  if ((*i).tlID != tlID && static_cast<int>((*i).tlLinkNo) == tlIndex) {
1702  WRITE_WARNING("The lane " + toString<int>((*i).fromLane) + " on edge " + getID() + " already had a traffic light signal.");
1703  hadError = true;
1704  }
1705  }
1706  }
1707  if (hadError && no == 0) {
1708  WRITE_WARNING("Could not set any signal of the traffic light '" + tlID + "' (unknown group)");
1709  }
1710  return true;
1711 }
1712 
1713 
1714 void
1716  for (std::vector<Connection>::iterator it = myConnections.begin(); it != myConnections.end(); it++) {
1717  it->tlID = "";
1718  }
1719 }
1720 
1721 
1722 void
1723 NBEdge::disableConnection4TLS(int fromLane, NBEdge* toEdge, int toLane) {
1725  c.fromLane = fromLane;
1726  c.to = toEdge;
1727  c.toLane = toLane;
1728  myTLSDisabledConnections.push_back(c);
1729 }
1730 
1731 
1733 NBEdge::getCWBoundaryLine(const NBNode& n, SUMOReal offset) const {
1734  PositionVector ret;
1735  if (myFrom == (&n)) {
1736  // outgoing
1737  ret = !myAmLeftHand ? myLanes[0].shape : myLanes.back().shape;
1738  } else {
1739  // incoming
1740  ret = !myAmLeftHand ? myLanes.back().shape.reverse() : myLanes[0].shape.reverse();
1741  }
1742  ret.move2side(offset);
1743  return ret;
1744 }
1745 
1746 
1748 NBEdge::getCCWBoundaryLine(const NBNode& n, SUMOReal offset) const {
1749  PositionVector ret;
1750  if (myFrom == (&n)) {
1751  // outgoing
1752  ret = !myAmLeftHand ? myLanes.back().shape : myLanes[0].shape;
1753  } else {
1754  // incoming
1755  ret = !myAmLeftHand ? myLanes[0].shape.reverse() : myLanes.back().shape.reverse();
1756  }
1757  ret.move2side(-offset);
1758  return ret;
1759 }
1760 
1761 
1762 SUMOReal
1763 NBEdge::width() const {
1764  return (SUMOReal) myLanes.size() * SUMO_const_laneWidth + (SUMOReal)(myLanes.size() - 1) * SUMO_const_laneOffset;
1765 }
1766 
1767 
1768 bool
1769 NBEdge::expandableBy(NBEdge* possContinuation) const {
1770  // ok, the number of lanes must match
1771  if (myLanes.size() != possContinuation->myLanes.size()) {
1772  return false;
1773  }
1774  // the priority, too (?)
1775  if (getPriority() != possContinuation->getPriority()) {
1776  return false;
1777  }
1778  // the speed allowed
1779  if (mySpeed != possContinuation->mySpeed) {
1780  return false;
1781  }
1782  // the vehicle class constraints, too
1790  // also, check whether the connections - if any exit do allow to join
1791  // both edges
1792  // This edge must have a one-to-one connection to the following lanes
1793  switch (myStep) {
1795  break;
1796  case INIT:
1797  break;
1798  case EDGE2EDGES: {
1799  // the following edge must be connected
1800  const EdgeVector& conn = getConnectedEdges();
1801  if (find(conn.begin(), conn.end(), possContinuation)
1802  == conn.end()) {
1803 
1804  return false;
1805  }
1806  }
1807  break;
1808  case LANES2EDGES:
1809  case LANES2LANES_RECHECK:
1810  case LANES2LANES_DONE:
1811  case LANES2LANES_USER: {
1812  // the possible continuation must be connected
1813  if (find_if(myConnections.begin(), myConnections.end(), connections_toedge_finder(possContinuation)) == myConnections.end()) {
1814  return false;
1815  }
1816  // all lanes must go to the possible continuation
1817  std::vector<int> conns = getConnectionLanes(possContinuation);
1818  if (conns.size() != myLanes.size()) {
1819  return false;
1820  }
1821  }
1822  break;
1823  default:
1824  break;
1825  }
1826  return true;
1827 }
1828 
1829 
1830 void
1832  // append geometry
1833  myGeom.append(e->myGeom);
1834  for (unsigned int i = 0; i < myLanes.size(); i++) {
1835  myLanes[i].shape.append(e->myLanes[i].shape);
1836  }
1837  // recompute length
1838  myLength += e->myLength;
1839  // copy the connections and the building step if given
1840  myStep = e->myStep;
1843  // set the node
1844  myTo = e->myTo;
1845 }
1846 
1847 
1848 
1849 
1850 
1851 bool
1853  for (std::vector<Connection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
1854  if ((*i).toEdge == e && (*i).tlID != "") {
1855  return true;
1856  }
1857  }
1858  return false;
1859 }
1860 
1861 
1862 NBEdge*
1864  return myTurnDestination;
1865 }
1866 
1867 
1868 std::string
1869 NBEdge::getLaneID(unsigned int lane) const {
1870  assert(lane < myLanes.size());
1871  return myID + "_" + toString(lane);
1872 }
1873 
1874 
1875 std::string
1876 NBEdge::getLaneIDInsecure(unsigned int lane) const {
1877  return myID + "_" + toString(lane);
1878 }
1879 
1880 
1881 bool
1883  std::vector<SUMOReal> distances = myGeom.distances(e->getGeometry());
1884  assert(distances.size() > 0);
1885  return VectorHelper<SUMOReal>::maxValue(distances) < threshold;
1886 }
1887 
1888 
1889 void
1890 NBEdge::incLaneNo(unsigned int by) {
1891  unsigned int newLaneNo = (unsigned int) myLanes.size() + by;
1892  while (myLanes.size() < newLaneNo) {
1893  myLanes.push_back(Lane(this));
1894  }
1896  const EdgeVector& incs = myFrom->getIncomingEdges();
1897  for (EdgeVector::const_iterator i = incs.begin(); i != incs.end(); ++i) {
1898  (*i)->invalidateConnections(true);
1899  }
1900  invalidateConnections(true);
1901 }
1902 
1903 
1904 void
1905 NBEdge::decLaneNo(unsigned int by, int dir) {
1906  unsigned int newLaneNo = (unsigned int) myLanes.size() - by;
1907  while (myLanes.size() > newLaneNo) {
1908  myLanes.pop_back();
1909  }
1911  const EdgeVector& incs = myFrom->getIncomingEdges();
1912  for (EdgeVector::const_iterator i = incs.begin(); i != incs.end(); ++i) {
1913  (*i)->invalidateConnections(true);
1914  }
1915  if (dir == 0) {
1916  invalidateConnections(true);
1917  } else {
1918  const EdgeVector& outs = myTo->getOutgoingEdges();
1919  assert(outs.size() == 1);
1920  NBEdge* out = outs[0];
1921  if (dir < 0) {
1922  removeFromConnections(out, 0);
1923  } else {
1924  removeFromConnections(out, (int) myLanes.size());
1925  }
1926  }
1927 }
1928 
1929 
1930 void
1932  assert(myTo->getOutgoingEdges().size() == 0);
1934 }
1935 
1936 
1937 void
1939  if (lane < 0) { // all lanes are meant...
1940  for (unsigned int i = 0; i < myLanes.size(); i++) {
1941  allowVehicleClass((int) i, vclass);
1942  }
1943  } else {
1944  assert(lane < (int) myLanes.size());
1945  myLanes[lane].permissions |= vclass;
1946  }
1947 }
1948 
1949 
1950 void
1952  if (lane < 0) { // all lanes are meant...
1953  for (unsigned int i = 0; i < myLanes.size(); i++) {
1954  disallowVehicleClass((int) i, vclass);
1955  }
1956  } else {
1957  assert(lane < (int) myLanes.size());
1958  myLanes[lane].permissions &= ~vclass;
1959  }
1960 }
1961 
1962 
1963 void
1965  if (lane < 0) { // all lanes are meant...
1966  for (unsigned int i = 0; i < myLanes.size(); i++) {
1967  allowVehicleClass((int) i, vclass);
1968  }
1969  } else {
1970  assert(lane < (int) myLanes.size());
1971  myLanes[lane].preferred |= vclass;
1972  }
1973 }
1974 
1975 
1976 void
1977 NBEdge::setLaneWidth(int lane, SUMOReal width) {
1978  if (lane < 0) {
1979  // all lanes are meant...
1980  myLaneWidth = width;
1981  for (unsigned int i = 0; i < myLanes.size(); i++) {
1982  // ... do it for each lane
1983  setLaneWidth((int) i, width);
1984  }
1985  return;
1986  }
1987  assert(lane < (int) myLanes.size());
1988  myLanes[lane].width = width;
1989 }
1990 
1991 
1992 SUMOReal
1993 NBEdge::getLaneWidth(int lane) const {
1994  return myLanes[lane].width != UNSPECIFIED_WIDTH
1995  ? myLanes[lane].width
1997 }
1998 
1999 
2000 SUMOReal
2001 NBEdge::getOffset(int lane) const {
2002  return myLanes[lane].offset != UNSPECIFIED_OFFSET ? myLanes[lane].offset : getOffset();
2003 }
2004 
2005 
2006 void
2007 NBEdge::setOffset(int lane, SUMOReal offset) {
2008  if (lane < 0) {
2009  // all lanes are meant...
2010  myOffset = offset;
2011  for (unsigned int i = 0; i < myLanes.size(); i++) {
2012  // ... do it for each lane
2013  setOffset((int) i, offset);
2014  }
2015  return;
2016  }
2017  assert(lane < (int) myLanes.size());
2018  myLanes[lane].offset = offset;
2019 }
2020 
2021 
2022 void
2023 NBEdge::setSpeed(int lane, SUMOReal speed) {
2024  if (lane < 0) {
2025  // all lanes are meant...
2026  mySpeed = speed;
2027  for (unsigned int i = 0; i < myLanes.size(); i++) {
2028  // ... do it for each lane
2029  setSpeed((int) i, speed);
2030  }
2031  return;
2032  }
2033  assert(lane < (int) myLanes.size());
2034  myLanes[lane].speed = speed;
2035 }
2036 
2037 
2038 void
2039 NBEdge::setPermissions(SVCPermissions permissions, int lane) {
2040  if (lane < 0) {
2041  for (unsigned int i = 0; i < myLanes.size(); i++) {
2042  // ... do it for each lane
2043  setPermissions(permissions, i);
2044  }
2045  } else {
2046  assert(lane < (int) myLanes.size());
2047  myLanes[lane].permissions = permissions;
2048  }
2049 }
2050 
2051 
2052 void
2054  if (lane < 0) {
2055  for (unsigned int i = 0; i < myLanes.size(); i++) {
2056  // ... do it for each lane
2057  setPreferredVehicleClass(permissions, i);
2058  }
2059  } else {
2060  assert(lane < (int) myLanes.size());
2061  myLanes[lane].preferred = permissions;
2062  }
2063 }
2064 
2065 
2067 NBEdge::getPermissions(int lane) const {
2068  if (lane < 0) {
2069  SVCPermissions result = 0;
2070  for (unsigned int i = 0; i < myLanes.size(); i++) {
2071  result |= getPermissions(i);
2072  }
2073  return result;
2074  } else {
2075  assert(lane < (int) myLanes.size());
2076  return myLanes[lane].permissions;
2077  }
2078 }
2079 
2080 
2081 void
2083  myLoadedLength = val;
2084 }
2085 
2086 
2087 void
2089  for (std::vector<Lane>::iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
2090  (*i).permissions = SVCFreeForAll;
2091  (*i).preferred = 0;
2092  }
2093 }
2094 
2095 
2096 /****************************************************************************/
SUMOReal length2D() const
Definition: Line.cpp:177
std::string id
Definition: NBEdge.h:177
void invalidateConnections(bool reallowSetting=false)
Definition: NBEdge.cpp:848
The link is a partial left direction.
SUMOReal atan2DegreeAngle() const
Definition: Line.cpp:143
const PositionVector & getLaneShape(unsigned int i) const
Returns the shape of the nth lane.
Definition: NBEdge.cpp:474
std::vector< Lane > myLanes
Lane information.
Definition: NBEdge.h:1228
static std::pair< SUMOReal, SUMOReal > getNormal90D_CW(const Position &beg, const Position &end, SUMOReal length, SUMOReal wanted_offset)
Definition: GeomHelper.cpp:359
bool includes(Direction d) const
Definition: NBEdge.cpp:159
const Position & p2() const
Definition: Line.cpp:86
const EdgeVector & getIncomingEdges() const
Returns this node&#39;s incoming edges.
Definition: NBNode.h:177
bool setControllingTLInformation(const NBConnection &c, const std::string &tlID)
Returns if the link could be set as to be controlled.
Definition: NBEdge.cpp:1650
static SUMOReal getCWAngleDiff(SUMOReal angle1, SUMOReal angle2)
Returns the distance of second angle from first angle clockwise.
Definition: GeomHelper.cpp:381
void divideOnEdges(const EdgeVector *outgoing)
Definition: NBEdge.cpp:1425
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:201
SUMOReal myTotalAngle
Definition: NBEdge.h:1187
std::vector< unsigned int > * preparePriorities(const EdgeVector *outgoing)
Definition: NBEdge.cpp:1503
std::string foeIncomingLanes
Definition: NBEdge.h:187
bool insert(const std::string &id, const Position &position, NBDistrict *district)
Inserts a node into the map.
Definition: NBNodeCont.cpp:78
const SUMOReal SUMO_const_laneWidth
Definition: StdDefs.h:41
int getTLIndex() const
Definition: NBConnection.h:98
std::vector< TLSDisabledConnection > myTLSDisabledConnections
Definition: NBEdge.h:1249
~NBEdge()
Destructor.
Definition: NBEdge.cpp:341
LaneSpreadFunction myLaneSpreadFunction
The information about how to spread the lanes.
Definition: NBEdge.h:1217
PositionVector getSubpart2D(SUMOReal beginOffset, SUMOReal endOffset) const
SUMOReal viaVmax
Definition: NBEdge.h:183
void sortOutgoingConnectionsByAngle()
sorts the outgoing connections by their angle relative to their junction
Definition: NBEdge.cpp:796
std::string viaID
Definition: NBEdge.h:182
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:365
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types...
NBNode * myTo
Definition: NBEdge.h:1179
The relationships between edges are computed/loaded.
Definition: NBEdge.h:95
void insertAt(int index, const Position &p)
bool empty() const
Definition: NBEdge.cpp:153
void appendTurnaround(bool noTLSControlled)
Add a connection to the previously computed turnaround, if wished.
Definition: NBEdge.cpp:1555
#define M_PI
Definition: angles.h:37
PositionVector getCCWBoundaryLine(const NBNode &n, SUMOReal offset) const
Definition: NBEdge.cpp:1748
void setLaneWidth(int lane, SUMOReal width)
set lane specific width (negative lane implies set for all lanes)
Definition: NBEdge.cpp:1977
std::vector< SUMOReal > distances(const PositionVector &s) const
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition: NBNode.h:228
void setSpeed(int lane, SUMOReal speed)
set lane specific speed (negative lane implies set for all lanes)
Definition: NBEdge.cpp:2023
Some static methods for string processing.
Definition: StringUtils.h:45
PositionVector computeInternalLaneShape(NBEdge *fromE, int fromL, NBEdge *toE, int toL, int numPoints=5) const
Compute the shape for an internal lane.
Definition: NBNode.cpp:418
void setOffset(int lane, SUMOReal offset)
set lane specific end-offset (negative lane implies set for all lanes)
Definition: NBEdge.cpp:2007
void moveOutgoingConnectionsFrom(NBEdge *e, unsigned int laneOff)
Definition: NBEdge.cpp:1612
const SUMOReal SUMO_const_laneWidthAndOffset
Definition: StdDefs.h:45
void removeEdge(NBEdge *edge, bool removeFromConnections=true)
Removes edge from this node and optionally removes connections as well.
Definition: NBNode.cpp:977
Position getPositionAtDistance2D(SUMOReal offset) const
Definition: Line.cpp:105
void addIncomingEdge(NBEdge *edge)
adds an incoming edge
Definition: NBNode.cpp:369
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:278
void clearControllingTLInformation()
clears tlID for all connections
Definition: NBEdge.cpp:1715
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:1639
bool hasDefaultGeometryEndpoints() const
Returns whether the geometry is terminated by the node positions This default may be violated by init...
Definition: NBEdge.cpp:371
The link is a 180 degree turn.
int getFromLane() const
returns the from-lane
void incLaneNo(unsigned int by)
Definition: NBEdge.cpp:1890
bool intersects(const Position &p1, const Position &p2) const
static std::pair< SUMOReal, SUMOReal > laneOffset(const Position &from, const Position &to, SUMOReal laneCenterOffset, bool leftHand)
Computes the offset from the edge shape on the current segment.
Definition: NBEdge.cpp:1248
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:635
void buildInnerEdges(const NBNode &n, unsigned int noInternalNoSplits, unsigned int &linkIndex, unsigned int &splitIndex)
Definition: NBEdge.cpp:983
void markAsInLane2LaneState()
Definition: NBEdge.cpp:1931
bool addLane2LaneConnection(unsigned int fromLane, NBEdge *dest, unsigned int toLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false)
Adds a connection between the specified this edge&#39;s lane and an approached one.
Definition: NBEdge.cpp:613
Lanes to lanes - relationships are computed; should be recheked.
Definition: NBEdge.h:99
PositionVector computeLaneShape(unsigned int lane, SUMOReal offset)
Computes the shape for the given lane.
Definition: NBEdge.cpp:1187
SUMOReal getLaneWidth() const
Returns the default width of lanes of this edge.
Definition: NBEdge.h:440
std::string getLaneIDInsecure(unsigned int lane) const
Definition: NBEdge.cpp:1876
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:2039
int myFromJunctionPriority
The priority normalised for the node the edge is outgoing of.
Definition: NBEdge.h:1208
void computeLaneShapes()
Computes the offset from the edge shape on the current segment.
Definition: NBEdge.cpp:1140
PositionVector myGeom
The geometry for the edge.
Definition: NBEdge.h:1214
void remapConnections(const EdgeVector &incoming)
Remaps the connection in a way that allows the removal of it.
Definition: NBEdge.cpp:808
SUMOReal distanceTo(const Position &p2) const
returns the euclidean distance in 3 dimension
Definition: Position.h:208
void eraseAt(int i)
const SUMOReal SUMO_const_laneOffset
Definition: StdDefs.h:44
bool isTurningDirectionAt(const NBNode *n, const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition: NBEdge.cpp:1570
static const SUMOReal UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:203
PositionVector getCWBoundaryLine(const NBNode &n, SUMOReal offset) const
Definition: NBEdge.cpp:1733
std::vector< Connection > getConnectionsFromLane(unsigned int lane) const
Returns connections from a given lane.
Definition: NBEdge.cpp:711
SUMOReal x() const
Returns the x-position.
Definition: Position.h:63
void addOutgoingEdge(NBEdge *edge)
adds an outgoing edge
Definition: NBNode.cpp:379
void setGeometry(const PositionVector &g, bool inner=false)
(Re)sets the edge&#39;s geometry
Definition: NBEdge.cpp:378
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:36
The link is a (hard) left direction.
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:196
The connection was computed and validated.
Definition: NBEdge.h:116
PositionVector startShapeAt(const PositionVector &laneShape, const NBNode *startNode) const
Definition: NBEdge.cpp:433
SUMOReal vmax
Definition: NBEdge.h:179
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:1211
EdgeVector getConnectedEdges() const
Returns the list of outgoing edges unsorted.
Definition: NBEdge.cpp:770
The link is a straight direction.
PositionVector shape
Definition: NBEdge.h:178
const EdgeVector & getOutgoingEdges() const
Returns this node&#39;s outgoing edges.
Definition: NBNode.h:185
void moveConnectionToRight(unsigned int lane)
Definition: NBEdge.cpp:959
void setTurningDestination(NBEdge *e)
Definition: NBEdge.cpp:1128
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 mySpeed
The maximal speed.
Definition: NBEdge.h:1193
bool addEdge2EdgeConnection(NBEdge *dest)
Adds a connection to another edge.
Definition: NBEdge.cpp:589
Line lineAt(int pos) const
bool myAmMacroscopicConnector
Information whether this edge is a (macroscopic) connector.
Definition: NBEdge.h:1241
bool isConnectedTo(NBEdge *e)
Returns the information whethe a connection to the given edge has been added (or computed) ...
Definition: NBEdge.cpp:729
const PositionVector getInnerGeometry() const
Returns the geometry of the edge without the endpoints.
Definition: NBEdge.cpp:356
void push_front_noDoublePos(const Position &p)
void reshiftPosition(SUMOReal xoff, SUMOReal yoff)
Applies an offset to the edge.
Definition: NBEdge.cpp:346
const Position & getPosition() const
Returns the position of this node.
Definition: NBNode.h:165
const Position & p1() const
Definition: Line.cpp:80
bool computeLanes2Edges()
computes the edge, step2: computation of which lanes approach the edges)
Definition: NBEdge.cpp:1364
NBEdge * myTurnDestination
The turn destination edge.
Definition: NBEdge.h:1205
const std::map< NBEdge *, std::vector< unsigned int > > & getBuiltConnections() const
Definition: NBEdge.h:1051
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:168
bool hasLaneSpecificSpeed() const
whether lanes differ in speed
Definition: NBEdge.cpp:1314
int getPriority() const
Returns the priority of the edge.
Definition: NBEdge.h:346
bool insert(NBEdge *edge, bool ignorePrunning=false)
Adds an edge to the dictionary.
Definition: NBEdgeCont.cpp:164
void checkGeometry(const SUMOReal maxAngle, const SUMOReal minRadius, bool fix)
Check the angles of successive geometry segments.
Definition: NBEdge.cpp:543
std::string getLaneID(unsigned int lane) const
Definition: NBEdge.cpp:1869
void moveConnectionToLeft(unsigned int lane)
Definition: NBEdge.cpp:936
bool myAmLeftHand
Whether this edge is a left-hand edge.
Definition: NBEdge.h:1234
void reshiftRotate(SUMOReal xoff, SUMOReal yoff, SUMOReal rot)
std::string tlID
The id of the traffic light that controls this connection.
Definition: NBEdge.h:168
std::string getInternalLaneID() const
Definition: NBEdge.cpp:73
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:1186
bool hasLaneSpecificPermissions() const
whether lanes differ in allowed vehicle classes
Definition: NBEdge.cpp:1289
bool lanesWereAssigned() const
Definition: NBEdge.cpp:1627
bool needsCont(NBEdge *fromE, NBEdge *toE, NBEdge *otherFromE, NBEdge *otherToE, const NBEdge::Connection &c) const
Definition: NBNode.cpp:542
std::vector< unsigned int > foeInternalLinks
Definition: NBEdge.h:186
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:338
SUMOReal z() const
Returns the z-position.
Definition: Position.h:73
static SUMOReal angle(SUMOReal x1, SUMOReal y1, SUMOReal x2, SUMOReal y2)
Definition: NBHelpers.cpp:52
SUMOReal myLaneWidth
This width of this edge&#39;s lanes.
Definition: NBEdge.h:1223
int myPriority
The priority of the edge.
Definition: NBEdge.h:1190
Definition: Line.h:51
void init(unsigned int noLanes, bool tryIgnoreNodePositions)
Initialization routines common to all constructors.
Definition: NBEdge.cpp:297
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:66
T MIN2(T a, T b)
Definition: StdDefs.h:57
bool needsLaneSpecificOutput() const
whether at least one lane has values differing from the edges values
Definition: NBEdge.cpp:1336
EdgeBuildingStep myStep
The building step.
Definition: NBEdge.h:1173
#define POSITION_EPS
Definition: config.h:186
unsigned int computePrioritySum(std::vector< unsigned int > *priorities)
Definition: NBEdge.cpp:1545
SUMOReal myOffset
This edges&#39;s offset to the intersection begin (will be applied to all lanes)
Definition: NBEdge.h:1220
#define DEG2RAD(x)
Definition: GeomHelper.h:45
std::vector< Connection > myConnections
List of connections to following edges.
Definition: NBEdge.h:1198
void setLoadedLength(SUMOReal val)
Definition: NBEdge.cpp:2082
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:51
The connection was given by the user.
Definition: NBEdge.h:114
const PositionVector & getShape() const
Definition: NBNode.cpp:1338
void removeFromConnections(NBEdge *toEdge, int fromLane=-1, int toLane=-1, bool tryLater=false)
Removes the specified connection(s)
Definition: NBEdge.cpp:824
static void compute(BresenhamCallBack *callBack, const unsigned int val1, const unsigned int val2)
Definition: Bresenham.cpp:45
const SVCPermissions SVCFreeForAll
bool myAmInnerEdge
Information whether this is a junction-inner edge.
Definition: NBEdge.h:1238
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:1071
Base class for objects which have an id.
Definition: Named.h:45
bool recheckLanes()
Definition: NBEdge.cpp:1388
bool intersects(const Line &l) const
Definition: Line.cpp:171
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
Definition: NBEdge.cpp:1096
SUMOReal myLoadedLength
An optional length to use (-1 if not valid)
Definition: NBEdge.h:1231
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:78
bool hasRestrictions() const
whether at least one lane has restrictions
Definition: NBEdge.cpp:1278
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:201
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition: NBEdge.cpp:2067
void extrapolateBy(SUMOReal length)
Definition: Line.cpp:60
SUMOReal length() const
Returns the length.
void push_back(const PositionVector &p)
Appends all positions from the given vector.
std::string myID
The name of the object.
Definition: Named.h:121
void decLaneNo(unsigned int by, int dir=0)
Definition: NBEdge.cpp:1905
std::vector< int > getConnectionLanes(NBEdge *currentOutgoing) const
Returns the list of lanes that may be used to reach the given edge.
Definition: NBEdge.cpp:782
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:81
void computeEdgeShape()
Recomputeds the lane shapes to terminate at the node shape For every lane the intersection with the f...
Definition: NBEdge.cpp:392
void disableConnection4TLS(int fromLane, NBEdge *toEdge, int toLane)
Definition: NBEdge.cpp:1723
PositionVector viaShape
Definition: NBEdge.h:184
bool hasLaneSpecificOffset() const
whether lanes differ in offset
Definition: NBEdge.cpp:1325
SUMOReal getMaxLaneOffset()
Definition: NBEdge.cpp:1633
static bool connections_sorter(const Connection &c1, const Connection &c2)
Definition: NBEdge.h:1384
static const SUMOReal UNSPECIFIED_LOADED_LENGTH
no length override given
Definition: NBEdge.h:205
Position positionAtOffset2D(SUMOReal pos) const
Returns the position at the given length.
std::vector< NBEdge * > EdgeVector
Definition: NBCont.h:38
SUMOReal myLength
The length of the edge.
Definition: NBEdge.h:1182
void setPreferredVehicleClass(SVCPermissions permissions, int lane=-1)
Definition: NBEdge.cpp:2053
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:499
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:1202
static SUMOReal getMinAngleDiff(SUMOReal angle1, SUMOReal angle2)
Returns the minimum distance (clockwise/counter-clockwise) between both angles.
Definition: GeomHelper.cpp:391
void reduceGeometry(const SUMOReal minDist)
Removes points with a distance lesser than the given.
Definition: NBEdge.cpp:537
void setJunctionPriority(const NBNode *const node, int prio)
Sets the junction priority of the edge.
Definition: NBEdge.cpp:1106
void replaceInConnections(NBEdge *which, NBEdge *by, unsigned int laneOff)
Definition: NBEdge.cpp:860
const EdgeVector * getConnectedSorted()
Returns the list of outgoing edges without the turnaround sorted in clockwise direction.
Definition: NBEdge.cpp:742
void sortOutgoingConnectionsByIndex()
sorts the outgoing connections by their from-lane-index and their to-lane-index
Definition: NBEdge.cpp:802
std::string myType
The type of the edge.
Definition: NBEdge.h:1176
LaneSpreadFunction
Numbers representing special SUMO-XML-attribute values Information how the edge&#39;s lateral offset shal...
void append(NBEdge *continuation)
Definition: NBEdge.cpp:1831
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:1134
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:1598
The connection was computed.
Definition: NBEdge.h:112
SUMOReal myStartAngle
The angles of the edge.
Definition: NBEdge.h:1185
Represents a single node (junction) during network building.
Definition: NBNode.h:74
void dismissVehicleClassInformation()
Definition: NBEdge.cpp:2088
bool hasSignalisedConnectionTo(const NBEdge *const e) const
Definition: NBEdge.cpp:1852
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:142
void move2side(SUMOReal amount)
NBEdge * getTurnDestination() const
Definition: NBEdge.cpp:1863
bool hasLaneSpecificWidth() const
whether lanes differ in width
Definition: NBEdge.cpp:1303
Direction
enum of possible directions
Definition: NBEdge.h:1075
#define SUMOReal
Definition: config.h:215
bool isNearEnough2BeJoined2(NBEdge *e, SUMOReal threshold) const
Definition: NBEdge.cpp:1882
void preferVehicleClass(int lane, SUMOVehicleClass vclass)
Definition: NBEdge.cpp:1964
static SUMOReal relAngle(SUMOReal angle1, SUMOReal angle2)
Definition: NBHelpers.cpp:62
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:1938
void addGeometryPoint(int index, const Position &p)
Adds a further geometry point.
Definition: NBEdge.cpp:486
void computeAngle()
computes the angle of this edge and stores it in myAngle
Definition: NBEdge.cpp:1259
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
Definition: NBNodeCont.cpp:129
bool hasConnectionTo(NBEdge *destEdge, unsigned int destLane) const
Retrieves info about a connection to a certain lane of a certain edge.
Definition: NBEdge.cpp:723
SUMOReal getSpeed() const
Returns the speed allowed on this edge.
Definition: NBEdge.h:422
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:63
bool computeEdge2Edges(bool noLeftMovers)
computes the edge (step1: computation of approached edges)
Definition: NBEdge.cpp:1343
static T maxValue(const std::vector< T > &v)
Definition: VectorHelper.h:97
std::vector< SUMOReal > intersectsAtLengths2D(const PositionVector &v)
Definition: Line.cpp:126
SUMOReal width() const
Definition: NBEdge.cpp:1763
void setConnection(unsigned int lane, NBEdge *destEdge, unsigned int destLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false)
Adds a connection to a certain lane of a certain edge.
Definition: NBEdge.cpp:652
unsigned int internalLaneIndex
The lane index of this internal lane within the internal edge.
Definition: NBEdge.h:190
bool foes(const NBEdge *const from1, const NBEdge *const to1, const NBEdge *const from2, const NBEdge *const to2) const
Returns the information whether the given flows cross.
Definition: NBNode.cpp:1100
void setLaneSpreadFunction(LaneSpreadFunction spread)
(Re)sets how the lanes lateral offset shall be computed
Definition: NBEdge.cpp:480
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:179
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:197
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:1253
void append(const PositionVector &v)
NBNode * myFrom
The source and the destination node.
Definition: NBEdge.h:1179
bool expandableBy(NBEdge *possContinuation) const
Definition: NBEdge.cpp:1769
Position intersectsAt(const Line &l) const
Definition: Line.cpp:165
SUMOReal getOffset() const
Returns the offset to the destination node.
Definition: NBEdge.h:465
PositionVector getSubpart(SUMOReal beginOffset, SUMOReal endOffset) const
~MainDirections()
destructor
Definition: NBEdge.cpp:149
void disallowVehicleClass(int lane, SUMOVehicleClass vclass)
set disallowed class for the given lane or for all lanes if -1 is given
Definition: NBEdge.cpp:1951
MainDirections(const EdgeVector &outgoing, NBEdge *parent, NBNode *to)
constructor
Definition: NBEdge.cpp:112
void copyConnectionsFrom(NBEdge *src)
Definition: NBEdge.cpp:929
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:246
static const SUMOReal ANGLE_LOOKAHEAD
the distance at which to take the default anglen
Definition: NBEdge.h:207
SUMOReal getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge&#39;s geometry at the given node.
Definition: NBEdge.cpp:1116
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:1090
LinkDirection getDirection(const NBEdge *const incoming, const NBEdge *const outgoing) const
Returns the representation of the described stream&#39;s direction.
Definition: NBNode.cpp:1188
bool splitGeometry(NBEdgeCont &ec, NBNodeCont &nc)
Splits this edge at geometry points.
Definition: NBEdge.cpp:492