SUMO - Simulation of Urban MObility
NBRequest.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2018 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
18 // This class computes the logic of a junction
19 /****************************************************************************/
20 
21 
22 // ===========================================================================
23 // included modules
24 // ===========================================================================
25 #include <config.h>
26 
27 #include <string>
28 #include <vector>
29 #include <set>
30 #include <algorithm>
31 #include <bitset>
32 #include <sstream>
33 #include <map>
34 #include <cassert>
36 #include <utils/common/ToString.h>
39 #include "NBEdge.h"
40 #include "NBContHelper.h"
41 #include "NBNode.h"
42 #include "NBRequest.h"
43 
44 //#define DEBUG_RESPONSE
45 //#define DEBUG_FOES
46 #define DEBUGCOND (myJunction->getID() == "C")
47 
48 // ===========================================================================
49 // static member variables
50 // ===========================================================================
52 int NBRequest::myNotBuild = 0;
53 
54 
55 // ===========================================================================
56 // method definitions
57 // ===========================================================================
59  NBNode* junction,
60  const EdgeVector& all,
61  const EdgeVector& incoming,
62  const EdgeVector& outgoing,
63  const NBConnectionProhibits& loadedProhibits) :
64  myJunction(junction),
65  myAll(all),
66  myIncoming(incoming),
67  myOutgoing(outgoing) {
68  const int variations = numLinks();
69  // build maps with information which forbidding connection were
70  // computed and what's in there
71  myForbids.reserve(variations);
72  myDone.reserve(variations);
73  for (int i = 0; i < variations; i++) {
74  myForbids.push_back(LinkInfoCont(variations, false));
75  myDone.push_back(LinkInfoCont(variations, false));
76  }
77  // insert loaded prohibits
78  for (NBConnectionProhibits::const_iterator j = loadedProhibits.begin(); j != loadedProhibits.end(); j++) {
79  NBConnection prohibited = (*j).first;
80  bool ok1 = prohibited.check(ec);
81  if (find(myIncoming.begin(), myIncoming.end(), prohibited.getFrom()) == myIncoming.end()) {
82  ok1 = false;
83  }
84  if (find(myOutgoing.begin(), myOutgoing.end(), prohibited.getTo()) == myOutgoing.end()) {
85  ok1 = false;
86  }
87  int idx1 = 0;
88  if (ok1) {
89  idx1 = getIndex(prohibited.getFrom(), prohibited.getTo());
90  if (idx1 < 0) {
91  ok1 = false;
92  }
93  }
94  const NBConnectionVector& prohibiting = (*j).second;
95  for (NBConnectionVector::const_iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
96  NBConnection sprohibiting = *k;
97  bool ok2 = sprohibiting.check(ec);
98  if (find(myIncoming.begin(), myIncoming.end(), sprohibiting.getFrom()) == myIncoming.end()) {
99  ok2 = false;
100  }
101  if (find(myOutgoing.begin(), myOutgoing.end(), sprohibiting.getTo()) == myOutgoing.end()) {
102  ok2 = false;
103  }
104  if (ok1 && ok2) {
105  int idx2 = getIndex(sprohibiting.getFrom(), sprohibiting.getTo());
106  if (idx2 < 0) {
107  ok2 = false;
108  } else {
109  myForbids[idx2][idx1] = true;
110  myDone[idx2][idx1] = true;
111  myDone[idx1][idx2] = true;
112  myGoodBuilds++;
113  }
114  } else {
115  std::string pfID = prohibited.getFrom() != 0 ? prohibited.getFrom()->getID() : "UNKNOWN";
116  std::string ptID = prohibited.getTo() != 0 ? prohibited.getTo()->getID() : "UNKNOWN";
117  std::string bfID = sprohibiting.getFrom() != 0 ? sprohibiting.getFrom()->getID() : "UNKNOWN";
118  std::string btID = sprohibiting.getTo() != 0 ? sprohibiting.getTo()->getID() : "UNKNOWN";
119  WRITE_WARNING("could not prohibit " + pfID + "->" + ptID + " by " + bfID + "->" + btID);
120  myNotBuild++;
121  }
122  }
123  }
124  // ok, check whether someone has prohibited two links vice versa
125  // (this happens also in some Vissim-networks, when edges are joined)
126  for (int s1 = 0; s1 < variations; s1++) {
127  for (int s2 = s1 + 1; s2 < variations; s2++) {
128  // not set, yet
129  if (!myDone[s1][s2]) {
130  continue;
131  }
132  // check whether both prohibit vice versa
133  if (myForbids[s1][s2] && myForbids[s2][s1]) {
134  // mark unset - let our algorithm fix it later
135  myDone[s1][s2] = false;
136  myDone[s2][s1] = false;
137  }
138  }
139  }
140 }
141 
142 
144 
145 
146 void
148  EdgeVector::const_iterator i, j;
149  for (i = myIncoming.begin(); i != myIncoming.end(); i++) {
150  for (j = myOutgoing.begin(); j != myOutgoing.end(); j++) {
153  }
154  }
155  // reset signalised/non-signalised dependencies
156  resetSignalised();
157  // reset foes it the number of lanes matches (or exceeds) the number of incoming connections
159 }
160 
161 
162 void
164  EdgeVector::const_iterator pfrom = find(myAll.begin(), myAll.end(), from);
165  while (*pfrom != to) {
167  if ((*pfrom)->getToNode() == myJunction) {
168  EdgeVector::const_iterator pto = find(myAll.begin(), myAll.end(), to);
169  while (*pto != from) {
170  if (!((*pto)->getToNode() == myJunction)) {
171  setBlocking(from, to, *pfrom, *pto);
172  }
174  }
175  }
176  }
177 }
178 
179 
180 void
182  EdgeVector::const_iterator pfrom = find(myAll.begin(), myAll.end(), from);
183  while (*pfrom != to) {
184  NBContHelper::nextCW(myAll, pfrom);
185  if ((*pfrom)->getToNode() == myJunction) {
186  EdgeVector::const_iterator pto = find(myAll.begin(), myAll.end(), to);
187  while (*pto != from) {
188  if (!((*pto)->getToNode() == myJunction)) {
189  setBlocking(from, to, *pfrom, *pto);
190  }
192  }
193  }
194  }
195 }
196 
197 
198 void
200  NBEdge* from2, NBEdge* to2) {
201  // check whether one of the links has a dead end
202  if (to1 == 0 || to2 == 0) {
203  return;
204  }
205  // get the indices of both links
206  int idx1 = getIndex(from1, to1);
207  int idx2 = getIndex(from2, to2);
208  if (idx1 < 0 || idx2 < 0) {
209  return; // !!! error output? did not happend, yet
210  }
211  // check whether the link crossing has already been checked
212  assert(idx1 < (int)(myIncoming.size() * myOutgoing.size()));
213  if (myDone[idx1][idx2]) {
214  return;
215  }
216  // mark the crossings as done
217  myDone[idx1][idx2] = true;
218  myDone[idx2][idx1] = true;
219  // special case all-way stop
221  // all ways forbid each other. Conflict resolution happens via arrival time
222  myForbids[idx1][idx2] = true;
223  myForbids[idx2][idx1] = true;
224  return;
225  }
226  // check if one of the links is a turn; this link is always not priorised
227  // true for right-before-left and priority
228  if (from1->isTurningDirectionAt(to1)) {
229  myForbids[idx2][idx1] = true;
230  return;
231  }
232  if (from2->isTurningDirectionAt(to2)) {
233  myForbids[idx1][idx2] = true;
234  return;
235  }
236  // if there are no connections, there are no prohibitions
237  if (from1->isConnectedTo(to1)) {
238  if (!from2->isConnectedTo(to2)) {
239  myForbids[idx1][idx2] = true;
240  myForbids[idx2][idx1] = false;
241  return;
242  }
243  } else {
244  if (!from2->isConnectedTo(to2)) {
245  myForbids[idx1][idx2] = false;
246  myForbids[idx2][idx1] = false;
247  return;
248  } else {
249  myForbids[idx1][idx2] = false;
250  myForbids[idx2][idx1] = true;
251  return;
252  }
253  }
254  // check the priorities if required by node type
256  int from1p = from1->getJunctionPriority(myJunction);
257  int from2p = from2->getJunctionPriority(myJunction);
258  // check if one of the connections is higher priorised when incoming into
259  // the junction, the connection road will yield
260  if (from1p > from2p) {
261  myForbids[idx1][idx2] = true;
262  return;
263  }
264  if (from2p > from1p) {
265  myForbids[idx2][idx1] = true;
266  return;
267  }
268  }
269  // straight connections prohibit turning connections if the priorities are equal
270  // (unless the junction is a bent priority junction)
272  LinkDirection ld1 = myJunction->getDirection(from1, to1);
273  LinkDirection ld2 = myJunction->getDirection(from2, to2);
274  if (ld1 == LINKDIR_STRAIGHT) {
275  if (ld2 != LINKDIR_STRAIGHT) {
276  myForbids[idx1][idx2] = true;
277  myForbids[idx2][idx1] = false;
278  return;
279  }
280  } else {
281  if (ld2 == LINKDIR_STRAIGHT) {
282  myForbids[idx1][idx2] = false;
283  myForbids[idx2][idx1] = true;
284  return;
285  }
286  }
287  }
288 
289  // check whether one of the connections is higher priorised on
290  // the outgoing edge when both roads are high priorised
291  // the connection with the lower priorised outgoing edge will lead
292  // should be valid for priority junctions only
293  /*
294  if (from1p > 0 && from2p > 0) {
295  assert(myJunction->getType() != NODETYPE_RIGHT_BEFORE_LEFT);
296  int to1p = to1->getJunctionPriority(myJunction);
297  int to2p = to2->getJunctionPriority(myJunction);
298  if (to1p > to2p) {
299  myForbids[idx1][idx2] = true;
300  return;
301  }
302  if (to2p > to1p) {
303  myForbids[idx2][idx1] = true;
304  return;
305  }
306  }
307  */
308 
309  // compute the yielding due to the right-before-left rule
310  // get the position of the incoming lanes in the junction-wheel
311  EdgeVector::const_iterator c1 = find(myAll.begin(), myAll.end(), from1);
313  // go through next edges clockwise...
314  while (*c1 != from1 && *c1 != from2) {
315  if (*c1 == to2) {
316  // if we encounter to2 the second one prohibits the first
317  myForbids[idx2][idx1] = true;
318  return;
319  }
321  }
322  // get the position of the incoming lanes in the junction-wheel
323  EdgeVector::const_iterator c2 = find(myAll.begin(), myAll.end(), from2);
325  // go through next edges clockwise...
326  while (*c2 != from2 && *c2 != from1) {
327  if (*c2 == to1) {
328  // if we encounter to1 the second one prohibits the first
329  myForbids[idx1][idx2] = true;
330  return;
331  }
333  }
334 }
335 
336 
337 int
339  EdgeVector::const_iterator p = find(myAll.begin(), myAll.end(), from);
340  int ret = 0;
341  do {
342  ret++;
343  if (p == myAll.begin()) {
344  p = myAll.end();
345  }
346  p--;
347  } while (*p != to);
348  return ret;
349 }
350 
351 
352 void
353 NBRequest::writeLogic(std::string /* key */, OutputDevice& into, const bool checkLaneFoes) const {
354  int pos = 0;
355  EdgeVector::const_iterator i;
356  // normal connections
357  const bool padding = getSizes().second + myJunction->getCrossings().size() > 10;
358  for (i = myIncoming.begin(); i != myIncoming.end(); i++) {
359  int noLanes = (*i)->getNumLanes();
360  for (int k = 0; k < noLanes; k++) {
361  pos = writeLaneResponse(into, *i, k, pos, checkLaneFoes, padding);
362  }
363  }
364  // crossings
365  auto crossings = myJunction->getCrossings();
366  for (auto c : crossings) {
367  pos = writeCrossingResponse(into, *c, pos);
368  }
369 }
370 
371 
372 void
374  // go through possible prohibitions
375  for (EdgeVector::const_iterator i11 = myIncoming.begin(); i11 != myIncoming.end(); i11++) {
376  int noLanesEdge1 = (*i11)->getNumLanes();
377  for (int j1 = 0; j1 < noLanesEdge1; j1++) {
378  std::vector<NBEdge::Connection> el1 = (*i11)->getConnectionsFromLane(j1);
379  for (std::vector<NBEdge::Connection>::iterator i12 = el1.begin(); i12 != el1.end(); ++i12) {
380  int idx1 = getIndex((*i11), (*i12).toEdge);
381  if (idx1 < 0) {
382  continue;
383  }
384  // go through possibly prohibited
385  for (EdgeVector::const_iterator i21 = myIncoming.begin(); i21 != myIncoming.end(); i21++) {
386  int noLanesEdge2 = (*i21)->getNumLanes();
387  for (int j2 = 0; j2 < noLanesEdge2; j2++) {
388  std::vector<NBEdge::Connection> el2 = (*i21)->getConnectionsFromLane(j2);
389  for (std::vector<NBEdge::Connection>::iterator i22 = el2.begin(); i22 != el2.end(); i22++) {
390  int idx2 = getIndex((*i21), (*i22).toEdge);
391  if (idx2 < 0) {
392  continue;
393  }
394  // check
395  // same incoming connections do not prohibit each other
396  if ((*i11) == (*i21)) {
397  myForbids[idx1][idx2] = false;
398  myForbids[idx2][idx1] = false;
399  continue;
400  }
401  // check other
402  // if both are non-signalised or both are signalised
403  if (((*i12).tlID == "" && (*i22).tlID == "")
404  ||
405  ((*i12).tlID != "" && (*i22).tlID != "")) {
406  // do nothing
407  continue;
408  }
409  // supposing, we don not have to
410  // brake if we are no foes
411  if (!foes(*i11, (*i12).toEdge, *i21, (*i22).toEdge)) {
412  continue;
413  }
414  // otherwise:
415  // the non-signalised must break
416  if ((*i12).tlID != "") {
417  myForbids[idx1][idx2] = true;
418  myForbids[idx2][idx1] = false;
419  } else {
420  myForbids[idx1][idx2] = false;
421  myForbids[idx2][idx1] = true;
422  }
423  }
424  }
425  }
426  }
427  }
428  }
429 }
430 
431 
432 std::pair<int, int>
434  int noLanes = 0;
435  int noLinks = 0;
436  for (EdgeVector::const_iterator i = myIncoming.begin();
437  i != myIncoming.end(); i++) {
438  int noLanesEdge = (*i)->getNumLanes();
439  for (int j = 0; j < noLanesEdge; j++) {
440  int numConnections = (int)(*i)->getConnectionsFromLane(j).size();
441  noLinks += numConnections;
442  if (numConnections > 0) {
443  noLanes++;
444  }
445  }
446  }
447  return std::make_pair(noLanes, noLinks);
448 }
449 
450 
451 bool
452 NBRequest::foes(const NBEdge* const from1, const NBEdge* const to1,
453  const NBEdge* const from2, const NBEdge* const to2) const {
454  // unconnected edges do not forbid other edges
455  if (to1 == 0 || to2 == 0) {
456  return false;
457  }
458  // get the indices
459  int idx1 = getIndex(from1, to1);
460  int idx2 = getIndex(from2, to2);
461  if (idx1 < 0 || idx2 < 0) {
462  return false; // sure? (The connection does not exist within this junction)
463  }
464  assert(idx1 < (int)(myIncoming.size() * myOutgoing.size()));
465  assert(idx2 < (int)(myIncoming.size()*myOutgoing.size()));
466  return myForbids[idx1][idx2] || myForbids[idx2][idx1];
467 }
468 
469 
470 bool
471 NBRequest::forbids(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,
472  const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo,
473  bool regardNonSignalisedLowerPriority) const {
474  // unconnected edges do not forbid other edges
475  if (possProhibitorTo == 0 || possProhibitedTo == 0) {
476  return false;
477  }
478  // get the indices
479  int possProhibitorIdx = getIndex(possProhibitorFrom, possProhibitorTo);
480  int possProhibitedIdx = getIndex(possProhibitedFrom, possProhibitedTo);
481  if (possProhibitorIdx < 0 || possProhibitedIdx < 0) {
482  return false; // sure? (The connection does not exist within this junction)
483  }
484  assert(possProhibitorIdx < (int)(myIncoming.size() * myOutgoing.size()));
485  assert(possProhibitedIdx < (int)(myIncoming.size() * myOutgoing.size()));
486  // check simple right-of-way-rules
487  if (!regardNonSignalisedLowerPriority) {
488  return myForbids[possProhibitorIdx][possProhibitedIdx];
489  }
490  // if its not forbidden, report
491  if (!myForbids[possProhibitorIdx][possProhibitedIdx]) {
492  return false;
493  }
494  // do not forbid a signalised stream by a non-signalised
495  if (!possProhibitorFrom->hasSignalisedConnectionTo(possProhibitorTo)) {
496  return false;
497  }
498  return true;
499 }
500 
501 
502 int
504  int fromLane, int pos, const bool checkLaneFoes, bool padding) const {
505  for (const NBEdge::Connection& c : from->getConnectionsFromLane(fromLane)) {
506  assert(c.toEdge != 0);
508  od.writeAttr(SUMO_ATTR_INDEX, pos++);
509  if (padding && pos <= 10) {
510  od.writePadding(" ");
511  }
512  const std::string foes = getFoesString(from, c.toEdge, fromLane, c.toLane, checkLaneFoes);
513  const std::string response = myJunction->getType() == NODETYPE_ZIPPER ? foes : getResponseString(from, c, checkLaneFoes);
514  od.writeAttr(SUMO_ATTR_RESPONSE, response);
515  od.writeAttr(SUMO_ATTR_FOES, foes);
516  if (!OptionsCont::getOptions().getBool("no-internal-links")) {
517  od.writeAttr(SUMO_ATTR_CONT, c.haveVia);
518  }
519  od.closeTag();
520  }
521  return pos;
522 }
523 
524 
525 int
526 NBRequest::writeCrossingResponse(OutputDevice& od, const NBNode::Crossing& crossing, int pos) const {
527  std::string foes(myJunction->getCrossings().size(), '0');
528  std::string response(myJunction->getCrossings().size(), '0');
529  // conflicts with normal connections
530  for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
531  //const std::vector<NBEdge::Connection> &allConnections = (*i)->getConnections();
532  const NBEdge* from = *i;
533  int noLanes = from->getNumLanes();
534  for (int j = noLanes; j-- > 0;) {
535  std::vector<NBEdge::Connection> connected = from->getConnectionsFromLane(j);
536  int size = (int) connected.size();
537  for (int k = size; k-- > 0;) {
538  const NBEdge* to = connected[k].toEdge;
539  bool foe = false;
540  for (EdgeVector::const_iterator it_e = crossing.edges.begin(); it_e != crossing.edges.end(); ++it_e) {
541  if ((*it_e) == from || (*it_e) == to) {
542  foe = true;
543  break;
544  }
545  }
546  foes += foe ? '1' : '0';
547  response += mustBrakeForCrossing(myJunction, from, to, crossing) || !foe ? '0' : '1';
548  }
549  }
550  }
552  od.writeAttr(SUMO_ATTR_INDEX, pos++);
553  od.writeAttr(SUMO_ATTR_RESPONSE, response);
555  od.writeAttr(SUMO_ATTR_CONT, false);
556  od.closeTag();
557  return pos;
558 }
559 
560 
561 std::string
562 NBRequest::getResponseString(const NBEdge* const from, const NBEdge::Connection& c, const bool checkLaneFoes) const {
563  const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
564  const NBEdge* const to = c.toEdge;
565  const int fromLane = c.fromLane;
566  const int toLane = c.toLane;
567  int idx = 0;
568  if (to != 0) {
569  idx = getIndex(from, to);
570  }
571  std::string result;
572  // crossings
573  auto crossings = myJunction->getCrossings();
574  for (std::vector<NBNode::Crossing*>::const_reverse_iterator i = crossings.rbegin(); i != crossings.rend(); i++) {
575  result += mustBrakeForCrossing(myJunction, from, to, **i) ? '1' : '0';
576  }
577  NBEdge::Connection queryCon = from->getConnection(fromLane, to, toLane);
578  // normal connections
579  for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
580  //const std::vector<NBEdge::Connection> &allConnections = (*i)->getConnections();
581  int noLanes = (*i)->getNumLanes();
582  for (int j = noLanes; j-- > 0;) {
583  std::vector<NBEdge::Connection> connected = (*i)->getConnectionsFromLane(j);
584  int size = (int) connected.size();
585  for (int k = size; k-- > 0;) {
586  if (c.mayDefinitelyPass) {
587  result += '0';
588  } else if ((*i) == from && fromLane == j) {
589  // do not prohibit a connection by others from same lane
590  result += '0';
591  } else {
592  assert(connected[k].toEdge != 0);
593  const int idx2 = getIndex(*i, connected[k].toEdge);
594  assert(k < (int) connected.size());
595  assert(idx < (int)(myIncoming.size() * myOutgoing.size()));
596  assert(idx2 < (int)(myIncoming.size() * myOutgoing.size()));
597  // check whether the connection is prohibited by another one
598 #ifdef DEBUG_RESPONSE
599  if (DEBUGCOND) {
600  std::cout << " c=" << queryCon.getDescription(from) << " prohibitC=" << connected[k].getDescription(*i)
601  << " f=" << myForbids[idx2][idx]
602  << " clf=" << checkLaneFoes
603  << " clfbc=" << checkLaneFoesByClass(queryCon, *i, connected[k])
604  << " lc=" << laneConflict(from, to, toLane, *i, connected[k].toEdge, connected[k].toLane)
605  << " rtc=" << NBNode::rightTurnConflict(from, to, fromLane, *i, connected[k].toEdge, connected[k].fromLane, lefthand)
606  << " mc=" << mergeConflict(from, queryCon, *i, connected[k], false)
607  << " oltc=" << oppositeLeftTurnConflict(from, queryCon, *i, connected[k], false)
608  << " rorc=" << myJunction->rightOnRedConflict(c.tlLinkIndex, connected[k].tlLinkIndex)
609  << " tlscc=" << myJunction->tlsContConflict(from, c, *i, connected[k])
610  << "\n";
611  }
612 #endif
613  const bool hasLaneConflict = (!(checkLaneFoes || checkLaneFoesByClass(queryCon, *i, connected[k]))
614  || laneConflict(from, to, toLane, *i, connected[k].toEdge, connected[k].toLane));
615  if ((myForbids[idx2][idx] && hasLaneConflict)
616  || NBNode::rightTurnConflict(from, to, fromLane, *i, connected[k].toEdge, connected[k].fromLane, lefthand)
617  || mergeConflict(from, queryCon, *i, connected[k], false)
618  || oppositeLeftTurnConflict(from, queryCon, *i, connected[k], false)
619  || myJunction->rightOnRedConflict(c.tlLinkIndex, connected[k].tlLinkIndex)
620  || (myJunction->tlsContConflict(from, c, *i, connected[k]) && hasLaneConflict)
621  ) {
622  result += '1';
623  } else {
624  result += '0';
625  }
626  }
627  }
628  }
629  }
630  return result;
631 }
632 
633 
634 std::string
635 NBRequest::getFoesString(NBEdge* from, NBEdge* to, int fromLane, int toLane, const bool checkLaneFoes) const {
636  const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
637  // remember the case when the lane is a "dead end" in the meaning that
638  // vehicles must choose another lane to move over the following
639  // junction
640  // !!! move to forbidden
641  std::string result;
642  // crossings
643  auto crossings = myJunction->getCrossings();
644  for (std::vector<NBNode::Crossing*>::const_reverse_iterator i = crossings.rbegin(); i != crossings.rend(); i++) {
645  bool foes = false;
646  for (EdgeVector::const_iterator it_e = (**i).edges.begin(); it_e != (**i).edges.end(); ++it_e) {
647  if ((*it_e) == from || (*it_e) == to) {
648  foes = true;
649  break;
650  }
651  }
652  result += foes ? '1' : '0';
653  }
654  NBEdge::Connection queryCon = from->getConnection(fromLane, to, toLane);
655  // normal connections
656  for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin();
657  i != myIncoming.rend(); i++) {
658 
659  for (int j = (int)(*i)->getNumLanes() - 1; j >= 0; --j) {
660  std::vector<NBEdge::Connection> connected = (*i)->getConnectionsFromLane(j);
661  int size = (int) connected.size();
662  for (int k = size; k-- > 0;) {
663  const bool hasLaneConflict = (!(checkLaneFoes || checkLaneFoesByClass(queryCon, *i, connected[k]))
664  || laneConflict(from, to, toLane, *i, connected[k].toEdge, connected[k].toLane));
665  if ((foes(from, to, (*i), connected[k].toEdge) && hasLaneConflict)
666  || NBNode::rightTurnConflict(from, to, fromLane, *i, connected[k].toEdge, connected[k].fromLane, lefthand)
667  || myJunction->turnFoes(from, to, fromLane, *i, connected[k].toEdge, connected[k].fromLane, lefthand)
668  || mergeConflict(from, queryCon, *i, connected[k], true)
669  || oppositeLeftTurnConflict(from, queryCon, *i, connected[k], true)
670  ) {
671  result += '1';
672  } else {
673  result += '0';
674  }
675  }
676  }
677  }
678  return result;
679 }
680 
681 
682 bool
684  const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const {
685  if (from == prohibitorFrom
686  && con.toEdge == prohibitorCon.toEdge
687  && con.toLane == prohibitorCon.toLane
688  && con.fromLane != prohibitorCon.fromLane
690  if (foes) {
691  return true;
692  }
693  if (prohibitorCon.mayDefinitelyPass) {
694  return true;
695  }
696  if (con.mayDefinitelyPass) {
697  return false;
698  }
699  const bool bike = from->getPermissions(con.fromLane) == SVC_BICYCLE;
700  const bool prohibitorBike = prohibitorFrom->getPermissions(prohibitorCon.fromLane) == SVC_BICYCLE;
701  if (myOutgoing.size() == 1) {
702  // at on-ramp like situations, right lane should yield
703  return bike || (con.fromLane < prohibitorCon.fromLane && !prohibitorBike);
704  } else if (myIncoming.size() == 1) {
705  // at off-ramp like situations, right lane should pass unless it's a bicycle lane
706  return bike || (con.fromLane > prohibitorCon.fromLane && !prohibitorBike);
707  } else {
708  // priority depends on direction:
709  // for right turns the rightmost lane gets priority
710  // otherwise the left lane
711  LinkDirection dir = myJunction->getDirection(from, con.toEdge);
712  if (dir == LINKDIR_RIGHT || dir == LINKDIR_PARTRIGHT) {
713  return con.fromLane > prohibitorCon.fromLane;
714  } else {
715  return con.fromLane < prohibitorCon.fromLane;
716  }
717  }
718 
719  } else {
720  return false;
721  }
722 }
723 
724 
725 bool
727  const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const {
728  LinkDirection dir = myJunction->getDirection(from, con.toEdge);
729  // XXX lefthand issue (solve via #4256)
730  if (dir != LINKDIR_LEFT && dir != LINKDIR_PARTLEFT) {
731  return false;
732  }
733  dir = myJunction->getDirection(prohibitorFrom, prohibitorCon.toEdge);
734  if (dir != LINKDIR_LEFT && dir != LINKDIR_PARTLEFT) {
735  return false;
736  }
737  if (from == prohibitorFrom || NBRequest::foes(from, con.toEdge, prohibitorFrom, prohibitorCon.toEdge)) {
738  // not an opposite pair
739  return false;
740  };
741 
742  double width2 = prohibitorCon.toEdge->getLaneWidth(prohibitorCon.toLane) / 2;
743  PositionVector shape = con.shape;
744  shape.append(con.viaShape);
745  PositionVector otherShape = prohibitorCon.shape;
746  otherShape.append(prohibitorCon.viaShape);
747  if (shape.size() == 0 || otherShape.size() == 0) {
748  // no internal lanes built
749  return false;
750  }
751  const double minDV = NBEdge::firstIntersection(shape, otherShape, width2);
752  if (minDV < shape.length() - POSITION_EPS && minDV > POSITION_EPS) {
753  // break symmetry using edge id
754  return foes || from->getID() < prohibitorFrom->getID();
755  } else {
756  return false;
757  }
758 }
759 
760 bool
762  const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon) const {
763  if (con.toEdge != prohibitorCon.toEdge) {
764  return false;
765  }
766  SVCPermissions svc = con.toEdge->getPermissions(con.toLane);
767  SVCPermissions svc2 = prohibitorFrom->getPermissions(prohibitorCon.fromLane) & prohibitorCon.toEdge->getPermissions(prohibitorCon.toLane);
768  // check for lane level conflict if the only common classes are bicycles or pedestrians
769  return (svc & svc2 & ~(SVC_BICYCLE | SVC_PEDESTRIAN)) == 0;
770 }
771 
772 
773 bool
774 NBRequest::laneConflict(const NBEdge* from, const NBEdge* to, int toLane,
775  const NBEdge* prohibitorFrom, const NBEdge* prohibitorTo, int prohibitorToLane) const {
776  if (to != prohibitorTo) {
777  return true;
778  }
779  // since we know that the edge2edge connections are in conflict, the only
780  // situation in which the lane2lane connections can be conflict-free is, if
781  // they target the same edge but do not cross each other
782  double angle = NBHelpers::relAngle(
783  from->getAngleAtNode(from->getToNode()), to->getAngleAtNode(to->getFromNode()));
784  if (angle == 180) {
785  angle = -180; // turnarounds are left turns
786  }
787  const double prohibitorAngle = NBHelpers::relAngle(
788  prohibitorFrom->getAngleAtNode(prohibitorFrom->getToNode()), to->getAngleAtNode(to->getFromNode()));
789  const bool rightOfProhibitor = prohibitorFrom->isTurningDirectionAt(to)
790  || (angle > prohibitorAngle && !from->isTurningDirectionAt(to));
791  return rightOfProhibitor ? toLane >= prohibitorToLane : toLane <= prohibitorToLane;
792 }
793 
794 int
795 NBRequest::getIndex(const NBEdge* const from, const NBEdge* const to) const {
796  EdgeVector::const_iterator fp = find(myIncoming.begin(), myIncoming.end(), from);
797  EdgeVector::const_iterator tp = find(myOutgoing.begin(), myOutgoing.end(), to);
798  if (fp == myIncoming.end() || tp == myOutgoing.end()) {
799  return -1;
800  }
801  // compute the index
802  return (int)(distance(myIncoming.begin(), fp) * myOutgoing.size() + distance(myOutgoing.begin(), tp));
803 }
804 
805 
806 std::ostream&
807 operator<<(std::ostream& os, const NBRequest& r) {
808  int variations = r.numLinks();
809  for (int i = 0; i < variations; i++) {
810  os << i << ' ';
811  for (int j = 0; j < variations; j++) {
812  if (r.myForbids[i][j]) {
813  os << '1';
814  } else {
815  os << '0';
816  }
817  }
818  os << std::endl;
819  }
820  os << std::endl;
821  return os;
822 }
823 
824 
825 bool
826 NBRequest::mustBrake(const NBEdge* const from, const NBEdge* const to, int fromLane, int toLane, bool includePedCrossings) const {
827  // vehicles which do not have a following lane must always decelerate to the end
828  if (to == 0) {
829  return true;
830  }
831  // get the indices
832  int idx2 = getIndex(from, to);
833  if (idx2 == -1) {
834  return false;
835  }
836  // go through all (existing) connections;
837  // check whether any of these forbids the one to determine
838  assert(idx2 < (int)(myIncoming.size()*myOutgoing.size()));
839  for (int idx1 = 0; idx1 < numLinks(); idx1++) {
840  //assert(myDone[idx1][idx2]);
841  if (myDone[idx1][idx2] && myForbids[idx1][idx2]) {
842  return true;
843  }
844  }
845  // maybe we need to brake for a pedestrian crossing
846  if (includePedCrossings) {
847  auto crossings = myJunction->getCrossings();
848  for (std::vector<NBNode::Crossing*>::const_reverse_iterator i = crossings.rbegin(); i != crossings.rend(); i++) {
849  if (mustBrakeForCrossing(myJunction, from, to, **i)) {
850  return true;
851  }
852  }
853  }
854  // maybe we need to brake due to a right-turn conflict with straight-going
855  // bicycles
856  LinkDirection dir = myJunction->getDirection(from, to);
857  if (dir == LINKDIR_RIGHT || dir == LINKDIR_PARTRIGHT) {
858  const std::vector<NBEdge::Connection>& cons = from->getConnections();
859  for (std::vector<NBEdge::Connection>::const_iterator i = cons.begin(); i != cons.end(); i++) {
860  if (NBNode::rightTurnConflict(from, to, fromLane,
861  from, (*i).toEdge, (*i).fromLane)) {
862  return true;
863  }
864  }
865  }
866  // maybe we need to brake due to a merge conflict
867  NBEdge::Connection queryCon = from->getConnection(fromLane, to, toLane);
868  for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
869  int noLanes = (*i)->getNumLanes();
870  for (int j = noLanes; j-- > 0;) {
871  std::vector<NBEdge::Connection> connected = (*i)->getConnectionsFromLane(j);
872  const int size = (int) connected.size();
873  for (int k = size; k-- > 0;) {
874  if ((*i) == from && fromLane != j
875  && mergeConflict(from, queryCon, *i, connected[k], myJunction->getType() == NODETYPE_ZIPPER)) {
876  return true;
877  }
878  }
879  }
880  }
881 
882  return false;
883 }
884 
885 bool
886 NBRequest::mustBrakeForCrossing(const NBNode* node, const NBEdge* const from, const NBEdge* const to, const NBNode::Crossing& crossing) {
887  const LinkDirection dir = node->getDirection(from, to);
888  const bool mustYield = dir == LINKDIR_LEFT || dir == LINKDIR_RIGHT;
889  if (crossing.priority || mustYield) {
890  for (EdgeVector::const_iterator it_e = crossing.edges.begin(); it_e != crossing.edges.end(); ++it_e) {
891  // left and right turns must yield to unprioritized crossings only on their destination edge
892  if (((*it_e) == from && crossing.priority) || (*it_e) == to) {
893  return true;
894  }
895  }
896  }
897  return false;
898 }
899 
900 
901 bool
902 NBRequest::mustBrake(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,
903  const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo) const {
904  // get the indices
905  int idx1 = getIndex(possProhibitorFrom, possProhibitorTo);
906  int idx2 = getIndex(possProhibitedFrom, possProhibitedTo);
907  return (myForbids[idx2][idx1]);
908 }
909 
910 
911 void
913  // check if any errors occurred on build the link prohibitions
914  if (myNotBuild != 0) {
915  WRITE_WARNING(toString(myNotBuild) + " of " + toString(myNotBuild + myGoodBuilds) + " prohibitions were not build.");
916  }
917 }
918 
919 
920 void
922  // map from edge to number of incoming connections
923  std::map<NBEdge*, int> incomingCount; // initialized to 0
924  // map from edge to indices of approached lanes
925  std::map<NBEdge*, std::set<int> > approachedLanes;
926  // map from edge to list of incoming edges
927  std::map<NBEdge*, EdgeVector> incomingEdges;
928  for (EdgeVector::const_iterator it_e = myIncoming.begin(); it_e != myIncoming.end(); it_e++) {
929  const std::vector<NBEdge::Connection> connections = (*it_e)->getConnections();
930  for (std::vector<NBEdge::Connection>::const_iterator it_c = connections.begin(); it_c != connections.end(); ++it_c) {
931  incomingCount[it_c->toEdge]++;
932  approachedLanes[it_c->toEdge].insert(it_c->toLane);
933  incomingEdges[it_c->toEdge].push_back(*it_e);
934  }
935  }
936  for (std::map<NBEdge*, int>::iterator it = incomingCount.begin(); it != incomingCount.end(); ++it) {
937  NBEdge* to = it->first;
938  // we cannot test against to->getNumLanes() since not all lanes may be used
939  if ((int)approachedLanes[to].size() >= it->second) {
940  EdgeVector& incoming = incomingEdges[to];
941  // make these connections mutually unconflicting
942  for (EdgeVector::iterator it_e1 = incoming.begin(); it_e1 != incoming.end(); ++it_e1) {
943  for (EdgeVector::iterator it_e2 = incoming.begin(); it_e2 != incoming.end(); ++it_e2) {
944  myForbids[getIndex(*it_e1, to)][getIndex(*it_e2, to)] = false;
945  }
946  }
947  }
948  }
949 }
950 
951 
952 int
954  return (int)(myIncoming.size() * myOutgoing.size() + myJunction->getCrossings().size());
955 }
956 
957 /****************************************************************************/
958 
static double relAngle(double angle1, double angle2)
computes the relative angle between the two angles
Definition: NBHelpers.cpp:47
std::pair< int, 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:433
The link is a partial left direction.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:256
void computeLeftOutgoingLinkCrossings(NBEdge *from, NBEdge *to)
computes the relationships between links outgoing left of the given link
Definition: NBRequest.cpp:181
bool check(const NBEdgeCont &ec)
checks whether the edges are still valid
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:160
int toLane
The lane the connections yields in.
Definition: NBEdge.h:188
is a pedestrian
std::vector< bool > LinkInfoCont
definition of a container to store boolean informations about a link into
Definition: NBRequest.h:246
void append(const PositionVector &v, double sameThreshold=2.0)
static int myNotBuild
Definition: NBRequest.h:261
NBEdge * toEdge
The edge the connections yields in.
Definition: NBEdge.h:185
bool isConnectedTo(const NBEdge *e) const
Returns the information whethe a connection to the given edge has been added (or computed) ...
Definition: NBEdge.cpp:1132
bool mergeConflict(const NBEdge *from, const NBEdge::Connection &con, const NBEdge *prohibitorFrom, const NBEdge::Connection &prohibitorCon, bool foes) const
whether multple connections from the same edge target the same lane
Definition: NBRequest.cpp:683
bool hasSignalisedConnectionTo(const NBEdge *const e) const
Check if edge has signalised connections.
Definition: NBEdge.cpp:2950
NBRequest(const NBEdgeCont &ec, NBNode *junction, const EdgeVector &all, const EdgeVector &incoming, const EdgeVector &outgoing, const NBConnectionProhibits &loadedProhibits)
Definition: NBRequest.cpp:58
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
Definition: NBEdge.cpp:1729
std::vector< Crossing * > getCrossings() const
return this junctions pedestrian crossings
Definition: NBNode.cpp:2223
vehicle is a bicycle
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
The representation of a single edge during network building.
Definition: NBEdge.h:65
NBNode * myJunction
the node the request is assigned to
Definition: NBRequest.h:234
std::string getResponseString(const NBEdge *const from, const NBEdge::Connection &c, const bool checkLaneFoes) const
Writes the response of a certain link.
Definition: NBRequest.cpp:562
static int myGoodBuilds
Definition: NBRequest.h:261
void buildBitfieldLogic()
builds the bitset-representation of the logic
Definition: NBRequest.cpp:147
const EdgeVector & myOutgoing
edges outgoing from the junction
Definition: NBRequest.h:243
bool rightOnRedConflict(int index, int foeIndex) const
whether the given index must yield to the foeIndex while turing right on a red light ...
Definition: NBNode.cpp:3018
bool mayDefinitelyPass
Information about being definitely free to drive (on-ramps)
Definition: NBEdge.h:197
NBEdge * getFrom() const
returns the from-edge (start of the connection)
void setBlocking(NBEdge *from1, NBEdge *to1, NBEdge *from2, NBEdge *to2)
Definition: NBRequest.cpp:199
static void nextCW(const EdgeVector &edges, EdgeVector::const_iterator &from)
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
const std::string & getID() const
Returns the id.
Definition: Named.h:69
bool checkLaneFoesByClass(const NBEdge::Connection &con, const NBEdge *prohibitorFrom, const NBEdge::Connection &prohibitorCon) const
whether the given connections must be check for lane conflicts due to the vClasses involved ...
Definition: NBRequest.cpp:761
std::string getDescription(const NBEdge *parent) const
get string describing this connection
Definition: NBEdge.cpp:84
The link is a (hard) left direction.
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:242
int writeLaneResponse(OutputDevice &od, NBEdge *from, int lane, int pos, const bool checkLaneFoes, bool padding) const
writes the response of a certain lane Returns the next link index within the junction ...
Definition: NBRequest.cpp:503
const EdgeVector & myIncoming
edges incoming to the junction
Definition: NBRequest.h:240
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
int numLinks() const
return to total number of edge-to-edge connections of this request-logic
Definition: NBRequest.cpp:953
static bool rightTurnConflict(const NBEdge *from, const NBEdge *to, int fromLane, const NBEdge *prohibitorFrom, const NBEdge *prohibitorTo, int prohibitorFromLane, bool lefthand=false)
return whether the given laneToLane connection is a right turn which must yield to a bicycle crossing...
Definition: NBNode.cpp:1486
CombinationsCont myDone
the link X link is done-checks
Definition: NBRequest.h:258
bool priority
whether the pedestrians have priority
Definition: NBNode.h:145
LinkDirection
The different directions a link between two lanes may take (or a stream between two edges)...
int getIndex(const NBEdge *const from, const NBEdge *const to) const
Returns the index to the internal combination container for the given edge combination.
Definition: NBRequest.cpp:795
The link is a straight direction.
PositionVector shape
shape of Connection
Definition: NBEdge.h:218
bool mustBrake(const NBEdge *const possProhibitorFrom, const NBEdge *const possProhibitorTo, const NBEdge *const possProhibitedFrom, const NBEdge *const possProhibitedTo) const
Returns the information whether "prohibited" flow must let "prohibitor" flow pass.
Definition: NBRequest.cpp:902
static void reportWarnings()
reports warnings if any occurred
Definition: NBRequest.cpp:912
bool tlsContConflict(const NBEdge *from, const NBEdge::Connection &c, const NBEdge *foeFrom, const NBEdge::Connection &foe) const
whether the connection must yield if the foe remains on the intersection after its phase ends ...
Definition: NBNode.cpp:800
std::vector< Connection > getConnectionsFromLane(int lane) const
Returns connections from a given lane.
Definition: NBEdge.cpp:1085
static bool mustBrakeForCrossing(const NBNode *node, const NBEdge *const from, const NBEdge *const to, const NBNode::Crossing &crossing)
Returns the information whether the described flow must brake for the given crossing.
Definition: NBRequest.cpp:886
~NBRequest()
destructor
Definition: NBRequest.cpp:143
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:49
bool forbids(const NBEdge *const possProhibitorFrom, const NBEdge *const possProhibitorTo, const NBEdge *const possProhibitedFrom, const NBEdge *const possProhibitedTo, bool regardNonSignalisedLowerPriority) const
Returns the information whether "prohibited" flow must let "prohibitor" flow pass.
Definition: NBRequest.cpp:471
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:415
int fromLane
The lane the connections starts at.
Definition: NBEdge.h:182
A list of positions.
bool turnFoes(const NBEdge *from, const NBEdge *to, int fromLane, const NBEdge *from2, const NBEdge *to2, int fromLane2, bool lefthand=false) const
return whether the given laneToLane connection originate from the same edge and are in conflict due t...
Definition: NBNode.cpp:1533
bool isConstantWidthTransition() const
detects whether a given junction splits or merges lanes while keeping constant road width ...
Definition: NBNode.cpp:694
void computeRightOutgoingLinkCrossings(NBEdge *from, NBEdge *to)
computes the relationships between links outgoing right of the given link */
Definition: NBRequest.cpp:163
static double firstIntersection(const PositionVector &v1, const PositionVector &v2, double width2)
compute the first intersection point between the given lane geometries considering their rspective wi...
Definition: NBEdge.cpp:1680
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:61
The link is a (hard) right direction.
#define POSITION_EPS
Definition: config.h:172
double getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge&#39;s geometry at the given node.
Definition: NBEdge.cpp:1749
int writeCrossingResponse(OutputDevice &od, const NBNode::Crossing &crossing, int pos) const
writes the response of a certain crossing Returns the next link index within the junction ...
Definition: NBRequest.cpp:526
The link is a partial right direction.
description of a logic request within the junction
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition: NBEdge.cpp:3279
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:452
const EdgeVector & myAll
all (icoming and outgoing) of the junctions edges
Definition: NBRequest.h:237
#define DEBUGCOND
Definition: NBRequest.cpp:46
int tlLinkIndex
The index of this connection within the controlling traffic light.
Definition: NBEdge.h:194
std::vector< NBConnection > NBConnectionVector
Definition of a connection vector.
bool oppositeLeftTurnConflict(const NBEdge *from, const NBEdge::Connection &con, const NBEdge *prohibitorFrom, const NBEdge::Connection &prohibitorCon, bool foes) const
whether opposite left turns intersect
Definition: NBRequest.cpp:726
LinkDirection getDirection(const NBEdge *const incoming, const NBEdge *const outgoing, bool leftHand=false) const
Returns the representation of the described stream&#39;s direction.
Definition: NBNode.cpp:1696
NBEdge * getTo() const
returns the to-edge (end of the connection)
bool laneConflict(const NBEdge *from, const NBEdge *to, int toLane, const NBEdge *prohibitorFrom, const NBEdge *prohibitorTo, int prohibitorToLane) const
return whether the given laneToLane connections prohibit each other under the assumption that the edg...
Definition: NBRequest.cpp:774
Connection getConnection(int fromLane, const NBEdge *to, int toLane) const
Returns the specified connection This method goes through "myConnections" and returns the specified o...
Definition: NBEdge.cpp:1097
double getLaneWidth() const
Returns the default width of lanes of this edge.
Definition: NBEdge.h:525
bool isBentPriority()
return whether a priority road turns at this node
Definition: NBNode.h:726
double length() const
Returns the length.
std::map< NBConnection, NBConnectionVector > NBConnectionProhibits
Definition of a container for connection block dependencies Includes a list of all connections which ...
PositionVector viaShape
shape of via
Definition: NBEdge.h:230
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:862
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:34
void writeLogic(std::string key, OutputDevice &into, const bool checkLaneFoes) const
writes the XML-representation of the logic as a bitset-logic XML representation
Definition: NBRequest.cpp:353
friend std::ostream & operator<<(std::ostream &os, const NBRequest &r)
prints the request
Definition: NBRequest.cpp:807
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:266
std::string getFoesString(NBEdge *from, NBEdge *to, int fromLane, int toLane, const bool checkLaneFoes) const
Definition: NBRequest.cpp:635
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition: NBEdge.cpp:2632
EdgeVector edges
The edges being crossed.
Definition: NBNode.h:131
Represents a single node (junction) during network building.
Definition: NBNode.h:68
A definition of a pedestrian crossing.
Definition: NBNode.h:125
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:64
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:429
int distanceCounterClockwise(NBEdge *from, NBEdge *to)
returns the distance between the incoming (from) and the outgoing (to) edge clockwise in edges ...
Definition: NBRequest.cpp:338
OutputDevice & writePadding(const std::string &val)
writes padding (ignored for binary output)
Definition: OutputDevice.h:308
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:436
void resetCooperating()
reset foes it the number of lanes matches (or exceeds) the number of incoming connections for an edge...
Definition: NBRequest.cpp:921
static void nextCCW(const EdgeVector &edges, EdgeVector::const_iterator &from)
CombinationsCont myForbids
the link X link blockings
Definition: NBRequest.h:255
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
void resetSignalised()
Definition: NBRequest.cpp:373