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 ROJTRTurnDefLoader.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @date Tue, 20 Jan 2004
19 : ///
20 : // Loader for the of turning percentages and source/sink definitions
21 : /****************************************************************************/
22 : #include <config.h>
23 :
24 : #include <set>
25 : #include <string>
26 : #include <utils/common/FileHelpers.h>
27 : #include <utils/xml/XMLSubSys.h>
28 : #include <utils/common/UtilExceptions.h>
29 : #include <utils/common/MsgHandler.h>
30 : #include <utils/common/StringUtils.h>
31 : #include <utils/common/ToString.h>
32 : #include <utils/options/OptionsCont.h>
33 : #include <utils/xml/SUMOXMLDefinitions.h>
34 : #include <utils/vehicle/SUMOVehicleParserHelper.h>
35 : #include <router/RONet.h>
36 : #include "ROJTREdge.h"
37 : #include "ROJTRTurnDefLoader.h"
38 :
39 :
40 : // ===========================================================================
41 : // method definitions
42 : // ===========================================================================
43 56 : ROJTRTurnDefLoader::ROJTRTurnDefLoader(RONet& net) :
44 56 : SUMOSAXHandler("turn-ratio-file"), myNet(net),
45 56 : myIntervalBegin(0), myIntervalEnd(STEPS2TIME(SUMOTime_MAX)),
46 56 : myEdge(nullptr),
47 56 : mySourcesAreSinks(OptionsCont::getOptions().getBool("sources-are-sinks")),
48 56 : myDiscountSources(OptionsCont::getOptions().getBool("discount-sources")),
49 112 : myHaveWarnedAboutDeprecatedFormat(false)
50 56 : {}
51 :
52 :
53 56 : ROJTRTurnDefLoader::~ROJTRTurnDefLoader() {}
54 :
55 :
56 : void
57 1620 : ROJTRTurnDefLoader::myStartElement(int element,
58 : const SUMOSAXAttributes& attrs) {
59 1620 : bool ok = true;
60 1620 : switch (element) {
61 34 : case SUMO_TAG_INTERVAL:
62 34 : myIntervalBegin = attrs.get<double>(SUMO_ATTR_BEGIN, nullptr, ok);
63 34 : myIntervalEnd = attrs.get<double>(SUMO_ATTR_END, nullptr, ok);
64 34 : break;
65 58 : case SUMO_TAG_FROMEDGE:
66 58 : if (!myHaveWarnedAboutDeprecatedFormat) {
67 7 : myHaveWarnedAboutDeprecatedFormat = true;
68 14 : WRITE_WARNINGF(TL("The turn-file format with elements %, % is deprecated, please use % instead."),
69 : toString(SUMO_TAG_FROMEDGE), toString(SUMO_TAG_TOEDGE), toString(SUMO_TAG_EDGEREL));
70 : }
71 58 : beginFromEdge(attrs);
72 : break;
73 173 : case SUMO_TAG_TOEDGE:
74 173 : addToEdge(attrs);
75 : break;
76 1012 : case SUMO_TAG_EDGEREL:
77 1012 : addEdgeRel(attrs);
78 : break;
79 9 : case SUMO_TAG_SINK:
80 9 : if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
81 9 : std::string edges = attrs.get<std::string>(SUMO_ATTR_EDGES, nullptr, ok);
82 21 : StringTokenizer st(edges, StringTokenizer::WHITECHARS);
83 17 : while (st.hasNext()) {
84 11 : std::string id = st.next();
85 11 : ROEdge* edge = myNet.getEdge(id);
86 8 : if (edge == nullptr) {
87 9 : throw ProcessError(TLF("The edge '%' declared as a sink is not known.", id));
88 : }
89 : edge->setSink();
90 : }
91 9 : }
92 : break;
93 276 : case SUMO_TAG_FLOW: {
94 276 : const std::string flowID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
95 276 : if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
96 276 : const std::string edgeID = attrs.get<std::string>(SUMO_ATTR_FROM, nullptr, ok);
97 276 : ROEdge* edge = myNet.getEdge(edgeID);
98 276 : if (edge == nullptr) {
99 0 : throw ProcessError("The from-edge '" + edgeID + "' in flow '" + flowID + "' is not known.");
100 : }
101 276 : if (mySourcesAreSinks) {
102 : edge->setSink();
103 : }
104 276 : if (myDiscountSources) {
105 184 : SUMOVehicleParameter* pars = SUMOVehicleParserHelper::parseFlowAttributes(SUMO_TAG_FLOW, attrs, true, true, 0, TIME2STEPS(3600 * 24));
106 : int numVehs = 0;
107 184 : if (pars->repetitionProbability > 0) {
108 0 : numVehs = int(STEPS2TIME(pars->repetitionEnd - pars->depart) * pars->repetitionProbability);
109 : } else {
110 184 : numVehs = pars->repetitionNumber;
111 : }
112 184 : delete pars;
113 : static_cast<ROJTREdge*>(edge)->changeSourceFlow(numVehs);
114 : }
115 : } else {
116 0 : WRITE_WARNINGF(TL("Ignoring flow '%' without 'from'"), flowID);
117 : }
118 : break;
119 : }
120 0 : case SUMO_TAG_SOURCE:
121 0 : if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
122 0 : std::string edges = attrs.get<std::string>(SUMO_ATTR_EDGES, nullptr, ok);
123 0 : StringTokenizer st(edges, StringTokenizer::WHITECHARS);
124 0 : while (st.hasNext()) {
125 0 : std::string id = st.next();
126 0 : ROEdge* edge = myNet.getEdge(id);
127 0 : if (edge == nullptr) {
128 0 : throw ProcessError(TLF("The edge '%' declared as a source is not known.", id));
129 : }
130 : edge->setSource();
131 : }
132 0 : }
133 : break;
134 : default:
135 : break;
136 : }
137 1617 : }
138 :
139 :
140 : void
141 58 : ROJTRTurnDefLoader::beginFromEdge(const SUMOSAXAttributes& attrs) {
142 58 : myEdge = nullptr;
143 58 : bool ok = true;
144 : // get the id, report an error if not given or empty...
145 58 : std::string id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
146 58 : if (!ok) {
147 : return;
148 : }
149 : //
150 58 : myEdge = static_cast<ROJTREdge*>(myNet.getEdge(id));
151 58 : if (myEdge == nullptr) {
152 0 : WRITE_ERRORF(TL("The edge '%' is not known within the network (within a 'from-edge' tag)."), id);
153 0 : return;
154 : }
155 : }
156 :
157 :
158 : void
159 173 : ROJTRTurnDefLoader::addToEdge(const SUMOSAXAttributes& attrs) {
160 173 : if (myEdge == nullptr) {
161 0 : return;
162 : }
163 173 : bool ok = true;
164 : // get the id, report an error if not given or empty...
165 173 : std::string id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
166 173 : if (!ok) {
167 : return;
168 : }
169 : //
170 173 : ROJTREdge* edge = static_cast<ROJTREdge*>(myNet.getEdge(id));
171 173 : if (edge == nullptr) {
172 0 : WRITE_ERRORF(TL("The edge '%' is not known within the network (within a 'to-edge' tag)."), id);
173 0 : return;
174 : }
175 173 : const double probability = attrs.get<double>(SUMO_ATTR_PROB, id.c_str(), ok);
176 173 : if (ok) {
177 173 : if (probability < 0) {
178 0 : WRITE_ERRORF(TL("'probability' must be positive (in definition of to-edge '%')."), id);
179 : } else {
180 173 : myEdge->addFollowerProbability(edge, myIntervalBegin, myIntervalEnd, probability);
181 : }
182 : }
183 : }
184 :
185 :
186 : void
187 1012 : ROJTRTurnDefLoader::addEdgeRel(const SUMOSAXAttributes& attrs) {
188 1012 : bool ok = true;
189 : // get the id, report an error if not given or empty...
190 1012 : std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, nullptr, ok);
191 1012 : std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, nullptr, ok);
192 2024 : double probability = attrs.get<double>(
193 1564 : attrs.hasAttribute(SUMO_ATTR_COUNT) && !attrs.hasAttribute(SUMO_ATTR_PROB) ? SUMO_ATTR_COUNT : SUMO_ATTR_PROB,
194 1012 : (fromID + "->" + toID).c_str(), ok);
195 1012 : if (!ok) {
196 : return;
197 : }
198 : //
199 1012 : ROJTREdge* from = static_cast<ROJTREdge*>(myNet.getEdge(fromID));
200 1012 : if (from == nullptr) {
201 0 : WRITE_ERRORF(TL("The edge '%' is not known."), fromID);
202 0 : return;
203 : }
204 : ROJTREdge* to = static_cast<ROJTREdge*>(myNet.getEdge(toID));
205 1012 : if (to == nullptr) {
206 0 : WRITE_ERRORF(TL("The edge '%' is not known."), toID);
207 0 : return;
208 : }
209 1012 : if (probability < 0) {
210 0 : WRITE_ERRORF(TL("'probability' must be positive (in edgeRelation from '%' to '%'."), fromID, toID);
211 : } else {
212 1012 : from->addFollowerProbability(to, myIntervalBegin, myIntervalEnd, probability);
213 : }
214 : }
215 :
216 :
217 : /****************************************************************************/
|