Eclipse SUMO - Simulation of Urban MObility
NBPTLineCont.cpp
Go to the documentation of this file.
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 /****************************************************************************/
19 // Container for NBPTLine during netbuild
20 /****************************************************************************/
21 #include <config.h>
22 
23 #include <iostream>
25 #include <utils/common/ToString.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 // ===========================================================================
52  for (auto& myPTLine : myPTLines) {
53  delete myPTLine.second;
54  }
55  myPTLines.clear();
56 }
57 
58 
59 bool
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  for (std::shared_ptr<NBPTStop> stop : line->getStops()) {
110  myServedPTStops.insert(stop->getID());
111  }
112  }
113 }
114 
115 
116 void
118  const std::vector<std::string>& waysIds = line->getWays();
119  if (waysIds.size() == 1 && line->getStops().size() > 1) {
120  reviseSingleWayStops(line, ec, sc);
121  return;
122  }
123  if (waysIds.size() <= 1) {
124  WRITE_WARNINGF(TL("Cannot revise pt stop localization for pt line '%', which consist of one way only. Ignoring!"), line->getLineID());
125  return;
126  }
127  if (line->getRoute().size() == 0) {
128  WRITE_WARNINGF(TL("Cannot revise pt stop localization for pt line '%', which has no route edges. Ignoring!"), line->getLineID());
129  return;
130  }
131  std::vector<std::shared_ptr<NBPTStop> > stops = line->getStops();
132  for (std::shared_ptr<NBPTStop> stop : stops) {
133  //get the corresponding and one of the two adjacent ways
134  stop = findWay(line, stop, ec, sc);
135  if (stop == nullptr) {
136  // warning already given
137  continue;
138  }
139  auto waysIdsIt = std::find(waysIds.begin(), waysIds.end(), stop->getOrigEdgeId());
140  if (waysIdsIt == waysIds.end()) {
141  // warning already given
142  continue;
143  }
144  // find directional edge (OSM ways are bidirectional)
145  const std::vector<long long int>* const way = line->getWayNodes(stop->getOrigEdgeId());
146  if (way == nullptr) {
147  WRITE_WARNINGF(TL("Cannot assign stop '%' on edge '%' to pt line '%' (wayNodes not found). Ignoring!"),
148  stop->getID(), stop->getOrigEdgeId(), line->getLineID());
149  continue;
150  }
151 
152  int dir;
153  const std::vector<long long int>* wayPrev = nullptr;
154  if (waysIdsIt != waysIds.begin()) {
155  wayPrev = line->getWayNodes(*(waysIdsIt - 1));
156  }
157  const std::vector<long long int>* wayNext = nullptr;
158  if (waysIdsIt != (waysIds.end() - 1)) {
159  wayNext = line->getWayNodes(*(waysIdsIt + 1));
160  }
161  if (wayPrev == nullptr && wayNext == nullptr) {
162  WRITE_WARNINGF(TL("Cannot revise pt stop localization for incomplete pt line '%'. Ignoring!"), line->getLineID());
163  continue;
164  }
165  const long long int wayEnds = way->back();
166  const long long int wayBegins = way->front();
167  const long long int wayPrevEnds = wayPrev != nullptr ? wayPrev->back() : 0;
168  const long long int wayPrevBegins = wayPrev != nullptr ? wayPrev->front() : 0;
169  const long long int wayNextEnds = wayNext != nullptr ? wayNext->back() : 0;
170  const long long int wayNextBegins = wayNext != nullptr ? wayNext->front() : 0;
171  if (wayBegins == wayPrevEnds || wayBegins == wayPrevBegins || wayEnds == wayNextBegins || wayEnds == wayNextEnds) {
172  dir = FWD;
173  } else if (wayEnds == wayPrevBegins || wayEnds == wayPrevEnds || wayBegins == wayNextEnds || wayBegins == wayNextBegins) {
174  dir = BWD;
175  } else {
176  WRITE_WARNINGF(TL("Cannot revise pt stop localization for incomplete pt line '%'. Ignoring!"), line->getLineID());
177  continue;
178  }
179 
180  std::string edgeId = stop->getEdgeId();
181  NBEdge* current = ec.getByID(edgeId);
182  int assignedTo = edgeId.at(0) == '-' ? BWD : FWD;
183 
184  if (dir != assignedTo) {
185  NBEdge* reverse = NBPTStopCont::getReverseEdge(current);
186  if (reverse == nullptr) {
187  WRITE_WARNINGF(TL("Could not re-assign PT stop '%', probably broken osm file."), stop->getID());
188  continue;
189  }
190  if (stop->getLines().size() > 0) {
191  std::shared_ptr<NBPTStop> reverseStop = sc.getReverseStop(stop, ec);
192  sc.insert(reverseStop);
193  line->replaceStop(stop, reverseStop);
194  stop = reverseStop;
195  } else {
196  WRITE_WARNINGF(TL("PT stop '%' has been moved to edge '%'."), stop->getID(), reverse->getID());
197  }
198  stop->setEdgeId(reverse->getID(), ec);
199  }
200  stop->addLine(line->getRef());
201  }
202 }
203 
204 
206  const std::vector<std::string>& waysIds = line->getWays();
207  for (std::shared_ptr<NBPTStop> stop : line->getStops()) {
208  //get the corresponding and one of the two adjacent ways
209  stop = findWay(line, stop, ec, sc);
210  if (stop == nullptr) {
211  // warning already given
212  continue;
213  }
214  auto waysIdsIt = std::find(waysIds.begin(), waysIds.end(), stop->getOrigEdgeId());
215  if (waysIdsIt == waysIds.end()) {
216  // warning already given
217  continue;
218  }
219  stop->addLine(line->getRef());
220  }
221 }
222 
223 
224 std::shared_ptr<NBPTStop>
225 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  if (stop->isLoose()) {
233  // find closest edge in route
234  double minDist = std::numeric_limits<double>::max();
235  NBEdge* best = nullptr;
236  for (NBEdge* edge : line->getRoute()) {
237  const double dist = edge->getLaneShape(0).distance2D(stop->getPosition());
238  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  if (minDist < OptionsCont::getOptions().getFloat("ptline.match-dist")) {
251  const std::string wayID = getWayID(best->getID());
252  if (stop->getEdgeId() == "") {
253  stop->setEdgeId(best->getID(), ec);
254  stop->setOrigEdgeId(wayID);
255  } 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  std::shared_ptr<NBPTStop> newStop = sc.findStop(wayID, stop->getPosition());
259  if (newStop == nullptr) {
260  newStop = std::make_shared<NBPTStop>(stop->getID() + "@" + line->getLineID(), stop->getPosition(), best->getID(), wayID, stop->getLength(), stop->getName(), stop->getPermissions());
261  newStop->setEdgeId(best->getID(), ec); // trigger lane assignment
262  sc.insert(newStop);
263  }
264  line->replaceStop(stop, newStop);
265  stop = newStop;
266  }
267  } else {
268  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  for (; waysIdsIt != waysIds.end(); waysIdsIt++) {
276  if ((*waysIdsIt) == stop->getOrigEdgeId()) {
277  break;
278  }
279  }
280 
281  if (waysIdsIt == waysIds.end()) {
282  // stop edge not found, try additional edges
283  for (auto& edgeCand : stop->getAdditionalEdgeCandidates()) {
284  bool found = false;
285  waysIdsIt = waysIds.begin();
286  for (; waysIdsIt != waysIds.end(); waysIdsIt++) {
287  if ((*waysIdsIt) == edgeCand.first) {
288  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  if (waysIdsIt == waysIds.end()) {
300  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 
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  for (auto it3 = pTLine->getWays().begin(); it3 != pTLine->getWays().end(); it3++) {
318 
319  int foundForward = 0;
320  if (cont.retrieve(*it3, false) != nullptr) {
321  currentWayEdges.push_back(cont.retrieve(*it3, false));
322  foundForward++;
323  } else {
324  int i = 0;
325  while (cont.retrieve(*it3 + "#" + std::to_string(i), true) != nullptr) {
326  if (cont.retrieve(*it3 + "#" + std::to_string(i), false)) {
327  currentWayEdges.push_back(cont.retrieve(*it3 + "#" + std::to_string(i), false));
328  foundForward++;
329  }
330  i++;
331  }
332  }
333 
334  int foundReverse = 0;
335  if (cont.retrieve("-" + *it3, false) != nullptr) {
336  currentWayMinusEdges.push_back(cont.retrieve("-" + *it3, false));
337  foundReverse++;
338  } else {
339  int i = 0;
340  while (cont.retrieve("-" + *it3 + "#" + std::to_string(i), true) != nullptr) {
341  if (cont.retrieve("-" + *it3 + "#" + std::to_string(i), false)) {
342  currentWayMinusEdges.insert(currentWayMinusEdges.end() - foundReverse,
343  cont.retrieve("-" + *it3 + "#" + std::to_string(i), false));
344  foundReverse++;
345  }
346  i++;
347  }
348  }
349  bool fakeMinus = false;
350  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  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  if (currentWayEdges.empty()) {
370  continue;
371  }
372  if (last == currentWayEdges.front()->getFromNode() && last != nullptr) {
373  if (!prevWayEdges.empty()) {
374  edges.insert(edges.end(), prevWayEdges.begin(), prevWayEdges.end());
375  prevWayEdges.clear();
376  prevWayMinusEdges.clear();
377  }
378  edges.insert(edges.end(), currentWayEdges.begin(), currentWayEdges.end());
379  last = currentWayEdges.back()->getToNode();
380  } else if (last == currentWayEdges.back()->getToNode() && last != nullptr) {
381  if (!prevWayEdges.empty()) {
382  edges.insert(edges.end(), prevWayEdges.begin(), prevWayEdges.end());
383  prevWayEdges.clear();
384  prevWayMinusEdges.clear();
385  }
386  if (currentWayMinusEdges.empty()) {
387  currentWayEdges.clear();
388  last = nullptr;
389  continue;
390  } else {
391  edges.insert(edges.end(), currentWayMinusEdges.begin(), currentWayMinusEdges.end());
392  if (fakeMinus) {
393  last = currentWayMinusEdges.back()->getFromNode();
394  } else {
395  last = currentWayMinusEdges.back()->getToNode();
396  }
397  }
398  } else if (first == currentWayEdges.front()->getFromNode() && first != nullptr) {
399  edges.insert(edges.end(), prevWayMinusEdges.begin(), prevWayMinusEdges.end());
400  edges.insert(edges.end(), currentWayEdges.begin(), currentWayEdges.end());
401  last = currentWayEdges.back()->getToNode();
402  prevWayEdges.clear();
403  prevWayMinusEdges.clear();
404  } else if (first == currentWayEdges.back()->getToNode() && first != nullptr) {
405  edges.insert(edges.end(), prevWayMinusEdges.begin(), prevWayMinusEdges.end());
406  if (currentWayMinusEdges.empty()) {
407  currentWayEdges.clear();
408  last = nullptr;
409  prevWayEdges.clear();
410  prevWayMinusEdges.clear();
411  continue;
412  } else {
413  edges.insert(edges.end(), currentWayMinusEdges.begin(), currentWayMinusEdges.end());
414  last = currentWayMinusEdges.back()->getToNode();
415  prevWayEdges.clear();
416  prevWayMinusEdges.clear();
417  }
418  } else {
419  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  } else if (pTLine->getWays().size() == 1) {
428  if (currentWayEdges.size() > 0) {
429  edges.insert(edges.end(), currentWayEdges.begin(), currentWayEdges.end());
430  } else {
431  edges.insert(edges.end(), currentWayMinusEdges.begin(), currentWayMinusEdges.end());
432  }
433  }
434  prevWayEdges = currentWayEdges;
435  prevWayMinusEdges = currentWayMinusEdges;
436  if (!prevWayEdges.empty()) {
437  first = prevWayEdges.front()->getFromNode();
438  last = prevWayEdges.back()->getToNode();
439  } else {
440  first = nullptr;
441  last = nullptr;
442  }
443  }
444  currentWayEdges.clear();
445  currentWayMinusEdges.clear();
446  }
447  pTLine->setEdges(edges);
448 }
449 
450 
451 void
452 NBPTLineCont::replaceEdge(const std::string& edgeID, const EdgeVector& replacement) {
453  //std::cout << " replaceEdge " << edgeID << " replacement=" << toString(replacement) << "\n";
454  if (myPTLines.size() > 0 && myPTLineLookup.size() == 0) {
455  // init lookup once
456  for (auto& item : myPTLines) {
457  for (const NBEdge* e : item.second->getRoute()) {
458  myPTLineLookup[e->getID()].insert(item.second);
459  }
460  }
461  }
462  for (NBPTLine* line : myPTLineLookup[edgeID]) {
463  line->replaceEdge(edgeID, replacement);
464  for (const NBEdge* e : replacement) {
465  myPTLineLookup[e->getID()].insert(line);
466  }
467  }
468  myPTLineLookup.erase(edgeID);
469 }
470 
471 
472 std::set<std::string>&
474  return myServedPTStops;
475 }
476 
477 
478 void
480  std::map<std::string, SUMOVehicleClass> types;
481  types["bus"] = SVC_BUS;
482  types["tram"] = SVC_TRAM;
483  types["train"] = SVC_RAIL;
484  types["subway"] = SVC_RAIL_URBAN;
485  types["light_rail"] = SVC_RAIL_URBAN;
486  types["monorail"] = SVC_RAIL_URBAN;
487  types["aerialway"] = SVC_RAIL_URBAN;
488  types["ferry"] = SVC_SHIP;
489 
491  ec.getAllRouterEdges(), true, &NBRouterEdge::getTravelTimeStatic, nullptr, true);
492 
493  for (auto& item : myPTLines) {
494  NBPTLine* line = item.second;
495  std::vector<std::shared_ptr<NBPTStop> > stops = line->getStops();
496  if (stops.size() < 2) {
497  continue;
498  }
499  if (types.count(line->getType()) == 0) {
500  WRITE_WARNINGF(TL("Could not determine vehicle class for public transport line of type '%'."), line->getType());
501  continue;
502  }
503  NBVehicle veh(line->getRef(), types[line->getType()]);
504  std::vector<std::shared_ptr<NBPTStop> > newStops;
505  std::shared_ptr<NBPTStop> from = nullptr;
506  for (auto it = stops.begin(); it != stops.end(); ++it) {
507  std::shared_ptr<NBPTStop> to = *it;
508  std::shared_ptr<NBPTStop> used = *it;
509  if (to->getBidiStop() != nullptr) {
510  double best = std::numeric_limits<double>::max();
511  std::shared_ptr<NBPTStop> to2 = to->getBidiStop();
512  if (from == nullptr) {
513  if ((it + 1) != stops.end()) {
514  from = to;
515  std::shared_ptr<NBPTStop> from2 = to2;
516  to = *(it + 1);
517  const double c1 = getCost(ec, *router, from, to, &veh);
518  const double c2 = getCost(ec, *router, from2, to, &veh);
519  //std::cout << " from=" << from->getID() << " to=" << to->getID() << " c1=" << MIN2(10000.0, c1) << "\n";
520  //std::cout << " from2=" << from2->getID() << " to=" << to->getID() << " c2=" << MIN2(10000.0, c2) << "\n";
521  best = c1;
522  if (to->getBidiStop() != nullptr) {
523  to2 = to->getBidiStop();
524  const double c3 = getCost(ec, *router, from, to2, &veh);
525  const double c4 = getCost(ec, *router, from2, to2, &veh);
526  //std::cout << " from=" << from->getID() << " to2=" << to2->getID() << " c3=" << MIN2(10000.0, c3) << "\n";
527  //std::cout << " from2=" << from2->getID() << " to2=" << to2->getID() << " c4=" << MIN2(10000.0, c4) << "\n";
528  if (c2 < best) {
529  used = from2;
530  best = c2;
531  }
532  if (c3 < best) {
533  used = from;
534  best = c3;
535  }
536  if (c4 < best) {
537  used = from2;
538  best = c4;
539  }
540  } else {
541  if (c2 < c1) {
542  used = from2;
543  best = c2;
544  } else {
545  best = c1;
546  }
547  }
548  }
549  } else {
550  const double c1 = getCost(ec, *router, from, to, &veh);
551  const double c2 = getCost(ec, *router, from, to2, &veh);
552  //std::cout << " from=" << from->getID() << " to=" << to->getID() << " c1=" << MIN2(10000.0, c1) << "\n";
553  //std::cout << " from=" << from->getID() << " t2o=" << to2->getID() << " c2=" << MIN2(10000.0, c2) << "\n";
554  if (c2 < c1) {
555  used = to2;
556  best = c2;
557  } else {
558  best = c1;
559  }
560 
561  }
562  if (best < std::numeric_limits<double>::max()) {
563  from = used;
564  } else {
565  WRITE_WARNINGF(TL("Could not determine direction for line '%' at stop '%'."), line->getLineID(), used->getID());
566  }
567  }
568  from = used;
569  newStops.push_back(used);
570  }
571  assert(stops.size() == newStops.size());
572  line->replaceStops(newStops);
573  }
574  delete router;
575 }
576 
577 
578 void
580  for (auto& item : myPTLines) {
581  item.second->removeInvalidEdges(ec);
582  }
583 }
584 
585 
586 void
588  for (auto& item : myPTLines) {
589  NBPTLine* line = item.second;
590  const std::vector<NBEdge*>& route = line->getRoute();
591  const SUMOVehicleClass svc = line->getVClass();
592  for (int i = 1; i < (int)route.size(); i++) {
593  NBEdge* e1 = route[i - 1];
594  NBEdge* e2 = route[i];
595  std::vector<NBEdge::Connection> cons = e1->getConnectionsFromLane(-1, e2, -1);
596  if (cons.size() == 0) {
597  //WRITE_WARNINGF(TL("Disconnected ptline '%' between edge '%' and edge '%'"), line->getLineID(), e1->getID(), e2->getID());
598  } else {
599  bool ok = false;
600  for (const auto& c : cons) {
601  if ((e1->getPermissions(c.fromLane) & svc) == svc) {
602  ok = true;
603  break;
604  }
605  }
606  if (!ok) {
607  int lane = cons[0].fromLane;
608  e1->setPermissions(e1->getPermissions(lane) | svc, lane);
609  }
610  }
611  }
612  }
613 }
614 
615 
616 double
618  const std::shared_ptr<NBPTStop> from, const std::shared_ptr<NBPTStop> to, const NBVehicle* veh) {
619  NBEdge* fromEdge = ec.getByID(from->getEdgeId());
620  NBEdge* toEdge = ec.getByID(to->getEdgeId());
621  if (fromEdge == nullptr || toEdge == nullptr) {
622  return std::numeric_limits<double>::max();
623  } else if (fromEdge == toEdge) {
624  if (from->getEndPos() <= to->getEndPos()) {
625  return to->getEndPos() - from->getEndPos();
626  } else {
627  return std::numeric_limits<double>::max();
628  }
629  } else if (fromEdge->getBidiEdge() == toEdge) {
630  return std::numeric_limits<double>::max();
631  }
632  std::vector<const NBRouterEdge*> route;
633  router.compute(fromEdge, toEdge, veh, 0, route);
634  if (route.size() == 0) {
635  return std::numeric_limits<double>::max();
636  } else {
637  return router.recomputeCosts(route, veh, 0);
638  }
639 }
640 
641 
642 std::string
643 NBPTLineCont::getWayID(const std::string& edgeID) {
644  std::size_t found = edgeID.rfind("#");
645  std::string result = edgeID;
646  if (found != std::string::npos) {
647  result = edgeID.substr(0, found);
648  }
649  if (result[0] == '-') {
650  result = result.substr(1);
651  }
652  return result;
653 }
654 
655 
656 /****************************************************************************/
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:296
#define TL(string)
Definition: MsgHandler.h:315
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:35
#define DEBUGLINEID
#define DEBUGSTOPID
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permission is a railway edge.
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_SHIP
is an arbitrary ship
@ SVC_RAIL
vehicle is a not electrified rail
@ SVC_RAIL_URBAN
vehicle is a city rail
@ SVC_TRAM
vehicle is a light rail
@ SVC_BUS
vehicle is a bus
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
Computes the shortest path through a network using the Dijkstra algorithm.
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:59
NBEdge * getByID(const std::string &edgeID) const
Returns the edge with id if it exists.
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
Definition: NBEdgeCont.cpp:281
RouterEdgeVector getAllRouterEdges() const
return all router edges
The representation of a single edge during network building.
Definition: NBEdge.h:92
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition: NBEdge.cpp:4306
void setPermissions(SVCPermissions permissions, int lane=-1)
set allowed/disallowed classes for the given lane or for all lanes if -1 is given
Definition: NBEdge.cpp:4269
const std::string & getID() const
Definition: NBEdge.h:1522
std::vector< Connection > getConnectionsFromLane(int lane, const NBEdge *to=nullptr, int toLane=-1) const
Returns connections from a given lane.
Definition: NBEdge.cpp:1252
const NBEdge * getBidiEdge() const
Definition: NBEdge.h:1508
const PositionVector & getLaneShape(int i) const
Returns the shape of the nth lane.
Definition: NBEdge.cpp:967
Represents a single node (junction) during network building.
Definition: NBNode.h:66
static double getCost(const NBEdgeCont &ec, SUMOAbstractRouter< NBRouterEdge, NBVehicle > &router, const std::shared_ptr< NBPTStop > from, const std::shared_ptr< NBPTStop > to, const NBVehicle *veh)
void reviseStops(NBPTLine *line, const NBEdgeCont &ec, NBPTStopCont &sc)
find directional edge for all stops of the line
void fixPermissions()
ensure that all turn lanes have sufficient permissions
void process(NBEdgeCont &ec, NBPTStopCont &sc, bool routeOnly=false)
std::set< std::string > myServedPTStops
Definition: NBPTLineCont.h:81
~NBPTLineCont()
destructor
std::map< std::string, NBPTLine * > myPTLines
The map of names to pt lines.
Definition: NBPTLineCont.h:68
std::shared_ptr< NBPTStop > findWay(NBPTLine *line, std::shared_ptr< NBPTStop > stop, const NBEdgeCont &ec, NBPTStopCont &sc) const
NBPTLine * retrieve(const std::string &lineID)
void replaceEdge(const std::string &edgeID, const EdgeVector &replacement)
replace the edge with the given edge list in all lines
std::set< std::string > & getServedPTStops()
void constructRoute(NBPTLine *myPTLine, const NBEdgeCont &cont)
bool insert(NBPTLine *ptLine)
insert new line
void removeInvalidEdges(const NBEdgeCont &ec)
filter out edges that were removed due to –geometry.remove
void fixBidiStops(const NBEdgeCont &ec)
select the correct stop on superposed rail edges
static const int BWD
Definition: NBPTLineCont.h:65
static const int FWD
Definition: NBPTLineCont.h:64
static std::string getWayID(const std::string &edgeID)
void reviseSingleWayStops(NBPTLine *line, const NBEdgeCont &ec, NBPTStopCont &sc)
std::map< std::string, std::set< NBPTLine * > > myPTLineLookup
The map of edge ids to lines that use this edge in their route.
Definition: NBPTLineCont.h:89
void replaceStop(std::shared_ptr< NBPTStop > oldStop, std::shared_ptr< NBPTStop > newStop)
replace the given stop
Definition: NBPTLine.cpp:279
void replaceStops(std::vector< std::shared_ptr< NBPTStop > > stops)
Definition: NBPTLine.h:74
const std::vector< long long int > * getWayNodes(std::string wayId)
Definition: NBPTLine.cpp:132
void deleteInvalidStops(const NBEdgeCont &ec, const NBPTStopCont &sc)
remove invalid stops from the line
Definition: NBPTLine.cpp:307
const std::string & getLineID() const
Definition: NBPTLine.h:51
const std::string & getType() const
Definition: NBPTLine.h:59
const std::vector< std::string > & getWays() const
Definition: NBPTLine.h:118
SUMOVehicleClass getVClass() const
Definition: NBPTLine.h:89
const std::vector< NBEdge * > & getRoute() const
Definition: NBPTLine.cpp:174
const std::string & getName() const
Definition: NBPTLine.h:55
const std::string & getRef() const
get line reference (not unique)
Definition: NBPTLine.h:70
const std::vector< std::shared_ptr< NBPTStop > > & getStops()
Definition: NBPTLine.cpp:68
void setEdges(const std::vector< NBEdge * > &edges)
Definition: NBPTLine.cpp:141
Container for public transport stops during the net building process.
Definition: NBPTStopCont.h:44
static NBEdge * getReverseEdge(NBEdge *edge)
std::shared_ptr< NBPTStop > getReverseStop(std::shared_ptr< NBPTStop > pStop, const NBEdgeCont &ec)
std::shared_ptr< NBPTStop > findStop(const std::string &origEdgeID, Position pos, double threshold=1) const
bool insert(std::shared_ptr< NBPTStop > ptStop, bool floating=false)
Inserts a node into the map.
static double getTravelTimeStatic(const NBRouterEdge *const edge, const NBVehicle *const, double)
Definition: NBEdge.h:82
A vehicle as used by router.
Definition: NBVehicle.h:42
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
Definition: Named.h:67
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:60
double distance2D(const Position &p, bool perpendicular=false) const
closest 2D-distance to point p (or -1 if perpendicular is true and the point is beyond this vector)
virtual bool compute(const E *from, const E *to, const V *const vehicle, SUMOTime msTime, std::vector< const E * > &into, bool silent=false)=0
Builds the route between the given edges using the minimum effort at the given time The definition of...
virtual double recomputeCosts(const std::vector< const E * > &edges, const V *const v, SUMOTime msTime, double *lengthp=nullptr) const
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
Definition: json.hpp:21838