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