LCOV - code coverage report
Current view: top level - src/netbuild - NBRequest.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 93.4 % 485 453
Test Date: 2026-03-02 16:00:03 Functions: 89.2 % 37 33

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2001-2026 German Aerospace Center (DLR) and others.
       4              : // This program and the accompanying materials are made available under the
       5              : // terms of the Eclipse Public License 2.0 which is available at
       6              : // https://www.eclipse.org/legal/epl-2.0/
       7              : // This Source Code may also be made available under the following Secondary
       8              : // Licenses when the conditions for such availability set forth in the Eclipse
       9              : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10              : // or later which is available at
      11              : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12              : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13              : /****************************************************************************/
      14              : /// @file    NBRequest.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Jakob Erdmann
      17              : /// @author  Michael Behrisch
      18              : /// @author  Laura Bieker
      19              : /// @date    Tue, 20 Nov 2001
      20              : ///
      21              : // This class computes the logic of a junction
      22              : /****************************************************************************/
      23              : #include <config.h>
      24              : 
      25              : #include <string>
      26              : #include <vector>
      27              : #include <set>
      28              : #include <algorithm>
      29              : #include <bitset>
      30              : #include <sstream>
      31              : #include <map>
      32              : #include <cassert>
      33              : #include <utils/common/MsgHandler.h>
      34              : #include <utils/common/ToString.h>
      35              : #include <utils/options/OptionsCont.h>
      36              : #include <utils/iodevices/OutputDevice.h>
      37              : #include "NBEdge.h"
      38              : #include "NBContHelper.h"
      39              : #include "NBNode.h"
      40              : #include "NBRequest.h"
      41              : 
      42              : //#define DEBUG_RESPONSE
      43              : //#define DEBUG_SETBLOCKING
      44              : #define DEBUGCOND (myJunction->getID() == "C")
      45              : 
      46              : // ===========================================================================
      47              : // static member variables
      48              : // ===========================================================================
      49              : int NBRequest::myGoodBuilds = 0;
      50              : int NBRequest::myNotBuild = 0;
      51              : 
      52              : 
      53              : // ===========================================================================
      54              : // method definitions
      55              : // ===========================================================================
      56        49076 : NBRequest::NBRequest(const NBEdgeCont& ec,
      57              :                      NBNode* junction,
      58              :                      const EdgeVector& all,
      59              :                      const EdgeVector& incoming,
      60              :                      const EdgeVector& outgoing,
      61        49076 :                      const NBConnectionProhibits& loadedProhibits) :
      62        49076 :     myJunction(junction),
      63        49076 :     myAll(all),
      64        49076 :     myIncoming(incoming),
      65        49076 :     myOutgoing(outgoing) {
      66        49076 :     const int variations = numLinks();
      67              :     // build maps with information which forbidding connection were
      68              :     //  computed and what's in there
      69        49076 :     myForbids.reserve(variations);
      70        49076 :     myDone.reserve(variations);
      71       298560 :     for (int i = 0; i < variations; i++) {
      72       249484 :         myForbids.push_back(LinkInfoCont(variations, false));
      73       498968 :         myDone.push_back(LinkInfoCont(variations, false));
      74              :     }
      75              :     // insert loaded prohibits
      76        49178 :     for (NBConnectionProhibits::const_iterator j = loadedProhibits.begin(); j != loadedProhibits.end(); j++) {
      77          102 :         NBConnection prohibited = (*j).first;
      78          102 :         bool ok1 = prohibited.check(ec);
      79          102 :         if (find(myIncoming.begin(), myIncoming.end(), prohibited.getFrom()) == myIncoming.end()) {
      80              :             ok1 = false;
      81              :         }
      82          102 :         if (find(myOutgoing.begin(), myOutgoing.end(), prohibited.getTo()) == myOutgoing.end()) {
      83              :             ok1 = false;
      84              :         }
      85              :         int idx1 = 0;
      86          102 :         if (ok1) {
      87          102 :             idx1 = getIndex(prohibited.getFrom(), prohibited.getTo());
      88          102 :             if (idx1 < 0) {
      89              :                 ok1 = false;
      90              :             }
      91              :         }
      92              :         const NBConnectionVector& prohibiting = (*j).second;
      93          301 :         for (NBConnectionVector::const_iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
      94          199 :             NBConnection sprohibiting = *k;
      95          199 :             bool ok2 = sprohibiting.check(ec);
      96          199 :             if (find(myIncoming.begin(), myIncoming.end(), sprohibiting.getFrom()) == myIncoming.end()) {
      97              :                 ok2 = false;
      98              :             }
      99          199 :             if (find(myOutgoing.begin(), myOutgoing.end(), sprohibiting.getTo()) == myOutgoing.end()) {
     100              :                 ok2 = false;
     101              :             }
     102          199 :             if (ok1 && ok2) {
     103          199 :                 int idx2 = getIndex(sprohibiting.getFrom(), sprohibiting.getTo());
     104          199 :                 if (idx2 < 0) {
     105              :                     ok2 = false;
     106              :                 } else {
     107          199 :                     myForbids[idx2][idx1] = true;
     108              :                     myDone[idx2][idx1] = true;
     109          199 :                     myDone[idx1][idx2] = true;
     110          199 :                     myGoodBuilds++;
     111              :                 }
     112              :             } else {
     113            0 :                 std::string pfID = prohibited.getFrom() != nullptr ? prohibited.getFrom()->getID() : "UNKNOWN";
     114            0 :                 std::string ptID = prohibited.getTo() != nullptr ? prohibited.getTo()->getID() : "UNKNOWN";
     115            0 :                 std::string bfID = sprohibiting.getFrom() != nullptr ? sprohibiting.getFrom()->getID() : "UNKNOWN";
     116            0 :                 std::string btID = sprohibiting.getTo() != nullptr ? sprohibiting.getTo()->getID() : "UNKNOWN";
     117            0 :                 WRITE_WARNING("could not prohibit " + pfID + "->" + ptID + " by " + bfID + "->" + btID);
     118            0 :                 myNotBuild++;
     119              :             }
     120          199 :         }
     121          102 :     }
     122              :     // ok, check whether someone has prohibited two links vice versa
     123              :     //  (this happens also in some Vissim-networks, when edges are joined)
     124       298560 :     for (int s1 = 0; s1 < variations; s1++) {
     125      1898159 :         for (int s2 = s1 + 1; s2 < variations; s2++) {
     126              :             // not set, yet
     127      1648675 :             if (!myDone[s1][s2]) {
     128      1648563 :                 continue;
     129              :             }
     130              :             // check whether both prohibit vice versa
     131          112 :             if (myForbids[s1][s2] && myForbids[s2][s1]) {
     132              :                 // mark unset - let our algorithm fix it later
     133              :                 myDone[s1][s2] = false;
     134              :                 myDone[s2][s1] = false;
     135              :             }
     136              :         }
     137              :     }
     138        49076 : }
     139              : 
     140              : 
     141        49076 : NBRequest::~NBRequest() {}
     142              : 
     143              : 
     144              : void
     145        42632 : NBRequest::buildBitfieldLogic() {
     146              :     EdgeVector::const_iterator i, j;
     147       130330 :     for (i = myIncoming.begin(); i != myIncoming.end(); i++) {
     148       314610 :         for (j = myOutgoing.begin(); j != myOutgoing.end(); j++) {
     149       226912 :             computeRightOutgoingLinkCrossings(*i, *j);
     150       226912 :             computeLeftOutgoingLinkCrossings(*i, *j);
     151              :         }
     152              :     }
     153              :     // reset signalised/non-signalised dependencies
     154        42632 :     resetSignalised();
     155              :     // reset foes it the number of lanes matches (or exceeds) the number of incoming connections
     156        42632 :     resetCooperating();
     157        42632 : }
     158              : 
     159              : 
     160              : void
     161       226912 : NBRequest::computeRightOutgoingLinkCrossings(NBEdge* from, NBEdge* to) {
     162       226912 :     EdgeVector::const_iterator pfrom = std::find(myAll.begin(), myAll.end(), from);
     163       973367 :     while (*pfrom != to) {
     164       746455 :         NBContHelper::nextCCW(myAll, pfrom);
     165       746455 :         if ((*pfrom)->getToNode() == myJunction) {
     166       260353 :             EdgeVector::const_iterator pto = std::find(myAll.begin(), myAll.end(), to);
     167      1047036 :             while (*pto != from) {
     168       786683 :                 if (!((*pto)->getToNode() == myJunction)) {
     169       525960 :                     setBlocking(from, to, *pfrom, *pto);
     170              :                 }
     171       786683 :                 NBContHelper::nextCCW(myAll, pto);
     172              :             }
     173              :         }
     174              :     }
     175       226912 : }
     176              : 
     177              : 
     178              : void
     179       226912 : NBRequest::computeLeftOutgoingLinkCrossings(NBEdge* from, NBEdge* to) {
     180       226912 :     EdgeVector::const_iterator pfrom = std::find(myAll.begin(), myAll.end(), from);
     181       973367 :     while (*pfrom != to) {
     182       746455 :         NBContHelper::nextCW(myAll, pfrom);
     183       746455 :         if ((*pfrom)->getToNode() == myJunction) {
     184       260353 :             EdgeVector::const_iterator pto = std::find(myAll.begin(), myAll.end(), to);
     185      1047036 :             while (*pto != from) {
     186       786683 :                 if (!((*pto)->getToNode() == myJunction)) {
     187       525960 :                     setBlocking(from, to, *pfrom, *pto);
     188              :                 }
     189       786683 :                 NBContHelper::nextCW(myAll, pto);
     190              :             }
     191              :         }
     192              :     }
     193       226912 : }
     194              : 
     195              : 
     196              : void
     197      1051920 : NBRequest::setBlocking(NBEdge* from1, NBEdge* to1,
     198              :                        NBEdge* from2, NBEdge* to2) {
     199              :     // check whether one of the links has a dead end
     200      1051920 :     if (to1 == nullptr || to2 == nullptr) {
     201      1051920 :         return;
     202              :     }
     203              :     // get the indices of both links
     204      1051920 :     int idx1 = getIndex(from1, to1);
     205      1051920 :     int idx2 = getIndex(from2, to2);
     206      1051920 :     if (idx1 < 0 || idx2 < 0) {
     207              :         return; // !!! error output? did not happend, yet
     208              :     }
     209              :     // check whether the link crossing has already been checked
     210              :     assert(idx1 < (int)(myIncoming.size() * myOutgoing.size()));
     211      1051920 :     if (myDone[idx1][idx2]) {
     212              :         return;
     213              :     }
     214              :     // mark the crossings as done
     215              :     myDone[idx1][idx2] = true;
     216       525870 :     myDone[idx2][idx1] = true;
     217              :     // special case all-way stop
     218       525870 :     if (myJunction->getType() == SumoXMLNodeType::ALLWAY_STOP) {
     219              :         // all ways forbid each other. Conflict resolution happens via arrival time
     220              :         myForbids[idx1][idx2] = true;
     221              :         myForbids[idx2][idx1] = true;
     222           40 :         return;
     223              :     }
     224              :     // check if one of the links is a turn; this link is always not priorised
     225              :     //  true for right-before-left and priority
     226       525830 :     if (from1->isTurningDirectionAt(to1)) {
     227              :         myForbids[idx2][idx1] = true;
     228        67489 :         return;
     229              :     }
     230       458341 :     if (from2->isTurningDirectionAt(to2)) {
     231              :         myForbids[idx1][idx2] = true;
     232        63837 :         return;
     233              :     }
     234              :     // if  there are no connections, there are no prohibitions
     235       394504 :     if (from1->isConnectedTo(to1)) {
     236       243144 :         if (!from2->isConnectedTo(to2)) {
     237              :             myForbids[idx1][idx2] = true;
     238              :             myForbids[idx2][idx1] = false;
     239        27776 :             return;
     240              :         }
     241              :     } else {
     242       151360 :         if (!from2->isConnectedTo(to2)) {
     243              :             myForbids[idx1][idx2] = false;
     244              :             myForbids[idx2][idx1] = false;
     245       122856 :             return;
     246              :         } else {
     247              :             myForbids[idx1][idx2] = false;
     248              :             myForbids[idx2][idx1] = true;
     249        28504 :             return;
     250              :         }
     251              :     }
     252              : #ifdef DEBUG_SETBLOCKING
     253              :     if (DEBUGCOND) std::cout << "setBlocking type=" << toString(myJunction->getType())
     254              :                                  << " bentPrio=" << myJunction->isBentPriority()
     255              :                                  << " 1:" << from1->getID() << "->" << to1->getID()
     256              :                                  << " 2:" << from2->getID() << "->" << to2->getID() << "\n";
     257              : #endif
     258              :     // check the priorities if required by node type
     259       215368 :     const bool typeEqual = myJunction->getType() == SumoXMLNodeType::RIGHT_BEFORE_LEFT || myJunction->getType() == SumoXMLNodeType::LEFT_BEFORE_RIGHT;
     260              :     if (!typeEqual) {
     261       191945 :         int from1p = from1->getJunctionPriority(myJunction);
     262       191945 :         int from2p = from2->getJunctionPriority(myJunction);
     263              : #ifdef DEBUG_SETBLOCKING
     264              :         if (DEBUGCOND) {
     265              :             std::cout << "     p1=" << from1p << " p2=" << from2p << "\n";
     266              :         }
     267              : #endif
     268              :         // check if one of the connections is higher priorised when incoming into
     269              :         //  the junction, the connection road will yield
     270       191945 :         if (from1p > from2p) {
     271              :             myForbids[idx1][idx2] = true;
     272        67394 :             return;
     273              :         }
     274       124551 :         if (from2p > from1p) {
     275              :             myForbids[idx2][idx1] = true;
     276        54964 :             return;
     277              :         }
     278              :     }
     279              :     // straight connections prohibit turning connections if the priorities are equal
     280              :     // (unless the junction is a bent priority junction)
     281        93010 :     LinkDirection ld1 = myJunction->getDirection(from1, to1);
     282        93010 :     LinkDirection ld2 = myJunction->getDirection(from2, to2);
     283        93010 :     if (!typeEqual && !myJunction->isBentPriority()) {
     284              : #ifdef DEBUG_SETBLOCKING
     285              :         if (DEBUGCOND) std::cout << "setBlocking"
     286              :                                      << " 1:" << from1->getID() << "->" << to1->getID()
     287              :                                      << " 2:" << from2->getID() << "->" << to2->getID()
     288              :                                      << " dir1=" << toString(ld1) << " dir2=" << toString(ld2) << "\n";
     289              : #endif
     290        45357 :         if (ld1 == LinkDirection::STRAIGHT) {
     291        11274 :             if (ld2 != LinkDirection::STRAIGHT) {
     292              :                 myForbids[idx1][idx2] = true;
     293              :                 myForbids[idx2][idx1] = false;
     294        10341 :                 return;
     295              :             }
     296              :         } else {
     297        34083 :             if (ld2 == LinkDirection::STRAIGHT) {
     298              :                 myForbids[idx1][idx2] = false;
     299              :                 myForbids[idx2][idx1] = true;
     300        10990 :                 return;
     301              :             }
     302              :         }
     303              :     }
     304              : 
     305              :     // check whether one of the connections is higher priorised on
     306              :     //  the outgoing edge when both roads are high priorised
     307              :     //  the connection with the lower priorised outgoing edge will lead
     308              :     // should be valid for priority junctions only
     309              :     /*
     310              :     if (from1p > 0 && from2p > 0) {
     311              :         assert(myJunction->getType() != SumoXMLNodeType::RIGHT_BEFORE_LEFT);
     312              :         int to1p = to1->getJunctionPriority(myJunction);
     313              :         int to2p = to2->getJunctionPriority(myJunction);
     314              :         if (to1p > to2p) {
     315              :             myForbids[idx1][idx2] = true;
     316              :             return;
     317              :         }
     318              :         if (to2p > to1p) {
     319              :             myForbids[idx2][idx1] = true;
     320              :             return;
     321              :         }
     322              :     }
     323              :     */
     324              : #ifdef DEBUG_SETBLOCKING
     325              :     if (DEBUGCOND) std::cout << "setBlocking1"
     326              :                                  << " 1:" << from1->getID() << "->" << to1->getID()
     327              :                                  << " 2:" << from2->getID() << "->" << to2->getID();
     328              :             << " relAngle=" << NBHelpers::relAngle(from1->getAngleAtNode(myJunction), from2->getAngleAtNode(myJunction))
     329              : #endif
     330              : 
     331              :             // compute the yielding due to the right-before-left rule
     332              :             // (or left-before-right rule)
     333              :             // get the position of the incoming lanes in the junction-wheel
     334        71679 :             EdgeVector::const_iterator c1 = std::find(myAll.begin(), myAll.end(), from1);
     335        71679 :     NBContHelper::nextCW(myAll, c1);
     336              :     // go through next edges clockwise...
     337       218973 :     while (*c1 != from1 && *c1 != from2) {
     338       172427 :         if (*c1 == to2) {
     339              :             // if we encounter to2 the second one prohibits the first
     340        25133 :             if (myJunction->getType() == SumoXMLNodeType::LEFT_BEFORE_RIGHT
     341        25133 :                     && (ld1 != LinkDirection::LEFT || ld2 == LinkDirection::LEFT || (from1->getTurnDestination(true) != to2 &&
     342            7 :                             (ld2 != LinkDirection::RIGHT ||
     343            7 :                              fabs(NBHelpers::relAngle(from1->getAngleAtNode(myJunction),
     344            7 :                                      from2->getAngleAtNode(myJunction))) < 150))
     345              :                        )) {
     346              :                 myForbids[idx1][idx2] = true;
     347              : #ifdef DEBUG_SETBLOCKING
     348              :                 if (DEBUGCOND) {
     349              :                     std::cout << " case1: 2 yields\n";
     350              :                 }
     351              : #endif
     352              :             } else {
     353              :                 myForbids[idx2][idx1] = true;
     354              : #ifdef DEBUG_SETBLOCKING
     355              :                 if (DEBUGCOND) {
     356              :                     std::cout << " case1: 1 yields\n";
     357              :                 }
     358              : #endif
     359              :             }
     360        25133 :             return;
     361              :         }
     362       147294 :         NBContHelper::nextCW(myAll, c1);
     363              :     }
     364              :     // get the position of the incoming lanes in the junction-wheel
     365        46546 :     EdgeVector::const_iterator c2 = std::find(myAll.begin(), myAll.end(), from2);
     366        46546 :     NBContHelper::nextCW(myAll, c2);
     367              :     // go through next edges clockwise...
     368       151639 :     while (*c2 != from2 && *c2 != from1) {
     369       151639 :         if (*c2 == to1) {
     370              :             // if we encounter to1 the second one prohibits the first
     371        46546 :             if (myJunction->getType() == SumoXMLNodeType::LEFT_BEFORE_RIGHT
     372        46546 :                     && (ld2 != LinkDirection::LEFT || ld1 == LinkDirection::LEFT || (from2->getTurnDestination(true) != to1 &&
     373            9 :                             (ld1 != LinkDirection::RIGHT ||
     374            9 :                              fabs(NBHelpers::relAngle(from1->getAngleAtNode(myJunction),
     375            9 :                                      from2->getAngleAtNode(myJunction))) < 150))
     376              :                        )) {
     377              :                 myForbids[idx2][idx1] = true;
     378              : #ifdef DEBUG_SETBLOCKING
     379              :                 if (DEBUGCOND) {
     380              :                     std::cout << " case2: 1 yields\n";
     381              :                 }
     382              : #endif
     383              :             } else {
     384              :                 myForbids[idx1][idx2] = true;
     385              : #ifdef DEBUG_SETBLOCKING
     386              :                 if (DEBUGCOND) {
     387              :                     std::cout << " case2: 2 yields\n";
     388              :                 }
     389              : #endif
     390              :             }
     391        46546 :             return;
     392              :         }
     393       105093 :         NBContHelper::nextCW(myAll, c2);
     394              :     }
     395              : #ifdef DEBUG_SETBLOCKING
     396              :     if (DEBUGCOND) {
     397              :         std::cout << " noDecision\n";
     398              :     }
     399              : #endif
     400              : }
     401              : 
     402              : 
     403              : int
     404            0 : NBRequest::distanceCounterClockwise(NBEdge* from, NBEdge* to) {
     405            0 :     EdgeVector::const_iterator p = std::find(myAll.begin(), myAll.end(), from);
     406              :     int ret = 0;
     407              :     do {
     408            0 :         ret++;
     409            0 :         if (p == myAll.begin()) {
     410              :             p = myAll.end();
     411              :         }
     412              :         p--;
     413            0 :     } while (*p != to);
     414            0 :     return ret;
     415              : }
     416              : 
     417              : const std::string&
     418            0 : NBRequest::getFoes(int linkIndex) const {
     419              :     assert(linkIndex >= 0);
     420              :     assert(linkIndex < (int)myFoes.size());
     421            0 :     return myFoes[linkIndex];
     422              : }
     423              : 
     424              : 
     425              : const std::string&
     426       206926 : NBRequest::getResponse(int linkIndex) const {
     427              :     assert(linkIndex >= 0);
     428              :     assert(linkIndex < (int)myResponse.size());
     429       206926 :     return myResponse[linkIndex];
     430              : }
     431              : 
     432              : 
     433              : void
     434        41640 : NBRequest::writeLogic(OutputDevice& into) const {
     435        41640 :     int numLinks = (int)myResponse.size();
     436              :     assert((int)myFoes.size() == numLinks);
     437              :     assert((int)myHaveVia.size() == numLinks);
     438              :     const bool padding = numLinks > 10;
     439       240406 :     for (int i = 0; i < numLinks; i++) {
     440       198766 :         into.openTag(SUMO_TAG_REQUEST);
     441       198766 :         into.writeAttr(SUMO_ATTR_INDEX, i);
     442       198766 :         if (padding && i < 10) {
     443        95220 :             into.writePadding(" ");
     444              :         }
     445       198766 :         into.writeAttr(SUMO_ATTR_RESPONSE, myResponse[i]);
     446       198766 :         into.writeAttr(SUMO_ATTR_FOES, myFoes[i]);
     447       397532 :         if (!OptionsCont::getOptions().getBool("no-internal-links")) {
     448        92753 :             into.writeAttr(SUMO_ATTR_CONT, myHaveVia[i]);
     449              :         }
     450       397532 :         into.closeTag();
     451              :     }
     452        41640 : }
     453              : 
     454              : 
     455              : void
     456        42632 : NBRequest::computeLogic(const bool checkLaneFoes) {
     457              :     myResponse.clear();
     458              :     myFoes.clear();
     459              :     myHaveVia.clear();
     460              :     int pos = 0;
     461              :     EdgeVector::const_iterator i;
     462              :     // normal connections
     463       130330 :     for (i = myIncoming.begin(); i != myIncoming.end(); i++) {
     464        87698 :         int noLanes = (*i)->getNumLanes();
     465       203232 :         for (int k = 0; k < noLanes; k++) {
     466       117359 :             pos = computeLaneResponse(*i, k, pos, checkLaneFoes || myJunction->getType() == SumoXMLNodeType::ZIPPER);
     467              :         }
     468              :     }
     469              :     // crossings
     470        42632 :     auto crossings = myJunction->getCrossings();
     471        44245 :     for (auto c : crossings) {
     472         1613 :         pos = computeCrossingResponse(*c, pos);
     473              :     }
     474        42632 : }
     475              : 
     476              : void
     477        42632 : NBRequest::resetSignalised() {
     478              :     // go through possible prohibitions
     479       130330 :     for (EdgeVector::const_iterator i11 = myIncoming.begin(); i11 != myIncoming.end(); i11++) {
     480        87698 :         int noLanesEdge1 = (*i11)->getNumLanes();
     481       203232 :         for (int j1 = 0; j1 < noLanesEdge1; j1++) {
     482       115534 :             std::vector<NBEdge::Connection> el1 = (*i11)->getConnectionsFromLane(j1);
     483       319435 :             for (std::vector<NBEdge::Connection>::iterator i12 = el1.begin(); i12 != el1.end(); ++i12) {
     484       203901 :                 int idx1 = getIndex((*i11), (*i12).toEdge);
     485       203901 :                 if (idx1 < 0) {
     486            0 :                     continue;
     487              :                 }
     488              :                 // go through possibly prohibited
     489       829119 :                 for (EdgeVector::const_iterator i21 = myIncoming.begin(); i21 != myIncoming.end(); i21++) {
     490       625218 :                     int noLanesEdge2 = (*i21)->getNumLanes();
     491      1505268 :                     for (int j2 = 0; j2 < noLanesEdge2; j2++) {
     492       880050 :                         std::vector<NBEdge::Connection> el2 = (*i21)->getConnectionsFromLane(j2);
     493      3015209 :                         for (std::vector<NBEdge::Connection>::iterator i22 = el2.begin(); i22 != el2.end(); i22++) {
     494      2135159 :                             int idx2 = getIndex((*i21), (*i22).toEdge);
     495      2135159 :                             if (idx2 < 0) {
     496            0 :                                 continue;
     497              :                             }
     498              :                             // check
     499              :                             // same incoming connections do not prohibit each other
     500      2135159 :                             if ((*i11) == (*i21)) {
     501       640403 :                                 myForbids[idx1][idx2] = false;
     502       640403 :                                 myForbids[idx2][idx1] = false;
     503              : #ifdef DEBUG_SETBLOCKING
     504              :                                 if (DEBUGCOND) std::cout << "resetSignalised both"
     505              :                                                              << " 1:" << (*i11)->getID() << "->" << (*i12).toEdge->getID()
     506              :                                                              << " 2:" << (*i21)->getID() << "->" << (*i22).toEdge->getID()
     507              :                                                              << "\n";
     508              : #endif
     509       640403 :                                 continue;
     510              :                             }
     511              :                             // check other
     512              :                             // if both are non-signalised or both are signalised
     513      1262708 :                             if (((*i12).tlID == "" && (*i22).tlID == "")
     514      1495990 :                                     ||
     515       232048 :                                     ((*i12).tlID != "" && (*i22).tlID != "")) {
     516              :                                 // do nothing
     517      1492288 :                                 continue;
     518              :                             }
     519              :                             // supposing, we don not have to
     520              :                             //  brake if we are no foes
     521         2468 :                             if (!foes(*i11, (*i12).toEdge, *i21, (*i22).toEdge)) {
     522         1930 :                                 continue;
     523              :                             }
     524              :                             // otherwise:
     525              :                             //  the non-signalised must break
     526          538 :                             if ((*i12).tlID != "") {
     527          269 :                                 myForbids[idx1][idx2] = true;
     528          269 :                                 myForbids[idx2][idx1] = false;
     529              : #ifdef DEBUG_SETBLOCKING
     530              :                                 if (DEBUGCOND) std::cout << "resetSignalised:2 yields"
     531              :                                                              << " 1:" << (*i11)->getID() << "->" << (*i12).toEdge->getID()
     532              :                                                              << " 2:" << (*i21)->getID() << "->" << (*i22).toEdge->getID() << "\n";
     533              : #endif
     534              :                             } else {
     535          269 :                                 myForbids[idx1][idx2] = false;
     536          269 :                                 myForbids[idx2][idx1] = true;
     537              : #ifdef DEBUG_SETBLOCKING
     538              :                                 if (DEBUGCOND) std::cout << "resetSignalised:1 yields"
     539              :                                                              << " 1:" << (*i11)->getID() << "->" << (*i12).toEdge->getID()
     540              :                                                              << " 2:" << (*i21)->getID() << "->" << (*i22).toEdge->getID() << "\n";
     541              : #endif
     542              :                             }
     543              :                         }
     544       880050 :                     }
     545              :                 }
     546              :             }
     547       115534 :         }
     548              :     }
     549        42632 : }
     550              : 
     551              : 
     552              : std::pair<int, int>
     553        49522 : NBRequest::getSizes() const {
     554              :     int numLanes = 0;
     555              :     int numLinks = 0;
     556       148369 :     for (const NBEdge* const e : myIncoming) {
     557              :         const int numLanesEdge = e->getNumLanes();
     558       227345 :         for (int j = 0; j < numLanesEdge; j++) {
     559       128498 :             int numConnections = (int)e->getConnectionsFromLane(j).size();
     560       128498 :             numLinks += numConnections;
     561       128498 :             if (numConnections > 0) {
     562       108277 :                 numLanes++;
     563              :             }
     564              :         }
     565              :     }
     566        49522 :     return std::make_pair(numLanes, numLinks);
     567              : }
     568              : 
     569              : 
     570              : bool
     571      3686956 : NBRequest::foes(const NBEdge* const from1, const NBEdge* const to1,
     572              :                 const NBEdge* const from2, const NBEdge* const to2) const {
     573              :     // unconnected edges do not forbid other edges
     574      3686956 :     if (to1 == nullptr || to2 == nullptr) {
     575              :         return false;
     576              :     }
     577              :     // get the indices
     578      3686956 :     int idx1 = getIndex(from1, to1);
     579      3686956 :     int idx2 = getIndex(from2, to2);
     580      3686956 :     if (idx1 < 0 || idx2 < 0) {
     581              :         return false; // sure? (The connection does not exist within this junction)
     582              :     }
     583              :     assert(idx1 < (int)(myIncoming.size() * myOutgoing.size()));
     584              :     assert(idx2 < (int)(myIncoming.size()*myOutgoing.size()));
     585      3531440 :     return myForbids[idx1][idx2] || myForbids[idx2][idx1];
     586              : }
     587              : 
     588              : 
     589              : bool
     590      1460006 : NBRequest::forbids(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,
     591              :                    const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo,
     592              :                    bool regardNonSignalisedLowerPriority) const {
     593              :     // unconnected edges do not forbid other edges
     594      1460006 :     if (possProhibitorTo == nullptr || possProhibitedTo == nullptr) {
     595              :         return false;
     596              :     }
     597              :     // get the indices
     598      1460006 :     int possProhibitorIdx = getIndex(possProhibitorFrom, possProhibitorTo);
     599      1460006 :     int possProhibitedIdx = getIndex(possProhibitedFrom, possProhibitedTo);
     600      1460006 :     if (possProhibitorIdx < 0 || possProhibitedIdx < 0) {
     601              :         return false; // sure? (The connection does not exist within this junction)
     602              :     }
     603              :     assert(possProhibitorIdx < (int)(myIncoming.size() * myOutgoing.size()));
     604              :     assert(possProhibitedIdx < (int)(myIncoming.size() * myOutgoing.size()));
     605              :     // check simple right-of-way-rules
     606      1460006 :     if (!regardNonSignalisedLowerPriority) {
     607       589321 :         return myForbids[possProhibitorIdx][possProhibitedIdx];
     608              :     }
     609              :     // if its not forbidden, report
     610       870685 :     if (!myForbids[possProhibitorIdx][possProhibitedIdx]) {
     611              :         return false;
     612              :     }
     613              :     // do not forbid a signalised stream by a non-signalised
     614       157182 :     if (!possProhibitorFrom->hasSignalisedConnectionTo(possProhibitorTo)) {
     615              :         return false;
     616              :     }
     617              :     return true;
     618              : }
     619              : 
     620              : int
     621       115534 : NBRequest::computeLaneResponse(NBEdge* from, int fromLane, int pos, const bool checkLaneFoes) {
     622       319435 :     for (const NBEdge::Connection& c : from->getConnectionsFromLane(fromLane)) {
     623              :         assert(c.toEdge != 0);
     624       203901 :         pos++;
     625       203901 :         const std::string foes = getFoesString(from, c, checkLaneFoes);
     626       203901 :         const std::string response = getResponseString(from, c, checkLaneFoes);
     627       203901 :         myFoes.push_back(foes);
     628       203901 :         myResponse.push_back(response);
     629       203901 :         myHaveVia.push_back(c.haveVia);
     630       115534 :     }
     631       115534 :     return pos;
     632              : }
     633              : 
     634              : 
     635              : int
     636         1613 : NBRequest::computeCrossingResponse(const NBNode::Crossing& crossing, int pos) {
     637         3226 :     std::string foes(myJunction->getCrossings().size(), '0');
     638         3226 :     std::string response(myJunction->getCrossings().size(), '0');
     639              :     // conflicts with normal connections
     640         7936 :     for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
     641         6323 :         const NBEdge* from = *i;
     642        20610 :         for (int j = from->getNumLanes(); j-- > 0;) {
     643        14287 :             const std::vector<NBEdge::Connection>& connected = from->getConnectionsFromLane(j);
     644        14287 :             const int size = (int) connected.size();
     645        32553 :             for (int k = size; k-- > 0;) {
     646        18266 :                 const NBEdge* to = connected[k].toEdge;
     647              :                 bool foe = false;
     648        38283 :                 for (const NBEdge* const e : crossing.edges) {
     649        28050 :                     if (e == from || e == to) {
     650              :                         foe = true;
     651              :                         break;
     652              :                     }
     653              :                 }
     654        18266 :                 foes += foe ? '1' : '0';
     655        18266 :                 response += mustBrakeForCrossing(myJunction, from, to, crossing) || !foe ? '0' : '1';
     656              :             }
     657        14287 :         }
     658              :     }
     659         1613 :     pos++;
     660         1613 :     myResponse.push_back(response);
     661         1613 :     myFoes.push_back(foes);
     662         1613 :     myHaveVia.push_back(false);
     663         1613 :     return pos;
     664              : }
     665              : 
     666              : 
     667              : std::string
     668       203901 : NBRequest::getResponseString(const NBEdge* const from, const NBEdge::Connection& c, const bool checkLaneFoes) const {
     669       203901 :     const NBEdge* const to = c.toEdge;
     670       203901 :     const int fromLane = c.fromLane;
     671       203901 :     const int toLane = c.toLane;
     672              :     int idx = 0;
     673       203901 :     if (to != nullptr) {
     674       203901 :         idx = getIndex(from, to);
     675              :     }
     676              :     std::string result;
     677       203901 :     const bool zipper = myJunction->getType() == SumoXMLNodeType::ZIPPER;
     678              :     // crossings
     679       203901 :     auto crossings = myJunction->getCrossings();
     680       222167 :     for (std::vector<NBNode::Crossing*>::const_reverse_iterator i = crossings.rbegin(); i != crossings.rend(); i++) {
     681        18266 :         result += mustBrakeForCrossing(myJunction, from, to, **i) ? '1' : '0';
     682              :     }
     683              :     // normal connections
     684       829119 :     for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
     685              :         //const std::vector<NBEdge::Connection> &allConnections = (*i)->getConnections();
     686       625218 :         int noLanes = (*i)->getNumLanes();
     687      1505268 :         for (int j = noLanes; j-- > 0;) {
     688       880050 :             std::vector<NBEdge::Connection> connected = (*i)->getConnectionsFromLane(j);
     689       880050 :             int size = (int) connected.size();
     690      3015209 :             for (int k = size; k-- > 0;) {
     691      2135159 :                 if (c.mayDefinitelyPass) {
     692              :                     result += '0';
     693              : #ifdef DEBUG_RESPONSE
     694              :                     if (DEBUGCOND) {
     695              :                         std::cout << " c=" << c.getDescription(from) << " pass\n";
     696              :                     }
     697              : #endif
     698      2135038 :                 } else if ((*i) == from && fromLane == j) {
     699              :                     // do not prohibit a connection by others from same lane
     700              :                     // except for indirect turns
     701              : #ifdef DEBUG_RESPONSE
     702              :                     if (DEBUGCOND) {
     703              :                         std::cout << " c=" << c.getDescription(from) << " prohibitC=" << connected[k].getDescription(*i)
     704              :                                   << " itc=" <<  indirectLeftTurnConflict(from, c, *i, connected[k], false)
     705              :                                   << "\n";
     706              :                     }
     707              : #endif
     708       515246 :                     if (indirectLeftTurnConflict(from, c, *i, connected[k], false)) {
     709              :                         result += '1';
     710              :                     } else {
     711              :                         result += '0';
     712              :                     }
     713              :                 } else {
     714              :                     assert(connected[k].toEdge != 0);
     715      1619792 :                     const int idx2 = getIndex(*i, connected[k].toEdge);
     716              :                     assert(k < (int) connected.size());
     717              :                     assert(idx < (int)(myIncoming.size() * myOutgoing.size()));
     718              :                     assert(idx2 < (int)(myIncoming.size() * myOutgoing.size()));
     719              :                     // check whether the connection is prohibited by another one
     720              : #ifdef DEBUG_RESPONSE
     721              :                     if (DEBUGCOND) {
     722              :                         std::cout << " c=" << c.getDescription(from) << " prohibitC=" << connected[k].getDescription(*i)
     723              :                                   << " idx=" << idx << " idx2=" << idx2
     724              :                                   << " f=" << myForbids[idx2][idx]
     725              :                                   << " clf=" << checkLaneFoes
     726              :                                   << " clfbc=" << checkLaneFoesByClass(c, *i, connected[k])
     727              :                                   << " clfbcoop=" << checkLaneFoesByCooperation(from, c, *i, connected[k])
     728              :                                   << " lc=" << laneConflict(from, to, toLane, *i, connected[k].toEdge, connected[k].toLane)
     729              :                                   << " rtc=" << NBNode::rightTurnConflict(from, to, fromLane, *i, connected[k].toEdge, connected[k].fromLane)
     730              :                                   << " rtc2=" << rightTurnConflict(from, c, *i, connected[k])
     731              :                                   << " mc=" << mergeConflict(from, c, *i, connected[k], false)
     732              :                                   << " oltc=" << oppositeLeftTurnConflict(from, c, *i, connected[k], false)
     733              :                                   << " itc=" <<  indirectLeftTurnConflict(from, c, *i, connected[k], zipper)
     734              :                                   << " bc=" <<  bidiConflict(from, c, *i, connected[k], false)
     735              :                                   << " ec=" << (myJunction->extraConflict(c.tlLinkIndex, connected[k].tlLinkIndex) && (myForbids[idx2][idx] || myForbids[idx][idx2]))
     736              :                                   << " tlscc=" << myJunction->tlsStrandedConflict(from, c, *i, connected[k])
     737              :                                   << "\n";
     738              :                     }
     739              : #endif
     740      3194418 :                     const bool hasLaneConflict = (!(checkLaneFoes || checkLaneFoesByClass(c, *i, connected[k])
     741      1584926 :                                                     || checkLaneFoesByCooperation(from, c, *i, connected[k]))
     742      1661087 :                                                   || laneConflict(from, to, toLane, *i, connected[k].toEdge, connected[k].toLane));
     743      3239584 :                     if (((myForbids[idx2][idx] || (zipper && myForbids[idx][idx2])) && hasLaneConflict && !bidiConflict(*i, connected[k], from, c, false))
     744      1289258 :                             || rightTurnConflict(from, c, *i, connected[k])
     745      1288657 :                             || mergeConflict(from, c, *i, connected[k], zipper)
     746      1288453 :                             || oppositeLeftTurnConflict(from, c, *i, connected[k], zipper)
     747      1285796 :                             || indirectLeftTurnConflict(from, c, *i, connected[k], zipper)
     748      1285796 :                             || bidiConflict(from, c, *i, connected[k], false)
     749              :                             // the extra conflict could be specific to another connection within the same signal group
     750      1285821 :                             || (myJunction->extraConflict(c.tlLinkIndex, connected[k].tlLinkIndex) && (myForbids[idx2][idx] || myForbids[idx][idx2]))
     751      2905532 :                             || (myJunction->tlsStrandedConflict(from, c, *i, connected[k])
     752         8382 :                                 && laneConflict(from, to, toLane, *i, connected[k].toEdge, connected[k].toLane)
     753      1633366 :                                 && !OptionsCont::getOptions().getBool("tls.ignore-internal-junction-jam"))
     754              :                        ) {
     755              :                         result += '1';
     756              :                     } else {
     757              :                         result += '0';
     758              :                     }
     759              :                 }
     760              :             }
     761       880050 :         }
     762              :     }
     763       203901 :     return result;
     764       203901 : }
     765              : 
     766              : 
     767              : std::string
     768       203901 : NBRequest::getFoesString(NBEdge* from, const NBEdge::Connection& c, const bool checkLaneFoes) const {
     769       407802 :     const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
     770              :     // remember the case when the lane is a "dead end" in the meaning that
     771              :     // vehicles must choose another lane to move over the following
     772              :     // junction
     773              :     // !!! move to forbidden
     774              :     std::string result;
     775              :     // crossings
     776       203901 :     auto crossings = myJunction->getCrossings();
     777       222167 :     for (std::vector<NBNode::Crossing*>::const_reverse_iterator i = crossings.rbegin(); i != crossings.rend(); i++) {
     778              :         bool foes = false;
     779        38283 :         for (EdgeVector::const_iterator it_e = (**i).edges.begin(); it_e != (**i).edges.end(); ++it_e) {
     780        28050 :             if ((*it_e) == from || (*it_e) == c.toEdge) {
     781              :                 foes = true;
     782              :                 break;
     783              :             }
     784              :         }
     785        18266 :         result += foes ? '1' : '0';
     786              :     }
     787              :     // normal connections
     788       829119 :     for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
     789      1505268 :         for (int j = (*i)->getNumLanes() - 1; j >= 0; --j) {
     790       880050 :             const std::vector<NBEdge::Connection>& connected = (*i)->getConnectionsFromLane(j);
     791       880050 :             int size = (int) connected.size();
     792      3015209 :             for (int k = size; k-- > 0;) {
     793      4209563 :                 const bool hasLaneConflict = (!(checkLaneFoes || checkLaneFoesByClass(c, *i, connected[k])
     794      2088238 :                                                 || checkLaneFoesByCooperation(from, c, *i, connected[k]))
     795      2185001 :                                               || laneConflict(from, c.toEdge, c.toLane, *i, connected[k].toEdge, connected[k].toLane));
     796      2817357 :                 if ((foes(from, c.toEdge, (*i), connected[k].toEdge) && hasLaneConflict)
     797      1474344 :                         || rightTurnConflict(from, c, *i, connected[k])
     798      1473743 :                         || myJunction->turnFoes(from, c.toEdge, c.fromLane, *i, connected[k].toEdge, connected[k].fromLane, lefthand)
     799      1473076 :                         || mergeConflict(from, c, *i, connected[k], true)
     800      1472680 :                         || oppositeLeftTurnConflict(from, c, *i, connected[k], true)
     801      1467365 :                         || indirectLeftTurnConflict(from, c, *i, connected[k], true)
     802      3602502 :                         || bidiConflict(from, c, *i, connected[k], true)
     803              :                    ) {
     804              :                     result += '1';
     805              :                 } else {
     806              :                     result += '0';
     807              :                 }
     808              :             }
     809       880050 :         }
     810              :     }
     811       203901 :     return result;
     812       203901 : }
     813              : 
     814              : 
     815              : bool
     816      2764166 : NBRequest::rightTurnConflict(const NBEdge* from, const NBEdge::Connection& con,
     817              :                              const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon) const {
     818      5528217 :     return (!con.mayDefinitelyPass &&
     819      2764051 :             (NBNode::rightTurnConflict(from, con.toEdge, con.fromLane, prohibitorFrom, prohibitorCon.toEdge, prohibitorCon.fromLane)
     820              :              // reverse conflicht (override)
     821      2762820 :              || (prohibitorCon.mayDefinitelyPass &&
     822           72 :                  NBNode::rightTurnConflict(prohibitorFrom, prohibitorCon.toEdge, prohibitorCon.fromLane, from, con.toEdge, con.fromLane))));
     823              : 
     824              : 
     825              : }
     826              : 
     827              : 
     828              : bool
     829      4241560 : NBRequest::mergeConflict(const NBEdge* from, const NBEdge::Connection& con,
     830              :                          const NBEdge* prohibitorFrom,  const NBEdge::Connection& prohibitorCon, bool foes) const {
     831              :     if (from == prohibitorFrom
     832      1189296 :             && con.toEdge == prohibitorCon.toEdge
     833      4688018 :             && ((con.toLane == prohibitorCon.toLane
     834       326698 :                  && con.fromLane != prohibitorCon.fromLane
     835         1461 :                  && !myJunction->isConstantWidthTransition())
     836              :                 // this is actually a crossing rather than a merger
     837       445001 :                 || (con.fromLane > prohibitorCon.fromLane && con.toLane < prohibitorCon.toLane)
     838       444993 :                 || (con.fromLane < prohibitorCon.fromLane && con.toLane > prohibitorCon.toLane))) {
     839         1473 :         if (foes) {
     840              :             return true;
     841              :         }
     842          881 :         if (prohibitorCon.mayDefinitelyPass) {
     843              :             return true;
     844              :         }
     845          878 :         if (con.mayDefinitelyPass) {
     846              :             return false;
     847              :         }
     848          878 :         const bool bike = from->getPermissions(con.fromLane) == SVC_BICYCLE;
     849          878 :         const bool prohibitorBike = prohibitorFrom->getPermissions(prohibitorCon.fromLane) == SVC_BICYCLE;
     850          878 :         if (myOutgoing.size() == 1) {
     851              :             // at on-ramp like situations, right lane should yield
     852           51 :             return bike || (con.fromLane < prohibitorCon.fromLane && !prohibitorBike);
     853              :         } else {
     854              :             // priority depends on direction:
     855              :             // for right turns the rightmost lane gets priority
     856              :             // otherwise the left lane
     857          844 :             LinkDirection dir = myJunction->getDirection(from, con.toEdge);
     858          844 :             if (dir == LinkDirection::RIGHT || dir == LinkDirection::PARTRIGHT) {
     859          533 :                 return con.fromLane > prohibitorCon.fromLane;
     860              :             } else {
     861          311 :                 if (myIncoming.size() == 1) {
     862              :                     // at off-ramp like situations, right lane should pass unless it's a bicycle lane
     863            6 :                     return bike || (con.fromLane > prohibitorCon.fromLane && !prohibitorBike);
     864              :                 } else {
     865          307 :                     return con.fromLane < prohibitorCon.fromLane;
     866              :                 }
     867              :             }
     868              :         }
     869              : 
     870              :     } else {
     871      4240087 :         return false;
     872              :     }
     873              : }
     874              : 
     875              : 
     876              : bool
     877      2761133 : NBRequest::oppositeLeftTurnConflict(const NBEdge* from, const NBEdge::Connection& con,
     878              :                                     const NBEdge* prohibitorFrom,  const NBEdge::Connection& prohibitorCon, bool foes) const {
     879      2761133 :     LinkDirection dir = myJunction->getDirection(from, con.toEdge);
     880              :     // XXX lefthand issue (solve via #4256)
     881      2761133 :     if (dir != LinkDirection::LEFT && dir != LinkDirection::PARTLEFT) {
     882              :         return false;
     883              :     }
     884       563089 :     dir = myJunction->getDirection(prohibitorFrom, prohibitorCon.toEdge);
     885       563089 :     if (dir != LinkDirection::LEFT && dir != LinkDirection::PARTLEFT) {
     886              :         return false;
     887              :     }
     888       155656 :     if (from == prohibitorFrom || NBRequest::foes(from, con.toEdge, prohibitorFrom, prohibitorCon.toEdge)) {
     889              :         // not an opposite pair
     890        87564 :         return false;
     891              :     }
     892              : 
     893        68092 :     const double width1 = MIN2(from->getLaneWidth(con.fromLane) / 2, OptionsCont::getOptions().getFloat("internal-junctions.vehicle-width") / 2);
     894        68092 :     const double width2 = prohibitorCon.toEdge->getLaneWidth(prohibitorCon.toLane) / 2;
     895              :     PositionVector shape = con.shape;
     896        68092 :     shape.append(con.viaShape);
     897              :     PositionVector otherShape = prohibitorCon.shape;
     898        68092 :     otherShape.append(prohibitorCon.viaShape);
     899        68092 :     if (shape.size() == 0 || otherShape.size() == 0) {
     900              :         // no internal lanes built
     901              :         return false;
     902              :     }
     903        21980 :     const double minDV = NBEdge::firstIntersection(shape, otherShape, width1, width2);
     904        21980 :     if (minDV < shape.length() - POSITION_EPS && minDV > POSITION_EPS) {
     905              :         // break symmetry using edge id
     906        10630 :         return foes || from->getID() < prohibitorFrom->getID();
     907              :     }
     908              :     return false;
     909        68092 : }
     910              : 
     911              : bool
     912      3704642 : NBRequest::indirectLeftTurnConflict(const NBEdge* from, const NBEdge::Connection& con,
     913              :                                     const NBEdge* prohibitorFrom,  const NBEdge::Connection& prohibitorCon, bool foes) const {
     914      3704642 :     if (from == prohibitorFrom) {
     915      1401831 :         if (con.toEdge == prohibitorCon.toEdge) {
     916              :             return false;
     917       838607 :         } else if (con.indirectLeft) {
     918          126 :             LinkDirection dir = myJunction->getDirection(prohibitorFrom, prohibitorCon.toEdge);
     919          126 :             return (dir == LinkDirection::STRAIGHT);
     920       838481 :         } else if (foes && prohibitorCon.indirectLeft) {
     921           27 :             LinkDirection dir = myJunction->getDirection(from, con.toEdge);
     922           27 :             return (dir == LinkDirection::STRAIGHT);
     923              :         }
     924              :     }
     925              :     return false;
     926              : }
     927              : 
     928              : bool
     929      3821634 : NBRequest::bidiConflict(const NBEdge* from, const NBEdge::Connection& con,
     930              :                         const NBEdge* prohibitorFrom,  const NBEdge::Connection& prohibitorCon, bool foes) const {
     931      3821634 :     if (from == prohibitorFrom) {
     932              :         return false;
     933              :     }
     934      2847753 :     if (isRailway(from->getPermissions())) {
     935              :         // railways manage right-of-way via signals
     936              :         return false;
     937              :     }
     938      1345411 :     if ((foes && (from->getBidiEdge() == prohibitorCon.toEdge))
     939      4166769 :             || prohibitorFrom->getBidiEdge() == con.toEdge) {
     940         1044 :         const bool fromBidi = from->getLaneShape(con.fromLane).reverse().almostSame(
     941          522 :                                   prohibitorCon.toEdge->getLaneShape(prohibitorCon.toLane), POSITION_EPS);
     942         1044 :         const bool prohibitorFromBidi = prohibitorFrom->getLaneShape(prohibitorCon.fromLane).reverse().almostSame(
     943          522 :                                             con.toEdge->getLaneShape(con.toLane), POSITION_EPS);
     944          522 :         if (!foes && fromBidi && prohibitorFromBidi) {
     945              :             // do not create a symmetrical conflict
     946              :             return false;
     947              :         }
     948          506 :         if (prohibitorFromBidi &&
     949          613 :                 prohibitorFrom->getLaneShape(prohibitorCon.fromLane).reverse().almostSame(
     950          107 :                     prohibitorCon.toEdge->getLaneShape(prohibitorCon.toLane), POSITION_EPS)) {
     951              :             // prohibitor has a bidi-turnaround
     952              :             return false;
     953              :         }
     954              : 
     955          461 :         return fromBidi || prohibitorFromBidi;
     956              :     }
     957              :     return false;
     958              : }
     959              : 
     960              : bool
     961      3730817 : NBRequest::checkLaneFoesByClass(const NBEdge::Connection& con,
     962              :                                 const NBEdge* prohibitorFrom,  const NBEdge::Connection& prohibitorCon) const {
     963      3730817 :     if (con.toEdge != prohibitorCon.toEdge) {
     964              :         return false;
     965              :     }
     966      1059125 :     SVCPermissions svc = con.toEdge->getPermissions(con.toLane);
     967      1059125 :     SVCPermissions svc2 = prohibitorFrom->getPermissions(prohibitorCon.fromLane) & prohibitorCon.toEdge->getPermissions(prohibitorCon.toLane);
     968              :     // check for lane level conflict if the only common classes are bicycles or pedestrians
     969      1059125 :     return ((svc & svc2 & ~(SVC_BICYCLE | SVC_PEDESTRIAN)) == 0
     970              :             // or if the connection is to a dedicated lane whereas the prohibitor is a "general" lane
     971      1059125 :             || (((svc & SVC_PASSENGER) == 0) && ((svc2 & SVC_PASSENGER) != 0)));
     972              : }
     973              : 
     974              : 
     975              : bool
     976      3673164 : NBRequest::checkLaneFoesByCooperation(const NBEdge* from, const NBEdge::Connection& con,
     977              :                                       const NBEdge* prohibitorFrom,  const NBEdge::Connection& prohibitorCon) const {
     978      3673164 :     if (con.toEdge != prohibitorCon.toEdge) {
     979              :         return false;
     980              :     }
     981              :     // if from and prohibitorFrom target distinct lanes for all their
     982              :     // connections to the common target edge, cooperation is possible
     983              :     // (and should always happen unless the connections cross for some byzantine reason)
     984              : 
     985              :     std::set<int> fromTargetLanes;
     986      4873334 :     for (const NBEdge::Connection& c : from->getConnections()) {
     987      3871862 :         if (c.toEdge == con.toEdge) {
     988      1455361 :             fromTargetLanes.insert(c.toLane);
     989              :         }
     990              :     }
     991      2368071 :     for (const NBEdge::Connection& c : prohibitorFrom->getConnections()) {
     992      2334587 :         if (c.toEdge == con.toEdge && fromTargetLanes.count(c.toLane) != 0) {
     993              :             //std::cout << " con=" << con->getDescription(from) << " foe=" << prohibitorCon.getDescription(prohibitorFrom)
     994              :             //    << " no cooperation (targets=" << joinToString(fromTargetLanes, ' ') << " index=" << c.toLane << "\n";
     995              :             return false;
     996              :         }
     997              :     }
     998              :     return true;
     999              : }
    1000              : 
    1001              : 
    1002              : bool
    1003       123653 : NBRequest::laneConflict(const NBEdge* from, const NBEdge* to, int toLane,
    1004              :                         const NBEdge* prohibitorFrom, const NBEdge* prohibitorTo, int prohibitorToLane) const {
    1005       123653 :     if (to != prohibitorTo) {
    1006              :         return true;
    1007              :     }
    1008              :     // since we know that the edge2edge connections are in conflict, the only
    1009              :     // situation in which the lane2lane connections can be conflict-free is, if
    1010              :     // they target the same edge but do not cross each other
    1011       106655 :     double angle = NBHelpers::relAngle(
    1012              :                        from->getAngleAtNode(from->getToNode()), to->getAngleAtNode(to->getFromNode()));
    1013       106655 :     if (angle == 180) {
    1014              :         angle = -180; // turnarounds are left turns
    1015              :     }
    1016       106655 :     const double prohibitorAngle = NBHelpers::relAngle(
    1017              :                                        prohibitorFrom->getAngleAtNode(prohibitorFrom->getToNode()), to->getAngleAtNode(to->getFromNode()));
    1018       106655 :     const bool rightOfProhibitor = prohibitorFrom->isTurningDirectionAt(to)
    1019       106655 :                                    || (angle > prohibitorAngle && !from->isTurningDirectionAt(to));
    1020       106655 :     return rightOfProhibitor ? toLane >= prohibitorToLane : toLane <= prohibitorToLane;
    1021              : }
    1022              : 
    1023              : int
    1024     16755521 : NBRequest::getIndex(const NBEdge* const from, const NBEdge* const to) const {
    1025     16755521 :     EdgeVector::const_iterator fp = std::find(myIncoming.begin(), myIncoming.end(), from);
    1026     16755521 :     EdgeVector::const_iterator tp = std::find(myOutgoing.begin(), myOutgoing.end(), to);
    1027     16755521 :     if (fp == myIncoming.end() || tp == myOutgoing.end()) {
    1028              :         return -1;
    1029              :     }
    1030              :     // compute the index
    1031     16600005 :     return (int)(distance(myIncoming.begin(), fp) * myOutgoing.size() + distance(myOutgoing.begin(), tp));
    1032              : }
    1033              : 
    1034              : 
    1035              : std::ostream&
    1036            0 : operator<<(std::ostream& os, const NBRequest& r) {
    1037            0 :     int variations = r.numLinks();
    1038            0 :     for (int i = 0; i < variations; i++) {
    1039            0 :         os << i << ' ';
    1040            0 :         for (int j = 0; j < variations; j++) {
    1041            0 :             if (r.myForbids[i][j]) {
    1042            0 :                 os << '1';
    1043              :             } else {
    1044            0 :                 os << '0';
    1045              :             }
    1046              :         }
    1047              :         os << std::endl;
    1048              :     }
    1049              :     os << std::endl;
    1050            0 :     return os;
    1051              : }
    1052              : 
    1053              : 
    1054              : bool
    1055       228767 : NBRequest::mustBrake(const NBEdge* const from, const NBEdge* const to, int fromLane, int toLane, bool includePedCrossings) const {
    1056       228767 :     NBEdge::Connection con(fromLane, const_cast<NBEdge*>(to), toLane);
    1057       228767 :     const int linkIndex = myJunction->getConnectionIndex(from, con);
    1058       228767 :     if (linkIndex >= 0 && (int)myResponse.size() > linkIndex) {
    1059       206926 :         std::string response = getResponse(linkIndex);
    1060       206926 :         if (!includePedCrossings) {
    1061          304 :             response = response.substr(0, response.size() - myJunction->getCrossings().size());
    1062              :         }
    1063       206926 :         if (response.find_first_of("1") == std::string::npos) {
    1064              :             return false;
    1065       100052 :         } else if (!myJunction->isTLControlled()) {
    1066              :             return true;
    1067              :         }
    1068              :         // if the link must respond it could also be due to a tlsConflict. This
    1069              :         // must not carry over the off-state response so we continue with
    1070              :         // the regular check
    1071              :     }
    1072              :     // get the indices
    1073        36333 :     int idx2 = getIndex(from, to);
    1074        36333 :     if (idx2 == -1) {
    1075              :         return false;
    1076              :     }
    1077              :     // go through all (existing) connections;
    1078              :     //  check whether any of these forbids the one to determine
    1079              :     assert(idx2 < (int)(myIncoming.size()*myOutgoing.size()));
    1080       239665 :     for (int idx1 = 0; idx1 < numLinks(); idx1++) {
    1081              :         //assert(myDone[idx1][idx2]);
    1082       330867 :         if (myDone[idx1][idx2] && myForbids[idx1][idx2]) {
    1083              :             return true;
    1084              :         }
    1085              :     }
    1086              :     // maybe we need to brake for a pedestrian crossing
    1087         2700 :     if (includePedCrossings) {
    1088         2306 :         auto crossings = myJunction->getCrossings();
    1089         2976 :         for (std::vector<NBNode::Crossing*>::const_reverse_iterator i = crossings.rbegin(); i != crossings.rend(); i++) {
    1090         1488 :             if (mustBrakeForCrossing(myJunction, from, to, **i)) {
    1091              :                 return true;
    1092              :             }
    1093              :         }
    1094         2306 :     }
    1095              :     // maybe we need to brake due to a right-turn conflict with straight-going
    1096              :     // bicycles
    1097         1882 :     const NBEdge::Connection& queryCon = from->getConnection(fromLane, to, toLane);
    1098         1882 :     LinkDirection dir = myJunction->getDirection(from, to);
    1099         1882 :     if (dir == LinkDirection::RIGHT || dir == LinkDirection::PARTRIGHT) {
    1100          631 :         for (const NBEdge::Connection& fromCon : from->getConnections()) {
    1101          564 :             if (rightTurnConflict(from, queryCon, from, fromCon)) {
    1102              :                 return true;
    1103              :             }
    1104              :         }
    1105              :     }
    1106              :     // maybe we need to brake due to a merge conflict
    1107         9397 :     for (EdgeVector::const_reverse_iterator i = myIncoming.rbegin(); i != myIncoming.rend(); i++) {
    1108         7635 :         int noLanes = (*i)->getNumLanes();
    1109        22428 :         for (int j = noLanes; j-- > 0;) {
    1110        14806 :             std::vector<NBEdge::Connection> connected = (*i)->getConnectionsFromLane(j);
    1111        14806 :             const int size = (int) connected.size();
    1112        46273 :             for (int k = size; k-- > 0;) {
    1113        39496 :                 if ((*i) == from && fromLane != j
    1114        35093 :                         && mergeConflict(from, queryCon, *i, connected[k], myJunction->getType() == SumoXMLNodeType::ZIPPER)) {
    1115              :                     return true;
    1116              :                 }
    1117              :             }
    1118        14806 :         }
    1119              :     }
    1120              :     // maybe we need to brake due to a zipper conflict
    1121         1762 :     if (myJunction->getType() == SumoXMLNodeType::ZIPPER) {
    1122            0 :         for (int idx1 = 0; idx1 < numLinks(); idx1++) {
    1123              :             //assert(myDone[idx1][idx2]);
    1124            0 :             if (myDone[idx1][idx2] && myForbids[idx2][idx1]) {
    1125              :                 return true;
    1126              :             }
    1127              :         }
    1128              :     }
    1129              :     return false;
    1130       228767 : }
    1131              : 
    1132              : 
    1133              : bool
    1134        44546 : NBRequest::mustBrakeForCrossing(const NBNode* node, const NBEdge* const from, const NBEdge* const to, const NBNode::Crossing& crossing) {
    1135        44546 :     const LinkDirection dir = node->getDirection(from, to);
    1136        44546 :     const bool mustYield = dir == LinkDirection::LEFT || dir == LinkDirection::RIGHT;
    1137        44546 :     if (crossing.priority || mustYield) {
    1138        77424 :         for (const NBEdge* const e : crossing.edges) {
    1139              :             // left and right turns must yield to unprioritized crossings only on their destination edge
    1140        53777 :             if ((e == from && crossing.priority) || e == to) {
    1141              :                 return true;
    1142              :             }
    1143              :         }
    1144              :     }
    1145              :     return false;
    1146              : }
    1147              : 
    1148              : 
    1149              : bool
    1150            0 : NBRequest::mustBrake(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,
    1151              :                      const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo) const {
    1152              :     // get the indices
    1153            0 :     int idx1 = getIndex(possProhibitorFrom, possProhibitorTo);
    1154            0 :     int idx2 = getIndex(possProhibitedFrom, possProhibitedTo);
    1155            0 :     return (myForbids[idx2][idx1]);
    1156              : }
    1157              : 
    1158              : 
    1159              : void
    1160         1840 : NBRequest::reportWarnings() {
    1161              :     // check if any errors occurred on build the link prohibitions
    1162         1840 :     if (myNotBuild != 0) {
    1163            0 :         WRITE_WARNING(toString(myNotBuild) + " of " + toString(myNotBuild + myGoodBuilds) + " prohibitions were not build.");
    1164              :     }
    1165         1840 : }
    1166              : 
    1167              : 
    1168              : void
    1169        42632 : NBRequest::resetCooperating() {
    1170              :     // map from edge to number of incoming connections
    1171              :     std::map<const NBEdge*, int> incomingCount; // initialized to 0
    1172              :     // map from edge to indices of approached lanes
    1173              :     std::map<const NBEdge*, std::set<int> > approachedLanes;
    1174              :     // map from edge to list of incoming edges
    1175              :     std::map<const NBEdge*, std::vector<const NBEdge*> > incomingEdges;
    1176       130330 :     for (const NBEdge* const e : myIncoming) {
    1177       291599 :         for (const NBEdge::Connection& con : e->getConnections()) {
    1178       203901 :             incomingCount[con.toEdge]++;
    1179       203901 :             approachedLanes[con.toEdge].insert(con.toLane);
    1180       203901 :             incomingEdges[con.toEdge].push_back(e);
    1181              :         }
    1182              :     }
    1183       128159 :     for (std::map<const NBEdge*, int>::iterator it = incomingCount.begin(); it != incomingCount.end(); ++it) {
    1184        85527 :         const NBEdge* const to = it->first;
    1185              :         // we cannot test against to->getNumLanes() since not all lanes may be used
    1186        85527 :         if ((int)approachedLanes[to].size() >= it->second) {
    1187        36279 :             const std::vector<const NBEdge*>& incoming = incomingEdges[to];
    1188              :             // make these connections mutually unconflicting
    1189        83042 :             for (const NBEdge* const e1 : incoming) {
    1190       125948 :                 for (const NBEdge* const e2 : incoming) {
    1191        79185 :                     myForbids[getIndex(e1, to)][getIndex(e2, to)] = false;
    1192              : #ifdef DEBUG_SETBLOCKING
    1193              :                     if (DEBUGCOND) std::cout << "resetCooperating"
    1194              :                                                  << " 1:" << e1->getID() << "->" << to->getID()
    1195              :                                                  << " 2:" << e2->getID() << "->" << to->getID()
    1196              :                                                  << "\n";
    1197              : #endif
    1198              :                 }
    1199              :             }
    1200              :         }
    1201              :     }
    1202        42632 : }
    1203              : 
    1204              : 
    1205              : bool
    1206        42814 : NBRequest::hasConflict() const {
    1207        84344 :     for (int i = 0; i < (int)myFoes.size(); i++) {
    1208        61426 :         if (hasConflictAtLink(i)) {
    1209              :             return true;
    1210              :         }
    1211              :     }
    1212              :     return false;
    1213              : }
    1214              : 
    1215              : bool
    1216        62645 : NBRequest::hasConflictAtLink(int linkIndex) const {
    1217        62645 :     return myFoes[linkIndex].find_first_of("1") != std::string::npos;
    1218              : }
    1219              : 
    1220              : int
    1221       288741 : NBRequest::numLinks() const {
    1222       288741 :     return (int)(myIncoming.size() * myOutgoing.size() + myJunction->getCrossings().size());
    1223              : }
    1224              : 
    1225              : 
    1226              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1