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 MSEdge.cpp
15 : /// @author Christian Roessel
16 : /// @author Jakob Erdmann
17 : /// @author Christoph Sommer
18 : /// @author Daniel Krajzewicz
19 : /// @author Laura Bieker
20 : /// @author Michael Behrisch
21 : /// @author Sascha Krieg
22 : /// @date Tue, 06 Mar 2001
23 : ///
24 : // A road/street connecting two junctions
25 : /****************************************************************************/
26 : #include <config.h>
27 :
28 : #include <algorithm>
29 : #include <iostream>
30 : #include <cassert>
31 : #ifdef HAVE_FOX
32 : #include <utils/common/ScopedLocker.h>
33 : #endif
34 : #include <utils/common/StringTokenizer.h>
35 : #include <utils/options/OptionsCont.h>
36 : #include <microsim/devices/MSRoutingEngine.h>
37 : #include <mesosim/MELoop.h>
38 : #include <mesosim/MESegment.h>
39 : #include <mesosim/MEVehicle.h>
40 : #include "MSInsertionControl.h"
41 : #include "MSJunction.h"
42 : #include "MSLane.h"
43 : #include "MSLaneChanger.h"
44 : #include "MSLaneChangerSublane.h"
45 : #include "MSLink.h"
46 : #include "MSGlobals.h"
47 : #include "MSNet.h"
48 : #include "MSVehicle.h"
49 : #include "MSLeaderInfo.h"
50 : #include <microsim/transportables/MSTransportable.h>
51 : #include "MSEdgeWeightsStorage.h"
52 : #include "MSEdge.h"
53 :
54 : #define BEST_LANE_LOOKAHEAD 3000.0
55 :
56 : // ===========================================================================
57 : // static member definitions
58 : // ===========================================================================
59 : MSEdge::DictType MSEdge::myDict;
60 : MSEdgeVector MSEdge::myEdges;
61 : SVCPermissions MSEdge::myMesoIgnoredVClasses(0);
62 : DepartLaneDefinition MSEdge::myDefaultDepartLaneDefinition(DepartLaneDefinition::DEFAULT);
63 : int MSEdge::myDefaultDepartLane(0);
64 :
65 : // ===========================================================================
66 : // member method definitions
67 : // ===========================================================================
68 1999724 : MSEdge::MSEdge(const std::string& id, int numericalID,
69 : const SumoXMLEdgeFunc function,
70 : const std::string& streetName,
71 : const std::string& edgeType,
72 : const std::string& routingType,
73 : int priority,
74 1999724 : double distance) :
75 1999724 : Named(id), myNumericalID(numericalID), myLanes(nullptr),
76 1999724 : myLaneChanger(nullptr), myFunction(function), myVaporizationRequests(0),
77 1999724 : myLastFailedInsertionTime(-1),
78 1999724 : myFromJunction(nullptr), myToJunction(nullptr),
79 1999724 : myHaveTransientPermissions(false),
80 1999724 : myOtherTazConnector(nullptr),
81 1999724 : myStreetName(streetName),
82 1999724 : myEdgeType(edgeType),
83 1999724 : myRoutingType(routingType),
84 1999724 : myPriority(priority),
85 1999724 : myDistance(distance),
86 1999724 : myWidth(0.),
87 1999724 : myLength(0.),
88 1999724 : myEmptyTraveltime(0.),
89 1999724 : myTimePenalty(0.),
90 1999724 : myAmDelayed(false),
91 1999724 : myAmRoundabout(false),
92 1999724 : myAmFringe(true),
93 3999448 : myBidiEdge(nullptr)
94 1999724 : { }
95 :
96 :
97 3443492 : MSEdge::~MSEdge() {
98 1984741 : delete myLaneChanger;
99 1984741 : delete myReversedRoutingEdge;
100 1984741 : delete myRailwayRoutingEdge;
101 13367197 : }
102 :
103 :
104 : void
105 1862547 : MSEdge::initialize(const std::vector<MSLane*>* lanes) {
106 : assert(lanes != 0);
107 1862547 : myLanes = std::shared_ptr<const std::vector<MSLane*> >(lanes);
108 1862547 : if (myFunction == SumoXMLEdgeFunc::CONNECTOR) {
109 69416 : myCombinedPermissions = SVCAll;
110 : }
111 4019484 : for (MSLane* const lane : *lanes) {
112 2156937 : lane->setRightSideOnEdge(myWidth, (int)mySublaneSides.size());
113 2156937 : MSLeaderInfo ahead(lane->getWidth());
114 5034678 : for (int j = 0; j < ahead.numSublanes(); ++j) {
115 2877741 : mySublaneSides.push_back(myWidth + j * MSGlobals::gLateralResolution);
116 : }
117 2156937 : myWidth += lane->getWidth();
118 2156937 : }
119 1862547 : }
120 :
121 :
122 1913968 : void MSEdge::recalcCache() {
123 1913968 : if (myLanes->empty()) {
124 : return;
125 : }
126 1913968 : myLength = myLanes->front()->getLength();
127 3827936 : myEmptyTraveltime = myLength / MAX2(getSpeedLimit(), NUMERICAL_EPS);
128 1913968 : if (isNormal() && (MSGlobals::gUseMesoSim || MSGlobals::gTLSPenalty > 0)) {
129 : SUMOTime minorPenalty = 0;
130 196503 : bool haveTLSPenalty = MSGlobals::gTLSPenalty > 0;
131 196503 : if (MSGlobals::gUseMesoSim) {
132 196388 : const MESegment::MesoEdgeType& edgeType = MSNet::getInstance()->getMesoType(getEdgeType());
133 196388 : minorPenalty = edgeType.minorPenalty;
134 196388 : haveTLSPenalty = edgeType.tlsPenalty > 0;
135 : }
136 196503 : if (haveTLSPenalty || minorPenalty > 0) {
137 : // add tls penalties to the minimum travel time
138 : SUMOTime minPenalty = -1;
139 2555 : for (const MSLane* const l : *myLanes) {
140 4099 : for (const MSLink* const link : l->getLinkCont()) {
141 2387 : if (link->getLane()->isWalkingArea() && link->getLaneBefore()->isNormal()) {
142 60 : continue;
143 : }
144 2327 : SUMOTime linkPenalty = link->isTLSControlled() ? link->getMesoTLSPenalty() : (link->havePriority() ? 0 : minorPenalty);
145 2327 : if (minPenalty == -1) {
146 : minPenalty = linkPenalty;
147 : } else {
148 : minPenalty = MIN2(minPenalty, linkPenalty);
149 : }
150 : }
151 : }
152 843 : if (minPenalty > 0) {
153 285 : myEmptyTraveltime += STEPS2TIME(minPenalty);
154 285 : myTimePenalty = STEPS2TIME(minPenalty);
155 : }
156 : }
157 1717465 : } else if (isCrossing() && MSGlobals::gTLSPenalty > 0) {
158 : // penalties are recorded for the entering link
159 112 : for (const auto& ili : myLanes->front()->getIncomingLanes()) {
160 56 : double penalty = STEPS2TIME(ili.viaLink->getMesoTLSPenalty());
161 56 : if (!ili.viaLink->haveOffPriority()) {
162 0 : penalty = MAX2(penalty, MSGlobals::gMinorPenalty);
163 : }
164 56 : if (penalty > 0) {
165 20 : myEmptyTraveltime += penalty;
166 20 : myTimePenalty = penalty;
167 : }
168 : }
169 1717409 : } else if (isInternal() && MSGlobals::gUsingInternalLanes) {
170 1011990 : const MSLink* link = myLanes->front()->getIncomingLanes()[0].viaLink;
171 1011990 : if (!link->isTLSControlled() && !link->havePriority()) {
172 496752 : if (link->isTurnaround()) {
173 189420 : myEmptyTraveltime += MSGlobals::gTurnaroundPenalty;
174 189420 : myTimePenalty = MSGlobals::gTurnaroundPenalty;
175 : } else {
176 307332 : myEmptyTraveltime += MSGlobals::gMinorPenalty;
177 307332 : myTimePenalty = MSGlobals::gMinorPenalty;
178 : }
179 : }
180 : }
181 : }
182 :
183 :
184 : void
185 40 : MSEdge::resetTAZ(MSJunction* junction) {
186 : mySuccessors.clear();
187 : myPredecessors.clear();
188 678 : for (const MSEdge* edge : junction->getIncoming()) {
189 638 : if (!edge->isInternal()) {
190 118 : MSEdgeVector& succ = const_cast<MSEdgeVector&>(edge->mySuccessors);
191 : MSConstEdgePairVector& succVia = const_cast<MSConstEdgePairVector&>(edge->myViaSuccessors);
192 118 : MSEdgeVector& pred = const_cast<MSEdgeVector&>(edge->myPredecessors);
193 118 : auto it = std::find(succ.begin(), succ.end(), this);
194 118 : auto it2 = std::find(succVia.begin(), succVia.end(), std::make_pair(const_cast<const MSEdge*>(this), (const MSEdge*)nullptr));
195 118 : auto it3 = std::find(pred.begin(), pred.end(), this);
196 118 : if (it != succ.end()) {
197 : succ.erase(it);
198 : succVia.erase(it2);
199 : }
200 118 : if (it3 != pred.end()) {
201 : pred.erase(it3);
202 : }
203 : }
204 : }
205 40 : }
206 :
207 : void
208 1790601 : MSEdge::closeBuilding() {
209 3944585 : for (MSLane* const lane : *myLanes) {
210 5114780 : for (MSLink* const link : lane->getLinkCont()) {
211 2960796 : link->initParallelLinks();
212 : MSLane* const toL = link->getLane();
213 : MSLane* const viaL = link->getViaLane();
214 2960796 : if (toL != nullptr) {
215 : MSEdge& to = toL->getEdge();
216 2960796 : if (std::find(mySuccessors.begin(), mySuccessors.end(), &to) == mySuccessors.end()) {
217 2759117 : mySuccessors.push_back(&to);
218 5518234 : myViaSuccessors.push_back(std::make_pair(&to, (viaL == nullptr ? nullptr : &viaL->getEdge())));
219 : }
220 2960796 : if (std::find(to.myPredecessors.begin(), to.myPredecessors.end(), this) == to.myPredecessors.end()) {
221 2759117 : to.myPredecessors.push_back(this);
222 : }
223 2960796 : if (link->getDirection() != LinkDirection::TURN) {
224 2308186 : myAmFringe = false;
225 : }
226 : }
227 2960796 : if (viaL != nullptr) {
228 : MSEdge& to = viaL->getEdge();
229 1035971 : if (std::find(to.myPredecessors.begin(), to.myPredecessors.end(), this) == to.myPredecessors.end()) {
230 954655 : to.myPredecessors.push_back(this);
231 : }
232 : }
233 : }
234 2153984 : lane->checkBufferType();
235 : }
236 1790601 : std::sort(mySuccessors.begin(), mySuccessors.end(), by_id_sorter());
237 1790601 : rebuildAllowedLanes(true);
238 1790601 : recalcCache();
239 :
240 : // extend lookup table for sublane model after all edges are read
241 1790601 : if (myLanes->back()->getOpposite() != nullptr) {
242 8374 : MSLane* opposite = myLanes->back()->getOpposite();
243 8374 : MSLeaderInfo ahead(opposite->getWidth());
244 22814 : for (int j = 0; j < ahead.numSublanes(); ++j) {
245 14440 : mySublaneSides.push_back(myWidth + j * MSGlobals::gLateralResolution);
246 : }
247 8374 : }
248 1790601 : }
249 :
250 :
251 : void
252 1790593 : MSEdge::postLoadInitLaneChanger() {
253 1790593 : if (myLaneChanger != nullptr) {
254 446325 : myLaneChanger->postloadInitLC();
255 : }
256 1790593 : }
257 :
258 : void
259 1790601 : MSEdge::buildLaneChanger() {
260 1790601 : if (!myLanes->empty()) {
261 1790601 : const bool allowChanging = allowsLaneChanging();
262 1790601 : if (MSGlobals::gLateralResolution > 0) {
263 : // may always initiate sublane-change
264 185448 : if (!isInternal() || MSGlobals::gUsingInternalLanes) {
265 185233 : myLaneChanger = new MSLaneChangerSublane(myLanes.get(), allowChanging);
266 : }
267 : } else {
268 1605153 : if (MSGlobals::gLaneChangeDuration > 0) {
269 4981 : myLaneChanger = new MSLaneChanger(myLanes.get(), allowChanging);
270 1600172 : } else if (myLanes->size() > 1 || canChangeToOpposite()) {
271 256119 : myLaneChanger = new MSLaneChanger(myLanes.get(), allowChanging);
272 : }
273 : }
274 : }
275 1790601 : }
276 :
277 :
278 : bool
279 1790601 : MSEdge::allowsLaneChanging() const {
280 1790601 : if (isInternal() && MSGlobals::gUsingInternalLanes) {
281 : // allow changing only if all links leading to this internal lane have priority
282 : // or they are controlled by a traffic light
283 1508165 : for (const MSLane* const lane : *myLanes) {
284 1032518 : const MSLink* const link = lane->getLogicalPredecessorLane()->getLinkTo(lane);
285 : assert(link != nullptr);
286 : const LinkState state = link->getState();
287 468223 : if ((state == LINKSTATE_MINOR && lane->getBidiLane() == nullptr)
288 564721 : || state == LINKSTATE_EQUAL
289 564721 : || state == LINKSTATE_STOP
290 : || state == LINKSTATE_ALLWAY_STOP
291 1032518 : || state == LINKSTATE_DEADEND) {
292 : return false;
293 : }
294 : }
295 : }
296 : return true;
297 : }
298 :
299 :
300 : void
301 18968956 : MSEdge::addToAllowed(const SVCPermissions permissions, std::shared_ptr<const std::vector<MSLane*> > allowedLanes, AllowedLanesCont& laneCont) const {
302 18968956 : if (!allowedLanes->empty()) {
303 : // recheck whether we had this list to save memory
304 18694020 : for (auto& allowed : laneCont) {
305 17649177 : if (*allowed.second == *allowedLanes) {
306 13296448 : allowed.first |= permissions;
307 : return;
308 : }
309 : }
310 1044843 : laneCont.push_back(std::make_pair(permissions, allowedLanes));
311 : }
312 : }
313 :
314 :
315 : SVCPermissions
316 3008913 : MSEdge::getMesoPermissions(SVCPermissions p, SVCPermissions ignoreIgnored) {
317 3008913 : SVCPermissions ignored = myMesoIgnoredVClasses & ~ignoreIgnored;
318 3008913 : return (p | ignored) == ignored ? 0 : p;
319 : }
320 :
321 :
322 : void
323 1791859 : MSEdge::rebuildAllowedLanes(const bool onInit, bool updateVehicles) {
324 : // rebuild myMinimumPermissions and myCombinedPermissions
325 1791859 : myMinimumPermissions = SVCAll;
326 1791859 : myCombinedPermissions = 0;
327 : bool lanesChangedPermission = false;
328 3947614 : for (MSLane* const lane : *myLanes) {
329 : // same dedicated lanes are ignored in meso to avoid capacity errors.
330 : // Here we have to make sure that vehicles which are set to depart on
331 : // such lanes trigger an error.
332 2155755 : SVCPermissions allow = getMesoPermissions(lane->getPermissions(), SVC_PEDESTRIAN);
333 2155755 : myMinimumPermissions &= allow;
334 2155755 : myCombinedPermissions |= allow;
335 2155755 : lanesChangedPermission |= lane->hadPermissionChanges();
336 : }
337 1791859 : if (!onInit && !myHaveTransientPermissions && lanesChangedPermission) {
338 808 : myHaveTransientPermissions = true;
339 : // backup original structures when first needed
340 808 : myOrigAllowed = myAllowed;
341 : myOrigAllowedTargets = myAllowedTargets;
342 : myOrigClassesViaSuccessorMap = myClassesViaSuccessorMap;
343 : }
344 : // rebuild myAllowed
345 : myAllowed.clear();
346 1791859 : if (myCombinedPermissions != myMinimumPermissions) {
347 170117 : myAllowed.push_back(std::make_pair(SVC_IGNORING, myLanes));
348 5783978 : for (SVCPermissions vclass = SVC_PRIVATE; vclass <= SUMOVehicleClass_MAX; vclass *= 2) {
349 5613861 : if ((myCombinedPermissions & vclass) == vclass) {
350 : std::shared_ptr<std::vector<MSLane*> > allowedLanes = std::make_shared<std::vector<MSLane*> >();
351 11918840 : for (MSLane* const lane : *myLanes) {
352 8069181 : if (lane->allowsVehicleClass((SUMOVehicleClass)vclass)) {
353 4072190 : allowedLanes->push_back(lane);
354 : }
355 : }
356 7699318 : addToAllowed(vclass, allowedLanes, myAllowed);
357 : }
358 : }
359 : }
360 1791859 : if (onInit) {
361 1790601 : myOriginalMinimumPermissions = myMinimumPermissions;
362 1790601 : myOriginalCombinedPermissions = myCombinedPermissions;
363 : } else {
364 1258 : rebuildAllowedTargets(updateVehicles);
365 3190 : for (MSEdge* pred : myPredecessors) {
366 1932 : if (myHaveTransientPermissions && !pred->myHaveTransientPermissions) {
367 1132 : pred->myOrigAllowed = pred->myAllowed;
368 : pred->myOrigAllowedTargets = pred->myAllowedTargets;
369 : pred->myOrigClassesViaSuccessorMap = pred->myClassesViaSuccessorMap;
370 1132 : pred->myHaveTransientPermissions = true;
371 : }
372 1932 : pred->rebuildAllowedTargets(updateVehicles);
373 : }
374 1258 : if (MSGlobals::gUseMesoSim) {
375 2191 : for (MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(*this); s != nullptr; s = s->getNextSegment()) {
376 1845 : s->updatePermissions();
377 : }
378 : }
379 3029 : for (MSLane* const lane : *myLanes) {
380 3589 : for (MSLink* link : lane->getLinkCont()) {
381 1818 : link->updatePermissions();
382 : }
383 3720 : for (auto ili : lane->getIncomingLanes()) {
384 1949 : ili.viaLink->updatePermissions();
385 : }
386 : }
387 : }
388 1791859 : }
389 :
390 :
391 : void
392 1794613 : MSEdge::rebuildAllowedTargets(const bool updateVehicles) {
393 : myAllowedTargets.clear();
394 4559611 : for (const MSEdge* target : mySuccessors) {
395 : bool universalMap = true; // whether the mapping for SVC_IGNORING is also valid for all vehicle classes
396 : std::shared_ptr<std::vector<MSLane*> > allLanes = std::make_shared<std::vector<MSLane*> >();
397 : // compute the mapping for SVC_IGNORING
398 6304211 : for (MSLane* const lane : *myLanes) {
399 : SVCPermissions combinedTargetPermissions = 0;
400 10050579 : for (const MSLink* const link : lane->getLinkCont()) {
401 6511366 : if (&link->getLane()->getEdge() == target) {
402 2967731 : allLanes->push_back(lane);
403 2967731 : combinedTargetPermissions |= link->getLane()->getPermissions();
404 2967731 : if (link->getViaLane() != nullptr &&
405 1037703 : ((lane->getPermissions() & link->getLane()->getPermissions()) != link->getViaLane()->getPermissions())) {
406 : // custom connection permissions
407 : universalMap = false;
408 : }
409 : }
410 : }
411 3539213 : if (combinedTargetPermissions == 0 || (lane->getPermissions() & combinedTargetPermissions) != lane->getPermissions()) {
412 : universalMap = false;
413 : }
414 : }
415 2764998 : if (universalMap) {
416 2248065 : if (myAllowed.empty()) {
417 : // we have no lane specific permissions
418 4427736 : myAllowedTargets[target].push_back(std::make_pair(myMinimumPermissions, myLanes));
419 : } else {
420 134545 : for (const auto& i : myAllowed) {
421 301044 : addToAllowed(i.first, i.second, myAllowedTargets[target]);
422 : }
423 : }
424 : } else {
425 1033866 : addToAllowed(SVC_IGNORING, allLanes, myAllowedTargets[target]);
426 : // compute the vclass specific mapping
427 17575722 : for (SVCPermissions vclass = SVC_PRIVATE; vclass <= SUMOVehicleClass_MAX; vclass *= 2) {
428 17058789 : if ((myCombinedPermissions & vclass) == vclass) {
429 : std::shared_ptr<std::vector<MSLane*> > allowedLanes = std::make_shared<std::vector<MSLane*> >();
430 45081569 : for (MSLane* const lane : *myLanes) {
431 30579553 : if (lane->allowsVehicleClass((SUMOVehicleClass)vclass)) {
432 58631606 : for (const MSLink* const link : lane->getLinkCont()) {
433 38348559 : if (link->getLane()->allowsVehicleClass((SUMOVehicleClass)vclass) && &link->getLane()->getEdge() == target && (link->getViaLane() == nullptr || link->getViaLane()->allowsVehicleClass((SUMOVehicleClass)vclass))) {
434 10235594 : allowedLanes->push_back(lane);
435 : }
436 : }
437 : }
438 : }
439 43506048 : addToAllowed(vclass, allowedLanes, myAllowedTargets[target]);
440 : }
441 : }
442 : }
443 : }
444 1794613 : if (updateVehicles) {
445 2629 : for (const MSLane* const lane : *myLanes) {
446 1564 : const MSLane::VehCont& vehs = lane->getVehiclesSecure();
447 3957 : for (MSVehicle* veh : vehs) {
448 2393 : veh->updateBestLanes(true);
449 : }
450 1564 : lane->releaseVehicles();
451 : }
452 : }
453 : myClassesSuccessorMap.clear();
454 1794613 : }
455 :
456 :
457 : // ------------ Access to the edge's lanes
458 : MSLane*
459 774 : MSEdge::leftLane(const MSLane* const lane) const {
460 774 : return parallelLane(lane, 1);
461 : }
462 :
463 :
464 : MSLane*
465 400 : MSEdge::rightLane(const MSLane* const lane) const {
466 400 : return parallelLane(lane, -1);
467 : }
468 :
469 :
470 : MSLane*
471 84323837 : MSEdge::parallelLane(const MSLane* const lane, int offset, bool includeOpposite) const {
472 84323837 : const int resultIndex = lane->getIndex() + offset;
473 84323837 : if (resultIndex >= getNumLanes() && includeOpposite) {
474 20698757 : const MSEdge* opposite = getOppositeEdge();
475 20698757 : if (opposite != nullptr && resultIndex < getNumLanes() + opposite->getNumLanes()) {
476 1379244 : return opposite->getLanes()[opposite->getNumLanes() + getNumLanes() - resultIndex - 1];
477 : }
478 : return nullptr;
479 63625080 : } else if (resultIndex >= (int)myLanes->size() || resultIndex < 0) {
480 : return nullptr;
481 : } else {
482 39017203 : return (*myLanes)[resultIndex];
483 : }
484 : }
485 :
486 :
487 : const std::vector<MSLane*>*
488 77905452 : MSEdge::allowedLanes(const MSEdge& destination, SUMOVehicleClass vclass, bool ignoreTransientPermissions) const {
489 77905452 : const auto& targets = ignoreTransientPermissions && myHaveTransientPermissions ? myOrigAllowedTargets : myAllowedTargets;
490 : AllowedLanesByTarget::const_iterator i = targets.find(&destination);
491 77905452 : if (i != targets.end()) {
492 77883044 : for (const auto& allowed : i->second) {
493 77758672 : if ((allowed.first & vclass) == vclass) {
494 : return allowed.second.get();
495 : }
496 : }
497 : }
498 : return nullptr;
499 : }
500 :
501 :
502 : const std::vector<MSLane*>*
503 274255166 : MSEdge::allowedLanes(SUMOVehicleClass vclass) const {
504 274255166 : if ((myMinimumPermissions & vclass) == vclass) {
505 43306128 : return myLanes.get();
506 : } else {
507 230949038 : if ((myCombinedPermissions & vclass) == vclass) {
508 461894585 : for (const auto& allowed : myAllowed) {
509 461894585 : if ((allowed.first & vclass) == vclass) {
510 : return allowed.second.get();
511 : }
512 : }
513 : }
514 2007 : return nullptr;
515 : }
516 : }
517 :
518 :
519 : const std::vector<MSLane*>*
520 2171229481 : MSEdge::allowedLanes(SUMOVehicleClass vclass, bool ignoreTransientPermissions) const {
521 2171229481 : const SVCPermissions& minP = ignoreTransientPermissions ? myOriginalMinimumPermissions : myMinimumPermissions;
522 2171229481 : if ((minP & vclass) == vclass) {
523 633736558 : return myLanes.get();
524 : } else {
525 1537492923 : const SVCPermissions comP = ignoreTransientPermissions ? myOriginalCombinedPermissions : myCombinedPermissions;
526 1537492923 : if ((comP & vclass) == vclass) {
527 1537492851 : const AllowedLanesCont& allowedCont = ignoreTransientPermissions && myHaveTransientPermissions ? myOrigAllowed : myAllowed;
528 3080684505 : for (const auto& allowed : allowedCont) {
529 3080684505 : if ((allowed.first & vclass) == vclass) {
530 : return allowed.second.get();
531 : }
532 : }
533 : }
534 72 : return nullptr;
535 : }
536 : }
537 :
538 :
539 : // ------------
540 : SUMOTime
541 433 : MSEdge::incVaporization(SUMOTime) {
542 433 : ++myVaporizationRequests;
543 433 : return 0;
544 : }
545 :
546 :
547 : SUMOTime
548 279 : MSEdge::decVaporization(SUMOTime) {
549 279 : --myVaporizationRequests;
550 279 : return 0;
551 : }
552 :
553 :
554 : MSLane*
555 216196673 : MSEdge::getFreeLane(const std::vector<MSLane*>* allowed, const SUMOVehicleClass vclass, double departPos) const {
556 216196673 : if (allowed == nullptr) {
557 183167176 : allowed = allowedLanes(vclass);
558 : }
559 : MSLane* res = nullptr;
560 183167176 : if (allowed != nullptr) {
561 : double largestGap = 0;
562 : MSLane* resByGap = nullptr;
563 : double leastOccupancy = std::numeric_limits<double>::max();
564 455325101 : for (std::vector<MSLane*>::const_iterator i = allowed->begin(); i != allowed->end(); ++i) {
565 239130427 : const double occupancy = (*i)->getBruttoOccupancy();
566 239130427 : if (occupancy < leastOccupancy) {
567 223593213 : res = (*i);
568 : leastOccupancy = occupancy;
569 : }
570 239130427 : const MSVehicle* last = (*i)->getLastFullVehicle();
571 239130427 : const double lastGap = (last != nullptr ? last->getPositionOnLane() : myLength) - departPos;
572 239130427 : if (lastGap > largestGap) {
573 : largestGap = lastGap;
574 55806361 : resByGap = (*i);
575 : }
576 : }
577 216194674 : if (resByGap != nullptr) {
578 : //if (res != resByGap) std::cout << SIMTIME << " edge=" << getID() << " departPos=" << departPos << " res=" << Named::getIDSecure(res) << " resByGap=" << Named::getIDSecure(resByGap) << " largestGap=" << largestGap << "\n";
579 : res = resByGap;
580 : }
581 : }
582 216196673 : return res;
583 : }
584 :
585 :
586 : MSLane*
587 839177809 : MSEdge::getProbableLane(const std::vector<MSLane*>* allowed, const SUMOVehicleClass vclass, double departPos, double maxSpeed) const {
588 839177809 : if (allowed == nullptr) {
589 0 : allowed = allowedLanes(vclass);
590 : }
591 : MSLane* res = nullptr;
592 0 : if (allowed != nullptr) {
593 : double largestGap = 0;
594 : double largestSpeed = 0;
595 : MSLane* resByGap = nullptr;
596 : double leastOccupancy = std::numeric_limits<double>::max();
597 : int aIndex = 0;
598 1684232696 : for (std::vector<MSLane*>::const_iterator i = allowed->begin(); i != allowed->end(); ++i, aIndex++) {
599 845054887 : const double occupancy = (*i)->getBruttoOccupancy();
600 845054887 : if (occupancy < leastOccupancy) {
601 844328386 : res = (*i);
602 : leastOccupancy = occupancy;
603 : }
604 845054887 : const MSVehicle* last = (*i)->getLastFullVehicle();
605 845054887 : double lastGap = (last != nullptr ? last->getPositionOnLane() : myLength) - departPos;
606 : // never insert to the left of a vehicle with a larger speedFactor
607 845054887 : if (lastGap > largestGap && maxSpeed >= largestSpeed) {
608 : largestGap = lastGap;
609 799980591 : resByGap = (*i);
610 : }
611 845054887 : if (last != nullptr) {
612 842809752 : largestSpeed = MAX2(largestSpeed, getVehicleMaxSpeed(last));
613 : }
614 : }
615 839177809 : if (resByGap != nullptr) {
616 : //if (res != resByGap) std::cout << SIMTIME << " edge=" << getID() << " departPos=" << departPos << " res=" << Named::getIDSecure(res) << " resByGap=" << Named::getIDSecure(resByGap) << " largestGap=" << largestGap << "\n";
617 : res = resByGap;
618 : }
619 : }
620 839177809 : return res;
621 : }
622 :
623 :
624 : double
625 1056360741 : MSEdge::getDepartPosBound(const MSVehicle& veh, bool upper) const {
626 1056360741 : const SUMOVehicleParameter& pars = veh.getParameter();
627 : double pos = getLength();
628 : // determine the position
629 1056360741 : switch (pars.departPosProcedure) {
630 9465891 : case DepartPosDefinition::GIVEN:
631 9465891 : pos = pars.departPos;
632 9465891 : if (pos < 0.) {
633 2289709 : pos += myLength;
634 : }
635 : break;
636 : case DepartPosDefinition::RANDOM:
637 : // could be any position on the edge
638 : break;
639 : case DepartPosDefinition::RANDOM_FREE:
640 : // could be any position on the edge due to multiple random attempts
641 : break;
642 : case DepartPosDefinition::FREE:
643 : // many candidate positions, upper bound could be computed exactly
644 : // with much effort
645 : break;
646 11595186 : case DepartPosDefinition::LAST:
647 11595186 : if (upper) {
648 259692 : for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
649 175072 : MSVehicle* last = (*i)->getLastFullVehicle();
650 175072 : if (last != nullptr) {
651 151537 : pos = MIN2(pos, last->getPositionOnLane());
652 : }
653 : }
654 : } else {
655 : pos = 0;
656 : }
657 : break;
658 830096256 : case DepartPosDefinition::BASE:
659 : case DepartPosDefinition::DEFAULT:
660 830096256 : if (!upper) {
661 : pos = 0;
662 : }
663 : break;
664 28 : default:
665 28 : pos = MIN2(pos, veh.getVehicleType().getLength());
666 : break;
667 : }
668 1056360741 : return pos;
669 : }
670 :
671 :
672 : MSLane*
673 46 : MSEdge::getDepartLaneMeso(SUMOVehicle& veh) const {
674 46 : if (veh.getParameter().departLaneProcedure == DepartLaneDefinition::GIVEN) {
675 3 : if ((int) myLanes->size() <= veh.getParameter().departLane || !(*myLanes)[veh.getParameter().departLane]->allowsVehicleClass(veh.getVehicleType().getVehicleClass())) {
676 0 : return nullptr;
677 : }
678 3 : return (*myLanes)[veh.getParameter().departLane];
679 : }
680 43 : return (*myLanes)[0];
681 : }
682 :
683 :
684 : MSLane*
685 1760017415 : MSEdge::getDepartLane(MSVehicle& veh) const {
686 1760017415 : DepartLaneDefinition dld = veh.getParameter().departLaneProcedure;
687 1760017415 : int departLane = veh.getParameter().departLane;
688 1760017415 : if (dld == DepartLaneDefinition::DEFAULT) {
689 1324705917 : dld = myDefaultDepartLaneDefinition;
690 1324705917 : departLane = myDefaultDepartLane;
691 : }
692 1760017415 : switch (dld) {
693 121180525 : case DepartLaneDefinition::GIVEN:
694 121180525 : if ((int) myLanes->size() <= departLane || !(*myLanes)[departLane]->allowsVehicleClass(veh.getVClass())) {
695 66 : return nullptr;
696 : }
697 121180459 : return (*myLanes)[departLane];
698 91059626 : case DepartLaneDefinition::RANDOM:
699 182119252 : return RandHelper::getRandomFrom(*allowedLanes(veh.getVehicleType().getVehicleClass()));
700 183066896 : case DepartLaneDefinition::FREE:
701 183066896 : return getFreeLane(nullptr, veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false));
702 4971244 : case DepartLaneDefinition::ALLOWED_FREE:
703 4971244 : if (veh.getRoute().size() == 1) {
704 5960 : return getFreeLane(nullptr, veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false));
705 : } else {
706 4965284 : return getFreeLane(allowedLanes(**(veh.getRoute().begin() + 1), veh.getVehicleType().getVehicleClass()), veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false));
707 : }
708 867040544 : case DepartLaneDefinition::BEST_FREE:
709 : case DepartLaneDefinition::BEST_PROB: {
710 867040544 : veh.updateBestLanes(false, myLanes->front());
711 867040544 : const std::vector<MSVehicle::LaneQ>& bl = veh.getBestLanes();
712 : double bestLength = -1;
713 2559885106 : for (std::vector<MSVehicle::LaneQ>::const_iterator i = bl.begin(); i != bl.end(); ++i) {
714 1692844562 : if ((*i).length > bestLength) {
715 : bestLength = (*i).length;
716 : }
717 : }
718 : // beyond a certain length, all lanes are suitable
719 : // however, we still need to check departPos to avoid unsuitable insertion
720 : // (this is only possible in some cases)
721 : double departPos = 0;
722 867040544 : if (bestLength > BEST_LANE_LOOKAHEAD) {
723 1282057 : departPos = getDepartPosBound(veh);
724 1282057 : bestLength = MIN2(bestLength - departPos, BEST_LANE_LOOKAHEAD);
725 : }
726 867040544 : std::vector<MSLane*>* bestLanes = new std::vector<MSLane*>();
727 2559885106 : for (std::vector<MSVehicle::LaneQ>::const_iterator i = bl.begin(); i != bl.end(); ++i) {
728 1692844562 : if (((*i).length - departPos) >= bestLength) {
729 875221378 : if (isInternal()) {
730 32 : for (MSLane* lane : *myLanes) {
731 20 : if (lane->getNormalSuccessorLane() == (*i).lane && lane->allowsVehicleClass(veh.getVClass()) ) {
732 12 : bestLanes->push_back(lane);
733 : }
734 : }
735 875221366 : } else if ((*i).lane->allowsVehicleClass(veh.getVClass())) {
736 874789416 : bestLanes->push_back((*i).lane);
737 : }
738 : }
739 : }
740 : MSLane* ret = nullptr;
741 867040544 : if (veh.getParameter().departLaneProcedure == DepartLaneDefinition::BEST_FREE) {
742 27862735 : ret = getFreeLane(bestLanes, veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false));
743 : } else {
744 839177809 : ret = getProbableLane(bestLanes, veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false), getVehicleMaxSpeed(&veh));
745 : }
746 867040544 : delete bestLanes;
747 867040544 : return ret;
748 : }
749 492698580 : case DepartLaneDefinition::DEFAULT:
750 : case DepartLaneDefinition::FIRST_ALLOWED:
751 492698580 : return getFirstAllowed(veh.getVehicleType().getVehicleClass());
752 : default:
753 : break;
754 : }
755 0 : if (!(*myLanes)[0]->allowsVehicleClass(veh.getVehicleType().getVehicleClass())) {
756 : return nullptr;
757 : }
758 0 : return (*myLanes)[0];
759 : }
760 :
761 :
762 : MSLane*
763 493685421 : MSEdge::getFirstAllowed(SUMOVehicleClass vClass, bool defaultFirst, int routingMode) const {
764 501234382 : for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
765 500365482 : if ((*i)->allowsVehicleClass(vClass, routingMode)) {
766 492816521 : return *i;
767 : }
768 : }
769 868900 : return defaultFirst && !myLanes->empty() ? myLanes->front() : nullptr;
770 : }
771 :
772 :
773 : bool
774 2825250957 : MSEdge::validateDepartSpeed(SUMOVehicle& v) const {
775 2825250957 : const SUMOVehicleParameter& pars = v.getParameter();
776 2825250957 : const MSVehicleType& type = v.getVehicleType();
777 2825250957 : if (pars.departSpeedProcedure == DepartSpeedDefinition::GIVEN) {
778 : // departSpeed could have been rounded down in the output
779 150640421 : double vMax = getVehicleMaxSpeed(&v) + SPEED_EPS;
780 150640421 : if (pars.departSpeed > vMax) {
781 : // check departLane (getVehicleMaxSpeed checks lane 0)
782 19611 : MSLane* departLane = MSGlobals::gMesoNet ? getDepartLaneMeso(v) : getDepartLane(dynamic_cast<MSVehicle&>(v));
783 19611 : if (departLane != nullptr) {
784 19611 : vMax = departLane->getVehicleMaxSpeed(&v);
785 19611 : if (pars.wasSet(VEHPARS_SPEEDFACTOR_SET)) {
786 : // speedFactor could have been rounded down in the output
787 7 : vMax *= (1 + SPEED_EPS);
788 : }
789 : // additive term must come after multiplication!
790 19611 : vMax += SPEED_EPS;
791 19611 : if (pars.departSpeed > vMax) {
792 19597 : if (type.getSpeedFactor().getParameter(1) > 0.) {
793 39156 : v.setChosenSpeedFactor(type.computeChosenSpeedDeviation(pars.speedFactor, nullptr, pars.departSpeed / MIN2(getSpeedLimit(), type.getDesiredMaxSpeed() - SPEED_EPS)));
794 19578 : if (v.getChosenSpeedFactor() > type.getSpeedFactor().getParameter(0) + 2 * type.getSpeedFactor().getParameter(1)) {
795 : // only warn for significant deviation
796 33536 : WRITE_WARNINGF(TL("Choosing new speed factor % for vehicle '%' to match departure speed % (max %)."),
797 : toString(v.getChosenSpeedFactor()), pars.id, pars.departSpeed, vMax);
798 : }
799 : } else {
800 : return false;
801 : }
802 : }
803 : }
804 : }
805 : }
806 : return true;
807 : }
808 :
809 :
810 : bool
811 2825712343 : MSEdge::insertVehicle(SUMOVehicle& v, SUMOTime time, const bool checkOnly, const bool forceCheck) const {
812 : // when vaporizing, no vehicles are inserted, but checking needs to be successful to trigger removal
813 2825693557 : if (isVaporizing() || isTazConnector()
814 5650940601 : || v.getRouteValidity(true, checkOnly) != MSBaseVehicle::ROUTE_VALID) {
815 484152 : return checkOnly;
816 : }
817 2825228012 : const SUMOVehicleParameter& pars = v.getParameter();
818 2825228012 : if (!validateDepartSpeed(v)) {
819 14 : if (MSGlobals::gCheckRoutes) {
820 21 : throw ProcessError(TLF("Departure speed for vehicle '%' is too high for the departure edge '%', time=%.",
821 21 : pars.id, getID(), time2string(time)));
822 : } else {
823 21 : WRITE_WARNINGF(TL("Departure speed for vehicle '%' is too high for the departure edge '%', time=%."),
824 : pars.id, getID(), time2string(time));
825 : }
826 : }
827 2825228005 : if (MSGlobals::gUseMesoSim) {
828 594717408 : if (!forceCheck && myLastFailedInsertionTime == time) {
829 : return false;
830 : }
831 : double pos = 0.0;
832 92598556 : switch (pars.departPosProcedure) {
833 596154 : case DepartPosDefinition::GIVEN:
834 596154 : if (pars.departPos >= 0.) {
835 : pos = pars.departPos;
836 : } else {
837 8397 : pos = pars.departPos + getLength();
838 : }
839 596154 : if (pos < 0 || pos > getLength()) {
840 6 : WRITE_WARNINGF(TL("Invalid departPos % given for vehicle '%', time=%. Inserting at lane end instead."),
841 : pos, v.getID(), time2string(time));
842 : pos = getLength();
843 : }
844 : break;
845 : case DepartPosDefinition::RANDOM:
846 : case DepartPosDefinition::RANDOM_FREE:
847 : pos = RandHelper::rand(getLength());
848 44186 : break;
849 : default:
850 : break;
851 : }
852 : bool result = false;
853 92598556 : MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this, pos);
854 : MEVehicle* veh = static_cast<MEVehicle*>(&v);
855 : int qIdx;
856 92598556 : if (pars.departPosProcedure == DepartPosDefinition::FREE) {
857 469860 : while (segment != nullptr && !result) {
858 431670 : if (checkOnly) {
859 6 : result = segment->hasSpaceFor(veh, time, qIdx, true) == time;
860 : } else {
861 431664 : result = segment->initialise(veh, time);
862 : }
863 : segment = segment->getNextSegment();
864 : }
865 : } else {
866 92560366 : if (checkOnly) {
867 80542225 : result = segment->hasSpaceFor(veh, time, qIdx, true) == time;
868 : } else {
869 12018141 : result = segment->initialise(veh, time);
870 : }
871 : }
872 92598554 : return result;
873 : }
874 2230510597 : if (checkOnly) {
875 611579274 : DepartLaneDefinition dld = v.getParameter().departLaneProcedure;
876 611579274 : if (dld == DepartLaneDefinition::DEFAULT) {
877 561535951 : dld = myDefaultDepartLaneDefinition;
878 : }
879 611579274 : switch (dld) {
880 80464625 : case DepartLaneDefinition::GIVEN:
881 : case DepartLaneDefinition::DEFAULT:
882 : case DepartLaneDefinition::FIRST_ALLOWED: {
883 80464625 : MSLane* insertionLane = getDepartLane(static_cast<MSVehicle&>(v));
884 80464625 : if (insertionLane == nullptr) {
885 1295850 : WRITE_WARNINGF(TL("Could not insert vehicle '%' on any lane of edge '%', time=%."),
886 : v.getID(), getID(), time2string(time));
887 431950 : return false;
888 : }
889 80032675 : const double occupancy = insertionLane->getBruttoOccupancy();
890 80032675 : return (occupancy == 0 || occupancy * myLength + v.getVehicleType().getLengthWithGap() <= myLength ||
891 6049985 : v.getParameter().departProcedure == DepartDefinition::SPLIT);
892 : }
893 531114649 : default:
894 539956847 : for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
895 535996481 : const double occupancy = (*i)->getBruttoOccupancy();
896 535996481 : if (occupancy == 0 || occupancy * myLength + v.getVehicleType().getLengthWithGap() <= myLength ||
897 8842198 : v.getParameter().departProcedure == DepartDefinition::SPLIT) {
898 : return true;
899 : }
900 : }
901 : }
902 : return false;
903 : }
904 1618931323 : MSLane* insertionLane = getDepartLane(static_cast<MSVehicle&>(v));
905 1618931323 : if (insertionLane == nullptr) {
906 : return false;
907 : }
908 :
909 1618062423 : if (!forceCheck) {
910 1618062246 : if (myLastFailedInsertionTime == time) {
911 : if (myFailedInsertionMemory.count(insertionLane->getIndex())) {
912 : // A vehicle was already rejected for the proposed insertionLane in this timestep
913 : return false;
914 : }
915 : } else {
916 : // last rejection occurred in a previous timestep, clear cache
917 : myFailedInsertionMemory.clear();
918 : }
919 : }
920 :
921 13557483 : bool success = insertionLane->insertVehicle(static_cast<MSVehicle&>(v));
922 :
923 13557482 : if (!success) {
924 : // constraints may enforce explicit re-ordering so we need to try other vehicles after failure
925 20122838 : if (!insertionLane->hasParameter("insertionOrder" + v.getID())) {
926 10061272 : myFailedInsertionMemory.insert(insertionLane->getIndex());
927 : }
928 : }
929 : return success;
930 : }
931 :
932 :
933 : void
934 42856972 : MSEdge::changeLanes(SUMOTime t) const {
935 42856972 : if (myLaneChanger != nullptr) {
936 42856972 : myLaneChanger->laneChange(t);
937 : }
938 42856972 : }
939 :
940 :
941 : const MSEdge*
942 5849113 : MSEdge::getInternalFollowingEdge(const MSEdge* followerAfterInternal, SUMOVehicleClass vClass) const {
943 : //@todo to be optimized
944 6669908 : for (const MSLane* const l : *myLanes) {
945 9775979 : for (const MSLink* const link : l->getLinkCont()) {
946 8955184 : if (&link->getLane()->getEdge() == followerAfterInternal) {
947 5584397 : if (link->getViaLane() != nullptr) {
948 4554669 : if (link->getViaLane()->allowsVehicleClass(vClass)) {
949 4514675 : return &link->getViaLane()->getEdge();
950 : } else {
951 39994 : continue;
952 : }
953 : } else {
954 : return nullptr; // network without internal links
955 : }
956 : }
957 : }
958 : }
959 : return nullptr;
960 : }
961 :
962 :
963 : double
964 1242923 : MSEdge::getInternalFollowingLengthTo(const MSEdge* followerAfterInternal, SUMOVehicleClass vClass) const {
965 : assert(followerAfterInternal != 0);
966 : assert(!followerAfterInternal->isInternal());
967 : double dist = 0.;
968 1242923 : const MSEdge* edge = getInternalFollowingEdge(followerAfterInternal, vClass);
969 : // Take into account non-internal lengths until next non-internal edge
970 2294436 : while (edge != nullptr && edge->isInternal()) {
971 1051513 : dist += edge->getLength();
972 1051513 : edge = edge->getInternalFollowingEdge(followerAfterInternal, vClass);
973 : }
974 1242923 : return dist;
975 : }
976 :
977 :
978 : const MSEdge*
979 151360 : MSEdge::getNormalBefore() const {
980 : const MSEdge* result = this;
981 160477 : while (result->isInternal() && MSGlobals::gUsingInternalLanes) {
982 : assert(result->getPredecessors().size() == 1);
983 9117 : result = result->getPredecessors().front();
984 : }
985 151360 : return result;
986 : }
987 :
988 : const MSEdge*
989 6176392 : MSEdge::getNormalSuccessor() const {
990 : const MSEdge* result = this;
991 11581412 : while (result->isInternal()) {
992 : assert(result->getSuccessors().size() == 1);
993 5405020 : result = result->getSuccessors().front();
994 : }
995 6176392 : return result;
996 : }
997 :
998 : double
999 195623228 : MSEdge::getMeanSpeed() const {
1000 : double v = 0;
1001 : double totalNumVehs = 0;
1002 195623228 : if (MSGlobals::gUseMesoSim) {
1003 259572617 : for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1004 : const int numVehs = segment->getCarNumber();
1005 189135141 : if (numVehs > 0) {
1006 25345403 : v += numVehs * segment->getMeanSpeed();
1007 25345403 : totalNumVehs += numVehs;
1008 : }
1009 : }
1010 70437476 : if (totalNumVehs == 0) {
1011 61217891 : return getLength() / myEmptyTraveltime; // may include tls-penalty
1012 : }
1013 : } else {
1014 287892474 : for (const MSLane* const lane : *myLanes) {
1015 : int numVehs = lane->getVehicleNumber();
1016 162706722 : if (numVehs == 0) {
1017 : // take speed limit but with lowest possible weight
1018 : numVehs = 1;
1019 : }
1020 162706722 : v += numVehs * lane->getMeanSpeed();
1021 162706722 : totalNumVehs += numVehs;
1022 : }
1023 125185752 : if (myBidiEdge != nullptr) {
1024 8790320 : for (const MSLane* const lane : myBidiEdge->getLanes()) {
1025 4553258 : if (lane->getVehicleNumber() > 0) {
1026 : // do not route across edges which are already occupied in reverse direction
1027 : return 0;
1028 : }
1029 : }
1030 : }
1031 124870088 : if (totalNumVehs == 0) {
1032 0 : return getSpeedLimit();
1033 : }
1034 : }
1035 134089673 : return v / totalNumVehs;
1036 : }
1037 :
1038 :
1039 : double
1040 8 : MSEdge::getMeanFriction() const {
1041 : double f = 0.;
1042 32 : for (const MSLane* const lane : *myLanes) {
1043 24 : f += lane->getFrictionCoefficient();
1044 : }
1045 8 : if (!myLanes->empty()) {
1046 8 : return f / (double)myLanes->size();
1047 : }
1048 : return 1.;
1049 : }
1050 :
1051 :
1052 : double
1053 1272 : MSEdge::getMeanSpeedBike() const {
1054 1272 : if (MSGlobals::gUseMesoSim) {
1055 : // no separate bicycle speeds in meso
1056 362 : return getMeanSpeed();
1057 : }
1058 : double v = 0;
1059 : double totalNumVehs = 0;
1060 3005 : for (const MSLane* const lane : *myLanes) {
1061 : const int numVehs = lane->getVehicleNumber();
1062 2095 : v += numVehs * lane->getMeanSpeedBike();
1063 2095 : totalNumVehs += numVehs;
1064 : }
1065 910 : if (totalNumVehs == 0) {
1066 455 : return getSpeedLimit();
1067 : }
1068 455 : return v / totalNumVehs;
1069 : }
1070 :
1071 :
1072 : double
1073 63996 : MSEdge::getCurrentTravelTime(double minSpeed) const {
1074 : assert(minSpeed > 0);
1075 63996 : if (!myAmDelayed) {
1076 44802 : return myEmptyTraveltime;
1077 : }
1078 38388 : return getLength() / MAX2(minSpeed, getMeanSpeed());
1079 : }
1080 :
1081 :
1082 : double
1083 0 : MSEdge::getRoutingSpeed() const {
1084 0 : return MSRoutingEngine::getAssumedSpeed(this, nullptr);
1085 : }
1086 :
1087 :
1088 : bool
1089 1862545 : MSEdge::dictionary(const std::string& id, MSEdge* ptr) {
1090 : const DictType::iterator it = myDict.lower_bound(id);
1091 1862545 : if (it == myDict.end() || it->first != id) {
1092 : // id not in myDict
1093 1862545 : myDict.emplace_hint(it, id, ptr);
1094 3725130 : while (ptr->getNumericalID() >= (int)myEdges.size()) {
1095 1862585 : myEdges.push_back(nullptr);
1096 : }
1097 1862545 : myEdges[ptr->getNumericalID()] = ptr;
1098 1862545 : return true;
1099 : }
1100 : return false;
1101 : }
1102 :
1103 :
1104 : MSEdge*
1105 8783027 : MSEdge::dictionary(const std::string& id) {
1106 : const DictType::iterator it = myDict.find(id);
1107 8783027 : if (it == myDict.end()) {
1108 : return nullptr;
1109 : }
1110 6917814 : return it->second;
1111 : }
1112 :
1113 :
1114 : MSEdge*
1115 2967302 : MSEdge::dictionaryHint(const std::string& id, const int startIdx) {
1116 : // this method is mainly useful when parsing connections from the net.xml which are sorted by "from" id
1117 2967302 : if (myEdges[startIdx] != nullptr && myEdges[startIdx]->getID() == id) {
1118 : return myEdges[startIdx];
1119 : }
1120 1874072 : if (startIdx + 1 < (int)myEdges.size() && myEdges[startIdx + 1] != nullptr && myEdges[startIdx + 1]->getID() == id) {
1121 : return myEdges[startIdx + 1];
1122 : }
1123 617612 : return dictionary(id);
1124 : }
1125 :
1126 :
1127 : const MSEdgeVector&
1128 907588 : MSEdge::getAllEdges() {
1129 907588 : return myEdges;
1130 : }
1131 :
1132 :
1133 : void
1134 42795 : MSEdge::clear() {
1135 1890359 : for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
1136 1847564 : delete (*i).second;
1137 : }
1138 : myDict.clear();
1139 : myEdges.clear();
1140 42795 : }
1141 :
1142 :
1143 : void
1144 285 : MSEdge::insertIDs(std::vector<std::string>& into) {
1145 16016 : for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
1146 15731 : into.push_back((*i).first);
1147 : }
1148 285 : }
1149 :
1150 :
1151 : void
1152 416930 : MSEdge::parseEdgesList(const std::string& desc, ConstMSEdgeVector& into,
1153 : const std::string& rid) {
1154 416930 : StringTokenizer st(desc);
1155 416930 : parseEdgesList(st.getVector(), into, rid);
1156 416930 : }
1157 :
1158 :
1159 : void
1160 417212 : MSEdge::parseEdgesList(const std::vector<std::string>& desc, ConstMSEdgeVector& into,
1161 : const std::string& rid) {
1162 1574788 : for (std::vector<std::string>::const_iterator i = desc.begin(); i != desc.end(); ++i) {
1163 1157625 : const MSEdge* edge = MSEdge::dictionary(*i);
1164 : // check whether the edge exists
1165 1157625 : if (edge == nullptr) {
1166 49 : throw ProcessError("The edge '" + *i + "' within the route " + rid + " is not known."
1167 147 : + "\n The route can not be build.");
1168 : }
1169 1157576 : into.push_back(edge);
1170 : }
1171 417163 : }
1172 :
1173 :
1174 : double
1175 1834655 : MSEdge::getDistanceTo(const MSEdge* other, const bool doBoundaryEstimate) const {
1176 : assert(this != other);
1177 1834655 : if (doBoundaryEstimate) {
1178 19288 : return myBoundary.distanceTo2D(other->myBoundary);
1179 : }
1180 1815367 : if (isTazConnector()) {
1181 564 : if (other->isTazConnector()) {
1182 448 : return myBoundary.distanceTo2D(other->myBoundary);
1183 : }
1184 116 : return myBoundary.distanceTo2D(other->getLanes()[0]->getShape()[0]);
1185 : }
1186 1814803 : if (other->isTazConnector()) {
1187 5405 : return other->myBoundary.distanceTo2D(getLanes()[0]->getShape()[-1]);
1188 : }
1189 1809398 : return getLanes()[0]->getShape()[-1].distanceTo2D(other->getLanes()[0]->getShape()[0]);
1190 : }
1191 :
1192 :
1193 : const Position
1194 2224 : MSEdge::getStopPosition(const SUMOVehicleParameter::Stop& stop) {
1195 2224 : return MSLane::dictionary(stop.lane)->geometryPositionAtOffset((stop.endPos + stop.startPos) / 2.);
1196 : }
1197 :
1198 :
1199 : double
1200 94722094 : MSEdge::getSpeedLimit() const {
1201 : // @note lanes might have different maximum speeds in theory
1202 94722094 : return myLanes->empty() ? 1 : getLanes()[0]->getSpeedLimit();
1203 : }
1204 :
1205 :
1206 : double
1207 848 : MSEdge::getSpeedLimit(SUMOVehicleClass svc) const {
1208 : // @note lanes might have different maximum speeds in theory
1209 848 : return myLanes->empty() ? 1 : getLanes()[0]->getSpeedLimit(svc);
1210 : }
1211 :
1212 :
1213 : double
1214 1942577 : MSEdge::getLengthGeometryFactor() const {
1215 1942577 : return myLanes->empty() ? 1 : getLanes()[0]->getLengthGeometryFactor();
1216 : }
1217 :
1218 : double
1219 2069462566 : MSEdge::getVehicleMaxSpeed(const SUMOTrafficObject* const veh) const {
1220 : // @note lanes might have different maximum speeds in theory
1221 2069462566 : return myLanes->empty() ? 1 : getLanes()[0]->getVehicleMaxSpeed(veh);
1222 : }
1223 :
1224 :
1225 : void
1226 203 : MSEdge::setMaxSpeed(const double val, const bool modified, const double jamThreshold) {
1227 : assert(val >= 0);
1228 203 : if (myLanes != nullptr) {
1229 560 : for (MSLane* const lane : *myLanes) {
1230 357 : lane->setMaxSpeed(val, modified, jamThreshold);
1231 : }
1232 : }
1233 203 : }
1234 :
1235 :
1236 : void
1237 3539886 : MSEdge::addTransportable(MSTransportable* t) const {
1238 3539886 : if (t->isPerson()) {
1239 : myPersons.insert(t);
1240 : } else {
1241 : myContainers.insert(t);
1242 : }
1243 3539886 : }
1244 :
1245 : void
1246 8732720 : MSEdge::removeTransportable(MSTransportable* t) const {
1247 8732720 : std::set<MSTransportable*, ComparatorNumericalIdLess>& tc = t->isPerson() ? myPersons : myContainers;
1248 : auto it = tc.find(t);
1249 8732720 : if (it != tc.end()) {
1250 : tc.erase(it);
1251 : }
1252 8732720 : }
1253 :
1254 : std::vector<MSTransportable*>
1255 128243817 : MSEdge::getSortedPersons(SUMOTime timestep, bool includeRiding) const {
1256 128243817 : std::vector<MSTransportable*> result(myPersons.begin(), myPersons.end());
1257 128243817 : if (includeRiding) {
1258 2896155 : for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
1259 2042878 : const MSLane::VehCont& vehs = (*i)->getVehiclesSecure();
1260 3266518 : for (MSLane::VehCont::const_iterator j = vehs.begin(); j != vehs.end(); ++j) {
1261 1223640 : const std::vector<MSTransportable*>& persons = (*j)->getPersons();
1262 1223640 : result.insert(result.end(), persons.begin(), persons.end());
1263 : }
1264 2042878 : (*i)->releaseVehicles();
1265 : }
1266 : }
1267 128243817 : sort(result.begin(), result.end(), transportable_by_position_sorter(timestep));
1268 128243817 : return result;
1269 0 : }
1270 :
1271 :
1272 : std::vector<MSTransportable*>
1273 57952192 : MSEdge::getSortedContainers(SUMOTime timestep, bool /* includeRiding */) const {
1274 57952192 : std::vector<MSTransportable*> result(myContainers.begin(), myContainers.end());
1275 57952192 : sort(result.begin(), result.end(), transportable_by_position_sorter(timestep));
1276 57952192 : return result;
1277 0 : }
1278 :
1279 :
1280 : int
1281 4999022 : MSEdge::transportable_by_position_sorter::operator()(const MSTransportable* const c1, const MSTransportable* const c2) const {
1282 4999022 : const double pos1 = c1->getCurrentStage()->getEdgePos(myTime);
1283 4999022 : const double pos2 = c2->getCurrentStage()->getEdgePos(myTime);
1284 4999022 : if (pos1 != pos2) {
1285 4848868 : return pos1 < pos2;
1286 : }
1287 150154 : return c1->getID() < c2->getID();
1288 : }
1289 :
1290 :
1291 : void
1292 124760 : MSEdge::addSuccessor(MSEdge* edge, const MSEdge* via) {
1293 124760 : mySuccessors.push_back(edge);
1294 124760 : myViaSuccessors.push_back(std::make_pair(edge, via));
1295 124760 : if (isTazConnector() && edge->getFromJunction() != nullptr) {
1296 62377 : myBoundary.add(edge->getFromJunction()->getPosition());
1297 : }
1298 :
1299 249520 : edge->myPredecessors.push_back(this);
1300 124760 : if (edge->isTazConnector() && getToJunction() != nullptr) {
1301 62383 : edge->myBoundary.add(getToJunction()->getPosition());
1302 : }
1303 124760 : }
1304 :
1305 :
1306 : const MSEdgeVector&
1307 90436709 : MSEdge::getSuccessors(SUMOVehicleClass vClass) const {
1308 90436709 : if (vClass == SVC_IGNORING || !MSNet::getInstance()->hasPermissions() || myFunction == SumoXMLEdgeFunc::CONNECTOR) {
1309 90419506 : return mySuccessors;
1310 : }
1311 : #ifdef HAVE_FOX
1312 17203 : ScopedLocker<> lock(mySuccessorMutex, MSGlobals::gNumThreads > 1);
1313 : #endif
1314 : std::map<SUMOVehicleClass, MSEdgeVector>::iterator i = myClassesSuccessorMap.find(vClass);
1315 17203 : if (i == myClassesSuccessorMap.end()) {
1316 : // instantiate vector
1317 2231 : myClassesSuccessorMap[vClass];
1318 : i = myClassesSuccessorMap.find(vClass);
1319 : // this vClass is requested for the first time. rebuild all successors
1320 11474 : for (MSEdgeVector::const_iterator it = mySuccessors.begin(); it != mySuccessors.end(); ++it) {
1321 9243 : if ((*it)->isTazConnector()) {
1322 289 : i->second.push_back(*it);
1323 : } else {
1324 8954 : const std::vector<MSLane*>* allowed = allowedLanes(**it, vClass);
1325 8954 : if (allowed != nullptr && allowed->size() > 0) {
1326 6727 : i->second.push_back(*it);
1327 : }
1328 : }
1329 : }
1330 : }
1331 : // can use cached value
1332 17203 : return i->second;
1333 : }
1334 :
1335 :
1336 : const MSConstEdgePairVector&
1337 197909517 : MSEdge::getViaSuccessors(SUMOVehicleClass vClass, bool ignoreTransientPermissions) const {
1338 197909517 : if (vClass == SVC_IGNORING || !MSNet::getInstance()->hasPermissions() || myFunction == SumoXMLEdgeFunc::CONNECTOR) {
1339 192160483 : return myViaSuccessors;
1340 : }
1341 : #ifdef HAVE_FOX
1342 5749034 : ScopedLocker<> lock(mySuccessorMutex, MSGlobals::gNumThreads > 1);
1343 : #endif
1344 5749034 : auto& viaMap = ignoreTransientPermissions && myHaveTransientPermissions ? myOrigClassesViaSuccessorMap : myClassesViaSuccessorMap;
1345 : auto i = viaMap.find(vClass);
1346 5749034 : if (i != viaMap.end()) {
1347 : // can use cached value
1348 5693454 : return i->second;
1349 : }
1350 : // instantiate vector
1351 55580 : MSConstEdgePairVector& result = viaMap[vClass];
1352 : // this vClass is requested for the first time. rebuild all successors
1353 236614 : for (const auto& viaPair : myViaSuccessors) {
1354 181034 : if (viaPair.first->isTazConnector()) {
1355 6313 : result.push_back(viaPair);
1356 : } else {
1357 174721 : const std::vector<MSLane*>* allowed = allowedLanes(*viaPair.first, vClass, ignoreTransientPermissions);
1358 174721 : if (allowed != nullptr && allowed->size() > 0) {
1359 131315 : result.push_back(viaPair);
1360 : }
1361 : }
1362 : }
1363 : return result;
1364 : }
1365 :
1366 :
1367 : void
1368 1792908 : MSEdge::setJunctions(MSJunction* from, MSJunction* to) {
1369 1792908 : myFromJunction = from;
1370 1792908 : myToJunction = to;
1371 1792908 : if (!isTazConnector()) {
1372 1792908 : myBoundary.add(from->getPosition());
1373 1792908 : myBoundary.add(to->getPosition());
1374 : }
1375 1792908 : }
1376 :
1377 :
1378 : bool
1379 2975535 : MSEdge::canChangeToOpposite() const {
1380 2975535 : return (!myLanes->empty() && myLanes->back()->getOpposite() != nullptr &&
1381 : // do not change on curved internal lanes
1382 : (!isInternal()
1383 5883 : || (MSGlobals::gUsingInternalLanes
1384 5883 : && myLanes->back()->getIncomingLanes()[0].viaLink->getDirection() == LinkDirection::STRAIGHT)));
1385 : }
1386 :
1387 :
1388 : const MSEdge*
1389 22448234 : MSEdge::getOppositeEdge() const {
1390 22448234 : if (!myLanes->empty() && myLanes->back()->getOpposite() != nullptr) {
1391 2976499 : return &(myLanes->back()->getOpposite()->getEdge());
1392 : } else {
1393 19471735 : return nullptr;
1394 : }
1395 : }
1396 :
1397 :
1398 : bool
1399 178 : MSEdge::hasMinorLink() const {
1400 354 : for (const MSLane* const l : *myLanes) {
1401 386 : for (const MSLink* const link : l->getLinkCont()) {
1402 210 : if (!link->havePriority()) {
1403 : return true;
1404 : }
1405 : }
1406 : }
1407 : return false;
1408 : }
1409 :
1410 : bool
1411 211687 : MSEdge::hasChangeProhibitions(SUMOVehicleClass svc, int index) const {
1412 211687 : if (myLanes->size() == 1) {
1413 : return false;
1414 : }
1415 294653 : for (const MSLane* const l : *myLanes) {
1416 199957 : if (l->getIndex() <= index && !l->allowsChangingRight(svc) && l->getIndex() > 0) {
1417 : return true;
1418 199913 : } else if (l->getIndex() >= index && !l->allowsChangingLeft(svc) && l->getIndex() < (int)(myLanes->size() - 1)) {
1419 : return true;
1420 : }
1421 : }
1422 : return false;
1423 : }
1424 :
1425 : void
1426 923963 : MSEdge::checkAndRegisterBiDirEdge(const std::string& bidiID) {
1427 923963 : if (bidiID != "") {
1428 32980 : myBidiEdge = dictionary(bidiID);
1429 32980 : if (myBidiEdge == nullptr) {
1430 0 : WRITE_ERRORF(TL("Bidi-edge '%' does not exist"), bidiID);
1431 : }
1432 32980 : setBidiLanes();
1433 529051 : return;
1434 : }
1435 890983 : if (getFunction() != SumoXMLEdgeFunc::NORMAL) {
1436 : return;
1437 : }
1438 : // legacy networks (no bidi attribute)
1439 394912 : ConstMSEdgeVector candidates = myToJunction->getOutgoing();
1440 3116350 : for (ConstMSEdgeVector::const_iterator it = candidates.begin(); it != candidates.end(); it++) {
1441 2721438 : if ((*it)->getToJunction() == myFromJunction) { //reverse edge
1442 312484 : if (myBidiEdge != nullptr && isSuperposable(*it)) {
1443 0 : WRITE_WARNINGF(TL("Ambiguous superposable edges between junction '%' and '%'."), myToJunction->getID(), myFromJunction->getID());
1444 0 : break;
1445 : }
1446 312484 : if (isSuperposable(*it)) {
1447 26 : myBidiEdge = *it;
1448 26 : setBidiLanes();
1449 : }
1450 : }
1451 : }
1452 394912 : }
1453 :
1454 :
1455 : void
1456 33006 : MSEdge::setBidiLanes() {
1457 : assert(myBidiEdge != nullptr);
1458 33006 : if (getNumLanes() == 1 && myBidiEdge->getNumLanes() == 1) {
1459 : // the other way round is set when this method runs for the bidiEdge
1460 31274 : getLanes()[0]->setBidiLane(myBidiEdge->getLanes()[0]);
1461 : } else {
1462 : // find lanes with matching reversed shapes
1463 : int numBidiLanes = 0;
1464 5262 : for (MSLane* l1 : *myLanes) {
1465 10794 : for (MSLane* l2 : *myBidiEdge->myLanes) {
1466 7264 : if (l1->getShape().reverse().almostSame(l2->getShape(), POSITION_EPS * 2)) {
1467 1786 : l1->setBidiLane(l2);
1468 1786 : numBidiLanes++;
1469 : }
1470 : }
1471 : }
1472 : // warn only once for each pair
1473 1732 : if (numBidiLanes == 0 && getNumericalID() < myBidiEdge->getNumericalID()) {
1474 15 : WRITE_WARNINGF(TL("Edge '%' and bidi edge '%' have no matching bidi lanes"), getID(), myBidiEdge->getID());
1475 : }
1476 : }
1477 33006 : }
1478 :
1479 :
1480 : bool
1481 312484 : MSEdge::isSuperposable(const MSEdge* other) {
1482 312484 : if (other == nullptr || other->getLanes().size() != myLanes->size()) {
1483 : return false;
1484 : }
1485 : std::vector<MSLane*>::const_iterator it1 = myLanes->begin();
1486 : std::vector<MSLane*>::const_reverse_iterator it2 = other->getLanes().rbegin();
1487 : do {
1488 307694 : if ((*it1)->getShape().reverse() != (*it2)->getShape()) {
1489 : return false;
1490 : }
1491 : it1++;
1492 : it2++;
1493 26 : } while (it1 != myLanes->end());
1494 :
1495 : return true;
1496 : }
1497 :
1498 :
1499 : void
1500 74535 : MSEdge::addWaiting(SUMOVehicle* vehicle) const {
1501 : #ifdef HAVE_FOX
1502 74535 : ScopedLocker<> lock(myWaitingMutex, MSGlobals::gNumSimThreads > 1);
1503 : #endif
1504 74535 : myWaiting.push_back(vehicle);
1505 74535 : }
1506 :
1507 :
1508 : void
1509 66066 : MSEdge::removeWaiting(const SUMOVehicle* vehicle) const {
1510 : #ifdef HAVE_FOX
1511 66066 : ScopedLocker<> lock(myWaitingMutex, MSGlobals::gNumSimThreads > 1);
1512 : #endif
1513 66066 : std::vector<SUMOVehicle*>::iterator it = std::find(myWaiting.begin(), myWaiting.end(), vehicle);
1514 66066 : if (it != myWaiting.end()) {
1515 65455 : myWaiting.erase(it);
1516 : }
1517 66066 : }
1518 :
1519 :
1520 : SUMOVehicle*
1521 136866 : MSEdge::getWaitingVehicle(MSTransportable* transportable, const double position) const {
1522 : #ifdef HAVE_FOX
1523 136866 : ScopedLocker<> lock(myWaitingMutex, MSGlobals::gNumSimThreads > 1);
1524 : #endif
1525 137168 : for (SUMOVehicle* const vehicle : myWaiting) {
1526 25726 : if (transportable->isWaitingFor(vehicle)) {
1527 28148 : if (vehicle->isStoppedInRange(position, MSGlobals::gStopTolerance) ||
1528 2514 : (!vehicle->hasDeparted() &&
1529 2308 : (vehicle->getParameter().departProcedure == DepartDefinition::TRIGGERED ||
1530 83 : vehicle->getParameter().departProcedure == DepartDefinition::CONTAINER_TRIGGERED))) {
1531 : return vehicle;
1532 : }
1533 210 : if (!vehicle->isLineStop(position) && vehicle->allowsBoarding(transportable)) {
1534 228 : WRITE_WARNING((transportable->isPerson() ? "Person '" : "Container '")
1535 : + transportable->getID() + "' at edge '" + getID() + "' position " + toString(position) + " cannot use waiting vehicle '"
1536 : + vehicle->getID() + "' at position " + toString(vehicle->getPositionOnLane()) + " because it is too far away.");
1537 : }
1538 : }
1539 : }
1540 : return nullptr;
1541 : }
1542 :
1543 : std::vector<const SUMOVehicle*>
1544 143797 : MSEdge::getVehicles() const {
1545 : std::vector<const SUMOVehicle*> result;
1546 143797 : if (MSGlobals::gUseMesoSim) {
1547 220 : for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1548 122 : std::vector<const MEVehicle*> segmentVehs = segment->getVehicles();
1549 122 : result.insert(result.end(), segmentVehs.begin(), segmentVehs.end());
1550 122 : }
1551 : } else {
1552 384890 : for (MSLane* lane : getLanes()) {
1553 827650 : for (auto veh : lane->getVehiclesSecure()) {
1554 586508 : result.push_back(veh);
1555 : }
1556 241142 : lane->releaseVehicles();
1557 : }
1558 : }
1559 143797 : return result;
1560 0 : }
1561 :
1562 : int
1563 631884 : MSEdge::getNumDrivingLanes() const {
1564 : int result = 0;
1565 631884 : SVCPermissions filter = SVCAll;
1566 631884 : if ((myCombinedPermissions & ~(SVC_PEDESTRIAN | SVC_WHEELCHAIR)) != 0) {
1567 : filter = ~(SVC_PEDESTRIAN | SVC_WHEELCHAIR);
1568 3862 : } else if ((myCombinedPermissions & (SVC_PEDESTRIAN | SVC_WHEELCHAIR)) != 0) {
1569 : // filter out green verge
1570 : filter = (SVC_PEDESTRIAN | SVC_WHEELCHAIR);
1571 : }
1572 1425368 : for (const MSLane* const l : *myLanes) {
1573 793484 : if ((l->getPermissions() & filter) != 0) {
1574 703121 : result++;
1575 : }
1576 : }
1577 631884 : return result;
1578 : }
1579 :
1580 : int
1581 399 : MSEdge::getVehicleNumber() const {
1582 399 : return (int)getVehicles().size();
1583 : }
1584 :
1585 :
1586 : bool
1587 0 : MSEdge::isEmpty() const {
1588 : /// more efficient than retrieving vehicle number
1589 0 : if (MSGlobals::gUseMesoSim) {
1590 0 : for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1591 0 : if (segment->getCarNumber() > 0) {
1592 : return false;
1593 : }
1594 : }
1595 : } else {
1596 0 : for (MSLane* lane : getLanes()) {
1597 0 : if (lane->getVehicleNumber() > 0) {
1598 : return false;
1599 : }
1600 : }
1601 : }
1602 : return true;
1603 : }
1604 :
1605 :
1606 : double
1607 14 : MSEdge::getWaitingSeconds() const {
1608 : double wtime = 0;
1609 14 : if (MSGlobals::gUseMesoSim) {
1610 12 : for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1611 9 : wtime += segment->getWaitingSeconds();
1612 : }
1613 : } else {
1614 34 : for (MSLane* lane : getLanes()) {
1615 23 : wtime += lane->getWaitingSeconds();
1616 : }
1617 : }
1618 14 : return wtime;
1619 : }
1620 :
1621 :
1622 : double
1623 22 : MSEdge::getOccupancy() const {
1624 22 : if (myLanes->size() == 0) {
1625 : return 0;
1626 : }
1627 22 : if (MSGlobals::gUseMesoSim) {
1628 : /// @note MESegment only tracks brutto occupancy so we compute this from sratch
1629 : double sum = 0;
1630 8 : for (const SUMOVehicle* veh : getVehicles()) {
1631 4 : sum += dynamic_cast<const MEVehicle*>(veh)->getVehicleType().getLength();
1632 4 : }
1633 4 : return sum / (myLength * (double)myLanes->size());
1634 : } else {
1635 : double sum = 0;
1636 48 : for (auto lane : getLanes()) {
1637 30 : sum += lane->getNettoOccupancy();
1638 : }
1639 18 : return sum / (double)myLanes->size();
1640 : }
1641 : }
1642 :
1643 :
1644 : double
1645 0 : MSEdge::getFlow() const {
1646 0 : if (myLanes->size() == 0) {
1647 : return 0;
1648 : }
1649 : double flow = 0;
1650 0 : for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1651 0 : flow += (double) segment->getCarNumber() * segment->getMeanSpeed();
1652 : }
1653 0 : return 3600 * flow / (*myLanes)[0]->getLength();
1654 : }
1655 :
1656 :
1657 : double
1658 0 : MSEdge::getBruttoOccupancy() const {
1659 0 : if (myLanes->size() == 0) {
1660 : return 0;
1661 : }
1662 : double occ = 0;
1663 0 : for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1664 0 : occ += segment->getBruttoOccupancy();
1665 : }
1666 0 : return occ / (*myLanes)[0]->getLength() / (double)(myLanes->size());
1667 : }
1668 :
1669 : double
1670 4240 : MSEdge::getTravelTimeAggregated(const MSEdge* const edge, const SUMOVehicle* const veh, double /*time*/) {
1671 4240 : return edge->getLength() / MIN2(MSRoutingEngine::getAssumedSpeed(edge, veh), veh->getMaxSpeed());
1672 : }
1673 :
1674 :
1675 : void
1676 2098 : MSEdge::inferEdgeType() {
1677 : // @note must be called after closeBuilding() to ensure successors and
1678 : // predecessors are set
1679 2098 : if (isInternal() && myEdgeType == "") {
1680 1274 : const std::string typeBefore = getNormalBefore()->getEdgeType();
1681 1274 : if (typeBefore != "") {
1682 694 : const std::string typeAfter = getNormalSuccessor()->getEdgeType();
1683 694 : if (typeBefore == typeAfter) {
1684 : myEdgeType = typeBefore;
1685 314 : } else if (typeAfter != "") {
1686 68 : MSNet* net = MSNet::getInstance();
1687 68 : auto resBefore = net->getRestrictions(typeBefore);
1688 68 : auto resAfter = net->getRestrictions(typeAfter);
1689 68 : if (resBefore != nullptr && resAfter != nullptr) {
1690 : // create new restrictions for this type-combination
1691 96 : myEdgeType = typeBefore + "|" + typeAfter;
1692 48 : if (net->getRestrictions(myEdgeType) == nullptr) {
1693 48 : for (const auto& item : *resBefore) {
1694 24 : const SUMOVehicleClass svc = item.first;
1695 24 : const double speed = item.second;
1696 : const auto it = (*resAfter).find(svc);
1697 24 : if (it != (*resAfter).end()) {
1698 24 : const double speed2 = it->second;
1699 24 : const double newSpeed = (MSNet::getInstance()->hasJunctionHigherSpeeds()
1700 24 : ? MAX2(speed, speed2) : (speed + speed2) / 2);
1701 24 : net->addRestriction(myEdgeType, svc, newSpeed);
1702 : }
1703 : }
1704 : }
1705 : }
1706 : }
1707 : }
1708 : }
1709 2098 : }
1710 :
1711 :
1712 : double
1713 2178 : MSEdge::getDistanceAt(double pos) const {
1714 : // negative values of myDistances indicate descending kilometrage
1715 2178 : return fabs(myDistance + pos);
1716 : }
1717 :
1718 :
1719 : bool
1720 1346 : MSEdge::hasTransientPermissions() const {
1721 1346 : return myHaveTransientPermissions;
1722 : }
1723 :
1724 :
1725 : std::pair<double, SUMOTime>
1726 596451655 : MSEdge::getLastBlocked(int index) const {
1727 596451655 : if (myLaneChanger != nullptr) {
1728 596451655 : return myLaneChanger->getLastBlocked(index);
1729 : }
1730 0 : return std::make_pair(-1, -1);
1731 : }
1732 :
1733 :
1734 : double
1735 2855 : MSEdge::getPreference(const SUMOVTypeParameter& pars) const {
1736 5710 : return MSNet::getInstance()->getPreference(getRoutingType(), pars);
1737 : }
1738 :
1739 :
1740 : void
1741 6960 : MSEdge::clearState() {
1742 : myPersons.clear();
1743 : myContainers.clear();
1744 : myWaiting.clear();
1745 6960 : }
1746 :
1747 :
1748 : const std::map<const MEVehicle*, std::pair<double, int> >&
1749 1526916 : MSEdge::getMesoPositions() const {
1750 : assert(MSGlobals::gUseMesoSim);
1751 1526916 : if (myLastCacheUpdate < SIMSTEP) {
1752 1493663 : myLastCacheUpdate = SIMSTEP;
1753 : auto old = std::move(myCachedMesoPos);
1754 : myCachedMesoPos.clear(); // moved-from map is valid-but-unspecified; make it defined-empty
1755 : int laneIndex = 0;
1756 1493663 : const double now = SIMTIME;
1757 3519743 : for (std::vector<MSLane*>::const_iterator msl = myLanes->begin(); msl != myLanes->end(); ++msl, ++laneIndex) {
1758 : // go through the vehicles
1759 : double segmentOffset = 0; // offset at start of current segment
1760 2026080 : for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this);
1761 4408110 : segment != nullptr; segment = segment->getNextSegment()) {
1762 : const double segLength = segment->getLength();
1763 2382030 : const double lanesCovered = segment->numQueues() == 1 ? std::round(segment->getCapacity() / segLength) : 1.;
1764 2382030 : if (laneIndex < segment->numQueues()) {
1765 : // make a copy so we don't have to worry about synchronization
1766 1866298 : std::vector<MEVehicle*> queue = segment->getQueue(laneIndex);
1767 1866298 : const int queueSize = (int)queue.size();
1768 : SUMOTime earliestExitTime = segment->getQueueBlockTime(laneIndex);
1769 : int overlap = 0;
1770 : double prevPos = std::numeric_limits<double>::max();
1771 4751344 : for (int i = 0; i < queueSize; ++i) {
1772 2885046 : const MEVehicle* const veh = queue[queueSize - i - 1];
1773 : earliestExitTime = MAX2(earliestExitTime, veh->getEventTime());
1774 2885046 : const double vehLength = veh->getVehicleType().getLengthWithGap();
1775 2885046 : double maxPos = segmentOffset + segLength;
1776 : auto it = old.find(veh);
1777 2885046 : const double oldPos = it != old.end() ? it->second.first : 0.; // store the old position to prevent backwards moving vehicles
1778 2885046 : if (i > 0) {
1779 2620934 : earliestExitTime += segment->getMinTauWithVehLength(vehLength, veh->getVehicleType().getCarFollowModel().getHeadwayTime());
1780 2620934 : maxPos = MIN2(maxPos, prevPos - vehLength / lanesCovered);
1781 : }
1782 2885046 : const double entry = veh->getLastEntryTimeSeconds();
1783 : assert(STEPS2TIME(earliestExitTime) > entry);
1784 2885046 : const double pos = MAX2(MIN2(segmentOffset + segLength * (now - entry) / (STEPS2TIME(earliestExitTime) - entry), maxPos), oldPos);
1785 : // check if we overlap with the previous vehicle such that the gui has the chance to add some lateral offset
1786 2885046 : if (overlap == 0 && prevPos - pos < vehLength) {
1787 853310 : overlap = lanesCovered > 1. ? -3 : -1;
1788 : } else {
1789 : overlap = 0;
1790 : }
1791 2885046 : myCachedMesoPos[veh] = std::make_pair(pos, overlap);
1792 : prevPos = pos;
1793 : }
1794 1866298 : }
1795 2382030 : segmentOffset += segLength;
1796 : }
1797 : }
1798 : }
1799 1526916 : return myCachedMesoPos;
1800 : }
1801 :
1802 :
1803 : double
1804 11296163 : MSEdge::getMinLength() const {
1805 : double result = std::numeric_limits<double>::max();
1806 32472123 : for (const MSLane* l : *myLanes) {
1807 : result = MIN2(result, l->getLength());
1808 : }
1809 11296163 : return result;
1810 : }
1811 :
1812 :
1813 : /****************************************************************************/
|