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