Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2002-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 RONetHandler.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Christian Roessel
18 : /// @author Michael Behrisch
19 : /// @author Yun-Pang Floetteroed
20 : /// @date Sept 2002
21 : ///
22 : // The handler for SUMO-Networks
23 : /****************************************************************************/
24 : #include <config.h>
25 :
26 : #include <string>
27 : #include <utils/common/MsgHandler.h>
28 : #include <utils/common/StringTokenizer.h>
29 : #include <utils/common/UtilExceptions.h>
30 : #include <utils/common/ToString.h>
31 : #include <utils/common/StringUtils.h>
32 : #include <utils/geom/PositionVector.h>
33 : #include <utils/geom/GeoConvHelper.h>
34 : #include <utils/vehicle/SUMORouteHandler.h>
35 : #include <utils/xml/SUMOSAXHandler.h>
36 : #include <utils/xml/SUMOXMLDefinitions.h>
37 : #include "ROEdge.h"
38 : #include "ROLane.h"
39 : #include "RONode.h"
40 : #include "RONet.h"
41 : #include "RONetHandler.h"
42 : #include "ROAbstractEdgeBuilder.h"
43 :
44 :
45 : // ===========================================================================
46 : // method definitions
47 : // ===========================================================================
48 4256 : RONetHandler::RONetHandler(RONet& net, ROAbstractEdgeBuilder& eb, const bool ignoreInternal, const double minorPenalty, double tlsPenalty, double turnaroundPenalty) :
49 : SUMOSAXHandler("sumo-network"),
50 4256 : myNet(net),
51 : myNetworkVersion(0, 0),
52 4256 : myEdgeBuilder(eb), myIgnoreInternal(ignoreInternal),
53 4256 : myCurrentName(), myCurrentEdge(nullptr), myCurrentStoppingPlace(nullptr),
54 4256 : myMinorPenalty(minorPenalty),
55 4256 : myTLSPenalty(tlsPenalty),
56 8512 : myTurnaroundPenalty(turnaroundPenalty)
57 4256 : {}
58 :
59 :
60 8512 : RONetHandler::~RONetHandler() {}
61 :
62 :
63 : void
64 1399975 : RONetHandler::myStartElement(int element,
65 : const SUMOSAXAttributes& attrs) {
66 1399975 : switch (element) {
67 4256 : case SUMO_TAG_LOCATION:
68 4256 : setLocation(attrs);
69 4256 : break;
70 4256 : case SUMO_TAG_NET: {
71 : bool ok;
72 8512 : myNetworkVersion = StringUtils::toVersion(attrs.get<std::string>(SUMO_ATTR_VERSION, nullptr, ok, false));
73 : break;
74 : }
75 283371 : case SUMO_TAG_EDGE:
76 : // in the first step, we do need the name to allocate the edge
77 : // in the second, we need it to know to which edge we have to add
78 : // the following edges to
79 283371 : parseEdge(attrs);
80 283359 : break;
81 320288 : case SUMO_TAG_LANE:
82 320288 : parseLane(attrs);
83 320288 : break;
84 90002 : case SUMO_TAG_JUNCTION:
85 90002 : parseJunction(attrs);
86 90002 : break;
87 416327 : case SUMO_TAG_CONNECTION:
88 416327 : parseConnection(attrs);
89 416009 : break;
90 1599 : case SUMO_TAG_BUS_STOP:
91 : case SUMO_TAG_TRAIN_STOP:
92 : case SUMO_TAG_CONTAINER_STOP:
93 : case SUMO_TAG_PARKING_AREA:
94 : case SUMO_TAG_CHARGING_STATION:
95 : case SUMO_TAG_OVERHEAD_WIRE_SEGMENT:
96 1599 : parseStoppingPlace(attrs, (SumoXMLTag)element);
97 1599 : break;
98 978 : case SUMO_TAG_ACCESS:
99 978 : parseAccess(attrs);
100 978 : break;
101 381 : case SUMO_TAG_TAZ:
102 381 : parseDistrict(attrs);
103 381 : break;
104 124 : case SUMO_TAG_TAZSOURCE:
105 124 : parseDistrictEdge(attrs, true);
106 124 : break;
107 125 : case SUMO_TAG_TAZSINK:
108 125 : parseDistrictEdge(attrs, false);
109 125 : break;
110 2112 : case SUMO_TAG_TYPE: {
111 2112 : bool ok = true;
112 4224 : myCurrentTypeID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
113 : break;
114 : }
115 17 : case SUMO_TAG_RESTRICTION: {
116 17 : bool ok = true;
117 34 : const SUMOVehicleClass svc = getVehicleClassID(attrs.get<std::string>(SUMO_ATTR_VCLASS, myCurrentTypeID.c_str(), ok));
118 17 : const double speed = attrs.get<double>(SUMO_ATTR_SPEED, myCurrentTypeID.c_str(), ok);
119 17 : if (ok) {
120 17 : myNet.addSpeedRestriction(myCurrentTypeID, svc, speed);
121 : }
122 : break;
123 : }
124 40 : case SUMO_TAG_PREFERENCE: {
125 40 : bool ok = true;
126 40 : const std::string routingType = attrs.get<std::string>(SUMO_ATTR_ROUTINGTYPE, nullptr, ok);
127 40 : const double prio = attrs.get<double>(SUMO_ATTR_PRIORITY, routingType.c_str(), ok);
128 40 : if (prio <= 0) {
129 0 : throw InvalidArgument("In preference for routingType '" + routingType + "', priority must be positve");
130 : }
131 40 : if (attrs.hasAttribute(SUMO_ATTR_VCLASSES)) {
132 8 : StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_VCLASSES, routingType.c_str(), ok));
133 32 : for (std::string className : st.getVector()) {
134 24 : myNet.addPreference(routingType, getVehicleClassID(className), prio);
135 8 : }
136 40 : } else if (!attrs.hasAttribute(SUMO_ATTR_VTYPES)) {
137 : // general preferenze applying to all types and vClasses
138 48 : myNet.addPreference(routingType, "", prio);
139 : }
140 40 : if (attrs.hasAttribute(SUMO_ATTR_VTYPES)) {
141 8 : StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_VTYPES, routingType.c_str(), ok));
142 16 : for (std::string typeName : st.getVector()) {
143 24 : myNet.addPreference(routingType, typeName, prio);
144 8 : }
145 8 : }
146 : break;
147 : }
148 4 : case SUMO_TAG_REROUTER: {
149 4 : bool ok = true;
150 8 : myRerouterID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
151 : break;
152 : }
153 4 : case SUMO_TAG_INTERVAL:
154 4 : if (myRerouterID != "") {
155 4 : bool ok = true;
156 4 : myIntervalBegin = attrs.getOptSUMOTimeReporting(SUMO_ATTR_BEGIN, myRerouterID.c_str(), ok, -1);
157 4 : myIntervalEnd = attrs.getOptSUMOTimeReporting(SUMO_ATTR_END, myRerouterID.c_str(), ok, SUMOTime_MAX);
158 : }
159 : break;
160 4 : case SUMO_TAG_CLOSING_REROUTE: {
161 4 : const std::string& closed_id = attrs.getStringSecure(SUMO_ATTR_ID, "");
162 4 : ROEdge* closedEdge = myNet.getEdge(closed_id);
163 4 : if (closedEdge == nullptr) {
164 0 : throw ProcessError(TLF("rerouter '%': Edge '%' to close is not known.", myRerouterID, closed_id));
165 : }
166 : bool ok;
167 4 : const std::string allow = attrs.getOpt<std::string>(SUMO_ATTR_ALLOW, myRerouterID.c_str(), ok, "", false);
168 4 : const std::string disallow = attrs.getOpt<std::string>(SUMO_ATTR_DISALLOW, myRerouterID.c_str(), ok, "");
169 4 : RouterProhibition prohibition;
170 4 : prohibition.permissions = parseVehicleClasses(allow, disallow);
171 4 : prohibition.begin = STEPS2TIME(myIntervalBegin);
172 4 : prohibition.end = STEPS2TIME(attrs.getOptSUMOTimeReporting(SUMO_ATTR_UNTIL, nullptr, ok, myIntervalEnd));
173 4 : myNet.addProhibition(closedEdge, prohibition);
174 : break;
175 : }
176 81965 : case SUMO_TAG_PARAM:
177 81965 : addParam(attrs);
178 81965 : break;
179 : default:
180 : break;
181 : }
182 1399645 : }
183 :
184 :
185 : void
186 1398880 : RONetHandler::myEndElement(int element) {
187 1398880 : switch (element) {
188 4 : case SUMO_TAG_REROUTER:
189 4 : myRerouterID = "";
190 : break;
191 3671 : case SUMO_TAG_NET:
192 : // build junction graph
193 3749 : for (std::set<std::string>::const_iterator it = myUnseenNodeIDs.begin(); it != myUnseenNodeIDs.end(); ++it) {
194 234 : WRITE_ERRORF(TL("Unknown node '%'."), *it);
195 : }
196 : break;
197 : default:
198 : break;
199 : }
200 1398880 : }
201 :
202 :
203 : void
204 81965 : RONetHandler::addParam(const SUMOSAXAttributes& attrs) {
205 81965 : bool ok = true;
206 81965 : const std::string key = attrs.get<std::string>(SUMO_ATTR_KEY, nullptr, ok);
207 : // circumventing empty string test
208 81965 : const std::string val = attrs.hasAttribute(SUMO_ATTR_VALUE) ? attrs.getString(SUMO_ATTR_VALUE) : "";
209 : // add parameter in current created element, or in myLoadedParameterised
210 81965 : if (myCurrentEdge != nullptr) {
211 81965 : myCurrentEdge->setParameter(key, val);
212 : }
213 81965 : }
214 :
215 :
216 : void
217 283371 : RONetHandler::parseEdge(const SUMOSAXAttributes& attrs) {
218 : // get the id, report an error if not given or empty...
219 283371 : bool ok = true;
220 283371 : myCurrentName = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
221 283371 : if (!ok) {
222 12 : throw ProcessError();
223 : }
224 283359 : const SumoXMLEdgeFunc func = attrs.getOpt<SumoXMLEdgeFunc>(SUMO_ATTR_FUNCTION, myCurrentName.c_str(), ok, SumoXMLEdgeFunc::NORMAL);
225 283359 : if (!ok) {
226 54 : return;
227 : }
228 : // get the edge
229 : std::string from;
230 : std::string to;
231 : int priority;
232 283353 : myCurrentEdge = nullptr;
233 283353 : if (func == SumoXMLEdgeFunc::INTERNAL || func == SumoXMLEdgeFunc::CROSSING || func == SumoXMLEdgeFunc::WALKINGAREA) {
234 : assert(myCurrentName[0] == ':');
235 360526 : const std::string junctionID = SUMOXMLDefinitions::getJunctionIDFromInternalEdge(myCurrentName);
236 : from = junctionID;
237 : to = junctionID;
238 : priority = -1;
239 180263 : } else {
240 206180 : from = attrs.get<std::string>(SUMO_ATTR_FROM, myCurrentName.c_str(), ok);
241 206180 : to = attrs.get<std::string>(SUMO_ATTR_TO, myCurrentName.c_str(), ok);
242 103090 : priority = attrs.get<int>(SUMO_ATTR_PRIORITY, myCurrentName.c_str(), ok);
243 103090 : if (!ok) {
244 : return;
245 : }
246 : }
247 283305 : RONode* fromNode = myNet.getNode(from);
248 238445 : if (fromNode == nullptr) {
249 : myUnseenNodeIDs.insert(from);
250 44860 : fromNode = new RONode(from);
251 44860 : myNet.addNode(fromNode);
252 : }
253 283305 : RONode* toNode = myNet.getNode(to);
254 262008 : if (toNode == nullptr) {
255 : myUnseenNodeIDs.insert(to);
256 21297 : toNode = new RONode(to);
257 21297 : myNet.addNode(toNode);
258 : }
259 283305 : const std::string type = attrs.getOpt<std::string>(SUMO_ATTR_TYPE, myCurrentName.c_str(), ok, "");
260 283305 : const std::string routingType = attrs.getOpt<std::string>(SUMO_ATTR_ROUTINGTYPE, myCurrentName.c_str(), ok, "");
261 : // build the edge
262 283305 : myCurrentEdge = myEdgeBuilder.buildEdge(myCurrentName, fromNode, toNode, priority, type, routingType);
263 : myCurrentEdge->setFunction(func);
264 :
265 283305 : if (myNet.addEdge(myCurrentEdge)) {
266 283293 : fromNode->addOutgoing(myCurrentEdge);
267 283293 : toNode->addIncoming(myCurrentEdge);
268 566586 : const std::string bidi = attrs.getOpt<std::string>(SUMO_ATTR_BIDI, myCurrentName.c_str(), ok, "");
269 283293 : if (bidi != "") {
270 9906 : myBidiEdges[myCurrentEdge] = bidi;
271 : }
272 : } else {
273 12 : myCurrentEdge = nullptr;
274 : }
275 : }
276 :
277 :
278 : void
279 320288 : RONetHandler::parseLane(const SUMOSAXAttributes& attrs) {
280 320288 : if (myCurrentEdge == nullptr) {
281 : // was an internal edge to skip or an error occurred
282 282 : return;
283 : }
284 320162 : bool ok = true;
285 : // get the id, report an error if not given or empty...
286 320162 : std::string id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
287 320162 : if (!ok) {
288 : return;
289 : }
290 : // get the speed
291 320138 : double maxSpeed = attrs.get<double>(SUMO_ATTR_SPEED, id.c_str(), ok);
292 320138 : double length = attrs.get<double>(SUMO_ATTR_LENGTH, id.c_str(), ok);
293 320138 : std::string allow = attrs.getOpt<std::string>(SUMO_ATTR_ALLOW, id.c_str(), ok, "");
294 640276 : std::string disallow = attrs.getOpt<std::string>(SUMO_ATTR_DISALLOW, id.c_str(), ok, "");
295 320138 : const PositionVector shape = attrs.get<PositionVector>(SUMO_ATTR_SHAPE, id.c_str(), ok);
296 320138 : if (!ok) {
297 : return;
298 : }
299 320030 : if (shape.size() < 2) {
300 72 : WRITE_ERRORF(TL("Ignoring lane '%' with broken shape."), id);
301 24 : return;
302 : }
303 : // get the length
304 : // get the vehicle classes
305 320006 : SVCPermissions permissions = parseVehicleClasses(allow, disallow, myNetworkVersion);
306 320006 : if (permissions != SVCAll) {
307 206543 : myNet.setPermissionsFound();
308 : }
309 : // add when both values are valid
310 320006 : if (maxSpeed > 0 && length > 0 && id.length() > 0) {
311 320006 : myCurrentEdge->addLane(new ROLane(id, myCurrentEdge, length, maxSpeed, permissions, shape));
312 : } else {
313 0 : WRITE_WARNING("Ignoring lane '" + id + "' with speed " + toString(maxSpeed) + " and length " + toString(length));
314 : }
315 320138 : }
316 :
317 :
318 : void
319 90002 : RONetHandler::parseJunction(const SUMOSAXAttributes& attrs) {
320 90002 : bool ok = true;
321 : // get the id, report an error if not given or empty...
322 90002 : std::string id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
323 90002 : const SumoXMLNodeType type = attrs.get<SumoXMLNodeType>(SUMO_ATTR_TYPE, id.c_str(), ok);
324 90002 : if (type == SumoXMLNodeType::INTERNAL) {
325 : return;
326 : }
327 : myUnseenNodeIDs.erase(id);
328 : // get the position of the node
329 65649 : const double x = attrs.get<double>(SUMO_ATTR_X, id.c_str(), ok);
330 65649 : const double y = attrs.get<double>(SUMO_ATTR_Y, id.c_str(), ok);
331 65649 : const double z = attrs.getOpt<double>(SUMO_ATTR_Z, id.c_str(), ok, 0.);
332 65649 : if (!ok) {
333 : return;
334 : }
335 65604 : RONode* n = myNet.getNode(id);
336 65500 : if (n == nullptr) {
337 312 : WRITE_WARNINGF(TL("Skipping isolated junction '%'."), id);
338 : } else {
339 65500 : n->setPosition(Position(x, y, z));
340 : }
341 : }
342 :
343 :
344 : void
345 416327 : RONetHandler::parseConnection(const SUMOSAXAttributes& attrs) {
346 416327 : bool ok = true;
347 416327 : std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, nullptr, ok);
348 416327 : std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, nullptr, ok);
349 416327 : const int fromLane = attrs.get<int>(SUMO_ATTR_FROM_LANE, nullptr, ok);
350 416327 : const int toLane = attrs.get<int>(SUMO_ATTR_TO_LANE, nullptr, ok);
351 416327 : std::string dir = attrs.get<std::string>(SUMO_ATTR_DIR, nullptr, ok);
352 416645 : std::string viaID = attrs.getOpt<std::string>(SUMO_ATTR_VIA, nullptr, ok, "");
353 416645 : std::string tlID = attrs.getOpt<std::string>(SUMO_ATTR_TLID, nullptr, ok, "");
354 416327 : ROEdge* from = myNet.getEdge(fromID);
355 : ROEdge* to = myNet.getEdge(toID);
356 416327 : if (from == nullptr) {
357 207 : throw ProcessError(TLF("unknown from-edge '%' in connection", fromID));
358 : }
359 416258 : if (to == nullptr) {
360 207 : throw ProcessError(TLF("unknown to-edge '%' in connection", toID));
361 : }
362 416189 : if ((int)from->getLanes().size() <= fromLane) {
363 270 : throw ProcessError("invalid fromLane '" + toString(fromLane) + "' in connection from '" + fromID + "'.");
364 : }
365 416099 : if ((int)to->getLanes().size() <= toLane) {
366 270 : throw ProcessError("invalid toLane '" + toString(toLane) + "' in connection to '" + toID + "'.");
367 : }
368 416009 : if (myIgnoreInternal || viaID == "") {
369 273005 : std::string allow = attrs.getOpt<std::string>(SUMO_ATTR_ALLOW, nullptr, ok, "");
370 273005 : std::string disallow = attrs.getOpt<std::string>(SUMO_ATTR_DISALLOW, nullptr, ok, "");
371 : ROEdge* dummyVia = nullptr;
372 : SVCPermissions permissions;
373 273005 : if (allow == "" && disallow == "") {
374 : permissions = SVC_UNSPECIFIED;
375 : } else {
376 13 : myNet.setPermissionsFound();
377 : // dummyVia is only needed to hold permissions
378 13 : permissions = parseVehicleClasses(allow, disallow);
379 13 : dummyVia = new ROEdge("dummyVia_" + from->getLanes()[fromLane]->getID() + "->" + to->getLanes()[toLane]->getID(),
380 26 : from->getToJunction(), from->getToJunction(), permissions);
381 13 : myNet.addEdge(dummyVia);
382 : }
383 273005 : from->getLanes()[fromLane]->addOutgoingLane(to->getLanes()[toLane], dummyVia);
384 819015 : from->addSuccessor(to, nullptr, dir);
385 : } else {
386 143004 : ROEdge* const via = myNet.getEdge(SUMOXMLDefinitions::getEdgeIDFromLane(viaID));
387 143004 : if (via == nullptr) {
388 0 : throw ProcessError(TLF("unknown via-edge '%' in connection", viaID));
389 : }
390 143004 : from->getLanes()[fromLane]->addOutgoingLane(to->getLanes()[toLane], via);
391 286008 : from->addSuccessor(to, via, dir);
392 286008 : via->addSuccessor(to, nullptr, dir);
393 143004 : LinkState state = SUMOXMLDefinitions::LinkStates.get(attrs.get<std::string>(SUMO_ATTR_STATE, nullptr, ok));
394 143004 : if (state == LINKSTATE_MINOR || state == LINKSTATE_EQUAL || state == LINKSTATE_STOP || state == LINKSTATE_ALLWAY_STOP) {
395 84530 : via->setTimePenalty(myMinorPenalty);
396 : }
397 254487 : if (dir == toString(LinkDirection::TURN) || dir == toString(LinkDirection::TURN_LEFTHAND)) {
398 31843 : via->setTimePenalty(myTurnaroundPenalty);
399 : }
400 143004 : if (tlID != "") {
401 11632 : via->setTimePenalty(myTLSPenalty);
402 : }
403 : }
404 416009 : if (to->isCrossing()) {
405 9679 : to->setTimePenalty(myTLSPenalty);
406 : }
407 416009 : }
408 :
409 :
410 : void
411 1599 : RONetHandler::parseStoppingPlace(const SUMOSAXAttributes& attrs, const SumoXMLTag element) {
412 1599 : bool ok = true;
413 1599 : myCurrentStoppingPlace = new SUMOVehicleParameter::Stop();
414 : // get the id, throw if not given or empty...
415 1599 : std::string id = attrs.get<std::string>(SUMO_ATTR_ID, toString(element).c_str(), ok);
416 : // get the lane
417 1599 : myCurrentStoppingPlace->lane = attrs.get<std::string>(SUMO_ATTR_LANE, toString(element).c_str(), ok);
418 1599 : if (!ok) {
419 0 : throw ProcessError();
420 : }
421 1599 : const ROEdge* edge = myNet.getEdgeForLaneID(myCurrentStoppingPlace->lane);
422 1599 : if (edge == nullptr) {
423 0 : throw InvalidArgument("Unknown lane '" + myCurrentStoppingPlace->lane + "' for " + toString(element) + " '" + id + "'.");
424 : }
425 : // get the positions
426 1599 : myCurrentStoppingPlace->startPos = attrs.getOpt<double>(SUMO_ATTR_STARTPOS, id.c_str(), ok, 0.);
427 1599 : myCurrentStoppingPlace->endPos = attrs.getOpt<double>(SUMO_ATTR_ENDPOS, id.c_str(), ok, edge->getLength());
428 1599 : const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, id.c_str(), ok, false);
429 1599 : if (!ok || (SUMORouteHandler::checkStopPos(myCurrentStoppingPlace->startPos, myCurrentStoppingPlace->endPos, edge->getLength(), POSITION_EPS, friendlyPos) != SUMORouteHandler::StopPos::STOPPOS_VALID)) {
430 0 : throw InvalidArgument("Invalid position for " + toString(element) + " '" + id + "'.");
431 : }
432 : // this is a hack: the busstop attribute is meant to hold the id within the simulation context but this is not used within the router context
433 1599 : myCurrentStoppingPlace->busstop = attrs.getOpt<std::string>(SUMO_ATTR_NAME, id.c_str(), ok, "");
434 : // this is a hack: the actType is not used when using this to encode a stopping place
435 1599 : myCurrentStoppingPlace->actType = toString(element);
436 1599 : myNet.addStoppingPlace(id, element, myCurrentStoppingPlace);
437 1599 : }
438 :
439 :
440 : void
441 978 : RONetHandler::parseAccess(const SUMOSAXAttributes& attrs) {
442 978 : bool ok = true;
443 978 : const std::string lane = attrs.get<std::string>(SUMO_ATTR_LANE, "access", ok);
444 978 : const ROEdge* edge = myNet.getEdgeForLaneID(lane);
445 978 : if (edge == nullptr) {
446 0 : throw InvalidArgument("Unknown lane '" + lane + "' for access.");
447 : }
448 978 : if ((edge->getPermissions() & SVC_PEDESTRIAN) == 0) {
449 0 : WRITE_WARNINGF(TL("Ignoring invalid access from non-pedestrian edge '%'."), edge->getID());
450 : return;
451 : }
452 978 : const bool random = attrs.getOpt<std::string>(SUMO_ATTR_POSITION, "access", ok) == "random";
453 978 : double pos = random ? edge->getLength() / 2. : attrs.getOpt<double>(SUMO_ATTR_POSITION, "access", ok, 0.);
454 978 : double length = attrs.getOpt<double>(SUMO_ATTR_LENGTH, "access", ok, -1);
455 978 : const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, "access", ok, false);
456 978 : if (!ok || (SUMORouteHandler::checkStopPos(pos, pos, edge->getLength(), 0., friendlyPos) != SUMORouteHandler::StopPos::STOPPOS_VALID)) {
457 0 : throw InvalidArgument("Invalid position " + toString(pos) + " for access on lane '" + lane + "'.");
458 : }
459 : if (!ok) {
460 : throw ProcessError();
461 : }
462 978 : if (length < 0) {
463 568 : const Position accPos = myNet.getLane(lane)->geometryPositionAtOffset(pos);
464 568 : const double stopCenter = (myCurrentStoppingPlace->startPos + myCurrentStoppingPlace->endPos) / 2;
465 568 : const Position stopPos = myNet.getLane(myCurrentStoppingPlace->lane)->geometryPositionAtOffset(stopCenter);
466 568 : length = accPos.distanceTo(stopPos);
467 : }
468 1956 : myCurrentStoppingPlace->accessPos.push_back(std::make_tuple(lane, pos, length));
469 : }
470 :
471 :
472 : void
473 381 : RONetHandler::parseDistrict(const SUMOSAXAttributes& attrs) {
474 381 : myCurrentEdge = nullptr;
475 381 : bool ok = true;
476 381 : myCurrentName = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
477 381 : if (!ok) {
478 0 : return;
479 : }
480 762 : ROEdge* const sink = myEdgeBuilder.buildEdge(myCurrentName + "-sink", nullptr, nullptr, 0, "", "");
481 762 : ROEdge* const source = myEdgeBuilder.buildEdge(myCurrentName + "-source", nullptr, nullptr, 0, "", "");
482 381 : myNet.addDistrict(myCurrentName, source, sink);
483 381 : if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
484 244 : const std::vector<std::string>& desc = attrs.get<std::vector<std::string> >(SUMO_ATTR_EDGES, myCurrentName.c_str(), ok);
485 809 : for (const std::string& eID : desc) {
486 1695 : myNet.addDistrictEdge(myCurrentName, eID, true);
487 1695 : myNet.addDistrictEdge(myCurrentName, eID, false);
488 : }
489 244 : }
490 : }
491 :
492 :
493 : void
494 249 : RONetHandler::parseDistrictEdge(const SUMOSAXAttributes& attrs, bool isSource) {
495 249 : bool ok = true;
496 249 : std::string id = attrs.get<std::string>(SUMO_ATTR_ID, myCurrentName.c_str(), ok);
497 747 : myNet.addDistrictEdge(myCurrentName, id, isSource);
498 249 : }
499 :
500 : void
501 4256 : RONetHandler::setLocation(const SUMOSAXAttributes& attrs) {
502 4256 : bool ok = true;
503 4256 : PositionVector s = attrs.get<PositionVector>(SUMO_ATTR_NET_OFFSET, nullptr, ok);
504 4256 : Boundary convBoundary = attrs.get<Boundary>(SUMO_ATTR_CONV_BOUNDARY, nullptr, ok);
505 4256 : Boundary origBoundary = attrs.get<Boundary>(SUMO_ATTR_ORIG_BOUNDARY, nullptr, ok);
506 4256 : std::string proj = attrs.get<std::string>(SUMO_ATTR_ORIG_PROJ, nullptr, ok);
507 4256 : if (ok) {
508 4256 : Position networkOffset = s[0];
509 4256 : GeoConvHelper::init(proj, networkOffset, origBoundary, convBoundary);
510 : }
511 4256 : }
512 :
513 :
514 : /****************************************************************************/
|