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.sourceforge.net/
13 // Copyright (C) 2001-2012 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"
66 
67 #ifdef CHECK_MEMORY_LEAKS
68 #include <foreign/nvwa/debug_new.h>
69 #endif // CHECK_MEMORY_LEAKS
70 
71 
72 // ===========================================================================
73 // static members
74 // ===========================================================================
75 
76 // ===========================================================================
77 // method definitions
78 // ===========================================================================
79 /* -------------------------------------------------------------------------
80  * NBNode::ApproachingDivider-methods
81  * ----------------------------------------------------------------------- */
83  EdgeVector* approaching, NBEdge* currentOutgoing) :
84  myApproaching(approaching), myCurrentOutgoing(currentOutgoing) {
85  // check whether origin lanes have been given
86  assert(myApproaching != 0);
87 }
88 
89 
91 
92 
93 void
94 NBNode::ApproachingDivider::execute(const unsigned int src, const unsigned int dest) {
95  assert(myApproaching->size() > src);
96  // get the origin edge
97  NBEdge* incomingEdge = (*myApproaching)[src];
98  if (incomingEdge->getStep() == NBEdge::LANES2LANES_DONE || incomingEdge->getStep() == NBEdge::LANES2LANES_USER) {
99  return;
100  }
101  std::vector<int> approachingLanes =
102  incomingEdge->getConnectionLanes(myCurrentOutgoing);
103  assert(approachingLanes.size() != 0);
104  std::deque<int>* approachedLanes = spread(approachingLanes, dest);
105  assert(approachedLanes->size() <= myCurrentOutgoing->getNumLanes());
106  // set lanes
107  for (unsigned int i = 0; i < approachedLanes->size(); i++) {
108  unsigned int approached = (*approachedLanes)[i];
109  assert(approachedLanes->size() > i);
110  assert(approachingLanes.size() > i);
111  incomingEdge->setConnection((unsigned int) approachingLanes[i], myCurrentOutgoing,
112  approached, NBEdge::L2L_COMPUTED);
113  }
114  delete approachedLanes;
115 }
116 
117 
118 std::deque<int>*
119 NBNode::ApproachingDivider::spread(const std::vector<int>& approachingLanes,
120  int dest) const {
121  std::deque<int>* ret = new std::deque<int>();
122  unsigned int noLanes = (unsigned int) approachingLanes.size();
123  // when only one lane is approached, we check, whether the SUMOReal-value
124  // is assigned more to the left or right lane
125  if (noLanes == 1) {
126  ret->push_back(dest);
127  return ret;
128  }
129 
130  unsigned int noOutgoingLanes = myCurrentOutgoing->getNumLanes();
131  //
132  ret->push_back(dest);
133  unsigned int noSet = 1;
134  int roffset = 1;
135  int loffset = 1;
136  while (noSet < noLanes) {
137  // It may be possible, that there are not enough lanes the source
138  // lanes may be divided on
139  // In this case, they remain unset
140  // !!! this is only a hack. It is possible, that this yields in
141  // uncommon divisions
142  if (noOutgoingLanes == noSet) {
143  return ret;
144  }
145 
146  // as due to the conversion of SUMOReal->uint the numbers will be lower
147  // than they should be, we try to append to the left side first
148  //
149  // check whether the left boundary of the approached street has
150  // been overridden; if so, move all lanes to the right
151  if (dest + loffset >= static_cast<int>(noOutgoingLanes)) {
152  loffset -= 1;
153  roffset += 1;
154  for (unsigned int i = 0; i < ret->size(); i++) {
155  (*ret)[i] = (*ret)[i] - 1;
156  }
157  }
158  // append the next lane to the left of all edges
159  // increase the position (destination edge)
160  ret->push_back(dest + loffset);
161  noSet++;
162  loffset += 1;
163 
164  // as above
165  if (noOutgoingLanes == noSet) {
166  return ret;
167  }
168 
169  // now we try to append the next lane to the right side, when needed
170  if (noSet < noLanes) {
171  // check whether the right boundary of the approached street has
172  // been overridden; if so, move all lanes to the right
173  if (dest < roffset) {
174  loffset += 1;
175  roffset -= 1;
176  for (unsigned int i = 0; i < ret->size(); i++) {
177  (*ret)[i] = (*ret)[i] + 1;
178  }
179  }
180  ret->push_front(dest - roffset);
181  noSet++;
182  roffset += 1;
183  }
184  }
185  return ret;
186 }
187 
188 
189 
190 
191 /* -------------------------------------------------------------------------
192  * NBNode-methods
193  * ----------------------------------------------------------------------- */
194 NBNode::NBNode(const std::string& id, const Position& position) :
195  Named(StringUtils::convertUmlaute(id)),
196  myPosition(position),
198 { }
199 
200 
201 NBNode::NBNode(const std::string& id, const Position& position,
202  SumoXMLNodeType type) :
203  Named(StringUtils::convertUmlaute(id)),
204  myPosition(position),
205  myType(type), myDistrict(0), myRequest(0)
206 { }
207 
208 
209 NBNode::NBNode(const std::string& id, const Position& position, NBDistrict* district) :
210  Named(StringUtils::convertUmlaute(id)),
211  myPosition(position),
212  myType(NODETYPE_DISTRICT), myDistrict(district), myRequest(0)
213 { }
214 
215 
217  delete myRequest;
218 }
219 
220 
221 void
223  bool updateEdgeGeometries) {
224  myPosition = position;
225  // patch type
226  myType = type;
229  }
230  if (updateEdgeGeometries) {
231  for (EdgeVector::iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
232  PositionVector geom = (*i)->getGeometry();
233  geom[-1] = myPosition;
234  (*i)->setGeometry(geom);
235  }
236  for (EdgeVector::iterator i = myOutgoingEdges.begin(); i != myOutgoingEdges.end(); i++) {
237  PositionVector geom = (*i)->getGeometry();
238  geom[0] = myPosition;
239  (*i)->setGeometry(geom);
240  }
241  }
242 }
243 
244 
245 
246 // ----------- Applying offset
247 void
249  myPosition.add(xoff, yoff, 0);
250  myPoly.add(xoff, yoff, 0);
251 }
252 
253 
254 // ----------- Methods for dealing with assigned traffic lights
255 void
257  myTrafficLights.insert(tlDef);
259 }
260 
261 
262 void
264  tlDef->removeNode(this);
265  myTrafficLights.erase(tlDef);
266 }
267 
268 
269 void
271  std::set<NBTrafficLightDefinition*> trafficLights = myTrafficLights; // make a copy because we will modify the original
272  for (std::set<NBTrafficLightDefinition*>::const_iterator i = trafficLights.begin(); i != trafficLights.end(); ++i) {
273  removeTrafficLight(*i);
274  }
275 }
276 
277 
278 bool
280  if (!isTLControlled()) {
281  return false;
282  }
283  for (std::set<NBTrafficLightDefinition*>::const_iterator i = myTrafficLights.begin(); i != myTrafficLights.end(); ++i) {
284  if ((*i)->getID().find("joined") == 0) {
285  return true;
286  }
287  }
288  return false;
289 }
290 
291 
292 // ----------- Prunning the input
293 unsigned int
295  unsigned int ret = 0;
296  unsigned int pos = 0;
297  EdgeVector::const_iterator j = myIncomingEdges.begin();
298  while (j != myIncomingEdges.end()) {
299  // skip edges which are only incoming and not outgoing
300  if (find(myOutgoingEdges.begin(), myOutgoingEdges.end(), *j) == myOutgoingEdges.end()) {
301  ++j;
302  ++pos;
303  continue;
304  }
305  // an edge with both its origin and destination being the current
306  // node should be removed
307  NBEdge* dummy = *j;
308  WRITE_WARNING(" Removing self-looping edge '" + dummy->getID() + "'");
309  // get the list of incoming edges connected to the self-loop
310  EdgeVector incomingConnected;
311  for (EdgeVector::const_iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
312  if ((*i)->isConnectedTo(dummy) && *i != dummy) {
313  incomingConnected.push_back(*i);
314  }
315  }
316  // get the list of outgoing edges connected to the self-loop
317  EdgeVector outgoingConnected;
318  for (EdgeVector::const_iterator i = myOutgoingEdges.begin(); i != myOutgoingEdges.end(); i++) {
319  if (dummy->isConnectedTo(*i) && *i != dummy) {
320  outgoingConnected.push_back(*i);
321  }
322  }
323  // let the self-loop remap its connections
324  dummy->remapConnections(incomingConnected);
325  remapRemoved(tc, dummy, incomingConnected, outgoingConnected);
326  // delete the self-loop
327  ec.erase(dc, dummy);
328  j = myIncomingEdges.begin() + pos;
329  ++ret;
330  }
331  return ret;
332 }
333 
334 
335 // -----------
336 void
338  assert(edge != 0);
339  if (find(myIncomingEdges.begin(), myIncomingEdges.end(), edge) == myIncomingEdges.end()) {
340  myIncomingEdges.push_back(edge);
341  myAllEdges.push_back(edge);
342  }
343 }
344 
345 
346 void
348  assert(edge != 0);
349  if (find(myOutgoingEdges.begin(), myOutgoingEdges.end(), edge) == myOutgoingEdges.end()) {
350  myOutgoingEdges.push_back(edge);
351  myAllEdges.push_back(edge);
352  }
353 }
354 
355 
356 bool
358  // one in, one out->continuation
359  if (myIncomingEdges.size() == 1 && myOutgoingEdges.size() == 1) {
360  // both must have the same number of lanes
361  return (*(myIncomingEdges.begin()))->getNumLanes() == (*(myOutgoingEdges.begin()))->getNumLanes();
362  }
363  // two in and two out and both in reverse direction
364  if (myIncomingEdges.size() == 2 && myOutgoingEdges.size() == 2) {
365  for (EdgeVector::const_iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
366  NBEdge* in = *i;
367  EdgeVector::const_iterator opposite = find_if(myOutgoingEdges.begin(), myOutgoingEdges.end(), NBContHelper::opposite_finder(in, this));
368  // must have an opposite edge
369  if (opposite == myOutgoingEdges.end()) {
370  return false;
371  }
372  // both must have the same number of lanes
374  if (in->getNumLanes() != (*opposite)->getNumLanes()) {
375  return false;
376  }
377  }
378  return true;
379  }
380  // nope
381  return false;
382 }
383 
384 
387  NBEdge* toE, int toL, int numPoints) const {
388  if (fromL >= (int) fromE->getNumLanes()) {
389  throw ProcessError("Connection '" + fromE->getID() + "_" + toString(fromL) + "->" + toE->getID() + "_" + toString(toL) + "' starts at a not existing lane.");
390  }
391  if (toL >= (int) toE->getNumLanes()) {
392  throw ProcessError("Connection '" + fromE->getID() + "_" + toString(fromL) + "->" + toE->getID() + "_" + toString(toL) + "' yields in a not existing lane.");
393  }
394  bool noSpline = false;
395  PositionVector ret;
396  PositionVector init;
397  Position beg = fromE->getLaneShape(fromL).getEnd();
398  Position end = toE->getLaneShape(toL).getBegin();
399  Position intersection;
400  unsigned int noInitialPoints = 0;
401  if (beg.distanceTo(end) <= POSITION_EPS) {
402  noSpline = true;
403  } else {
404  if (fromE->getTurnDestination() == toE) {
405  // turnarounds:
406  // - end of incoming lane
407  // - position between incoming/outgoing end/begin shifted by the distance orthogonally
408  // - begin of outgoing lane
409  noInitialPoints = 3;
410  init.push_back(beg);
411  Line straightConn(fromE->getLaneShape(fromL)[-1], toE->getLaneShape(toL)[0]);
412  Position straightCenter = straightConn.getPositionAtDistance((SUMOReal) straightConn.length() / (SUMOReal) 2.);
413  Position center = straightCenter;//.add(straightCenter);
414  Line cross(straightConn);
415  cross.sub(cross.p1().x(), cross.p1().y());
416  cross.rotateAtP1(PI / 2);
417  center.sub(cross.p2());
418  init.push_back(center);
419  init.push_back(end);
420  } else {
421  const SUMOReal angle = fabs(fromE->getLaneShape(fromL).getEndLine().atan2Angle() - toE->getLaneShape(toL).getBegLine().atan2Angle());
422  if (angle < PI / 4. || angle > 7. / 4.*PI) {
423  // very low angle: almost straight
424  noInitialPoints = 4;
425  init.push_back(beg);
426  Line begL = fromE->getLaneShape(fromL).getEndLine();
427  begL.extrapolateSecondBy(100);
428  Line endL = toE->getLaneShape(toL).getBegLine();
429  endL.extrapolateFirstBy(100);
430  SUMOReal distance = beg.distanceTo(end);
431  if (distance > 10) {
432  {
433  SUMOReal off1 = fromE->getLaneShape(fromL).getEndLine().length() + (SUMOReal) 5. * (SUMOReal) fromE->getNumLanes();
434  off1 = MIN2(off1, (SUMOReal)(fromE->getLaneShape(fromL).getEndLine().length() + distance / 2.));
435  Position tmp = begL.getPositionAtDistance(off1);
436  init.push_back(tmp);
437  }
438  {
439  SUMOReal off1 = (SUMOReal) 100. - (SUMOReal) 5. * (SUMOReal) toE->getNumLanes();
440  off1 = MAX2(off1, (SUMOReal)(100. - distance / 2.));
441  Position tmp = endL.getPositionAtDistance(off1);
442  init.push_back(tmp);
443  }
444  } else {
445  noSpline = true;
446  }
447  init.push_back(end);
448  } else {
449  // turning
450  // - end of incoming lane
451  // - intersection of the extrapolated lanes
452  // - begin of outgoing lane
453  // attention: if there is no intersection, use a straight line
454  noInitialPoints = 3;
455  init.push_back(beg);
456  Line begL = fromE->getLaneShape(fromL).getEndLine();
457  Line endL = toE->getLaneShape(toL).getBegLine();
458  bool check = !begL.p1().almostSame(begL.p2()) && !endL.p1().almostSame(endL.p2());
459  if (check) {
460  begL.extrapolateSecondBy(100);
461  endL.extrapolateFirstBy(100);
462  } else {
463  WRITE_WARNING("Could not use edge geometry for internal lane, node '" + getID() + "'.");
464  }
465  if (!check || !begL.intersects(endL)) {
466  noSpline = true;
467  } else {
468  init.push_back(begL.intersectsAt(endL));
469  }
470  init.push_back(end);
471  }
472  }
473  }
474  //
475  if (noSpline) {
476  ret.push_back(fromE->getLaneShape(fromL).getEnd());
477  ret.push_back(toE->getLaneShape(toL).getBegin());
478  } else {
479  SUMOReal* def = new SUMOReal[1 + noInitialPoints * 3];
480  for (int i = 0; i < (int) init.size(); ++i) {
481  // starts at index 1
482  def[i * 3 + 1] = init[i].x();
483  def[i * 3 + 2] = 0;
484  def[i * 3 + 3] = init[i].y();
485  }
486  SUMOReal* ret_buf = new SUMOReal[numPoints * 3 + 1];
487  bezier(noInitialPoints, def, numPoints, ret_buf);
488  delete[] def;
489  Position prev;
490  for (int i = 0; i < (int) numPoints; i++) {
491  Position current(ret_buf[i * 3 + 1], ret_buf[i * 3 + 3]);
492  if (prev != current) {
493  ret.push_back(current);
494  }
495  prev = current;
496  }
497  delete[] ret_buf;
498  }
499  const NBEdge::Lane& lane = fromE->getLaneStruct(fromL);
500  if (lane.offset > 0) {
501  PositionVector beg = lane.shape.getSubpart(lane.shape.length() - lane.offset, lane.shape.length());;
502  beg.appendWithCrossingPoint(ret);
503  ret = beg;
504  }
505  return ret;
506 }
507 
508 
509 bool
510 NBNode::needsCont(NBEdge* fromE, NBEdge* toE, NBEdge* otherFromE, NBEdge* otherToE, const NBEdge::Connection& c) const {
512  return false;
513  }
514  if (fromE == otherFromE) {
515  // ignore same edge links
516  return false;
517  }
518  if (!foes(otherFromE, otherToE, fromE, toE)) {
519  // if they do not cross, no waiting place is needed
520  return false;
521  }
522  LinkDirection d1 = getDirection(fromE, toE);
523  LinkDirection d2 = getDirection(otherFromE, otherToE);
524  bool thisLeft = (d1 == LINKDIR_LEFT || d1 == LINKDIR_TURN);
525  bool otherLeft = (d2 == LINKDIR_LEFT || d2 == LINKDIR_TURN);
526  bool bothLeft = thisLeft && otherLeft;
527  if (c.tlID != "" && !bothLeft) {
528  // tls-controlled links will have space
529  return true;
530  }
531  if (fromE->getJunctionPriority(this) > 0 && otherFromE->getJunctionPriority(this) > 0) {
532  return mustBrake(fromE, toE, c.toLane);
533  }
534  return false;
535 }
536 
537 
538 void
540  delete myRequest; // possibly recomputation step
541  myRequest = 0;
542  if (myIncomingEdges.size() == 0 || myOutgoingEdges.size() == 0) {
543  // no logic if nothing happens here
545  return;
546  }
547  // check whether the node was set to be unregulated by the user
548  if (oc.getBool("keep-nodes-unregulated") || oc.isInStringVector("keep-nodes-unregulated.explicit", getID())
549  || (oc.getBool("keep-nodes-unregulated.district-nodes") && (isNearDistrict() || isDistrict()))) {
551  return;
552  }
553  // compute the logic if necessary or split the junction
555  // build the request
556  myRequest = new NBRequest(ec, this,
558  // check whether it is not too large
559  unsigned int numConnections = myRequest->getSizes().second;
560  if (numConnections >= 64) {
561  // yep -> make it untcontrolled, warn
562  WRITE_WARNING("Junction '" + getID() + "' is too complicated (#links>64); will be set to unregulated.");
563  delete myRequest;
564  myRequest = 0;
566  } else if (numConnections == 0) {
567  delete myRequest;
568  myRequest = 0;
570  } else {
572  }
573  }
574 }
575 
576 
577 bool
579  if (myRequest) {
580  myRequest->writeLogic(myID, into);
581  return true;
582  }
583  return false;
584 }
585 
586 
587 void
588 NBNode::computeNodeShape(bool leftHand) {
589  if (myIncomingEdges.size() == 0 && myOutgoingEdges.size() == 0) {
590  return;
591  }
592  try {
593  NBNodeShapeComputer computer(*this);
594  myPoly = computer.compute(leftHand);
595  } catch (InvalidArgument&) {
596  WRITE_WARNING("For node '" + getID() + "': could not compute shape.");
597  }
598 }
599 
600 
601 void
603  // special case a):
604  // one in, one out, the outgoing has one lane more
605  if (myIncomingEdges.size() == 1 && myOutgoingEdges.size() == 1
606  && myIncomingEdges[0]->getNumLanes() == myOutgoingEdges[0]->getNumLanes() - 1
607  && myIncomingEdges[0] != myOutgoingEdges[0]
608  && myIncomingEdges[0]->isConnectedTo(myOutgoingEdges[0])) {
609 
610  NBEdge* incoming = myIncomingEdges[0];
611  NBEdge* outgoing = myOutgoingEdges[0];
612  // check if it's not the turnaround
613  if (incoming->getTurnDestination() == outgoing) {
614  // will be added later or not...
615  return;
616  }
617  for (int i = 0; i < (int) incoming->getNumLanes(); ++i) {
618  incoming->setConnection(i, outgoing, i + 1, NBEdge::L2L_COMPUTED);
619  }
620  incoming->setConnection(0, outgoing, 0, NBEdge::L2L_COMPUTED);
621  return;
622  }
623  // special case b):
624  // two in, one out, the outgoing has the same number of lanes as the sum of the incoming
625  // --> highway on-ramp
626  bool check = false;
627  if (myIncomingEdges.size() == 2 && myOutgoingEdges.size() == 1) {
628  check = myIncomingEdges[0]->getNumLanes() + myIncomingEdges[1]->getNumLanes() == myOutgoingEdges[0]->getNumLanes();
629  check &= (myIncomingEdges[0]->getStep() <= NBEdge::LANES2EDGES);
630  check &= (myIncomingEdges[1]->getStep() <= NBEdge::LANES2EDGES);
631  check &= myIncomingEdges[0] != myOutgoingEdges[0];
632  check &= myIncomingEdges[1] != myOutgoingEdges[0];
633  check &= myIncomingEdges[0]->isConnectedTo(myOutgoingEdges[0]);
634  check &= myIncomingEdges[1]->isConnectedTo(myOutgoingEdges[0]);
635  }
636  if (check) {
637  NBEdge* inc1 = myIncomingEdges[0];
638  NBEdge* inc2 = myIncomingEdges[1];
639  // for internal: check which one is the rightmost
640  SUMOReal a1 = inc1->getAngleAtNode(this);
641  SUMOReal a2 = inc2->getAngleAtNode(this);
644  if (ccw > cw) {
645  std::swap(inc1, inc2);
646  }
647  inc1->addLane2LaneConnections(0, myOutgoingEdges[0], 0, inc1->getNumLanes(), NBEdge::L2L_VALIDATED, true, true);
648  inc2->addLane2LaneConnections(0, myOutgoingEdges[0], inc1->getNumLanes(), inc2->getNumLanes(), NBEdge::L2L_VALIDATED, true, true);
649  return;
650  }
651  // special case c):
652  // one in, two out, the incoming has the same number of lanes as the sum of the outgoing
653  // --> highway off-ramp
654  check = false;
655  if (myIncomingEdges.size() == 1 && myOutgoingEdges.size() == 2) {
656  check = myIncomingEdges[0]->getNumLanes() == myOutgoingEdges[1]->getNumLanes() + myOutgoingEdges[0]->getNumLanes();
657  check &= (myIncomingEdges[0]->getStep() <= NBEdge::LANES2EDGES);
658  check &= myIncomingEdges[0] != myOutgoingEdges[0];
659  check &= myIncomingEdges[0] != myOutgoingEdges[1];
660  check &= myIncomingEdges[0]->isConnectedTo(myOutgoingEdges[0]);
661  check &= myIncomingEdges[0]->isConnectedTo(myOutgoingEdges[1]);
662  }
663  if (check) {
664  NBEdge* out1 = myOutgoingEdges[0];
665  NBEdge* out2 = myOutgoingEdges[1];
666  // for internal: check which one is the rightmost
667  SUMOReal a1 = out1->getAngleAtNode(this);
668  SUMOReal a2 = out2->getAngleAtNode(this);
671  if (ccw < cw) {
672  std::swap(out1, out2);
673  }
674  myIncomingEdges[0]->addLane2LaneConnections(0, out1, 0, out1->getNumLanes(), NBEdge::L2L_VALIDATED, true, true);
675  myIncomingEdges[0]->addLane2LaneConnections(out1->getNumLanes(), out2, 0, out2->getNumLanes(), NBEdge::L2L_VALIDATED, false, true);
676  return;
677  }
678 
679  // go through this node's outgoing edges
680  // for every outgoing edge, compute the distribution of the node's
681  // incoming edges on this edge when approaching this edge
682  // the incoming edges' steps will then also be marked as LANE2LANE_RECHECK...
683  EdgeVector::reverse_iterator i;
684  for (i = myOutgoingEdges.rbegin(); i != myOutgoingEdges.rend(); i++) {
685  NBEdge* currentOutgoing = *i;
686  // get the information about edges that do approach this edge
687  EdgeVector* approaching = getEdgesThatApproach(currentOutgoing);
688  if (approaching->size() != 0) {
689  ApproachingDivider divider(approaching, currentOutgoing);
690  Bresenham::compute(&divider, static_cast<unsigned int>(approaching->size()),
691  currentOutgoing->getNumLanes());
692  }
693  delete approaching;
694  }
695  // ... but we may have the case that there are no outgoing edges
696  // In this case, we have to mark the incoming edges as being in state
697  // LANE2LANE( not RECHECK) by hand
698  if (myOutgoingEdges.size() == 0) {
699  for (i = myIncomingEdges.rbegin(); i != myIncomingEdges.rend(); i++) {
700  (*i)->markAsInLane2LaneState();
701  }
702  }
703 }
704 
705 
706 EdgeVector*
708  // get the position of the node to get the approaching nodes of
709  EdgeVector::const_iterator i = find(myAllEdges.begin(),
710  myAllEdges.end(), currentOutgoing);
711  // get the first possible approaching edge
713  // go through the list of edges clockwise and add the edges
714  EdgeVector* approaching = new EdgeVector();
715  for (; *i != currentOutgoing;) {
716  // check only incoming edges
717  if ((*i)->getToNode() == this && (*i)->getTurnDestination() != currentOutgoing) {
718  std::vector<int> connLanes = (*i)->getConnectionLanes(currentOutgoing);
719  if (connLanes.size() != 0) {
720  approaching->push_back(*i);
721  }
722  }
724  }
725  return approaching;
726 }
727 
728 
729 void
730 NBNode::replaceOutgoing(NBEdge* which, NBEdge* by, unsigned int laneOff) {
731  // replace the edge in the list of outgoing nodes
732  EdgeVector::iterator i = find(myOutgoingEdges.begin(), myOutgoingEdges.end(), which);
733  if (i != myOutgoingEdges.end()) {
734  (*i) = by;
735  i = find(myAllEdges.begin(), myAllEdges.end(), which);
736  (*i) = by;
737  }
738  // replace the edge in connections of incoming edges
739  for (i = myIncomingEdges.begin(); i != myIncomingEdges.end(); ++i) {
740  (*i)->replaceInConnections(which, by, laneOff);
741  }
742  // replace within the connetion prohibition dependencies
743  replaceInConnectionProhibitions(which, by, 0, laneOff);
744 }
745 
746 
747 void
749  // replace edges
750  unsigned int laneOff = 0;
751  for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
752  replaceOutgoing(*i, by, laneOff);
753  laneOff += (*i)->getNumLanes();
754  }
755  // removed SUMOReal occurences
757  // check whether this node belongs to a district and the edges
758  // must here be also remapped
759  if (myDistrict != 0) {
760  myDistrict->replaceOutgoing(which, by);
761  }
762 }
763 
764 
765 void
766 NBNode::replaceIncoming(NBEdge* which, NBEdge* by, unsigned int laneOff) {
767  // replace the edge in the list of incoming nodes
768  EdgeVector::iterator i = find(myIncomingEdges.begin(), myIncomingEdges.end(), which);
769  if (i != myIncomingEdges.end()) {
770  (*i) = by;
771  i = find(myAllEdges.begin(), myAllEdges.end(), which);
772  (*i) = by;
773  }
774  // replace within the connetion prohibition dependencies
775  replaceInConnectionProhibitions(which, by, laneOff, 0);
776 }
777 
778 
779 void
781  // replace edges
782  unsigned int laneOff = 0;
783  for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
784  replaceIncoming(*i, by, laneOff);
785  laneOff += (*i)->getNumLanes();
786  }
787  // removed SUMOReal occurences
789  // check whether this node belongs to a district and the edges
790  // must here be also remapped
791  if (myDistrict != 0) {
792  myDistrict->replaceIncoming(which, by);
793  }
794 }
795 
796 
797 
798 void
800  unsigned int whichLaneOff, unsigned int byLaneOff) {
801  // replace in keys
802  NBConnectionProhibits::iterator j = myBlockedConnections.begin();
803  while (j != myBlockedConnections.end()) {
804  bool changed = false;
805  NBConnection c = (*j).first;
806  if (c.replaceFrom(which, whichLaneOff, by, byLaneOff)) {
807  changed = true;
808  }
809  if (c.replaceTo(which, whichLaneOff, by, byLaneOff)) {
810  changed = true;
811  }
812  if (changed) {
813  myBlockedConnections[c] = (*j).second;
814  myBlockedConnections.erase(j);
815  j = myBlockedConnections.begin();
816  } else {
817  j++;
818  }
819  }
820  // replace in values
821  for (j = myBlockedConnections.begin(); j != myBlockedConnections.end(); j++) {
822  NBConnectionVector& prohibiting = (*j).second;
823  for (NBConnectionVector::iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
824  NBConnection& sprohibiting = *k;
825  sprohibiting.replaceFrom(which, whichLaneOff, by, byLaneOff);
826  sprohibiting.replaceTo(which, whichLaneOff, by, byLaneOff);
827  }
828  }
829 }
830 
831 
832 
833 void
835  unsigned int i, j;
836  // check incoming
837  for (i = 0; myIncomingEdges.size() > 0 && i < myIncomingEdges.size() - 1; i++) {
838  j = i + 1;
839  while (j < myIncomingEdges.size()) {
840  if (myIncomingEdges[i] == myIncomingEdges[j]) {
841  myIncomingEdges.erase(myIncomingEdges.begin() + j);
842  } else {
843  j++;
844  }
845  }
846  }
847  // check outgoing
848  for (i = 0; myOutgoingEdges.size() > 0 && i < myOutgoingEdges.size() - 1; i++) {
849  j = i + 1;
850  while (j < myOutgoingEdges.size()) {
851  if (myOutgoingEdges[i] == myOutgoingEdges[j]) {
852  myOutgoingEdges.erase(myOutgoingEdges.begin() + j);
853  } else {
854  j++;
855  }
856  }
857  }
858  // check all
859  for (i = 0; myAllEdges.size() > 0 && i < myAllEdges.size() - 1; i++) {
860  j = i + 1;
861  while (j < myAllEdges.size()) {
862  if (myAllEdges[i] == myAllEdges[j]) {
863  myAllEdges.erase(myAllEdges.begin() + j);
864  } else {
865  j++;
866  }
867  }
868  }
869 }
870 
871 
872 bool
873 NBNode::hasIncoming(const NBEdge* const e) const {
874  return find(myIncomingEdges.begin(), myIncomingEdges.end(), e) != myIncomingEdges.end();
875 }
876 
877 
878 bool
879 NBNode::hasOutgoing(const NBEdge* const e) const {
880  return find(myOutgoingEdges.begin(), myOutgoingEdges.end(), e) != myOutgoingEdges.end();
881 }
882 
883 
884 NBEdge*
886  EdgeVector edges = myIncomingEdges;
887  if (find(edges.begin(), edges.end(), e) != edges.end()) {
888  edges.erase(find(edges.begin(), edges.end(), e));
889  }
890  if (edges.size() == 0) {
891  return 0;
892  }
893  if (e->getToNode() == this) {
894  sort(edges.begin(), edges.end(), NBContHelper::edge_opposite_direction_sorter(e, this));
895  } else {
896  sort(edges.begin(), edges.end(), NBContHelper::edge_similar_direction_sorter(e));
897  }
898  return edges[0];
899 }
900 
901 
902 void
904  const NBConnection& mustStop) {
905  if (mayDrive.getFrom() == 0 ||
906  mayDrive.getTo() == 0 ||
907  mustStop.getFrom() == 0 ||
908  mustStop.getTo() == 0) {
909 
910  WRITE_WARNING("Something went wrong during the building of a connection...");
911  return; // !!! mark to recompute connections
912  }
913  NBConnectionVector conn = myBlockedConnections[mustStop];
914  conn.push_back(mayDrive);
915  myBlockedConnections[mustStop] = conn;
916 }
917 
918 
919 NBEdge*
920 NBNode::getPossiblySplittedIncoming(const std::string& edgeid) {
921  unsigned int size = (unsigned int) edgeid.length();
922  for (EdgeVector::iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
923  std::string id = (*i)->getID();
924  if (id.substr(0, size) == edgeid) {
925  return *i;
926  }
927  }
928  return 0;
929 }
930 
931 
932 NBEdge*
933 NBNode::getPossiblySplittedOutgoing(const std::string& edgeid) {
934  unsigned int size = (unsigned int) edgeid.length();
935  for (EdgeVector::iterator i = myOutgoingEdges.begin(); i != myOutgoingEdges.end(); i++) {
936  std::string id = (*i)->getID();
937  if (id.substr(0, size) == edgeid) {
938  return *i;
939  }
940  }
941  return 0;
942 }
943 
944 
945 void
946 NBNode::removeEdge(NBEdge* edge, bool removeFromConnections) {
947  EdgeVector::iterator i = find(myAllEdges.begin(), myAllEdges.end(), edge);
948  if (i != myAllEdges.end()) {
949  myAllEdges.erase(i);
950  i = find(myOutgoingEdges.begin(), myOutgoingEdges.end(), edge);
951  if (i != myOutgoingEdges.end()) {
952  myOutgoingEdges.erase(i);
953  } else {
954  i = find(myIncomingEdges.begin(), myIncomingEdges.end(), edge);
955  if (i != myIncomingEdges.end()) {
956  myIncomingEdges.erase(i);
957  } else {
958  // edge must have been either incoming or outgoing
959  assert(false);
960  }
961  }
962  if (removeFromConnections) {
963  for (i = myAllEdges.begin(); i != myAllEdges.end(); ++i) {
964  (*i)->removeFromConnections(edge);
965  }
966  }
967  }
968 }
969 
970 
971 Position
973  Position pos(0, 0);
974  EdgeVector::const_iterator i;
975  for (i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
976  NBNode* conn = (*i)->getFromNode();
977  Position toAdd = conn->getPosition();
978  toAdd.sub(myPosition);
979  toAdd.mul((SUMOReal) 1.0 / sqrt(toAdd.x()*toAdd.x() + toAdd.y()*toAdd.y()));
980  pos.add(toAdd);
981  }
982  for (i = myOutgoingEdges.begin(); i != myOutgoingEdges.end(); i++) {
983  NBNode* conn = (*i)->getToNode();
984  Position toAdd = conn->getPosition();
985  toAdd.sub(myPosition);
986  toAdd.mul((SUMOReal) 1.0 / sqrt(toAdd.x()*toAdd.x() + toAdd.y()*toAdd.y()));
987  pos.add(toAdd);
988  }
989  pos.mul((SUMOReal) - 1.0 / (myIncomingEdges.size() + myOutgoingEdges.size()));
990  if (pos.x() == 0 && pos.y() == 0) {
991  pos = Position(1, 0);
992  }
993  pos.norm2d();
994  return pos;
995 }
996 
997 
998 
999 void
1001  for (EdgeVector::const_iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
1002  (*i)->invalidateConnections();
1003  }
1004 }
1005 
1006 
1007 void
1009  for (EdgeVector::const_iterator i = myOutgoingEdges.begin(); i != myOutgoingEdges.end(); i++) {
1010  (*i)->invalidateConnections();
1011  }
1012 }
1013 
1014 
1015 bool
1016 NBNode::mustBrake(const NBEdge* const from, const NBEdge* const to, int toLane) const {
1017  // check whether it is participant to a traffic light
1018  // - controlled links are set by the traffic lights, not the normal
1019  // right-of-way rules
1020  // - uncontrolled participants (spip lanes etc.) should always break
1021  if (myTrafficLights.size() != 0) {
1022  // ok, we have a traffic light, return true by now, it will be later
1023  // controlled by the tls
1024  return true;
1025  }
1026  // unregulated->does not need to brake
1027  if (myRequest == 0) {
1028  return false;
1029  }
1030  // vehicles which do not have a following lane must always decelerate to the end
1031  if (to == 0) {
1032  return true;
1033  }
1034  // check whether any other connection on this node prohibits this connection
1035  bool try1 = myRequest->mustBrake(from, to);
1036  if (!try1 || toLane == -1) {
1037  return try1;
1038  }
1039  if (from->getSpeed() < 70. / 3.6) {
1040  return try1;
1041  }
1042  // on highways (on-ramps, in fact):
1043  // check whether any other connection uses the same destination edge
1044  for (EdgeVector::const_iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
1045  if ((*i) == from) {
1046  continue;
1047  }
1048  const std::vector<NBEdge::Connection>& connections = (*i)->getConnections();
1049  for (std::vector<NBEdge::Connection>::const_iterator j = connections.begin(); j != connections.end(); ++j) {
1050  if ((*j).toEdge == to && ((*j).toLane < 0 || (*j).toLane == toLane)) {
1051  return true;
1052  }
1053  }
1054  }
1055  return false;
1056 }
1057 
1058 
1059 bool
1060 NBNode::isLeftMover(const NBEdge* const from, const NBEdge* const to) const {
1061  // when the junction has only one incoming edge, there are no
1062  // problems caused by left blockings
1063  if (myIncomingEdges.size() == 1 || myOutgoingEdges.size() == 1) {
1064  return false;
1065  }
1066  SUMOReal fromAngle = from->getAngleAtNode(this);
1067  SUMOReal toAngle = to->getAngleAtNode(this);
1068  SUMOReal cw = GeomHelper::getCWAngleDiff(fromAngle, toAngle);
1069  SUMOReal ccw = GeomHelper::getCCWAngleDiff(fromAngle, toAngle);
1070  std::vector<NBEdge*>::const_iterator i = std::find(myAllEdges.begin(), myAllEdges.end(), from);
1071  do {
1073  } while ((!hasOutgoing(*i) || from->isTurningDirectionAt(this, *i)) && *i != from);
1074  return cw < ccw && (*i) == to && myOutgoingEdges.size() > 2;
1075 }
1076 
1077 
1078 bool
1079 NBNode::forbids(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,
1080  const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo,
1081  bool regardNonSignalisedLowerPriority) const {
1082  return myRequest != 0 && myRequest->forbids(possProhibitorFrom, possProhibitorTo,
1083  possProhibitedFrom, possProhibitedTo,
1084  regardNonSignalisedLowerPriority);
1085 }
1086 
1087 
1088 bool
1089 NBNode::foes(const NBEdge* const from1, const NBEdge* const to1,
1090  const NBEdge* const from2, const NBEdge* const to2) const {
1091  return myRequest != 0 && myRequest->foes(from1, to1, from2, to2);
1092 }
1093 
1094 
1095 void
1097  NBEdge* removed, const EdgeVector& incoming,
1098  const EdgeVector& outgoing) {
1099  assert(find(incoming.begin(), incoming.end(), removed) == incoming.end());
1100  bool changed = true;
1101  while (changed) {
1102  changed = false;
1103  NBConnectionProhibits blockedConnectionsTmp = myBlockedConnections;
1104  NBConnectionProhibits blockedConnectionsNew;
1105  // remap in connections
1106  for (NBConnectionProhibits::iterator i = blockedConnectionsTmp.begin(); i != blockedConnectionsTmp.end(); i++) {
1107  const NBConnection& blocker = (*i).first;
1108  const NBConnectionVector& blocked = (*i).second;
1109  // check the blocked connections first
1110  // check whether any of the blocked must be changed
1111  bool blockedChanged = false;
1112  NBConnectionVector newBlocked;
1113  NBConnectionVector::const_iterator j;
1114  for (j = blocked.begin(); j != blocked.end(); j++) {
1115  const NBConnection& sblocked = *j;
1116  if (sblocked.getFrom() == removed || sblocked.getTo() == removed) {
1117  blockedChanged = true;
1118  }
1119  }
1120  // adapt changes if so
1121  for (j = blocked.begin(); blockedChanged && j != blocked.end(); j++) {
1122  const NBConnection& sblocked = *j;
1123  if (sblocked.getFrom() == removed && sblocked.getTo() == removed) {
1124  /* for(EdgeVector::const_iterator k=incoming.begin(); k!=incoming.end(); k++) {
1125  !!! newBlocked.push_back(NBConnection(*k, *k));
1126  }*/
1127  } else if (sblocked.getFrom() == removed) {
1128  assert(sblocked.getTo() != removed);
1129  for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
1130  newBlocked.push_back(NBConnection(*k, sblocked.getTo()));
1131  }
1132  } else if (sblocked.getTo() == removed) {
1133  assert(sblocked.getFrom() != removed);
1134  for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
1135  newBlocked.push_back(NBConnection(sblocked.getFrom(), *k));
1136  }
1137  } else {
1138  newBlocked.push_back(NBConnection(sblocked.getFrom(), sblocked.getTo()));
1139  }
1140  }
1141  if (blockedChanged) {
1142  blockedConnectionsNew[blocker] = newBlocked;
1143  changed = true;
1144  }
1145  // if the blocked were kept
1146  else {
1147  if (blocker.getFrom() == removed && blocker.getTo() == removed) {
1148  changed = true;
1149  /* for(EdgeVector::const_iterator k=incoming.begin(); k!=incoming.end(); k++) {
1150  !!! blockedConnectionsNew[NBConnection(*k, *k)] = blocked;
1151  }*/
1152  } else if (blocker.getFrom() == removed) {
1153  assert(blocker.getTo() != removed);
1154  changed = true;
1155  for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
1156  blockedConnectionsNew[NBConnection(*k, blocker.getTo())] = blocked;
1157  }
1158  } else if (blocker.getTo() == removed) {
1159  assert(blocker.getFrom() != removed);
1160  changed = true;
1161  for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
1162  blockedConnectionsNew[NBConnection(blocker.getFrom(), *k)] = blocked;
1163  }
1164  } else {
1165  blockedConnectionsNew[blocker] = blocked;
1166  }
1167  }
1168  }
1169  myBlockedConnections = blockedConnectionsNew;
1170  }
1171  // remap in traffic lights
1172  tc.remapRemoved(removed, incoming, outgoing);
1173 }
1174 
1175 
1177 NBNode::getDirection(const NBEdge* const incoming, const NBEdge* const outgoing) const {
1178  // ok, no connection at all -> dead end
1179  if (outgoing == 0) {
1180  return LINKDIR_NODIR;
1181  }
1182  // turning direction
1183  if (incoming->isTurningDirectionAt(this, outgoing)) {
1184  return LINKDIR_TURN;
1185  }
1186  // get the angle between incoming/outgoing at the junction
1187  SUMOReal angle =
1188  NBHelpers::normRelAngle(incoming->getAngleAtNode(this), outgoing->getAngleAtNode(this));
1189  // ok, should be a straight connection
1190  if (abs((int) angle) + 1 < 45) {
1191  return LINKDIR_STRAIGHT;
1192  }
1193 
1194  // check for left and right, first
1195  if (angle > 0) {
1196  // check whether any other edge goes further to the right
1197  EdgeVector::const_iterator i =
1198  find(myAllEdges.begin(), myAllEdges.end(), outgoing);
1200  while ((*i) != incoming) {
1201  if ((*i)->getFromNode() == this) {
1202  return LINKDIR_PARTRIGHT;
1203  }
1205  }
1206  return LINKDIR_RIGHT;
1207  }
1208  // check whether any other edge goes further to the left
1209  EdgeVector::const_iterator i =
1210  find(myAllEdges.begin(), myAllEdges.end(), outgoing);
1212  while ((*i) != incoming) {
1213  if ((*i)->getFromNode() == this && !incoming->isTurningDirectionAt(this, *i)) {
1214  return LINKDIR_PARTLEFT;
1215  }
1217  }
1218  return LINKDIR_LEFT;
1219 }
1220 
1221 
1222 LinkState
1223 NBNode::getLinkState(const NBEdge* incoming, NBEdge* outgoing, int fromlane,
1224  bool mayDefinitelyPass, const std::string& tlID) const {
1225  if (tlID != "") {
1227  }
1228  if (outgoing == 0) { // always off
1230  }
1232  return LINKSTATE_EQUAL; // all the same
1233  }
1234  if ((!incoming->isInnerEdge() && mustBrake(incoming, outgoing, fromlane)) && !mayDefinitelyPass) {
1235  return LINKSTATE_MINOR; // minor road
1236  }
1237  // traffic lights are not regarded here
1238  return LINKSTATE_MAJOR;
1239 }
1240 
1241 
1242 bool
1244  // check whether this node is included in a traffic light
1245  if (myTrafficLights.size() != 0) {
1246  return false;
1247  }
1248  EdgeVector::const_iterator i;
1249  // one in, one out -> just a geometry ...
1250  if (myOutgoingEdges.size() == 1 && myIncomingEdges.size() == 1) {
1251  // ... if types match ...
1252  if (!myIncomingEdges[0]->expandableBy(myOutgoingEdges[0])) {
1253  return false;
1254  }
1255  //
1256  return myIncomingEdges[0]->getFromNode() != myOutgoingEdges[0]->getToNode();
1257  }
1258  // two in, two out -> may be something else
1259  if (myOutgoingEdges.size() == 2 && myIncomingEdges.size() == 2) {
1260  // check whether the origin nodes of the incoming edges differ
1261  std::set<NBNode*> origSet;
1262  for (i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
1263  origSet.insert((*i)->getFromNode());
1264  }
1265  if (origSet.size() < 2) {
1266  return false;
1267  }
1268  // check whether this node is an intermediate node of
1269  // a two-directional street
1270  for (i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
1271  // try to find the opposite direction
1272  NBNode* origin = (*i)->getFromNode();
1273  // find the back direction of the current edge
1274  EdgeVector::const_iterator j =
1275  find_if(myOutgoingEdges.begin(), myOutgoingEdges.end(),
1277  // check whether the back direction exists
1278  if (j != myOutgoingEdges.end()) {
1279  // check whether the edge from the backdirection (must be
1280  // the counter-clockwise one) may be joined with the current
1282  // check whether the types allow joining
1283  if (!(*i)->expandableBy(*j)) {
1284  return false;
1285  }
1286  } else {
1287  // ok, at least one outgoing edge is not an opposite
1288  // of an incoming one
1289  return false;
1290  }
1291  }
1292  return true;
1293  }
1294  // ok, a real node
1295  return false;
1296 }
1297 
1298 
1299 std::vector<std::pair<NBEdge*, NBEdge*> >
1301  assert(checkIsRemovable());
1302  std::vector<std::pair<NBEdge*, NBEdge*> > ret;
1303  // one in, one out-case
1304  if (myOutgoingEdges.size() == 1 && myIncomingEdges.size() == 1) {
1305  ret.push_back(
1306  std::pair<NBEdge*, NBEdge*>(
1308  return ret;
1309  }
1310  // two in, two out-case
1311  for (EdgeVector::const_iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
1312  NBNode* origin = (*i)->getFromNode();
1313  EdgeVector::const_iterator j =
1314  find_if(myOutgoingEdges.begin(), myOutgoingEdges.end(),
1317  ret.push_back(std::pair<NBEdge*, NBEdge*>(*i, *j));
1318  }
1319  return ret;
1320 }
1321 
1322 
1323 const PositionVector&
1325  return myPoly;
1326 }
1327 
1328 
1329 SUMOReal
1331  EdgeVector::const_iterator i = myAllEdges.begin();
1332  assert(i != myAllEdges.end());
1333  SUMOReal ret = (*i)->width();
1334  ++i;
1335  for (; i != myAllEdges.end(); i++) {
1336  ret = ret > (*i)->width() ? ret : (*i)->width();
1337  }
1338  return ret;
1339 }
1340 
1341 
1342 NBEdge*
1344  for (EdgeVector::const_iterator i = myOutgoingEdges.begin(); i != myOutgoingEdges.end(); i++) {
1345  if ((*i)->getToNode() == n) {
1346  return (*i);
1347  }
1348  }
1349  return 0;
1350 }
1351 
1352 
1353 bool
1355  if (isDistrict()) {
1356  return false;
1357  }
1358  EdgeVector edges;
1359  copy(getIncomingEdges().begin(), getIncomingEdges().end(),
1360  back_inserter(edges));
1361  copy(getOutgoingEdges().begin(), getOutgoingEdges().end(),
1362  back_inserter(edges));
1363  for (EdgeVector::const_iterator j = edges.begin(); j != edges.end(); ++j) {
1364  NBEdge* t = *j;
1365  NBNode* other = 0;
1366  if (t->getToNode() == this) {
1367  other = t->getFromNode();
1368  } else {
1369  other = t->getToNode();
1370  }
1371  EdgeVector edges2;
1372  copy(other->getIncomingEdges().begin(), other->getIncomingEdges().end(), back_inserter(edges2));
1373  copy(other->getOutgoingEdges().begin(), other->getOutgoingEdges().end(), back_inserter(edges2));
1374  for (EdgeVector::const_iterator k = edges2.begin(); k != edges2.end(); ++k) {
1375  if ((*k)->getFromNode()->isDistrict() || (*k)->getToNode()->isDistrict()) {
1376  return true;
1377  }
1378  }
1379  }
1380  return false;
1381 }
1382 
1383 
1384 bool
1386  return myType == NODETYPE_DISTRICT;
1387 }
1388 
1389 
1390 void
1392  unsigned int noInternalNoSplits = 0;
1393  for (EdgeVector::const_iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
1394  const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
1395  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1396  if ((*k).toEdge == 0) {
1397  continue;
1398  }
1399  noInternalNoSplits++;
1400  }
1401  }
1402  unsigned int lno = 0;
1403  unsigned int splitNo = 0;
1404  for (EdgeVector::const_iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
1405  (*i)->buildInnerEdges(*this, noInternalNoSplits, lno, splitNo);
1406  }
1407 }
1408 
1409 
1410 /****************************************************************************/
1411