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