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-2012 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 width, 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), myWidth(width),
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 width, 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), myWidth(width),
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  myWidth(tpl->getWidth()),
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 width, 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  myWidth = width;
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.getBegin() == myFrom->getPosition() &&
356  myGeom.getEnd() == myTo->getPosition();
357 }
358 
359 
360 void
361 NBEdge::setGeometry(const PositionVector& s, bool inner) {
362  Position begin = myGeom.getBegin(); // may differ from node position
363  Position end = myGeom.getEnd(); // 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, i);
379  if (shape.size() >= 2) {
380  shape = startShapeAt(shape.reverse(), myTo, i).reverse();
381  }
382  // sanity checks
383  if (shape.length() < POSITION_EPS) {
384  WRITE_MESSAGE("Lane '" + myID + "' has calculated shape length near zero. Revert it back to old shape.");
385  // @note old shape may still be shorter than POSITION_EPS
386  shape = old;
387  } else {
388  // @note If the node shapes are overlapping we may get a shape which goes in the wrong direction
389  Line lc(shape[0], shape[-1]);
390  Line lo(old[0], old[-1]);
392  shape = shape.reverse();
393  }
394  }
395  }
396  // recompute edge's length as the average of lane lenghts
397  SUMOReal avgLength = 0;
398  for (unsigned int i = 0; i < myLanes.size(); i++) {
399  assert(myLanes[i].shape.length() > 0);
400  avgLength += myLanes[i].shape.length();
401  }
402  myLength = avgLength / (SUMOReal) myLanes.size();
403 }
404 
405 
407 NBEdge::startShapeAt(const PositionVector& laneShape, const NBNode* startNode, unsigned int laneIndex) const {
408  const std::string error = "Could not find a way to attach lane '" + getLaneID(laneIndex) +
409  "' at node shape of '" + startNode->getID() + "'.";
410  const PositionVector& nodeShape = startNode->getShape();
411  Line lb = laneShape.getBegLine();
412  // this doesn't look reasonable @todo use lb.extrapolateFirstBy(100.0);
413  lb.extrapolateBy(100.0);
414  if (nodeShape.intersects(laneShape)) {
415  // shape intersects directly
416  std::vector<SUMOReal> pbv = laneShape.intersectsAtLengths2D(nodeShape);
417  assert(pbv.size() > 0);
419  assert(pb >= 0);
420  if (pb <= laneShape.length()) {
421  return laneShape.getSubpart2D(pb, laneShape.length());
422  } else {
423  return laneShape; // @todo do not ignore this error silently
424  }
425  } else if (nodeShape.intersects(lb.p1(), lb.p2())) {
426  // extension of first segment intersects
427  std::vector<SUMOReal> pbv = lb.intersectsAtLengths2D(nodeShape);
428  assert(pbv.size() > 0);
430  assert(pb >= 0);
431  PositionVector result = laneShape;
432  result.eraseAt(0);
434  return result;
435  //if (result.size() >= 2) {
436  // return result;
437  //} else {
438  // WRITE_WARNING(error + " (resulting shape is too short)");
439  // return laneShape;
440  //}
441  } else {
442  // could not find proper intersection. Probably the edge is very short
443  // and lies within nodeShape
444  // @todo enable warning WRITE_WARNING(error + " (laneShape lies within nodeShape)");
445  return laneShape;
446  }
447 }
448 
449 
450 const PositionVector&
451 NBEdge::getLaneShape(unsigned int i) const {
452  return myLanes[i].shape;
453 }
454 
455 
456 void
458  myLaneSpreadFunction = spread;
459 }
460 
461 
462 void
463 NBEdge::addGeometryPoint(int index, const Position& p) {
464  myGeom.insertAt(index, p);
465 }
466 
467 
468 bool
470  // check whether there any splits to perform
471  if (myGeom.size() < 3) {
472  return false;
473  }
474  // ok, split
475  NBNode* newFrom = myFrom;
476  NBNode* myLastNode = myTo;
477  NBNode* newTo = 0;
478  NBEdge* currentEdge = this;
479  for (int i = 1; i < (int) myGeom.size() - 1; i++) {
480  // build the node first
481  if (i != static_cast<int>(myGeom.size() - 2)) {
482  std::string nodename = myID + "_in_between#" + toString(i);
483  if (!nc.insert(nodename, myGeom[i])) {
484  throw ProcessError("Error on adding in-between node '" + nodename + "'.");
485  }
486  newTo = nc.retrieve(nodename);
487  } else {
488  newTo = myLastNode;
489  }
490  if (i == 1) {
491  currentEdge->myTo->removeEdge(this);
492  currentEdge->myTo = newTo;
493  newTo->addIncomingEdge(currentEdge);
494  } else {
495  std::string edgename = myID + "[" + toString(i - 1) + "]";
496  // @bug lane-specific width, speed, overall offset and restrictions are ignored
497  currentEdge = new NBEdge(edgename, newFrom, newTo, myType, mySpeed, (unsigned int) myLanes.size(),
499  if (!ec.insert(currentEdge, true)) {
500  throw ProcessError("Error on adding splitted edge '" + edgename + "'.");
501  }
502  }
503  newFrom = newTo;
504  }
505  myGeom.clear();
508  myStep = INIT;
509  return true;
510 }
511 
512 
513 // ----------- Setting and getting connections
514 bool
517  return true;
518  }
519  // check whether the node was merged and now a connection between
520  // not matching edges is tried to be added
521  // This happens f.e. within the ptv VISSIM-example "Beijing"
522  if (dest != 0 && myTo != dest->myFrom) {
523  return false;
524  }
525  if (dest == 0) {
527  myConnections.push_back(Connection(-1, dest, -1));
528  } else if (find_if(myConnections.begin(), myConnections.end(), connections_toedge_finder(dest)) == myConnections.end()) {
529  myConnections.push_back(Connection(-1, dest, -1));
530  }
531  if (myStep < EDGE2EDGES) {
532  myStep = EDGE2EDGES;
533  }
534  return true;
535 }
536 
537 
538 bool
539 NBEdge::addLane2LaneConnection(unsigned int from, NBEdge* dest,
540  unsigned int toLane, Lane2LaneInfoType type,
541  bool mayUseSameDestination,
542  bool mayDefinitelyPass) {
544  return true;
545  }
546  // check whether the node was merged and now a connection between
547  // not matching edges is tried to be added
548  // This happens f.e. within the ptv VISSIM-example "Beijing"
549  if (myTo != dest->myFrom) {
550  return false;
551  }
552  if (!addEdge2EdgeConnection(dest)) {
553  return false;
554  }
555  setConnection(from, dest, toLane, type, mayUseSameDestination, mayDefinitelyPass);
556  return true;
557 }
558 
559 
560 bool
561 NBEdge::addLane2LaneConnections(unsigned int fromLane,
562  NBEdge* dest, unsigned int toLane,
563  unsigned int no, Lane2LaneInfoType type,
564  bool invalidatePrevious,
565  bool mayDefinitelyPass) {
566  if (invalidatePrevious) {
567  invalidateConnections(true);
568  }
569  bool ok = true;
570  for (unsigned int i = 0; i < no && ok; i++) {
571  ok &= addLane2LaneConnection(fromLane + i, dest, toLane + i, type, false, mayDefinitelyPass);
572  }
573  return ok;
574 }
575 
576 
577 void
578 NBEdge::setConnection(unsigned int lane, NBEdge* destEdge,
579  unsigned int destLane, Lane2LaneInfoType type,
580  bool mayUseSameDestination,
581  bool mayDefinitelyPass) {
583  return;
584  }
585  // some kind of a misbehaviour which may occure when the junction's outgoing
586  // edge priorities were not properly computed, what may happen due to
587  // an incomplete or not proper input
588  // what happens is that under some circumstances a single lane may set to
589  // be approached more than once by the one of our lanes.
590  // This must not be!
591  // we test whether it is the case and do nothing if so - the connection
592  // will be refused
593  //
594  if (!mayUseSameDestination && hasConnectionTo(destEdge, destLane)) {
595  return;
596  }
597  if (find_if(myConnections.begin(), myConnections.end(), connections_finder(lane, destEdge, destLane)) != myConnections.end()) {
598  return;
599  }
600  if (myLanes.size() <= lane) {
601  WRITE_ERROR("Could not set connection from '" + getLaneID(lane) + "' to '" + destEdge->getLaneID(destLane) + "'.");
602  return;
603  }
604  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end();) {
605  if ((*i).toEdge == destEdge && ((*i).fromLane == -1 || (*i).toLane == -1)) {
606  i = myConnections.erase(i);
607  } else {
608  ++i;
609  }
610  }
611  myConnections.push_back(Connection(lane, destEdge, destLane));
612  if (mayDefinitelyPass) {
613  myConnections.back().mayDefinitelyPass = true;
614  }
615  if (type == L2L_USER) {
617  } else {
618  // check whether we have to take another look at it later
619  if (type == L2L_COMPUTED) {
620  // yes, the connection was set using an algorithm which requires a recheck
622  } else {
623  // ok, let's only not recheck it if we did no add something that has to be recheked
624  if (myStep != LANES2LANES_RECHECK) {
626  }
627  }
628  }
629 }
630 
631 
632 std::vector<NBEdge::Connection>
633 NBEdge::getConnectionsFromLane(unsigned int lane) const {
634  std::vector<NBEdge::Connection> ret;
635  for (std::vector<Connection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
636  if ((*i).fromLane == static_cast<int>(lane)) {
637  ret.push_back(*i);
638  }
639  }
640  return ret;
641 }
642 
643 
644 bool
645 NBEdge::hasConnectionTo(NBEdge* destEdge, unsigned int destLane) const {
646  return destEdge != 0 && find_if(myConnections.begin(), myConnections.end(), connections_toedgelane_finder(destEdge, destLane)) != myConnections.end();
647 }
648 
649 
650 bool
652  if (e == myTurnDestination) {
653  return true;
654  }
655  return
656  find_if(myConnections.begin(), myConnections.end(), connections_toedge_finder(e))
657  !=
658  myConnections.end();
659 
660 }
661 
662 
663 const EdgeVector*
665  // check whether connections exist and if not, use edges from the node
666  EdgeVector outgoing;
667  if (myConnections.size() == 0) {
668  outgoing = myTo->getOutgoingEdges();
669  } else {
670  for (std::vector<Connection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
671  if (find(outgoing.begin(), outgoing.end(), (*i).toEdge) == outgoing.end()) {
672  outgoing.push_back((*i).toEdge);
673  }
674  }
675  }
676  // allocate the sorted container
677  unsigned int size = (unsigned int) outgoing.size();
678  EdgeVector* edges = new EdgeVector();
679  edges->reserve(size);
680  for (EdgeVector::const_iterator i = outgoing.begin(); i != outgoing.end(); i++) {
681  NBEdge* outedge = *i;
682  if (outedge != 0 && outedge != myTurnDestination) {
683  edges->push_back(outedge);
684  }
685  }
686  sort(edges->begin(), edges->end(), NBContHelper::relative_edge_sorter(this, myTo));
687  return edges;
688 }
689 
690 
693  EdgeVector ret;
694  for (std::vector<Connection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
695  if (find(ret.begin(), ret.end(), (*i).toEdge) == ret.end()) {
696  ret.push_back((*i).toEdge);
697  }
698  }
699  return ret;
700 }
701 
702 
703 std::vector<int>
704 NBEdge::getConnectionLanes(NBEdge* currentOutgoing) const {
705  std::vector<int> ret;
706  if (currentOutgoing != myTurnDestination) {
707  for (std::vector<Connection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
708  if ((*i).toEdge == currentOutgoing) {
709  ret.push_back((*i).fromLane);
710  }
711  }
712  }
713  return ret;
714 }
715 
716 
717 void
720 }
721 
722 
723 void
725  sort(myConnections.begin(), myConnections.end(), connections_sorter);
726 }
727 
728 
729 void
731  EdgeVector connected = getConnectedEdges();
732  for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
733  NBEdge* inc = *i;
734  // We have to do this
735  inc->myStep = EDGE2EDGES;
736  // add all connections
737  for (EdgeVector::iterator j = connected.begin(); j != connected.end(); j++) {
738  inc->addEdge2EdgeConnection(*j);
739  }
740  inc->removeFromConnections(this);
741  }
742 }
743 
744 
745 void
746 NBEdge::removeFromConnections(NBEdge* toEdge, int fromLane, int toLane) {
747  // remove from "myConnections"
748  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end();) {
749  Connection& c = *i;
750  if (c.toEdge == toEdge
751  && (fromLane < 0 || c.fromLane == fromLane)
752  && (toLane < 0 || c.toLane == toLane)) {
753  i = myConnections.erase(i);
754  } else {
755  ++i;
756  }
757  }
758  // check whether it was the turn destination
759  if (myTurnDestination == toEdge && fromLane < 0) {
760  myTurnDestination = 0;
761  }
762 }
763 
764 
765 void
766 NBEdge::invalidateConnections(bool reallowSetting) {
767  myTurnDestination = 0;
768  myConnections.clear();
769  if (reallowSetting) {
770  myStep = INIT;
771  } else {
773  }
774 }
775 
776 
777 void
778 NBEdge::replaceInConnections(NBEdge* which, NBEdge* by, unsigned int laneOff) {
779  UNUSED_PARAMETER(laneOff);
780  // replace in "_connectedEdges"
781  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
782  if ((*i).toEdge == which) {
783  (*i).toEdge = by;
784  }
785  }
786  // check whether it was the turn destination
787  if (myTurnDestination == which) {
788  myTurnDestination = by;
789  }
790 }
791 
792 void
793 NBEdge::replaceInConnections(NBEdge* which, const std::vector<NBEdge::Connection>& origConns) {
794  std::map<int, int> laneMap;
795  int minLane = -1;
796  int maxLane = -1;
797  // get lanes used to approach the edge to remap
798  bool wasConnected = false;
799  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
800  if ((*i).toEdge != which) {
801  continue;
802  }
803  wasConnected = true;
804  if ((*i).fromLane != -1) {
805  int fromLane = (*i).fromLane;
806  laneMap[(*i).toLane] = fromLane;
807  if (minLane == -1 || minLane > fromLane) {
808  minLane = fromLane;
809  }
810  if (maxLane == -1 || maxLane < fromLane) {
811  maxLane = fromLane;
812  }
813  }
814  }
815  if (!wasConnected) {
816  return;
817  }
818  // remove the remapped edge from connections
819  removeFromConnections(which);
820  // add new connections
821  std::vector<NBEdge::Connection> conns = origConns;
822  for (std::vector<NBEdge::Connection>::iterator i = conns.begin(); i != conns.end(); ++i) {
823  if ((*i).toEdge == which) {
824  continue;
825  }
826  int fromLane = (*i).fromLane;
827  int toUse = -1;
828  if (laneMap.find(fromLane) == laneMap.end()) {
829  if (fromLane >= 0 && fromLane <= minLane) {
830  toUse = minLane;
831  }
832  if (fromLane >= 0 && fromLane >= maxLane) {
833  toUse = maxLane;
834  }
835  } else {
836  toUse = laneMap[fromLane];
837  }
838  if (toUse == -1) {
839  toUse = 0;
840  }
841  setConnection(toUse, (*i).toEdge, (*i).toLane, L2L_COMPUTED, false, (*i).mayDefinitelyPass);
842  }
843 }
844 
845 
846 void
848  myStep = src->myStep;
850 }
851 
852 
853 void
854 NBEdge::moveConnectionToLeft(unsigned int lane) {
855  unsigned int index = 0;
856  if (myAmLeftHand) {
857  for (int i = (int) myConnections.size() - 1; i >= 0; --i) {
858  if (myConnections[i].fromLane == static_cast<int>(lane) && getTurnDestination() != myConnections[i].toEdge) {
859  index = i;
860  }
861  }
862  } else {
863  for (unsigned int i = 0; i < myConnections.size(); ++i) {
864  if (myConnections[i].fromLane == static_cast<int>(lane)) {
865  index = i;
866  }
867  }
868  }
869  std::vector<Connection>::iterator i = myConnections.begin() + index;
870  Connection c = *i;
871  myConnections.erase(i);
872  setConnection(lane + 1, c.toEdge, c.toLane, L2L_VALIDATED, false);
873 }
874 
875 
876 void
877 NBEdge::moveConnectionToRight(unsigned int lane) {
878  if (myAmLeftHand) {
879  for (int i = (int) myConnections.size() - 1; i >= 0; --i) {
880  if (myConnections[i].fromLane == static_cast<int>(lane) && getTurnDestination() != myConnections[i].toEdge) {
881  Connection c = myConnections[i];
882  myConnections.erase(myConnections.begin() + i);
883  setConnection(lane - 1, c.toEdge, c.toLane, L2L_VALIDATED, false);
884  return;
885  }
886  }
887  } else {
888  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
889  if ((*i).fromLane == static_cast<int>(lane)) {
890  Connection c = *i;
891  i = myConnections.erase(i);
892  setConnection(lane - 1, c.toEdge, c.toLane, L2L_VALIDATED, false);
893  return;
894  }
895  }
896  }
897 }
898 
899 
900 
901 
902 
903 
904 
905 
906 
907 
908 void
909 NBEdge::buildInnerEdges(const NBNode& n, unsigned int noInternalNoSplits, unsigned int& lno, unsigned int& splitNo) {
910  std::string innerID = ":" + n.getID();
911  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
912  Connection& con = *i;
913  con.haveVia = false; // reset first since this may be called multiple times
914  if (con.toEdge == 0) {
915  continue;
916  }
917 
918  PositionVector shape = n.computeInternalLaneShape(this, con.fromLane, con.toEdge, con.toLane);
919 
920  LinkDirection dir = n.getDirection(this, con.toEdge);
921  std::pair<SUMOReal, std::vector<unsigned int> > crossingPositions(-1, std::vector<unsigned int>());
922  std::string foeInternalLanes;
923  std::set<std::string> tmpFoeIncomingLanes;
924  switch (dir) {
925  case LINKDIR_LEFT:
926  case LINKDIR_PARTLEFT:
927  case LINKDIR_TURN: {
928  unsigned int index = 0;
929  const std::vector<NBEdge*>& incoming = n.getIncomingEdges();
930  for (EdgeVector::const_iterator i2 = incoming.begin(); i2 != incoming.end(); ++i2) {
931  const std::vector<Connection>& elv = (*i2)->getConnections();
932  for (std::vector<NBEdge::Connection>::const_iterator k2 = elv.begin(); k2 != elv.end(); k2++) {
933  if ((*k2).toEdge == 0) {
934  continue;
935  }
936  bool needsCont = n.needsCont(this, con.toEdge, *i2, (*k2).toEdge, *k2);
937  // compute the crossing point
938  if (needsCont) {
939  crossingPositions.second.push_back(index);
940  const PositionVector otherShape = n.computeInternalLaneShape(*i2, (*k2).fromLane, (*k2).toEdge, (*k2).toLane);
941  const std::vector<SUMOReal> dv = shape.intersectsAtLengths2D(otherShape);
942  if (dv.size() > 0) {
943  const SUMOReal minDV = dv[0];
944  if (minDV < shape.length() - .1 && minDV > .1) { // !!!?
945  assert(minDV >= 0);
946  if (crossingPositions.first < 0 || crossingPositions.first > minDV) {
947  crossingPositions.first = minDV;
948  }
949  }
950  }
951  }
952  // compute foe internal lanes
953  if (n.foes(this, con.toEdge, *i2, (*k2).toEdge)) {
954  if (foeInternalLanes.length() != 0) {
955  foeInternalLanes += " ";
956  }
957  foeInternalLanes += (":" + n.getID() + "_" + toString(index) + "_0");
958  }
959  // compute foe incoming lanes
960  NBEdge* e = getToNode()->getOppositeIncoming(this);
961  if ((e == *i2 && needsCont && !n.forbids(this, con.toEdge, *i2, (*k2).toEdge, true))
962  || (dir == LINKDIR_TURN && this != *i2 && con.toEdge == (*k2).toEdge)) {
963  tmpFoeIncomingLanes.insert((*i2)->getID() + "_" + toString((*k2).fromLane));
964  }
965  index++;
966  }
967  }
968  if (dir == LINKDIR_TURN && crossingPositions.first < 0 && crossingPositions.second.size() != 0) {
969  // let turnarounds wait in the middle if no other crossing point was found
970  crossingPositions.first = (SUMOReal) shape.length() / 2.;
971  }
972  }
973  break;
974  default:
975  break;
976  }
977 
978 
979  // compute the maximum speed allowed
980  // see !!! for an explanation (with a_lat_mean ~0.3)
981  SUMOReal vmax = (SUMOReal) 0.3 * (SUMOReal) 9.80778 *
983  con.toEdge->getLaneShape(con.toLane).getBegin())
984  / (SUMOReal) 2.0 / (SUMOReal) PI;
985  vmax = MIN2(vmax, ((getSpeed() + con.toEdge->getSpeed()) / (SUMOReal) 2.0));
986  vmax = (getSpeed() + con.toEdge->getSpeed()) / (SUMOReal) 2.0;
987  //
988  Position end = con.toEdge->getLaneShape(con.toLane).getBegin();
989  Position beg = getLaneShape(con.fromLane).getEnd();
990 
991  assert(shape.size() >= 2);
992  // get internal splits if any
993  if (crossingPositions.first >= 0) {
994  std::pair<PositionVector, PositionVector> split = shape.splitAt(crossingPositions.first);
995  con.id = innerID + "_" + toString(lno);
996  con.vmax = vmax;
997  con.shape = split.first;
998  con.foeInternalLanes = foeInternalLanes;
999  con.foeIncomingLanes = ""; // reset first because this may be called multiple times
1000 
1001  for (std::set<std::string>::iterator q = tmpFoeIncomingLanes.begin(); q != tmpFoeIncomingLanes.end(); ++q) {
1002  if (con.foeIncomingLanes.length() != 0) {
1003  con.foeIncomingLanes += " ";
1004  }
1005  con.foeIncomingLanes += *q;
1006  }
1007  con.viaID = innerID + "_" + toString(splitNo + noInternalNoSplits);
1008  con.viaVmax = vmax;
1009  con.viaShape = split.second;
1010  con.haveVia = true;
1011  splitNo++;
1012  } else {
1013  con.id = innerID + "_" + toString(lno);
1014  con.vmax = vmax;
1015  con.shape = shape;
1016  }
1017 
1018 
1019  lno++;
1020  }
1021 }
1022 
1023 // -----------
1024 int
1025 NBEdge::getJunctionPriority(const NBNode* const node) const {
1026  if (node == myFrom) {
1027  return myFromJunctionPriority;
1028  } else {
1029  return myToJunctionPriority;
1030  }
1031 }
1032 
1033 
1034 void
1035 NBEdge::setJunctionPriority(const NBNode* const node, int prio) {
1036  if (node == myFrom) {
1037  myFromJunctionPriority = prio;
1038  } else {
1039  myToJunctionPriority = prio;
1040  }
1041 }
1042 
1043 
1044 SUMOReal
1045 NBEdge::getAngleAtNode(const NBNode* const atNode) const {
1046  if (atNode == myFrom) {
1047  return myGeom.getBegLine().atan2DegreeAngle();
1048  } else {
1049  assert(atNode == myTo);
1050  return myGeom.getEndLine().atan2DegreeAngle();
1051  }
1052 }
1053 
1054 
1055 void
1057  myTurnDestination = e;
1058 }
1059 
1060 
1061 SUMOReal
1062 NBEdge::getLaneSpeed(unsigned int lane) const {
1063  return myLanes[lane].speed;
1064 }
1065 
1066 
1067 void
1069  // vissim needs this
1070  if (myFrom == myTo) {
1071  return;
1072  }
1073  // build the shape of each lane
1074  for (unsigned int i = 0; i < myLanes.size(); i++) {
1075  try {
1076  myLanes[i].shape = computeLaneShape(i);
1077  } catch (InvalidArgument& e) {
1078  WRITE_WARNING("In edge '" + getID() + "': lane shape could not be determined (" + e.what() + ")");
1079  myLanes[i].shape = myGeom;
1080  }
1081  }
1082 }
1083 
1084 
1086 NBEdge::computeLaneShape(unsigned int lane) throw(InvalidArgument) {
1087  PositionVector shape;
1088  bool haveWarned = false;
1089  for (int i = 0; i < (int) myGeom.size(); i++) {
1090  if (i == 0) {
1091  Position from = myGeom[i];
1092  Position to = myGeom[i + 1];
1093  std::pair<SUMOReal, SUMOReal> offsets = laneOffset(from, to, SUMO_const_laneWidthAndOffset, (unsigned int)(myLanes.size() - 1 - lane));
1094  shape.push_back(
1095  // (methode umbenennen; was heisst hier "-")
1096  Position(from.x() - offsets.first, from.y() - offsets.second, from.z()));
1097  } else if (i == static_cast<int>(myGeom.size() - 1)) {
1098  Position from = myGeom[i - 1];
1099  Position to = myGeom[i];
1100  std::pair<SUMOReal, SUMOReal> offsets = laneOffset(from, to, SUMO_const_laneWidthAndOffset, (unsigned int)(myLanes.size() - 1 - lane));
1101  shape.push_back(
1102  // (methode umbenennen; was heisst hier "-")
1103  Position(to.x() - offsets.first, to.y() - offsets.second, to.z()));
1104  } else {
1105  Position from = myGeom[i - 1];
1106  Position me = myGeom[i];
1107  Position to = myGeom[i + 1];
1108  std::pair<SUMOReal, SUMOReal> offsets = laneOffset(from, me, SUMO_const_laneWidthAndOffset, (unsigned int)(myLanes.size() - 1 - lane));
1109  std::pair<SUMOReal, SUMOReal> offsets2 = laneOffset(me, to, SUMO_const_laneWidthAndOffset, (unsigned int)(myLanes.size() - 1 - lane));
1110  Line l1(
1111  Position(from.x() - offsets.first, from.y() - offsets.second),
1112  Position(me.x() - offsets.first, me.y() - offsets.second));
1113  l1.extrapolateBy(100);
1114  Line l2(
1115  Position(me.x() - offsets2.first, me.y() - offsets2.second),
1116  Position(to.x() - offsets2.first, to.y() - offsets2.second));
1118  if (angle < 10. || angle > 350.) {
1119  shape.push_back(
1120  // (methode umbenennen; was heisst hier "-")
1121  Position(me.x() - offsets.first, me.y() - offsets.second, me.z()));
1122  continue;
1123  }
1124  l2.extrapolateBy(100);
1125  if (l1.intersects(l2)) {
1126  Position intersetion = l1.intersectsAt(l2);
1127  shape.push_back(Position(intersetion.x(), intersetion.y(), me.z()));
1128  } else {
1129  if (!haveWarned) {
1130  WRITE_WARNING("In lane '" + getLaneID(lane) + "': Could not build shape.");
1131  haveWarned = true;
1132  }
1133  }
1134  }
1135  }
1136  return shape;
1137 }
1138 
1139 
1140 std::pair<SUMOReal, SUMOReal>
1141 NBEdge::laneOffset(const Position& from, const Position& to,
1142  SUMOReal lanewidth, unsigned int lane) throw(InvalidArgument) {
1143  return laneOffset(from, to, lanewidth, lane,
1144  myLanes.size(), myLaneSpreadFunction, myAmLeftHand);
1145 }
1146 
1147 
1148 std::pair<SUMOReal, SUMOReal>
1149 NBEdge::laneOffset(const Position& from, const Position& to,
1150  SUMOReal lanewidth, unsigned int lane,
1151  size_t noLanes, LaneSpreadFunction lsf, bool leftHand) {
1152  std::pair<SUMOReal, SUMOReal> offsets =
1153  GeomHelper::getNormal90D_CW(from, to, lanewidth);
1154  SUMOReal xoff = offsets.first / (SUMOReal) 2.0;
1155  SUMOReal yoff = offsets.second / (SUMOReal) 2.0;
1156  if (lsf == LANESPREAD_RIGHT) {
1157  xoff += (offsets.first * (SUMOReal) lane);
1158  yoff += (offsets.second * (SUMOReal) lane);
1159  } else {
1160  xoff += (offsets.first * (SUMOReal) lane) - (offsets.first * (SUMOReal) noLanes / (SUMOReal) 2.0);
1161  yoff += (offsets.second * (SUMOReal) lane) - (offsets.second * (SUMOReal) noLanes / (SUMOReal) 2.0);
1162  }
1163  if (leftHand) {
1164  return std::pair<SUMOReal, SUMOReal>(-xoff, -yoff);
1165  } else {
1166  return std::pair<SUMOReal, SUMOReal>(xoff, yoff);
1167  }
1168 }
1169 
1170 
1171 bool
1173  for (std::vector<Lane>::const_iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
1174  if ((*i).permissions != SVCFreeForAll) {
1175  return true;
1176  }
1177  }
1178  return false;
1179 }
1180 
1181 
1182 bool
1184  std::vector<Lane>::const_iterator i = myLanes.begin();
1185  SVCPermissions firstLanePermissions = i->permissions;
1186  i++;
1187  for (; i != myLanes.end(); ++i) {
1188  if (i->permissions != firstLanePermissions) {
1189  return true;
1190  }
1191  }
1192  return false;
1193 }
1194 
1195 
1196 bool
1198  for (std::vector<Lane>::const_iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
1199  if (i->width != getWidth()) {
1200  return true;
1201  }
1202  }
1203  return false;
1204 }
1205 
1206 
1207 bool
1209  for (std::vector<Lane>::const_iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
1210  if (i->speed != getSpeed()) {
1211  return true;
1212  }
1213  }
1214  return false;
1215 }
1216 
1217 
1218 bool
1220  for (std::vector<Lane>::const_iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
1221  if (i->offset != getOffset()) {
1222  return true;
1223  }
1224  }
1225  return false;
1226 }
1227 
1228 
1229 bool
1232 }
1233 
1234 
1235 
1236 bool
1237 NBEdge::computeEdge2Edges(bool noLeftMovers) {
1238  // return if this relationship has been build in previous steps or
1239  // during the import
1240  if (myStep >= EDGE2EDGES) {
1241  return true;
1242  }
1243  if (myConnections.size() == 0) {
1244  const EdgeVector& o = myTo->getOutgoingEdges();
1245  for (EdgeVector::const_iterator i = o.begin(); i != o.end(); ++i) {
1246  if (noLeftMovers && myTo->isLeftMover(this, *i)) {
1247  continue;
1248  }
1249  myConnections.push_back(Connection(-1, *i, -1));
1250  }
1251  }
1252  myStep = EDGE2EDGES;
1253  return true;
1254 }
1255 
1256 
1257 bool
1259  // return if this relationship has been build in previous steps or
1260  // during the import
1261  if (myStep >= LANES2EDGES) {
1262  return true;
1263  }
1264  assert(myStep == EDGE2EDGES);
1265  // get list of possible outgoing edges sorted by direction clockwise
1266  // the edge in the backward direction (turnaround) is not in the list
1267  const EdgeVector* edges = getConnectedSorted();
1268  if (myConnections.size() != 0 && edges->size() == 0) {
1269  // dead end per definition!?
1270  myConnections.clear();
1271  } else {
1272  // divide the lanes on reachable edges
1273  divideOnEdges(edges);
1274  }
1275  delete edges;
1276  myStep = LANES2EDGES;
1277  return true;
1278 }
1279 
1280 
1281 bool
1283  std::vector<unsigned int> connNumbersPerLane(myLanes.size(), 0);
1284  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end();) {
1285  if ((*i).toEdge == 0 || (*i).fromLane < 0 || (*i).toLane < 0) {
1286  i = myConnections.erase(i);
1287  } else {
1288  if ((*i).fromLane >= 0) {
1289  ++connNumbersPerLane[(*i).fromLane];
1290  }
1291  ++i;
1292  }
1293  }
1295  // check #1:
1296  // If there is a lane with no connections and any neighbour lane has
1297  // more than one connections, try to move one of them.
1298  // This check is only done for edges which connections were assigned
1299  // using the standard algorithm.
1300  for (unsigned int i = 0; i < myLanes.size(); i++) {
1301  if (connNumbersPerLane[i] == 0) {
1302  if (i > 0 && connNumbersPerLane[i - 1] > 1) {
1303  moveConnectionToLeft(i - 1);
1304  } else if (i < myLanes.size() - 1 && connNumbersPerLane[i + 1] > 1) {
1305  moveConnectionToRight(i + 1);
1306  }
1307  }
1308  }
1309  }
1310  return true;
1311 }
1312 
1313 
1314 void
1316  if (outgoing->size() == 0) {
1317  // we have to do this, because the turnaround may have been added before
1318  myConnections.clear();
1319  return;
1320  }
1321  // precompute priorities; needed as some kind of assumptions for
1322  // priorities of directions (see preparePriorities)
1323  std::vector<unsigned int>* priorities = preparePriorities(outgoing);
1324 
1325  // compute the sum of priorities (needed for normalisation)
1326  unsigned int prioSum = computePrioritySum(priorities);
1327  // compute the resulting number of lanes that should be used to
1328  // reach the following edge
1329  unsigned int size = (unsigned int) outgoing->size();
1330  std::vector<SUMOReal> resultingLanes;
1331  resultingLanes.reserve(size);
1332  SUMOReal sumResulting = 0; // the sum of resulting lanes
1333  SUMOReal minResulting = 10000; // the least number of lanes to reach an edge
1334  unsigned int i;
1335  for (i = 0; i < size; i++) {
1336  // res will be the number of lanes which are meant to reach the
1337  // current outgoing edge
1338  SUMOReal res =
1339  (SUMOReal)(*priorities)[i] *
1340  (SUMOReal) myLanes.size() / (SUMOReal) prioSum;
1341  // do not let this number be greater than the number of available lanes
1342  if (res > myLanes.size()) {
1343  res = (SUMOReal) myLanes.size();
1344  }
1345  // add it to the list
1346  resultingLanes.push_back(res);
1347  sumResulting += res;
1348  if (minResulting > res) {
1349  minResulting = res;
1350  }
1351  }
1352  // compute the number of virtual edges
1353  // a virtual edge is used as a replacement for a real edge from now on
1354  // it shall ollow to divide the existing lanes on this structure without
1355  // regarding the structure of outgoing edges
1356  sumResulting += minResulting / (SUMOReal) 2.;
1357  unsigned int noVirtual = (unsigned int)(sumResulting / minResulting);
1358  // compute the transition from virtual to real edges
1359  EdgeVector transition;
1360  transition.reserve(size);
1361  for (i = 0; i < size; i++) {
1362  // tmpNo will be the number of connections from this edge
1363  // to the next edge
1364  assert(i < resultingLanes.size());
1365  SUMOReal tmpNo = (SUMOReal) resultingLanes[i] / (SUMOReal) minResulting;
1366  for (SUMOReal j = 0; j < tmpNo; j++) {
1367  assert(outgoing->size() > i);
1368  transition.push_back((*outgoing)[i]);
1369  }
1370  }
1371 
1372  // assign lanes to edges
1373  // (conversion from virtual to real edges is done)
1374  ToEdgeConnectionsAdder adder(transition);
1375  Bresenham::compute(&adder, static_cast<unsigned int>(myLanes.size()), noVirtual);
1376  const std::map<NBEdge*, std::vector<unsigned int> >& l2eConns = adder.getBuiltConnections();
1377  myConnections.clear();
1378  for (std::map<NBEdge*, std::vector<unsigned int> >::const_iterator i = l2eConns.begin(); i != l2eConns.end(); ++i) {
1379  const std::vector<unsigned int> lanes = (*i).second;
1380  for (std::vector<unsigned int>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
1381  if (myAmLeftHand) {
1382  myConnections.push_back(Connection(int(myLanes.size() - 1 - *j), (*i).first, -1));
1383  } else {
1384  myConnections.push_back(Connection(int(*j), (*i).first, -1));
1385  }
1386  }
1387  }
1388  delete priorities;
1389 }
1390 
1391 
1392 std::vector<unsigned int>*
1394  // copy the priorities first
1395  std::vector<unsigned int>* priorities = new std::vector<unsigned int>();
1396  if (outgoing->size() == 0) {
1397  return priorities;
1398  }
1399  priorities->reserve(outgoing->size());
1400  EdgeVector::const_iterator i;
1401  for (i = outgoing->begin(); i != outgoing->end(); i++) {
1402  int prio = (*i)->getJunctionPriority(myTo);
1403  assert((prio + 1) * 2 > 0);
1404  prio = (prio + 1) * 2;
1405  priorities->push_back(prio);
1406  }
1407  // when the right turning direction has not a higher priority, divide
1408  // the importance by 2 due to the possibility to leave the junction
1409  // faster from this lane
1410  MainDirections mainDirections(*outgoing, this, myTo);
1411  EdgeVector tmp(*outgoing);
1412  sort(tmp.begin(), tmp.end(), NBContHelper::edge_similar_direction_sorter(this));
1413  i = find(outgoing->begin(), outgoing->end(), *(tmp.begin()));
1414  unsigned int dist = (unsigned int) distance(outgoing->begin(), i);
1415  if (dist != 0 && !mainDirections.includes(MainDirections::DIR_RIGHTMOST)) {
1416  assert(priorities->size() > 0);
1417  (*priorities)[0] = (*priorities)[0] / 2;
1418  }
1419  // HEURISTIC:
1420  // when no higher priority exists, let the forward direction be
1421  // the main direction
1422  if (mainDirections.empty()) {
1423  assert(dist < priorities->size());
1424  (*priorities)[dist] = (*priorities)[dist] * 2;
1425  }
1426  if (mainDirections.includes(MainDirections::DIR_FORWARD) && myLanes.size() > 2) {
1427  (*priorities)[dist] = (*priorities)[dist] * 2;
1428  }
1429  // return
1430  return priorities;
1431 }
1432 
1433 
1434 unsigned int
1435 NBEdge::computePrioritySum(std::vector<unsigned int>* priorities) {
1436  unsigned int sum = 0;
1437  for (std::vector<unsigned int>::iterator i = priorities->begin(); i != priorities->end(); i++) {
1438  sum += int(*i);
1439  }
1440  return sum;
1441 }
1442 
1443 
1444 void
1445 NBEdge::appendTurnaround(bool noTLSControlled) {
1446  // do nothing if no turnaround is known
1447  if (myTurnDestination == 0) {
1448  return;
1449  }
1450  // do nothing if the destination node is controlled by a tls and no turnarounds
1451  // shall be appended for such junctions
1452  if (noTLSControlled && myTo->isTLControlled()) {
1453  return;
1454  }
1455  setConnection((unsigned int)(myLanes.size() - 1), myTurnDestination, myTurnDestination->getNumLanes() - 1, L2L_VALIDATED);
1456 }
1457 
1458 
1459 bool
1460 NBEdge::isTurningDirectionAt(const NBNode* n, const NBEdge* const edge) const {
1461  // maybe it was already set as the turning direction
1462  if (edge == myTurnDestination) {
1463  return true;
1464  } else if (myTurnDestination != 0) {
1465  // otherwise - it's not if a turning direction exists
1466  return false;
1467  }
1468  // if the same nodes are connected
1469  if (myFrom == edge->myTo && myTo == edge->myFrom) {
1470  return true;
1471  }
1472  // we have to check whether the connection between the nodes is
1473  // geometrically similar
1474  SUMOReal thisFromAngle2 = getAngleAtNode(n);
1475  SUMOReal otherToAngle2 = edge->getAngleAtNode(n);
1476  if (thisFromAngle2 < otherToAngle2) {
1477  std::swap(thisFromAngle2, otherToAngle2);
1478  }
1479  if (thisFromAngle2 - otherToAngle2 > 170 && thisFromAngle2 - otherToAngle2 < 190) {
1480  return true;
1481  }
1482  return false;
1483 }
1484 
1485 
1486 
1487 NBNode*
1489  // return the from-node when the position is at the begin of the edge
1490  if (pos < tolerance) {
1491  return myFrom;
1492  }
1493  // return the to-node when the position is at the end of the edge
1494  if (pos > myLength - tolerance) {
1495  return myTo;
1496  }
1497  return 0;
1498 }
1499 
1500 
1501 void
1502 NBEdge::moveOutgoingConnectionsFrom(NBEdge* e, unsigned int laneOff) {
1503  unsigned int lanes = e->getNumLanes();
1504  for (unsigned int i = 0; i < lanes; i++) {
1505  std::vector<NBEdge::Connection> elv = e->getConnectionsFromLane(i);
1506  for (std::vector<NBEdge::Connection>::iterator j = elv.begin(); j != elv.end(); j++) {
1507  NBEdge::Connection el = *j;
1508  assert(el.tlID == "");
1509  bool ok = addLane2LaneConnection(i + laneOff, el.toEdge, el.toLane, L2L_COMPUTED);
1510  assert(ok);
1511  }
1512  }
1513 }
1514 
1515 
1516 bool
1519 }
1520 
1521 
1522 SUMOReal
1525 }
1526 
1527 
1528 Position
1530  const PositionVector& shape0 = myLanes[0].shape;
1531  const PositionVector& shapel = myLanes.back().shape;
1532  width = width < shape0.length() / (SUMOReal) 2.0
1533  ? width
1534  : shape0.length() / (SUMOReal) 2.0;
1535  if (node == myFrom) {
1536  Position pos = shapel.positionAtLengthPosition(width);
1537  GeomHelper::transfer_to_side(pos, shapel[0], shapel[-1], SUMO_const_halfLaneAndOffset);
1538  return pos;
1539  } else {
1540  Position pos = shape0.positionAtLengthPosition(shape0.length() - width);
1541  GeomHelper::transfer_to_side(pos, shape0[-1], shape0[0], SUMO_const_halfLaneAndOffset);
1542  return pos;
1543  }
1544 }
1545 
1546 
1547 Position
1549  const PositionVector& shape0 = myLanes[0].shape;
1550  const PositionVector& shapel = myLanes.back().shape;
1551  width = width < shape0.length() / (SUMOReal) 2.0
1552  ? width
1553  : shape0.length() / (SUMOReal) 2.0;
1554  if (node == myFrom) {
1555  Position pos = shape0.positionAtLengthPosition(width);
1556  GeomHelper::transfer_to_side(pos, shape0[0], shape0[-1], -SUMO_const_halfLaneAndOffset);
1557  return pos;
1558  } else {
1559  Position pos = shapel.positionAtLengthPosition(shapel.length() - width);
1560  GeomHelper::transfer_to_side(pos, shapel[-1], shapel[0], -SUMO_const_halfLaneAndOffset);
1561  return pos;
1562  }
1563 }
1564 
1565 
1566 bool
1567 NBEdge::mayBeTLSControlled(int fromLane, NBEdge* toEdge, int toLane) const {
1569  tpl.fromLane = fromLane;
1570  tpl.to = toEdge;
1571  tpl.toLane = toLane;
1572  std::vector<TLSDisabledConnection>::const_iterator i = find_if(myTLSDisabledConnections.begin(), myTLSDisabledConnections.end(), tls_disable_finder(tpl));
1573  return i == myTLSDisabledConnections.end();
1574 }
1575 
1576 
1577 bool
1578 NBEdge::setControllingTLInformation(const NBConnection& c, const std::string& tlID) {
1579  const int fromLane = c.getFromLane();
1580  NBEdge* toEdge = c.getTo();
1581  const int toLane = c.getToLane();
1582  const int tlIndex = c.getTLIndex();
1583  // check whether the connection was not set as not to be controled previously
1585  tpl.fromLane = fromLane;
1586  tpl.to = toEdge;
1587  tpl.toLane = toLane;
1588  std::vector<TLSDisabledConnection>::iterator i = find_if(myTLSDisabledConnections.begin(), myTLSDisabledConnections.end(), tls_disable_finder(tpl));
1589  if (i != myTLSDisabledConnections.end()) {
1590  return false;
1591  }
1592 
1593  assert(fromLane < 0 || fromLane < (int) myLanes.size());
1594  // try to use information about the connections if given
1595  if (fromLane >= 0 && toLane >= 0) {
1596  // find the specified connection
1597  std::vector<Connection>::iterator i =
1598  find_if(myConnections.begin(), myConnections.end(), connections_finder(fromLane, toEdge, toLane));
1599  // ok, we have to test this as on the removal of self-loop edges some connections
1600  // will be reassigned
1601  if (i != myConnections.end()) {
1602  // get the connection
1603  Connection& connection = *i;
1604  // set the information about the tl
1605  connection.tlID = tlID;
1606  connection.tlLinkNo = tlIndex;
1607  return true;
1608  }
1609  }
1610  // if the original connection was not found, set the information for all
1611  // connections
1612  unsigned int no = 0;
1613  bool hadError = false;
1614  for (std::vector<Connection>::iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
1615  if ((*i).toEdge != toEdge) {
1616  continue;
1617  }
1618  if (fromLane >= 0 && fromLane != (*i).fromLane) {
1619  continue;
1620  }
1621  if (toLane >= 0 && toLane != (*i).toLane) {
1622  continue;
1623  }
1624  if ((*i).tlID == "") {
1625  (*i).tlID = tlID;
1626  (*i).tlLinkNo = tlIndex;
1627  no++;
1628  } else {
1629  if ((*i).tlID != tlID && static_cast<int>((*i).tlLinkNo) == tlIndex) {
1630  WRITE_WARNING("The lane " + toString<int>((*i).fromLane) + " on edge " + getID() + " already had a traffic light signal.");
1631  hadError = true;
1632  }
1633  }
1634  }
1635  if (hadError && no == 0) {
1636  WRITE_WARNING("Could not set any signal of the traffic light '" + tlID + "' (unknown group)");
1637  }
1638  return true;
1639 }
1640 
1641 
1642 void
1644  for (std::vector<Connection>::iterator it = myConnections.begin(); it != myConnections.end(); it++) {
1645  it->tlID = "";
1646  }
1647 }
1648 
1649 
1650 void
1651 NBEdge::disableConnection4TLS(int fromLane, NBEdge* toEdge, int toLane) {
1653  c.fromLane = fromLane;
1654  c.to = toEdge;
1655  c.toLane = toLane;
1656  myTLSDisabledConnections.push_back(c);
1657 }
1658 
1659 
1661 NBEdge::getCWBoundaryLine(const NBNode& n, SUMOReal offset) const {
1662  PositionVector ret;
1663  if (myFrom == (&n)) {
1664  // outgoing
1665  ret = !myAmLeftHand ? myLanes[0].shape : myLanes.back().shape;
1666  } else {
1667  // incoming
1668  ret = !myAmLeftHand ? myLanes.back().shape.reverse() : myLanes[0].shape.reverse();
1669  }
1670  ret.move2side(offset);
1671  return ret;
1672 }
1673 
1674 
1676 NBEdge::getCCWBoundaryLine(const NBNode& n, SUMOReal offset) const {
1677  PositionVector ret;
1678  if (myFrom == (&n)) {
1679  // outgoing
1680  ret = !myAmLeftHand ? myLanes.back().shape : myLanes[0].shape;
1681  } else {
1682  // incoming
1683  ret = !myAmLeftHand ? myLanes[0].shape.reverse() : myLanes.back().shape.reverse();
1684  }
1685  ret.move2side(-offset);
1686  return ret;
1687 }
1688 
1689 
1690 SUMOReal
1691 NBEdge::width() const {
1692  return (SUMOReal) myLanes.size() * SUMO_const_laneWidth + (SUMOReal)(myLanes.size() - 1) * SUMO_const_laneOffset;
1693 }
1694 
1695 
1696 bool
1697 NBEdge::expandableBy(NBEdge* possContinuation) const {
1698  // ok, the number of lanes must match
1699  if (myLanes.size() != possContinuation->myLanes.size()) {
1700  return false;
1701  }
1702  // the priority, too (?)
1703  if (getPriority() != possContinuation->getPriority()) {
1704  return false;
1705  }
1706  // the speed allowed
1707  if (mySpeed != possContinuation->mySpeed) {
1708  return false;
1709  }
1710  // the vehicle class constraints, too
1718  // also, check whether the connections - if any exit do allow to join
1719  // both edges
1720  // This edge must have a one-to-one connection to the following lanes
1721  switch (myStep) {
1723  break;
1724  case INIT:
1725  break;
1726  case EDGE2EDGES: {
1727  // the following edge must be connected
1728  const EdgeVector& conn = getConnectedEdges();
1729  if (find(conn.begin(), conn.end(), possContinuation)
1730  == conn.end()) {
1731 
1732  return false;
1733  }
1734  }
1735  break;
1736  case LANES2EDGES:
1737  case LANES2LANES_RECHECK:
1738  case LANES2LANES_DONE:
1739  case LANES2LANES_USER: {
1740  // the possible continuation must be connected
1741  if (find_if(myConnections.begin(), myConnections.end(), connections_toedge_finder(possContinuation)) == myConnections.end()) {
1742  return false;
1743  }
1744  // all lanes must go to the possible continuation
1745  std::vector<int> conns = getConnectionLanes(possContinuation);
1746  if (conns.size() != myLanes.size()) {
1747  return false;
1748  }
1749  }
1750  break;
1751  default:
1752  break;
1753  }
1754  return true;
1755 }
1756 
1757 
1758 void
1760  // append geometry
1762  for (unsigned int i = 0; i < myLanes.size(); i++) {
1763  myLanes[i].shape.appendWithCrossingPoint(e->myLanes[i].shape);
1764  }
1765  // recompute length
1766  myLength += e->myLength;
1767  // copy the connections and the building step if given
1768  myStep = e->myStep;
1771  // set the node
1772  myTo = e->myTo;
1773 }
1774 
1775 
1776 
1777 
1778 
1779 bool
1781  for (std::vector<Connection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
1782  if ((*i).toEdge == e && (*i).tlID != "") {
1783  return true;
1784  }
1785  }
1786  return false;
1787 }
1788 
1789 
1790 NBEdge*
1792  return myTurnDestination;
1793 }
1794 
1795 
1796 std::string
1797 NBEdge::getLaneID(unsigned int lane) const {
1798  assert(lane < myLanes.size());
1799  return myID + "_" + toString(lane);
1800 }
1801 
1802 
1803 bool
1805  std::vector<SUMOReal> distances = myGeom.distances(e->getGeometry());
1806  assert(distances.size() > 0);
1807  return VectorHelper<SUMOReal>::maxValue(distances) < threshold;
1808 }
1809 
1810 
1811 void
1812 NBEdge::incLaneNo(unsigned int by) {
1813  unsigned int newLaneNo = (unsigned int) myLanes.size() + by;
1814  while (myLanes.size() < newLaneNo) {
1815  myLanes.push_back(Lane(this));
1816  }
1818  const EdgeVector& incs = myFrom->getIncomingEdges();
1819  for (EdgeVector::const_iterator i = incs.begin(); i != incs.end(); ++i) {
1820  (*i)->invalidateConnections(true);
1821  }
1822  invalidateConnections(true);
1823 }
1824 
1825 
1826 void
1827 NBEdge::decLaneNo(unsigned int by, int dir) {
1828  unsigned int newLaneNo = (unsigned int) myLanes.size() - by;
1829  while (myLanes.size() > newLaneNo) {
1830  myLanes.pop_back();
1831  }
1833  const EdgeVector& incs = myFrom->getIncomingEdges();
1834  for (EdgeVector::const_iterator i = incs.begin(); i != incs.end(); ++i) {
1835  (*i)->invalidateConnections(true);
1836  }
1837  if (dir == 0) {
1838  invalidateConnections(true);
1839  } else {
1840  const EdgeVector& outs = myTo->getOutgoingEdges();
1841  assert(outs.size() == 1);
1842  NBEdge* out = outs[0];
1843  if (dir < 0) {
1844  removeFromConnections(out, 0);
1845  } else {
1846  removeFromConnections(out, (int) myLanes.size());
1847  }
1848  }
1849 }
1850 
1851 
1852 void
1854  assert(myTo->getOutgoingEdges().size() == 0);
1856 }
1857 
1858 
1859 void
1861  if (lane < 0) { // all lanes are meant...
1862  for (unsigned int i = 0; i < myLanes.size(); i++) {
1863  allowVehicleClass((int) i, vclass);
1864  }
1865  } else {
1866  assert(lane < (int) myLanes.size());
1867  myLanes[lane].permissions |= vclass;
1868  }
1869 }
1870 
1871 
1872 void
1874  if (lane < 0) { // all lanes are meant...
1875  for (unsigned int i = 0; i < myLanes.size(); i++) {
1876  disallowVehicleClass((int) i, vclass);
1877  }
1878  } else {
1879  assert(lane < (int) myLanes.size());
1880  myLanes[lane].permissions &= ~vclass;
1881  }
1882 }
1883 
1884 
1885 void
1887  if (lane < 0) { // all lanes are meant...
1888  for (unsigned int i = 0; i < myLanes.size(); i++) {
1889  allowVehicleClass((int) i, vclass);
1890  }
1891  } else {
1892  assert(lane < (int) myLanes.size());
1893  myLanes[lane].preferred |= vclass;
1894  }
1895 }
1896 
1897 
1898 void
1899 NBEdge::setWidth(int lane, SUMOReal width) {
1900  if (lane < 0) {
1901  // all lanes are meant...
1902  myWidth = width;
1903  for (unsigned int i = 0; i < myLanes.size(); i++) {
1904  // ... do it for each lane
1905  setWidth((int) i, width);
1906  }
1907  return;
1908  }
1909  assert(lane < (int) myLanes.size());
1910  myLanes[lane].width = width;
1911 }
1912 
1913 
1914 void
1915 NBEdge::setOffset(int lane, SUMOReal offset) {
1916  if (lane < 0) {
1917  // all lanes are meant...
1918  myOffset = offset;
1919  for (unsigned int i = 0; i < myLanes.size(); i++) {
1920  // ... do it for each lane
1921  setOffset((int) i, offset);
1922  }
1923  return;
1924  }
1925  assert(lane < (int) myLanes.size());
1926  myLanes[lane].offset = offset;
1927 }
1928 
1929 
1930 void
1931 NBEdge::setSpeed(int lane, SUMOReal speed) {
1932  if (lane < 0) {
1933  // all lanes are meant...
1934  mySpeed = speed;
1935  for (unsigned int i = 0; i < myLanes.size(); i++) {
1936  // ... do it for each lane
1937  setSpeed((int) i, speed);
1938  }
1939  return;
1940  }
1941  assert(lane < (int) myLanes.size());
1942  myLanes[lane].speed = speed;
1943 }
1944 
1945 
1946 void
1947 NBEdge::setPermissions(SVCPermissions permissions, int lane) {
1948  if (lane < 0) {
1949  for (unsigned int i = 0; i < myLanes.size(); i++) {
1950  // ... do it for each lane
1951  setPermissions(permissions, i);
1952  }
1953  } else {
1954  assert(lane < (int) myLanes.size());
1955  myLanes[lane].permissions = permissions;
1956  }
1957 }
1958 
1959 
1960 void
1962  if (lane < 0) {
1963  for (unsigned int i = 0; i < myLanes.size(); i++) {
1964  // ... do it for each lane
1965  setPreferredVehicleClass(permissions, i);
1966  }
1967  } else {
1968  assert(lane < (int) myLanes.size());
1969  myLanes[lane].preferred = permissions;
1970  }
1971 }
1972 
1973 
1975 NBEdge::getPermissions(int lane) const {
1976  if (lane < 0) {
1977  SVCPermissions result = 0;
1978  for (unsigned int i = 0; i < myLanes.size(); i++) {
1979  result |= getPermissions(i);
1980  }
1981  return result;
1982  } else {
1983  assert(lane < (int) myLanes.size());
1984  return myLanes[lane].permissions;
1985  }
1986 }
1987 
1988 
1989 void
1991  myLoadedLength = val;
1992 }
1993 
1994 
1995 void
1997  for (std::vector<Lane>::iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
1998  (*i).permissions = SVCFreeForAll;
1999  (*i).preferred = 0;
2000  }
2001 }
2002 
2003 
2004 /****************************************************************************/