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