SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NBNode.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // The representation of a single node
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo-sim.org/
13 // Copyright (C) 2001-2014 DLR (http://www.dlr.de/) and contributors
14 /****************************************************************************/
15 //
16 // This file is part of SUMO.
17 // SUMO is free software: you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation, either version 3 of the License, or
20 // (at your option) any later version.
21 //
22 /****************************************************************************/
23 
24 
25 // ===========================================================================
26 // included modules
27 // ===========================================================================
28 #ifdef _MSC_VER
29 #include <windows_config.h>
30 #else
31 #include <config.h>
32 #endif
33 
34 #include <string>
35 #include <map>
36 #include <cassert>
37 #include <algorithm>
38 #include <vector>
39 #include <deque>
40 #include <set>
41 #include <cmath>
42 #include <iterator>
46 #include <utils/geom/Line.h>
47 #include <utils/geom/GeomHelper.h>
48 #include <utils/geom/bezier.h>
50 #include <utils/common/StdDefs.h>
51 #include <utils/common/ToString.h>
54 #include <iomanip>
55 #include "NBNode.h"
56 #include "NBNodeCont.h"
57 #include "NBNodeShapeComputer.h"
58 #include "NBEdgeCont.h"
59 #include "NBTypeCont.h"
60 #include "NBHelpers.h"
61 #include "NBDistrict.h"
62 #include "NBContHelper.h"
63 #include "NBRequest.h"
64 #include "NBOwnTLDef.h"
67 
68 #ifdef CHECK_MEMORY_LEAKS
69 #include <foreign/nvwa/debug_new.h>
70 #endif // CHECK_MEMORY_LEAKS
71 
72 
73 // ===========================================================================
74 // static members
75 // ===========================================================================
76 
77 // ===========================================================================
78 // method definitions
79 // ===========================================================================
80 /* -------------------------------------------------------------------------
81  * NBNode::ApproachingDivider-methods
82  * ----------------------------------------------------------------------- */
84  EdgeVector* approaching, NBEdge* currentOutgoing) :
85  myApproaching(approaching), myCurrentOutgoing(currentOutgoing) {
86  // check whether origin lanes have been given
87  assert(myApproaching != 0);
88 }
89 
90 
92 
93 
94 void
95 NBNode::ApproachingDivider::execute(const unsigned int src, const unsigned int dest) {
96  assert(myApproaching->size() > src);
97  // get the origin edge
98  NBEdge* incomingEdge = (*myApproaching)[src];
99  if (incomingEdge->getStep() == NBEdge::LANES2LANES_DONE || incomingEdge->getStep() == NBEdge::LANES2LANES_USER) {
100  return;
101  }
102  std::vector<int> approachingLanes =
103  incomingEdge->getConnectionLanes(myCurrentOutgoing);
104  assert(approachingLanes.size() != 0);
105  std::deque<int>* approachedLanes = spread(approachingLanes, dest);
106  assert(approachedLanes->size() <= myCurrentOutgoing->getNumLanes());
107  // set lanes
108  for (unsigned int i = 0; i < approachedLanes->size(); i++) {
109  unsigned int approached = (*approachedLanes)[i];
110  assert(approachedLanes->size() > i);
111  assert(approachingLanes.size() > i);
112  incomingEdge->setConnection((unsigned int) approachingLanes[i], myCurrentOutgoing,
113  approached, NBEdge::L2L_COMPUTED);
114  }
115  delete approachedLanes;
116 }
117 
118 
119 std::deque<int>*
120 NBNode::ApproachingDivider::spread(const std::vector<int>& approachingLanes,
121  int dest) const {
122  std::deque<int>* ret = new std::deque<int>();
123  unsigned int noLanes = (unsigned int) approachingLanes.size();
124  // when only one lane is approached, we check, whether the SUMOReal-value
125  // is assigned more to the left or right lane
126  if (noLanes == 1) {
127  ret->push_back(dest);
128  return ret;
129  }
130 
131  unsigned int noOutgoingLanes = myCurrentOutgoing->getNumLanes();
132  //
133  ret->push_back(dest);
134  unsigned int noSet = 1;
135  int roffset = 1;
136  int loffset = 1;
137  while (noSet < noLanes) {
138  // It may be possible, that there are not enough lanes the source
139  // lanes may be divided on
140  // In this case, they remain unset
141  // !!! this is only a hack. It is possible, that this yields in
142  // uncommon divisions
143  if (noOutgoingLanes == noSet) {
144  return ret;
145  }
146 
147  // as due to the conversion of SUMOReal->uint the numbers will be lower
148  // than they should be, we try to append to the left side first
149  //
150  // check whether the left boundary of the approached street has
151  // been overridden; if so, move all lanes to the right
152  if (dest + loffset >= static_cast<int>(noOutgoingLanes)) {
153  loffset -= 1;
154  roffset += 1;
155  for (unsigned int i = 0; i < ret->size(); i++) {
156  (*ret)[i] = (*ret)[i] - 1;
157  }
158  }
159  // append the next lane to the left of all edges
160  // increase the position (destination edge)
161  ret->push_back(dest + loffset);
162  noSet++;
163  loffset += 1;
164 
165  // as above
166  if (noOutgoingLanes == noSet) {
167  return ret;
168  }
169 
170  // now we try to append the next lane to the right side, when needed
171  if (noSet < noLanes) {
172  // check whether the right boundary of the approached street has
173  // been overridden; if so, move all lanes to the right
174  if (dest < roffset) {
175  loffset += 1;
176  roffset -= 1;
177  for (unsigned int i = 0; i < ret->size(); i++) {
178  (*ret)[i] = (*ret)[i] + 1;
179  }
180  }
181  ret->push_front(dest - roffset);
182  noSet++;
183  roffset += 1;
184  }
185  }
186  return ret;
187 }
188 
189 
190 
191 
192 /* -------------------------------------------------------------------------
193  * NBNode-methods
194  * ----------------------------------------------------------------------- */
195 NBNode::NBNode(const std::string& id, const Position& position,
196  SumoXMLNodeType type) :
197  Named(StringUtils::convertUmlaute(id)),
198  myPosition(position),
199  myType(type), myDistrict(0), myRequest(0)
200 { }
201 
202 
203 NBNode::NBNode(const std::string& id, const Position& position, NBDistrict* district) :
204  Named(StringUtils::convertUmlaute(id)),
205  myPosition(position),
206  myType(district == 0 ? NODETYPE_UNKNOWN : NODETYPE_DISTRICT), myDistrict(district), myRequest(0)
207 { }
208 
209 
211  delete myRequest;
212 }
213 
214 
215 void
217  bool updateEdgeGeometries) {
218  myPosition = position;
219  // patch type
220  myType = type;
223  }
224  if (updateEdgeGeometries) {
225  for (EdgeVector::iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
226  PositionVector geom = (*i)->getGeometry();
227  geom[-1] = myPosition;
228  (*i)->setGeometry(geom);
229  }
230  for (EdgeVector::iterator i = myOutgoingEdges.begin(); i != myOutgoingEdges.end(); i++) {
231  PositionVector geom = (*i)->getGeometry();
232  geom[0] = myPosition;
233  (*i)->setGeometry(geom);
234  }
235  }
236 }
237 
238 
239 
240 // ----------- Applying offset
241 void
243  myPosition.add(xoff, yoff, 0);
244  myPoly.add(xoff, yoff, 0);
245 }
246 
247 
248 // ----------- Methods for dealing with assigned traffic lights
249 void
251  myTrafficLights.insert(tlDef);
254  }
255 }
256 
257 
258 void
260  tlDef->removeNode(this);
261  myTrafficLights.erase(tlDef);
262 }
263 
264 
265 void
267  std::set<NBTrafficLightDefinition*> trafficLights = myTrafficLights; // make a copy because we will modify the original
268  for (std::set<NBTrafficLightDefinition*>::const_iterator i = trafficLights.begin(); i != trafficLights.end(); ++i) {
269  removeTrafficLight(*i);
270  }
271 }
272 
273 
274 bool
276  if (!isTLControlled()) {
277  return false;
278  }
279  for (std::set<NBTrafficLightDefinition*>::const_iterator i = myTrafficLights.begin(); i != myTrafficLights.end(); ++i) {
280  if ((*i)->getID().find("joined") == 0) {
281  return true;
282  }
283  }
284  return false;
285 }
286 
287 
288 void
290  if (isTLControlled()) {
291  std::set<NBTrafficLightDefinition*> oldDefs(myTrafficLights);
292  for (std::set<NBTrafficLightDefinition*>::iterator it = oldDefs.begin(); it != oldDefs.end(); ++it) {
293  NBTrafficLightDefinition* orig = *it;
294  if (dynamic_cast<NBOwnTLDef*>(orig) == 0) {
295  NBTrafficLightDefinition* newDef = new NBOwnTLDef(orig->getID(), orig->getOffset(), orig->getType());
296  const std::vector<NBNode*>& nodes = orig->getNodes();
297  while (!nodes.empty()) {
298  nodes.front()->removeTrafficLight(orig);
299  newDef->addNode(nodes.front());
300  }
301  tlCont.removeFully(orig->getID());
302  tlCont.insert(newDef);
303  }
304  }
305  }
306 }
307 
308 
309 // ----------- Prunning the input
310 unsigned int
312  unsigned int ret = 0;
313  unsigned int pos = 0;
314  EdgeVector::const_iterator j = myIncomingEdges.begin();
315  while (j != myIncomingEdges.end()) {
316  // skip edges which are only incoming and not outgoing
317  if (find(myOutgoingEdges.begin(), myOutgoingEdges.end(), *j) == myOutgoingEdges.end()) {
318  ++j;
319  ++pos;
320  continue;
321  }
322  // an edge with both its origin and destination being the current
323  // node should be removed
324  NBEdge* dummy = *j;
325  WRITE_WARNING(" Removing self-looping edge '" + dummy->getID() + "'");
326  // get the list of incoming edges connected to the self-loop
327  EdgeVector incomingConnected;
328  for (EdgeVector::const_iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
329  if ((*i)->isConnectedTo(dummy) && *i != dummy) {
330  incomingConnected.push_back(*i);
331  }
332  }
333  // get the list of outgoing edges connected to the self-loop
334  EdgeVector outgoingConnected;
335  for (EdgeVector::const_iterator i = myOutgoingEdges.begin(); i != myOutgoingEdges.end(); i++) {
336  if (dummy->isConnectedTo(*i) && *i != dummy) {
337  outgoingConnected.push_back(*i);
338  }
339  }
340  // let the self-loop remap its connections
341  dummy->remapConnections(incomingConnected);
342  remapRemoved(tc, dummy, incomingConnected, outgoingConnected);
343  // delete the self-loop
344  ec.erase(dc, dummy);
345  j = myIncomingEdges.begin() + pos;
346  ++ret;
347  }
348  return ret;
349 }
350 
351 
352 // -----------
353 void
355  assert(edge != 0);
356  if (find(myIncomingEdges.begin(), myIncomingEdges.end(), edge) == myIncomingEdges.end()) {
357  myIncomingEdges.push_back(edge);
358  myAllEdges.push_back(edge);
359  }
360 }
361 
362 
363 void
365  assert(edge != 0);
366  if (find(myOutgoingEdges.begin(), myOutgoingEdges.end(), edge) == myOutgoingEdges.end()) {
367  myOutgoingEdges.push_back(edge);
368  myAllEdges.push_back(edge);
369  }
370 }
371 
372 
373 bool
375  // one in, one out->continuation
376  if (myIncomingEdges.size() == 1 && myOutgoingEdges.size() == 1) {
377  // both must have the same number of lanes
378  return (*(myIncomingEdges.begin()))->getNumLanes() == (*(myOutgoingEdges.begin()))->getNumLanes();
379  }
380  // two in and two out and both in reverse direction
381  if (myIncomingEdges.size() == 2 && myOutgoingEdges.size() == 2) {
382  for (EdgeVector::const_iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
383  NBEdge* in = *i;
384  EdgeVector::const_iterator opposite = find_if(myOutgoingEdges.begin(), myOutgoingEdges.end(), NBContHelper::opposite_finder(in, this));
385  // must have an opposite edge
386  if (opposite == myOutgoingEdges.end()) {
387  return false;
388  }
389  // both must have the same number of lanes
391  if (in->getNumLanes() != (*opposite)->getNumLanes()) {
392  return false;
393  }
394  }
395  return true;
396  }
397  // nope
398  return false;
399 }
400 
401 
404  NBEdge* toE, int toL, int numPoints) const {
405  if (fromL >= (int) fromE->getNumLanes()) {
406  throw ProcessError("Connection '" + fromE->getID() + "_" + toString(fromL) + "->" + toE->getID() + "_" + toString(toL) + "' starts at a not existing lane.");
407  }
408  if (toL >= (int) toE->getNumLanes()) {
409  throw ProcessError("Connection '" + fromE->getID() + "_" + toString(fromL) + "->" + toE->getID() + "_" + toString(toL) + "' yields in a not existing lane.");
410  }
411  bool noSpline = false;
412  PositionVector ret;
413  PositionVector init;
414  Position beg = fromE->getLaneShape(fromL).back();
415  Position end = toE->getLaneShape(toL).front();
416  Position intersection;
417  unsigned int noInitialPoints = 0;
418  if (beg.distanceTo(end) <= POSITION_EPS) {
419  noSpline = true;
420  } else {
421  if (fromE->getTurnDestination() == toE) {
422  // turnarounds:
423  // - end of incoming lane
424  // - position between incoming/outgoing end/begin shifted by the distance orthogonally
425  // - begin of outgoing lane
426  noInitialPoints = 3;
427  init.push_back(beg);
428  Line straightConn(fromE->getLaneShape(fromL)[-1], toE->getLaneShape(toL)[0]);
429  Position straightCenter = straightConn.getPositionAtDistance((SUMOReal) straightConn.length() / (SUMOReal) 2.);
430  Position center = straightCenter;//.add(straightCenter);
431  Line cross(straightConn);
432  cross.sub(cross.p1().x(), cross.p1().y());
433  cross.rotateAtP1(M_PI / 2);
434  center.sub(cross.p2());
435  init.push_back(center);
436  init.push_back(end);
437  } else {
438  const SUMOReal angle = fabs(fromE->getLaneShape(fromL).getEndLine().atan2Angle() - toE->getLaneShape(toL).getBegLine().atan2Angle());
439  if (angle < M_PI / 4. || angle > 7. / 4.*M_PI) {
440  // very low angle: almost straight
441  noInitialPoints = 4;
442  init.push_back(beg);
443  Line begL = fromE->getLaneShape(fromL).getEndLine();
444  begL.extrapolateSecondBy(100);
445  Line endL = toE->getLaneShape(toL).getBegLine();
446  endL.extrapolateFirstBy(100);
447  SUMOReal distance = beg.distanceTo(end);
448  if (distance > 10) {
449  {
450  SUMOReal off1 = fromE->getLaneShape(fromL).getEndLine().length() + (SUMOReal) 5. * (SUMOReal) fromE->getNumLanes();
451  off1 = MIN2(off1, (SUMOReal)(fromE->getLaneShape(fromL).getEndLine().length() + distance / 2.));
452  Position tmp = begL.getPositionAtDistance(off1);
453  init.push_back(tmp);
454  }
455  {
456  SUMOReal off1 = (SUMOReal) 100. - (SUMOReal) 5. * (SUMOReal) toE->getNumLanes();
457  off1 = MAX2(off1, (SUMOReal)(100. - distance / 2.));
458  Position tmp = endL.getPositionAtDistance(off1);
459  init.push_back(tmp);
460  }
461  } else {
462  noSpline = true;
463  }
464  init.push_back(end);
465  } else {
466  // turning
467  // - end of incoming lane
468  // - intersection of the extrapolated lanes
469  // - begin of outgoing lane
470  // attention: if there is no intersection, use a straight line
471  noInitialPoints = 3;
472  init.push_back(beg);
473  Line begL = fromE->getLaneShape(fromL).getEndLine();
474  Line endL = toE->getLaneShape(toL).getBegLine();
475  bool check = !begL.p1().almostSame(begL.p2()) && !endL.p1().almostSame(endL.p2());
476  if (check) {
477  begL.extrapolateSecondBy(100);
478  endL.extrapolateFirstBy(100);
479  } else {
480  WRITE_WARNING("Could not use edge geometry for internal lane, node '" + getID() + "'.");
481  }
482  if (!check || !begL.intersects(endL)) {
483  noSpline = true;
484  } else {
485  init.push_back(begL.intersectsAt(endL));
486  }
487  init.push_back(end);
488  }
489  }
490  }
491  //
492  if (noSpline) {
493  ret.push_back(fromE->getLaneShape(fromL).back());
494  ret.push_back(toE->getLaneShape(toL).front());
495  } else {
496  SUMOReal* def = new SUMOReal[1 + noInitialPoints * 3];
497  for (int i = 0; i < (int) init.size(); ++i) {
498  // starts at index 1
499  def[i * 3 + 1] = init[i].x();
500  def[i * 3 + 2] = 0;
501  def[i * 3 + 3] = init[i].y();
502  }
503  SUMOReal* ret_buf = new SUMOReal[numPoints * 3 + 1];
504  bezier(noInitialPoints, def, numPoints, ret_buf);
505  delete[] def;
506  Position prev;
507  for (int i = 0; i < (int) numPoints; i++) {
508  Position current(ret_buf[i * 3 + 1], ret_buf[i * 3 + 3]);
509  if (prev != current) {
510  ret.push_back(current);
511  }
512  prev = current;
513  }
514  delete[] ret_buf;
515  }
516  const NBEdge::Lane& lane = fromE->getLaneStruct(fromL);
517  if (lane.offset > 0) {
518  PositionVector beg = lane.shape.getSubpart(lane.shape.length() - lane.offset, lane.shape.length());;
519  beg.append(ret);
520  ret = beg;
521  }
522  return ret;
523 }
524 
525 
526 bool
527 NBNode::needsCont(NBEdge* fromE, NBEdge* toE, NBEdge* otherFromE, NBEdge* otherToE, const NBEdge::Connection& c) const {
529  return false;
530  }
531  if (fromE == otherFromE) {
532  // ignore same edge links
533  return false;
534  }
535  if (!foes(otherFromE, otherToE, fromE, toE)) {
536  // if they do not cross, no waiting place is needed
537  return false;
538  }
539  LinkDirection d1 = getDirection(fromE, toE);
540  LinkDirection d2 = getDirection(otherFromE, otherToE);
541  bool thisLeft = (d1 == LINKDIR_LEFT || d1 == LINKDIR_TURN);
542  bool otherLeft = (d2 == LINKDIR_LEFT || d2 == LINKDIR_TURN);
543  bool bothLeft = thisLeft && otherLeft;
544  if (c.tlID != "" && !bothLeft) {
545  // tls-controlled links will have space
546  return true;
547  }
548  if (fromE->getJunctionPriority(this) > 0 && otherFromE->getJunctionPriority(this) > 0) {
549  return mustBrake(fromE, toE, c.toLane);
550  }
551  return false;
552 }
553 
554 
555 void
557  delete myRequest; // possibly recomputation step
558  myRequest = 0;
559  if (myIncomingEdges.size() == 0 || myOutgoingEdges.size() == 0) {
560  // no logic if nothing happens here
562  return;
563  }
564  // check whether the node was set to be unregulated by the user
565  if (oc.getBool("keep-nodes-unregulated") || oc.isInStringVector("keep-nodes-unregulated.explicit", getID())
566  || (oc.getBool("keep-nodes-unregulated.district-nodes") && (isNearDistrict() || isDistrict()))) {
568  return;
569  }
570  // compute the logic if necessary or split the junction
572  // build the request
573  myRequest = new NBRequest(ec, this,
575  // check whether it is not too large
576  unsigned int numConnections = myRequest->getSizes().second;
577  if (numConnections >= 64) {
578  // yep -> make it untcontrolled, warn
579  WRITE_WARNING("Junction '" + getID() + "' is too complicated (#links>64); will be set to unregulated.");
580  delete myRequest;
581  myRequest = 0;
583  } else if (numConnections == 0) {
584  delete myRequest;
585  myRequest = 0;
587  } else {
589  }
590  }
591 }
592 
593 
594 bool
595 NBNode::writeLogic(OutputDevice& into, const bool checkLaneFoes) const {
596  if (myRequest) {
597  myRequest->writeLogic(myID, into, checkLaneFoes);
598  return true;
599  }
600  return false;
601 }
602 
603 
604 void
605 NBNode::computeNodeShape(bool leftHand, SUMOReal mismatchThreshold) {
606  if (myIncomingEdges.size() == 0 && myOutgoingEdges.size() == 0) {
607  return;
608  }
609  try {
610  NBNodeShapeComputer computer(*this);
611  myPoly = computer.compute(leftHand);
612  if (myPoly.size() > 0) {
613  PositionVector tmp = myPoly;
614  tmp.push_back_noDoublePos(tmp[0]); // need closed shape
615  if (mismatchThreshold >= 0
616  && !tmp.around(myPosition)
617  && tmp.distance(myPosition) > mismatchThreshold) {
618  WRITE_WARNING("Junction shape for '" + myID + "' has distance " + toString(tmp.distance(myPosition)) + " to its given position");
619  }
620  }
621  } catch (InvalidArgument&) {
622  WRITE_WARNING("For node '" + getID() + "': could not compute shape.");
623  // make sure our shape is not empty because our XML schema forbids empty attributes
624  myPoly.clear();
626  }
627 }
628 
629 
630 void
632  // special case a):
633  // one in, one out, the outgoing has one lane more
634  if (myIncomingEdges.size() == 1 && myOutgoingEdges.size() == 1
635  && myIncomingEdges[0]->getNumLanes() == myOutgoingEdges[0]->getNumLanes() - 1
636  && myIncomingEdges[0] != myOutgoingEdges[0]
637  && myIncomingEdges[0]->isConnectedTo(myOutgoingEdges[0])) {
638 
639  NBEdge* incoming = myIncomingEdges[0];
640  NBEdge* outgoing = myOutgoingEdges[0];
641  // check if it's not the turnaround
642  if (incoming->getTurnDestination() == outgoing) {
643  // will be added later or not...
644  return;
645  }
646  for (int i = 0; i < (int) incoming->getNumLanes(); ++i) {
647  incoming->setConnection(i, outgoing, i + 1, NBEdge::L2L_COMPUTED);
648  }
649  incoming->setConnection(0, outgoing, 0, NBEdge::L2L_COMPUTED);
650  return;
651  }
652  // special case b):
653  // two in, one out, the outgoing has the same number of lanes as the sum of the incoming
654  // --> highway on-ramp
655  bool check = false;
656  if (myIncomingEdges.size() == 2 && myOutgoingEdges.size() == 1) {
657  check = myIncomingEdges[0]->getNumLanes() + myIncomingEdges[1]->getNumLanes() == myOutgoingEdges[0]->getNumLanes();
658  check &= (myIncomingEdges[0]->getStep() <= NBEdge::LANES2EDGES);
659  check &= (myIncomingEdges[1]->getStep() <= NBEdge::LANES2EDGES);
660  check &= myIncomingEdges[0] != myOutgoingEdges[0];
661  check &= myIncomingEdges[1] != myOutgoingEdges[0];
662  check &= myIncomingEdges[0]->isConnectedTo(myOutgoingEdges[0]);
663  check &= myIncomingEdges[1]->isConnectedTo(myOutgoingEdges[0]);
664  }
665  if (check) {
666  NBEdge* inc1 = myIncomingEdges[0];
667  NBEdge* inc2 = myIncomingEdges[1];
668  // for internal: check which one is the rightmost
669  SUMOReal a1 = inc1->getAngleAtNode(this);
670  SUMOReal a2 = inc2->getAngleAtNode(this);
673  if (ccw > cw) {
674  std::swap(inc1, inc2);
675  }
676  inc1->addLane2LaneConnections(0, myOutgoingEdges[0], 0, inc1->getNumLanes(), NBEdge::L2L_VALIDATED, true, true);
677  inc2->addLane2LaneConnections(0, myOutgoingEdges[0], inc1->getNumLanes(), inc2->getNumLanes(), NBEdge::L2L_VALIDATED, true, true);
678  return;
679  }
680  // special case c):
681  // one in, two out, the incoming has the same number of lanes as the sum of the outgoing
682  // --> highway off-ramp
683  check = false;
684  if (myIncomingEdges.size() == 1 && myOutgoingEdges.size() == 2) {
685  check = myIncomingEdges[0]->getNumLanes() == myOutgoingEdges[1]->getNumLanes() + myOutgoingEdges[0]->getNumLanes();
686  check &= (myIncomingEdges[0]->getStep() <= NBEdge::LANES2EDGES);
687  check &= myIncomingEdges[0] != myOutgoingEdges[0];
688  check &= myIncomingEdges[0] != myOutgoingEdges[1];
689  check &= myIncomingEdges[0]->isConnectedTo(myOutgoingEdges[0]);
690  check &= myIncomingEdges[0]->isConnectedTo(myOutgoingEdges[1]);
691  }
692  if (check) {
693  NBEdge* out1 = myOutgoingEdges[0];
694  NBEdge* out2 = myOutgoingEdges[1];
695  // for internal: check which one is the rightmost
697  std::swap(out1, out2);
698  }
699  myIncomingEdges[0]->addLane2LaneConnections(0, out1, 0, out1->getNumLanes(), NBEdge::L2L_VALIDATED, true, true);
700  myIncomingEdges[0]->addLane2LaneConnections(out1->getNumLanes(), out2, 0, out2->getNumLanes(), NBEdge::L2L_VALIDATED, false, true);
701  return;
702  }
703 
704  // go through this node's outgoing edges
705  // for every outgoing edge, compute the distribution of the node's
706  // incoming edges on this edge when approaching this edge
707  // the incoming edges' steps will then also be marked as LANE2LANE_RECHECK...
708  EdgeVector::reverse_iterator i;
709  for (i = myOutgoingEdges.rbegin(); i != myOutgoingEdges.rend(); i++) {
710  NBEdge* currentOutgoing = *i;
711  // get the information about edges that do approach this edge
712  EdgeVector* approaching = getEdgesThatApproach(currentOutgoing);
713  if (approaching->size() != 0) {
714  ApproachingDivider divider(approaching, currentOutgoing);
715  Bresenham::compute(&divider, static_cast<unsigned int>(approaching->size()),
716  currentOutgoing->getNumLanes());
717  }
718  delete approaching;
719  }
720  // ... but we may have the case that there are no outgoing edges
721  // In this case, we have to mark the incoming edges as being in state
722  // LANE2LANE( not RECHECK) by hand
723  if (myOutgoingEdges.size() == 0) {
724  for (i = myIncomingEdges.rbegin(); i != myIncomingEdges.rend(); i++) {
725  (*i)->markAsInLane2LaneState();
726  }
727  }
728 }
729 
730 
731 EdgeVector*
733  // get the position of the node to get the approaching nodes of
734  EdgeVector::const_iterator i = find(myAllEdges.begin(),
735  myAllEdges.end(), currentOutgoing);
736  // get the first possible approaching edge
738  // go through the list of edges clockwise and add the edges
739  EdgeVector* approaching = new EdgeVector();
740  for (; *i != currentOutgoing;) {
741  // check only incoming edges
742  if ((*i)->getToNode() == this && (*i)->getTurnDestination() != currentOutgoing) {
743  std::vector<int> connLanes = (*i)->getConnectionLanes(currentOutgoing);
744  if (connLanes.size() != 0) {
745  approaching->push_back(*i);
746  }
747  }
749  }
750  return approaching;
751 }
752 
753 
754 void
755 NBNode::replaceOutgoing(NBEdge* which, NBEdge* by, unsigned int laneOff) {
756  // replace the edge in the list of outgoing nodes
757  EdgeVector::iterator i = find(myOutgoingEdges.begin(), myOutgoingEdges.end(), which);
758  if (i != myOutgoingEdges.end()) {
759  (*i) = by;
760  i = find(myAllEdges.begin(), myAllEdges.end(), which);
761  (*i) = by;
762  }
763  // replace the edge in connections of incoming edges
764  for (i = myIncomingEdges.begin(); i != myIncomingEdges.end(); ++i) {
765  (*i)->replaceInConnections(which, by, laneOff);
766  }
767  // replace within the connetion prohibition dependencies
768  replaceInConnectionProhibitions(which, by, 0, laneOff);
769 }
770 
771 
772 void
774  // replace edges
775  unsigned int laneOff = 0;
776  for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
777  replaceOutgoing(*i, by, laneOff);
778  laneOff += (*i)->getNumLanes();
779  }
780  // removed SUMOReal occurences
782  // check whether this node belongs to a district and the edges
783  // must here be also remapped
784  if (myDistrict != 0) {
785  myDistrict->replaceOutgoing(which, by);
786  }
787 }
788 
789 
790 void
791 NBNode::replaceIncoming(NBEdge* which, NBEdge* by, unsigned int laneOff) {
792  // replace the edge in the list of incoming nodes
793  EdgeVector::iterator i = find(myIncomingEdges.begin(), myIncomingEdges.end(), which);
794  if (i != myIncomingEdges.end()) {
795  (*i) = by;
796  i = find(myAllEdges.begin(), myAllEdges.end(), which);
797  (*i) = by;
798  }
799  // replace within the connetion prohibition dependencies
800  replaceInConnectionProhibitions(which, by, laneOff, 0);
801 }
802 
803 
804 void
806  // replace edges
807  unsigned int laneOff = 0;
808  for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
809  replaceIncoming(*i, by, laneOff);
810  laneOff += (*i)->getNumLanes();
811  }
812  // removed SUMOReal occurences
814  // check whether this node belongs to a district and the edges
815  // must here be also remapped
816  if (myDistrict != 0) {
817  myDistrict->replaceIncoming(which, by);
818  }
819 }
820 
821 
822 
823 void
825  unsigned int whichLaneOff, unsigned int byLaneOff) {
826  // replace in keys
827  NBConnectionProhibits::iterator j = myBlockedConnections.begin();
828  while (j != myBlockedConnections.end()) {
829  bool changed = false;
830  NBConnection c = (*j).first;
831  if (c.replaceFrom(which, whichLaneOff, by, byLaneOff)) {
832  changed = true;
833  }
834  if (c.replaceTo(which, whichLaneOff, by, byLaneOff)) {
835  changed = true;
836  }
837  if (changed) {
838  myBlockedConnections[c] = (*j).second;
839  myBlockedConnections.erase(j);
840  j = myBlockedConnections.begin();
841  } else {
842  j++;
843  }
844  }
845  // replace in values
846  for (j = myBlockedConnections.begin(); j != myBlockedConnections.end(); j++) {
847  NBConnectionVector& prohibiting = (*j).second;
848  for (NBConnectionVector::iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
849  NBConnection& sprohibiting = *k;
850  sprohibiting.replaceFrom(which, whichLaneOff, by, byLaneOff);
851  sprohibiting.replaceTo(which, whichLaneOff, by, byLaneOff);
852  }
853  }
854 }
855 
856 
857 
858 void
860  unsigned int i, j;
861  // check incoming
862  for (i = 0; myIncomingEdges.size() > 0 && i < myIncomingEdges.size() - 1; i++) {
863  j = i + 1;
864  while (j < myIncomingEdges.size()) {
865  if (myIncomingEdges[i] == myIncomingEdges[j]) {
866  myIncomingEdges.erase(myIncomingEdges.begin() + j);
867  } else {
868  j++;
869  }
870  }
871  }
872  // check outgoing
873  for (i = 0; myOutgoingEdges.size() > 0 && i < myOutgoingEdges.size() - 1; i++) {
874  j = i + 1;
875  while (j < myOutgoingEdges.size()) {
876  if (myOutgoingEdges[i] == myOutgoingEdges[j]) {
877  myOutgoingEdges.erase(myOutgoingEdges.begin() + j);
878  } else {
879  j++;
880  }
881  }
882  }
883  // check all
884  for (i = 0; myAllEdges.size() > 0 && i < myAllEdges.size() - 1; i++) {
885  j = i + 1;
886  while (j < myAllEdges.size()) {
887  if (myAllEdges[i] == myAllEdges[j]) {
888  myAllEdges.erase(myAllEdges.begin() + j);
889  } else {
890  j++;
891  }
892  }
893  }
894 }
895 
896 
897 bool
898 NBNode::hasIncoming(const NBEdge* const e) const {
899  return find(myIncomingEdges.begin(), myIncomingEdges.end(), e) != myIncomingEdges.end();
900 }
901 
902 
903 bool
904 NBNode::hasOutgoing(const NBEdge* const e) const {
905  return find(myOutgoingEdges.begin(), myOutgoingEdges.end(), e) != myOutgoingEdges.end();
906 }
907 
908 
909 NBEdge*
911  EdgeVector edges = myIncomingEdges;
912  if (find(edges.begin(), edges.end(), e) != edges.end()) {
913  edges.erase(find(edges.begin(), edges.end(), e));
914  }
915  if (edges.size() == 0) {
916  return 0;
917  }
918  if (e->getToNode() == this) {
919  sort(edges.begin(), edges.end(), NBContHelper::edge_opposite_direction_sorter(e, this));
920  } else {
921  sort(edges.begin(), edges.end(), NBContHelper::edge_similar_direction_sorter(e));
922  }
923  return edges[0];
924 }
925 
926 
927 void
929  const NBConnection& mustStop) {
930  if (mayDrive.getFrom() == 0 ||
931  mayDrive.getTo() == 0 ||
932  mustStop.getFrom() == 0 ||
933  mustStop.getTo() == 0) {
934 
935  WRITE_WARNING("Something went wrong during the building of a connection...");
936  return; // !!! mark to recompute connections
937  }
938  NBConnectionVector conn = myBlockedConnections[mustStop];
939  conn.push_back(mayDrive);
940  myBlockedConnections[mustStop] = conn;
941 }
942 
943 
944 NBEdge*
945 NBNode::getPossiblySplittedIncoming(const std::string& edgeid) {
946  unsigned int size = (unsigned int) edgeid.length();
947  for (EdgeVector::iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
948  std::string id = (*i)->getID();
949  if (id.substr(0, size) == edgeid) {
950  return *i;
951  }
952  }
953  return 0;
954 }
955 
956 
957 NBEdge*
958 NBNode::getPossiblySplittedOutgoing(const std::string& edgeid) {
959  unsigned int size = (unsigned int) edgeid.length();
960  for (EdgeVector::iterator i = myOutgoingEdges.begin(); i != myOutgoingEdges.end(); i++) {
961  std::string id = (*i)->getID();
962  if (id.substr(0, size) == edgeid) {
963  return *i;
964  }
965  }
966  return 0;
967 }
968 
969 
970 void
971 NBNode::removeEdge(NBEdge* edge, bool removeFromConnections) {
972  EdgeVector::iterator i = find(myAllEdges.begin(), myAllEdges.end(), edge);
973  if (i != myAllEdges.end()) {
974  myAllEdges.erase(i);
975  i = find(myOutgoingEdges.begin(), myOutgoingEdges.end(), edge);
976  if (i != myOutgoingEdges.end()) {
977  myOutgoingEdges.erase(i);
978  } else {
979  i = find(myIncomingEdges.begin(), myIncomingEdges.end(), edge);
980  if (i != myIncomingEdges.end()) {
981  myIncomingEdges.erase(i);
982  } else {
983  // edge must have been either incoming or outgoing
984  assert(false);
985  }
986  }
987  if (removeFromConnections) {
988  for (i = myAllEdges.begin(); i != myAllEdges.end(); ++i) {
989  (*i)->removeFromConnections(edge);
990  }
991  }
992  }
993 }
994 
995 
996 Position
998  Position pos(0, 0);
999  EdgeVector::const_iterator i;
1000  for (i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
1001  NBNode* conn = (*i)->getFromNode();
1002  Position toAdd = conn->getPosition();
1003  toAdd.sub(myPosition);
1004  toAdd.mul((SUMOReal) 1.0 / sqrt(toAdd.x()*toAdd.x() + toAdd.y()*toAdd.y()));
1005  pos.add(toAdd);
1006  }
1007  for (i = myOutgoingEdges.begin(); i != myOutgoingEdges.end(); i++) {
1008  NBNode* conn = (*i)->getToNode();
1009  Position toAdd = conn->getPosition();
1010  toAdd.sub(myPosition);
1011  toAdd.mul((SUMOReal) 1.0 / sqrt(toAdd.x()*toAdd.x() + toAdd.y()*toAdd.y()));
1012  pos.add(toAdd);
1013  }
1014  pos.mul((SUMOReal) - 1.0 / (myIncomingEdges.size() + myOutgoingEdges.size()));
1015  if (pos.x() == 0 && pos.y() == 0) {
1016  pos = Position(1, 0);
1017  }
1018  pos.norm2d();
1019  return pos;
1020 }
1021 
1022 
1023 
1024 void
1026  for (EdgeVector::const_iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
1027  (*i)->invalidateConnections();
1028  }
1029 }
1030 
1031 
1032 void
1034  for (EdgeVector::const_iterator i = myOutgoingEdges.begin(); i != myOutgoingEdges.end(); i++) {
1035  (*i)->invalidateConnections();
1036  }
1037 }
1038 
1039 
1040 bool
1041 NBNode::mustBrake(const NBEdge* const from, const NBEdge* const to, int /* toLane */) const {
1042  // check whether it is participant to a traffic light
1043  // - controlled links are set by the traffic lights, not the normal
1044  // right-of-way rules
1045  // - uncontrolled participants (spip lanes etc.) should always break
1046  if (myTrafficLights.size() != 0) {
1047  // ok, we have a traffic light, return true by now, it will be later
1048  // controlled by the tls
1049  return true;
1050  }
1051  // unregulated->does not need to brake
1052  if (myRequest == 0) {
1053  return false;
1054  }
1055  // vehicles which do not have a following lane must always decelerate to the end
1056  if (to == 0) {
1057  return true;
1058  }
1059  // check whether any other connection on this node prohibits this connection
1060  return myRequest->mustBrake(from, to);
1061 }
1062 
1063 
1064 bool
1065 NBNode::isLeftMover(const NBEdge* const from, const NBEdge* const to) const {
1066  // when the junction has only one incoming edge, there are no
1067  // problems caused by left blockings
1068  if (myIncomingEdges.size() == 1 || myOutgoingEdges.size() == 1) {
1069  return false;
1070  }
1071  SUMOReal fromAngle = from->getAngleAtNode(this);
1072  SUMOReal toAngle = to->getAngleAtNode(this);
1073  SUMOReal cw = GeomHelper::getCWAngleDiff(fromAngle, toAngle);
1074  SUMOReal ccw = GeomHelper::getCCWAngleDiff(fromAngle, toAngle);
1075  std::vector<NBEdge*>::const_iterator i = std::find(myAllEdges.begin(), myAllEdges.end(), from);
1076  do {
1078  } while ((!hasOutgoing(*i) || from->isTurningDirectionAt(this, *i)) && *i != from);
1079  return cw < ccw && (*i) == to && myOutgoingEdges.size() > 2;
1080 }
1081 
1082 
1083 bool
1084 NBNode::forbids(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,
1085  const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo,
1086  bool regardNonSignalisedLowerPriority) const {
1087  return myRequest != 0 && myRequest->forbids(possProhibitorFrom, possProhibitorTo,
1088  possProhibitedFrom, possProhibitedTo,
1089  regardNonSignalisedLowerPriority);
1090 }
1091 
1092 
1093 bool
1094 NBNode::foes(const NBEdge* const from1, const NBEdge* const to1,
1095  const NBEdge* const from2, const NBEdge* const to2) const {
1096  return myRequest != 0 && myRequest->foes(from1, to1, from2, to2);
1097 }
1098 
1099 
1100 void
1102  NBEdge* removed, const EdgeVector& incoming,
1103  const EdgeVector& outgoing) {
1104  assert(find(incoming.begin(), incoming.end(), removed) == incoming.end());
1105  bool changed = true;
1106  while (changed) {
1107  changed = false;
1108  NBConnectionProhibits blockedConnectionsTmp = myBlockedConnections;
1109  NBConnectionProhibits blockedConnectionsNew;
1110  // remap in connections
1111  for (NBConnectionProhibits::iterator i = blockedConnectionsTmp.begin(); i != blockedConnectionsTmp.end(); i++) {
1112  const NBConnection& blocker = (*i).first;
1113  const NBConnectionVector& blocked = (*i).second;
1114  // check the blocked connections first
1115  // check whether any of the blocked must be changed
1116  bool blockedChanged = false;
1117  NBConnectionVector newBlocked;
1118  NBConnectionVector::const_iterator j;
1119  for (j = blocked.begin(); j != blocked.end(); j++) {
1120  const NBConnection& sblocked = *j;
1121  if (sblocked.getFrom() == removed || sblocked.getTo() == removed) {
1122  blockedChanged = true;
1123  }
1124  }
1125  // adapt changes if so
1126  for (j = blocked.begin(); blockedChanged && j != blocked.end(); j++) {
1127  const NBConnection& sblocked = *j;
1128  if (sblocked.getFrom() == removed && sblocked.getTo() == removed) {
1129  /* for(EdgeVector::const_iterator k=incoming.begin(); k!=incoming.end(); k++) {
1130  !!! newBlocked.push_back(NBConnection(*k, *k));
1131  }*/
1132  } else if (sblocked.getFrom() == removed) {
1133  assert(sblocked.getTo() != removed);
1134  for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
1135  newBlocked.push_back(NBConnection(*k, sblocked.getTo()));
1136  }
1137  } else if (sblocked.getTo() == removed) {
1138  assert(sblocked.getFrom() != removed);
1139  for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
1140  newBlocked.push_back(NBConnection(sblocked.getFrom(), *k));
1141  }
1142  } else {
1143  newBlocked.push_back(NBConnection(sblocked.getFrom(), sblocked.getTo()));
1144  }
1145  }
1146  if (blockedChanged) {
1147  blockedConnectionsNew[blocker] = newBlocked;
1148  changed = true;
1149  }
1150  // if the blocked were kept
1151  else {
1152  if (blocker.getFrom() == removed && blocker.getTo() == removed) {
1153  changed = true;
1154  /* for(EdgeVector::const_iterator k=incoming.begin(); k!=incoming.end(); k++) {
1155  !!! blockedConnectionsNew[NBConnection(*k, *k)] = blocked;
1156  }*/
1157  } else if (blocker.getFrom() == removed) {
1158  assert(blocker.getTo() != removed);
1159  changed = true;
1160  for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
1161  blockedConnectionsNew[NBConnection(*k, blocker.getTo())] = blocked;
1162  }
1163  } else if (blocker.getTo() == removed) {
1164  assert(blocker.getFrom() != removed);
1165  changed = true;
1166  for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
1167  blockedConnectionsNew[NBConnection(blocker.getFrom(), *k)] = blocked;
1168  }
1169  } else {
1170  blockedConnectionsNew[blocker] = blocked;
1171  }
1172  }
1173  }
1174  myBlockedConnections = blockedConnectionsNew;
1175  }
1176  // remap in traffic lights
1177  tc.remapRemoved(removed, incoming, outgoing);
1178 }
1179 
1180 
1182 NBNode::getDirection(const NBEdge* const incoming, const NBEdge* const outgoing) const {
1183  // ok, no connection at all -> dead end
1184  if (outgoing == 0) {
1185  return LINKDIR_NODIR;
1186  }
1187  // turning direction
1188  if (incoming->isTurningDirectionAt(this, outgoing)) {
1189  return LINKDIR_TURN;
1190  }
1191  // get the angle between incoming/outgoing at the junction
1192  SUMOReal angle =
1193  NBHelpers::normRelAngle(incoming->getAngleAtNode(this), outgoing->getAngleAtNode(this));
1194  // ok, should be a straight connection
1195  if (abs((int) angle) + 1 < 45) {
1196  return LINKDIR_STRAIGHT;
1197  }
1198 
1199  // check for left and right, first
1200  if (angle > 0) {
1201  // check whether any other edge goes further to the right
1202  EdgeVector::const_iterator i =
1203  find(myAllEdges.begin(), myAllEdges.end(), outgoing);
1205  while ((*i) != incoming) {
1206  if ((*i)->getFromNode() == this) {
1207  return LINKDIR_PARTRIGHT;
1208  }
1210  }
1211  return LINKDIR_RIGHT;
1212  }
1213  // check whether any other edge goes further to the left
1214  EdgeVector::const_iterator i =
1215  find(myAllEdges.begin(), myAllEdges.end(), outgoing);
1217  while ((*i) != incoming) {
1218  if ((*i)->getFromNode() == this && !incoming->isTurningDirectionAt(this, *i)) {
1219  return LINKDIR_PARTLEFT;
1220  }
1222  }
1223  return LINKDIR_LEFT;
1224 }
1225 
1226 
1227 LinkState
1228 NBNode::getLinkState(const NBEdge* incoming, NBEdge* outgoing, int fromlane,
1229  bool mayDefinitelyPass, const std::string& tlID) const {
1230  if (tlID != "") {
1232  }
1233  if (outgoing == 0) { // always off
1235  }
1237  return LINKSTATE_EQUAL; // all the same
1238  }
1239  if (myType == NODETYPE_ALLWAY_STOP) {
1240  return LINKSTATE_ALLWAY_STOP; // all drive, first one to arrive may drive first
1241  }
1242  if ((!incoming->isInnerEdge() && mustBrake(incoming, outgoing, fromlane)) && !mayDefinitelyPass) {
1243  return myType == NODETYPE_PRIORITY_STOP ? LINKSTATE_STOP : LINKSTATE_MINOR; // minor road
1244  }
1245  // traffic lights are not regarded here
1246  return LINKSTATE_MAJOR;
1247 }
1248 
1249 
1250 bool
1252  // check whether this node is included in a traffic light
1253  if (myTrafficLights.size() != 0) {
1254  return false;
1255  }
1256  EdgeVector::const_iterator i;
1257  // one in, one out -> just a geometry ...
1258  if (myOutgoingEdges.size() == 1 && myIncomingEdges.size() == 1) {
1259  // ... if types match ...
1260  if (!myIncomingEdges[0]->expandableBy(myOutgoingEdges[0])) {
1261  return false;
1262  }
1263  //
1264  return myIncomingEdges[0]->getFromNode() != myOutgoingEdges[0]->getToNode();
1265  }
1266  // two in, two out -> may be something else
1267  if (myOutgoingEdges.size() == 2 && myIncomingEdges.size() == 2) {
1268  // check whether the origin nodes of the incoming edges differ
1269  std::set<NBNode*> origSet;
1270  for (i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
1271  origSet.insert((*i)->getFromNode());
1272  }
1273  if (origSet.size() < 2) {
1274  return false;
1275  }
1276  // check whether this node is an intermediate node of
1277  // a two-directional street
1278  for (i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
1279  // try to find the opposite direction
1280  NBNode* origin = (*i)->getFromNode();
1281  // find the back direction of the current edge
1282  EdgeVector::const_iterator j =
1283  find_if(myOutgoingEdges.begin(), myOutgoingEdges.end(),
1285  // check whether the back direction exists
1286  if (j != myOutgoingEdges.end()) {
1287  // check whether the edge from the backdirection (must be
1288  // the counter-clockwise one) may be joined with the current
1290  // check whether the types allow joining
1291  if (!(*i)->expandableBy(*j)) {
1292  return false;
1293  }
1294  } else {
1295  // ok, at least one outgoing edge is not an opposite
1296  // of an incoming one
1297  return false;
1298  }
1299  }
1300  return true;
1301  }
1302  // ok, a real node
1303  return false;
1304 }
1305 
1306 
1307 std::vector<std::pair<NBEdge*, NBEdge*> >
1309  assert(checkIsRemovable());
1310  std::vector<std::pair<NBEdge*, NBEdge*> > ret;
1311  // one in, one out-case
1312  if (myOutgoingEdges.size() == 1 && myIncomingEdges.size() == 1) {
1313  ret.push_back(
1314  std::pair<NBEdge*, NBEdge*>(
1316  return ret;
1317  }
1318  // two in, two out-case
1319  for (EdgeVector::const_iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
1320  NBNode* origin = (*i)->getFromNode();
1321  EdgeVector::const_iterator j =
1322  find_if(myOutgoingEdges.begin(), myOutgoingEdges.end(),
1325  ret.push_back(std::pair<NBEdge*, NBEdge*>(*i, *j));
1326  }
1327  return ret;
1328 }
1329 
1330 
1331 const PositionVector&
1333  return myPoly;
1334 }
1335 
1336 
1337 NBEdge*
1339  for (EdgeVector::const_iterator i = myOutgoingEdges.begin(); i != myOutgoingEdges.end(); i++) {
1340  if ((*i)->getToNode() == n) {
1341  return (*i);
1342  }
1343  }
1344  return 0;
1345 }
1346 
1347 
1348 bool
1350  if (isDistrict()) {
1351  return false;
1352  }
1353  EdgeVector edges;
1354  copy(getIncomingEdges().begin(), getIncomingEdges().end(),
1355  back_inserter(edges));
1356  copy(getOutgoingEdges().begin(), getOutgoingEdges().end(),
1357  back_inserter(edges));
1358  for (EdgeVector::const_iterator j = edges.begin(); j != edges.end(); ++j) {
1359  NBEdge* t = *j;
1360  NBNode* other = 0;
1361  if (t->getToNode() == this) {
1362  other = t->getFromNode();
1363  } else {
1364  other = t->getToNode();
1365  }
1366  EdgeVector edges2;
1367  copy(other->getIncomingEdges().begin(), other->getIncomingEdges().end(), back_inserter(edges2));
1368  copy(other->getOutgoingEdges().begin(), other->getOutgoingEdges().end(), back_inserter(edges2));
1369  for (EdgeVector::const_iterator k = edges2.begin(); k != edges2.end(); ++k) {
1370  if ((*k)->getFromNode()->isDistrict() || (*k)->getToNode()->isDistrict()) {
1371  return true;
1372  }
1373  }
1374  }
1375  return false;
1376 }
1377 
1378 
1379 bool
1381  return myType == NODETYPE_DISTRICT;
1382 }
1383 
1384 
1385 void
1387  unsigned int noInternalNoSplits = 0;
1388  for (EdgeVector::const_iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
1389  const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
1390  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1391  if ((*k).toEdge == 0) {
1392  continue;
1393  }
1394  noInternalNoSplits++;
1395  }
1396  }
1397  unsigned int lno = 0;
1398  unsigned int splitNo = 0;
1399  for (EdgeVector::const_iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
1400  (*i)->buildInnerEdges(*this, noInternalNoSplits, lno, splitNo);
1401  }
1402 }
1403 
1404 
1405 bool
1407  if (myIncomingEdges.size() == 1 && myOutgoingEdges.size() == 1) {
1408  return true;
1409  }
1410  if (myIncomingEdges.size() == 2 && myOutgoingEdges.size() == 2) {
1411  // check whether the incoming and outgoing edges are pairwise (near) parallel and
1412  // thus the only cross-connections could be turn-arounds
1413  NBEdge* out0 = myOutgoingEdges[0];
1414  NBEdge* out1 = myOutgoingEdges[1];
1415  for (EdgeVector::const_iterator it = myIncomingEdges.begin(); it != myIncomingEdges.end(); ++it) {
1416  NBEdge* inEdge = *it;
1417  SUMOReal angle0 = fabs(NBHelpers::relAngle(inEdge->getAngleAtNode(this), out0->getAngleAtNode(this)));
1418  SUMOReal angle1 = fabs(NBHelpers::relAngle(inEdge->getAngleAtNode(this), out1->getAngleAtNode(this)));
1419  if (MAX2(angle0, angle1) <= 160) {
1420  // neither of the outgoing edges is parallel to inEdge
1421  return false;
1422  }
1423  }
1424  return true;
1425  }
1426  return false;
1427 }
1428 
1429 
1430 void
1434  }
1435 }
1436 
1437 
1438 Position
1440  /* Conceptually, the center point would be identical with myPosition.
1441  * However, if the shape is influenced by custom geometry endpoints of the adjoining edges,
1442  * myPosition may fall outside the shape. In this case it is better to use
1443  * the center of the shape
1444  **/
1445  PositionVector tmp = myPoly;
1446  tmp.closePolygon();
1447  //std::cout << getID() << " around=" << tmp.around(myPosition) << " dist=" << tmp.distance(myPosition) << "\n";
1448  if (tmp.size() < 3 || tmp.around(myPosition) || tmp.distance(myPosition) < POSITION_EPS) {
1449  return myPosition;
1450  } else {
1451  return myPoly.getPolygonCenter();
1452  }
1453 }
1454 
1455 /****************************************************************************/
1456 
void sub(SUMOReal dx, SUMOReal dy)
Substracts the given position from this one.
Definition: Position.h:139
The link is a partial left direction.
const PositionVector & getLaneShape(unsigned int i) const
Returns the shape of the nth lane.
Definition: NBEdge.cpp:478
void replaceIncoming(NBEdge *which, NBEdge *by, unsigned int laneOff)
Replaces occurences of the first edge within the list of incoming by the second Connections are remap...
Definition: NBNode.cpp:791
const Position & p2() const
Definition: Line.cpp:86
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges.
Definition: NBNode.h:170
void replaceOutgoing(const EdgeVector &which, NBEdge *const by)
Replaces outgoing edges from the vector (source) by the given edge.
Definition: NBDistrict.cpp:138
Position getEmptyDir() const
Returns something like the most unused direction Should only be used to add source or sink nodes...
Definition: NBNode.cpp:997
static SUMOReal getCWAngleDiff(SUMOReal angle1, SUMOReal angle2)
Returns the distance of second angle from first angle clockwise.
Definition: GeomHelper.cpp:381
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:148
int toLane
The lane the connections yields in.
Definition: NBEdge.h:166
void setRoundabout()
update the type of this node as a roundabout
Definition: NBNode.cpp:1431
Position getCenter() const
Returns a position that is guaranteed to lie within the node shape.
Definition: NBNode.cpp:1439
ApproachingDivider(EdgeVector *approaching, NBEdge *currentOutgoing)
Constructor.
Definition: NBNode.cpp:83
static SUMOReal getCCWAngleDiff(SUMOReal angle1, SUMOReal angle2)
Returns the distance of second angle from first angle counter-clockwise.
Definition: GeomHelper.cpp:371
PositionVector shape
The lane's shape.
Definition: NBEdge.h:128
virtual void addNode(NBNode *node)
Adds a node to the traffic light logic.
bool isInStringVector(const std::string &optionName, const std::string &itemName)
Returns the named option is a list of string values containing the specified item.
void add(const Position &pos)
Adds the given position to this one.
Definition: Position.h:119
void norm2d()
Definition: Position.h:158
bool isDistrict() const
Definition: NBNode.cpp:1380
PositionVector myPoly
the (outer) shape of the junction
Definition: NBNode.h:510
NBEdge * getOppositeIncoming(NBEdge *e) const
Definition: NBNode.cpp:910
void execute(const unsigned int src, const unsigned int dest)
Definition: NBNode.cpp:95
SumoXMLNodeType myType
The type of the junction.
Definition: NBNode.h:501
#define M_PI
Definition: angles.h:37
A container for traffic light definitions and built programs.
void reinit(const Position &position, SumoXMLNodeType type, bool updateEdgeGeometries=false)
Resets initial values.
Definition: NBNode.cpp:216
static SUMOReal normRelAngle(SUMOReal angle1, SUMOReal angle2)
ensure that reverse relAngles (>=179.999) always count as turnarounds (-180)
Definition: NBHelpers.cpp:75
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition: NBNode.h:221
~NBNode()
Destructor.
Definition: NBNode.cpp:210
Some static methods for string processing.
Definition: StringUtils.h:45
bool forbids(const NBEdge *const possProhibitorFrom, const NBEdge *const possProhibitorTo, const NBEdge *const possProhibitedFrom, const NBEdge *const possProhibitedTo, bool regardNonSignalisedLowerPriority) const
Returns the information whether "prohibited" flow must let "prohibitor" flow pass.
Definition: NBRequest.cpp:445
TrafficLightType getType() const
get the algorithm type (static etc..)
PositionVector computeInternalLaneShape(NBEdge *fromE, int fromL, NBEdge *toE, int toL, int numPoints=5) const
Compute the shape for an internal lane.
Definition: NBNode.cpp:403
This class computes shapes of junctions.
This is an uncontrolled, minor link, has to stop.
void removeEdge(NBEdge *edge, bool removeFromConnections=true)
Removes edge from this node and optionally removes connections as well.
Definition: NBNode.cpp:971
void addIncomingEdge(NBEdge *edge)
adds an incoming edge
Definition: NBNode.cpp:354
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
The representation of a single edge during network building.
Definition: NBEdge.h:71
Line getEndLine() const
Class to sort edges by their angle in relation to the given edge.
Definition: NBContHelper.h:148
bool replaceTo(NBEdge *which, NBEdge *by)
replaces the to-edge by the one given
The link is a 180 degree turn.
void rotateAtP1(SUMOReal rot)
Definition: Line.cpp:228
bool mustBrake(const NBEdge *const from, const NBEdge *const to, int toLane) const
Returns the information whether the described flow must let any other flow pass.
Definition: NBNode.cpp:1041
bool hasOutgoing(const NBEdge *const e) const
Returns whether the given edge starts at this node.
Definition: NBNode.cpp:904
A container for districts.
The base class for traffic light logic definitions.
bool addLane2LaneConnections(unsigned int fromLane, NBEdge *dest, unsigned int toLane, unsigned int no, Lane2LaneInfoType type, bool invalidatePrevious=false, bool mayDefinitelyPass=false)
Builds no connections starting at the given lanes.
Definition: NBEdge.cpp:639
bool isJoinedTLSControlled() const
Returns whether this node is controlled by a tls that spans over more than one node.
Definition: NBNode.cpp:275
void removeDoubleEdges()
Definition: NBNode.cpp:859
T MAX2(T a, T b)
Definition: StdDefs.h:71
void extrapolateFirstBy(SUMOReal length)
Definition: Line.cpp:69
bool isInnerEdge() const
Returns whether this edge was marked as being within an intersection.
Definition: NBEdge.h:828
This is an uncontrolled, right-before-left link.
static void nextCW(const EdgeVector &edges, EdgeVector::const_iterator &from)
void remapConnections(const EdgeVector &incoming)
Remaps the connection in a way that allows the removal of it.
Definition: NBEdge.cpp:812
SUMOReal distanceTo(const Position &p2) const
returns the euclidean distance in 3 dimension
Definition: Position.h:219
bool checkIsRemovable() const
Definition: NBNode.cpp:1251
bool around(const Position &p, SUMOReal offset=0) const
Returns the information whether the position vector describes a polygon lying around the given point ...
bool isTurningDirectionAt(const NBNode *n, const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition: NBEdge.cpp:1597
bool almostSame(const Position &p2, SUMOReal maxDiv=POSITION_EPS) const
Definition: Position.h:213
void removeTrafficLight(NBTrafficLightDefinition *tlDef)
Removes the given traffic light from this node.
Definition: NBNode.cpp:259
The link is controlled by a tls which is off, not blinking, may pass.
NBConnectionProhibits myBlockedConnections
Definition: NBNode.h:504
void writeLogic(std::string key, OutputDevice &into, const bool checkLaneFoes) const
Definition: NBRequest.cpp:334
bool hasIncoming(const NBEdge *const e) const
Returns whether the given edge ends at this node.
Definition: NBNode.cpp:898
SUMOReal x() const
Returns the x-position.
Definition: Position.h:63
This is an uncontrolled, all-way stop link.
void addOutgoingEdge(NBEdge *edge)
adds an outgoing edge
Definition: NBNode.cpp:364
NBEdge * getFrom() const
returns the from-edge (start of the connection)
#define abs(a)
Definition: polyfonts.c:63
The link is a (hard) left direction.
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:196
The connection was computed and validated.
Definition: NBEdge.h:116
NBRequest * myRequest
Definition: NBNode.h:512
LinkDirection
The different directions a link between two lanes may take (or a stream between two edges)...
The link is a straight direction.
SUMOTime getOffset()
Returns the offset.
NBDistrict * myDistrict
The district the node is the centre of.
Definition: NBNode.h:507
A class representing a single district.
Definition: NBDistrict.h:72
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges.
Definition: NBNode.h:178
An (internal) definition of a single lane of an edge.
Definition: NBEdge.h:123
const std::string & getID() const
Returns the id.
Definition: Named.h:60
EdgeVector myAllEdges
Vector of incoming and outgoing edges.
Definition: NBNode.h:498
void computeLanes2Lanes()
computes the connections of lanes to edges
Definition: NBNode.cpp:631
Position getPositionAtDistance(SUMOReal offset) const
Definition: Line.cpp:92
void invalidateIncomingConnections()
Definition: NBNode.cpp:1025
bool isConnectedTo(NBEdge *e)
Returns the information whethe a connection to the given edge has been added (or computed) ...
Definition: NBEdge.cpp:733
const Position & getPosition() const
Returns the position of this node.
Definition: NBNode.h:158
const Position & p1() const
Definition: Line.cpp:80
bool replaceFrom(NBEdge *which, NBEdge *by)
replaces the from-edge by the one given
Lanes to lanes - relationships are loaded; no recheck is necessary/wished.
Definition: NBEdge.h:103
NBEdge * getPossiblySplittedIncoming(const std::string &edgeid)
Definition: NBNode.cpp:945
void computeNodeShape(bool leftHand, SUMOReal mismatchThreshold)
Compute the junction shape for this node.
Definition: NBNode.cpp:605
bool isSimpleContinuation() const
Definition: NBNode.cpp:374
void buildBitfieldLogic(bool leftHanded)
Definition: NBRequest.cpp:156
void remapRemoved(NBEdge *removed, const EdgeVector &incoming, const EdgeVector &outgoing)
Replaces occurences of the removed edge in incoming/outgoing edges of all definitions.
std::string tlID
The id of the traffic light that controls this connection.
Definition: NBEdge.h:168
This is an uncontrolled, minor link, has to brake.
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:46
A list of positions.
bool mustBrake(const NBEdge *const possProhibitorFrom, const NBEdge *const possProhibitorTo, const NBEdge *const possProhibitedFrom, const NBEdge *const possProhibitedTo) const
Returns the information whether "prohibited" flow must let "prohibitor" flow pass.
Definition: NBRequest.cpp:666
void add(SUMOReal xoff, SUMOReal yoff, SUMOReal zoff)
bool needsCont(NBEdge *fromE, NBEdge *toE, NBEdge *otherFromE, NBEdge *otherToE, const NBEdge::Connection &c) const
Definition: NBNode.cpp:527
unsigned int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:338
bool geometryLike() const
whether this is structurally similar to a geometry node
Definition: NBNode.cpp:1406
SUMOReal offset
This lane's offset to the intersection begin.
Definition: NBEdge.h:136
void invalidateOutgoingConnections()
Definition: NBNode.cpp:1033
SUMOReal distance(const Position &p) const
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic, in MSLink and GNEInternalLane.
void removeTrafficLights()
Removes all references to traffic lights that control this tls.
Definition: NBNode.cpp:266
EdgeVector * getEdgesThatApproach(NBEdge *currentOutgoing)
Definition: NBNode.cpp:732
Definition: Line.h:51
std::set< NBTrafficLightDefinition * > myTrafficLights
Definition: NBNode.h:514
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:66
T MIN2(T a, T b)
Definition: StdDefs.h:65
void bezier(int npts, SUMOReal b[], int cpts, SUMOReal p[])
Definition: bezier.cpp:100
The link is a (hard) right direction.
#define POSITION_EPS
Definition: config.h:186
PositionVector compute(bool leftHand)
Computes the shape of the assigned junction.
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:52
const PositionVector & getShape() const
Definition: NBNode.cpp:1332
The link is a partial right direction.
static void compute(BresenhamCallBack *callBack, const unsigned int val1, const unsigned int val2)
Definition: Bresenham.cpp:45
NBEdge * getConnectionTo(NBNode *n) const
Definition: NBNode.cpp:1338
const std::vector< NBNode * > & getNodes() const
Returns the list of controlled nodes.
SUMOReal atan2Angle() const
Definition: Line.cpp:137
virtual void removeNode(NBNode *node)
Removes the given node from the list of controlled nodes.
EdgeVector myIncomingEdges
Vector of incoming edges.
Definition: NBNode.h:492
bool isLeftMover(const NBEdge *const from, const NBEdge *const to) const
Computes whether the given connection is a left mover across the junction.
Definition: NBNode.cpp:1065
Base class for objects which have an id.
Definition: Named.h:45
std::vector< NBConnection > NBConnectionVector
Definition of a connection vector.
std::vector< std::pair< NBEdge *, NBEdge * > > getEdgesToJoin() const
Definition: NBNode.cpp:1308
bool intersects(const Line &l) const
Definition: Line.cpp:171
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
Definition: NBEdge.cpp:1101
NBEdge * getPossiblySplittedOutgoing(const std::string &edgeid)
Definition: NBNode.cpp:958
unsigned int removeSelfLoops(NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tc)
Removes edges which are both incoming and outgoing into this node.
Definition: NBNode.cpp:311
EdgeVector myOutgoingEdges
Vector of outgoing edges.
Definition: NBNode.h:495
SUMOReal length() const
Returns the length.
void push_back(const PositionVector &p)
Appends all positions from the given vector.
std::string myID
The name of the object.
Definition: Named.h:128
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:362
void addTrafficLight(NBTrafficLightDefinition *tlDef)
Adds a traffic light to the list of traffic lights that control this node.
Definition: NBNode.cpp:250
void extrapolateSecondBy(SUMOReal length)
Definition: Line.cpp:75
bool isNearDistrict() const
Definition: NBNode.cpp:1349
SUMOReal length() const
Definition: Line.cpp:183
std::vector< int > getConnectionLanes(NBEdge *currentOutgoing) const
Returns the list of lanes that may be used to reach the given edge.
Definition: NBEdge.cpp:786
Position myPosition
The position the node lies at.
Definition: NBNode.h:489
std::map< NBConnection, NBConnectionVector > NBConnectionProhibits
Definition of a container for connection block dependencies Includes a list of all connections which ...
void replaceOutgoing(NBEdge *which, NBEdge *by, unsigned int laneOff)
Replaces occurences of the first edge within the list of outgoing by the second Connections are remap...
Definition: NBNode.cpp:755
~ApproachingDivider()
Destructor.
Definition: NBNode.cpp:91
LinkState getLinkState(const NBEdge *incoming, NBEdge *outgoing, int fromLane, bool mayDefinitelyPass, const std::string &tlID) const
Definition: NBNode.cpp:1228
SumoXMLNodeType
Numbers representing special SUMO-XML-attribute values for representing node- (junction-) types used ...
bool isLeftHanded() const
Returns whether the built edges are left-handed.
Definition: NBEdgeCont.h:455
void replaceInConnectionProhibitions(NBEdge *which, NBEdge *by, unsigned int whichLaneOff, unsigned int byLaneOff)
Definition: NBNode.cpp:824
The link is controlled by a tls which is off and blinks, has to brake.
std::vector< NBEdge * > EdgeVector
Definition: NBCont.h:38
void buildInnerEdges()
Definition: NBNode.cpp:1386
EdgeVector * myApproaching
The list of edges that approach the current edge.
Definition: NBNode.h:96
SUMOReal y() const
Returns the y-position.
Definition: Position.h:68
A storage for options typed value containers)
Definition: OptionsCont.h:108
void sub(SUMOReal x, SUMOReal y)
Definition: Line.cpp:203
void erase(NBDistrictCont &dc, NBEdge *edge)
Removes the given edge from the container (deleting it)
Definition: NBEdgeCont.cpp:366
void replaceInConnections(NBEdge *which, NBEdge *by, unsigned int laneOff)
Definition: NBEdge.cpp:864
This is an uncontrolled, major link, may pass.
void mul(SUMOReal val)
Multiplies both positions with the given value.
Definition: Position.h:99
std::deque< int > * spread(const std::vector< int > &approachingLanes, int dest) const
Definition: NBNode.cpp:120
NBEdge * getTo() const
returns the to-edge (end of the connection)
Line getBegLine() const
The connection was computed.
Definition: NBEdge.h:112
Represents a single node (junction) during network building.
Definition: NBNode.h:74
bool removeFully(const std::string id)
Removes a logic definition (and all programs) from the dictionary.
Lane & getLaneStruct(unsigned int lane)
Definition: NBEdge.h:994
bool foes(const NBEdge *const from1, const NBEdge *const to1, const NBEdge *const from2, const NBEdge *const to2) const
Returns the information whether the given flows cross.
Definition: NBRequest.cpp:426
Lanes to lanes - relationships are computed; no recheck is necessary/wished.
Definition: NBEdge.h:101
bool insert(NBTrafficLightDefinition *logic, bool forceInsert=false)
Adds a logic definition to the dictionary.
NBEdge * getTurnDestination() const
Definition: NBEdge.cpp:1889
void addSortedLinkFoes(const NBConnection &mayDrive, const NBConnection &mustStop)
Definition: NBNode.cpp:928
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:70
#define SUMOReal
Definition: config.h:215
Computes lane-2-lane connections.
Definition: NBNode.h:93
bool writeLogic(OutputDevice &into, const bool checkLaneFoes) const
Definition: NBNode.cpp:595
static SUMOReal relAngle(SUMOReal angle1, SUMOReal angle2)
Definition: NBHelpers.cpp:62
void push_back_noDoublePos(const Position &p)
void computeLogic(const NBEdgeCont &ec, OptionsCont &oc)
computes the node's type, logic and traffic light
Definition: NBNode.cpp:556
Position getPolygonCenter() const
Returns the arithmetic of all corner points.
void setConnection(unsigned int lane, NBEdge *destEdge, unsigned int destLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false)
Adds a connection to a certain lane of a certain edge.
Definition: NBEdge.cpp:656
A traffic light logics which must be computed (only nodes/edges are given)
Definition: NBOwnTLDef.h:54
bool foes(const NBEdge *const from1, const NBEdge *const to1, const NBEdge *const from2, const NBEdge *const to2) const
Returns the information whether the given flows cross.
Definition: NBNode.cpp:1094
void invalidateTLS(NBTrafficLightLogicCont &tlCont)
causes the traffic light to be computed anew
Definition: NBNode.cpp:289
void closePolygon()
ensures that the last position equals the first
Lanes to edges - relationships are computed/loaded.
Definition: NBEdge.h:97
NBNode(const std::string &id, const Position &position, SumoXMLNodeType type)
Constructor.
Definition: NBNode.cpp:195
void append(const PositionVector &v)
Position intersectsAt(const Line &l) const
Definition: Line.cpp:165
PositionVector getSubpart(SUMOReal beginOffset, SUMOReal endOffset) const
static void nextCCW(const EdgeVector &edges, EdgeVector::const_iterator &from)
void reshiftPosition(SUMOReal xoff, SUMOReal yoff)
Applies an offset to the node.
Definition: NBNode.cpp:242
void remapRemoved(NBTrafficLightLogicCont &tc, NBEdge *removed, const EdgeVector &incoming, const EdgeVector &outgoing)
Definition: NBNode.cpp:1101
std::pair< unsigned int, unsigned int > getSizes() const
returns the number of the junction's lanes and the number of the junction's links in respect...
Definition: NBRequest.cpp:407
void replaceIncoming(const EdgeVector &which, NBEdge *const by)
Replaces incoming edges from the vector (sinks) by the given edge.
Definition: NBDistrict.cpp:106
SUMOReal getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge's geometry at the given node.
Definition: NBEdge.cpp:1121
bool forbids(const NBEdge *const possProhibitorFrom, const NBEdge *const possProhibitorTo, const NBEdge *const possProhibitedFrom, const NBEdge *const possProhibitedTo, bool regardNonSignalisedLowerPriority) const
Returns the information whether "prohibited" flow must let "prohibitor" flow pass.
Definition: NBNode.cpp:1084
The link has no direction (is a dead end link)
LinkDirection getDirection(const NBEdge *const incoming, const NBEdge *const outgoing) const
Returns the representation of the described stream's direction.
Definition: NBNode.cpp:1182
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:354