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-2013 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  Named(StringUtils::convertUmlaute(id)),
197  myPosition(position),
199 { }
200 
201 
202 NBNode::NBNode(const std::string& id, const Position& position,
203  SumoXMLNodeType type) :
204  Named(StringUtils::convertUmlaute(id)),
205  myPosition(position),
206  myType(type), myDistrict(0), myRequest(0)
207 { }
208 
209 
210 NBNode::NBNode(const std::string& id, const Position& position, NBDistrict* district) :
211  Named(StringUtils::convertUmlaute(id)),
212  myPosition(position),
213  myType(NODETYPE_DISTRICT), myDistrict(district), myRequest(0)
214 { }
215 
216 
218  delete myRequest;
219 }
220 
221 
222 void
224  bool updateEdgeGeometries) {
225  myPosition = position;
226  // patch type
227  myType = type;
230  }
231  if (updateEdgeGeometries) {
232  for (EdgeVector::iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
233  PositionVector geom = (*i)->getGeometry();
234  geom[-1] = myPosition;
235  (*i)->setGeometry(geom);
236  }
237  for (EdgeVector::iterator i = myOutgoingEdges.begin(); i != myOutgoingEdges.end(); i++) {
238  PositionVector geom = (*i)->getGeometry();
239  geom[0] = myPosition;
240  (*i)->setGeometry(geom);
241  }
242  }
243 }
244 
245 
246 
247 // ----------- Applying offset
248 void
250  myPosition.add(xoff, yoff, 0);
251  myPoly.add(xoff, yoff, 0);
252 }
253 
254 
255 // ----------- Methods for dealing with assigned traffic lights
256 void
258  myTrafficLights.insert(tlDef);
261  }
262 }
263 
264 
265 void
267  tlDef->removeNode(this);
268  myTrafficLights.erase(tlDef);
269 }
270 
271 
272 void
274  std::set<NBTrafficLightDefinition*> trafficLights = myTrafficLights; // make a copy because we will modify the original
275  for (std::set<NBTrafficLightDefinition*>::const_iterator i = trafficLights.begin(); i != trafficLights.end(); ++i) {
276  removeTrafficLight(*i);
277  }
278 }
279 
280 
281 bool
283  if (!isTLControlled()) {
284  return false;
285  }
286  for (std::set<NBTrafficLightDefinition*>::const_iterator i = myTrafficLights.begin(); i != myTrafficLights.end(); ++i) {
287  if ((*i)->getID().find("joined") == 0) {
288  return true;
289  }
290  }
291  return false;
292 }
293 
294 
295 void
297  if (isTLControlled()) {
298  std::set<NBTrafficLightDefinition*> newDefs;
299  for (std::set<NBTrafficLightDefinition*>::iterator it = myTrafficLights.begin(); it != myTrafficLights.end(); ++it) {
300  NBTrafficLightDefinition* orig = *it;
301  if (dynamic_cast<NBOwnTLDef*>(orig) != 0) {
302  // this definition will be guessed anyway. no need to invalidate
303  newDefs.insert(orig);
304  } else {
305  const std::string new_id = orig->getID() + "_reguessed";
306  NBTrafficLightDefinition* newDef = new NBOwnTLDef(new_id, orig->getOffset(), orig->getType());
307  if (!tlCont.insert(newDef)) {
308  // the original definition was shared by other nodes and was already invalidated
309  delete newDef;
310  newDef = tlCont.getDefinition(new_id, orig->getProgramID());
311  assert(newDef != 0);
312  }
313  newDefs.insert(newDef);
314  }
315  }
317  for (std::set<NBTrafficLightDefinition*>::iterator it = newDefs.begin(); it != newDefs.end(); ++it) {
318  (*it)->addNode(this);
319  }
320  }
321 }
322 
323 
324 // ----------- Prunning the input
325 unsigned int
327  unsigned int ret = 0;
328  unsigned int pos = 0;
329  EdgeVector::const_iterator j = myIncomingEdges.begin();
330  while (j != myIncomingEdges.end()) {
331  // skip edges which are only incoming and not outgoing
332  if (find(myOutgoingEdges.begin(), myOutgoingEdges.end(), *j) == myOutgoingEdges.end()) {
333  ++j;
334  ++pos;
335  continue;
336  }
337  // an edge with both its origin and destination being the current
338  // node should be removed
339  NBEdge* dummy = *j;
340  WRITE_WARNING(" Removing self-looping edge '" + dummy->getID() + "'");
341  // get the list of incoming edges connected to the self-loop
342  EdgeVector incomingConnected;
343  for (EdgeVector::const_iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
344  if ((*i)->isConnectedTo(dummy) && *i != dummy) {
345  incomingConnected.push_back(*i);
346  }
347  }
348  // get the list of outgoing edges connected to the self-loop
349  EdgeVector outgoingConnected;
350  for (EdgeVector::const_iterator i = myOutgoingEdges.begin(); i != myOutgoingEdges.end(); i++) {
351  if (dummy->isConnectedTo(*i) && *i != dummy) {
352  outgoingConnected.push_back(*i);
353  }
354  }
355  // let the self-loop remap its connections
356  dummy->remapConnections(incomingConnected);
357  remapRemoved(tc, dummy, incomingConnected, outgoingConnected);
358  // delete the self-loop
359  ec.erase(dc, dummy);
360  j = myIncomingEdges.begin() + pos;
361  ++ret;
362  }
363  return ret;
364 }
365 
366 
367 // -----------
368 void
370  assert(edge != 0);
371  if (find(myIncomingEdges.begin(), myIncomingEdges.end(), edge) == myIncomingEdges.end()) {
372  myIncomingEdges.push_back(edge);
373  myAllEdges.push_back(edge);
374  }
375 }
376 
377 
378 void
380  assert(edge != 0);
381  if (find(myOutgoingEdges.begin(), myOutgoingEdges.end(), edge) == myOutgoingEdges.end()) {
382  myOutgoingEdges.push_back(edge);
383  myAllEdges.push_back(edge);
384  }
385 }
386 
387 
388 bool
390  // one in, one out->continuation
391  if (myIncomingEdges.size() == 1 && myOutgoingEdges.size() == 1) {
392  // both must have the same number of lanes
393  return (*(myIncomingEdges.begin()))->getNumLanes() == (*(myOutgoingEdges.begin()))->getNumLanes();
394  }
395  // two in and two out and both in reverse direction
396  if (myIncomingEdges.size() == 2 && myOutgoingEdges.size() == 2) {
397  for (EdgeVector::const_iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
398  NBEdge* in = *i;
399  EdgeVector::const_iterator opposite = find_if(myOutgoingEdges.begin(), myOutgoingEdges.end(), NBContHelper::opposite_finder(in, this));
400  // must have an opposite edge
401  if (opposite == myOutgoingEdges.end()) {
402  return false;
403  }
404  // both must have the same number of lanes
406  if (in->getNumLanes() != (*opposite)->getNumLanes()) {
407  return false;
408  }
409  }
410  return true;
411  }
412  // nope
413  return false;
414 }
415 
416 
419  NBEdge* toE, int toL, int numPoints) const {
420  if (fromL >= (int) fromE->getNumLanes()) {
421  throw ProcessError("Connection '" + fromE->getID() + "_" + toString(fromL) + "->" + toE->getID() + "_" + toString(toL) + "' starts at a not existing lane.");
422  }
423  if (toL >= (int) toE->getNumLanes()) {
424  throw ProcessError("Connection '" + fromE->getID() + "_" + toString(fromL) + "->" + toE->getID() + "_" + toString(toL) + "' yields in a not existing lane.");
425  }
426  bool noSpline = false;
427  PositionVector ret;
428  PositionVector init;
429  Position beg = fromE->getLaneShape(fromL).back();
430  Position end = toE->getLaneShape(toL).front();
431  Position intersection;
432  unsigned int noInitialPoints = 0;
433  if (beg.distanceTo(end) <= POSITION_EPS) {
434  noSpline = true;
435  } else {
436  if (fromE->getTurnDestination() == toE) {
437  // turnarounds:
438  // - end of incoming lane
439  // - position between incoming/outgoing end/begin shifted by the distance orthogonally
440  // - begin of outgoing lane
441  noInitialPoints = 3;
442  init.push_back(beg);
443  Line straightConn(fromE->getLaneShape(fromL)[-1], toE->getLaneShape(toL)[0]);
444  Position straightCenter = straightConn.getPositionAtDistance((SUMOReal) straightConn.length() / (SUMOReal) 2.);
445  Position center = straightCenter;//.add(straightCenter);
446  Line cross(straightConn);
447  cross.sub(cross.p1().x(), cross.p1().y());
448  cross.rotateAtP1(M_PI / 2);
449  center.sub(cross.p2());
450  init.push_back(center);
451  init.push_back(end);
452  } else {
453  const SUMOReal angle = fabs(fromE->getLaneShape(fromL).getEndLine().atan2Angle() - toE->getLaneShape(toL).getBegLine().atan2Angle());
454  if (angle < M_PI / 4. || angle > 7. / 4.*M_PI) {
455  // very low angle: almost straight
456  noInitialPoints = 4;
457  init.push_back(beg);
458  Line begL = fromE->getLaneShape(fromL).getEndLine();
459  begL.extrapolateSecondBy(100);
460  Line endL = toE->getLaneShape(toL).getBegLine();
461  endL.extrapolateFirstBy(100);
462  SUMOReal distance = beg.distanceTo(end);
463  if (distance > 10) {
464  {
465  SUMOReal off1 = fromE->getLaneShape(fromL).getEndLine().length() + (SUMOReal) 5. * (SUMOReal) fromE->getNumLanes();
466  off1 = MIN2(off1, (SUMOReal)(fromE->getLaneShape(fromL).getEndLine().length() + distance / 2.));
467  Position tmp = begL.getPositionAtDistance(off1);
468  init.push_back(tmp);
469  }
470  {
471  SUMOReal off1 = (SUMOReal) 100. - (SUMOReal) 5. * (SUMOReal) toE->getNumLanes();
472  off1 = MAX2(off1, (SUMOReal)(100. - distance / 2.));
473  Position tmp = endL.getPositionAtDistance(off1);
474  init.push_back(tmp);
475  }
476  } else {
477  noSpline = true;
478  }
479  init.push_back(end);
480  } else {
481  // turning
482  // - end of incoming lane
483  // - intersection of the extrapolated lanes
484  // - begin of outgoing lane
485  // attention: if there is no intersection, use a straight line
486  noInitialPoints = 3;
487  init.push_back(beg);
488  Line begL = fromE->getLaneShape(fromL).getEndLine();
489  Line endL = toE->getLaneShape(toL).getBegLine();
490  bool check = !begL.p1().almostSame(begL.p2()) && !endL.p1().almostSame(endL.p2());
491  if (check) {
492  begL.extrapolateSecondBy(100);
493  endL.extrapolateFirstBy(100);
494  } else {
495  WRITE_WARNING("Could not use edge geometry for internal lane, node '" + getID() + "'.");
496  }
497  if (!check || !begL.intersects(endL)) {
498  noSpline = true;
499  } else {
500  init.push_back(begL.intersectsAt(endL));
501  }
502  init.push_back(end);
503  }
504  }
505  }
506  //
507  if (noSpline) {
508  ret.push_back(fromE->getLaneShape(fromL).back());
509  ret.push_back(toE->getLaneShape(toL).front());
510  } else {
511  SUMOReal* def = new SUMOReal[1 + noInitialPoints * 3];
512  for (int i = 0; i < (int) init.size(); ++i) {
513  // starts at index 1
514  def[i * 3 + 1] = init[i].x();
515  def[i * 3 + 2] = 0;
516  def[i * 3 + 3] = init[i].y();
517  }
518  SUMOReal* ret_buf = new SUMOReal[numPoints * 3 + 1];
519  bezier(noInitialPoints, def, numPoints, ret_buf);
520  delete[] def;
521  Position prev;
522  for (int i = 0; i < (int) numPoints; i++) {
523  Position current(ret_buf[i * 3 + 1], ret_buf[i * 3 + 3]);
524  if (prev != current) {
525  ret.push_back(current);
526  }
527  prev = current;
528  }
529  delete[] ret_buf;
530  }
531  const NBEdge::Lane& lane = fromE->getLaneStruct(fromL);
532  if (lane.offset > 0) {
533  PositionVector beg = lane.shape.getSubpart(lane.shape.length() - lane.offset, lane.shape.length());;
534  beg.append(ret);
535  ret = beg;
536  }
537  return ret;
538 }
539 
540 
541 bool
542 NBNode::needsCont(NBEdge* fromE, NBEdge* toE, NBEdge* otherFromE, NBEdge* otherToE, const NBEdge::Connection& c) const {
544  return false;
545  }
546  if (fromE == otherFromE) {
547  // ignore same edge links
548  return false;
549  }
550  if (!foes(otherFromE, otherToE, fromE, toE)) {
551  // if they do not cross, no waiting place is needed
552  return false;
553  }
554  LinkDirection d1 = getDirection(fromE, toE);
555  LinkDirection d2 = getDirection(otherFromE, otherToE);
556  bool thisLeft = (d1 == LINKDIR_LEFT || d1 == LINKDIR_TURN);
557  bool otherLeft = (d2 == LINKDIR_LEFT || d2 == LINKDIR_TURN);
558  bool bothLeft = thisLeft && otherLeft;
559  if (c.tlID != "" && !bothLeft) {
560  // tls-controlled links will have space
561  return true;
562  }
563  if (fromE->getJunctionPriority(this) > 0 && otherFromE->getJunctionPriority(this) > 0) {
564  return mustBrake(fromE, toE, c.toLane);
565  }
566  return false;
567 }
568 
569 
570 void
572  delete myRequest; // possibly recomputation step
573  myRequest = 0;
574  if (myIncomingEdges.size() == 0 || myOutgoingEdges.size() == 0) {
575  // no logic if nothing happens here
577  return;
578  }
579  // check whether the node was set to be unregulated by the user
580  if (oc.getBool("keep-nodes-unregulated") || oc.isInStringVector("keep-nodes-unregulated.explicit", getID())
581  || (oc.getBool("keep-nodes-unregulated.district-nodes") && (isNearDistrict() || isDistrict()))) {
583  return;
584  }
585  // compute the logic if necessary or split the junction
587  // build the request
588  myRequest = new NBRequest(ec, this,
590  // check whether it is not too large
591  unsigned int numConnections = myRequest->getSizes().second;
592  if (numConnections >= 64) {
593  // yep -> make it untcontrolled, warn
594  WRITE_WARNING("Junction '" + getID() + "' is too complicated (#links>64); will be set to unregulated.");
595  delete myRequest;
596  myRequest = 0;
598  } else if (numConnections == 0) {
599  delete myRequest;
600  myRequest = 0;
602  } else {
604  }
605  }
606 }
607 
608 
609 bool
610 NBNode::writeLogic(OutputDevice& into, const bool checkLaneFoes) const {
611  if (myRequest) {
612  myRequest->writeLogic(myID, into, checkLaneFoes);
613  return true;
614  }
615  return false;
616 }
617 
618 
619 void
620 NBNode::computeNodeShape(bool leftHand) {
621  if (myIncomingEdges.size() == 0 && myOutgoingEdges.size() == 0) {
622  return;
623  }
624  try {
625  NBNodeShapeComputer computer(*this);
626  myPoly = computer.compute(leftHand);
627  } catch (InvalidArgument&) {
628  WRITE_WARNING("For node '" + getID() + "': could not compute shape.");
629  // make sure our shape is not empty because our XML schema forbids empty attributes
630  myPoly.clear();
632  }
633 }
634 
635 
636 void
638  // special case a):
639  // one in, one out, the outgoing has one lane more
640  if (myIncomingEdges.size() == 1 && myOutgoingEdges.size() == 1
641  && myIncomingEdges[0]->getNumLanes() == myOutgoingEdges[0]->getNumLanes() - 1
642  && myIncomingEdges[0] != myOutgoingEdges[0]
643  && myIncomingEdges[0]->isConnectedTo(myOutgoingEdges[0])) {
644 
645  NBEdge* incoming = myIncomingEdges[0];
646  NBEdge* outgoing = myOutgoingEdges[0];
647  // check if it's not the turnaround
648  if (incoming->getTurnDestination() == outgoing) {
649  // will be added later or not...
650  return;
651  }
652  for (int i = 0; i < (int) incoming->getNumLanes(); ++i) {
653  incoming->setConnection(i, outgoing, i + 1, NBEdge::L2L_COMPUTED);
654  }
655  incoming->setConnection(0, outgoing, 0, NBEdge::L2L_COMPUTED);
656  return;
657  }
658  // special case b):
659  // two in, one out, the outgoing has the same number of lanes as the sum of the incoming
660  // --> highway on-ramp
661  bool check = false;
662  if (myIncomingEdges.size() == 2 && myOutgoingEdges.size() == 1) {
663  check = myIncomingEdges[0]->getNumLanes() + myIncomingEdges[1]->getNumLanes() == myOutgoingEdges[0]->getNumLanes();
664  check &= (myIncomingEdges[0]->getStep() <= NBEdge::LANES2EDGES);
665  check &= (myIncomingEdges[1]->getStep() <= NBEdge::LANES2EDGES);
666  check &= myIncomingEdges[0] != myOutgoingEdges[0];
667  check &= myIncomingEdges[1] != myOutgoingEdges[0];
668  check &= myIncomingEdges[0]->isConnectedTo(myOutgoingEdges[0]);
669  check &= myIncomingEdges[1]->isConnectedTo(myOutgoingEdges[0]);
670  }
671  if (check) {
672  NBEdge* inc1 = myIncomingEdges[0];
673  NBEdge* inc2 = myIncomingEdges[1];
674  // for internal: check which one is the rightmost
675  SUMOReal a1 = inc1->getAngleAtNode(this);
676  SUMOReal a2 = inc2->getAngleAtNode(this);
679  if (ccw > cw) {
680  std::swap(inc1, inc2);
681  }
682  inc1->addLane2LaneConnections(0, myOutgoingEdges[0], 0, inc1->getNumLanes(), NBEdge::L2L_VALIDATED, true, true);
683  inc2->addLane2LaneConnections(0, myOutgoingEdges[0], inc1->getNumLanes(), inc2->getNumLanes(), NBEdge::L2L_VALIDATED, true, true);
684  return;
685  }
686  // special case c):
687  // one in, two out, the incoming has the same number of lanes as the sum of the outgoing
688  // --> highway off-ramp
689  check = false;
690  if (myIncomingEdges.size() == 1 && myOutgoingEdges.size() == 2) {
691  check = myIncomingEdges[0]->getNumLanes() == myOutgoingEdges[1]->getNumLanes() + myOutgoingEdges[0]->getNumLanes();
692  check &= (myIncomingEdges[0]->getStep() <= NBEdge::LANES2EDGES);
693  check &= myIncomingEdges[0] != myOutgoingEdges[0];
694  check &= myIncomingEdges[0] != myOutgoingEdges[1];
695  check &= myIncomingEdges[0]->isConnectedTo(myOutgoingEdges[0]);
696  check &= myIncomingEdges[0]->isConnectedTo(myOutgoingEdges[1]);
697  }
698  if (check) {
699  NBEdge* out1 = myOutgoingEdges[0];
700  NBEdge* out2 = myOutgoingEdges[1];
701  // for internal: check which one is the rightmost
703  std::swap(out1, out2);
704  }
705  myIncomingEdges[0]->addLane2LaneConnections(0, out1, 0, out1->getNumLanes(), NBEdge::L2L_VALIDATED, true, true);
706  myIncomingEdges[0]->addLane2LaneConnections(out1->getNumLanes(), out2, 0, out2->getNumLanes(), NBEdge::L2L_VALIDATED, false, true);
707  return;
708  }
709 
710  // go through this node's outgoing edges
711  // for every outgoing edge, compute the distribution of the node's
712  // incoming edges on this edge when approaching this edge
713  // the incoming edges' steps will then also be marked as LANE2LANE_RECHECK...
714  EdgeVector::reverse_iterator i;
715  for (i = myOutgoingEdges.rbegin(); i != myOutgoingEdges.rend(); i++) {
716  NBEdge* currentOutgoing = *i;
717  // get the information about edges that do approach this edge
718  EdgeVector* approaching = getEdgesThatApproach(currentOutgoing);
719  if (approaching->size() != 0) {
720  ApproachingDivider divider(approaching, currentOutgoing);
721  Bresenham::compute(&divider, static_cast<unsigned int>(approaching->size()),
722  currentOutgoing->getNumLanes());
723  }
724  delete approaching;
725  }
726  // ... but we may have the case that there are no outgoing edges
727  // In this case, we have to mark the incoming edges as being in state
728  // LANE2LANE( not RECHECK) by hand
729  if (myOutgoingEdges.size() == 0) {
730  for (i = myIncomingEdges.rbegin(); i != myIncomingEdges.rend(); i++) {
731  (*i)->markAsInLane2LaneState();
732  }
733  }
734 }
735 
736 
737 EdgeVector*
739  // get the position of the node to get the approaching nodes of
740  EdgeVector::const_iterator i = find(myAllEdges.begin(),
741  myAllEdges.end(), currentOutgoing);
742  // get the first possible approaching edge
744  // go through the list of edges clockwise and add the edges
745  EdgeVector* approaching = new EdgeVector();
746  for (; *i != currentOutgoing;) {
747  // check only incoming edges
748  if ((*i)->getToNode() == this && (*i)->getTurnDestination() != currentOutgoing) {
749  std::vector<int> connLanes = (*i)->getConnectionLanes(currentOutgoing);
750  if (connLanes.size() != 0) {
751  approaching->push_back(*i);
752  }
753  }
755  }
756  return approaching;
757 }
758 
759 
760 void
761 NBNode::replaceOutgoing(NBEdge* which, NBEdge* by, unsigned int laneOff) {
762  // replace the edge in the list of outgoing nodes
763  EdgeVector::iterator i = find(myOutgoingEdges.begin(), myOutgoingEdges.end(), which);
764  if (i != myOutgoingEdges.end()) {
765  (*i) = by;
766  i = find(myAllEdges.begin(), myAllEdges.end(), which);
767  (*i) = by;
768  }
769  // replace the edge in connections of incoming edges
770  for (i = myIncomingEdges.begin(); i != myIncomingEdges.end(); ++i) {
771  (*i)->replaceInConnections(which, by, laneOff);
772  }
773  // replace within the connetion prohibition dependencies
774  replaceInConnectionProhibitions(which, by, 0, laneOff);
775 }
776 
777 
778 void
780  // replace edges
781  unsigned int laneOff = 0;
782  for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
783  replaceOutgoing(*i, by, laneOff);
784  laneOff += (*i)->getNumLanes();
785  }
786  // removed SUMOReal occurences
788  // check whether this node belongs to a district and the edges
789  // must here be also remapped
790  if (myDistrict != 0) {
791  myDistrict->replaceOutgoing(which, by);
792  }
793 }
794 
795 
796 void
797 NBNode::replaceIncoming(NBEdge* which, NBEdge* by, unsigned int laneOff) {
798  // replace the edge in the list of incoming nodes
799  EdgeVector::iterator i = find(myIncomingEdges.begin(), myIncomingEdges.end(), which);
800  if (i != myIncomingEdges.end()) {
801  (*i) = by;
802  i = find(myAllEdges.begin(), myAllEdges.end(), which);
803  (*i) = by;
804  }
805  // replace within the connetion prohibition dependencies
806  replaceInConnectionProhibitions(which, by, laneOff, 0);
807 }
808 
809 
810 void
812  // replace edges
813  unsigned int laneOff = 0;
814  for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
815  replaceIncoming(*i, by, laneOff);
816  laneOff += (*i)->getNumLanes();
817  }
818  // removed SUMOReal occurences
820  // check whether this node belongs to a district and the edges
821  // must here be also remapped
822  if (myDistrict != 0) {
823  myDistrict->replaceIncoming(which, by);
824  }
825 }
826 
827 
828 
829 void
831  unsigned int whichLaneOff, unsigned int byLaneOff) {
832  // replace in keys
833  NBConnectionProhibits::iterator j = myBlockedConnections.begin();
834  while (j != myBlockedConnections.end()) {
835  bool changed = false;
836  NBConnection c = (*j).first;
837  if (c.replaceFrom(which, whichLaneOff, by, byLaneOff)) {
838  changed = true;
839  }
840  if (c.replaceTo(which, whichLaneOff, by, byLaneOff)) {
841  changed = true;
842  }
843  if (changed) {
844  myBlockedConnections[c] = (*j).second;
845  myBlockedConnections.erase(j);
846  j = myBlockedConnections.begin();
847  } else {
848  j++;
849  }
850  }
851  // replace in values
852  for (j = myBlockedConnections.begin(); j != myBlockedConnections.end(); j++) {
853  NBConnectionVector& prohibiting = (*j).second;
854  for (NBConnectionVector::iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
855  NBConnection& sprohibiting = *k;
856  sprohibiting.replaceFrom(which, whichLaneOff, by, byLaneOff);
857  sprohibiting.replaceTo(which, whichLaneOff, by, byLaneOff);
858  }
859  }
860 }
861 
862 
863 
864 void
866  unsigned int i, j;
867  // check incoming
868  for (i = 0; myIncomingEdges.size() > 0 && i < myIncomingEdges.size() - 1; i++) {
869  j = i + 1;
870  while (j < myIncomingEdges.size()) {
871  if (myIncomingEdges[i] == myIncomingEdges[j]) {
872  myIncomingEdges.erase(myIncomingEdges.begin() + j);
873  } else {
874  j++;
875  }
876  }
877  }
878  // check outgoing
879  for (i = 0; myOutgoingEdges.size() > 0 && i < myOutgoingEdges.size() - 1; i++) {
880  j = i + 1;
881  while (j < myOutgoingEdges.size()) {
882  if (myOutgoingEdges[i] == myOutgoingEdges[j]) {
883  myOutgoingEdges.erase(myOutgoingEdges.begin() + j);
884  } else {
885  j++;
886  }
887  }
888  }
889  // check all
890  for (i = 0; myAllEdges.size() > 0 && i < myAllEdges.size() - 1; i++) {
891  j = i + 1;
892  while (j < myAllEdges.size()) {
893  if (myAllEdges[i] == myAllEdges[j]) {
894  myAllEdges.erase(myAllEdges.begin() + j);
895  } else {
896  j++;
897  }
898  }
899  }
900 }
901 
902 
903 bool
904 NBNode::hasIncoming(const NBEdge* const e) const {
905  return find(myIncomingEdges.begin(), myIncomingEdges.end(), e) != myIncomingEdges.end();
906 }
907 
908 
909 bool
910 NBNode::hasOutgoing(const NBEdge* const e) const {
911  return find(myOutgoingEdges.begin(), myOutgoingEdges.end(), e) != myOutgoingEdges.end();
912 }
913 
914 
915 NBEdge*
917  EdgeVector edges = myIncomingEdges;
918  if (find(edges.begin(), edges.end(), e) != edges.end()) {
919  edges.erase(find(edges.begin(), edges.end(), e));
920  }
921  if (edges.size() == 0) {
922  return 0;
923  }
924  if (e->getToNode() == this) {
925  sort(edges.begin(), edges.end(), NBContHelper::edge_opposite_direction_sorter(e, this));
926  } else {
927  sort(edges.begin(), edges.end(), NBContHelper::edge_similar_direction_sorter(e));
928  }
929  return edges[0];
930 }
931 
932 
933 void
935  const NBConnection& mustStop) {
936  if (mayDrive.getFrom() == 0 ||
937  mayDrive.getTo() == 0 ||
938  mustStop.getFrom() == 0 ||
939  mustStop.getTo() == 0) {
940 
941  WRITE_WARNING("Something went wrong during the building of a connection...");
942  return; // !!! mark to recompute connections
943  }
944  NBConnectionVector conn = myBlockedConnections[mustStop];
945  conn.push_back(mayDrive);
946  myBlockedConnections[mustStop] = conn;
947 }
948 
949 
950 NBEdge*
951 NBNode::getPossiblySplittedIncoming(const std::string& edgeid) {
952  unsigned int size = (unsigned int) edgeid.length();
953  for (EdgeVector::iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
954  std::string id = (*i)->getID();
955  if (id.substr(0, size) == edgeid) {
956  return *i;
957  }
958  }
959  return 0;
960 }
961 
962 
963 NBEdge*
964 NBNode::getPossiblySplittedOutgoing(const std::string& edgeid) {
965  unsigned int size = (unsigned int) edgeid.length();
966  for (EdgeVector::iterator i = myOutgoingEdges.begin(); i != myOutgoingEdges.end(); i++) {
967  std::string id = (*i)->getID();
968  if (id.substr(0, size) == edgeid) {
969  return *i;
970  }
971  }
972  return 0;
973 }
974 
975 
976 void
977 NBNode::removeEdge(NBEdge* edge, bool removeFromConnections) {
978  EdgeVector::iterator i = find(myAllEdges.begin(), myAllEdges.end(), edge);
979  if (i != myAllEdges.end()) {
980  myAllEdges.erase(i);
981  i = find(myOutgoingEdges.begin(), myOutgoingEdges.end(), edge);
982  if (i != myOutgoingEdges.end()) {
983  myOutgoingEdges.erase(i);
984  } else {
985  i = find(myIncomingEdges.begin(), myIncomingEdges.end(), edge);
986  if (i != myIncomingEdges.end()) {
987  myIncomingEdges.erase(i);
988  } else {
989  // edge must have been either incoming or outgoing
990  assert(false);
991  }
992  }
993  if (removeFromConnections) {
994  for (i = myAllEdges.begin(); i != myAllEdges.end(); ++i) {
995  (*i)->removeFromConnections(edge);
996  }
997  }
998  }
999 }
1000 
1001 
1002 Position
1004  Position pos(0, 0);
1005  EdgeVector::const_iterator i;
1006  for (i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
1007  NBNode* conn = (*i)->getFromNode();
1008  Position toAdd = conn->getPosition();
1009  toAdd.sub(myPosition);
1010  toAdd.mul((SUMOReal) 1.0 / sqrt(toAdd.x()*toAdd.x() + toAdd.y()*toAdd.y()));
1011  pos.add(toAdd);
1012  }
1013  for (i = myOutgoingEdges.begin(); i != myOutgoingEdges.end(); i++) {
1014  NBNode* conn = (*i)->getToNode();
1015  Position toAdd = conn->getPosition();
1016  toAdd.sub(myPosition);
1017  toAdd.mul((SUMOReal) 1.0 / sqrt(toAdd.x()*toAdd.x() + toAdd.y()*toAdd.y()));
1018  pos.add(toAdd);
1019  }
1020  pos.mul((SUMOReal) - 1.0 / (myIncomingEdges.size() + myOutgoingEdges.size()));
1021  if (pos.x() == 0 && pos.y() == 0) {
1022  pos = Position(1, 0);
1023  }
1024  pos.norm2d();
1025  return pos;
1026 }
1027 
1028 
1029 
1030 void
1032  for (EdgeVector::const_iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
1033  (*i)->invalidateConnections();
1034  }
1035 }
1036 
1037 
1038 void
1040  for (EdgeVector::const_iterator i = myOutgoingEdges.begin(); i != myOutgoingEdges.end(); i++) {
1041  (*i)->invalidateConnections();
1042  }
1043 }
1044 
1045 
1046 bool
1047 NBNode::mustBrake(const NBEdge* const from, const NBEdge* const to, int /* toLane */) const {
1048  // check whether it is participant to a traffic light
1049  // - controlled links are set by the traffic lights, not the normal
1050  // right-of-way rules
1051  // - uncontrolled participants (spip lanes etc.) should always break
1052  if (myTrafficLights.size() != 0) {
1053  // ok, we have a traffic light, return true by now, it will be later
1054  // controlled by the tls
1055  return true;
1056  }
1057  // unregulated->does not need to brake
1058  if (myRequest == 0) {
1059  return false;
1060  }
1061  // vehicles which do not have a following lane must always decelerate to the end
1062  if (to == 0) {
1063  return true;
1064  }
1065  // check whether any other connection on this node prohibits this connection
1066  return myRequest->mustBrake(from, to);
1067 }
1068 
1069 
1070 bool
1071 NBNode::isLeftMover(const NBEdge* const from, const NBEdge* const to) const {
1072  // when the junction has only one incoming edge, there are no
1073  // problems caused by left blockings
1074  if (myIncomingEdges.size() == 1 || myOutgoingEdges.size() == 1) {
1075  return false;
1076  }
1077  SUMOReal fromAngle = from->getAngleAtNode(this);
1078  SUMOReal toAngle = to->getAngleAtNode(this);
1079  SUMOReal cw = GeomHelper::getCWAngleDiff(fromAngle, toAngle);
1080  SUMOReal ccw = GeomHelper::getCCWAngleDiff(fromAngle, toAngle);
1081  std::vector<NBEdge*>::const_iterator i = std::find(myAllEdges.begin(), myAllEdges.end(), from);
1082  do {
1084  } while ((!hasOutgoing(*i) || from->isTurningDirectionAt(this, *i)) && *i != from);
1085  return cw < ccw && (*i) == to && myOutgoingEdges.size() > 2;
1086 }
1087 
1088 
1089 bool
1090 NBNode::forbids(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,
1091  const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo,
1092  bool regardNonSignalisedLowerPriority) const {
1093  return myRequest != 0 && myRequest->forbids(possProhibitorFrom, possProhibitorTo,
1094  possProhibitedFrom, possProhibitedTo,
1095  regardNonSignalisedLowerPriority);
1096 }
1097 
1098 
1099 bool
1100 NBNode::foes(const NBEdge* const from1, const NBEdge* const to1,
1101  const NBEdge* const from2, const NBEdge* const to2) const {
1102  return myRequest != 0 && myRequest->foes(from1, to1, from2, to2);
1103 }
1104 
1105 
1106 void
1108  NBEdge* removed, const EdgeVector& incoming,
1109  const EdgeVector& outgoing) {
1110  assert(find(incoming.begin(), incoming.end(), removed) == incoming.end());
1111  bool changed = true;
1112  while (changed) {
1113  changed = false;
1114  NBConnectionProhibits blockedConnectionsTmp = myBlockedConnections;
1115  NBConnectionProhibits blockedConnectionsNew;
1116  // remap in connections
1117  for (NBConnectionProhibits::iterator i = blockedConnectionsTmp.begin(); i != blockedConnectionsTmp.end(); i++) {
1118  const NBConnection& blocker = (*i).first;
1119  const NBConnectionVector& blocked = (*i).second;
1120  // check the blocked connections first
1121  // check whether any of the blocked must be changed
1122  bool blockedChanged = false;
1123  NBConnectionVector newBlocked;
1124  NBConnectionVector::const_iterator j;
1125  for (j = blocked.begin(); j != blocked.end(); j++) {
1126  const NBConnection& sblocked = *j;
1127  if (sblocked.getFrom() == removed || sblocked.getTo() == removed) {
1128  blockedChanged = true;
1129  }
1130  }
1131  // adapt changes if so
1132  for (j = blocked.begin(); blockedChanged && j != blocked.end(); j++) {
1133  const NBConnection& sblocked = *j;
1134  if (sblocked.getFrom() == removed && sblocked.getTo() == removed) {
1135  /* for(EdgeVector::const_iterator k=incoming.begin(); k!=incoming.end(); k++) {
1136  !!! newBlocked.push_back(NBConnection(*k, *k));
1137  }*/
1138  } else if (sblocked.getFrom() == removed) {
1139  assert(sblocked.getTo() != removed);
1140  for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
1141  newBlocked.push_back(NBConnection(*k, sblocked.getTo()));
1142  }
1143  } else if (sblocked.getTo() == removed) {
1144  assert(sblocked.getFrom() != removed);
1145  for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
1146  newBlocked.push_back(NBConnection(sblocked.getFrom(), *k));
1147  }
1148  } else {
1149  newBlocked.push_back(NBConnection(sblocked.getFrom(), sblocked.getTo()));
1150  }
1151  }
1152  if (blockedChanged) {
1153  blockedConnectionsNew[blocker] = newBlocked;
1154  changed = true;
1155  }
1156  // if the blocked were kept
1157  else {
1158  if (blocker.getFrom() == removed && blocker.getTo() == removed) {
1159  changed = true;
1160  /* for(EdgeVector::const_iterator k=incoming.begin(); k!=incoming.end(); k++) {
1161  !!! blockedConnectionsNew[NBConnection(*k, *k)] = blocked;
1162  }*/
1163  } else if (blocker.getFrom() == removed) {
1164  assert(blocker.getTo() != removed);
1165  changed = true;
1166  for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
1167  blockedConnectionsNew[NBConnection(*k, blocker.getTo())] = blocked;
1168  }
1169  } else if (blocker.getTo() == removed) {
1170  assert(blocker.getFrom() != removed);
1171  changed = true;
1172  for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
1173  blockedConnectionsNew[NBConnection(blocker.getFrom(), *k)] = blocked;
1174  }
1175  } else {
1176  blockedConnectionsNew[blocker] = blocked;
1177  }
1178  }
1179  }
1180  myBlockedConnections = blockedConnectionsNew;
1181  }
1182  // remap in traffic lights
1183  tc.remapRemoved(removed, incoming, outgoing);
1184 }
1185 
1186 
1188 NBNode::getDirection(const NBEdge* const incoming, const NBEdge* const outgoing) const {
1189  // ok, no connection at all -> dead end
1190  if (outgoing == 0) {
1191  return LINKDIR_NODIR;
1192  }
1193  // turning direction
1194  if (incoming->isTurningDirectionAt(this, outgoing)) {
1195  return LINKDIR_TURN;
1196  }
1197  // get the angle between incoming/outgoing at the junction
1198  SUMOReal angle =
1199  NBHelpers::normRelAngle(incoming->getAngleAtNode(this), outgoing->getAngleAtNode(this));
1200  // ok, should be a straight connection
1201  if (abs((int) angle) + 1 < 45) {
1202  return LINKDIR_STRAIGHT;
1203  }
1204 
1205  // check for left and right, first
1206  if (angle > 0) {
1207  // check whether any other edge goes further to the right
1208  EdgeVector::const_iterator i =
1209  find(myAllEdges.begin(), myAllEdges.end(), outgoing);
1211  while ((*i) != incoming) {
1212  if ((*i)->getFromNode() == this) {
1213  return LINKDIR_PARTRIGHT;
1214  }
1216  }
1217  return LINKDIR_RIGHT;
1218  }
1219  // check whether any other edge goes further to the left
1220  EdgeVector::const_iterator i =
1221  find(myAllEdges.begin(), myAllEdges.end(), outgoing);
1223  while ((*i) != incoming) {
1224  if ((*i)->getFromNode() == this && !incoming->isTurningDirectionAt(this, *i)) {
1225  return LINKDIR_PARTLEFT;
1226  }
1228  }
1229  return LINKDIR_LEFT;
1230 }
1231 
1232 
1233 LinkState
1234 NBNode::getLinkState(const NBEdge* incoming, NBEdge* outgoing, int fromlane,
1235  bool mayDefinitelyPass, const std::string& tlID) const {
1236  if (tlID != "") {
1238  }
1239  if (outgoing == 0) { // always off
1241  }
1243  return LINKSTATE_EQUAL; // all the same
1244  }
1245  if (myType == NODETYPE_ALLWAY_STOP) {
1246  return LINKSTATE_ALLWAY_STOP; // all drive, first one to arrive may drive first
1247  }
1248  if ((!incoming->isInnerEdge() && mustBrake(incoming, outgoing, fromlane)) && !mayDefinitelyPass) {
1249  return myType == NODETYPE_PRIORITY_STOP ? LINKSTATE_STOP : LINKSTATE_MINOR; // minor road
1250  }
1251  // traffic lights are not regarded here
1252  return LINKSTATE_MAJOR;
1253 }
1254 
1255 
1256 bool
1258  // check whether this node is included in a traffic light
1259  if (myTrafficLights.size() != 0) {
1260  return false;
1261  }
1262  EdgeVector::const_iterator i;
1263  // one in, one out -> just a geometry ...
1264  if (myOutgoingEdges.size() == 1 && myIncomingEdges.size() == 1) {
1265  // ... if types match ...
1266  if (!myIncomingEdges[0]->expandableBy(myOutgoingEdges[0])) {
1267  return false;
1268  }
1269  //
1270  return myIncomingEdges[0]->getFromNode() != myOutgoingEdges[0]->getToNode();
1271  }
1272  // two in, two out -> may be something else
1273  if (myOutgoingEdges.size() == 2 && myIncomingEdges.size() == 2) {
1274  // check whether the origin nodes of the incoming edges differ
1275  std::set<NBNode*> origSet;
1276  for (i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
1277  origSet.insert((*i)->getFromNode());
1278  }
1279  if (origSet.size() < 2) {
1280  return false;
1281  }
1282  // check whether this node is an intermediate node of
1283  // a two-directional street
1284  for (i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
1285  // try to find the opposite direction
1286  NBNode* origin = (*i)->getFromNode();
1287  // find the back direction of the current edge
1288  EdgeVector::const_iterator j =
1289  find_if(myOutgoingEdges.begin(), myOutgoingEdges.end(),
1291  // check whether the back direction exists
1292  if (j != myOutgoingEdges.end()) {
1293  // check whether the edge from the backdirection (must be
1294  // the counter-clockwise one) may be joined with the current
1296  // check whether the types allow joining
1297  if (!(*i)->expandableBy(*j)) {
1298  return false;
1299  }
1300  } else {
1301  // ok, at least one outgoing edge is not an opposite
1302  // of an incoming one
1303  return false;
1304  }
1305  }
1306  return true;
1307  }
1308  // ok, a real node
1309  return false;
1310 }
1311 
1312 
1313 std::vector<std::pair<NBEdge*, NBEdge*> >
1315  assert(checkIsRemovable());
1316  std::vector<std::pair<NBEdge*, NBEdge*> > ret;
1317  // one in, one out-case
1318  if (myOutgoingEdges.size() == 1 && myIncomingEdges.size() == 1) {
1319  ret.push_back(
1320  std::pair<NBEdge*, NBEdge*>(
1322  return ret;
1323  }
1324  // two in, two out-case
1325  for (EdgeVector::const_iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
1326  NBNode* origin = (*i)->getFromNode();
1327  EdgeVector::const_iterator j =
1328  find_if(myOutgoingEdges.begin(), myOutgoingEdges.end(),
1331  ret.push_back(std::pair<NBEdge*, NBEdge*>(*i, *j));
1332  }
1333  return ret;
1334 }
1335 
1336 
1337 const PositionVector&
1339  return myPoly;
1340 }
1341 
1342 
1343 NBEdge*
1345  for (EdgeVector::const_iterator i = myOutgoingEdges.begin(); i != myOutgoingEdges.end(); i++) {
1346  if ((*i)->getToNode() == n) {
1347  return (*i);
1348  }
1349  }
1350  return 0;
1351 }
1352 
1353 
1354 bool
1356  if (isDistrict()) {
1357  return false;
1358  }
1359  EdgeVector edges;
1360  copy(getIncomingEdges().begin(), getIncomingEdges().end(),
1361  back_inserter(edges));
1362  copy(getOutgoingEdges().begin(), getOutgoingEdges().end(),
1363  back_inserter(edges));
1364  for (EdgeVector::const_iterator j = edges.begin(); j != edges.end(); ++j) {
1365  NBEdge* t = *j;
1366  NBNode* other = 0;
1367  if (t->getToNode() == this) {
1368  other = t->getFromNode();
1369  } else {
1370  other = t->getToNode();
1371  }
1372  EdgeVector edges2;
1373  copy(other->getIncomingEdges().begin(), other->getIncomingEdges().end(), back_inserter(edges2));
1374  copy(other->getOutgoingEdges().begin(), other->getOutgoingEdges().end(), back_inserter(edges2));
1375  for (EdgeVector::const_iterator k = edges2.begin(); k != edges2.end(); ++k) {
1376  if ((*k)->getFromNode()->isDistrict() || (*k)->getToNode()->isDistrict()) {
1377  return true;
1378  }
1379  }
1380  }
1381  return false;
1382 }
1383 
1384 
1385 bool
1387  return myType == NODETYPE_DISTRICT;
1388 }
1389 
1390 
1391 void
1393  unsigned int noInternalNoSplits = 0;
1394  for (EdgeVector::const_iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
1395  const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
1396  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1397  if ((*k).toEdge == 0) {
1398  continue;
1399  }
1400  noInternalNoSplits++;
1401  }
1402  }
1403  unsigned int lno = 0;
1404  unsigned int splitNo = 0;
1405  for (EdgeVector::const_iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
1406  (*i)->buildInnerEdges(*this, noInternalNoSplits, lno, splitNo);
1407  }
1408 }
1409 
1410 
1411 bool
1413  if (myIncomingEdges.size() == 1 && myOutgoingEdges.size() == 1) {
1414  return true;
1415  }
1416  if (myIncomingEdges.size() == 2 && myOutgoingEdges.size() == 2) {
1417  // check whether the incoming and outgoing edges are pairwise (near) parallel and
1418  // thus the only cross-connections could be turn-arounds
1419  NBEdge* out0 = myOutgoingEdges[0];
1420  NBEdge* out1 = myOutgoingEdges[1];
1421  for (EdgeVector::const_iterator it = myIncomingEdges.begin(); it != myIncomingEdges.end(); ++it) {
1422  NBEdge* inEdge = *it;
1423  SUMOReal angle0 = fabs(NBHelpers::relAngle(inEdge->getAngleAtNode(this), out0->getAngleAtNode(this)));
1424  SUMOReal angle1 = fabs(NBHelpers::relAngle(inEdge->getAngleAtNode(this), out1->getAngleAtNode(this)));
1425  if (MAX2(angle0, angle1) <= 160) {
1426  // neither of the outgoing edges is parallel to inEdge
1427  return false;
1428  }
1429  }
1430  return true;
1431  }
1432  return false;
1433 }
1434 
1435 
1436 void
1440  }
1441 }
1442 
1443 
1444 Position
1446  /* Conceptually, the center point would be identical with myPosition.
1447  * However, if the shape is influenced by custom geometry endpoints of the adjoining edges,
1448  * myPosition may fall outside the shape. In this case it is better to use
1449  * the center of the shape
1450  **/
1451  PositionVector tmp = myPoly;
1452  tmp.closePolygon();
1453  //std::cout << getID() << " around=" << tmp.around(myPosition) << " dist=" << tmp.distance(myPosition) << "\n";
1454  if (tmp.size() < 3 || tmp.around(myPosition) || tmp.distance(myPosition) < POSITION_EPS) {
1455  return myPosition;
1456  } else {
1457  return myPoly.getPolygonCenter();
1458  }
1459 }
1460 
1461 /****************************************************************************/
1462 
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:474
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:797
const Position & p2() const
Definition: Line.cpp:86
const EdgeVector & getIncomingEdges() const
Returns this node&#39;s incoming edges.
Definition: NBNode.h:177
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:1003
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:1437
Position getCenter() const
Returns a position that is guaranteed to lie within the node shape.
Definition: NBNode.cpp:1445
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&#39;s shape.
Definition: NBEdge.h:128
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:1386
PositionVector myPoly
the (outer) shape of the junction
Definition: NBNode.h:513
NBEdge * getOppositeIncoming(NBEdge *e) const
Definition: NBNode.cpp:916
void execute(const unsigned int src, const unsigned int dest)
Definition: NBNode.cpp:95
SumoXMLNodeType myType
The type of the junction.
Definition: NBNode.h:504
#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:223
static SUMOReal normRelAngle(SUMOReal angle1, SUMOReal angle2)
Definition: NBHelpers.cpp:75
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition: NBNode.h:228
~NBNode()
Destructor.
Definition: NBNode.cpp:217
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 &quot;prohibited&quot; flow must let &quot;prohibitor&quot; 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:418
This class computes shapes of junctions.
This is an uncontrolled, minor link, has to stop.
void computeNodeShape(bool leftHand)
Definition: NBNode.cpp:620
void removeEdge(NBEdge *edge, bool removeFromConnections=true)
Removes edge from this node and optionally removes connections as well.
Definition: NBNode.cpp:977
void addIncomingEdge(NBEdge *edge)
adds an incoming edge
Definition: NBNode.cpp:369
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
const std::string & getProgramID() const
Returns the ProgramID.
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:1047
bool hasOutgoing(const NBEdge *const e) const
Returns whether the given edge starts at this node.
Definition: NBNode.cpp:910
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:635
bool isJoinedTLSControlled() const
Returns whether this node is controlled by a tls that spans over more than one node.
Definition: NBNode.cpp:282
void removeDoubleEdges()
Definition: NBNode.cpp:865
T MAX2(T a, T b)
Definition: StdDefs.h:63
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:808
SUMOReal distanceTo(const Position &p2) const
returns the euclidean distance in 3 dimension
Definition: Position.h:208
bool checkIsRemovable() const
Definition: NBNode.cpp:1257
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:1570
bool almostSame(const Position &p2, SUMOReal maxDiv=POSITION_EPS) const
Definition: Position.h:202
void removeTrafficLight(NBTrafficLightDefinition *tlDef)
Removes the given traffic light from this node.
Definition: NBNode.cpp:266
The link is controlled by a tls which is off, not blinking, may pass.
NBConnectionProhibits myBlockedConnections
Definition: NBNode.h:507
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:904
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:379
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:515
LinkDirection
The different directions a link between two lanes may take (or a stream between two edges)...
NBTrafficLightDefinition * getDefinition(const std::string &id, const std::string &programID) const
Returns the named definition.
The link is a straight direction.
SUMOTime getOffset()
Returns the offset.
NBDistrict * myDistrict
The district the node is the centre of.
Definition: NBNode.h:510
A class representing a single district.
Definition: NBDistrict.h:72
const EdgeVector & getOutgoingEdges() const
Returns this node&#39;s outgoing edges.
Definition: NBNode.h:185
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:501
void computeLanes2Lanes()
computes the connections of lanes to edges
Definition: NBNode.cpp:637
Position getPositionAtDistance(SUMOReal offset) const
Definition: Line.cpp:92
void invalidateIncomingConnections()
Definition: NBNode.cpp:1031
bool isConnectedTo(NBEdge *e)
Returns the information whethe a connection to the given edge has been added (or computed) ...
Definition: NBEdge.cpp:729
const Position & getPosition() const
Returns the position of this node.
Definition: NBNode.h:165
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:951
bool isSimpleContinuation() const
Definition: NBNode.cpp:389
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 &quot;prohibited&quot; flow must let &quot;prohibitor&quot; flow pass.
Definition: NBRequest.cpp:641
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:542
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:1412
SUMOReal offset
This lane&#39;s offset to the intersection begin.
Definition: NBEdge.h:136
void invalidateOutgoingConnections()
Definition: NBNode.cpp:1039
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:273
EdgeVector * getEdgesThatApproach(NBEdge *currentOutgoing)
Definition: NBNode.cpp:738
Definition: Line.h:51
std::set< NBTrafficLightDefinition * > myTrafficLights
Definition: NBNode.h:517
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:66
T MIN2(T a, T b)
Definition: StdDefs.h:57
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:51
const PositionVector & getShape() const
Definition: NBNode.cpp:1338
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:1344
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:495
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:1071
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:1314
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:1096
NBEdge * getPossiblySplittedOutgoing(const std::string &edgeid)
Definition: NBNode.cpp:964
unsigned int removeSelfLoops(NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tc)
Removes edges which are both incoming and outgoing into this node.
Definition: NBNode.cpp:326
EdgeVector myOutgoingEdges
Vector of outgoing edges.
Definition: NBNode.h:498
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:121
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:257
void extrapolateSecondBy(SUMOReal length)
Definition: Line.cpp:75
bool isNearDistrict() const
Definition: NBNode.cpp:1355
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:782
Position myPosition
The position the node lies at.
Definition: NBNode.h:492
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:761
~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:1234
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:830
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:1392
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:363
void replaceInConnections(NBEdge *which, NBEdge *by, unsigned int laneOff)
Definition: NBEdge.cpp:860
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
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
NBNode(const std::string &id, const Position &position)
Constructor.
Definition: NBNode.cpp:195
bool insert(NBTrafficLightDefinition *logic, bool forceInsert=false)
Adds a logic definition to the dictionary.
NBEdge * getTurnDestination() const
Definition: NBEdge.cpp:1863
void addSortedLinkFoes(const NBConnection &mayDrive, const NBConnection &mustStop)
Definition: NBNode.cpp:934
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:610
static SUMOReal relAngle(SUMOReal angle1, SUMOReal angle2)
Definition: NBHelpers.cpp:62
void computeLogic(const NBEdgeCont &ec, OptionsCont &oc)
computes the node&#39;s type, logic and traffic light
Definition: NBNode.cpp:571
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:652
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:1100
void invalidateTLS(NBTrafficLightLogicCont &tlCont)
causes the traffic light to be computed anew
Definition: NBNode.cpp:296
void closePolygon()
ensures that the last position equals the first
Lanes to edges - relationships are computed/loaded.
Definition: NBEdge.h:97
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:249
void remapRemoved(NBTrafficLightLogicCont &tc, NBEdge *removed, const EdgeVector &incoming, const EdgeVector &outgoing)
Definition: NBNode.cpp:1107
std::pair< unsigned int, unsigned int > getSizes() const
returns the number of the junction&#39;s lanes and the number of the junction&#39;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&#39;s geometry at the given node.
Definition: NBEdge.cpp:1116
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 &quot;prohibited&quot; flow must let &quot;prohibitor&quot; flow pass.
Definition: NBNode.cpp:1090
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&#39;s direction.
Definition: NBNode.cpp:1188
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:354