Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2002-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 MSRoute.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Friedemann Wesner
17 : /// @author Michael Behrisch
18 : /// @author Jakob Erdmann
19 : /// @date Sept 2002
20 : ///
21 : // A vehicle route
22 : /****************************************************************************/
23 : #include <config.h>
24 :
25 : #include <cassert>
26 : #include <algorithm>
27 : #include <limits>
28 : #include <utils/common/FileHelpers.h>
29 : #include <utils/common/RGBColor.h>
30 : #include <utils/iodevices/OutputDevice.h>
31 : #include "MSEdge.h"
32 : #include "MSLane.h"
33 : #include "MSRoute.h"
34 :
35 :
36 : // ===========================================================================
37 : // static member variables
38 : // ===========================================================================
39 : MSRoute::RouteDict MSRoute::myDict;
40 : MSRoute::RouteDistDict MSRoute::myDistDict;
41 : #ifdef HAVE_FOX
42 : FXMutex MSRoute::myDictMutex(true);
43 : #endif
44 :
45 :
46 : // ===========================================================================
47 : // member method definitions
48 : // ===========================================================================
49 1874791 : MSRoute::MSRoute(const std::string& id,
50 : const ConstMSEdgeVector& edges,
51 : const bool isPermanent, const RGBColor* const c,
52 : const std::vector<SUMOVehicleParameter::Stop>& stops,
53 : SUMOTime replacedTime,
54 1874791 : int replacedIndex) :
55 3749582 : Named(id), myEdges(edges), myAmPermanent(isPermanent),
56 1874791 : myColor(c),
57 1874791 : myPeriod(0),
58 1874791 : myCosts(-1),
59 1874791 : mySavings(0),
60 1874791 : myReroute(false),
61 1874791 : myStops(stops),
62 1874791 : myReplacedTime(replacedTime),
63 1874791 : myReplacedIndex(replacedIndex)
64 1874791 : {}
65 :
66 :
67 3519217 : MSRoute::~MSRoute() {
68 1874744 : delete myColor;
69 3519217 : }
70 :
71 :
72 : MSRouteIterator
73 1433989039 : MSRoute::begin() const {
74 1433989039 : return myEdges.begin();
75 : }
76 :
77 :
78 : MSRouteIterator
79 4541833244 : MSRoute::end() const {
80 4541833244 : return myEdges.end();
81 : }
82 :
83 :
84 : int
85 16940461 : MSRoute::size() const {
86 16940461 : return (int)myEdges.size();
87 : }
88 :
89 :
90 : const MSEdge*
91 26185308 : MSRoute::getLastEdge() const {
92 : assert(myEdges.size() > 0);
93 26185308 : return myEdges.back();
94 : }
95 :
96 :
97 : void
98 1299213 : MSRoute::checkRemoval() const {
99 : #ifdef HAVE_FOX
100 : FXMutexLock f(myDictMutex);
101 : #endif
102 1299213 : if (!myAmPermanent) {
103 : myDict.erase(getID());
104 : }
105 1299213 : }
106 :
107 :
108 : bool
109 1644777 : MSRoute::dictionary(const std::string& id, ConstMSRoutePtr route) {
110 : #ifdef HAVE_FOX
111 : FXMutexLock f(myDictMutex);
112 : #endif
113 1644777 : if (myDict.find(id) == myDict.end() && myDistDict.find(id) == myDistDict.end()) {
114 1644630 : myDict[id] = route;
115 1644630 : return true;
116 : }
117 : return false;
118 : }
119 :
120 :
121 : bool
122 1832 : MSRoute::dictionary(const std::string& id, RandomDistributor<ConstMSRoutePtr>* const routeDist, const bool permanent) {
123 : #ifdef HAVE_FOX
124 : FXMutexLock f(myDictMutex);
125 : #endif
126 1832 : if (myDict.find(id) == myDict.end() && myDistDict.find(id) == myDistDict.end()) {
127 1832 : myDistDict[id] = std::make_pair(routeDist, permanent);
128 1832 : return true;
129 : }
130 : return false;
131 : }
132 :
133 :
134 : ConstMSRoutePtr
135 5226823 : MSRoute::dictionary(const std::string& id, SumoRNG* rng) {
136 : #ifdef HAVE_FOX
137 : FXMutexLock f(myDictMutex);
138 : #endif
139 : RouteDict::iterator it = myDict.find(id);
140 5226823 : if (it == myDict.end()) {
141 : RouteDistDict::iterator it2 = myDistDict.find(id);
142 165414 : if (it2 == myDistDict.end() || it2->second.first->getOverallProb() == 0) {
143 : return nullptr;
144 : }
145 6258 : return it2->second.first->get(rng);
146 : }
147 : return it->second;
148 : }
149 :
150 :
151 : bool
152 4743058 : MSRoute::hasRoute(const std::string& id) {
153 : #ifdef HAVE_FOX
154 : FXMutexLock f(myDictMutex);
155 : #endif
156 4743058 : return myDict.find(id) != myDict.end();
157 : }
158 :
159 :
160 : RandomDistributor<ConstMSRoutePtr>*
161 15664 : MSRoute::distDictionary(const std::string& id) {
162 : #ifdef HAVE_FOX
163 : FXMutexLock f(myDictMutex);
164 : #endif
165 : RouteDistDict::iterator it2 = myDistDict.find(id);
166 15664 : if (it2 == myDistDict.end()) {
167 : return nullptr;
168 : }
169 2330 : return it2->second.first;
170 : }
171 :
172 :
173 : void
174 40275 : MSRoute::clear() {
175 : #ifdef HAVE_FOX
176 : FXMutexLock f(myDictMutex);
177 : #endif
178 40691 : for (RouteDistDict::iterator i = myDistDict.begin(); i != myDistDict.end(); ++i) {
179 832 : delete i->second.first;
180 : }
181 : myDistDict.clear();
182 : myDict.clear();
183 40275 : }
184 :
185 :
186 : void
187 458003 : MSRoute::checkDist(const std::string& id) {
188 : #ifdef HAVE_FOX
189 : FXMutexLock f(myDictMutex);
190 : #endif
191 : RouteDistDict::iterator it = myDistDict.find(id);
192 458003 : if (it != myDistDict.end() && !it->second.second) {
193 4735 : for (ConstMSRoutePtr rp : it->second.first->getVals()) {
194 : const MSRoute& r = *rp;
195 3319 : r.checkRemoval();
196 : }
197 2832 : delete it->second.first;
198 : myDistDict.erase(it);
199 : }
200 458003 : }
201 :
202 :
203 : void
204 260 : MSRoute::insertIDs(std::vector<std::string>& into) {
205 : #ifdef HAVE_FOX
206 : FXMutexLock f(myDictMutex);
207 : #endif
208 260 : into.reserve(myDict.size() + myDistDict.size() + into.size());
209 842 : for (RouteDict::const_iterator i = myDict.begin(); i != myDict.end(); ++i) {
210 582 : into.push_back((*i).first);
211 : }
212 1028 : for (RouteDistDict::const_iterator i = myDistDict.begin(); i != myDistDict.end(); ++i) {
213 768 : into.push_back((*i).first);
214 : }
215 260 : }
216 :
217 :
218 : int
219 285924 : MSRoute::writeEdgeIDs(OutputDevice& os, int firstIndex, int lastIndex, bool withInternal, SUMOVehicleClass svc) const {
220 : //std::cout << SIMTIME << " writeEdgeIDs " << getID() << " first=" << firstIndex << " lastIndex=" << lastIndex << " edges=" << toString(myEdges) << "\n";
221 285924 : if (lastIndex < 0) {
222 142744 : lastIndex = (int)myEdges.size();
223 : }
224 : int internal = 0;
225 1501586 : for (int i = firstIndex; i < lastIndex; i++) {
226 1215662 : os << myEdges[i]->getID() << ' ';
227 1215662 : if (withInternal && i + 1 < lastIndex) {
228 6 : const MSEdge* next = myEdges[i + 1];
229 6 : const MSEdge* edge = myEdges[i]->getInternalFollowingEdge(next, svc);
230 : // Take into account non-internal lengths until next non-internal edge
231 14 : while (edge != nullptr && edge->isInternal()) {
232 8 : os << edge->getID() << ' ';
233 8 : internal++;
234 8 : edge = edge->getInternalFollowingEdge(next, svc);
235 : }
236 : }
237 : }
238 285924 : return internal + lastIndex - firstIndex;
239 : }
240 :
241 :
242 : bool
243 0 : MSRoute::containsAnyOf(const MSEdgeVector& edgelist) const {
244 : MSEdgeVector::const_iterator i = edgelist.begin();
245 0 : for (; i != edgelist.end(); ++i) {
246 0 : if (contains(*i)) {
247 : return true;
248 : }
249 : }
250 : return false;
251 : }
252 :
253 :
254 : const MSEdge*
255 0 : MSRoute::operator[](int index) const {
256 0 : return myEdges[index];
257 : }
258 :
259 :
260 : void
261 425 : MSRoute::dict_saveState(OutputDevice& out) {
262 : #ifdef HAVE_FOX
263 : FXMutexLock f(myDictMutex);
264 : #endif
265 3617 : for (RouteDict::iterator it = myDict.begin(); it != myDict.end(); ++it) {
266 : ConstMSRoutePtr r = (*it).second;
267 3192 : out.openTag(SUMO_TAG_ROUTE);
268 : out.writeAttr(SUMO_ATTR_ID, r->getID());
269 3192 : out.writeAttr(SUMO_ATTR_STATE, r->myAmPermanent);
270 3192 : out.writeAttr(SUMO_ATTR_EDGES, r->myEdges);
271 3192 : if (r->myColor != nullptr) {
272 : out.writeAttr(SUMO_ATTR_COLOR, *r->myColor);
273 : }
274 3256 : for (auto stop : r->getStops()) {
275 64 : stop.write(out);
276 64 : }
277 6384 : out.closeTag();
278 : }
279 441 : for (const auto& item : myDistDict) {
280 16 : if (item.second.first->getVals().size() > 0) {
281 12 : out.openTag(SUMO_TAG_ROUTE_DISTRIBUTION).writeAttr(SUMO_ATTR_ID, item.first);
282 12 : out.writeAttr(SUMO_ATTR_STATE, item.second.second);
283 12 : std::ostringstream oss;
284 : bool space = false;
285 32 : for (const auto& route : item.second.first->getVals()) {
286 20 : if (space) {
287 8 : oss << " ";
288 : }
289 : oss << route->getID();
290 : space = true;
291 : }
292 12 : out.writeAttr(SUMO_ATTR_ROUTES, oss.str());
293 12 : out.writeAttr(SUMO_ATTR_PROBS, item.second.first->getProbs());
294 12 : out.closeTag();
295 12 : }
296 : }
297 425 : }
298 :
299 :
300 : void
301 177 : MSRoute::dict_clearState() {
302 : #ifdef HAVE_FOX
303 : FXMutexLock f(myDictMutex);
304 : #endif
305 : myDistDict.clear();
306 : myDict.clear();
307 177 : }
308 :
309 :
310 : double
311 21500 : MSRoute::getDistanceBetween(double fromPos, double toPos,
312 : const MSLane* fromLane, const MSLane* toLane, int routePosition) const {
313 : // std::cout << SIMTIME << " getDistanceBetween from=" << fromEdge->getID() << " to=" << toEdge->getID() << " fromPos=" << fromPos << " toPos=" << toPos << "\n";
314 : assert(fromPos >= 0. && fromPos <= fromLane->getLength());
315 : assert(toPos >= 0. && toPos <= toLane->getLength());
316 : assert(routePosition >= 0 && routePosition < (int)myEdges.size());
317 : assert(routePosition == 0 || !myEdges.front()->isInternal());
318 21500 : const MSEdge* fromEdge = &fromLane->getEdge();
319 21500 : const MSEdge* toEdge = &toLane->getEdge();
320 21500 : if (fromEdge == toEdge && fromPos <= toPos) {
321 15957 : return toPos - fromPos;
322 : }
323 : // TODO If fromEdge and toEdge are identical or both are internal and directly connected,
324 : // the code does not check whether they are in any relation to the route.
325 5543 : if (fromEdge->isInternal()) {
326 : double minDist = std::numeric_limits<double>::max();
327 1016 : for (const auto& via : fromEdge->getViaSuccessors()) {
328 508 : const MSEdge* const succ = via.second == nullptr ? via.first : via.second;
329 : assert(succ != nullptr);
330 : // std::cout << " recurse fromSucc=" << succ->getID() << "\n";
331 508 : const double d = getDistanceBetween(0., toPos, succ->getLanes()[0], toLane, routePosition);
332 508 : if (d != std::numeric_limits<double>::max() && fromLane->getLength() - fromPos + d < minDist) {
333 : minDist = fromLane->getLength() - fromPos + d;
334 : }
335 : }
336 508 : return minDist;
337 : }
338 5035 : if (toEdge->isInternal()) {
339 1816 : const MSEdge* const pred = toEdge->getPredecessors().front();
340 : assert(pred != nullptr);
341 : // std::cout << " recurse toPred=" << pred->getID() << "\n";
342 1816 : const double d = getDistanceBetween(fromPos, pred->getLength(), fromLane, pred->getLanes()[0], routePosition);
343 1816 : return d == std::numeric_limits<double>::max() ? d : toPos + d;
344 : }
345 3219 : ConstMSEdgeVector::const_iterator fromIt = std::find(myEdges.begin() + routePosition, myEdges.end(), fromEdge);
346 3219 : if (fromIt == myEdges.end()) {
347 : // start not contained in route
348 : return std::numeric_limits<double>::max();
349 : }
350 3214 : ConstMSEdgeVector::const_iterator toIt = std::find(fromIt + 1, myEdges.end(), toEdge);
351 3214 : if (toIt == myEdges.end()) {
352 : // destination not contained in route
353 : return std::numeric_limits<double>::max();
354 : }
355 1781 : return getDistanceBetween(fromPos, toPos, fromIt, toIt, true);
356 : }
357 :
358 :
359 : double
360 53973 : MSRoute::getDistanceBetween(double fromPos, double toPos,
361 : const MSRouteIterator& fromEdge, const MSRouteIterator& toEdge, bool includeInternal) const {
362 : bool isFirstIteration = true;
363 53973 : double distance = -fromPos;
364 53973 : MSRouteIterator it = fromEdge;
365 53973 : if (fromEdge == toEdge) {
366 : // destination position is on start edge
367 3065 : if (fromPos <= toPos) {
368 3065 : return toPos - fromPos;
369 : } else {
370 : // we cannot go backwards. Something is wrong here
371 : return std::numeric_limits<double>::max();
372 : }
373 50908 : } else if (fromEdge > toEdge) {
374 : // we don't visit the edge again
375 : return std::numeric_limits<double>::max();
376 : }
377 473760 : for (; it != end(); ++it) {
378 467459 : if (it == toEdge && !isFirstIteration) {
379 44607 : distance += toPos;
380 44607 : break;
381 : } else {
382 422852 : distance += (*it)->getLength();
383 422852 : if (includeInternal && (it + 1) != end()) {
384 : // XXX the length may be wrong if there are parallel internal edges for different vClasses
385 416174 : distance += (*it)->getInternalFollowingLengthTo(*(it + 1), SVC_IGNORING);
386 : }
387 : }
388 : isFirstIteration = false;
389 : }
390 : return distance;
391 : }
392 :
393 :
394 : const RGBColor&
395 9919262 : MSRoute::getColor() const {
396 9919262 : if (myColor == nullptr) {
397 9527248 : return RGBColor::DEFAULT_COLOR;
398 : }
399 : return *myColor;
400 : }
401 :
402 :
403 : const std::vector<SUMOVehicleParameter::Stop>&
404 8934966 : MSRoute::getStops() const {
405 8934966 : return myStops;
406 : }
407 :
408 :
409 : /****************************************************************************/
|