Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netbuild/NBPTLineCont.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 NBPTLineCont.cpp
15
/// @author Gregor Laemmel
16
/// @author Nikita Cherednychek
17
/// @date Tue, 20 Mar 2017
18
///
19
// Container for NBPTLine during netbuild
20
/****************************************************************************/
21
#include <config.h>
22
23
#include <iostream>
24
#include <utils/common/MsgHandler.h>
25
#include <utils/common/ToString.h>
26
#include <utils/options/OptionsCont.h>
27
#include <utils/router/DijkstraRouter.h>
28
#include "NBPTLineCont.h"
29
#include "NBPTStop.h"
30
#include "NBEdge.h"
31
#include "NBNode.h"
32
#include "NBVehicle.h"
33
#include "NBPTStopCont.h"
34
35
//#define DEBUG_FIND_WAY
36
//#define DEBUG_CONSTRUCT_ROUTE
37
38
#define DEBUGLINEID ""
39
#define DEBUGSTOPID ""
40
41
// ===========================================================================
42
// static value definitions
43
// ===========================================================================
44
const int NBPTLineCont::FWD(1);
45
const int NBPTLineCont::BWD(-1);
46
47
48
// ===========================================================================
49
// method definitions
50
// ===========================================================================
51
NBPTLineCont::~NBPTLineCont() {
52
for (auto& myPTLine : myPTLines) {
53
delete myPTLine.second;
54
}
55
myPTLines.clear();
56
}
57
58
59
bool
60
NBPTLineCont::insert(NBPTLine* ptLine) {
61
if (myPTLines.count(ptLine->getLineID()) == 0) {
62
myPTLines[ptLine->getLineID()] = ptLine;
63
return true;
64
}
65
return false;
66
}
67
68
69
NBPTLine*
70
NBPTLineCont::retrieve(const std::string& lineID) {
71
if (myPTLines.count(lineID) == 0) {
72
return nullptr;
73
} else {
74
return myPTLines[lineID];
75
}
76
}
77
78
void
79
NBPTLineCont::process(NBEdgeCont& ec, NBPTStopCont& sc, bool routeOnly) {
80
for (auto& item : myPTLines) {
81
NBPTLine* line = item.second;
82
if (item.second->getWays().size() > 0) {
83
// loaded from OSM rather than ptline input. We can use extra
84
// information to reconstruct route and stops
85
constructRoute(line, ec);
86
if (!routeOnly) {
87
// map stops to ways, using the constructed route for loose stops
88
reviseStops(line, ec, sc);
89
}
90
}
91
// fix circular line if necessary
92
if (line->getStops().size() > 1
93
&& line->getStops().front() == line->getStops().back()
94
&& line->getRoute().size() > 1
95
&& line->getRoute().front() != line->getRoute().back()) {
96
// we need to duplicate either the first or the last edge depending on the stop locations
97
const std::string firstStopEdge = line->getStops().front()->getEdgeId();
98
const std::string lastStopEdge = line->getStops().back()->getEdgeId();
99
std::vector<NBEdge*> edges = line->getRoute();
100
if (firstStopEdge == edges.back()->getID()) {
101
edges.insert(edges.begin(), edges.back());
102
} else if (lastStopEdge == edges.front()->getID()) {
103
edges.push_back(edges.front());
104
}
105
line->setEdges(edges);
106
}
107
line->deleteInvalidStops(ec, sc);
108
//line->deleteDuplicateStops();
109
}
110
}
111
112
113
void
114
NBPTLineCont::reviseStops(NBPTLine* line, const NBEdgeCont& ec, NBPTStopCont& sc) {
115
const std::vector<std::string>& waysIds = line->getWays();
116
if (waysIds.size() == 1 && line->getStops().size() > 1) {
117
reviseSingleWayStops(line, ec, sc);
118
return;
119
}
120
if (waysIds.size() <= 1) {
121
WRITE_WARNINGF(TL("Cannot revise pt stop localization for pt line '%', which consist of one way only. Ignoring!"), line->getLineID());
122
return;
123
}
124
if (line->getRoute().size() == 0) {
125
WRITE_WARNINGF(TL("Cannot revise pt stop localization for pt line '%', which has no route edges. Ignoring!"), line->getLineID());
126
return;
127
}
128
std::vector<std::shared_ptr<NBPTStop> > stops = line->getStops();
129
for (std::shared_ptr<NBPTStop> stop : stops) {
130
//get the corresponding and one of the two adjacent ways
131
stop = findWay(line, stop, ec, sc);
132
if (stop == nullptr) {
133
// warning already given
134
continue;
135
}
136
auto waysIdsIt = std::find(waysIds.begin(), waysIds.end(), stop->getOrigEdgeId());
137
if (waysIdsIt == waysIds.end()) {
138
// warning already given
139
continue;
140
}
141
// find directional edge (OSM ways are bidirectional)
142
const std::vector<long long int>* const way = line->getWayNodes(stop->getOrigEdgeId());
143
if (way == nullptr) {
144
WRITE_WARNINGF(TL("Cannot assign stop '%' on edge '%' to pt line '%' (wayNodes not found). Ignoring!"),
145
stop->getID(), stop->getOrigEdgeId(), line->getLineID());
146
continue;
147
}
148
149
int dir;
150
const std::vector<long long int>* wayPrev = nullptr;
151
if (waysIdsIt != waysIds.begin()) {
152
wayPrev = line->getWayNodes(*(waysIdsIt - 1));
153
}
154
const std::vector<long long int>* wayNext = nullptr;
155
if (waysIdsIt != (waysIds.end() - 1)) {
156
wayNext = line->getWayNodes(*(waysIdsIt + 1));
157
}
158
if (wayPrev == nullptr && wayNext == nullptr) {
159
WRITE_WARNINGF(TL("Cannot revise pt stop localization for incomplete pt line '%'. Ignoring!"), line->getLineID());
160
continue;
161
}
162
const long long int wayEnds = way->back();
163
const long long int wayBegins = way->front();
164
const long long int wayPrevEnds = wayPrev != nullptr ? wayPrev->back() : 0;
165
const long long int wayPrevBegins = wayPrev != nullptr ? wayPrev->front() : 0;
166
const long long int wayNextEnds = wayNext != nullptr ? wayNext->back() : 0;
167
const long long int wayNextBegins = wayNext != nullptr ? wayNext->front() : 0;
168
if (wayBegins == wayPrevEnds || wayBegins == wayPrevBegins || wayEnds == wayNextBegins || wayEnds == wayNextEnds) {
169
dir = FWD;
170
} else if (wayEnds == wayPrevBegins || wayEnds == wayPrevEnds || wayBegins == wayNextEnds || wayBegins == wayNextBegins) {
171
dir = BWD;
172
} else {
173
WRITE_WARNINGF(TL("Cannot revise pt stop localization for incomplete pt line '%'. Ignoring!"), line->getLineID());
174
continue;
175
}
176
177
std::string edgeId = stop->getEdgeId();
178
NBEdge* current = ec.getByID(edgeId);
179
int assignedTo = edgeId.at(0) == '-' ? BWD : FWD;
180
181
if (dir != assignedTo) {
182
NBEdge* reverse = NBPTStopCont::getReverseEdge(current);
183
if (reverse == nullptr) {
184
WRITE_WARNINGF(TL("Could not re-assign PT stop '%', probably broken osm file."), stop->getID());
185
continue;
186
}
187
if (stop->getLines().size() > 0) {
188
std::shared_ptr<NBPTStop> reverseStop = sc.getReverseStop(stop, ec);
189
sc.insert(reverseStop);
190
line->replaceStop(stop, reverseStop);
191
stop = reverseStop;
192
} else {
193
WRITE_WARNINGF(TL("PT stop '%' has been moved to edge '%'."), stop->getID(), reverse->getID());
194
}
195
stop->setEdgeId(reverse->getID(), ec);
196
}
197
stop->addLine(line->getRef());
198
}
199
}
200
201
202
void NBPTLineCont::reviseSingleWayStops(NBPTLine* line, const NBEdgeCont& ec, NBPTStopCont& sc) {
203
const std::vector<std::string>& waysIds = line->getWays();
204
for (std::shared_ptr<NBPTStop> stop : line->getStops()) {
205
//get the corresponding and one of the two adjacent ways
206
stop = findWay(line, stop, ec, sc);
207
if (stop == nullptr) {
208
// warning already given
209
continue;
210
}
211
auto waysIdsIt = std::find(waysIds.begin(), waysIds.end(), stop->getOrigEdgeId());
212
if (waysIdsIt == waysIds.end()) {
213
// warning already given
214
continue;
215
}
216
stop->addLine(line->getRef());
217
}
218
}
219
220
221
std::shared_ptr<NBPTStop>
222
NBPTLineCont::findWay(NBPTLine* line, std::shared_ptr<NBPTStop> stop, const NBEdgeCont& ec, NBPTStopCont& sc) const {
223
const std::vector<std::string>& waysIds = line->getWays();
224
#ifdef DEBUG_FIND_WAY
225
if (stop->getID() == DEBUGSTOPID) {
226
std::cout << " stop=" << stop->getID() << " line=" << line->getLineID() << " edgeID=" << stop->getEdgeId() << " origID=" << stop->getOrigEdgeId() << "\n";
227
}
228
#endif
229
if (stop->isLoose()) {
230
// find closest edge in route
231
double minDist = std::numeric_limits<double>::max();
232
NBEdge* best = nullptr;
233
for (NBEdge* edge : line->getRoute()) {
234
const double dist = edge->getLaneShape(0).distance2D(stop->getPosition());
235
if (dist < minDist) {
236
best = edge;
237
minDist = dist;
238
}
239
}
240
#ifdef DEBUG_FIND_WAY
241
if (stop->getID() == DEBUGSTOPID) {
242
std::cout << " best=" << Named::getIDSecure(best) << " minDist=" << minDist << " wayID=" << getWayID(best->getID())
243
<< " found=" << (std::find(waysIds.begin(), waysIds.end(), getWayID(best->getID())) != waysIds.end())
244
<< " wayIDs=" << toString(waysIds) << "\n";
245
}
246
#endif
247
if (minDist < OptionsCont::getOptions().getFloat("ptline.match-dist")) {
248
const std::string wayID = getWayID(best->getID());
249
if (stop->getEdgeId() == "") {
250
stop->setEdgeId(best->getID(), ec);
251
stop->setOrigEdgeId(wayID);
252
} else if (stop->getEdgeId() != best->getID()) {
253
// stop is used by multiple lines and mapped to different edges.
254
// check if an alternative stop already exists
255
std::shared_ptr<NBPTStop> newStop = sc.findStop(wayID, stop->getPosition());
256
if (newStop == nullptr) {
257
newStop = std::make_shared<NBPTStop>(stop->getID() + "@" + line->getLineID(), stop->getPosition(), best->getID(), wayID, stop->getLength(), stop->getName(), stop->getPermissions());
258
newStop->setEdgeId(best->getID(), ec); // trigger lane assignment
259
sc.insert(newStop);
260
}
261
line->replaceStop(stop, newStop);
262
stop = newStop;
263
}
264
} else {
265
WRITE_WARNINGF(TL("Could not assign stop '%' to pt line '%' (closest edge '%', distance %). Ignoring!"),
266
stop->getID(), line->getLineID(), Named::getIDSecure(best), minDist);
267
return nullptr;
268
}
269
} else {
270
// if the stop is part of an edge, find that edge among the line edges
271
auto waysIdsIt = waysIds.begin();
272
for (; waysIdsIt != waysIds.end(); waysIdsIt++) {
273
if ((*waysIdsIt) == stop->getOrigEdgeId()) {
274
break;
275
}
276
}
277
278
if (waysIdsIt == waysIds.end()) {
279
// stop edge not found, try additional edges
280
for (auto& edgeCand : stop->getAdditionalEdgeCandidates()) {
281
bool found = false;
282
waysIdsIt = waysIds.begin();
283
for (; waysIdsIt != waysIds.end(); waysIdsIt++) {
284
if ((*waysIdsIt) == edgeCand.first) {
285
if (stop->setEdgeId(edgeCand.second, ec)) {
286
stop->setOrigEdgeId(edgeCand.first);
287
found = true;
288
break;
289
}
290
}
291
}
292
if (found) {
293
break;
294
}
295
}
296
if (waysIdsIt == waysIds.end()) {
297
WRITE_WARNINGF(TL("Cannot assign stop % on edge '%' to pt line '%'. Ignoring!"), stop->getID(), stop->getOrigEdgeId(), line->getLineID());
298
}
299
}
300
}
301
return stop;
302
}
303
304
305
void NBPTLineCont::constructRoute(NBPTLine* pTLine, const NBEdgeCont& cont) {
306
std::vector<NBEdge*> edges;
307
308
NBNode* first = nullptr;
309
NBNode* last = nullptr;
310
std::vector<NBEdge*> prevWayEdges;
311
std::vector<NBEdge*> prevWayMinusEdges;
312
std::vector<NBEdge*> currentWayEdges;
313
std::vector<NBEdge*> currentWayMinusEdges;
314
for (auto it3 = pTLine->getWays().begin(); it3 != pTLine->getWays().end(); it3++) {
315
316
int foundForward = 0;
317
if (cont.retrieve(*it3, false) != nullptr) {
318
currentWayEdges.push_back(cont.retrieve(*it3, false));
319
foundForward++;
320
} else {
321
int i = 0;
322
while (cont.retrieve(*it3 + "#" + std::to_string(i), true) != nullptr) {
323
if (cont.retrieve(*it3 + "#" + std::to_string(i), false)) {
324
currentWayEdges.push_back(cont.retrieve(*it3 + "#" + std::to_string(i), false));
325
foundForward++;
326
}
327
i++;
328
}
329
}
330
331
int foundReverse = 0;
332
if (cont.retrieve("-" + *it3, false) != nullptr) {
333
currentWayMinusEdges.push_back(cont.retrieve("-" + *it3, false));
334
foundReverse++;
335
} else {
336
int i = 0;
337
while (cont.retrieve("-" + *it3 + "#" + std::to_string(i), true) != nullptr) {
338
if (cont.retrieve("-" + *it3 + "#" + std::to_string(i), false)) {
339
currentWayMinusEdges.insert(currentWayMinusEdges.end() - foundReverse,
340
cont.retrieve("-" + *it3 + "#" + std::to_string(i), false));
341
foundReverse++;
342
}
343
i++;
344
}
345
}
346
bool fakeMinus = false;
347
if (foundReverse == 0 && foundForward > 0 && isRailway(pTLine->getVClass())) {
348
// rail tracks may be used in both directions and are often not tagged as such.
349
// This can be repaired later with option --railway.topology.repair
350
currentWayMinusEdges.insert(currentWayMinusEdges.begin(), currentWayEdges.rbegin(), currentWayEdges.rbegin() + foundForward);
351
fakeMinus = true;
352
}
353
#ifdef DEBUG_CONSTRUCT_ROUTE
354
if (pTLine->getLineID() == DEBUGLINEID) {
355
std::cout << " way=" << (*it3)
356
<< " done=" << toString(edges)
357
<< " first=" << Named::getIDSecure(first)
358
<< " last=" << Named::getIDSecure(last)
359
<< "\n +=" << toString(currentWayEdges)
360
<< "\n -=" << toString(currentWayMinusEdges)
361
<< "\n p+=" << toString(prevWayEdges)
362
<< "\n p-=" << toString(prevWayMinusEdges)
363
<< "\n";
364
}
365
#endif
366
if (currentWayEdges.empty()) {
367
continue;
368
}
369
if (last == currentWayEdges.front()->getFromNode() && last != nullptr) {
370
if (!prevWayEdges.empty()) {
371
edges.insert(edges.end(), prevWayEdges.begin(), prevWayEdges.end());
372
prevWayEdges.clear();
373
prevWayMinusEdges.clear();
374
}
375
edges.insert(edges.end(), currentWayEdges.begin(), currentWayEdges.end());
376
last = currentWayEdges.back()->getToNode();
377
} else if (last == currentWayEdges.back()->getToNode() && last != nullptr) {
378
if (!prevWayEdges.empty()) {
379
edges.insert(edges.end(), prevWayEdges.begin(), prevWayEdges.end());
380
prevWayEdges.clear();
381
prevWayMinusEdges.clear();
382
}
383
if (currentWayMinusEdges.empty()) {
384
currentWayEdges.clear();
385
last = nullptr;
386
continue;
387
} else {
388
edges.insert(edges.end(), currentWayMinusEdges.begin(), currentWayMinusEdges.end());
389
if (fakeMinus) {
390
last = currentWayMinusEdges.back()->getFromNode();
391
} else {
392
last = currentWayMinusEdges.back()->getToNode();
393
}
394
}
395
} else if (first == currentWayEdges.front()->getFromNode() && first != nullptr) {
396
edges.insert(edges.end(), prevWayMinusEdges.begin(), prevWayMinusEdges.end());
397
edges.insert(edges.end(), currentWayEdges.begin(), currentWayEdges.end());
398
last = currentWayEdges.back()->getToNode();
399
prevWayEdges.clear();
400
prevWayMinusEdges.clear();
401
} else if (first == currentWayEdges.back()->getToNode() && first != nullptr) {
402
edges.insert(edges.end(), prevWayMinusEdges.begin(), prevWayMinusEdges.end());
403
if (currentWayMinusEdges.empty()) {
404
currentWayEdges.clear();
405
last = nullptr;
406
prevWayEdges.clear();
407
prevWayMinusEdges.clear();
408
continue;
409
} else {
410
edges.insert(edges.end(), currentWayMinusEdges.begin(), currentWayMinusEdges.end());
411
last = currentWayMinusEdges.back()->getToNode();
412
prevWayEdges.clear();
413
prevWayMinusEdges.clear();
414
}
415
} else {
416
if (it3 != pTLine->getWays().begin()) {
417
#ifdef DEBUG_CONSTRUCT_ROUTE
418
if (pTLine->getLineID() == DEBUGLINEID) {
419
std::cout << " way " << (*it3)
420
<< " is not the start of ptline " << pTLine->getLineID()
421
<< " (" + pTLine->getName() + ")\n";
422
}
423
#endif
424
} else if (pTLine->getWays().size() == 1) {
425
if (currentWayEdges.size() > 0) {
426
edges.insert(edges.end(), currentWayEdges.begin(), currentWayEdges.end());
427
} else {
428
edges.insert(edges.end(), currentWayMinusEdges.begin(), currentWayMinusEdges.end());
429
}
430
}
431
prevWayEdges = currentWayEdges;
432
prevWayMinusEdges = currentWayMinusEdges;
433
if (!prevWayEdges.empty()) {
434
first = prevWayEdges.front()->getFromNode();
435
last = prevWayEdges.back()->getToNode();
436
} else {
437
first = nullptr;
438
last = nullptr;
439
}
440
}
441
currentWayEdges.clear();
442
currentWayMinusEdges.clear();
443
}
444
pTLine->setEdges(edges);
445
}
446
447
448
void
449
NBPTLineCont::replaceEdge(const std::string& edgeID, const EdgeVector& replacement) {
450
//std::cout << " replaceEdge " << edgeID << " replacement=" << toString(replacement) << "\n";
451
if (myPTLines.size() > 0 && myPTLineLookup.size() == 0) {
452
// init lookup once
453
for (auto& item : myPTLines) {
454
for (const NBEdge* e : item.second->getRoute()) {
455
myPTLineLookup[e->getID()].insert(item.second);
456
}
457
}
458
}
459
for (NBPTLine* line : myPTLineLookup[edgeID]) {
460
line->replaceEdge(edgeID, replacement);
461
for (const NBEdge* e : replacement) {
462
myPTLineLookup[e->getID()].insert(line);
463
}
464
}
465
myPTLineLookup.erase(edgeID);
466
}
467
468
469
std::set<std::string>
470
NBPTLineCont::getServedPTStops() {
471
std::set<std::string> result;
472
for (auto& item : myPTLines) {
473
NBPTLine* line = item.second;
474
for (std::shared_ptr<NBPTStop> stop : line->getStops()) {
475
result.insert(stop->getID());
476
}
477
}
478
return result;
479
}
480
481
482
void
483
NBPTLineCont::fixBidiStops(const NBEdgeCont& ec) {
484
std::map<std::string, SUMOVehicleClass> types;
485
types["bus"] = SVC_BUS;
486
types["minibus"] = SVC_BUS;
487
types["trolleybus"] = SVC_BUS;
488
types["tram"] = SVC_TRAM;
489
types["train"] = SVC_RAIL;
490
types["subway"] = SVC_RAIL_URBAN;
491
types["light_rail"] = SVC_RAIL_URBAN;
492
types["monorail"] = SVC_RAIL_URBAN;
493
types["aerialway"] = SVC_RAIL_URBAN;
494
types["ferry"] = SVC_SHIP;
495
496
SUMOAbstractRouter<NBRouterEdge, NBVehicle>* const router = new DijkstraRouter<NBRouterEdge, NBVehicle>(
497
ec.getAllRouterEdges(), true, &NBRouterEdge::getTravelTimeStatic, nullptr, true);
498
499
for (auto& item : myPTLines) {
500
NBPTLine* line = item.second;
501
std::vector<std::shared_ptr<NBPTStop> > stops = line->getStops();
502
if (stops.size() < 2) {
503
continue;
504
}
505
if (types.count(line->getType()) == 0) {
506
WRITE_WARNINGF(TL("Could not determine vehicle class for public transport line of type '%'."), line->getType());
507
continue;
508
}
509
NBVehicle veh(line->getRef(), types[line->getType()]);
510
std::vector<std::shared_ptr<NBPTStop> > newStops;
511
std::shared_ptr<NBPTStop> from = nullptr;
512
for (auto it = stops.begin(); it != stops.end(); ++it) {
513
std::shared_ptr<NBPTStop> to = *it;
514
std::shared_ptr<NBPTStop> used = *it;
515
if (to->getBidiStop() != nullptr) {
516
double best = std::numeric_limits<double>::max();
517
std::shared_ptr<NBPTStop> to2 = to->getBidiStop();
518
if (from == nullptr) {
519
if ((it + 1) != stops.end()) {
520
from = to;
521
std::shared_ptr<NBPTStop> from2 = to2;
522
to = *(it + 1);
523
const double c1 = getCost(ec, *router, from, to, &veh);
524
const double c2 = getCost(ec, *router, from2, to, &veh);
525
//std::cout << " from=" << from->getID() << " to=" << to->getID() << " c1=" << MIN2(10000.0, c1) << "\n";
526
//std::cout << " from2=" << from2->getID() << " to=" << to->getID() << " c2=" << MIN2(10000.0, c2) << "\n";
527
best = c1;
528
if (to->getBidiStop() != nullptr) {
529
to2 = to->getBidiStop();
530
const double c3 = getCost(ec, *router, from, to2, &veh);
531
const double c4 = getCost(ec, *router, from2, to2, &veh);
532
//std::cout << " from=" << from->getID() << " to2=" << to2->getID() << " c3=" << MIN2(10000.0, c3) << "\n";
533
//std::cout << " from2=" << from2->getID() << " to2=" << to2->getID() << " c4=" << MIN2(10000.0, c4) << "\n";
534
if (c2 < best) {
535
used = from2;
536
best = c2;
537
}
538
if (c3 < best) {
539
used = from;
540
best = c3;
541
}
542
if (c4 < best) {
543
used = from2;
544
best = c4;
545
}
546
} else {
547
if (c2 < c1) {
548
used = from2;
549
best = c2;
550
} else {
551
best = c1;
552
}
553
}
554
}
555
} else {
556
const double c1 = getCost(ec, *router, from, to, &veh);
557
const double c2 = getCost(ec, *router, from, to2, &veh);
558
//std::cout << " from=" << from->getID() << " to=" << to->getID() << " c1=" << MIN2(10000.0, c1) << "\n";
559
//std::cout << " from=" << from->getID() << " t2o=" << to2->getID() << " c2=" << MIN2(10000.0, c2) << "\n";
560
if (c2 < c1) {
561
used = to2;
562
best = c2;
563
} else {
564
best = c1;
565
}
566
567
}
568
if (best < std::numeric_limits<double>::max()) {
569
from = used;
570
} else {
571
WRITE_WARNINGF(TL("Could not determine direction for line '%' at stop '%'."), line->getLineID(), used->getID());
572
}
573
}
574
from = used;
575
newStops.push_back(used);
576
}
577
assert(stops.size() == newStops.size());
578
line->replaceStops(newStops);
579
}
580
delete router;
581
}
582
583
584
void
585
NBPTLineCont::removeInvalidEdges(const NBEdgeCont& ec) {
586
for (auto& item : myPTLines) {
587
item.second->removeInvalidEdges(ec);
588
}
589
}
590
591
592
void
593
NBPTLineCont::fixPermissions() {
594
for (auto& item : myPTLines) {
595
NBPTLine* line = item.second;
596
const std::vector<NBEdge*>& route = line->getRoute();
597
const SUMOVehicleClass svc = line->getVClass();
598
for (int i = 1; i < (int)route.size(); i++) {
599
NBEdge* e1 = route[i - 1];
600
NBEdge* e2 = route[i];
601
std::vector<NBEdge::Connection> cons = e1->getConnectionsFromLane(-1, e2, -1);
602
if (cons.size() == 0) {
603
//WRITE_WARNINGF(TL("Disconnected ptline '%' between edge '%' and edge '%'"), line->getLineID(), e1->getID(), e2->getID());
604
} else {
605
bool ok = false;
606
for (const auto& c : cons) {
607
if ((e1->getPermissions(c.fromLane) & svc) == svc) {
608
ok = true;
609
break;
610
}
611
}
612
if (!ok) {
613
int lane = cons[0].fromLane;
614
e1->setPermissions(e1->getPermissions(lane) | svc, lane);
615
}
616
}
617
}
618
}
619
}
620
621
622
double
623
NBPTLineCont::getCost(const NBEdgeCont& ec, SUMOAbstractRouter<NBRouterEdge, NBVehicle>& router,
624
const std::shared_ptr<NBPTStop> from, const std::shared_ptr<NBPTStop> to, const NBVehicle* veh) {
625
NBEdge* fromEdge = ec.getByID(from->getEdgeId());
626
NBEdge* toEdge = ec.getByID(to->getEdgeId());
627
if (fromEdge == nullptr || toEdge == nullptr) {
628
return std::numeric_limits<double>::max();
629
} else if (fromEdge == toEdge) {
630
if (from->getEndPos() <= to->getEndPos()) {
631
return to->getEndPos() - from->getEndPos();
632
} else {
633
return std::numeric_limits<double>::max();
634
}
635
} else if (fromEdge->getBidiEdge() == toEdge) {
636
return std::numeric_limits<double>::max();
637
}
638
std::vector<const NBRouterEdge*> route;
639
router.compute(fromEdge, toEdge, veh, 0, route);
640
if (route.size() == 0) {
641
return std::numeric_limits<double>::max();
642
} else {
643
return router.recomputeCosts(route, veh, 0);
644
}
645
}
646
647
648
std::string
649
NBPTLineCont::getWayID(const std::string& edgeID) {
650
std::size_t found = edgeID.rfind("#");
651
std::string result = edgeID;
652
if (found != std::string::npos) {
653
result = edgeID.substr(0, found);
654
}
655
if (result[0] == '-') {
656
result = result.substr(1);
657
}
658
return result;
659
}
660
661
662
/****************************************************************************/
663
664