Line data Source code
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 FlippedEdge.h
15 : /// @author Ruediger Ebendt
16 : /// @date 01.12.2023
17 : ///
18 : // Extension of ReversedEdge, which is a wrapper around a ROEdge
19 : // or an MSEdge used for backward search. In contrast to reversed
20 : // edges, flipped edges have flipped nodes instead of standard nodes.
21 : // Introduced for the arc flag router.
22 : /****************************************************************************/
23 : #pragma once
24 : #include <config.h>
25 : #include <utils/common/SUMOVehicleClass.h>
26 : #ifdef HAVE_FOX
27 : #include <utils/foxtools/MsgHandlerSynchronized.h>
28 : #endif
29 : #include "ReversedEdge.h"
30 :
31 :
32 : // ===========================================================================
33 : // class declarations
34 : // ===========================================================================
35 : template<class E, class N, class V>
36 : class FlippedNode;
37 :
38 : // ===========================================================================
39 : // class definitions
40 : // ===========================================================================
41 : /// @brief The edge type representing backward edges with flipped nodes
42 : template<class E, class N, class V>
43 : class FlippedEdge : public ReversedEdge<E, V> {
44 : public:
45 :
46 : typedef std::vector<std::pair<const FlippedEdge<E, N, V>*, const FlippedEdge<E, N, V>*> > ConstFlippedEdgePairVector;
47 :
48 : /** @brief Constructor
49 : * @param[in] originalEdge The original (forward) edge
50 : */
51 0 : FlippedEdge(const E* originalEdge) :
52 : ReversedEdge<E, V>(originalEdge),
53 0 : myFromJunction(originalEdge->getToJunction()->getFlippedRoutingNode()),
54 0 : myToJunction(originalEdge->getFromJunction()->getFlippedRoutingNode())
55 0 : {}
56 :
57 : /// @brief Destructor
58 0 : ~FlippedEdge() {}
59 :
60 : /// @brief Initialize the flipped edge
61 : void init();
62 :
63 : /// @brief Returns the from-junction
64 : const FlippedNode<E, N, V>* getFromJunction() const {
65 0 : return myFromJunction;
66 : }
67 :
68 : /// @brief Returns the to-junction
69 : const FlippedNode<E, N, V>* getToJunction() const {
70 0 : return myToJunction;
71 : }
72 :
73 : /** @brief Returns the time for travelling on the given edge with the given vehicle at the given time
74 : * @param[in] edge The edge
75 : * @param[in] veh The vehicle
76 : * @param[in] time The time
77 : * @return The time for travelling on the given edge with the given vehicle at the given time
78 : */
79 0 : static double getTravelTimeStatic(const FlippedEdge<E, N, V>* const edge, const V* const veh, double time) {
80 0 : return edge->getOriginalEdge()->getTravelTime(veh, time);
81 : }
82 :
83 : /** @brief Returns the randomized time for travelling on the given edge with the given vehicle at the given time
84 : * @param[in] edge The edge
85 : * @param[in] veh The vehicle
86 : * @param[in] time The time
87 : * @return The randomized time for travelling on the given edge with the given vehicle at the given time
88 : */
89 0 : static double getTravelTimeStaticRandomized(const FlippedEdge<E, N, V>* const edge, const V* const veh, double time) {
90 0 : return edge->getOriginalEdge()->getTravelTimeStaticRandomized(edge->getOriginalEdge(), veh, time);
91 : }
92 :
93 : /** @brief Returns the via successors
94 : * @param[in] vClass The vehicle class
95 : * @param[in] ignoreTransientPermissions Unused parameter
96 : * @return The via successors
97 : */
98 0 : const ConstFlippedEdgePairVector& getViaSuccessors(SUMOVehicleClass vClass = SVC_IGNORING, bool ignoreTransientPermissions = false) const {
99 : UNUSED_PARAMETER(ignoreTransientPermissions); // @todo this should be changed (somewhat hidden by #14756)
100 0 : if (vClass == SVC_IGNORING || this->getOriginalEdge()->isTazConnector()) { // || !MSNet::getInstance()->hasPermissions()) {
101 0 : return myViaSuccessors;
102 : }
103 : #ifdef HAVE_FOX
104 0 : FXMutexLock lock(mySuccessorMutex);
105 : #endif
106 : auto i = myClassesViaSuccessorMap.find(vClass);
107 0 : if (i != myClassesViaSuccessorMap.end()) {
108 : // can use cached value
109 0 : return i->second;
110 : }
111 : // instantiate vector
112 0 : ConstFlippedEdgePairVector& result = myClassesViaSuccessorMap[vClass];
113 : // this vClass is requested for the first time. rebuild all successors
114 0 : for (const auto& viaPair : myViaSuccessors) {
115 0 : if (viaPair.first->getOriginalEdge()->isTazConnector()
116 0 : || viaPair.first->getOriginalEdge()->isConnectedTo(*(this->getOriginalEdge()), vClass)) {
117 0 : result.push_back(viaPair);
118 : }
119 : }
120 : return result;
121 : }
122 :
123 : /** @brief Returns the bidirectional edge
124 : * @return The bidirectional edge
125 : */
126 : const FlippedEdge<E, N, V>* getBidiEdge() const {
127 : return this->getOriginalEdge()->getBidiEdge()->getFlippedRoutingEdge();
128 : }
129 :
130 : /** @brief Returns the distance to another flipped edge
131 : * param[in] other The other flipped edge
132 : * param[in] doBoundaryEstimate The boolean flag indicating whether the distance is estimated using both boundaries or not
133 : * @return The distance to another flipped edge
134 : */
135 : double getDistanceTo(const FlippedEdge<E, N, V>* other, const bool doBoundaryEstimate = false) const {
136 0 : return this->getOriginalEdge()->getDistanceTo(other->getOriginalEdge(), doBoundaryEstimate);
137 : }
138 :
139 : /** @brief Returns the minimum travel time
140 : * @param[in] veh The vehicle
141 : * @return The minimum travel time
142 : */
143 : double getMinimumTravelTime(const V* const veh) const {
144 0 : return this->getOriginalEdge()->getMinimumTravelTime(veh);
145 : }
146 :
147 : /** @brief Returns the time penalty
148 : * @return The time penalty
149 : */
150 : double getTimePenalty() const {
151 : return this->getOriginalEdge()->getTimePenalty();
152 : }
153 :
154 : /** @brief Returns a boolean flag indicating whether this edge has loaded travel times or not
155 : * @return true iff this edge has loaded travel times
156 : */
157 : bool hasLoadedTravelTimes() const {
158 : return this->getOriginalEdge()->hasLoadedTravelTimes();
159 : }
160 :
161 : /** @brief Returns the speed allowed on this edge
162 : * @return The speed allowed on this edge
163 : */
164 : double getSpeedLimit() const {
165 : return this->getOriginalEdge()->getSpeedLimit();
166 : }
167 :
168 : /** @brief Returns a lower bound on shape.length() / myLength
169 : * @note The bound is sufficient for the astar air-distance heuristic
170 : * @return A lower bound on shape.length() / myLength
171 : */
172 : double getLengthGeometryFactor() const {
173 0 : return this->getOriginalEdge()->getLengthGeometryFactor();
174 : }
175 :
176 : /** @brief Returns the edge priority (road class)
177 : * @return The edge priority (road class)
178 : */
179 : int getPriority() const {
180 : return this->getOriginalEdge()->getPriority();
181 : }
182 :
183 : protected:
184 : /// @brief The junctions for this edge
185 : FlippedNode<E, N, V>* myFromJunction;
186 : FlippedNode<E, N, V>* myToJunction;
187 :
188 : private:
189 : /// @brief The successors available for a given vClass
190 : mutable std::map<SUMOVehicleClass, ConstFlippedEdgePairVector> myClassesViaSuccessorMap;
191 : mutable ConstFlippedEdgePairVector myViaSuccessors;
192 :
193 : #ifdef HAVE_FOX
194 : /// @brief Mutex for accessing successor edges
195 : mutable FXMutex mySuccessorMutex;
196 : #endif
197 : };
198 :
199 : // ===========================================================================
200 : // method definitions
201 : // ===========================================================================
202 :
203 : template<class E, class N, class V>
204 0 : void FlippedEdge<E, N, V>::init() {
205 0 : if (!this->getOriginalEdge()->isInternal()) {
206 0 : for (const auto& viaPair : this->getOriginalEdge()->getViaSuccessors()) {
207 0 : const FlippedEdge<E, N, V>* revSource = viaPair.first->getFlippedRoutingEdge();
208 0 : const E* via = viaPair.second;
209 : const FlippedEdge<E, N, V>* preVia = nullptr;
210 0 : while (via != nullptr && via->isInternal()) {
211 0 : via->getFlippedRoutingEdge()->myViaSuccessors.push_back(std::make_pair(this, preVia));
212 0 : preVia = via->getFlippedRoutingEdge();
213 0 : via = via->getViaSuccessors().front().second;
214 : }
215 0 : revSource->myViaSuccessors.push_back(std::make_pair(this, preVia));
216 : }
217 : }
218 0 : }
|