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-2014 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  setLaneWidth(i, tpl->getLaneWidth(i));
242  setOffset(i, tpl->getOffset(i));
243  }
244 }
245 
246 
247 void
248 NBEdge::reinit(NBNode* from, NBNode* to, const std::string& type,
249  SUMOReal speed, unsigned int nolanes, int priority,
250  PositionVector geom, SUMOReal laneWidth, SUMOReal offset,
251  const std::string& streetName,
252  LaneSpreadFunction spread,
253  bool tryIgnoreNodePositions) {
254  if (myFrom != from) {
255  myFrom->removeEdge(this, false);
256  }
257  if (myTo != to) {
258  myTo->removeEdge(this, false);
259  }
261  myFrom = from;
262  myTo = to;
263  myPriority = priority;
264  mySpeed = speed;
265  //?myTurnDestination(0),
266  //?myFromJunctionPriority(-1), myToJunctionPriority(-1),
267  myGeom = geom;
268  myLaneSpreadFunction = spread;
269  myOffset = offset;
270  myLaneWidth = laneWidth;
272  myStreetName = streetName;
273  //?, myAmTurningWithAngle(0), myAmTurningOf(0),
274  //?myAmInnerEdge(false), myAmMacroscopicConnector(false)
275  init(nolanes, tryIgnoreNodePositions);
276 }
277 
278 
279 void
281  // connections may still be valid
282  if (from == 0 || to == 0) {
283  throw ProcessError("At least one of edge's '" + myID + "' nodes is not known.");
284  }
285  if (myFrom != from) {
286  myFrom->removeEdge(this, false);
287  myFrom = from;
288  myFrom->addOutgoingEdge(this);
289  }
290  if (myTo != to) {
291  myTo->removeEdge(this, false);
292  myTo = to;
293  myTo->addIncomingEdge(this);
294  }
295  computeAngle();
296 }
297 
298 
299 void
300 NBEdge::init(unsigned int noLanes, bool tryIgnoreNodePositions) {
301  if (noLanes == 0) {
302  throw ProcessError("Edge '" + myID + "' needs at least one lane.");
303  }
304  if (myFrom == 0 || myTo == 0) {
305  throw ProcessError("At least one of edge's '" + myID + "' nodes is not known.");
306  }
307  // revisit geometry
308  // should have at least two points at the end...
309  // and in dome cases, the node positions must be added
311  if (!tryIgnoreNodePositions || myGeom.size() < 2) {
312  if (myGeom.size() == 0) {
315  } else {
318  }
319  }
320  if (myGeom.size() < 2) {
321  myGeom.clear();
324  }
325  if (myGeom.size() == 2 && myGeom[0] == myGeom[1]) {
326  WRITE_ERROR("Edge's '" + myID + "' from- and to-node are at the same position.");
328  }
329  //
330  myFrom->addOutgoingEdge(this);
331  myTo->addIncomingEdge(this);
332  // prepare container
334  assert(myGeom.size() >= 2);
335  myLanes.clear();
336  for (unsigned int i = 0; i < noLanes; i++) {
337  myLanes.push_back(Lane(this));
338  }
340  computeAngle();
341 }
342 
343 
345 
346 
347 // ----------- Applying offset
348 void
350  myGeom.reshiftRotate(xoff, yoff, 0);
351  for (unsigned int i = 0; i < myLanes.size(); i++) {
352  myLanes[i].shape.reshiftRotate(xoff, yoff, 0);
353  }
354 }
355 
356 
357 // ----------- Edge geometry access and computation
358 const PositionVector
360  PositionVector result = getGeometry();
361  result.pop_front();
362  result.pop_back();
363  return result;
364 }
365 
366 
367 bool
369  return myGeom.size() == 2 && hasDefaultGeometryEndpoints();
370 }
371 
372 
373 bool
375  return myGeom.front() == myFrom->getPosition() &&
376  myGeom.back() == myTo->getPosition();
377 }
378 
379 
380 void
381 NBEdge::setGeometry(const PositionVector& s, bool inner) {
382  Position begin = myGeom.front(); // may differ from node position
383  Position end = myGeom.back(); // may differ from node position
384  myGeom = s;
385  if (inner) {
386  myGeom.push_front(begin);
387  myGeom.push_back(end);
388  }
390  computeAngle();
391 }
392 
393 
394 void
396  for (unsigned int i = 0; i < myLanes.size(); i++) {
397  PositionVector& shape = myLanes[i].shape;
398  PositionVector old = shape;
399  shape = startShapeAt(shape, myFrom);
400  if (shape.size() >= 2) {
401  shape = startShapeAt(shape.reverse(), myTo).reverse();
402  }
403  // sanity checks
404  if (shape.length() < POSITION_EPS) {
405  if (old.length() < 2 * POSITION_EPS) {
406  shape = old;
407  } else {
408  const SUMOReal midpoint = old.length() / 2;
409  // EPS*2 because otherwhise shape has only a single point
410  shape = old.getSubpart(midpoint - POSITION_EPS, midpoint + POSITION_EPS);
411  assert(shape.size() >= 2);
412  assert(shape.length() > 0);
413  }
414  } else {
415  // @note If the node shapes are overlapping we may get a shape which goes in the wrong direction
416  // in this case the result shape should shortened
417  Line lc(shape[0], shape[-1]);
418  Line lo(old[0], old[-1]);
420  shape = shape.reverse();
421  shape = shape.getSubpart(0, 2 * POSITION_EPS); // *2 because otherwhise shape has only a single point
422  }
423  }
424  }
425  // recompute edge's length as the average of lane lenghts
426  SUMOReal avgLength = 0;
427  for (unsigned int i = 0; i < myLanes.size(); i++) {
428  assert(myLanes[i].shape.length() > 0);
429  avgLength += myLanes[i].shape.length();
430  }
431  myLength = avgLength / (SUMOReal) myLanes.size();
432  computeAngle(); // update angles using the finalized node and lane shapes
433 }
434 
435 
437 NBEdge::startShapeAt(const PositionVector& laneShape, const NBNode* startNode) const {
438  const PositionVector& nodeShape = startNode->getShape();
439  Line lb = laneShape.getBegLine();
440  // this doesn't look reasonable @todo use lb.extrapolateFirstBy(100.0);
441  lb.extrapolateBy(100.0);
442  if (nodeShape.intersects(laneShape)) {
443  // shape intersects directly
444  std::vector<SUMOReal> pbv = laneShape.intersectsAtLengths2D(nodeShape);
445  assert(pbv.size() > 0);
447  assert(pb >= 0);
448  PositionVector ns = pb <= laneShape.length() ? laneShape.getSubpart2D(pb, laneShape.length()) : laneShape;
449  ns[0].set(ns[0].x(), ns[0].y(), startNode->getPosition().z());
450  return ns;
451  } else if (nodeShape.intersects(lb.p1(), lb.p2())) {
452  // extension of first segment intersects
453  std::vector<SUMOReal> pbv = lb.intersectsAtLengths2D(nodeShape);
454  assert(pbv.size() > 0);
456  assert(pb >= 0);
457  PositionVector result = laneShape;
458  result.eraseAt(0);
459  Position np = lb.getPositionAtDistance2D(pb);
460  result.push_front_noDoublePos(Position(np.x(), np.y(), startNode->getPosition().z()));
461  return result;
462  //if (result.size() >= 2) {
463  // return result;
464  //} else {
465  // WRITE_WARNING(error + " (resulting shape is too short)");
466  // return laneShape;
467  //}
468  } else {
469  // could not find proper intersection. Probably the edge is very short
470  // and lies within nodeShape
471  // @todo enable warning WRITE_WARNING(error + " (laneShape lies within nodeShape)");
472  return laneShape;
473  }
474 }
475 
476 
477 const PositionVector&
478 NBEdge::getLaneShape(unsigned int i) const {
479  return myLanes[i].shape;
480 }
481 
482 
483 void
485  myLaneSpreadFunction = spread;
486 }
487 
488 
489 void
490 NBEdge::addGeometryPoint(int index, const Position& p) {
491  myGeom.insertAt(index, p);
492 }
493 
494 
495 bool
497  // check whether there any splits to perform
498  if (myGeom.size() < 3) {
499  return false;
500  }
501  // ok, split
502  NBNode* newFrom = myFrom;
503  NBNode* myLastNode = myTo;
504  NBNode* newTo = 0;
505  NBEdge* currentEdge = this;
506  for (int i = 1; i < (int) myGeom.size() - 1; i++) {
507  // build the node first
508  if (i != (int)myGeom.size() - 2) {
509  std::string nodename = myID + "_in_between#" + toString(i);
510  if (!nc.insert(nodename, myGeom[i])) {
511  throw ProcessError("Error on adding in-between node '" + nodename + "'.");
512  }
513  newTo = nc.retrieve(nodename);
514  } else {
515  newTo = myLastNode;
516  }
517  if (i == 1) {
518  currentEdge->myTo->removeEdge(this);
519  currentEdge->myTo = newTo;
520  newTo->addIncomingEdge(currentEdge);
521  } else {
522  std::string edgename = myID + "[" + toString(i - 1) + "]";
523  // @bug lane-specific width, speed, overall offset and restrictions are ignored
524  currentEdge = new NBEdge(edgename, newFrom, newTo, myType, mySpeed, (unsigned int) myLanes.size(),
526  if (!ec.insert(currentEdge, true)) {
527  throw ProcessError("Error on adding splitted edge '" + edgename + "'.");
528  }
529  }
530  newFrom = newTo;
531  }
532  myGeom.clear();
535  myStep = INIT;
536  return true;
537 }
538 
539 
540 void
542  myGeom.removeDoublePoints(minDist, true);
543 }
544 
545 
546 void
547 NBEdge::checkGeometry(const SUMOReal maxAngle, const SUMOReal minRadius, bool fix) {
548  if (myGeom.size() < 3) {
549  return;
550  }
551  //std::cout << "checking geometry of " << getID() << " geometry = " << toString(myGeom) << "\n";
552  std::vector<SUMOReal> angles; // absolute segment angles
553  //std::cout << " absolute angles:";
554  for (int i = 0; i < (int)myGeom.size() - 1; ++i) {
555  angles.push_back(myGeom.lineAt(i).atan2DegreeAngle());
556  //std::cout << " " << angles.back();
557  }
558  //std::cout << "\n relative angles: ";
559  for (int i = 0; i < (int)angles.size() - 1; ++i) {
560  const SUMOReal relAngle = fabs(NBHelpers::relAngle(angles[i], angles[i + 1]));
561  //std::cout << relAngle << " ";
562  if (maxAngle > 0 && relAngle > maxAngle) {
563  WRITE_WARNING("Found angle of " + toString(relAngle) + " degrees at edge " + getID() + ", segment " + toString(i));
564  }
565  if (relAngle < 1) {
566  continue;
567  }
568  if (i == 0 || i == (int)angles.size() - 2) {
569  const bool start = i == 0;
570  const Line l = (start ? myGeom.getBegLine() : myGeom.getEndLine());
571  const SUMOReal r = tan(DEG2RAD(90 - 0.5 * relAngle)) * l.length2D();
572  //std::cout << (start ? " start" : " end") << " length=" << l.length2D() << " radius=" << r << " ";
573  if (minRadius > 0 && r < minRadius) {
574  if (fix) {
575  WRITE_MESSAGE("Removing sharp turn with radius " + toString(r) + " at the " +
576  (start ? "start" : "end") + " of edge " + getID());
577  myGeom.eraseAt(start ? 1 : i + 1);
578  checkGeometry(maxAngle, minRadius, fix);
579  return;
580  } else {
581  WRITE_WARNING("Found sharp turn with radius " + toString(r) + " at the " +
582  (start ? "start" : "end") + " of edge " + getID());
583  }
584  }
585  }
586  }
587  //std::cout << "\n";
588 }
589 
590 
591 // ----------- Setting and getting connections
592 bool
595  return true;
596  }
597  // check whether the node was merged and now a connection between
598  // not matching edges is tried to be added
599  // This happens f.e. within the ptv VISSIM-example "Beijing"
600  if (dest != 0 && myTo != dest->myFrom) {
601  return false;
602  }
603  if (dest == 0) {
605  myConnections.push_back(Connection(-1, dest, -1));
606  } else if (find_if(myConnections.begin(), myConnections.end(), connections_toedge_finder(dest)) == myConnections.end()) {
607  myConnections.push_back(Connection(-1, dest, -1));
608  }
609  if (myStep < EDGE2EDGES) {
610  myStep = EDGE2EDGES;
611  }
612  return true;
613 }
614 
615 
616 bool
617 NBEdge::addLane2LaneConnection(unsigned int from, NBEdge* dest,
618  unsigned int toLane, Lane2LaneInfoType type,
619  bool mayUseSameDestination,
620  bool mayDefinitelyPass) {
622  return true;
623  }
624  // check whether the node was merged and now a connection between
625  // not matching edges is tried to be added
626  // This happens f.e. within the ptv VISSIM-example "Beijing"
627  if (myTo != dest->myFrom) {
628  return false;
629  }
630  if (!addEdge2EdgeConnection(dest)) {
631  return false;
632  }
633  setConnection(from, dest, toLane, type, mayUseSameDestination, mayDefinitelyPass);
634  return true;
635 }
636 
637 
638 bool
639 NBEdge::addLane2LaneConnections(unsigned int fromLane,
640  NBEdge* dest, unsigned int toLane,
641  unsigned int no, Lane2LaneInfoType type,
642  bool invalidatePrevious,
643  bool mayDefinitelyPass) {
644  if (invalidatePrevious) {
645  invalidateConnections(true);
646  }
647  bool ok = true;
648  for (unsigned int i = 0; i < no && ok; i++) {
649  ok &= addLane2LaneConnection(fromLane + i, dest, toLane + i, type, false, mayDefinitelyPass);
650  }
651  return ok;
652 }
653 
654 
655 void
656 NBEdge::setConnection(unsigned int lane, NBEdge* destEdge,
657  unsigned int destLane, Lane2LaneInfoType type,
658  bool mayUseSameDestination,
659  bool mayDefinitelyPass) {
661  return;
662  }
663  // some kind of a misbehaviour which may occure when the junction's outgoing
664  // edge priorities were not properly computed, what may happen due to
665  // an incomplete or not proper input
666  // what happens is that under some circumstances a single lane may set to
667  // be approached more than once by the one of our lanes.
668  // This must not be!
669  // we test whether it is the case and do nothing if so - the connection
670  // will be refused
671  //
672  if (!mayUseSameDestination && hasConnectionTo(destEdge, destLane)) {
673  return;
674  }
675  if (find_if(myConnections.begin(), myConnections.end(), connections_finder(lane, destEdge, destLane)) != myConnections.end()) {
676  return;
677  }
678  if (myLanes.size() <= lane) {
679  WRITE_ERROR("Could not set connection from '" + getLaneIDInsecure(lane) + "' to '" + destEdge->getLaneIDInsecure(destLane) + "'.");
680  return;
681  }
682  if (destEdge->getNumLanes() <= destLane) {
683  WRITE_ERROR("Could not set connection from '" + getLaneIDInsecure(lane) + "' to '" + destEdge->getLaneIDInsecure(destLane) + "'.");
684  return;
685  }
686  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end();) {
687  if ((*i).toEdge == destEdge && ((*i).fromLane == -1 || (*i).toLane == -1)) {
688  i = myConnections.erase(i);
689  } else {
690  ++i;
691  }
692  }
693  myConnections.push_back(Connection(lane, destEdge, destLane));
694  if (mayDefinitelyPass) {
695  myConnections.back().mayDefinitelyPass = true;
696  }
697  if (type == L2L_USER) {
699  } else {
700  // check whether we have to take another look at it later
701  if (type == L2L_COMPUTED) {
702  // yes, the connection was set using an algorithm which requires a recheck
704  } else {
705  // ok, let's only not recheck it if we did no add something that has to be recheked
706  if (myStep != LANES2LANES_RECHECK) {
708  }
709  }
710  }
711 }
712 
713 
714 std::vector<NBEdge::Connection>
715 NBEdge::getConnectionsFromLane(unsigned int lane) const {
716  std::vector<NBEdge::Connection> ret;
717  for (std::vector<Connection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
718  if ((*i).fromLane == static_cast<int>(lane)) {
719  ret.push_back(*i);
720  }
721  }
722  return ret;
723 }
724 
725 
726 bool
727 NBEdge::hasConnectionTo(NBEdge* destEdge, unsigned int destLane) const {
728  return destEdge != 0 && find_if(myConnections.begin(), myConnections.end(), connections_toedgelane_finder(destEdge, destLane)) != myConnections.end();
729 }
730 
731 
732 bool
734  if (e == myTurnDestination) {
735  return true;
736  }
737  return
738  find_if(myConnections.begin(), myConnections.end(), connections_toedge_finder(e))
739  !=
740  myConnections.end();
741 
742 }
743 
744 
745 const EdgeVector*
747  // check whether connections exist and if not, use edges from the node
748  EdgeVector outgoing;
749  if (myConnections.size() == 0) {
750  outgoing = myTo->getOutgoingEdges();
751  } else {
752  for (std::vector<Connection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
753  if (find(outgoing.begin(), outgoing.end(), (*i).toEdge) == outgoing.end()) {
754  outgoing.push_back((*i).toEdge);
755  }
756  }
757  }
758  // allocate the sorted container
759  unsigned int size = (unsigned int) outgoing.size();
760  EdgeVector* edges = new EdgeVector();
761  edges->reserve(size);
762  for (EdgeVector::const_iterator i = outgoing.begin(); i != outgoing.end(); i++) {
763  NBEdge* outedge = *i;
764  if (outedge != 0 && outedge != myTurnDestination) {
765  edges->push_back(outedge);
766  }
767  }
768  sort(edges->begin(), edges->end(), NBContHelper::relative_outgoing_edge_sorter(this));
769  return edges;
770 }
771 
772 
775  EdgeVector ret;
776  for (std::vector<Connection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
777  if (find(ret.begin(), ret.end(), (*i).toEdge) == ret.end()) {
778  ret.push_back((*i).toEdge);
779  }
780  }
781  return ret;
782 }
783 
784 
785 std::vector<int>
786 NBEdge::getConnectionLanes(NBEdge* currentOutgoing) const {
787  std::vector<int> ret;
788  if (currentOutgoing != myTurnDestination) {
789  for (std::vector<Connection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
790  if ((*i).toEdge == currentOutgoing) {
791  ret.push_back((*i).fromLane);
792  }
793  }
794  }
795  return ret;
796 }
797 
798 
799 void
802 }
803 
804 
805 void
807  sort(myConnections.begin(), myConnections.end(), connections_sorter);
808 }
809 
810 
811 void
813  EdgeVector connected = getConnectedEdges();
814  for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
815  NBEdge* inc = *i;
816  // We have to do this
817  inc->myStep = EDGE2EDGES;
818  // add all connections
819  for (EdgeVector::iterator j = connected.begin(); j != connected.end(); j++) {
820  inc->addEdge2EdgeConnection(*j);
821  }
822  inc->removeFromConnections(this);
823  }
824 }
825 
826 
827 void
828 NBEdge::removeFromConnections(NBEdge* toEdge, int fromLane, int toLane, bool tryLater) {
829  // remove from "myConnections"
830  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end();) {
831  Connection& c = *i;
832  if (c.toEdge == toEdge
833  && (fromLane < 0 || c.fromLane == fromLane)
834  && (toLane < 0 || c.toLane == toLane)) {
835  i = myConnections.erase(i);
836  tryLater = false;
837  } else {
838  ++i;
839  }
840  }
841  // check whether it was the turn destination
842  if (myTurnDestination == toEdge && fromLane < 0) {
843  myTurnDestination = 0;
844  }
845  if (tryLater) {
846  myConnectionsToDelete.push_back(Connection(fromLane, toEdge, toLane));
847  }
848 }
849 
850 
851 void
852 NBEdge::invalidateConnections(bool reallowSetting) {
853  myTurnDestination = 0;
854  myConnections.clear();
855  if (reallowSetting) {
856  myStep = INIT;
857  } else {
859  }
860 }
861 
862 
863 void
864 NBEdge::replaceInConnections(NBEdge* which, NBEdge* by, unsigned int laneOff) {
865  UNUSED_PARAMETER(laneOff);
866  // replace in "_connectedEdges"
867  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
868  if ((*i).toEdge == which) {
869  (*i).toEdge = by;
870  }
871  }
872  // check whether it was the turn destination
873  if (myTurnDestination == which) {
874  myTurnDestination = by;
875  }
876 }
877 
878 void
879 NBEdge::replaceInConnections(NBEdge* which, const std::vector<NBEdge::Connection>& origConns) {
880  std::map<int, int> laneMap;
881  int minLane = -1;
882  int maxLane = -1;
883  // get lanes used to approach the edge to remap
884  bool wasConnected = false;
885  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
886  if ((*i).toEdge != which) {
887  continue;
888  }
889  wasConnected = true;
890  if ((*i).fromLane != -1) {
891  int fromLane = (*i).fromLane;
892  laneMap[(*i).toLane] = fromLane;
893  if (minLane == -1 || minLane > fromLane) {
894  minLane = fromLane;
895  }
896  if (maxLane == -1 || maxLane < fromLane) {
897  maxLane = fromLane;
898  }
899  }
900  }
901  if (!wasConnected) {
902  return;
903  }
904  // remove the remapped edge from connections
905  removeFromConnections(which);
906  // add new connections
907  std::vector<NBEdge::Connection> conns = origConns;
908  for (std::vector<NBEdge::Connection>::iterator i = conns.begin(); i != conns.end(); ++i) {
909  if ((*i).toEdge == which) {
910  continue;
911  }
912  int fromLane = (*i).fromLane;
913  int toUse = -1;
914  if (laneMap.find(fromLane) == laneMap.end()) {
915  if (fromLane >= 0 && fromLane <= minLane) {
916  toUse = minLane;
917  }
918  if (fromLane >= 0 && fromLane >= maxLane) {
919  toUse = maxLane;
920  }
921  } else {
922  toUse = laneMap[fromLane];
923  }
924  if (toUse == -1) {
925  toUse = 0;
926  }
927  setConnection(toUse, (*i).toEdge, (*i).toLane, L2L_COMPUTED, false, (*i).mayDefinitelyPass);
928  }
929 }
930 
931 
932 void
934  myStep = src->myStep;
936 }
937 
938 
939 void
940 NBEdge::moveConnectionToLeft(unsigned int lane) {
941  unsigned int index = 0;
942  if (myAmLeftHand) {
943  for (int i = (int) myConnections.size() - 1; i >= 0; --i) {
944  if (myConnections[i].fromLane == static_cast<int>(lane) && getTurnDestination() != myConnections[i].toEdge) {
945  index = i;
946  }
947  }
948  } else {
949  for (unsigned int i = 0; i < myConnections.size(); ++i) {
950  if (myConnections[i].fromLane == static_cast<int>(lane)) {
951  index = i;
952  }
953  }
954  }
955  std::vector<Connection>::iterator i = myConnections.begin() + index;
956  Connection c = *i;
957  myConnections.erase(i);
958  setConnection(lane + 1, c.toEdge, c.toLane, L2L_VALIDATED, false);
959 }
960 
961 
962 void
963 NBEdge::moveConnectionToRight(unsigned int lane) {
964  if (myAmLeftHand) {
965  for (int i = (int) myConnections.size() - 1; i >= 0; --i) {
966  if (myConnections[i].fromLane == static_cast<int>(lane) && getTurnDestination() != myConnections[i].toEdge) {
967  Connection c = myConnections[i];
968  myConnections.erase(myConnections.begin() + i);
969  setConnection(lane - 1, c.toEdge, c.toLane, L2L_VALIDATED, false);
970  return;
971  }
972  }
973  } else {
974  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
975  if ((*i).fromLane == static_cast<int>(lane)) {
976  Connection c = *i;
977  i = myConnections.erase(i);
978  setConnection(lane - 1, c.toEdge, c.toLane, L2L_VALIDATED, false);
979  return;
980  }
981  }
982  }
983 }
984 
985 
986 void
987 NBEdge::buildInnerEdges(const NBNode& n, unsigned int noInternalNoSplits, unsigned int& linkIndex, unsigned int& splitIndex) {
988  std::string innerID = ":" + n.getID();
989  NBEdge* toEdge = 0;
990  unsigned int edgeIndex = linkIndex;
991  unsigned int internalLaneIndex = 0;
992  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
993  Connection& con = *i;
994  con.haveVia = false; // reset first since this may be called multiple times
995  if (con.toEdge == 0) {
996  continue;
997  }
998  if (con.toEdge != toEdge) {
999  // skip indices to keep some correspondence between edge ids and link indices:
1000  // internalEdgeIndex + internalLaneIndex = linkIndex
1001  edgeIndex = linkIndex;
1002  toEdge = (*i).toEdge;
1003  internalLaneIndex = 0;
1004  }
1005  PositionVector shape = n.computeInternalLaneShape(this, con.fromLane, con.toEdge, con.toLane);
1006  std::vector<unsigned int> foeInternalLinks;
1007 
1008  LinkDirection dir = n.getDirection(this, con.toEdge);
1009  // crossingPosition, list of foe link indices
1010  std::pair<SUMOReal, std::vector<unsigned int> > crossingPositions(-1, std::vector<unsigned int>());
1011  std::set<std::string> tmpFoeIncomingLanes;
1012  switch (dir) {
1013  case LINKDIR_LEFT:
1014  case LINKDIR_PARTLEFT:
1015  case LINKDIR_TURN: {
1016  unsigned int index = 0;
1017  const std::vector<NBEdge*>& incoming = n.getIncomingEdges();
1018  for (EdgeVector::const_iterator i2 = incoming.begin(); i2 != incoming.end(); ++i2) {
1019  const std::vector<Connection>& elv = (*i2)->getConnections();
1020  for (std::vector<NBEdge::Connection>::const_iterator k2 = elv.begin(); k2 != elv.end(); k2++) {
1021  if ((*k2).toEdge == 0) {
1022  continue;
1023  }
1024  bool needsCont = n.needsCont(this, con.toEdge, *i2, (*k2).toEdge, *k2);
1025  // compute the crossing point
1026  if (needsCont) {
1027  crossingPositions.second.push_back(index);
1028  const PositionVector otherShape = n.computeInternalLaneShape(*i2, (*k2).fromLane, (*k2).toEdge, (*k2).toLane);
1029  const std::vector<SUMOReal> dv = shape.intersectsAtLengths2D(otherShape);
1030  if (dv.size() > 0) {
1031  const SUMOReal minDV = dv[0];
1032  if (minDV < shape.length() - .1 && minDV > .1) { // !!!?
1033  assert(minDV >= 0);
1034  if (crossingPositions.first < 0 || crossingPositions.first > minDV) {
1035  crossingPositions.first = minDV;
1036  }
1037  }
1038  }
1039  }
1040  // compute foe internal lanes
1041  if (n.foes(this, con.toEdge, *i2, (*k2).toEdge)) {
1042  foeInternalLinks.push_back(index);
1043  }
1044  // compute foe incoming lanes
1045  const bool signalised = hasSignalisedConnectionTo(con.toEdge);
1046  if (n.forbids(*i2, (*k2).toEdge, this, con.toEdge, signalised) && (needsCont || dir == LINKDIR_TURN)) {
1047  tmpFoeIncomingLanes.insert((*i2)->getID() + "_" + toString((*k2).fromLane));
1048  }
1049  index++;
1050  }
1051  }
1052  if (dir == LINKDIR_TURN && crossingPositions.first < 0 && crossingPositions.second.size() != 0) {
1053  // let turnarounds wait in the middle if no other crossing point was found
1054  crossingPositions.first = (SUMOReal) shape.length() / 2.;
1055  }
1056  }
1057  break;
1058  default:
1059  break;
1060  }
1061 
1062 
1063  // compute the maximum speed allowed
1064  // see !!! for an explanation (with a_lat_mean ~0.3)
1065  SUMOReal vmax = (SUMOReal) 0.3 * (SUMOReal) 9.80778 *
1066  getLaneShape(con.fromLane).back().distanceTo(
1067  con.toEdge->getLaneShape(con.toLane).front())
1068  / (SUMOReal) 2.0 / (SUMOReal) M_PI;
1069  vmax = MIN2(vmax, ((getSpeed() + con.toEdge->getSpeed()) / (SUMOReal) 2.0));
1070  vmax = (getSpeed() + con.toEdge->getSpeed()) / (SUMOReal) 2.0;
1071  //
1072  Position end = con.toEdge->getLaneShape(con.toLane).front();
1073  Position beg = getLaneShape(con.fromLane).back();
1074 
1075  assert(shape.size() >= 2);
1076  // get internal splits if any
1077  if (crossingPositions.first >= 0) {
1078  std::pair<PositionVector, PositionVector> split = shape.splitAt(crossingPositions.first);
1079  con.id = innerID + "_" + toString(edgeIndex);
1080  con.shape = split.first;
1081  con.foeIncomingLanes = joinToString(tmpFoeIncomingLanes, " ");
1082  con.foeInternalLinks = foeInternalLinks; // resolve link indices to lane ids later
1083  con.viaID = innerID + "_" + toString(splitIndex + noInternalNoSplits);
1084  ++splitIndex;
1085  con.viaVmax = vmax;
1086  con.viaShape = split.second;
1087  con.haveVia = true;
1088  } else {
1089  con.id = innerID + "_" + toString(edgeIndex);
1090  con.shape = shape;
1091  }
1092  con.vmax = vmax;
1093  con.internalLaneIndex = internalLaneIndex;
1094  ++internalLaneIndex;
1095  ++linkIndex;
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 bool hasFromShape = myFrom->getShape().size() > 0;
1269  const bool hasToShape = myTo->getShape().size() > 0;
1270  Position fromCenter = (hasFromShape ? myFrom->getShape().getCentroid() : myFrom->getPosition());
1271  Position toCenter = (hasToShape ? myTo->getShape().getCentroid() : myTo->getPosition());
1272  PositionVector shape = ((hasFromShape || hasToShape) && getNumLanes() > 0 ?
1274  myLanes[getNumLanes() - 1].shape
1275  : myLanes[getNumLanes() / 2].shape)
1276  : myGeom);
1277 
1278  // if the junction shape is suspicious we cannot trust the angle to the centroid
1279  if ((hasFromShape && (myFrom->getShape().distance(shape[0]) > 2 * POSITION_EPS
1280  || myFrom->getShape().around(shape[-1])))
1281  || (hasToShape && (myTo->getShape().distance(shape[-1]) > 2 * POSITION_EPS
1282  || myTo->getShape().around(shape[0])))) {
1283  fromCenter = myFrom->getPosition();
1284  toCenter = myTo->getPosition();
1285  shape = myGeom;
1286  }
1287 
1288  const SUMOReal angleLookahead = MIN2(shape.length2D() / 2, ANGLE_LOOKAHEAD);
1289  const Position referencePosStart = shape.positionAtOffset2D(angleLookahead);
1291  fromCenter.x(), fromCenter.y(),
1292  referencePosStart.x(), referencePosStart.y());
1293  const Position referencePosEnd = shape.positionAtOffset2D(shape.length() - angleLookahead);
1295  referencePosEnd.x(), referencePosEnd.y(),
1296  toCenter.x(), toCenter.y());
1298  myFrom->getPosition().x(), myFrom->getPosition().y(),
1299  myTo->getPosition().x(), myTo->getPosition().y());
1300 
1301 }
1302 
1303 
1304 bool
1306  for (std::vector<Lane>::const_iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
1307  if ((*i).permissions != SVCFreeForAll) {
1308  return true;
1309  }
1310  }
1311  return false;
1312 }
1313 
1314 
1315 bool
1317  std::vector<Lane>::const_iterator i = myLanes.begin();
1318  SVCPermissions firstLanePermissions = i->permissions;
1319  i++;
1320  for (; i != myLanes.end(); ++i) {
1321  if (i->permissions != firstLanePermissions) {
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->width != myLanes.begin()->width) {
1333  return true;
1334  }
1335  }
1336  return false;
1337 }
1338 
1339 
1340 bool
1342  for (std::vector<Lane>::const_iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
1343  if (i->speed != getSpeed()) {
1344  return true;
1345  }
1346  }
1347  return false;
1348 }
1349 
1350 
1351 bool
1353  for (std::vector<Lane>::const_iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
1354  if (i->offset != myLanes.begin()->offset) {
1355  return true;
1356  }
1357  }
1358  return false;
1359 }
1360 
1361 
1362 bool
1365 }
1366 
1367 
1368 
1369 bool
1370 NBEdge::computeEdge2Edges(bool noLeftMovers) {
1371  // return if this relationship has been build in previous steps or
1372  // during the import
1373  if (myStep >= EDGE2EDGES) {
1374  return true;
1375  }
1376  if (myConnections.size() == 0) {
1377  const EdgeVector& o = myTo->getOutgoingEdges();
1378  for (EdgeVector::const_iterator i = o.begin(); i != o.end(); ++i) {
1379  if (noLeftMovers && myTo->isLeftMover(this, *i)) {
1380  continue;
1381  }
1382  myConnections.push_back(Connection(-1, *i, -1));
1383  }
1384  }
1385  myStep = EDGE2EDGES;
1386  return true;
1387 }
1388 
1389 
1390 bool
1392  // return if this relationship has been build in previous steps or
1393  // during the import
1394  if (myStep >= LANES2EDGES) {
1395  return true;
1396  }
1397  assert(myStep == EDGE2EDGES);
1398  // get list of possible outgoing edges sorted by direction clockwise
1399  // the edge in the backward direction (turnaround) is not in the list
1400  const EdgeVector* edges = getConnectedSorted();
1401  if (myConnections.size() != 0 && edges->size() == 0) {
1402  // dead end per definition!?
1403  myConnections.clear();
1404  } else {
1405  // divide the lanes on reachable edges
1406  divideOnEdges(edges);
1407  }
1408  delete edges;
1409  myStep = LANES2EDGES;
1410  return true;
1411 }
1412 
1413 
1414 bool
1416  std::vector<unsigned int> connNumbersPerLane(myLanes.size(), 0);
1417  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end();) {
1418  if ((*i).toEdge == 0 || (*i).fromLane < 0 || (*i).toLane < 0) {
1419  i = myConnections.erase(i);
1420  } else {
1421  if ((*i).fromLane >= 0) {
1422  ++connNumbersPerLane[(*i).fromLane];
1423  }
1424  ++i;
1425  }
1426  }
1428  // check #1:
1429  // If there is a lane with no connections and any neighbour lane has
1430  // more than one connections, try to move one of them.
1431  // This check is only done for edges which connections were assigned
1432  // using the standard algorithm.
1433  for (unsigned int i = 0; i < myLanes.size(); i++) {
1434  if (connNumbersPerLane[i] == 0) {
1435  if (i > 0 && connNumbersPerLane[i - 1] > 1) {
1436  moveConnectionToLeft(i - 1);
1437  } else if (i < myLanes.size() - 1 && connNumbersPerLane[i + 1] > 1) {
1438  moveConnectionToRight(i + 1);
1439  }
1440  }
1441  }
1442  }
1443  // check delayed removals
1444  for (std::vector<Connection>::iterator it = myConnectionsToDelete.begin(); it != myConnectionsToDelete.end(); ++it) {
1445  removeFromConnections(it->toEdge, it->fromLane, it->toLane);
1446  }
1447  return true;
1448 }
1449 
1450 
1451 void
1453  if (outgoing->size() == 0) {
1454  // we have to do this, because the turnaround may have been added before
1455  myConnections.clear();
1456  return;
1457  }
1458  // precompute priorities; needed as some kind of assumptions for
1459  // priorities of directions (see preparePriorities)
1460  std::vector<unsigned int>* priorities = preparePriorities(outgoing);
1461 
1462  // compute the sum of priorities (needed for normalisation)
1463  unsigned int prioSum = computePrioritySum(priorities);
1464  // compute the resulting number of lanes that should be used to
1465  // reach the following edge
1466  unsigned int size = (unsigned int) outgoing->size();
1467  std::vector<SUMOReal> resultingLanes;
1468  resultingLanes.reserve(size);
1469  SUMOReal sumResulting = 0; // the sum of resulting lanes
1470  SUMOReal minResulting = 10000; // the least number of lanes to reach an edge
1471  unsigned int i;
1472  for (i = 0; i < size; i++) {
1473  // res will be the number of lanes which are meant to reach the
1474  // current outgoing edge
1475  SUMOReal res =
1476  (SUMOReal)(*priorities)[i] *
1477  (SUMOReal) myLanes.size() / (SUMOReal) prioSum;
1478  // do not let this number be greater than the number of available lanes
1479  if (res > myLanes.size()) {
1480  res = (SUMOReal) myLanes.size();
1481  }
1482  // add it to the list
1483  resultingLanes.push_back(res);
1484  sumResulting += res;
1485  if (minResulting > res) {
1486  minResulting = res;
1487  }
1488  }
1489  // compute the number of virtual edges
1490  // a virtual edge is used as a replacement for a real edge from now on
1491  // it shall ollow to divide the existing lanes on this structure without
1492  // regarding the structure of outgoing edges
1493  sumResulting += minResulting / (SUMOReal) 2.;
1494  unsigned int noVirtual = (unsigned int)(sumResulting / minResulting);
1495  // compute the transition from virtual to real edges
1496  EdgeVector transition;
1497  transition.reserve(size);
1498  for (i = 0; i < size; i++) {
1499  // tmpNo will be the number of connections from this edge
1500  // to the next edge
1501  assert(i < resultingLanes.size());
1502  SUMOReal tmpNo = (SUMOReal) resultingLanes[i] / (SUMOReal) minResulting;
1503  for (SUMOReal j = 0; j < tmpNo; j++) {
1504  assert(outgoing->size() > i);
1505  transition.push_back((*outgoing)[i]);
1506  }
1507  }
1508 
1509  // assign lanes to edges
1510  // (conversion from virtual to real edges is done)
1511  ToEdgeConnectionsAdder adder(transition);
1512  Bresenham::compute(&adder, static_cast<unsigned int>(myLanes.size()), noVirtual);
1513  const std::map<NBEdge*, std::vector<unsigned int> >& l2eConns = adder.getBuiltConnections();
1514  myConnections.clear();
1515  for (std::map<NBEdge*, std::vector<unsigned int> >::const_iterator i = l2eConns.begin(); i != l2eConns.end(); ++i) {
1516  const std::vector<unsigned int> lanes = (*i).second;
1517  for (std::vector<unsigned int>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
1518  if (myAmLeftHand) {
1519  myConnections.push_back(Connection(int(myLanes.size() - 1 - *j), (*i).first, -1));
1520  } else {
1521  myConnections.push_back(Connection(int(*j), (*i).first, -1));
1522  }
1523  }
1524  }
1525  delete priorities;
1526 }
1527 
1528 
1529 std::vector<unsigned int>*
1531  // copy the priorities first
1532  std::vector<unsigned int>* priorities = new std::vector<unsigned int>();
1533  if (outgoing->size() == 0) {
1534  return priorities;
1535  }
1536  priorities->reserve(outgoing->size());
1537  EdgeVector::const_iterator i;
1538  for (i = outgoing->begin(); i != outgoing->end(); i++) {
1539  int prio = (*i)->getJunctionPriority(myTo);
1540  assert((prio + 1) * 2 > 0);
1541  prio = (prio + 1) * 2;
1542  priorities->push_back(prio);
1543  }
1544  // when the right turning direction has not a higher priority, divide
1545  // the importance by 2 due to the possibility to leave the junction
1546  // faster from this lane
1547  MainDirections mainDirections(*outgoing, this, myTo);
1548  EdgeVector tmp(*outgoing);
1549  sort(tmp.begin(), tmp.end(), NBContHelper::edge_similar_direction_sorter(this));
1550  i = find(outgoing->begin(), outgoing->end(), *(tmp.begin()));
1551  unsigned int dist = (unsigned int) distance(outgoing->begin(), i);
1552  if (dist != 0 && !mainDirections.includes(MainDirections::DIR_RIGHTMOST)) {
1553  assert(priorities->size() > 0);
1554  (*priorities)[0] = (*priorities)[0] / 2;
1555  }
1556  // HEURISTIC:
1557  // when no higher priority exists, let the forward direction be
1558  // the main direction
1559  if (mainDirections.empty()) {
1560  assert(dist < priorities->size());
1561  (*priorities)[dist] = (*priorities)[dist] * 2;
1562  }
1563  if (mainDirections.includes(MainDirections::DIR_FORWARD) && myLanes.size() > 2) {
1564  (*priorities)[dist] = (*priorities)[dist] * 2;
1565  }
1566  // return
1567  return priorities;
1568 }
1569 
1570 
1571 unsigned int
1572 NBEdge::computePrioritySum(std::vector<unsigned int>* priorities) {
1573  unsigned int sum = 0;
1574  for (std::vector<unsigned int>::iterator i = priorities->begin(); i != priorities->end(); i++) {
1575  sum += int(*i);
1576  }
1577  return sum;
1578 }
1579 
1580 
1581 void
1582 NBEdge::appendTurnaround(bool noTLSControlled) {
1583  // do nothing if no turnaround is known
1584  if (myTurnDestination == 0) {
1585  return;
1586  }
1587  // do nothing if the destination node is controlled by a tls and no turnarounds
1588  // shall be appended for such junctions
1589  if (noTLSControlled && myTo->isTLControlled()) {
1590  return;
1591  }
1592  setConnection((unsigned int)(myLanes.size() - 1), myTurnDestination, myTurnDestination->getNumLanes() - 1, L2L_VALIDATED);
1593 }
1594 
1595 
1596 bool
1597 NBEdge::isTurningDirectionAt(const NBNode* n, const NBEdge* const edge) const {
1598  // maybe it was already set as the turning direction
1599  if (edge == myTurnDestination) {
1600  return true;
1601  } else if (myTurnDestination != 0) {
1602  // otherwise - it's not if a turning direction exists
1603  return false;
1604  }
1605  // if the same nodes are connected
1606  if (myFrom == edge->myTo && myTo == edge->myFrom) {
1607  return true;
1608  }
1609  // we have to check whether the connection between the nodes is
1610  // geometrically similar
1611  SUMOReal thisFromAngle2 = getAngleAtNode(n);
1612  SUMOReal otherToAngle2 = edge->getAngleAtNode(n);
1613  if (thisFromAngle2 < otherToAngle2) {
1614  std::swap(thisFromAngle2, otherToAngle2);
1615  }
1616  if (thisFromAngle2 - otherToAngle2 > 170 && thisFromAngle2 - otherToAngle2 < 190) {
1617  return true;
1618  }
1619  return false;
1620 }
1621 
1622 
1623 
1624 NBNode*
1626  // return the from-node when the position is at the begin of the edge
1627  if (pos < tolerance) {
1628  return myFrom;
1629  }
1630  // return the to-node when the position is at the end of the edge
1631  if (pos > myLength - tolerance) {
1632  return myTo;
1633  }
1634  return 0;
1635 }
1636 
1637 
1638 void
1639 NBEdge::moveOutgoingConnectionsFrom(NBEdge* e, unsigned int laneOff) {
1640  unsigned int lanes = e->getNumLanes();
1641  for (unsigned int i = 0; i < lanes; i++) {
1642  std::vector<NBEdge::Connection> elv = e->getConnectionsFromLane(i);
1643  for (std::vector<NBEdge::Connection>::iterator j = elv.begin(); j != elv.end(); j++) {
1644  NBEdge::Connection el = *j;
1645  assert(el.tlID == "");
1646  bool ok = addLane2LaneConnection(i + laneOff, el.toEdge, el.toLane, L2L_COMPUTED);
1647  assert(ok);
1648  UNUSED_PARAMETER(ok); // only used for assertion
1649  }
1650  }
1651 }
1652 
1653 
1654 bool
1657 }
1658 
1659 
1660 SUMOReal
1663 }
1664 
1665 
1666 bool
1667 NBEdge::mayBeTLSControlled(int fromLane, NBEdge* toEdge, int toLane) const {
1669  tpl.fromLane = fromLane;
1670  tpl.to = toEdge;
1671  tpl.toLane = toLane;
1672  std::vector<TLSDisabledConnection>::const_iterator i = find_if(myTLSDisabledConnections.begin(), myTLSDisabledConnections.end(), tls_disable_finder(tpl));
1673  return i == myTLSDisabledConnections.end();
1674 }
1675 
1676 
1677 bool
1678 NBEdge::setControllingTLInformation(const NBConnection& c, const std::string& tlID) {
1679  const int fromLane = c.getFromLane();
1680  NBEdge* toEdge = c.getTo();
1681  const int toLane = c.getToLane();
1682  const int tlIndex = c.getTLIndex();
1683  // check whether the connection was not set as not to be controled previously
1685  tpl.fromLane = fromLane;
1686  tpl.to = toEdge;
1687  tpl.toLane = toLane;
1688  std::vector<TLSDisabledConnection>::iterator i = find_if(myTLSDisabledConnections.begin(), myTLSDisabledConnections.end(), tls_disable_finder(tpl));
1689  if (i != myTLSDisabledConnections.end()) {
1690  return false;
1691  }
1692 
1693  assert(fromLane < 0 || fromLane < (int) myLanes.size());
1694  // try to use information about the connections if given
1695  if (fromLane >= 0 && toLane >= 0) {
1696  // find the specified connection
1697  std::vector<Connection>::iterator i =
1698  find_if(myConnections.begin(), myConnections.end(), connections_finder(fromLane, toEdge, toLane));
1699  // ok, we have to test this as on the removal of self-loop edges some connections
1700  // will be reassigned
1701  if (i != myConnections.end()) {
1702  // get the connection
1703  Connection& connection = *i;
1704  // set the information about the tl
1705  connection.tlID = tlID;
1706  connection.tlLinkNo = tlIndex;
1707  return true;
1708  }
1709  }
1710  // if the original connection was not found, set the information for all
1711  // connections
1712  unsigned int no = 0;
1713  bool hadError = false;
1714  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
1715  if ((*i).toEdge != toEdge) {
1716  continue;
1717  }
1718  if (fromLane >= 0 && fromLane != (*i).fromLane) {
1719  continue;
1720  }
1721  if (toLane >= 0 && toLane != (*i).toLane) {
1722  continue;
1723  }
1724  if ((*i).tlID == "") {
1725  (*i).tlID = tlID;
1726  (*i).tlLinkNo = tlIndex;
1727  no++;
1728  } else {
1729  if ((*i).tlID != tlID && static_cast<int>((*i).tlLinkNo) == tlIndex) {
1730  WRITE_WARNING("The lane " + toString<int>((*i).fromLane) + " on edge " + getID() + " already had a traffic light signal.");
1731  hadError = true;
1732  }
1733  }
1734  }
1735  if (hadError && no == 0) {
1736  WRITE_WARNING("Could not set any signal of the traffic light '" + tlID + "' (unknown group)");
1737  }
1738  return true;
1739 }
1740 
1741 
1742 void
1744  for (std::vector<Connection>::iterator it = myConnections.begin(); it != myConnections.end(); it++) {
1745  it->tlID = "";
1746  }
1747 }
1748 
1749 
1750 void
1751 NBEdge::disableConnection4TLS(int fromLane, NBEdge* toEdge, int toLane) {
1753  c.fromLane = fromLane;
1754  c.to = toEdge;
1755  c.toLane = toLane;
1756  myTLSDisabledConnections.push_back(c);
1757 }
1758 
1759 
1761 NBEdge::getCWBoundaryLine(const NBNode& n, SUMOReal offset) const {
1762  PositionVector ret;
1763  if (myFrom == (&n)) {
1764  // outgoing
1765  ret = !myAmLeftHand ? myLanes[0].shape : myLanes.back().shape;
1766  } else {
1767  // incoming
1768  ret = !myAmLeftHand ? myLanes.back().shape.reverse() : myLanes[0].shape.reverse();
1769  }
1770  ret.move2side(offset);
1771  return ret;
1772 }
1773 
1774 
1776 NBEdge::getCCWBoundaryLine(const NBNode& n, SUMOReal offset) const {
1777  PositionVector ret;
1778  if (myFrom == (&n)) {
1779  // outgoing
1780  ret = !myAmLeftHand ? myLanes.back().shape : myLanes[0].shape;
1781  } else {
1782  // incoming
1783  ret = !myAmLeftHand ? myLanes[0].shape.reverse() : myLanes.back().shape.reverse();
1784  }
1785  ret.move2side(-offset);
1786  return ret;
1787 }
1788 
1789 
1790 SUMOReal
1791 NBEdge::width() const {
1792  return (SUMOReal) myLanes.size() * SUMO_const_laneWidth + (SUMOReal)(myLanes.size() - 1) * SUMO_const_laneOffset;
1793 }
1794 
1795 
1796 bool
1797 NBEdge::expandableBy(NBEdge* possContinuation) const {
1798  // ok, the number of lanes must match
1799  if (myLanes.size() != possContinuation->myLanes.size()) {
1800  return false;
1801  }
1802  // the priority, too (?)
1803  if (getPriority() != possContinuation->getPriority()) {
1804  return false;
1805  }
1806  // the speed allowed
1807  if (mySpeed != possContinuation->mySpeed) {
1808  return false;
1809  }
1810  // the vehicle class constraints, too
1818  // also, check whether the connections - if any exit do allow to join
1819  // both edges
1820  // This edge must have a one-to-one connection to the following lanes
1821  switch (myStep) {
1823  break;
1824  case INIT:
1825  break;
1826  case EDGE2EDGES: {
1827  // the following edge must be connected
1828  const EdgeVector& conn = getConnectedEdges();
1829  if (find(conn.begin(), conn.end(), possContinuation)
1830  == conn.end()) {
1831 
1832  return false;
1833  }
1834  }
1835  break;
1836  case LANES2EDGES:
1837  case LANES2LANES_RECHECK:
1838  case LANES2LANES_DONE:
1839  case LANES2LANES_USER: {
1840  // the possible continuation must be connected
1841  if (find_if(myConnections.begin(), myConnections.end(), connections_toedge_finder(possContinuation)) == myConnections.end()) {
1842  return false;
1843  }
1844  // all lanes must go to the possible continuation
1845  std::vector<int> conns = getConnectionLanes(possContinuation);
1846  if (conns.size() != myLanes.size()) {
1847  return false;
1848  }
1849  }
1850  break;
1851  default:
1852  break;
1853  }
1854  return true;
1855 }
1856 
1857 
1858 void
1860  // append geometry
1861  myGeom.append(e->myGeom);
1862  for (unsigned int i = 0; i < myLanes.size(); i++) {
1863  myLanes[i].shape.append(e->myLanes[i].shape);
1864  }
1865  // recompute length
1866  myLength += e->myLength;
1867  // copy the connections and the building step if given
1868  myStep = e->myStep;
1871  // set the node
1872  myTo = e->myTo;
1873  computeAngle(); // myEndAngle may be different now
1874 }
1875 
1876 
1877 bool
1879  for (std::vector<Connection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
1880  if ((*i).toEdge == e && (*i).tlID != "") {
1881  return true;
1882  }
1883  }
1884  return false;
1885 }
1886 
1887 
1888 NBEdge*
1890  return myTurnDestination;
1891 }
1892 
1893 
1894 std::string
1895 NBEdge::getLaneID(unsigned int lane) const {
1896  assert(lane < myLanes.size());
1897  return myID + "_" + toString(lane);
1898 }
1899 
1900 
1901 std::string
1902 NBEdge::getLaneIDInsecure(unsigned int lane) const {
1903  return myID + "_" + toString(lane);
1904 }
1905 
1906 
1907 bool
1909  std::vector<SUMOReal> distances = myGeom.distances(e->getGeometry());
1910  assert(distances.size() > 0);
1911  return VectorHelper<SUMOReal>::maxValue(distances) < threshold;
1912 }
1913 
1914 
1915 void
1916 NBEdge::incLaneNo(unsigned int by) {
1917  unsigned int newLaneNo = (unsigned int) myLanes.size() + by;
1918  while (myLanes.size() < newLaneNo) {
1919  myLanes.push_back(Lane(this));
1920  }
1922  const EdgeVector& incs = myFrom->getIncomingEdges();
1923  for (EdgeVector::const_iterator i = incs.begin(); i != incs.end(); ++i) {
1924  (*i)->invalidateConnections(true);
1925  }
1926  invalidateConnections(true);
1927 }
1928 
1929 
1930 void
1931 NBEdge::decLaneNo(unsigned int by, int dir) {
1932  unsigned int newLaneNo = (unsigned int) myLanes.size() - by;
1933  while (myLanes.size() > newLaneNo) {
1934  myLanes.pop_back();
1935  }
1937  const EdgeVector& incs = myFrom->getIncomingEdges();
1938  for (EdgeVector::const_iterator i = incs.begin(); i != incs.end(); ++i) {
1939  (*i)->invalidateConnections(true);
1940  }
1941  if (dir == 0) {
1942  invalidateConnections(true);
1943  } else {
1944  const EdgeVector& outs = myTo->getOutgoingEdges();
1945  assert(outs.size() == 1);
1946  NBEdge* out = outs[0];
1947  if (dir < 0) {
1948  removeFromConnections(out, 0);
1949  } else {
1950  removeFromConnections(out, (int) myLanes.size());
1951  }
1952  }
1953 }
1954 
1955 
1956 void
1958  assert(myTo->getOutgoingEdges().size() == 0);
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].permissions |= vclass;
1972  }
1973 }
1974 
1975 
1976 void
1978  if (lane < 0) { // all lanes are meant...
1979  for (unsigned int i = 0; i < myLanes.size(); i++) {
1980  disallowVehicleClass((int) i, vclass);
1981  }
1982  } else {
1983  assert(lane < (int) myLanes.size());
1984  myLanes[lane].permissions &= ~vclass;
1985  }
1986 }
1987 
1988 
1989 void
1991  if (lane < 0) { // all lanes are meant...
1992  for (unsigned int i = 0; i < myLanes.size(); i++) {
1993  allowVehicleClass((int) i, vclass);
1994  }
1995  } else {
1996  assert(lane < (int) myLanes.size());
1997  myLanes[lane].preferred |= vclass;
1998  }
1999 }
2000 
2001 
2002 void
2003 NBEdge::setLaneWidth(int lane, SUMOReal width) {
2004  if (lane < 0) {
2005  // all lanes are meant...
2006  myLaneWidth = width;
2007  for (unsigned int i = 0; i < myLanes.size(); i++) {
2008  // ... do it for each lane
2009  setLaneWidth((int) i, width);
2010  }
2011  return;
2012  }
2013  assert(lane < (int) myLanes.size());
2014  myLanes[lane].width = width;
2015 }
2016 
2017 
2018 SUMOReal
2019 NBEdge::getLaneWidth(int lane) const {
2020  return myLanes[lane].width != UNSPECIFIED_WIDTH
2021  ? myLanes[lane].width
2023 }
2024 
2025 
2026 SUMOReal
2027 NBEdge::getOffset(int lane) const {
2028  return myLanes[lane].offset != UNSPECIFIED_OFFSET ? myLanes[lane].offset : getOffset();
2029 }
2030 
2031 
2032 void
2033 NBEdge::setOffset(int lane, SUMOReal offset) {
2034  if (lane < 0) {
2035  // all lanes are meant...
2036  myOffset = offset;
2037  for (unsigned int i = 0; i < myLanes.size(); i++) {
2038  // ... do it for each lane
2039  setOffset((int) i, offset);
2040  }
2041  return;
2042  }
2043  assert(lane < (int) myLanes.size());
2044  myLanes[lane].offset = offset;
2045 }
2046 
2047 
2048 void
2049 NBEdge::setSpeed(int lane, SUMOReal speed) {
2050  if (lane < 0) {
2051  // all lanes are meant...
2052  mySpeed = speed;
2053  for (unsigned int i = 0; i < myLanes.size(); i++) {
2054  // ... do it for each lane
2055  setSpeed((int) i, speed);
2056  }
2057  return;
2058  }
2059  assert(lane < (int) myLanes.size());
2060  myLanes[lane].speed = speed;
2061 }
2062 
2063 
2064 void
2065 NBEdge::setPermissions(SVCPermissions permissions, int lane) {
2066  if (lane < 0) {
2067  for (unsigned int i = 0; i < myLanes.size(); i++) {
2068  // ... do it for each lane
2069  setPermissions(permissions, i);
2070  }
2071  } else {
2072  assert(lane < (int) myLanes.size());
2073  myLanes[lane].permissions = permissions;
2074  }
2075 }
2076 
2077 
2078 void
2080  if (lane < 0) {
2081  for (unsigned int i = 0; i < myLanes.size(); i++) {
2082  // ... do it for each lane
2083  setPreferredVehicleClass(permissions, i);
2084  }
2085  } else {
2086  assert(lane < (int) myLanes.size());
2087  myLanes[lane].preferred = permissions;
2088  }
2089 }
2090 
2091 
2093 NBEdge::getPermissions(int lane) const {
2094  if (lane < 0) {
2095  SVCPermissions result = 0;
2096  for (unsigned int i = 0; i < myLanes.size(); i++) {
2097  result |= getPermissions(i);
2098  }
2099  return result;
2100  } else {
2101  assert(lane < (int) myLanes.size());
2102  return myLanes[lane].permissions;
2103  }
2104 }
2105 
2106 
2107 void
2109  myLoadedLength = val;
2110 }
2111 
2112 
2113 void
2115  for (std::vector<Lane>::iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
2116  (*i).permissions = SVCFreeForAll;
2117  (*i).preferred = 0;
2118  }
2119 }
2120 
2121 
2122 bool
2124  if (c1.fromLane != c2.fromLane) {
2125  return c1.fromLane < c2.fromLane;
2126  }
2127  if (c1.toEdge != c2.toEdge) {
2128  return false; // do not change ordering among toEdges as this is determined by angle in an earlier step
2129  }
2130  return c1.toLane < c2.toLane;
2131 }
2132 
2133 /****************************************************************************/
SUMOReal length2D() const
Definition: Line.cpp:177
std::string id
Definition: NBEdge.h:177
void invalidateConnections(bool reallowSetting=false)
Definition: NBEdge.cpp:852
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:478
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's incoming edges.
Definition: NBNode.h:170
bool setControllingTLInformation(const NBConnection &c, const std::string &tlID)
Returns if the link could be set as to be controlled.
Definition: NBEdge.cpp:1678
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:1452
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:1530
std::string foeIncomingLanes
Definition: NBEdge.h:187
const SUMOReal SUMO_const_laneWidth
Definition: StdDefs.h:45
int getTLIndex() const
Definition: NBConnection.h:98
std::vector< TLSDisabledConnection > myTLSDisabledConnections
Definition: NBEdge.h:1249
~NBEdge()
Destructor.
Definition: NBEdge.cpp:344
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:800
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:368
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:1582
#define M_PI
Definition: angles.h:37
PositionVector getCCWBoundaryLine(const NBNode &n, SUMOReal offset) const
Definition: NBEdge.cpp:1776
void setLaneWidth(int lane, SUMOReal width)
set lane specific width (negative lane implies set for all lanes)
Definition: NBEdge.cpp:2003
std::vector< SUMOReal > distances(const PositionVector &s) const
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition: NBNode.h:221
void setSpeed(int lane, SUMOReal speed)
set lane specific speed (negative lane implies set for all lanes)
Definition: NBEdge.cpp:2049
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:403
void setOffset(int lane, SUMOReal offset)
set lane specific end-offset (negative lane implies set for all lanes)
Definition: NBEdge.cpp:2033
void moveOutgoingConnectionsFrom(NBEdge *e, unsigned int laneOff)
Definition: NBEdge.cpp:1639
const SUMOReal SUMO_const_laneWidthAndOffset
Definition: StdDefs.h:49
void removeEdge(NBEdge *edge, bool removeFromConnections=true)
Removes edge from this node and optionally removes connections as well.
Definition: NBNode.cpp:971
Position getPositionAtDistance2D(SUMOReal offset) const
Definition: Line.cpp:105
void addIncomingEdge(NBEdge *edge)
adds an incoming edge
Definition: NBNode.cpp:354
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:280
void clearControllingTLInformation()
clears tlID for all connections
Definition: NBEdge.cpp:1743
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:1667
bool hasDefaultGeometryEndpoints() const
Returns whether the geometry is terminated by the node positions This default may be violated by init...
Definition: NBEdge.cpp:374
The link is a 180 degree turn.
Position getCentroid() const
Returns the centroid (closes the polygon if unclosed)
int getFromLane() const
returns the from-lane
void incLaneNo(unsigned int by)
Definition: NBEdge.cpp:1916
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:639
void buildInnerEdges(const NBNode &n, unsigned int noInternalNoSplits, unsigned int &linkIndex, unsigned int &splitIndex)
Definition: NBEdge.cpp:987
void markAsInLane2LaneState()
Definition: NBEdge.cpp:1957
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's lane and an approached one.
Definition: NBEdge.cpp:617
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:440
std::string getLaneIDInsecure(unsigned int lane) const
Definition: NBEdge.cpp:1902
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:2065
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:1145
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:812
SUMOReal distanceTo(const Position &p2) const
returns the euclidean distance in 3 dimension
Definition: Position.h:219
void eraseAt(int i)
const SUMOReal SUMO_const_laneOffset
Definition: StdDefs.h:48
bool around(const Position &p, SUMOReal offset=0) const
Returns the information whether the position vector describes a polygon lying around the given point ...
bool isTurningDirectionAt(const NBNode *n, const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition: NBEdge.cpp:1597
static const SUMOReal UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:203
PositionVector getCWBoundaryLine(const NBNode &n, SUMOReal offset) const
Definition: NBEdge.cpp:1761
std::vector< Connection > getConnectionsFromLane(unsigned int lane) const
Returns connections from a given lane.
Definition: NBEdge.cpp:715
SUMOReal x() const
Returns the x-position.
Definition: Position.h:63
void addOutgoingEdge(NBEdge *edge)
adds an outgoing edge
Definition: NBNode.cpp:364
void setGeometry(const PositionVector &g, bool inner=false)
(Re)sets the edge's geometry
Definition: NBEdge.cpp:381
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:38
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:437
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:774
The link is a straight direction.
PositionVector shape
Definition: NBEdge.h:178
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges.
Definition: NBNode.h:178
void moveConnectionToRight(unsigned int lane)
Definition: NBEdge.cpp:963
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 length2D() const
Returns the length.
SUMOReal mySpeed
The maximal speed.
Definition: NBEdge.h:1193
bool addEdge2EdgeConnection(NBEdge *dest)
Adds a connection to another edge.
Definition: NBEdge.cpp:593
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:733
const PositionVector getInnerGeometry() const
Returns the geometry of the edge without the endpoints.
Definition: NBEdge.cpp:359
void push_front_noDoublePos(const Position &p)
void reshiftPosition(SUMOReal xoff, SUMOReal yoff)
Applies an offset to the edge.
Definition: NBEdge.cpp:349
const Position & getPosition() const
Returns the position of this node.
Definition: NBNode.h:158
const Position & p1() const
Definition: Line.cpp:80
bool computeLanes2Edges()
computes the edge, step2: computation of which lanes approach the edges)
Definition: NBEdge.cpp:1391
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:1341
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:547
std::string getLaneID(unsigned int lane) const
Definition: NBEdge.cpp:1895
void moveConnectionToLeft(unsigned int lane)
Definition: NBEdge.cpp:940
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:1316
bool lanesWereAssigned() const
Definition: NBEdge.cpp:1655
bool needsCont(NBEdge *fromE, NBEdge *toE, NBEdge *otherFromE, NBEdge *otherToE, const NBEdge::Connection &c) const
Definition: NBNode.cpp:527
static bool connections_sorter(const Connection &c1, const Connection &c2)
Definition: NBEdge.cpp:2123
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
SUMOReal distance(const Position &p) const
static SUMOReal angle(SUMOReal x1, SUMOReal y1, SUMOReal x2, SUMOReal y2)
Definition: NBHelpers.cpp:52
SUMOReal myLaneWidth
This width of this edge'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:300
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:66
T MIN2(T a, T b)
Definition: StdDefs.h:65
bool needsLaneSpecificOutput() const
whether at least one lane has values differing from the edges values
Definition: NBEdge.cpp:1363
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:1572
SUMOReal myOffset
This edges'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:2108
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:52
The connection was given by the user.
Definition: NBEdge.h:114
const PositionVector & getShape() const
Definition: NBNode.cpp:1332
void removeFromConnections(NBEdge *toEdge, int fromLane=-1, int toLane=-1, bool tryLater=false)
Removes the specified connection(s)
Definition: NBEdge.cpp:828
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:1065
Base class for objects which have an id.
Definition: Named.h:45
bool recheckLanes()
Definition: NBEdge.cpp:1415
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: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 "Umlaute" to their latin-version.
Definition: StringUtils.cpp:95
bool hasRestrictions() const
whether at least one lane has restrictions
Definition: NBEdge.cpp:1305
#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:2093
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:128
void decLaneNo(unsigned int by, int dir=0)
Definition: NBEdge.cpp:1931
std::vector< int > getConnectionLanes(NBEdge *currentOutgoing) const
Returns the list of lanes that may be used to reach the given edge.
Definition: NBEdge.cpp:786
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:395
void disableConnection4TLS(int fromLane, NBEdge *toEdge, int toLane)
Definition: NBEdge.cpp:1751
PositionVector viaShape
Definition: NBEdge.h:184
bool hasLaneSpecificOffset() const
whether lanes differ in offset
Definition: NBEdge.cpp:1352
SUMOReal getMaxLaneOffset()
Definition: NBEdge.cpp:1661
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:2079
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:541
void setJunctionPriority(const NBNode *const node, int prio)
Sets the junction priority of the edge.
Definition: NBEdge.cpp:1111
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
Definition: NBNodeCont.cpp:79
void replaceInConnections(NBEdge *which, NBEdge *by, unsigned int laneOff)
Definition: NBEdge.cpp:864
const EdgeVector * getConnectedSorted()
Returns the list of outgoing edges without the turnaround sorted in clockwise direction.
Definition: NBEdge.cpp:746
void sortOutgoingConnectionsByIndex()
sorts the outgoing connections by their from-lane-index and their to-lane-index
Definition: NBEdge.cpp:806
std::string myType
The type of the edge.
Definition: NBEdge.h:1176
LaneSpreadFunction
Numbers representing special SUMO-XML-attribute values Information how the edge's lateral offset shal...
void append(NBEdge *continuation)
Definition: NBEdge.cpp:1859
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:1625
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:2114
bool hasSignalisedConnectionTo(const NBEdge *const e) const
Definition: NBEdge.cpp:1878
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:152
void move2side(SUMOReal amount)
NBEdge * getTurnDestination() const
Definition: NBEdge.cpp:1889
bool hasLaneSpecificWidth() const
whether lanes differ in width
Definition: NBEdge.cpp:1330
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:1908
void preferVehicleClass(int lane, SUMOVehicleClass vclass)
Definition: NBEdge.cpp:1990
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:1964
void addGeometryPoint(int index, const Position &p)
Adds a further geometry point.
Definition: NBEdge.cpp:490
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:124
bool hasConnectionTo(NBEdge *destEdge, unsigned int destLane) const
Retrieves info about a connection to a certain lane of a certain edge.
Definition: NBEdge.cpp:727
SUMOReal getSpeed() const
Returns the speed allowed on this edge.
Definition: NBEdge.h:422
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:64
bool computeEdge2Edges(bool noLeftMovers)
computes the edge (step1: computation of approached edges)
Definition: NBEdge.cpp:1370
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:1791
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:656
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:1094
void setLaneSpreadFunction(LaneSpreadFunction spread)
(Re)sets how the lanes lateral offset shall be computed
Definition: NBEdge.cpp:484
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:1797
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:1977
MainDirections(const EdgeVector &outgoing, NBEdge *parent, NBNode *to)
constructor
Definition: NBEdge.cpp:112
void copyConnectionsFrom(NBEdge *src)
Definition: NBEdge.cpp:933
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:248
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'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 "prohibited" flow must let "prohibitor" flow pass.
Definition: NBNode.cpp:1084
LinkDirection getDirection(const NBEdge *const incoming, const NBEdge *const outgoing) const
Returns the representation of the described stream's direction.
Definition: NBNode.cpp:1182
bool splitGeometry(NBEdgeCont &ec, NBNodeCont &nc)
Splits this edge at geometry points.
Definition: NBEdge.cpp:496