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