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