Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2025 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 1845994 : 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 1845994 : double distance) :
75 1845994 : Named(id), myNumericalID(numericalID), myLanes(nullptr),
76 1845994 : myLaneChanger(nullptr), myFunction(function), myVaporizationRequests(0),
77 1845994 : myLastFailedInsertionTime(-1),
78 1845994 : myFromJunction(nullptr), myToJunction(nullptr),
79 1845994 : myHaveTransientPermissions(false),
80 1845994 : myOtherTazConnector(nullptr),
81 1845994 : myStreetName(streetName),
82 1845994 : myEdgeType(edgeType),
83 1845994 : myRoutingType(routingType),
84 1845994 : myPriority(priority),
85 1845994 : myDistance(distance),
86 1845994 : myWidth(0.),
87 1845994 : myLength(0.),
88 1845994 : myEmptyTraveltime(0.),
89 1845994 : myTimePenalty(0.),
90 1845994 : myAmDelayed(false),
91 1845994 : myAmRoundabout(false),
92 1845994 : myAmFringe(true),
93 3691988 : myBidiEdge(nullptr)
94 1845994 : { }
95 :
96 :
97 3199124 : MSEdge::~MSEdge() {
98 1830458 : delete myLaneChanger;
99 1830458 : delete myReversedRoutingEdge;
100 1830458 : delete myRailwayRoutingEdge;
101 10520956 : }
102 :
103 :
104 : void
105 1721203 : MSEdge::initialize(const std::vector<MSLane*>* lanes) {
106 : assert(lanes != 0);
107 1721203 : myLanes = std::shared_ptr<const std::vector<MSLane*> >(lanes);
108 1721203 : if (myFunction == SumoXMLEdgeFunc::CONNECTOR) {
109 57862 : myCombinedPermissions = SVCAll;
110 : }
111 3726965 : for (MSLane* const lane : *lanes) {
112 2005762 : lane->setRightSideOnEdge(myWidth, (int)mySublaneSides.size());
113 2005762 : MSLeaderInfo ahead(lane->getWidth());
114 4702191 : for (int j = 0; j < ahead.numSublanes(); ++j) {
115 2696429 : mySublaneSides.push_back(myWidth + j * MSGlobals::gLateralResolution);
116 : }
117 2005762 : myWidth += lane->getWidth();
118 2005762 : }
119 1721203 : }
120 :
121 :
122 1745794 : void MSEdge::recalcCache() {
123 1745794 : if (myLanes->empty()) {
124 : return;
125 : }
126 1745794 : myLength = myLanes->front()->getLength();
127 3491588 : myEmptyTraveltime = myLength / MAX2(getSpeedLimit(), NUMERICAL_EPS);
128 1745794 : if (isNormal() && (MSGlobals::gUseMesoSim || MSGlobals::gTLSPenalty > 0)) {
129 : SUMOTime minorPenalty = 0;
130 169433 : bool haveTLSPenalty = MSGlobals::gTLSPenalty > 0;
131 169433 : if (MSGlobals::gUseMesoSim) {
132 169318 : const MESegment::MesoEdgeType& edgeType = MSNet::getInstance()->getMesoType(getEdgeType());
133 169318 : minorPenalty = edgeType.minorPenalty;
134 169318 : haveTLSPenalty = edgeType.tlsPenalty > 0;
135 : }
136 169433 : 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 1576361 : } else if (isCrossing() && MSGlobals::gTLSPenalty > 0) {
158 : // penalties are recorded for the entering link
159 80 : for (const auto& ili : myLanes->front()->getIncomingLanes()) {
160 40 : double penalty = STEPS2TIME(ili.viaLink->getMesoTLSPenalty());
161 40 : if (!ili.viaLink->haveOffPriority()) {
162 0 : penalty = MAX2(penalty, MSGlobals::gMinorPenalty);
163 : }
164 40 : if (penalty > 0) {
165 20 : myEmptyTraveltime += penalty;
166 20 : myTimePenalty = penalty;
167 : }
168 : }
169 1576321 : } else if (isInternal() && MSGlobals::gUsingInternalLanes) {
170 713553 : const MSLink* link = myLanes->front()->getIncomingLanes()[0].viaLink;
171 713553 : if (!link->isTLSControlled() && !link->havePriority()) {
172 341048 : if (link->isTurnaround()) {
173 127048 : myEmptyTraveltime += MSGlobals::gTurnaroundPenalty;
174 127048 : myTimePenalty = MSGlobals::gTurnaroundPenalty;
175 : } else {
176 214000 : myEmptyTraveltime += MSGlobals::gMinorPenalty;
177 214000 : myTimePenalty = MSGlobals::gMinorPenalty;
178 : }
179 : }
180 : }
181 : }
182 :
183 :
184 : void
185 42 : MSEdge::resetTAZ(MSJunction* junction) {
186 : mySuccessors.clear();
187 : myPredecessors.clear();
188 728 : for (const MSEdge* edge : junction->getIncoming()) {
189 686 : if (!edge->isInternal()) {
190 126 : MSEdgeVector& succ = const_cast<MSEdgeVector&>(edge->mySuccessors);
191 : MSConstEdgePairVector& succVia = const_cast<MSConstEdgePairVector&>(edge->myViaSuccessors);
192 126 : MSEdgeVector& pred = const_cast<MSEdgeVector&>(edge->myPredecessors);
193 126 : auto it = std::find(succ.begin(), succ.end(), this);
194 126 : auto it2 = std::find(succVia.begin(), succVia.end(), std::make_pair(const_cast<const MSEdge*>(this), (const MSEdge*)nullptr));
195 126 : auto it3 = std::find(pred.begin(), pred.end(), this);
196 126 : if (it != succ.end()) {
197 : succ.erase(it);
198 : succVia.erase(it2);
199 : }
200 126 : if (it3 != pred.end()) {
201 : pred.erase(it3);
202 : }
203 : }
204 : }
205 42 : }
206 :
207 : void
208 1660846 : MSEdge::closeBuilding() {
209 3663698 : for (MSLane* const lane : *myLanes) {
210 4574716 : for (MSLink* const link : lane->getLinkCont()) {
211 2571864 : link->initParallelLinks();
212 : MSLane* const toL = link->getLane();
213 : MSLane* const viaL = link->getViaLane();
214 2571864 : if (toL != nullptr) {
215 : MSEdge& to = toL->getEdge();
216 2571864 : if (std::find(mySuccessors.begin(), mySuccessors.end(), &to) == mySuccessors.end()) {
217 2390269 : mySuccessors.push_back(&to);
218 4780538 : myViaSuccessors.push_back(std::make_pair(&to, (viaL == nullptr ? nullptr : &viaL->getEdge())));
219 : }
220 2571864 : if (std::find(to.myPredecessors.begin(), to.myPredecessors.end(), this) == to.myPredecessors.end()) {
221 2390269 : to.myPredecessors.push_back(this);
222 : }
223 2571864 : if (link->getDirection() != LinkDirection::TURN) {
224 2001205 : myAmFringe = false;
225 : }
226 : }
227 2571864 : if (viaL != nullptr) {
228 : MSEdge& to = viaL->getEdge();
229 783117 : if (std::find(to.myPredecessors.begin(), to.myPredecessors.end(), this) == to.myPredecessors.end()) {
230 713370 : to.myPredecessors.push_back(this);
231 : }
232 : }
233 : }
234 2002852 : lane->checkBufferType();
235 : }
236 1660846 : std::sort(mySuccessors.begin(), mySuccessors.end(), by_id_sorter());
237 1660846 : rebuildAllowedLanes(true);
238 1660846 : recalcCache();
239 :
240 : // extend lookup table for sublane model after all edges are read
241 1660846 : if (myLanes->back()->getOpposite() != nullptr) {
242 7526 : MSLane* opposite = myLanes->back()->getOpposite();
243 7526 : MSLeaderInfo ahead(opposite->getWidth());
244 21178 : for (int j = 0; j < ahead.numSublanes(); ++j) {
245 13652 : mySublaneSides.push_back(myWidth + j * MSGlobals::gLateralResolution);
246 : }
247 7526 : }
248 1660846 : }
249 :
250 :
251 : void
252 613 : MSEdge::updateMesoType() {
253 : assert(MSGlobals::gUseMesoSim);
254 613 : if (!myLanes->empty()) {
255 613 : MSGlobals::gMesoNet->updateSegmentsForEdge(*this);
256 : }
257 613 : }
258 :
259 : void
260 1660838 : MSEdge::postLoadInitLaneChanger() {
261 1660838 : if (myLaneChanger != nullptr) {
262 421787 : myLaneChanger->postloadInitLC();
263 : }
264 1660838 : }
265 :
266 : void
267 1660846 : MSEdge::buildLaneChanger() {
268 1660846 : if (!myLanes->empty()) {
269 1660846 : const bool allowChanging = allowsLaneChanging();
270 1660846 : if (MSGlobals::gLateralResolution > 0) {
271 : // may always initiate sublane-change
272 176506 : if (!isInternal() || MSGlobals::gUsingInternalLanes) {
273 176315 : myLaneChanger = new MSLaneChangerSublane(myLanes.get(), allowChanging);
274 : }
275 : } else {
276 1484340 : if (MSGlobals::gLaneChangeDuration > 0) {
277 3717 : myLaneChanger = new MSLaneChanger(myLanes.get(), allowChanging);
278 1480623 : } else if (myLanes->size() > 1 || canChangeToOpposite()) {
279 241763 : myLaneChanger = new MSLaneChanger(myLanes.get(), allowChanging);
280 : }
281 : }
282 : }
283 1660846 : }
284 :
285 :
286 : bool
287 1660846 : MSEdge::allowsLaneChanging() const {
288 1660846 : if (isInternal() && MSGlobals::gUsingInternalLanes) {
289 : // allow changing only if all links leading to this internal lane have priority
290 : // or they are controlled by a traffic light
291 1152548 : for (const MSLane* const lane : *myLanes) {
292 780397 : const MSLink* const link = lane->getLogicalPredecessorLane()->getLinkTo(lane);
293 : assert(link != nullptr);
294 : const LinkState state = link->getState();
295 332536 : if ((state == LINKSTATE_MINOR && lane->getBidiLane() == nullptr)
296 448097 : || state == LINKSTATE_EQUAL
297 448097 : || state == LINKSTATE_STOP
298 : || state == LINKSTATE_ALLWAY_STOP
299 780397 : || state == LINKSTATE_DEADEND) {
300 : return false;
301 : }
302 : }
303 : }
304 : return true;
305 : }
306 :
307 :
308 : void
309 16923265 : MSEdge::addToAllowed(const SVCPermissions permissions, std::shared_ptr<const std::vector<MSLane*> > allowedLanes, AllowedLanesCont& laneCont) const {
310 16923265 : if (!allowedLanes->empty()) {
311 : // recheck whether we had this list to save memory
312 17089928 : for (auto& allowed : laneCont) {
313 16124393 : if (*allowed.second == *allowedLanes) {
314 12010628 : allowed.first |= permissions;
315 : return;
316 : }
317 : }
318 965535 : laneCont.push_back(std::make_pair(permissions, allowedLanes));
319 : }
320 : }
321 :
322 :
323 : SVCPermissions
324 2745064 : MSEdge::getMesoPermissions(SVCPermissions p, SVCPermissions ignoreIgnored) {
325 2745064 : SVCPermissions ignored = myMesoIgnoredVClasses & ~ignoreIgnored;
326 2745064 : return (p | ignored) == ignored ? 0 : p;
327 : }
328 :
329 :
330 : void
331 1662292 : MSEdge::rebuildAllowedLanes(const bool onInit, bool updateVehicles) {
332 : // rebuild myMinimumPermissions and myCombinedPermissions
333 1662292 : myMinimumPermissions = SVCAll;
334 1662292 : myCombinedPermissions = 0;
335 : bool lanesChangedPermission = false;
336 3667128 : for (MSLane* const lane : *myLanes) {
337 : // same dedicated lanes are ignored in meso to avoid capacity errors.
338 : // Here we have to make sure that vehicles which are set to depart on
339 : // such lanes trigger an error.
340 2004836 : SVCPermissions allow = getMesoPermissions(lane->getPermissions(), SVC_PEDESTRIAN);
341 2004836 : myMinimumPermissions &= allow;
342 2004836 : myCombinedPermissions |= allow;
343 2004836 : lanesChangedPermission |= lane->hadPermissionChanges();
344 : }
345 1662292 : if (!onInit && !myHaveTransientPermissions && lanesChangedPermission) {
346 993 : myHaveTransientPermissions = true;
347 : // backup original structures when first needed
348 993 : myOrigAllowed = myAllowed;
349 : myOrigAllowedTargets = myAllowedTargets;
350 : myOrigClassesViaSuccessorMap = myClassesViaSuccessorMap;
351 : }
352 : // rebuild myAllowed
353 : myAllowed.clear();
354 1662292 : if (myCombinedPermissions != myMinimumPermissions) {
355 161908 : myAllowed.push_back(std::make_pair(SVC_IGNORING, myLanes));
356 5504872 : for (SVCPermissions vclass = SVC_PRIVATE; vclass <= SUMOVehicleClass_MAX; vclass *= 2) {
357 5342964 : if ((myCombinedPermissions & vclass) == vclass) {
358 : std::shared_ptr<std::vector<MSLane*> > allowedLanes = std::make_shared<std::vector<MSLane*> >();
359 11207147 : for (MSLane* const lane : *myLanes) {
360 7591642 : if (lane->allowsVehicleClass((SUMOVehicleClass)vclass)) {
361 3824047 : allowedLanes->push_back(lane);
362 : }
363 : }
364 7231010 : addToAllowed(vclass, allowedLanes, myAllowed);
365 : }
366 : }
367 : }
368 1662292 : if (onInit) {
369 1660846 : myOriginalMinimumPermissions = myMinimumPermissions;
370 1660846 : myOriginalCombinedPermissions = myCombinedPermissions;
371 : } else {
372 1446 : rebuildAllowedTargets(updateVehicles);
373 3671 : for (MSEdge* pred : myPredecessors) {
374 2225 : if (myHaveTransientPermissions && !pred->myHaveTransientPermissions) {
375 1368 : pred->myOrigAllowed = pred->myAllowed;
376 : pred->myOrigAllowedTargets = pred->myAllowedTargets;
377 : pred->myOrigClassesViaSuccessorMap = pred->myClassesViaSuccessorMap;
378 1368 : pred->myHaveTransientPermissions = true;
379 : }
380 2225 : pred->rebuildAllowedTargets(updateVehicles);
381 : }
382 1446 : if (MSGlobals::gUseMesoSim) {
383 2252 : for (MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(*this); s != nullptr; s = s->getNextSegment()) {
384 1886 : s->updatePermissions();
385 : }
386 : }
387 : }
388 1662292 : }
389 :
390 :
391 : void
392 1665522 : MSEdge::rebuildAllowedTargets(const bool updateVehicles) {
393 : myAllowedTargets.clear();
394 4062660 : 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 5482640 : for (MSLane* const lane : *myLanes) {
399 : SVCPermissions combinedTargetPermissions = 0;
400 8922561 : for (const MSLink* const link : lane->getLinkCont()) {
401 5837059 : if (&link->getLane()->getEdge() == target) {
402 2579872 : allLanes->push_back(lane);
403 2579872 : combinedTargetPermissions |= link->getLane()->getPermissions();
404 2579872 : if (link->getViaLane() != nullptr &&
405 785362 : ((lane->getPermissions() & link->getLane()->getPermissions()) != link->getViaLane()->getPermissions())) {
406 : // custom connection permissions
407 : universalMap = false;
408 : }
409 : }
410 : }
411 3085502 : if (combinedTargetPermissions == 0 || (lane->getPermissions() & combinedTargetPermissions) != lane->getPermissions()) {
412 : universalMap = false;
413 : }
414 : }
415 2397138 : if (universalMap) {
416 1939517 : if (myAllowed.empty()) {
417 : // we have no lane specific permissions
418 3812310 : myAllowedTargets[target].push_back(std::make_pair(myMinimumPermissions, myLanes));
419 : } else {
420 131649 : for (const auto& i : myAllowed) {
421 294861 : addToAllowed(i.first, i.second, myAllowedTargets[target]);
422 : }
423 : }
424 : } else {
425 915242 : addToAllowed(SVC_IGNORING, allLanes, myAllowedTargets[target]);
426 : // compute the vclass specific mapping
427 15559114 : for (SVCPermissions vclass = SVC_PRIVATE; vclass <= SUMOVehicleClass_MAX; vclass *= 2) {
428 15101493 : if ((myCombinedPermissions & vclass) == vclass) {
429 : std::shared_ptr<std::vector<MSLane*> > allowedLanes = std::make_shared<std::vector<MSLane*> >();
430 39586260 : for (MSLane* const lane : *myLanes) {
431 26834408 : if (lane->allowsVehicleClass((SUMOVehicleClass)vclass)) {
432 50710440 : for (const MSLink* const link : lane->getLinkCont()) {
433 33004428 : if (link->getLane()->allowsVehicleClass((SUMOVehicleClass)vclass) && &link->getLane()->getEdge() == target && (link->getViaLane() == nullptr || link->getViaLane()->allowsVehicleClass((SUMOVehicleClass)vclass))) {
434 9154715 : allowedLanes->push_back(lane);
435 : }
436 : }
437 : }
438 : }
439 38255556 : addToAllowed(vclass, allowedLanes, myAllowedTargets[target]);
440 : }
441 : }
442 : }
443 : }
444 1665522 : if (updateVehicles) {
445 3059 : for (const MSLane* const lane : *myLanes) {
446 1807 : const MSLane::VehCont& vehs = lane->getVehiclesSecure();
447 4487 : for (MSVehicle* veh : vehs) {
448 2680 : veh->updateBestLanes(true);
449 : }
450 1807 : lane->releaseVehicles();
451 : }
452 : }
453 : myClassesSuccessorMap.clear();
454 1665522 : }
455 :
456 :
457 : // ------------ Access to the edge's lanes
458 : MSLane*
459 870 : MSEdge::leftLane(const MSLane* const lane) const {
460 870 : return parallelLane(lane, 1);
461 : }
462 :
463 :
464 : MSLane*
465 448 : MSEdge::rightLane(const MSLane* const lane) const {
466 448 : return parallelLane(lane, -1);
467 : }
468 :
469 :
470 : MSLane*
471 86099015 : MSEdge::parallelLane(const MSLane* const lane, int offset, bool includeOpposite) const {
472 86099015 : const int resultIndex = lane->getIndex() + offset;
473 86099015 : if (resultIndex >= getNumLanes() && includeOpposite) {
474 20100506 : const MSEdge* opposite = getOppositeEdge();
475 20100506 : if (opposite != nullptr && resultIndex < getNumLanes() + opposite->getNumLanes()) {
476 1375721 : return opposite->getLanes()[opposite->getNumLanes() + getNumLanes() - resultIndex - 1];
477 : }
478 : return nullptr;
479 65998509 : } else if (resultIndex >= (int)myLanes->size() || resultIndex < 0) {
480 : return nullptr;
481 : } else {
482 43690243 : return (*myLanes)[resultIndex];
483 : }
484 : }
485 :
486 :
487 : const std::vector<MSLane*>*
488 80088246 : MSEdge::allowedLanes(const MSEdge& destination, SUMOVehicleClass vclass, bool ignoreTransientPermissions) const {
489 80088246 : const auto& targets = ignoreTransientPermissions && myHaveTransientPermissions ? myOrigAllowedTargets : myAllowedTargets;
490 : AllowedLanesByTarget::const_iterator i = targets.find(&destination);
491 80088246 : if (i != targets.end()) {
492 80096006 : for (const auto& allowed : i->second) {
493 79988789 : 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 714944811 : MSEdge::allowedLanes(SUMOVehicleClass vclass) const {
504 714944811 : if ((myMinimumPermissions & vclass) == vclass) {
505 44063133 : return myLanes.get();
506 : } else {
507 670881678 : if ((myCombinedPermissions & vclass) == vclass) {
508 1341760021 : for (const auto& allowed : myAllowed) {
509 1341760021 : if ((allowed.first & vclass) == vclass) {
510 : return allowed.second.get();
511 : }
512 : }
513 : }
514 1989 : return nullptr;
515 : }
516 : }
517 :
518 :
519 : const std::vector<MSLane*>*
520 6921333875 : MSEdge::allowedLanes(SUMOVehicleClass vclass, bool ignoreTransientPermissions) const {
521 6921333875 : const SVCPermissions& minP = ignoreTransientPermissions ? myOriginalMinimumPermissions : myMinimumPermissions;
522 6921333875 : if ((minP & vclass) == vclass) {
523 626920485 : return myLanes.get();
524 : } else {
525 6294413390 : const SVCPermissions comP = ignoreTransientPermissions ? myOriginalCombinedPermissions : myCombinedPermissions;
526 6294413390 : if ((comP & vclass) == vclass) {
527 6294413317 : const AllowedLanesCont& allowedCont = ignoreTransientPermissions ? myOrigAllowed : myAllowed;
528 12594520979 : for (const auto& allowed : allowedCont) {
529 12594520979 : if ((allowed.first & vclass) == vclass) {
530 : return allowed.second.get();
531 : }
532 : }
533 : }
534 73 : return nullptr;
535 : }
536 : }
537 :
538 :
539 : // ------------
540 : SUMOTime
541 432 : MSEdge::incVaporization(SUMOTime) {
542 432 : ++myVaporizationRequests;
543 432 : return 0;
544 : }
545 :
546 :
547 : SUMOTime
548 282 : MSEdge::decVaporization(SUMOTime) {
549 282 : --myVaporizationRequests;
550 282 : return 0;
551 : }
552 :
553 :
554 : MSLane*
555 565113935 : MSEdge::getFreeLane(const std::vector<MSLane*>* allowed, const SUMOVehicleClass vclass, double departPos) const {
556 565113935 : if (allowed == nullptr) {
557 525439317 : allowed = allowedLanes(vclass);
558 : }
559 : MSLane* res = nullptr;
560 525439317 : if (allowed != nullptr) {
561 : double largestGap = 0;
562 : MSLane* resByGap = nullptr;
563 : double leastOccupancy = std::numeric_limits<double>::max();
564 1155858615 : for (std::vector<MSLane*>::const_iterator i = allowed->begin(); i != allowed->end(); ++i) {
565 590746661 : const double occupancy = (*i)->getBruttoOccupancy();
566 590746661 : if (occupancy < leastOccupancy) {
567 573823454 : res = (*i);
568 : leastOccupancy = occupancy;
569 : }
570 590746661 : const MSVehicle* last = (*i)->getLastFullVehicle();
571 590746661 : const double lastGap = (last != nullptr ? last->getPositionOnLane() : myLength) - departPos;
572 590746661 : if (lastGap > largestGap) {
573 : largestGap = lastGap;
574 67877688 : resByGap = (*i);
575 : }
576 : }
577 565111954 : 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 565113935 : return res;
583 : }
584 :
585 :
586 : MSLane*
587 3267458 : MSEdge::getProbableLane(const std::vector<MSLane*>* allowed, const SUMOVehicleClass vclass, double departPos, double maxSpeed) const {
588 3267458 : 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 11511999 : for (std::vector<MSLane*>::const_iterator i = allowed->begin(); i != allowed->end(); ++i, aIndex++) {
599 8244541 : const double occupancy = (*i)->getBruttoOccupancy();
600 8244541 : if (occupancy < leastOccupancy) {
601 7552371 : res = (*i);
602 : leastOccupancy = occupancy;
603 : }
604 8244541 : const MSVehicle* last = (*i)->getLastFullVehicle();
605 8244541 : double lastGap = (last != nullptr ? last->getPositionOnLane() : myLength) - departPos;
606 : // never insert to the left of a vehicle with a larger speedFactor
607 8244541 : if (lastGap > largestGap && maxSpeed >= largestSpeed) {
608 : largestGap = lastGap;
609 4450922 : resByGap = (*i);
610 : }
611 8244541 : if (last != nullptr) {
612 8243633 : largestSpeed = MAX2(largestSpeed, getVehicleMaxSpeed(last));
613 : }
614 : }
615 3267458 : 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 3267458 : return res;
621 : }
622 :
623 :
624 : double
625 568456734 : MSEdge::getDepartPosBound(const MSVehicle& veh, bool upper) const {
626 568456734 : const SUMOVehicleParameter& pars = veh.getParameter();
627 : double pos = getLength();
628 : // determine the position
629 568456734 : switch (pars.departPosProcedure) {
630 1778242 : case DepartPosDefinition::GIVEN:
631 1778242 : pos = pars.departPos;
632 1778242 : if (pos < 0.) {
633 1699610 : 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 313720 : case DepartPosDefinition::LAST:
647 313720 : if (upper) {
648 468718 : for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
649 318336 : MSVehicle* last = (*i)->getLastFullVehicle();
650 318336 : if (last != nullptr) {
651 276366 : pos = MIN2(pos, last->getPositionOnLane());
652 : }
653 : }
654 : } else {
655 : pos = 0;
656 : }
657 : break;
658 61260494 : case DepartPosDefinition::BASE:
659 : case DepartPosDefinition::DEFAULT:
660 61260494 : if (!upper) {
661 : pos = 0;
662 : }
663 : break;
664 20 : default:
665 20 : pos = MIN2(pos, veh.getVehicleType().getLength());
666 : break;
667 : }
668 568456734 : return pos;
669 : }
670 :
671 : MSLane*
672 42 : MSEdge::getDepartLaneMeso(SUMOVehicle& veh) const {
673 42 : if (veh.getParameter().departLaneProcedure == DepartLaneDefinition::GIVEN) {
674 2 : if ((int) myLanes->size() <= veh.getParameter().departLane || !(*myLanes)[veh.getParameter().departLane]->allowsVehicleClass(veh.getVehicleType().getVehicleClass())) {
675 0 : return nullptr;
676 : }
677 2 : return (*myLanes)[veh.getParameter().departLane];
678 : }
679 40 : return (*myLanes)[0];
680 : }
681 :
682 : MSLane*
683 6827168998 : MSEdge::getDepartLane(MSVehicle& veh) const {
684 6827168998 : DepartLaneDefinition dld = veh.getParameter().departLaneProcedure;
685 6827168998 : int departLane = veh.getParameter().departLane;
686 6827168998 : if (dld == DepartLaneDefinition::DEFAULT) {
687 5964641093 : dld = myDefaultDepartLaneDefinition;
688 5964641093 : departLane = myDefaultDepartLane;
689 : }
690 6827168998 : switch (dld) {
691 100831973 : case DepartLaneDefinition::GIVEN:
692 100831973 : if ((int) myLanes->size() <= departLane || !(*myLanes)[departLane]->allowsVehicleClass(veh.getVehicleType().getVehicleClass())) {
693 61 : return nullptr;
694 : }
695 100831912 : return (*myLanes)[departLane];
696 189478300 : case DepartLaneDefinition::RANDOM:
697 378956600 : return RandHelper::getRandomFrom(*allowedLanes(veh.getVehicleType().getVehicleClass()));
698 525340618 : case DepartLaneDefinition::FREE:
699 525340618 : return getFreeLane(nullptr, veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false));
700 8215124 : case DepartLaneDefinition::ALLOWED_FREE:
701 8215124 : if (veh.getRoute().size() == 1) {
702 5494 : return getFreeLane(nullptr, veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false));
703 : } else {
704 8209630 : return getFreeLane(allowedLanes(**(veh.getRoute().begin() + 1), veh.getVehicleType().getVehicleClass()), veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false));
705 : }
706 34538098 : case DepartLaneDefinition::BEST_FREE:
707 : case DepartLaneDefinition::BEST_PROB: {
708 34538098 : veh.updateBestLanes(false, myLanes->front());
709 34538098 : const std::vector<MSVehicle::LaneQ>& bl = veh.getBestLanes();
710 : double bestLength = -1;
711 108905361 : for (std::vector<MSVehicle::LaneQ>::const_iterator i = bl.begin(); i != bl.end(); ++i) {
712 74367263 : if ((*i).length > bestLength) {
713 : bestLength = (*i).length;
714 : }
715 : }
716 : // beyond a certain length, all lanes are suitable
717 : // however, we still need to check departPos to avoid unsuitable insertion
718 : // (this is only possible in some cases)
719 : double departPos = 0;
720 34538098 : if (bestLength > BEST_LANE_LOOKAHEAD) {
721 362894 : departPos = getDepartPosBound(veh);
722 362894 : bestLength = MIN2(bestLength - departPos, BEST_LANE_LOOKAHEAD);
723 : }
724 34538098 : std::vector<MSLane*>* bestLanes = new std::vector<MSLane*>();
725 108905361 : for (std::vector<MSVehicle::LaneQ>::const_iterator i = bl.begin(); i != bl.end(); ++i) {
726 74367263 : if (((*i).length - departPos) >= bestLength) {
727 42152988 : if (isInternal()) {
728 32 : for (MSLane* lane : *myLanes) {
729 20 : if (lane->getNormalSuccessorLane() == (*i).lane) {
730 12 : bestLanes->push_back(lane);
731 : }
732 : }
733 : } else {
734 42152976 : bestLanes->push_back((*i).lane);
735 : }
736 : }
737 : }
738 : MSLane* ret = nullptr;
739 34538098 : if (veh.getParameter().departLaneProcedure == DepartLaneDefinition::BEST_FREE) {
740 31270640 : ret = getFreeLane(bestLanes, veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false));
741 : } else {
742 3267458 : ret = getProbableLane(bestLanes, veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false), getVehicleMaxSpeed(&veh));
743 : }
744 34538098 : delete bestLanes;
745 34538098 : return ret;
746 : }
747 5968764885 : case DepartLaneDefinition::DEFAULT:
748 : case DepartLaneDefinition::FIRST_ALLOWED:
749 5968764885 : return getFirstAllowed(veh.getVehicleType().getVehicleClass());
750 : default:
751 : break;
752 : }
753 0 : if (!(*myLanes)[0]->allowsVehicleClass(veh.getVehicleType().getVehicleClass())) {
754 : return nullptr;
755 : }
756 0 : return (*myLanes)[0];
757 : }
758 :
759 :
760 : MSLane*
761 5969504021 : MSEdge::getFirstAllowed(SUMOVehicleClass vClass, bool defaultFirst, int routingMode) const {
762 11416653167 : for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
763 11416648167 : if ((*i)->allowsVehicleClass(vClass, routingMode)) {
764 5969499021 : return *i;
765 : }
766 : }
767 5000 : return defaultFirst && !myLanes->empty() ? myLanes->front() : nullptr;
768 : }
769 :
770 :
771 : bool
772 7474094385 : MSEdge::validateDepartSpeed(SUMOVehicle& v) const {
773 7474094385 : const SUMOVehicleParameter& pars = v.getParameter();
774 7474094385 : const MSVehicleType& type = v.getVehicleType();
775 7474094385 : if (pars.departSpeedProcedure == DepartSpeedDefinition::GIVEN) {
776 : // departSpeed could have been rounded down in the output
777 306915719 : double vMax = getVehicleMaxSpeed(&v) + SPEED_EPS;
778 306915719 : if (pars.departSpeed > vMax) {
779 : // check departLane (getVehicleMaxSpeed checks lane 0)
780 22593 : MSLane* departLane = MSGlobals::gMesoNet ? getDepartLaneMeso(v) : getDepartLane(dynamic_cast<MSVehicle&>(v));
781 22593 : if (departLane != nullptr) {
782 22593 : vMax = departLane->getVehicleMaxSpeed(&v);
783 22593 : if (pars.wasSet(VEHPARS_SPEEDFACTOR_SET)) {
784 : // speedFactor could have been rounded down in the output
785 7 : vMax *= (1 + SPEED_EPS);
786 : }
787 : // additive term must come after multiplication!
788 22593 : vMax += SPEED_EPS;
789 22593 : if (pars.departSpeed > vMax) {
790 22579 : if (type.getSpeedFactor().getParameter(1) > 0.) {
791 45120 : v.setChosenSpeedFactor(type.computeChosenSpeedDeviation(nullptr, pars.departSpeed / MIN2(getSpeedLimit(), type.getDesiredMaxSpeed() - SPEED_EPS)));
792 22560 : if (v.getChosenSpeedFactor() > type.getSpeedFactor().getParameter(0) + 2 * type.getSpeedFactor().getParameter(1)) {
793 : // only warn for significant deviation
794 37156 : WRITE_WARNINGF(TL("Choosing new speed factor % for vehicle '%' to match departure speed % (max %)."),
795 : toString(v.getChosenSpeedFactor()), pars.id, pars.departSpeed, vMax);
796 : }
797 : } else {
798 : return false;
799 : }
800 : }
801 : }
802 : }
803 : }
804 : return true;
805 : }
806 :
807 :
808 : bool
809 7474657366 : MSEdge::insertVehicle(SUMOVehicle& v, SUMOTime time, const bool checkOnly, const bool forceCheck) const {
810 : // when vaporizing, no vehicles are inserted, but checking needs to be successful to trigger removal
811 7474638580 : if (isVaporizing() || isTazConnector()
812 14948729086 : || v.getRouteValidity(true, checkOnly) != MSBaseVehicle::ROUTE_VALID) {
813 585713 : return checkOnly;
814 : }
815 7474071473 : const SUMOVehicleParameter& pars = v.getParameter();
816 7474071473 : if (!validateDepartSpeed(v)) {
817 14 : if (MSGlobals::gCheckRoutes) {
818 21 : throw ProcessError(TLF("Departure speed for vehicle '%' is too high for the departure edge '%', time=%.",
819 21 : pars.id, getID(), time2string(time)));
820 : } else {
821 21 : WRITE_WARNINGF(TL("Departure speed for vehicle '%' is too high for the departure edge '%', time=%."),
822 : pars.id, getID(), time2string(time));
823 : }
824 : }
825 7474071466 : if (MSGlobals::gUseMesoSim) {
826 503865723 : if (!forceCheck && myLastFailedInsertionTime == time) {
827 : return false;
828 : }
829 : double pos = 0.0;
830 27995641 : switch (pars.departPosProcedure) {
831 573844 : case DepartPosDefinition::GIVEN:
832 573844 : if (pars.departPos >= 0.) {
833 : pos = pars.departPos;
834 : } else {
835 7315 : pos = pars.departPos + getLength();
836 : }
837 573844 : if (pos < 0 || pos > getLength()) {
838 6 : WRITE_WARNINGF(TL("Invalid departPos % given for vehicle '%', time=%. Inserting at lane end instead."),
839 : pos, v.getID(), time2string(time));
840 : pos = getLength();
841 : }
842 : break;
843 : case DepartPosDefinition::RANDOM:
844 : case DepartPosDefinition::RANDOM_FREE:
845 : pos = RandHelper::rand(getLength());
846 6874 : break;
847 : default:
848 : break;
849 : }
850 : bool result = false;
851 27995641 : MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this, pos);
852 : MEVehicle* veh = static_cast<MEVehicle*>(&v);
853 : int qIdx;
854 27995641 : if (pars.departPosProcedure == DepartPosDefinition::FREE) {
855 486418 : while (segment != nullptr && !result) {
856 447912 : if (checkOnly) {
857 6 : result = segment->hasSpaceFor(veh, time, qIdx, true) == time;
858 : } else {
859 447906 : result = segment->initialise(veh, time);
860 : }
861 : segment = segment->getNextSegment();
862 : }
863 : } else {
864 27957135 : if (checkOnly) {
865 26409871 : result = segment->hasSpaceFor(veh, time, qIdx, true) == time;
866 : } else {
867 1547264 : result = segment->initialise(veh, time);
868 : }
869 : }
870 27995638 : return result;
871 : }
872 6970205743 : if (checkOnly) {
873 2298595761 : switch (v.getParameter().departLaneProcedure) {
874 2105108839 : case DepartLaneDefinition::GIVEN:
875 : case DepartLaneDefinition::DEFAULT:
876 : case DepartLaneDefinition::FIRST_ALLOWED: {
877 2105108839 : MSLane* insertionLane = getDepartLane(static_cast<MSVehicle&>(v));
878 2105108839 : if (insertionLane == nullptr) {
879 0 : WRITE_WARNINGF(TL("Could not insert vehicle '%' on any lane of edge '%', time=%."),
880 : v.getID(), getID(), time2string(time));
881 0 : return false;
882 : }
883 2105108839 : const double occupancy = insertionLane->getBruttoOccupancy();
884 2105108839 : return (occupancy == 0 || occupancy * myLength + v.getVehicleType().getLengthWithGap() <= myLength ||
885 8598232 : v.getParameter().departProcedure == DepartDefinition::SPLIT);
886 : }
887 193486922 : default:
888 211078657 : for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
889 202862997 : const double occupancy = (*i)->getBruttoOccupancy();
890 202862997 : if (occupancy == 0 || occupancy * myLength + v.getVehicleType().getLengthWithGap() <= myLength ||
891 17591735 : v.getParameter().departProcedure == DepartDefinition::SPLIT) {
892 : return true;
893 : }
894 : }
895 : }
896 : return false;
897 : }
898 4671609982 : MSLane* insertionLane = getDepartLane(static_cast<MSVehicle&>(v));
899 4671609982 : if (insertionLane == nullptr) {
900 : return false;
901 : }
902 :
903 4671604982 : if (!forceCheck) {
904 4671604805 : if (myLastFailedInsertionTime == time) {
905 : if (myFailedInsertionMemory.count(insertionLane->getIndex())) {
906 : // A vehicle was already rejected for the proposed insertionLane in this timestep
907 : return false;
908 : }
909 : } else {
910 : // last rejection occurred in a previous timestep, clear cache
911 : myFailedInsertionMemory.clear();
912 : }
913 : }
914 :
915 14086534 : bool success = insertionLane->insertVehicle(static_cast<MSVehicle&>(v));
916 :
917 14086531 : if (!success) {
918 : // constraints may enforce explicit re-ordering so we need to try other vehicles after failure
919 21081084 : if (!insertionLane->hasParameter("insertionOrder" + v.getID())) {
920 10540395 : myFailedInsertionMemory.insert(insertionLane->getIndex());
921 : }
922 : }
923 : return success;
924 : }
925 :
926 :
927 : void
928 44587097 : MSEdge::changeLanes(SUMOTime t) const {
929 44587097 : if (myLaneChanger != nullptr) {
930 44587097 : myLaneChanger->laneChange(t);
931 : }
932 44587097 : }
933 :
934 :
935 : const MSEdge*
936 2381167 : MSEdge::getInternalFollowingEdge(const MSEdge* followerAfterInternal, SUMOVehicleClass vClass) const {
937 : //@todo to be optimized
938 2896458 : for (const MSLane* const l : *myLanes) {
939 3489309 : for (const MSLink* const link : l->getLinkCont()) {
940 2974018 : if (&link->getLane()->getEdge() == followerAfterInternal) {
941 2083312 : if (link->getViaLane() != nullptr) {
942 1082979 : if (link->getViaLane()->allowsVehicleClass(vClass)) {
943 1080325 : return &link->getViaLane()->getEdge();
944 : } else {
945 2654 : continue;
946 : }
947 : } else {
948 : return nullptr; // network without internal links
949 : }
950 : }
951 : }
952 : }
953 : return nullptr;
954 : }
955 :
956 :
957 : double
958 1213095 : MSEdge::getInternalFollowingLengthTo(const MSEdge* followerAfterInternal, SUMOVehicleClass vClass) const {
959 : assert(followerAfterInternal != 0);
960 : assert(!followerAfterInternal->isInternal());
961 : double dist = 0.;
962 1213095 : const MSEdge* edge = getInternalFollowingEdge(followerAfterInternal, vClass);
963 : // Take into account non-internal lengths until next non-internal edge
964 2232188 : while (edge != nullptr && edge->isInternal()) {
965 1019093 : dist += edge->getLength();
966 1019093 : edge = edge->getInternalFollowingEdge(followerAfterInternal, vClass);
967 : }
968 1213095 : return dist;
969 : }
970 :
971 :
972 : const MSEdge*
973 145028 : MSEdge::getNormalBefore() const {
974 : const MSEdge* result = this;
975 153425 : while (result->isInternal() && MSGlobals::gUsingInternalLanes) {
976 : assert(result->getPredecessors().size() == 1);
977 8397 : result = result->getPredecessors().front();
978 : }
979 145028 : return result;
980 : }
981 :
982 : const MSEdge*
983 6200628 : MSEdge::getNormalSuccessor() const {
984 : const MSEdge* result = this;
985 11746488 : while (result->isInternal()) {
986 : assert(result->getSuccessors().size() == 1);
987 5545860 : result = result->getSuccessors().front();
988 : }
989 6200628 : return result;
990 : }
991 :
992 : double
993 147001661 : MSEdge::getMeanSpeed() const {
994 : double v = 0;
995 : double totalNumVehs = 0;
996 147001661 : if (MSGlobals::gUseMesoSim) {
997 161981374 : for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
998 : const int numVehs = segment->getCarNumber();
999 137527083 : if (numVehs > 0) {
1000 23896491 : v += numVehs * segment->getMeanSpeed();
1001 23896491 : totalNumVehs += numVehs;
1002 : }
1003 : }
1004 24454291 : if (totalNumVehs == 0) {
1005 16502835 : return getLength() / myEmptyTraveltime; // may include tls-penalty
1006 : }
1007 : } else {
1008 282261554 : for (const MSLane* const lane : *myLanes) {
1009 : int numVehs = lane->getVehicleNumber();
1010 159714184 : if (numVehs == 0) {
1011 : // take speed limit but with lowest possible weight
1012 : numVehs = 1;
1013 : }
1014 159714184 : v += numVehs * lane->getMeanSpeed();
1015 159714184 : totalNumVehs += numVehs;
1016 : }
1017 122547370 : if (myBidiEdge != nullptr) {
1018 8298861 : for (const MSLane* const lane : myBidiEdge->getLanes()) {
1019 4300502 : if (lane->getVehicleNumber() > 0) {
1020 : // do not route across edges which are already occupied in reverse direction
1021 : return 0;
1022 : }
1023 : }
1024 : }
1025 122245371 : if (totalNumVehs == 0) {
1026 0 : return getSpeedLimit();
1027 : }
1028 : }
1029 130196827 : return v / totalNumVehs;
1030 : }
1031 :
1032 :
1033 : double
1034 8 : MSEdge::getMeanFriction() const {
1035 : double f = 0.;
1036 32 : for (const MSLane* const lane : *myLanes) {
1037 24 : f += lane->getFrictionCoefficient();
1038 : }
1039 8 : if (!myLanes->empty()) {
1040 8 : return f / (double)myLanes->size();
1041 : }
1042 : return 1.;
1043 : }
1044 :
1045 :
1046 : double
1047 1272 : MSEdge::getMeanSpeedBike() const {
1048 1272 : if (MSGlobals::gUseMesoSim) {
1049 : // no separate bicycle speeds in meso
1050 362 : return getMeanSpeed();
1051 : }
1052 : double v = 0;
1053 : double totalNumVehs = 0;
1054 3005 : for (const MSLane* const lane : *myLanes) {
1055 : const int numVehs = lane->getVehicleNumber();
1056 2095 : v += numVehs * lane->getMeanSpeedBike();
1057 2095 : totalNumVehs += numVehs;
1058 : }
1059 910 : if (totalNumVehs == 0) {
1060 455 : return getSpeedLimit();
1061 : }
1062 455 : return v / totalNumVehs;
1063 : }
1064 :
1065 :
1066 : double
1067 55164 : MSEdge::getCurrentTravelTime(double minSpeed) const {
1068 : assert(minSpeed > 0);
1069 55164 : if (!myAmDelayed) {
1070 36852 : return myEmptyTraveltime;
1071 : }
1072 36624 : return getLength() / MAX2(minSpeed, getMeanSpeed());
1073 : }
1074 :
1075 :
1076 : double
1077 0 : MSEdge::getRoutingSpeed() const {
1078 0 : return MSRoutingEngine::getAssumedSpeed(this, nullptr);
1079 : }
1080 :
1081 :
1082 : bool
1083 1721201 : MSEdge::dictionary(const std::string& id, MSEdge* ptr) {
1084 : const DictType::iterator it = myDict.lower_bound(id);
1085 1721201 : if (it == myDict.end() || it->first != id) {
1086 : // id not in myDict
1087 1721201 : myDict.emplace_hint(it, id, ptr);
1088 3442438 : while (ptr->getNumericalID() >= (int)myEdges.size()) {
1089 1721237 : myEdges.push_back(nullptr);
1090 : }
1091 1721201 : myEdges[ptr->getNumericalID()] = ptr;
1092 1721201 : return true;
1093 : }
1094 : return false;
1095 : }
1096 :
1097 :
1098 : MSEdge*
1099 7965148 : MSEdge::dictionary(const std::string& id) {
1100 : const DictType::iterator it = myDict.find(id);
1101 7965148 : if (it == myDict.end()) {
1102 : return nullptr;
1103 : }
1104 6242043 : return it->second;
1105 : }
1106 :
1107 :
1108 : MSEdge*
1109 2578268 : MSEdge::dictionaryHint(const std::string& id, const int startIdx) {
1110 : // this method is mainly useful when parsing connections from the net.xml which are sorted by "from" id
1111 2578268 : if (myEdges[startIdx] != nullptr && myEdges[startIdx]->getID() == id) {
1112 : return myEdges[startIdx];
1113 : }
1114 1556032 : if (startIdx + 1 < (int)myEdges.size() && myEdges[startIdx + 1] != nullptr && myEdges[startIdx + 1]->getID() == id) {
1115 : return myEdges[startIdx + 1];
1116 : }
1117 501710 : return dictionary(id);
1118 : }
1119 :
1120 :
1121 : const MSEdgeVector&
1122 842157 : MSEdge::getAllEdges() {
1123 842157 : return myEdges;
1124 : }
1125 :
1126 :
1127 : void
1128 40224 : MSEdge::clear() {
1129 1746023 : for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
1130 1705799 : delete (*i).second;
1131 : }
1132 : myDict.clear();
1133 : myEdges.clear();
1134 40224 : }
1135 :
1136 :
1137 : void
1138 309 : MSEdge::insertIDs(std::vector<std::string>& into) {
1139 16328 : for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
1140 16019 : into.push_back((*i).first);
1141 : }
1142 309 : }
1143 :
1144 :
1145 : void
1146 404500 : MSEdge::parseEdgesList(const std::string& desc, ConstMSEdgeVector& into,
1147 : const std::string& rid) {
1148 404500 : StringTokenizer st(desc);
1149 404500 : parseEdgesList(st.getVector(), into, rid);
1150 404500 : }
1151 :
1152 :
1153 : void
1154 404780 : MSEdge::parseEdgesList(const std::vector<std::string>& desc, ConstMSEdgeVector& into,
1155 : const std::string& rid) {
1156 1539191 : for (std::vector<std::string>::const_iterator i = desc.begin(); i != desc.end(); ++i) {
1157 1134462 : const MSEdge* edge = MSEdge::dictionary(*i);
1158 : // check whether the edge exists
1159 1134462 : if (edge == nullptr) {
1160 51 : throw ProcessError("The edge '" + *i + "' within the route " + rid + " is not known."
1161 153 : + "\n The route can not be build.");
1162 : }
1163 1134411 : into.push_back(edge);
1164 : }
1165 404729 : }
1166 :
1167 :
1168 : double
1169 2085651 : MSEdge::getDistanceTo(const MSEdge* other, const bool doBoundaryEstimate) const {
1170 : assert(this != other);
1171 2085651 : if (doBoundaryEstimate) {
1172 19288 : return myBoundary.distanceTo2D(other->myBoundary);
1173 : }
1174 2066363 : if (isTazConnector()) {
1175 453 : if (other->isTazConnector()) {
1176 441 : return myBoundary.distanceTo2D(other->myBoundary);
1177 : }
1178 12 : return myBoundary.distanceTo2D(other->getLanes()[0]->getShape()[0]);
1179 : }
1180 2065910 : if (other->isTazConnector()) {
1181 5264 : return other->myBoundary.distanceTo2D(getLanes()[0]->getShape()[-1]);
1182 : }
1183 2060646 : return getLanes()[0]->getShape()[-1].distanceTo2D(other->getLanes()[0]->getShape()[0]);
1184 : }
1185 :
1186 :
1187 : const Position
1188 2429 : MSEdge::getStopPosition(const SUMOVehicleParameter::Stop& stop) {
1189 2429 : return MSLane::dictionary(stop.lane)->geometryPositionAtOffset((stop.endPos + stop.startPos) / 2.);
1190 : }
1191 :
1192 :
1193 : double
1194 88574634 : MSEdge::getSpeedLimit() const {
1195 : // @note lanes might have different maximum speeds in theory
1196 88574634 : return myLanes->empty() ? 1 : getLanes()[0]->getSpeedLimit();
1197 : }
1198 :
1199 :
1200 : double
1201 1835822 : MSEdge::getLengthGeometryFactor() const {
1202 1835822 : return myLanes->empty() ? 1 : getLanes()[0]->getLengthGeometryFactor();
1203 : }
1204 :
1205 : double
1206 518707043 : MSEdge::getVehicleMaxSpeed(const SUMOTrafficObject* const veh) const {
1207 : // @note lanes might have different maximum speeds in theory
1208 518707043 : return myLanes->empty() ? 1 : getLanes()[0]->getVehicleMaxSpeed(veh);
1209 : }
1210 :
1211 :
1212 : void
1213 205 : MSEdge::setMaxSpeed(double val, double jamThreshold) {
1214 : assert(val >= 0);
1215 205 : if (myLanes != nullptr) {
1216 564 : for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
1217 359 : (*i)->setMaxSpeed(val, false, false, jamThreshold);
1218 : }
1219 : }
1220 205 : }
1221 :
1222 :
1223 : void
1224 1268519 : MSEdge::addTransportable(MSTransportable* t) const {
1225 1268519 : if (t->isPerson()) {
1226 : myPersons.insert(t);
1227 : } else {
1228 : myContainers.insert(t);
1229 : }
1230 1268519 : }
1231 :
1232 : void
1233 6316406 : MSEdge::removeTransportable(MSTransportable* t) const {
1234 6316406 : std::set<MSTransportable*, ComparatorNumericalIdLess>& tc = t->isPerson() ? myPersons : myContainers;
1235 : auto it = tc.find(t);
1236 6316406 : if (it != tc.end()) {
1237 : tc.erase(it);
1238 : }
1239 6316406 : }
1240 :
1241 : std::vector<MSTransportable*>
1242 7385110 : MSEdge::getSortedPersons(SUMOTime timestep, bool includeRiding) const {
1243 7385110 : std::vector<MSTransportable*> result(myPersons.begin(), myPersons.end());
1244 7385110 : if (includeRiding) {
1245 2354953 : for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
1246 1662532 : const MSLane::VehCont& vehs = (*i)->getVehiclesSecure();
1247 2886912 : for (MSLane::VehCont::const_iterator j = vehs.begin(); j != vehs.end(); ++j) {
1248 1224380 : const std::vector<MSTransportable*>& persons = (*j)->getPersons();
1249 1224380 : result.insert(result.end(), persons.begin(), persons.end());
1250 : }
1251 1662532 : (*i)->releaseVehicles();
1252 : }
1253 : }
1254 7385110 : sort(result.begin(), result.end(), transportable_by_position_sorter(timestep));
1255 7385110 : return result;
1256 0 : }
1257 :
1258 :
1259 : std::vector<MSTransportable*>
1260 60708734 : MSEdge::getSortedContainers(SUMOTime timestep, bool /* includeRiding */) const {
1261 60708734 : std::vector<MSTransportable*> result(myContainers.begin(), myContainers.end());
1262 60708734 : sort(result.begin(), result.end(), transportable_by_position_sorter(timestep));
1263 60708734 : return result;
1264 0 : }
1265 :
1266 :
1267 : int
1268 5254801 : MSEdge::transportable_by_position_sorter::operator()(const MSTransportable* const c1, const MSTransportable* const c2) const {
1269 5254801 : const double pos1 = c1->getCurrentStage()->getEdgePos(myTime);
1270 5254801 : const double pos2 = c2->getCurrentStage()->getEdgePos(myTime);
1271 5254801 : if (pos1 != pos2) {
1272 5097013 : return pos1 < pos2;
1273 : }
1274 157788 : return c1->getID() < c2->getID();
1275 : }
1276 :
1277 :
1278 : void
1279 119345 : MSEdge::addSuccessor(MSEdge* edge, const MSEdge* via) {
1280 119345 : mySuccessors.push_back(edge);
1281 119345 : myViaSuccessors.push_back(std::make_pair(edge, via));
1282 119345 : if (isTazConnector() && edge->getFromJunction() != nullptr) {
1283 59669 : myBoundary.add(edge->getFromJunction()->getPosition());
1284 : }
1285 :
1286 119345 : edge->myPredecessors.push_back(this);
1287 119345 : if (edge->isTazConnector() && getToJunction() != nullptr) {
1288 59676 : edge->myBoundary.add(getToJunction()->getPosition());
1289 : }
1290 119345 : }
1291 :
1292 :
1293 : const MSEdgeVector&
1294 8736971 : MSEdge::getSuccessors(SUMOVehicleClass vClass) const {
1295 8736971 : if (vClass == SVC_IGNORING || !MSNet::getInstance()->hasPermissions() || myFunction == SumoXMLEdgeFunc::CONNECTOR) {
1296 8720683 : return mySuccessors;
1297 : }
1298 : #ifdef HAVE_FOX
1299 16288 : ScopedLocker<> lock(mySuccessorMutex, MSGlobals::gNumThreads > 1);
1300 : #endif
1301 : std::map<SUMOVehicleClass, MSEdgeVector>::iterator i = myClassesSuccessorMap.find(vClass);
1302 16288 : if (i == myClassesSuccessorMap.end()) {
1303 : // instantiate vector
1304 1644 : myClassesSuccessorMap[vClass];
1305 : i = myClassesSuccessorMap.find(vClass);
1306 : // this vClass is requested for the first time. rebuild all successors
1307 7883 : for (MSEdgeVector::const_iterator it = mySuccessors.begin(); it != mySuccessors.end(); ++it) {
1308 6239 : if ((*it)->isTazConnector()) {
1309 239 : i->second.push_back(*it);
1310 : } else {
1311 6000 : const std::vector<MSLane*>* allowed = allowedLanes(**it, vClass);
1312 6000 : if (allowed != nullptr && allowed->size() > 0) {
1313 4970 : i->second.push_back(*it);
1314 : }
1315 : }
1316 : }
1317 : }
1318 : // can use cached value
1319 16288 : return i->second;
1320 : }
1321 :
1322 :
1323 : const MSConstEdgePairVector&
1324 164408076 : MSEdge::getViaSuccessors(SUMOVehicleClass vClass, bool ignoreTransientPermissions) const {
1325 164408076 : if (vClass == SVC_IGNORING || !MSNet::getInstance()->hasPermissions() || myFunction == SumoXMLEdgeFunc::CONNECTOR) {
1326 158227574 : return myViaSuccessors;
1327 : }
1328 : #ifdef HAVE_FOX
1329 6180502 : ScopedLocker<> lock(mySuccessorMutex, MSGlobals::gNumThreads > 1);
1330 : #endif
1331 6180502 : auto& viaMap = ignoreTransientPermissions && myHaveTransientPermissions ? myOrigClassesViaSuccessorMap : myClassesViaSuccessorMap;
1332 : auto i = viaMap.find(vClass);
1333 6180502 : if (i != viaMap.end()) {
1334 : // can use cached value
1335 6131024 : return i->second;
1336 : }
1337 : // instantiate vector
1338 49478 : MSConstEdgePairVector& result = viaMap[vClass];
1339 : // this vClass is requested for the first time. rebuild all successors
1340 200140 : for (const auto& viaPair : myViaSuccessors) {
1341 150662 : if (viaPair.first->isTazConnector()) {
1342 6217 : result.push_back(viaPair);
1343 : } else {
1344 144445 : const std::vector<MSLane*>* allowed = allowedLanes(*viaPair.first, vClass, ignoreTransientPermissions);
1345 144445 : if (allowed != nullptr && allowed->size() > 0) {
1346 115077 : result.push_back(viaPair);
1347 : }
1348 : }
1349 : }
1350 : return result;
1351 : }
1352 :
1353 :
1354 : void
1355 1663130 : MSEdge::setJunctions(MSJunction* from, MSJunction* to) {
1356 1663130 : myFromJunction = from;
1357 1663130 : myToJunction = to;
1358 1663130 : if (!isTazConnector()) {
1359 1663130 : myBoundary.add(from->getPosition());
1360 1663130 : myBoundary.add(to->getPosition());
1361 : }
1362 1663130 : }
1363 :
1364 :
1365 : bool
1366 2773297 : MSEdge::canChangeToOpposite() const {
1367 2773297 : return (!myLanes->empty() && myLanes->back()->getOpposite() != nullptr &&
1368 : // do not change on curved internal lanes
1369 : (!isInternal()
1370 5437 : || (MSGlobals::gUsingInternalLanes
1371 5433 : && myLanes->back()->getIncomingLanes()[0].viaLink->getDirection() == LinkDirection::STRAIGHT)));
1372 : }
1373 :
1374 :
1375 : const MSEdge*
1376 21855902 : MSEdge::getOppositeEdge() const {
1377 21855902 : if (!myLanes->empty() && myLanes->back()->getOpposite() != nullptr) {
1378 2984350 : return &(myLanes->back()->getOpposite()->getEdge());
1379 : } else {
1380 18871552 : return nullptr;
1381 : }
1382 : }
1383 :
1384 :
1385 : bool
1386 178 : MSEdge::hasMinorLink() const {
1387 370 : for (const MSLane* const l : *myLanes) {
1388 290 : for (const MSLink* const link : l->getLinkCont()) {
1389 98 : if (!link->havePriority()) {
1390 : return true;
1391 : }
1392 : }
1393 : }
1394 : return false;
1395 : }
1396 :
1397 : bool
1398 908098 : MSEdge::hasChangeProhibitions(SUMOVehicleClass svc, int index) const {
1399 908098 : if (myLanes->size() == 1) {
1400 : return false;
1401 : }
1402 2222504 : for (const MSLane* const l : *myLanes) {
1403 1486732 : if (l->getIndex() <= index && !l->allowsChangingRight(svc) && l->getIndex() > 0) {
1404 : return true;
1405 1486688 : } else if (l->getIndex() >= index && !l->allowsChangingLeft(svc) && l->getIndex() < (int)(myLanes->size() - 1)) {
1406 : return true;
1407 : }
1408 : }
1409 : return false;
1410 : }
1411 :
1412 : void
1413 878965 : MSEdge::checkAndRegisterBiDirEdge(const std::string& bidiID) {
1414 878965 : if (bidiID != "") {
1415 28880 : myBidiEdge = dictionary(bidiID);
1416 28880 : if (myBidiEdge == nullptr) {
1417 0 : WRITE_ERRORF(TL("Bidi-edge '%' does not exist"), bidiID);
1418 : }
1419 28880 : setBidiLanes();
1420 501861 : return;
1421 : }
1422 850085 : if (getFunction() != SumoXMLEdgeFunc::NORMAL) {
1423 : return;
1424 : }
1425 : // legacy networks (no bidi attribute)
1426 377104 : ConstMSEdgeVector candidates = myToJunction->getOutgoing();
1427 2980825 : for (ConstMSEdgeVector::const_iterator it = candidates.begin(); it != candidates.end(); it++) {
1428 2603721 : if ((*it)->getToJunction() == myFromJunction) { //reverse edge
1429 303500 : if (myBidiEdge != nullptr && isSuperposable(*it)) {
1430 0 : WRITE_WARNINGF(TL("Ambiguous superposable edges between junction '%' and '%'."), myToJunction->getID(), myFromJunction->getID());
1431 0 : break;
1432 : }
1433 303500 : if (isSuperposable(*it)) {
1434 26 : myBidiEdge = *it;
1435 26 : setBidiLanes();
1436 : }
1437 : }
1438 : }
1439 377104 : }
1440 :
1441 :
1442 : void
1443 28906 : MSEdge::setBidiLanes() {
1444 : assert(myBidiEdge != nullptr);
1445 28906 : if (getNumLanes() == 1 && myBidiEdge->getNumLanes() == 1) {
1446 : // the other way round is set when this method runs for the bidiEdge
1447 28368 : getLanes()[0]->setBidiLane(myBidiEdge->getLanes()[0]);
1448 : } else {
1449 : // find lanes with matching reversed shapes
1450 : int numBidiLanes = 0;
1451 1680 : for (MSLane* l1 : *myLanes) {
1452 3630 : for (MSLane* l2 : *myBidiEdge->myLanes) {
1453 2488 : if (l1->getShape().reverse().almostSame(l2->getShape(), POSITION_EPS * 2)) {
1454 592 : l1->setBidiLane(l2);
1455 592 : numBidiLanes++;
1456 : }
1457 : }
1458 : }
1459 : // warn only once for each pair
1460 538 : if (numBidiLanes == 0 && getNumericalID() < myBidiEdge->getNumericalID()) {
1461 15 : WRITE_WARNINGF(TL("Edge '%' and bidi edge '%' have no matching bidi lanes"), getID(), myBidiEdge->getID());
1462 : }
1463 : }
1464 28906 : }
1465 :
1466 :
1467 : bool
1468 303500 : MSEdge::isSuperposable(const MSEdge* other) {
1469 303500 : if (other == nullptr || other->getLanes().size() != myLanes->size()) {
1470 : return false;
1471 : }
1472 : std::vector<MSLane*>::const_iterator it1 = myLanes->begin();
1473 : std::vector<MSLane*>::const_reverse_iterator it2 = other->getLanes().rbegin();
1474 : do {
1475 298926 : if ((*it1)->getShape().reverse() != (*it2)->getShape()) {
1476 : return false;
1477 : }
1478 : it1++;
1479 : it2++;
1480 26 : } while (it1 != myLanes->end());
1481 :
1482 : return true;
1483 : }
1484 :
1485 :
1486 : void
1487 69591 : MSEdge::addWaiting(SUMOVehicle* vehicle) const {
1488 : #ifdef HAVE_FOX
1489 69591 : ScopedLocker<> lock(myWaitingMutex, MSGlobals::gNumSimThreads > 1);
1490 : #endif
1491 69591 : myWaiting.push_back(vehicle);
1492 69591 : }
1493 :
1494 :
1495 : void
1496 61502 : MSEdge::removeWaiting(const SUMOVehicle* vehicle) const {
1497 : #ifdef HAVE_FOX
1498 61502 : ScopedLocker<> lock(myWaitingMutex, MSGlobals::gNumSimThreads > 1);
1499 : #endif
1500 61502 : std::vector<SUMOVehicle*>::iterator it = std::find(myWaiting.begin(), myWaiting.end(), vehicle);
1501 61502 : if (it != myWaiting.end()) {
1502 61185 : myWaiting.erase(it);
1503 : }
1504 61502 : }
1505 :
1506 :
1507 : SUMOVehicle*
1508 76749 : MSEdge::getWaitingVehicle(MSTransportable* transportable, const double position) const {
1509 : #ifdef HAVE_FOX
1510 76749 : ScopedLocker<> lock(myWaitingMutex, MSGlobals::gNumSimThreads > 1);
1511 : #endif
1512 77037 : for (SUMOVehicle* const vehicle : myWaiting) {
1513 5138 : if (transportable->isWaitingFor(vehicle)) {
1514 7302 : if (vehicle->isStoppedInRange(position, MSGlobals::gStopTolerance) ||
1515 2251 : (!vehicle->hasDeparted() &&
1516 2054 : (vehicle->getParameter().departProcedure == DepartDefinition::TRIGGERED ||
1517 83 : vehicle->getParameter().departProcedure == DepartDefinition::CONTAINER_TRIGGERED))) {
1518 : return vehicle;
1519 : }
1520 201 : if (!vehicle->isLineStop(position) && vehicle->allowsBoarding(transportable)) {
1521 228 : WRITE_WARNING((transportable->isPerson() ? "Person '" : "Container '")
1522 : + transportable->getID() + "' at edge '" + getID() + "' position " + toString(position) + " cannot use waiting vehicle '"
1523 : + vehicle->getID() + "' at position " + toString(vehicle->getPositionOnLane()) + " because it is too far away.");
1524 : }
1525 : }
1526 : }
1527 : return nullptr;
1528 : }
1529 :
1530 : std::vector<const SUMOVehicle*>
1531 144389 : MSEdge::getVehicles() const {
1532 : std::vector<const SUMOVehicle*> result;
1533 144389 : if (MSGlobals::gUseMesoSim) {
1534 164 : for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1535 88 : std::vector<const MEVehicle*> segmentVehs = segment->getVehicles();
1536 88 : result.insert(result.end(), segmentVehs.begin(), segmentVehs.end());
1537 88 : }
1538 : } else {
1539 386933 : for (MSLane* lane : getLanes()) {
1540 829421 : for (auto veh : lane->getVehiclesSecure()) {
1541 586839 : result.push_back(veh);
1542 : }
1543 242582 : lane->releaseVehicles();
1544 : }
1545 : }
1546 144389 : return result;
1547 0 : }
1548 :
1549 : int
1550 617482 : MSEdge::getNumDrivingLanes() const {
1551 : int result = 0;
1552 617482 : SVCPermissions filter = SVCAll;
1553 617482 : if ((myCombinedPermissions & ~(SVC_PEDESTRIAN | SVC_WHEELCHAIR)) != 0) {
1554 : filter = ~(SVC_PEDESTRIAN | SVC_WHEELCHAIR);
1555 2049 : } else if ((myCombinedPermissions & (SVC_PEDESTRIAN | SVC_WHEELCHAIR)) != 0) {
1556 : // filter out green verge
1557 : filter = (SVC_PEDESTRIAN | SVC_WHEELCHAIR);
1558 : }
1559 1390238 : for (const MSLane* const l : *myLanes) {
1560 772756 : if ((l->getPermissions() & filter) != 0) {
1561 684828 : result++;
1562 : }
1563 : }
1564 617482 : return result;
1565 : }
1566 :
1567 : int
1568 661 : MSEdge::getVehicleNumber() const {
1569 661 : return (int)getVehicles().size();
1570 : }
1571 :
1572 :
1573 : bool
1574 0 : MSEdge::isEmpty() const {
1575 : /// more efficient than retrieving vehicle number
1576 0 : if (MSGlobals::gUseMesoSim) {
1577 0 : for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1578 0 : if (segment->getCarNumber() > 0) {
1579 : return false;
1580 : }
1581 : }
1582 : } else {
1583 0 : for (MSLane* lane : getLanes()) {
1584 0 : if (lane->getVehicleNumber() > 0) {
1585 : return false;
1586 : }
1587 : }
1588 : }
1589 : return true;
1590 : }
1591 :
1592 :
1593 : double
1594 14 : MSEdge::getWaitingSeconds() const {
1595 : double wtime = 0;
1596 14 : if (MSGlobals::gUseMesoSim) {
1597 4 : for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1598 3 : wtime += segment->getWaitingSeconds();
1599 : }
1600 : } else {
1601 42 : for (MSLane* lane : getLanes()) {
1602 29 : wtime += lane->getWaitingSeconds();
1603 : }
1604 : }
1605 14 : return wtime;
1606 : }
1607 :
1608 :
1609 : double
1610 22 : MSEdge::getOccupancy() const {
1611 22 : if (myLanes->size() == 0) {
1612 : return 0;
1613 : }
1614 22 : if (MSGlobals::gUseMesoSim) {
1615 : /// @note MESegment only tracks brutto occupancy so we compute this from sratch
1616 : double sum = 0;
1617 4 : for (const SUMOVehicle* veh : getVehicles()) {
1618 2 : sum += dynamic_cast<const MEVehicle*>(veh)->getVehicleType().getLength();
1619 2 : }
1620 2 : return sum / (myLength * (double)myLanes->size());
1621 : } else {
1622 : double sum = 0;
1623 56 : for (auto lane : getLanes()) {
1624 36 : sum += lane->getNettoOccupancy();
1625 : }
1626 20 : return sum / (double)myLanes->size();
1627 : }
1628 : }
1629 :
1630 :
1631 : double
1632 0 : MSEdge::getFlow() const {
1633 0 : if (myLanes->size() == 0) {
1634 : return 0;
1635 : }
1636 : double flow = 0;
1637 0 : for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1638 0 : flow += (double) segment->getCarNumber() * segment->getMeanSpeed();
1639 : }
1640 0 : return 3600 * flow / (*myLanes)[0]->getLength();
1641 : }
1642 :
1643 :
1644 : double
1645 0 : MSEdge::getBruttoOccupancy() const {
1646 0 : if (myLanes->size() == 0) {
1647 : return 0;
1648 : }
1649 : double occ = 0;
1650 0 : for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
1651 0 : occ += segment->getBruttoOccupancy();
1652 : }
1653 0 : return occ / (*myLanes)[0]->getLength() / (double)(myLanes->size());
1654 : }
1655 :
1656 : double
1657 4240 : MSEdge::getTravelTimeAggregated(const MSEdge* const edge, const SUMOVehicle* const veh, double /*time*/) {
1658 4240 : return edge->getLength() / MIN2(MSRoutingEngine::getAssumedSpeed(edge, veh), veh->getMaxSpeed());
1659 : }
1660 :
1661 :
1662 : void
1663 2098 : MSEdge::inferEdgeType() {
1664 : // @note must be called after closeBuilding() to ensure successors and
1665 : // predecessors are set
1666 2098 : if (isInternal() && myEdgeType == "") {
1667 1274 : const std::string typeBefore = getNormalBefore()->getEdgeType();
1668 1274 : if (typeBefore != "") {
1669 622 : const std::string typeAfter = getNormalSuccessor()->getEdgeType();
1670 622 : if (typeBefore == typeAfter) {
1671 : myEdgeType = typeBefore;
1672 244 : } else if (typeAfter != "") {
1673 60 : MSNet* net = MSNet::getInstance();
1674 60 : auto resBefore = net->getRestrictions(typeBefore);
1675 60 : auto resAfter = net->getRestrictions(typeAfter);
1676 60 : if (resBefore != nullptr && resAfter != nullptr) {
1677 : // create new restrictions for this type-combination
1678 80 : myEdgeType = typeBefore + "|" + typeAfter;
1679 40 : if (net->getRestrictions(myEdgeType) == nullptr) {
1680 40 : for (const auto& item : *resBefore) {
1681 20 : const SUMOVehicleClass svc = item.first;
1682 20 : const double speed = item.second;
1683 : const auto it = (*resAfter).find(svc);
1684 20 : if (it != (*resAfter).end()) {
1685 20 : const double speed2 = it->second;
1686 20 : const double newSpeed = (MSNet::getInstance()->hasJunctionHigherSpeeds()
1687 20 : ? MAX2(speed, speed2) : (speed + speed2) / 2);
1688 20 : net->addRestriction(myEdgeType, svc, newSpeed);
1689 : }
1690 : }
1691 : }
1692 : }
1693 : }
1694 : }
1695 : }
1696 2098 : }
1697 :
1698 :
1699 : double
1700 2134 : MSEdge::getDistanceAt(double pos) const {
1701 : // negative values of myDistances indicate descending kilometrage
1702 2134 : return fabs(myDistance + pos);
1703 : }
1704 :
1705 :
1706 : bool
1707 1019 : MSEdge::hasTransientPermissions() const {
1708 1019 : return myHaveTransientPermissions;
1709 : }
1710 :
1711 :
1712 : std::pair<double, SUMOTime>
1713 582491097 : MSEdge::getLastBlocked(int index) const {
1714 582491097 : if (myLaneChanger != nullptr) {
1715 582491097 : return myLaneChanger->getLastBlocked(index);
1716 : }
1717 0 : return std::make_pair(-1, -1);
1718 : }
1719 :
1720 :
1721 : double
1722 1631 : MSEdge::getPreference(const SUMOVTypeParameter& pars) const {
1723 3262 : return MSNet::getInstance()->getPreference(getRoutingType(), pars);
1724 : }
1725 :
1726 : void
1727 8193 : MSEdge::clearState() {
1728 : myPersons.clear();
1729 : myContainers.clear();
1730 : myWaiting.clear();
1731 8193 : }
1732 :
1733 : /****************************************************************************/
|