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