SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NBRequest.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // This class computes the logic of a junction
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 <vector>
36 #include <set>
37 #include <algorithm>
38 #include <bitset>
39 #include <sstream>
40 #include <map>
41 #include <cassert>
43 #include <utils/common/ToString.h>
46 #include "NBEdge.h"
47 #include "NBContHelper.h"
48 #include "NBTrafficLightLogic.h"
50 #include "NBNode.h"
51 #include "NBRequest.h"
52 
53 #ifdef CHECK_MEMORY_LEAKS
54 #include <foreign/nvwa/debug_new.h>
55 #endif // CHECK_MEMORY_LEAKS
56 
57 
58 // ===========================================================================
59 // static member variables
60 // ===========================================================================
61 size_t NBRequest::myGoodBuilds = 0;
62 size_t NBRequest::myNotBuild = 0;
63 
64 
65 // ===========================================================================
66 // method definitions
67 // ===========================================================================
69  NBNode* junction,
70  const EdgeVector& all,
71  const EdgeVector& incoming,
72  const EdgeVector& outgoing,
73  const NBConnectionProhibits& loadedProhibits)
74  : myJunction(junction),
75  myAll(all), myIncoming(incoming), myOutgoing(outgoing) {
76  size_t variations = myIncoming.size() * myOutgoing.size();
77  // build maps with information which forbidding connection were
78  // computed and what's in there
79  myForbids.reserve(variations);
80  myDone.reserve(variations);
81  for (size_t i = 0; i < variations; i++) {
82  myForbids.push_back(LinkInfoCont(variations, false));
83  myDone.push_back(LinkInfoCont(variations, false));
84  }
85  // insert loaded prohibits
86  for (NBConnectionProhibits::const_iterator j = loadedProhibits.begin(); j != loadedProhibits.end(); j++) {
87  NBConnection prohibited = (*j).first;
88  bool ok1 = prohibited.check(ec);
89  if (find(myIncoming.begin(), myIncoming.end(), prohibited.getFrom()) == myIncoming.end()) {
90  ok1 = false;
91  }
92  if (find(myOutgoing.begin(), myOutgoing.end(), prohibited.getTo()) == myOutgoing.end()) {
93  ok1 = false;
94  }
95  int idx1 = 0;
96  if (ok1) {
97  idx1 = getIndex(prohibited.getFrom(), prohibited.getTo());
98  if (idx1 < 0) {
99  ok1 = false;
100  }
101  }
102  const NBConnectionVector& prohibiting = (*j).second;
103  for (NBConnectionVector::const_iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
104  NBConnection sprohibiting = *k;
105  bool ok2 = sprohibiting.check(ec);
106  if (find(myIncoming.begin(), myIncoming.end(), sprohibiting.getFrom()) == myIncoming.end()) {
107  ok2 = false;
108  }
109  if (find(myOutgoing.begin(), myOutgoing.end(), sprohibiting.getTo()) == myOutgoing.end()) {
110  ok2 = false;
111  }
112  if (ok1 && ok2) {
113  int idx2 = getIndex(sprohibiting.getFrom(), sprohibiting.getTo());
114  if (idx2 < 0) {
115  ok2 = false;
116  } else {
117  myForbids[idx2][idx1] = true;
118  myDone[idx2][idx1] = true;
119  myDone[idx1][idx2] = true;
120  myGoodBuilds++;
121  }
122  } else {
123  std::string pfID = prohibited.getFrom() != 0 ? prohibited.getFrom()->getID() : "UNKNOWN";
124  std::string ptID = prohibited.getTo() != 0 ? prohibited.getTo()->getID() : "UNKNOWN";
125  std::string bfID = sprohibiting.getFrom() != 0 ? sprohibiting.getFrom()->getID() : "UNKNOWN";
126  std::string btID = sprohibiting.getTo() != 0 ? sprohibiting.getTo()->getID() : "UNKNOWN";
127  WRITE_WARNING("could not prohibit " + pfID + "->" + ptID + " by " + bfID + "->" + btID);
128  myNotBuild++;
129  }
130  }
131  }
132  // ok, check whether someone has prohibited two links vice versa
133  // (this happens also in some Vissim-networks, when edges are joined)
134  size_t no = myIncoming.size() * myOutgoing.size();
135  for (size_t s1 = 0; s1 < no; s1++) {
136  for (size_t s2 = s1 + 1; s2 < no; s2++) {
137  // not set, yet
138  if (!myDone[s1][s2]) {
139  continue;
140  }
141  // check whether both prohibit vice versa
142  if (myForbids[s1][s2] && myForbids[s2][s1]) {
143  // mark unset - let our algorithm fix it later
144  myDone[s1][s2] = false;
145  myDone[s2][s1] = false;
146  }
147  }
148  }
149 }
150 
151 
153 
154 
155 void
157  EdgeVector::const_iterator i, j;
158  for (i = myIncoming.begin(); i != myIncoming.end(); i++) {
159  for (j = myOutgoing.begin(); j != myOutgoing.end(); j++) {
160  computeRightOutgoingLinkCrossings(leftHanded, *i, *j);
161  computeLeftOutgoingLinkCrossings(leftHanded, *i, *j);
162  }
163  }
164  // reset signalised/non-signalised dependencies
165  resetSignalised();
166  // reset foes it the number of lanes matches (or exceeds) the number of incoming connections
168 }
169 
170 
171 void
173  EdgeVector::const_iterator pfrom = find(myAll.begin(), myAll.end(), from);
174  while (*pfrom != to) {
176  if ((*pfrom)->getToNode() == myJunction) {
177  EdgeVector::const_iterator pto = find(myAll.begin(), myAll.end(), to);
178  while (*pto != from) {
179  if (!((*pto)->getToNode() == myJunction)) {
180  setBlocking(leftHanded, from, to, *pfrom, *pto);
181  }
183  }
184  }
185  }
186 }
187 
188 
189 void
191  EdgeVector::const_iterator pfrom = find(myAll.begin(), myAll.end(), from);
192  while (*pfrom != to) {
193  NBContHelper::nextCW(myAll, pfrom);
194  if ((*pfrom)->getToNode() == myJunction) {
195  EdgeVector::const_iterator pto = find(myAll.begin(), myAll.end(), to);
196  while (*pto != from) {
197  if (!((*pto)->getToNode() == myJunction)) {
198  setBlocking(leftHanded, from, to, *pfrom, *pto);
199  }
201  }
202  }
203  }
204 }
205 
206 
207 void
208 NBRequest::setBlocking(bool leftHanded,
209  NBEdge* from1, NBEdge* to1,
210  NBEdge* from2, NBEdge* to2) {
211  // check whether one of the links has a dead end
212  if (to1 == 0 || to2 == 0) {
213  return;
214  }
215  // get the indices of both links
216  int idx1 = getIndex(from1, to1);
217  int idx2 = getIndex(from2, to2);
218  if (idx1 < 0 || idx2 < 0) {
219  return; // !!! error output? did not happend, yet
220  }
221  // check whether the link crossing has already been checked
222  assert((size_t) idx1 < myIncoming.size()*myOutgoing.size());
223  if (myDone[idx1][idx2]) {
224  return;
225  }
226  // mark the crossings as done
227  myDone[idx1][idx2] = true;
228  myDone[idx2][idx1] = true;
229  // special case all-way stop
231  // all ways forbid each other. Conflict resolution happens via arrival time
232  myForbids[idx1][idx2] = true;
233  myForbids[idx2][idx1] = true;
234  return;
235  }
236  // check if one of the links is a turn; this link is always not priorised
237  // true for right-before-left and priority
238  if (from1->isTurningDirectionAt(myJunction, to1)) {
239  myForbids[idx2][idx1] = true;
240  return;
241  }
242  if (from2->isTurningDirectionAt(myJunction, to2)) {
243  myForbids[idx1][idx2] = true;
244  return;
245  }
246  // check the priorities if required by node type
248  int from1p = from1->getJunctionPriority(myJunction);
249  int from2p = from2->getJunctionPriority(myJunction);
250  // check if one of the connections is higher priorised when incoming into
251  // the junction, the connection road will yield
252  if (from1p > from2p) {
253  myForbids[idx1][idx2] = true;
254  return;
255  }
256  if (from2p > from1p) {
257  myForbids[idx2][idx1] = true;
258  return;
259  }
260  }
261 
262  // check whether one of the connections is higher priorised on
263  // the outgoing edge when both roads are high priorised
264  // the connection with the lower priorised outgoing edge will lead
265  // should be valid for priority junctions only
266  /*
267  if (from1p > 0 && from2p > 0) {
268  assert(myJunction->getType() != NODETYPE_RIGHT_BEFORE_LEFT);
269  int to1p = to1->getJunctionPriority(myJunction);
270  int to2p = to2->getJunctionPriority(myJunction);
271  if (to1p > to2p) {
272  myForbids[idx1][idx2] = true;
273  return;
274  }
275  if (to2p > to1p) {
276  myForbids[idx2][idx1] = true;
277  return;
278  }
279  }
280  */
281 
282  // compute the yielding due to the right-before-left rule
283  // get the position of the incoming lanes in the junction-wheel
284  EdgeVector::const_iterator c1 = find(myAll.begin(), myAll.end(), from1);
286  // go through next edges clockwise...
287  while (*c1 != from1 && *c1 != from2) {
288  if (*c1 == to2) {
289  // if we encounter to2 the second one prohibits the first
290  if (!leftHanded) {
291  myForbids[idx2][idx1] = true;
292  } else {
293  myForbids[idx1][idx2] = true;
294  }
295  return;
296  }
298  }
299  // get the position of the incoming lanes in the junction-wheel
300  EdgeVector::const_iterator c2 = find(myAll.begin(), myAll.end(), from2);
302  // go through next edges clockwise...
303  while (*c2 != from2 && *c2 != from1) {
304  if (*c2 == to1) {
305  // if we encounter to1 the second one prohibits the first
306  if (!leftHanded) {
307  myForbids[idx1][idx2] = true;
308  } else {
309  myForbids[idx2][idx1] = true;
310  }
311  return;
312  }
314  }
315 }
316 
317 
318 size_t
320  EdgeVector::const_iterator p = find(myAll.begin(), myAll.end(), from);
321  size_t ret = 0;
322  do {
323  ret++;
324  if (p == myAll.begin()) {
325  p = myAll.end();
326  }
327  p--;
328  } while (*p != to);
329  return ret;
330 }
331 
332 
333 void
334 NBRequest::writeLogic(std::string /* key */, OutputDevice& into, const bool checkLaneFoes) const {
335  int pos = 0;
336  EdgeVector::const_iterator i;
337  for (i = myIncoming.begin(); i != myIncoming.end(); i++) {
338  unsigned int noLanes = (*i)->getNumLanes();
339  for (unsigned int k = 0; k < noLanes; k++) {
340  pos = writeLaneResponse(into, *i, k, pos, checkLaneFoes);
341  }
342  }
343 }
344 
345 
346 void
348  // go through possible prohibitions
349  for (EdgeVector::const_iterator i11 = myIncoming.begin(); i11 != myIncoming.end(); i11++) {
350  unsigned int noLanesEdge1 = (*i11)->getNumLanes();
351  for (unsigned int j1 = 0; j1 < noLanesEdge1; j1++) {
352  std::vector<NBEdge::Connection> el1 = (*i11)->getConnectionsFromLane(j1);
353  for (std::vector<NBEdge::Connection>::iterator i12 = el1.begin(); i12 != el1.end(); ++i12) {
354  int idx1 = getIndex((*i11), (*i12).toEdge);
355  if (idx1 < 0) {
356  continue;
357  }
358  // go through possibly prohibited
359  for (EdgeVector::const_iterator i21 = myIncoming.begin(); i21 != myIncoming.end(); i21++) {
360  unsigned int noLanesEdge2 = (*i21)->getNumLanes();
361  for (unsigned int j2 = 0; j2 < noLanesEdge2; j2++) {
362  std::vector<NBEdge::Connection> el2 = (*i21)->getConnectionsFromLane(j2);
363  for (std::vector<NBEdge::Connection>::iterator i22 = el2.begin(); i22 != el2.end(); i22++) {
364  int idx2 = getIndex((*i21), (*i22).toEdge);
365  if (idx2 < 0) {
366  continue;
367  }
368  // check
369  // same incoming connections do not prohibit each other
370  if ((*i11) == (*i21)) {
371  myForbids[idx1][idx2] = false;
372  myForbids[idx2][idx1] = false;
373  continue;
374  }
375  // check other
376  // if both are non-signalised or both are signalised
377  if (((*i12).tlID == "" && (*i22).tlID == "")
378  ||
379  ((*i12).tlID != "" && (*i22).tlID != "")) {
380  // do nothing
381  continue;
382  }
383  // supposing, we don not have to
384  // brake if we are no foes
385  if (!foes(*i11, (*i12).toEdge, *i21, (*i22).toEdge)) {
386  continue;
387  }
388  // otherwise:
389  // the non-signalised must break
390  if ((*i12).tlID != "") {
391  myForbids[idx1][idx2] = true;
392  myForbids[idx2][idx1] = false;
393  } else {
394  myForbids[idx1][idx2] = false;
395  myForbids[idx2][idx1] = true;
396  }
397  }
398  }
399  }
400  }
401  }
402  }
403 }
404 
405 
406 std::pair<unsigned int, unsigned int>
408  unsigned int noLanes = 0;
409  unsigned int noLinks = 0;
410  for (EdgeVector::const_iterator i = myIncoming.begin();
411  i != myIncoming.end(); i++) {
412  unsigned int noLanesEdge = (*i)->getNumLanes();
413  for (unsigned int j = 0; j < noLanesEdge; j++) {
414  unsigned int numConnections = (unsigned int)(*i)->getConnectionsFromLane(j).size();
415  noLinks += numConnections;
416  if (numConnections > 0) {
417  noLanes++;
418  }
419  }
420  }
421  return std::make_pair(noLanes, noLinks);
422 }
423 
424 
425 bool
426 NBRequest::foes(const NBEdge* const from1, const NBEdge* const to1,
427  const NBEdge* const from2, const NBEdge* const to2) const {
428  // unconnected edges do not forbid other edges
429  if (to1 == 0 || to2 == 0) {
430  return false;
431  }
432  // get the indices
433  int idx1 = getIndex(from1, to1);
434  int idx2 = getIndex(from2, to2);
435  if (idx1 < 0 || idx2 < 0) {
436  return false; // sure? (The connection does not exist within this junction)
437  }
438  assert((size_t) idx1 < myIncoming.size()*myOutgoing.size());
439  assert((size_t) idx2 < myIncoming.size()*myOutgoing.size());
440  return myForbids[idx1][idx2] || myForbids[idx2][idx1];
441 }
442 
443 
444 bool
445 NBRequest::forbids(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,
446  const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo,
447  bool regardNonSignalisedLowerPriority) const {
448  // unconnected edges do not forbid other edges
449  if (possProhibitorTo == 0 || possProhibitedTo == 0) {
450  return false;
451  }
452  // get the indices
453  int possProhibitorIdx = getIndex(possProhibitorFrom, possProhibitorTo);
454  int possProhibitedIdx = getIndex(possProhibitedFrom, possProhibitedTo);
455  if (possProhibitorIdx < 0 || possProhibitedIdx < 0) {
456  return false; // sure? (The connection does not exist within this junction)
457  }
458  assert((size_t) possProhibitorIdx < myIncoming.size()*myOutgoing.size());
459  assert((size_t) possProhibitedIdx < myIncoming.size()*myOutgoing.size());
460  // check simple right-of-way-rules
461  if (!regardNonSignalisedLowerPriority) {
462  return myForbids[possProhibitorIdx][possProhibitedIdx];
463  }
464  // if its not forbidden, report
465  if (!myForbids[possProhibitorIdx][possProhibitedIdx]) {
466  return false;
467  }
468  // do not forbid a signalised stream by a non-signalised
469  if (!possProhibitorFrom->hasSignalisedConnectionTo(possProhibitorTo)) {
470  return false;
471  }
472  return true;
473 }
474 
475 
476 int
478  int fromLane, int pos, const bool checkLaneFoes) const {
479  std::vector<NBEdge::Connection> connected = from->getConnectionsFromLane(fromLane);
480  for (std::vector<NBEdge::Connection>::iterator j = connected.begin(); j != connected.end(); j++) {
481  assert((*j).toEdge != 0);
483  od.writeAttr(SUMO_ATTR_INDEX, pos++);
484  od.writeAttr(SUMO_ATTR_RESPONSE, getResponseString(from, (*j).toEdge, fromLane, (*j).toLane, (*j).mayDefinitelyPass, checkLaneFoes));
485  od.writeAttr(SUMO_ATTR_FOES, getFoesString(from, (*j).toEdge, (*j).toLane, checkLaneFoes));
486  if (!OptionsCont::getOptions().getBool("no-internal-links")) {
487  od.writeAttr(SUMO_ATTR_CONT, j->haveVia);
488  }
489  od.closeTag();
490  }
491  return pos;
492 }
493 
494 
495 std::string
496 NBRequest::getResponseString(const NBEdge* const from, const NBEdge* const to,
497  int fromLane, int toLane, bool mayDefinitelyPass, const bool checkLaneFoes) const {
498  int idx = 0;
499  if (to != 0) {
500  idx = getIndex(from, to);
501  }
502  std::string result;
503  for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
504  //const std::vector<NBEdge::Connection> &allConnections = (*i)->getConnections();
505  unsigned int noLanes = (*i)->getNumLanes();
506  for (int j = noLanes; j-- > 0;) {
507  std::vector<NBEdge::Connection> connected = (*i)->getConnectionsFromLane(j);
508  int size = (int) connected.size();
509  for (int k = size; k-- > 0;) {
510  if (mayDefinitelyPass) {
511  result += '0';
512  } else if ((*i) == from && fromLane == j) {
513  // do not prohibit a connection by others from same lane
514  result += '0';
515  } else {
516  assert(k < (int) connected.size());
517  assert((size_t) idx < myIncoming.size()*myOutgoing.size());
518  assert(connected[k].toEdge != 0);
519  assert((size_t) getIndex(*i, connected[k].toEdge) < myIncoming.size()*myOutgoing.size());
520  // check whether the connection is prohibited by another one
521  if (myForbids[getIndex(*i, connected[k].toEdge)][idx] &&
522  (!checkLaneFoes || laneConflict(from, to, toLane, *i, connected[k].toEdge, connected[k].toLane))) {
523  result += '1';
524  continue;
525  }
526  result += '0';
527  }
528  }
529  }
530  }
531  return result;
532 }
533 
534 
535 std::string
536 NBRequest::getFoesString(NBEdge* from, NBEdge* to, int toLane, const bool checkLaneFoes) const {
537  // remember the case when the lane is a "dead end" in the meaning that
538  // vehicles must choose another lane to move over the following
539  // junction
540  // !!! move to forbidden
541  std::string result;
542  for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin();
543  i != myIncoming.rend(); i++) {
544 
545  unsigned int noLanes = (*i)->getNumLanes();
546  for (unsigned int j = noLanes; j-- > 0;) {
547  std::vector<NBEdge::Connection> connected = (*i)->getConnectionsFromLane(j);
548  int size = (int) connected.size();
549  for (int k = size; k-- > 0;) {
550  if (foes(from, to, (*i), connected[k].toEdge) &&
551  (!checkLaneFoes || laneConflict(from, to, toLane, *i, connected[k].toEdge, connected[k].toLane))) {
552  result += '1';
553  } else {
554  result += '0';
555  }
556  }
557  }
558  }
559  return result;
560 }
561 
562 
563 bool
564 NBRequest::laneConflict(const NBEdge* from, const NBEdge* to, int toLane,
565  const NBEdge* prohibitorFrom, const NBEdge* prohibitorTo, int prohibitorToLane) const {
566  if (to != prohibitorTo) {
567  return true;
568  }
569  // since we know that the edge2edge connections are in conflict, the only
570  // situation in which the lane2lane connections can be conflict-free is, if
571  // they target the same edge but do not cross each other
573  from->getAngleAtNode(from->getToNode()), to->getAngleAtNode(to->getFromNode()));
574  if (angle == 180) {
575  angle = -180; // turnarounds are left turns
576  }
577  const SUMOReal prohibitorAngle = NBHelpers::relAngle(
578  prohibitorFrom->getAngleAtNode(prohibitorFrom->getToNode()), to->getAngleAtNode(to->getFromNode()));
579  const bool rightOfProhibitor = prohibitorFrom->isTurningDirectionAt(prohibitorFrom->getToNode(), to)
580  || (angle > prohibitorAngle && !from->isTurningDirectionAt(from->getToNode(), to));
581  return rightOfProhibitor ? toLane >= prohibitorToLane : toLane <= prohibitorToLane;
582 }
583 
584 
585 int
586 NBRequest::getIndex(const NBEdge* const from, const NBEdge* const to) const {
587  EdgeVector::const_iterator fp = find(myIncoming.begin(), myIncoming.end(), from);
588  EdgeVector::const_iterator tp = find(myOutgoing.begin(), myOutgoing.end(), to);
589  if (fp == myIncoming.end() || tp == myOutgoing.end()) {
590  return -1;
591  }
592  // compute the index
593  return (int)(distance(myIncoming.begin(), fp) * myOutgoing.size() + distance(myOutgoing.begin(), tp));
594 }
595 
596 
597 std::ostream&
598 operator<<(std::ostream& os, const NBRequest& r) {
599  size_t variations = r.myIncoming.size() * r.myOutgoing.size();
600  for (size_t i = 0; i < variations; i++) {
601  os << i << ' ';
602  for (size_t j = 0; j < variations; j++) {
603  if (r.myForbids[i][j]) {
604  os << '1';
605  } else {
606  os << '0';
607  }
608  }
609  os << std::endl;
610  }
611  os << std::endl;
612  return os;
613 }
614 
615 
616 bool
617 NBRequest::mustBrake(const NBEdge* const from, const NBEdge* const to) const {
618  // vehicles which do not have a following lane must always decelerate to the end
619  if (to == 0) {
620  return true;
621  }
622  // get the indices
623  int idx2 = getIndex(from, to);
624  if (idx2 == -1) {
625  return false;
626  }
627  // go through all (existing) connections;
628  // check whether any of these forbids the one to determine
629  assert((size_t) idx2 < myIncoming.size()*myOutgoing.size());
630  for (size_t idx1 = 0; idx1 < myIncoming.size()*myOutgoing.size(); idx1++) {
631  //assert(myDone[idx1][idx2]);
632  if (myDone[idx1][idx2] && myForbids[idx1][idx2]) {
633  return true;
634  }
635  }
636  return false;
637 }
638 
639 
640 bool
641 NBRequest::mustBrake(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,
642  const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo) const {
643  // get the indices
644  int idx1 = getIndex(possProhibitorFrom, possProhibitorTo);
645  int idx2 = getIndex(possProhibitedFrom, possProhibitedTo);
646  return (myForbids[idx2][idx1]);
647 }
648 
649 
650 void
652  // check if any errors occured on build the link prohibitions
653  if (myNotBuild != 0) {
654  WRITE_WARNING(toString(myNotBuild) + " of " + toString(myNotBuild + myGoodBuilds) + " prohibitions were not build.");
655  }
656 }
657 
658 
659 void
661  // map from edge to number of incoming connections
662  std::map<NBEdge*, size_t> incomingCount; // initialized to 0
663  // map from edge to indices of approached lanes
664  std::map<NBEdge*, std::set<int> > approachedLanes;
665  // map from edge to list of incoming edges
666  std::map<NBEdge*, EdgeVector> incomingEdges;
667  for (EdgeVector::const_iterator it_e = myIncoming.begin(); it_e != myIncoming.end(); it_e++) {
668  const std::vector<NBEdge::Connection> connections = (*it_e)->getConnections();
669  for (std::vector<NBEdge::Connection>::const_iterator it_c = connections.begin(); it_c != connections.end(); ++it_c) {
670  incomingCount[it_c->toEdge]++;
671  approachedLanes[it_c->toEdge].insert(it_c->toLane);
672  incomingEdges[it_c->toEdge].push_back(*it_e);
673  }
674  }
675  for (std::map<NBEdge*, size_t>::iterator it = incomingCount.begin(); it != incomingCount.end(); ++it) {
676  NBEdge* to = it->first;
677  // we cannot test against to->getNumLanes() since not all lanes may be used
678  if (approachedLanes[to].size() >= it->second) {
679  EdgeVector& incoming = incomingEdges[to];
680  // make these connections mutually unconflicting
681  for (EdgeVector::iterator it_e1 = incoming.begin(); it_e1 != incoming.end(); ++it_e1) {
682  for (EdgeVector::iterator it_e2 = incoming.begin(); it_e2 != incoming.end(); ++it_e2) {
683  myForbids[getIndex(*it_e1, to)][getIndex(*it_e2, to)] = false;
684  }
685  }
686  }
687  }
688 }
689 
690 /****************************************************************************/
691