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 PublicTransportEdge.h
15 : /// @author Michael Behrisch
16 : /// @date Mon, 03 March 2014
17 : ///
18 : // The PublicTransportEdge is a special intermodal edge connecting the stop edges with scheduled traffic
19 : /****************************************************************************/
20 : #pragma once
21 : #include <config.h>
22 :
23 : #include "IntermodalEdge.h"
24 :
25 :
26 : // ===========================================================================
27 : // class definitions
28 : // ===========================================================================
29 : /// @brief the public transport edge type connecting the stop edges
30 : template<class E, class L, class N, class V>
31 : class PublicTransportEdge : public IntermodalEdge<E, L, N, V> {
32 : private:
33 3674 : struct Schedule {
34 1837 : Schedule(const std::string& _id, const SUMOTime _begin, const int _repetitionNumber, const SUMOTime _period, const SUMOTime _travelTime)
35 5511 : : ids({
36 : _id
37 1837 : }), begin(_begin), repetitionNumber(_repetitionNumber), period(_period), travelTime(_travelTime) {}
38 : // the id of the vehicle or flow from which this schedule is generated
39 : std::vector<std::string> ids;
40 : const SUMOTime begin;
41 : int repetitionNumber;
42 : // the repetition period for a flow or -1 for a vehicle
43 : SUMOTime period;
44 : const SUMOTime travelTime;
45 : };
46 :
47 : public:
48 1829 : PublicTransportEdge(const std::string id, int numericalID, const IntermodalEdge<E, L, N, V>* entryStop, const E* endEdge, const std::string& line, const double length) :
49 5487 : IntermodalEdge<E, L, N, V>(line + ":" + (id != "" ? id : endEdge->getID()), numericalID, endEdge, line, length), myEntryStop(entryStop) { }
50 :
51 3991 : bool includeInRoute(bool /* allEdges */) const {
52 3991 : return true;
53 : }
54 :
55 53147 : bool prohibits(const IntermodalTrip<E, N, V>* const trip) const {
56 53147 : return (trip->modeSet & SVC_BUS) == 0;
57 : }
58 :
59 : const IntermodalEdge<E, L, N, V>* getEntryStop() const {
60 55 : return myEntryStop;
61 : }
62 :
63 : bool hasSchedule(const SUMOTime begin) const {
64 : return mySchedules.find(begin) != mySchedules.end();
65 : }
66 :
67 1929 : void addSchedule(const std::string id, const SUMOTime begin, const int repetitionNumber, const SUMOTime period, const SUMOTime travelTime) {
68 : // try to merge with existing vehicle or flow
69 : bool found = false;
70 1937 : for (auto& it : mySchedules) {
71 : Schedule& s = it.second;
72 100 : if (travelTime == s.travelTime) {
73 100 : if (repetitionNumber == -1 && s.repetitionNumber == 1) {
74 76 : if (begin > s.begin) {
75 68 : s.period = begin - s.begin;
76 : found = true;
77 : }
78 24 : } else if (begin == s.begin + s.repetitionNumber * s.period) {
79 : found = true;
80 : }
81 : if (found) {
82 92 : s.repetitionNumber += MAX2(repetitionNumber, 1);
83 92 : s.ids.push_back(id);
84 : break;
85 : }
86 : }
87 : }
88 1929 : if (!found) {
89 3674 : mySchedules.insert(std::make_pair(begin, Schedule(id, begin, MAX2(repetitionNumber, 1), MAX2<SUMOTime>(period, 1), travelTime)));
90 : }
91 1929 : }
92 :
93 56630 : double getTravelTime(const IntermodalTrip<E, N, V>* const /* trip */, double time) const {
94 : SUMOTime minArrival = SUMOTime_MAX;
95 56630 : const SUMOTime step = TIME2STEPS(time);
96 113267 : for (typename std::multimap<SUMOTime, Schedule>::const_iterator it = mySchedules.begin(); it != mySchedules.end(); ++it) {
97 : const Schedule& s = it->second;
98 56637 : if (it->first > minArrival) {
99 : break;
100 : }
101 56637 : const SUMOTime offset = MAX2<SUMOTime>(0, step - s.begin);
102 56637 : int running = (int)(offset / s.period);
103 56637 : if (offset % s.period != 0) {
104 25707 : running++;
105 : }
106 56637 : if (running < s.repetitionNumber) {
107 30153 : const SUMOTime nextDepart = s.begin + running * s.period;
108 30153 : minArrival = MIN2(nextDepart + s.travelTime, minArrival);
109 : //std::cout << " edge=" << myEntryStop->getID() << "->" << this->getID() << " beg=" << s.begin << " end=" << s.end
110 : // << " atTime=" << time
111 : // << " running=" << running << " nextDepart=" << nextDepart
112 : // << " minASec=" << minArrivalSec << " travelTime=" << minArrivalSec - time << "\n";
113 : }
114 : }
115 56630 : if (minArrival != SUMOTime_MAX) {
116 30146 : return STEPS2TIME(minArrival - step);
117 : } else {
118 : // indicate failure
119 : return std::numeric_limits<double>::max();
120 : }
121 : }
122 :
123 3698 : double getIntended(const double time, std::string& intended) const {
124 : /// @note: duplicates some code of getTravelTime()
125 : SUMOTime minArrival = SUMOTime_MAX;
126 : double bestDepartTime = std::numeric_limits<double>::max();
127 3698 : const SUMOTime step = TIME2STEPS(time);
128 7396 : for (typename std::multimap<SUMOTime, Schedule>::const_iterator it = mySchedules.begin(); it != mySchedules.end(); ++it) {
129 : const Schedule& s = it->second;
130 3698 : if (it->first > minArrival) {
131 : break;
132 : }
133 3698 : const SUMOTime offset = MAX2<SUMOTime>(0, step - s.begin);
134 3698 : int running = (int)(offset / s.period);
135 3698 : if (offset % s.period != 0) {
136 1683 : running++;
137 : }
138 3698 : if (running < s.repetitionNumber) {
139 3698 : const SUMOTime nextDepart = s.begin + running * s.period;
140 3698 : if (nextDepart + s.travelTime < minArrival) {
141 : minArrival = nextDepart + s.travelTime;
142 3698 : bestDepartTime = STEPS2TIME(nextDepart);
143 : // see naming scheme inMSInsertionControl::determineCandidates()
144 3698 : if (s.ids.size() == 1 || running >= (int)s.ids.size()) {
145 11226 : intended = s.repetitionNumber == 1 ? s.ids[0] : s.ids[0] + "." + toString(running);
146 : } else {
147 77 : intended = s.ids[running];
148 : }
149 : }
150 : }
151 : }
152 3698 : return bestDepartTime;
153 : }
154 :
155 : private:
156 : std::multimap<SUMOTime, Schedule> mySchedules;
157 : const IntermodalEdge<E, L, N, V>* const myEntryStop;
158 :
159 : };
|