Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netedit/GNEPathManager.cpp
169665 views
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 GNEPathManager.cpp
15
/// @author Pablo Alvarez Lopez
16
/// @date Feb 2011
17
///
18
// Manager for paths in netedit (routes, trips, flows...)
19
/****************************************************************************/
20
21
#include <netbuild/NBNetBuilder.h>
22
#include <netedit/GNENet.h>
23
#include <netedit/GNESegment.h>
24
#include <netedit/GNETagProperties.h>
25
#include <netedit/GNEViewNet.h>
26
#include <netedit/elements/network/GNEConnection.h>
27
#include <utils/router/DijkstraRouter.h>
28
29
#include "GNEPathManager.h"
30
31
// ===========================================================================
32
// member method definitions
33
// ===========================================================================
34
35
// ---------------------------------------------------------------------------
36
// GNEPathManager::PathCalculator - methods
37
// ---------------------------------------------------------------------------
38
39
GNEPathManager::PathCalculator::PathCalculator(const GNENet* net) :
40
myNet(net),
41
myPathCalculatorUpdated(false),
42
myDijkstraRouter(nullptr) {
43
// create myDijkstraRouter
44
myDijkstraRouter = new DijkstraRouter<NBRouterEdge, NBVehicle>(
45
myNet->getNetBuilder()->getEdgeCont().getAllRouterEdges(),
46
true, &NBRouterEdge::getTravelTimeStatic, nullptr, true);
47
}
48
49
50
GNEPathManager::PathCalculator::~PathCalculator() {
51
delete myDijkstraRouter;
52
}
53
54
55
void
56
GNEPathManager::PathCalculator::updatePathCalculator() {
57
// simply delete and create myDijkstraRouter again
58
if (myDijkstraRouter) {
59
delete myDijkstraRouter;
60
}
61
myDijkstraRouter = new DijkstraRouter<NBRouterEdge, NBVehicle>(
62
myNet->getNetBuilder()->getEdgeCont().getAllRouterEdges(),
63
true, &NBRouterEdge::getTravelTimeStatic, nullptr, true);
64
// update flag
65
myPathCalculatorUpdated = true;
66
}
67
68
69
std::vector<GNEEdge*>
70
GNEPathManager::PathCalculator::calculateDijkstraPath(const SUMOVehicleClass vClass, const std::vector<GNEEdge*>& edges) const {
71
// declare a solution vector
72
std::vector<GNEEdge*> solution;
73
// check if path calculator is updated
74
if (!myPathCalculatorUpdated) {
75
// use partialEdges as solution
76
solution = edges;
77
return solution;
78
}
79
// calculate route depending of number of partial edges
80
if (edges.size() == 0) {
81
// partial edges empty, then return a empty vector
82
return solution;
83
} else if (edges.size() == 1) {
84
// if there is only one partialEdges, path has only one edge
85
solution.push_back(edges.front());
86
return solution;
87
} else if ((edges.size() == 2) && (edges.front() == edges.back())) {
88
// typical case for stops. Used to avoid unnecesary calls to compute
89
solution.push_back(edges.front());
90
return solution;
91
} else {
92
// declare temporal vehicle
93
NBVehicle tmpVehicle("temporalNBVehicle", vClass);
94
// obtain pointer to GNENet
95
GNENet* net = edges.front()->getNet();
96
// iterate over every selected myEdges
97
for (int i = 1; i < (int)edges.size(); i++) {
98
// ignore consecutive edges
99
if (edges.at(i - 1)->getNBEdge() != edges.at(i)->getNBEdge()) {
100
// declare a temporal route in which save route between two last myEdges
101
std::vector<const NBRouterEdge*> partialRoute;
102
myDijkstraRouter->compute(edges.at(i - 1)->getNBEdge(), edges.at(i)->getNBEdge(), &tmpVehicle, 10, partialRoute);
103
// if partial route is empty, return empty route
104
if (partialRoute.empty()) {
105
return {};
106
} else {
107
// save partial route in solution
108
for (const auto& edgeID : partialRoute) {
109
solution.push_back(net->getAttributeCarriers()->retrieveEdge(edgeID->getID()));
110
}
111
}
112
}
113
}
114
}
115
// filter solution
116
auto solutionIt = solution.begin();
117
// iterate over solution
118
while (solutionIt != solution.end()) {
119
if ((solutionIt + 1) != solution.end()) {
120
// if next edge is the same of current edge, remove it
121
if (*solutionIt == *(solutionIt + 1)) {
122
solutionIt = solution.erase(solutionIt);
123
} else {
124
solutionIt++;
125
}
126
} else {
127
solutionIt++;
128
}
129
}
130
return solution;
131
}
132
133
134
std::vector<GNEEdge*>
135
GNEPathManager::PathCalculator::calculateDijkstraPath(const SUMOVehicleClass vClass, GNEEdge* fromEdge, GNEEdge* toEdge) const {
136
return calculateDijkstraPath(vClass, {fromEdge, toEdge});
137
}
138
139
140
std::vector<GNEEdge*>
141
GNEPathManager::PathCalculator::calculateDijkstraPath(const SUMOVehicleClass vClass, GNEEdge* fromEdge, GNEJunction* toJunction) const {
142
std::vector<GNEEdge*> edges;
143
// get from and to edges
144
const auto toEdges = toJunction->getGNEIncomingEdges();
145
// try to find a path
146
for (const auto& toEdge : toEdges) {
147
edges = calculateDijkstraPath(vClass, fromEdge, toEdge);
148
// if a path was found, clean it
149
if (edges.size() > 0) {
150
return optimizeJunctionPath(edges);
151
}
152
}
153
return {};
154
}
155
156
157
std::vector<GNEEdge*>
158
GNEPathManager::PathCalculator::calculateDijkstraPath(const SUMOVehicleClass vClass, GNEJunction* fromJunction, GNEEdge* toEdge) const {
159
std::vector<GNEEdge*> edges;
160
// get from and to edges
161
const auto fromEdges = fromJunction->getGNEOutgoingEdges();
162
// try to find a path
163
for (const auto& fromEdge : fromEdges) {
164
edges = calculateDijkstraPath(vClass, fromEdge, toEdge);
165
// if a path was found, clean it
166
if (edges.size() > 0) {
167
return optimizeJunctionPath(edges);
168
}
169
}
170
return {};
171
}
172
173
174
std::vector<GNEEdge*>
175
GNEPathManager::PathCalculator::calculateDijkstraPath(const SUMOVehicleClass vClass, GNEJunction* fromJunction, GNEJunction* toJunction) const {
176
std::vector<GNEEdge*> edges;
177
// get from and to edges
178
const auto fromEdges = fromJunction->getGNEOutgoingEdges();
179
const auto toEdges = toJunction->getGNEIncomingEdges();
180
// try to find a path
181
for (const auto& fromEdge : fromEdges) {
182
for (const auto& toEdge : toEdges) {
183
edges = calculateDijkstraPath(vClass, fromEdge, toEdge);
184
// if a path was found, clean it
185
if (edges.size() > 0) {
186
return optimizeJunctionPath(edges);
187
}
188
}
189
}
190
return {};
191
}
192
193
194
void
195
GNEPathManager::PathCalculator::calculateReachability(const SUMOVehicleClass vClass, GNEEdge* originEdge) {
196
// first reset reachability of all lanes
197
for (const auto& edge : originEdge->getNet()->getAttributeCarriers()->getEdges()) {
198
for (const auto& lane : edge.second->getChildLanes()) {
199
lane->resetReachability();
200
}
201
}
202
// get max speed
203
const double defaultMaxSpeed = SUMOVTypeParameter::VClassDefaultValues(vClass).maxSpeed;
204
// declare map for reachable edges
205
std::map<GNEEdge*, double> reachableEdges;
206
// init first edge
207
reachableEdges[originEdge] = 0;
208
// declare a vector for checked edges
209
std::vector<GNEEdge*> check;
210
// add first edge
211
check.push_back(originEdge);
212
// continue while there is edges to check
213
while (check.size() > 0) {
214
GNEEdge* edge = check.front();
215
check.erase(check.begin());
216
double traveltime = reachableEdges[edge];
217
for (const auto& lane : edge->getChildLanes()) {
218
if ((edge->getNBEdge()->getLaneStruct(lane->getIndex()).permissions & vClass) == vClass) {
219
lane->setReachability(traveltime);
220
}
221
}
222
// update traveltime
223
traveltime += edge->getNBEdge()->getLength() / MIN2(edge->getNBEdge()->getSpeed(), defaultMaxSpeed);
224
std::vector<GNEEdge*> sucessors;
225
// get successor edges
226
for (const auto& sucessorEdge : edge->getToJunction()->getGNEOutgoingEdges()) {
227
// check if edge is connected with successor edge
228
if (consecutiveEdgesConnected(vClass, edge, sucessorEdge)) {
229
sucessors.push_back(sucessorEdge);
230
}
231
}
232
// add successors to check vector
233
for (const auto& nextEdge : sucessors) {
234
// revisit edge via faster path
235
if ((reachableEdges.count(nextEdge) == 0) || (reachableEdges[nextEdge] > traveltime)) {
236
reachableEdges[nextEdge] = traveltime;
237
check.push_back(nextEdge);
238
}
239
}
240
}
241
}
242
243
244
bool
245
GNEPathManager::PathCalculator::consecutiveEdgesConnected(const SUMOVehicleClass vClass, const GNEEdge* from, const GNEEdge* to) const {
246
// check conditions
247
if ((from == nullptr) || (to == nullptr)) {
248
// myEdges cannot be null
249
return false;
250
} else if (from == to) {
251
// the same edge cannot be consecutive of itself
252
return false;
253
} else if (vClass == SVC_PEDESTRIAN) {
254
// for pedestrians consecutive myEdges are always connected
255
return true;
256
} else {
257
// iterate over connections of from edge
258
for (const auto& fromLane : from->getChildLanes()) {
259
for (const auto& fromConnection : from->getGNEConnections()) {
260
// within from loop, iterate ove to lanes
261
for (const auto& toLane : to->getChildLanes()) {
262
if (fromConnection->getLaneTo() == toLane) {
263
// get lane structs for both lanes
264
const NBEdge::Lane NBFromLane = from->getNBEdge()->getLaneStruct(fromLane->getIndex());
265
const NBEdge::Lane NBToLane = to->getNBEdge()->getLaneStruct(toLane->getIndex());
266
// check vClass
267
if (((NBFromLane.permissions & vClass) == vClass) &&
268
((NBToLane.permissions & vClass) == vClass)) {
269
return true;
270
}
271
}
272
}
273
}
274
}
275
return false;
276
}
277
}
278
279
280
bool
281
GNEPathManager::PathCalculator::busStopConnected(const GNEAdditional* busStop, const GNEEdge* edge) const {
282
if (busStop->getTagProperty()->getTag() != SUMO_TAG_BUS_STOP) {
283
return false;
284
}
285
// check if busstop is placed over a pedestrian lane
286
if ((busStop->getParentLanes().front()->getParentEdge() == edge) &&
287
(edge->getNBEdge()->getLaneStruct(busStop->getParentLanes().front()->getIndex()).permissions & SVC_PEDESTRIAN) != 0) {
288
// busStop is placed over an lane that supports pedestrians, then return true
289
return true;
290
}
291
// obtain a list with all edge lanes that supports pedestrians
292
std::vector<GNELane*> pedestrianLanes;
293
for (int laneIndex = 0; laneIndex < (int)edge->getChildLanes().size(); laneIndex++) {
294
if ((edge->getNBEdge()->getLaneStruct(laneIndex).permissions & SVC_PEDESTRIAN) != 0) {
295
pedestrianLanes.push_back(edge->getChildLanes().at(laneIndex));
296
}
297
}
298
// check if exist an access between busStop and pedestrian lanes
299
for (const auto& access : busStop->getChildAdditionals()) {
300
// check that child is an access
301
if (access->getTagProperty()->getTag() == SUMO_TAG_ACCESS) {
302
for (const auto& lane : pedestrianLanes) {
303
if (access->getParentLanes().front() == lane) {
304
// found, then return true
305
return true;
306
}
307
}
308
}
309
}
310
// There isn't a valid access, then return false
311
return false;
312
}
313
314
315
bool
316
GNEPathManager::PathCalculator::isPathCalculatorUpdated() const {
317
return myPathCalculatorUpdated;
318
}
319
320
321
void
322
GNEPathManager::PathCalculator::invalidatePathCalculator() {
323
myPathCalculatorUpdated = false;
324
}
325
326
327
std::vector<GNEEdge*>
328
GNEPathManager::PathCalculator::optimizeJunctionPath(const std::vector<GNEEdge*>& edges) const {
329
bool stop = false;
330
std::vector<GNEEdge*> solutionA, solutionB;
331
// get from and to junctions
332
const auto fromJunction = edges.front()->getFromJunction();
333
const auto toJunction = edges.back()->getToJunction();
334
// first optimize from Junction
335
for (auto it = edges.rbegin(); (it != edges.rend()) && !stop; it++) {
336
solutionA.insert(solutionA.begin(), *it);
337
if ((*it)->getFromJunction() == fromJunction) {
338
stop = true;
339
}
340
}
341
// optimize to edge
342
stop = false;
343
for (auto it = solutionA.begin(); (it != solutionA.end()) && !stop; it++) {
344
solutionB.push_back(*it);
345
if ((*it)->getToJunction() == toJunction) {
346
stop = true;
347
}
348
}
349
return solutionB;
350
}
351
352
// ---------------------------------------------------------------------------
353
// GNEPathManager::PathDraw - methods
354
// ---------------------------------------------------------------------------
355
356
GNEPathManager::PathDraw::PathDraw() {}
357
358
359
GNEPathManager::PathDraw::~PathDraw() {}
360
361
362
void
363
GNEPathManager::PathDraw::clearPathDraw() {
364
// just clear myDrawedElements
365
myLaneDrawedElements.clear();
366
myLane2laneDrawedElements.clear();
367
}
368
369
370
bool
371
GNEPathManager::PathDraw::checkDrawPathGeometry(const GUIVisualizationSettings& s, const GNELane* lane,
372
const SumoXMLTag tag, const bool isPlan) {
373
// check conditions
374
if (s.drawForViewObjectsHandler) {
375
return true;
376
} else if (myLaneDrawedElements.count(lane) > 0) {
377
// check tag
378
if (!isPlan && myLaneDrawedElements.at(lane).count(tag) > 0) {
379
// element type was already inserted, then don't draw geometry
380
return false;
381
} else {
382
// insert tag for the given lane
383
myLaneDrawedElements.at(lane).insert(tag);
384
// draw geometry
385
return true;
386
}
387
} else {
388
// insert lane and tag
389
myLaneDrawedElements[lane].insert(tag);
390
// draw geometry
391
return true;
392
}
393
}
394
395
396
bool
397
GNEPathManager::PathDraw::checkDrawPathGeometry(const GUIVisualizationSettings& s, const GNESegment* segment,
398
const SumoXMLTag tag, const bool isPlan) {
399
// check conditions
400
if (s.drawForViewObjectsHandler) {
401
return true;
402
} else {
403
// declare lane2lane
404
const std::pair<const GNELane*, const GNELane*> lane2lane(segment->getPreviousLane(), segment->getNextLane());
405
// check lane2lane
406
if (myLane2laneDrawedElements.count(lane2lane) > 0) {
407
// check tag
408
if (!isPlan && myLane2laneDrawedElements.at(lane2lane).count(tag) > 0) {
409
// element type was already inserted, then don't draw geometry
410
return false;
411
} else {
412
// insert tag for the given lane2lane
413
myLane2laneDrawedElements.at(lane2lane).insert(tag);
414
// draw geometry
415
return true;
416
}
417
} else {
418
// insert lane2lane and tag
419
myLane2laneDrawedElements[lane2lane].insert(tag);
420
// draw geometry
421
return true;
422
}
423
}
424
}
425
426
// ---------------------------------------------------------------------------
427
// GNEPathManager - methods
428
// ---------------------------------------------------------------------------
429
430
GNEPathManager::GNEPathManager(const GNENet* net) :
431
myPathCalculator(new PathCalculator(net)),
432
myPathDraw(new PathDraw()) {
433
}
434
435
436
GNEPathManager::~GNEPathManager() {
437
// clear paths
438
clearSegments();
439
// delete route calculator Instance
440
delete myPathCalculator;
441
// delete path draw
442
delete myPathDraw;
443
}
444
445
446
GNEPathManager::PathCalculator*
447
GNEPathManager::getPathCalculator() {
448
return myPathCalculator;
449
}
450
451
452
const GNEPathElement*
453
GNEPathManager::getPathElement(const GUIGlObject* GLObject) const {
454
// first parse pathElement
455
const auto pathElement = dynamic_cast<const GNEPathElement*>(GLObject);
456
if (pathElement == nullptr) {
457
return nullptr;
458
} else {
459
// find it in paths
460
auto it = myPaths.find(pathElement);
461
if (it == myPaths.end()) {
462
return nullptr;
463
} else {
464
return it->first;
465
}
466
}
467
}
468
469
470
const std::vector<GNESegment*>&
471
GNEPathManager::getPathElementSegments(GNEPathElement* pathElement) const {
472
if (myPaths.count(pathElement) > 0) {
473
return myPaths.at(pathElement);
474
} else {
475
return myEmptySegments;
476
}
477
}
478
479
480
GNEPathManager::PathDraw*
481
GNEPathManager::getPathDraw() {
482
return myPathDraw;
483
}
484
485
486
bool
487
GNEPathManager::isPathValid(const GNEPathElement* pathElement) const {
488
// first check if path element exist
489
if (myPaths.count(pathElement) > 0) {
490
// iterate over all segments
491
for (const auto& segment : myPaths.at(pathElement)) {
492
// if we have two consecutive lane segments, then path isn't valid
493
if (segment->getLane() && segment->getNextLane()) {
494
return false;
495
}
496
}
497
// all ok, then return true
498
return true;
499
} else {
500
return false;
501
}
502
}
503
504
505
const GNELane*
506
GNEPathManager::getFirstLane(const GNEPathElement* pathElement) const {
507
if ((myPaths.count(pathElement) > 0) && (myPaths.at(pathElement).size() > 0)) {
508
return myPaths.at(pathElement).front()->getLane();
509
} else {
510
return nullptr;
511
}
512
}
513
514
515
516
void
517
GNEPathManager::calculatePath(GNEPathElement* pathElement, SUMOVehicleClass vClass, GNELane* fromLane, GNELane* toLane) {
518
// build path
519
buildPath(pathElement, vClass, myPathCalculator->calculateDijkstraPath(vClass, fromLane->getParentEdge(), toLane->getParentEdge()),
520
fromLane, nullptr, toLane, nullptr);
521
}
522
523
524
void
525
GNEPathManager::calculatePath(GNEPathElement* pathElement, SUMOVehicleClass vClass, GNELane* fromLane, GNEJunction* toJunction) {
526
// build path
527
buildPath(pathElement, vClass, myPathCalculator->calculateDijkstraPath(vClass, fromLane->getParentEdge(), toJunction),
528
fromLane, nullptr, nullptr, toJunction);
529
}
530
531
532
void
533
GNEPathManager::calculatePath(GNEPathElement* pathElement, SUMOVehicleClass vClass, GNEJunction* fromJunction, GNELane* toLane) {
534
// build path
535
buildPath(pathElement, vClass, myPathCalculator->calculateDijkstraPath(vClass, fromJunction, toLane->getParentEdge()),
536
nullptr, fromJunction, toLane, nullptr);
537
}
538
539
540
void
541
GNEPathManager::calculatePath(GNEPathElement* pathElement, SUMOVehicleClass vClass, GNEJunction* fromJunction, GNEJunction* toJunction) {
542
// build path
543
buildPath(pathElement, vClass, myPathCalculator->calculateDijkstraPath(vClass, fromJunction, toJunction), nullptr, fromJunction, nullptr, toJunction);
544
}
545
546
547
void
548
GNEPathManager::calculatePath(GNEPathElement* pathElement, SUMOVehicleClass vClass, const std::vector<GNEEdge*>& edges) {
549
// build path
550
if (edges.size() > 0) {
551
buildPath(pathElement, vClass, myPathCalculator->calculateDijkstraPath(vClass, edges),
552
edges.front()->getLaneByAllowedVClass(vClass), nullptr, edges.back()->getLaneByAllowedVClass(vClass), nullptr);
553
} else {
554
removePath(pathElement);
555
}
556
}
557
558
559
void
560
GNEPathManager::calculateConsecutivePathEdges(GNEPathElement* pathElement, SUMOVehicleClass vClass, const std::vector<GNEEdge*>& edges,
561
const int firstLaneIndex, const int lastLaneIndex) {
562
// declare lane vector
563
std::vector<GNELane*> lanes;
564
if (edges.size() > 0) {
565
lanes.reserve(edges.size());
566
// add first lane
567
if ((firstLaneIndex >= 0) && (firstLaneIndex < (int)edges.front()->getChildLanes().size())) {
568
lanes.push_back(edges.front()->getChildLanes().at(firstLaneIndex));
569
} else {
570
lanes.push_back(edges.front()->getLaneByAllowedVClass(vClass));
571
}
572
// add rest of lanes
573
if (edges.size() > 1) {
574
// add middle lanes
575
for (int i = 1; i < ((int)edges.size() - 1); i++) {
576
lanes.push_back(edges[i]->getLaneByAllowedVClass(vClass));
577
}
578
// add last lane
579
if ((lastLaneIndex >= 0) && (lastLaneIndex < (int)edges.back()->getChildLanes().size())) {
580
lanes.push_back(edges.back()->getChildLanes().at(lastLaneIndex));
581
} else {
582
lanes.push_back(edges.back()->getLaneByAllowedVClass(vClass));
583
}
584
}
585
}
586
// calculate consecutive path lanes
587
calculateConsecutivePathLanes(pathElement, lanes);
588
}
589
590
591
void
592
GNEPathManager::calculateConsecutivePathLanes(GNEPathElement* pathElement, const std::vector<GNELane*>& lanes) {
593
// first remove path element from paths
594
removePath(pathElement);
595
// continue depending of number of lanes
596
if (lanes.size() > 0) {
597
// declare segment vector
598
std::vector<GNESegment*> segments;
599
// declare last index
600
const int lastIndex = ((int)lanes.size() - 1);
601
// reserve segments
602
segments.reserve(2 * lanes.size());
603
// iterate over lanes
604
for (int i = 0; i < (int)lanes.size(); i++) {
605
// create lane segment
606
new GNESegment(this, pathElement, lanes.at(i), segments);
607
// continue if this isn't the last lane
608
if (i != lastIndex) {
609
// create junction segments
610
new GNESegment(this, pathElement, lanes.at(i)->getParentEdge()->getToJunction(), segments);
611
}
612
}
613
// mark label segment
614
markLabelSegment(segments);
615
// add segments in paths
616
myPaths[pathElement] = segments;
617
}
618
}
619
620
621
void
622
GNEPathManager::removePath(GNEPathElement* pathElement) {
623
// check if path element exist already in myPaths
624
if (myPaths.find(pathElement) != myPaths.end()) {
625
// delete segments
626
for (const auto& segment : myPaths.at(pathElement)) {
627
delete segment;
628
}
629
// remove path element from myPaths
630
myPaths.erase(pathElement);
631
}
632
}
633
634
635
void
636
GNEPathManager::drawLanePathElements(const GUIVisualizationSettings& s, const GNELane* lane) const {
637
// check detail level and lane segments
638
if (myLaneSegments.count(lane) > 0) {
639
int numRoutes = 0;
640
// first draw the elements marked for redraw
641
for (const auto& segment : myLaneSegments.at(lane)) {
642
if (gViewObjectsHandler.isPathElementMarkForRedraw(segment->getPathElement())) {
643
segment->getPathElement()->drawLanePartialGL(s, segment, 2);
644
// check if path element is a route
645
if (segment->getPathElement()->isRoute()) {
646
numRoutes++;
647
}
648
}
649
}
650
// now draw the rest of segments
651
for (const auto& segment : myLaneSegments.at(lane)) {
652
if (!gViewObjectsHandler.isPathElementMarkForRedraw(segment->getPathElement())) {
653
segment->getPathElement()->drawLanePartialGL(s, segment, 0);
654
// check if path element is a route
655
if (segment->getPathElement()->isRoute()) {
656
numRoutes++;
657
}
658
}
659
}
660
// check if draw overlapped routes
661
if ((numRoutes > 1) && lane->getNet()->getViewNet()->getDemandViewOptions().showOverlappedRoutes()) {
662
lane->drawOverlappedRoutes(numRoutes);
663
}
664
}
665
}
666
667
668
void
669
GNEPathManager::drawJunctionPathElements(const GUIVisualizationSettings& s, const GNEJunction* junction) const {
670
// check detail level and junction segments
671
if (myJunctionSegments.count(junction) > 0) {
672
// first draw the elements marked for redraw
673
for (const auto& segment : myJunctionSegments.at(junction)) {
674
if (gViewObjectsHandler.isPathElementMarkForRedraw(segment->getPathElement())) {
675
segment->getPathElement()->drawJunctionPartialGL(s, segment, 2);
676
}
677
}
678
// now draw the rest of segments
679
for (const auto& segment : myJunctionSegments.at(junction)) {
680
if (!gViewObjectsHandler.isPathElementMarkForRedraw(segment->getPathElement())) {
681
segment->getPathElement()->drawJunctionPartialGL(s, segment, 0);
682
}
683
}
684
}
685
}
686
687
688
void
689
GNEPathManager::redrawPathElements(const GUIVisualizationSettings& s) const {
690
// draw every segment partial
691
for (const auto& pathElementToRedraw : gViewObjectsHandler.getRedrawPathElements()) {
692
const auto it = myPaths.find(pathElementToRedraw);
693
if (it != myPaths.end()) {
694
for (const auto& segment : it->second) {
695
if (segment->getLane()) {
696
// draw with high offset
697
it->first->drawLanePartialGL(s, segment, 3);
698
} else if (segment->getJunction()) {
699
// draw with high offset
700
it->first->drawJunctionPartialGL(s, segment, 3);
701
}
702
}
703
}
704
}
705
}
706
707
708
void
709
GNEPathManager::invalidateLanePath(const GNELane* lane) {
710
// declare vector for path elements to compute
711
std::vector<GNEPathElement*> pathElementsToCompute;
712
// check lane in laneSegments
713
if (myLaneSegments.count(lane) > 0) {
714
// obtain affected path elements
715
for (const auto& segment : myLaneSegments.at(lane)) {
716
pathElementsToCompute.push_back(segment->getPathElement());
717
}
718
}
719
// compute path elements
720
for (const auto& pathElement : pathElementsToCompute) {
721
pathElement->computePathElement();
722
}
723
}
724
725
726
void
727
GNEPathManager::invalidateJunctionPath(const GNEJunction* junction) {
728
// declare vector for path elements to compute
729
std::vector<GNEPathElement*> pathElementsToCompute;
730
// check junction in junctionSegments
731
if (myJunctionSegments.count(junction) > 0) {
732
// obtain affected path elements
733
for (const auto& segment : myJunctionSegments.at(junction)) {
734
pathElementsToCompute.push_back(segment->getPathElement());
735
}
736
}
737
// compute path elements
738
for (const auto& pathElement : pathElementsToCompute) {
739
pathElement->computePathElement();
740
}
741
}
742
743
744
void
745
GNEPathManager::clearSegments() {
746
// clear segments quickly
747
myCleaningSegments = true;
748
// clear all segments
749
for (const auto& path : myPaths) {
750
// delete all segments
751
for (const auto& segment : path.second) {
752
delete segment;
753
}
754
}
755
// clear containers
756
myPaths.clear();
757
myJunctionSegments.clear();
758
myLaneSegments.clear();
759
// restore flag
760
myCleaningSegments = false;
761
}
762
763
764
void
765
GNEPathManager::addSegmentInLaneSegments(GNESegment* segment, const GNELane* lane) {
766
myLaneSegments[lane].insert(segment);
767
}
768
769
770
void
771
GNEPathManager::addSegmentInJunctionSegments(GNESegment* segment, const GNEJunction* junction) {
772
myJunctionSegments[junction].insert(segment);
773
}
774
775
776
void
777
GNEPathManager::clearSegmentFromJunctionAndLaneSegments(GNESegment* segment) {
778
// check if segment has a lane
779
if (segment->getLane()) {
780
auto lane = segment->getLane();
781
myLaneSegments[lane].erase(segment);
782
// clear lane if doesn't have more segments
783
if (myLaneSegments.at(lane).empty()) {
784
myLaneSegments.erase(lane);
785
}
786
}
787
if (segment->getJunction()) {
788
auto junction = segment->getJunction();
789
myJunctionSegments[junction].erase(segment);
790
// clear junction if doesn't have more segments
791
if (myJunctionSegments.at(junction).empty()) {
792
myJunctionSegments.erase(junction);
793
}
794
}
795
}
796
797
798
bool
799
GNEPathManager::connectedLanes(const GNELane* fromLane, const GNELane* toLane) const {
800
// get from and to NBEdges
801
NBEdge* fromNBEdge = fromLane->getParentEdge()->getNBEdge();
802
NBEdge* toNBEdge = toLane->getParentEdge()->getNBEdge();
803
// get connections vinculated with from Lane
804
const std::vector<NBEdge::Connection> connections = fromNBEdge->getConnectionsFromLane(fromLane->getIndex());
805
// find connection
806
std::vector<NBEdge::Connection>::const_iterator con_it = find_if(
807
connections.begin(), connections.end(),
808
NBEdge::connections_finder(fromLane->getIndex(), toNBEdge, toLane->getIndex()));
809
// check if connection was found
810
return (con_it != connections.end());
811
}
812
813
814
void
815
GNEPathManager::buildPath(GNEPathElement* pathElement, SUMOVehicleClass vClass, const std::vector<GNEEdge*> path,
816
GNELane* fromLane, GNEJunction* fromJunction, GNELane* toLane, GNEJunction* toJunction) {
817
// first remove path element from paths
818
removePath(pathElement);
819
// declare segment vector
820
std::vector<GNESegment*> segments;
821
// continue if path isn't empty
822
if (path.size() > 0) {
823
// declare last index
824
const int lastIndex = ((int)path.size() - 1);
825
// reserve segments
826
segments.reserve(2 * path.size());
827
if (fromJunction) {
828
// create lane segment using fromJunction
829
new GNESegment(this, pathElement, fromJunction, segments);
830
}
831
// iterate over path
832
for (int i = 0; i < (int)path.size(); i++) {
833
if ((i == 0) && fromLane) {
834
// create lane segment using fromLane
835
new GNESegment(this, pathElement, fromLane, segments);
836
// continue if this isn't the last path edge
837
if (i != lastIndex) {
838
// create junction segment using to junction
839
new GNESegment(this, pathElement, path.at(i)->getToJunction(), segments);
840
}
841
} else if ((i == lastIndex) && toLane) {
842
// create lane segment using toLane
843
new GNESegment(this, pathElement, toLane, segments);
844
} else {
845
// get first allowed lane
846
const GNELane* lane = path.at(i)->getLaneByAllowedVClass(vClass);
847
// create lane segment
848
new GNESegment(this, pathElement, lane, segments);
849
// continue if this isn't the last path edge
850
if (i != lastIndex) {
851
// create junction segment using to junction
852
new GNESegment(this, pathElement, path.at(i)->getToJunction(), segments);
853
}
854
}
855
}
856
if (toJunction) {
857
// create lane segment using toJunction
858
new GNESegment(this, pathElement, toJunction, segments);
859
}
860
// mark label segment
861
markLabelSegment(segments);
862
// add segments in paths
863
myPaths[pathElement] = segments;
864
} else {
865
// create first segment
866
GNESegment* firstSegment = nullptr;
867
GNESegment* lastSegment = nullptr;
868
// continue depending of from-to elements
869
if (fromLane) {
870
firstSegment = new GNESegment(this, pathElement, fromLane, segments);
871
} else if (fromJunction) {
872
firstSegment = new GNESegment(this, pathElement, fromJunction, segments);
873
}
874
if (toLane) {
875
lastSegment = new GNESegment(this, pathElement, toLane, segments);
876
} else if (toJunction) {
877
lastSegment = new GNESegment(this, pathElement, toJunction, segments);
878
}
879
// continue depending of segments
880
if (firstSegment && lastSegment) {
881
// mark segment as label segment
882
firstSegment->markSegmentLabel();
883
// add segments in path
884
myPaths[pathElement] = segments;
885
} else {
886
delete firstSegment;
887
delete lastSegment;
888
}
889
}
890
}
891
892
893
void
894
GNEPathManager::markLabelSegment(const std::vector<GNESegment*>& segments) const {
895
// separate junction segments and lane segments
896
std::vector<GNESegment*> laneSegments;
897
laneSegments.reserve(segments.size());
898
for (const auto& segment : segments) {
899
if (segment->getLane()) {
900
laneSegments.push_back(segment);
901
}
902
}
903
// get lane segment index
904
const int laneSegmentIndex = (int)((double)laneSegments.size() * 0.5);
905
// mark middle label as label segment
906
laneSegments.at(laneSegmentIndex)->markSegmentLabel();
907
}
908
909
/****************************************************************************/
910
911