1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 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 /****************************************************************************/
10 /// @file    MSRightOfWayJunction.cpp
11 /// @author  Christian Roessel
12 /// @author  Daniel Krajzewicz
13 /// @author  Michael Behrisch
14 /// @author  Jakob Erdmann
15 /// @date    Wed, 12 Dez 2001
16 /// @version $Id$
17 ///
18 // junction.
19 /****************************************************************************/
20 
21 
22 // ===========================================================================
23 // included modules
24 // ===========================================================================
25 #include <config.h>
26 
27 #include "MSRightOfWayJunction.h"
28 #include "MSLane.h"
29 #include "MSEdge.h"
30 #include "MSJunctionLogic.h"
31 #include "MSGlobals.h"
32 #include <algorithm>
33 #include <cassert>
34 #include <cmath>
35 #include <utils/common/RandHelper.h>
36 
37 
38 // ===========================================================================
39 // method definitions
40 // ===========================================================================
MSRightOfWayJunction(const std::string & id,SumoXMLNodeType type,const Position & position,const PositionVector & shape,std::vector<MSLane * > incoming,std::vector<MSLane * > internal,MSJunctionLogic * logic)41 MSRightOfWayJunction::MSRightOfWayJunction(const std::string& id,
42         SumoXMLNodeType type,
43         const Position& position,
44         const PositionVector& shape,
45         std::vector<MSLane*> incoming,
46         std::vector<MSLane*> internal,
47         MSJunctionLogic* logic) : MSLogicJunction(id, type, position, shape, incoming, internal),
48     myLogic(logic) {}
49 
50 
~MSRightOfWayJunction()51 MSRightOfWayJunction::~MSRightOfWayJunction() {
52     delete myLogic;
53 }
54 
55 
56 void
postloadInit()57 MSRightOfWayJunction::postloadInit() {
58     // inform links where they have to report approaching vehicles to
59     int requestPos = 0;
60     std::vector<MSLane*>::iterator i;
61     // going through the incoming lanes...
62     int maxNo = 0;
63     std::vector<std::pair<MSLane*, MSLink*> > sortedLinks;
64     for (i = myIncomingLanes.begin(); i != myIncomingLanes.end(); ++i) {
65         const MSLinkCont& links = (*i)->getLinkCont();
66         // ... set information for every link
67         for (MSLinkCont::const_iterator j = links.begin(); j != links.end(); j++) {
68             if ((*j)->getLane()->getEdge().isWalkingArea() ||
69                     ((*i)->getEdge().isWalkingArea() && !(*j)->getLane()->getEdge().isCrossing())) {
70                 continue;
71             }
72             sortedLinks.push_back(std::make_pair(*i, *j));
73             ++maxNo;
74         }
75     }
76 
77     const bool hasFoes = myLogic->hasFoes();
78     for (i = myIncomingLanes.begin(); i != myIncomingLanes.end(); ++i) {
79         const MSLinkCont& links = (*i)->getLinkCont();
80         // ... set information for every link
81         const MSLane* walkingAreaFoe = nullptr;
82         for (MSLinkCont::const_iterator j = links.begin(); j != links.end(); j++) {
83             if ((*j)->getLane()->getEdge().isWalkingArea()) {
84                 if ((*i)->getPermissions() != SVC_PEDESTRIAN) {
85                     // vehicular lane connects to a walkingarea
86                     walkingAreaFoe = (*j)->getLane();
87                 }
88                 continue;
89             } else if (((*i)->getEdge().isWalkingArea() && !(*j)->getLane()->getEdge().isCrossing())) {
90                 continue;
91             }
92             if (myLogic->getLogicSize() <= requestPos) {
93                 throw ProcessError("Found invalid logic position of a link for junction '" + getID() + "' (" + toString(requestPos) + ", max " + toString(myLogic->getLogicSize()) + ") -> (network error)");
94             }
95             const MSLogicJunction::LinkBits& linkResponse = myLogic->getResponseFor(requestPos); // SUMO_ATTR_RESPONSE
96             const MSLogicJunction::LinkBits& linkFoes = myLogic->getFoesFor(requestPos); // SUMO_ATTR_FOES
97             bool cont = myLogic->getIsCont(requestPos);
98             myLinkFoeLinks[*j] = std::vector<MSLink*>();
99             for (int c = 0; c < maxNo; ++c) {
100                 if (linkResponse.test(c)) {
101                     MSLink* foe = sortedLinks[c].second;
102                     myLinkFoeLinks[*j].push_back(foe);
103                     if (MSGlobals::gUsingInternalLanes && foe->getViaLane() != nullptr) {
104                         assert(foe->getViaLane()->getLinkCont().size() == 1);
105                         MSLink* foeExitLink = foe->getViaLane()->getLinkCont()[0];
106                         // add foe links after an internal junction
107                         if (foeExitLink->getViaLane() != nullptr) {
108                             myLinkFoeLinks[*j].push_back(foeExitLink);
109                         }
110                     }
111                 }
112             }
113             std::vector<MSLink*> foes;
114             for (int c = 0; c < maxNo; ++c) {
115                 if (linkFoes.test(c)) {
116                     MSLink* foe = sortedLinks[c].second;
117                     foes.push_back(foe);
118                     MSLane* l = foe->getViaLane();
119                     if (l == nullptr) {
120                         continue;
121                     }
122                     // add foe links after an internal junction
123                     const MSLinkCont& lc = l->getLinkCont();
124                     for (MSLinkCont::const_iterator q = lc.begin(); q != lc.end(); ++q) {
125                         if ((*q)->getViaLane() != nullptr) {
126                             foes.push_back(*q);
127                         }
128                     }
129                 }
130             }
131 
132             myLinkFoeInternalLanes[*j] = std::vector<MSLane*>();
133             if (MSGlobals::gUsingInternalLanes && myInternalLanes.size() > 0) {
134                 int li = 0;
135                 for (int c = 0; c < (int)sortedLinks.size(); ++c) {
136                     if (sortedLinks[c].second->getLane() == nullptr) { // dead end
137                         continue;
138                     }
139                     if (linkFoes.test(c)) {
140                         myLinkFoeInternalLanes[*j].push_back(myInternalLanes[li]);
141                         if (linkResponse.test(c)) {
142                             const std::vector<MSLane::IncomingLaneInfo>& l = myInternalLanes[li]->getIncomingLanes();
143                             if (l.size() == 1 && l[0].lane->getEdge().isInternal()) {
144                                 myLinkFoeInternalLanes[*j].push_back(l[0].lane);
145                             }
146                         }
147                     }
148                     ++li;
149                 }
150             }
151             (*j)->setRequestInformation((int)requestPos, hasFoes, cont, myLinkFoeLinks[*j], myLinkFoeInternalLanes[*j]);
152             // the exit link for a link before an internal junction is handled in MSInternalJunction
153             // so we need to skip if cont=true
154             if (MSGlobals::gUsingInternalLanes && (*j)->getViaLane() != nullptr && !cont) {
155                 assert((*j)->getViaLane()->getLinkCont().size() == 1);
156                 MSLink* exitLink = (*j)->getViaLane()->getLinkCont()[0];
157                 exitLink->setRequestInformation((int)requestPos, false, false, std::vector<MSLink*>(),
158                                                 myLinkFoeInternalLanes[*j], (*j)->getViaLane());
159                 for (const auto& ili : exitLink->getLane()->getIncomingLanes()) {
160                     if (ili.lane->getEdge().isWalkingArea()) {
161                         exitLink->addWalkingAreaFoeExit(ili.lane);
162                         break;
163                     }
164                 }
165             }
166             // the exit link for a crossing is needed for the pedestrian model
167             if (MSGlobals::gUsingInternalLanes && (*j)->getLane()->getEdge().isCrossing()) {
168                 MSLink* exitLink = (*j)->getLane()->getLinkCont()[0];
169                 exitLink->setRequestInformation((int)requestPos, false, false, std::vector<MSLink*>(),
170                                                 myLinkFoeInternalLanes[*j], (*j)->getLane());
171             }
172             for (std::vector<MSLink*>::const_iterator k = foes.begin(); k != foes.end(); ++k) {
173                 (*j)->addBlockedLink(*k);
174                 (*k)->addBlockedLink(*j);
175             }
176             requestPos++;
177         }
178         if (walkingAreaFoe != nullptr && links.size() > 1) {
179             for (MSLinkCont::const_iterator j = links.begin(); j != links.end(); j++) {
180                 if (!(*j)->getLane()->getEdge().isWalkingArea()) {
181                     MSLink* exitLink = (*j)->getViaLane()->getLinkCont()[0];
182                     exitLink->addWalkingAreaFoe(walkingAreaFoe);
183                 }
184             }
185         }
186     }
187 }
188 
189 
190 /****************************************************************************/
191 
192