Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
NIXMLEdgesHandler.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-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/****************************************************************************/
23// Importer for network edges stored in XML
24/****************************************************************************/
25#include <config.h>
26
27#include <string>
28#include <iostream>
29#include <map>
30#include <cmath>
32#include <netbuild/NBNodeCont.h>
33#include <netbuild/NBTypeCont.h>
43#include "NIXMLNodesHandler.h"
44#include "NIXMLEdgesHandler.h"
45#include "NIImporter_SUMO.h"
46
47
48// ===========================================================================
49// method definitions
50// ===========================================================================
52 NBEdgeCont& ec,
53 NBTypeCont& tc,
56 OptionsCont& options) :
57 SUMOSAXHandler("xml-edges - file"),
58 myOptions(options),
59 myNodeCont(nc),
60 myEdgeCont(ec),
61 myTypeCont(tc),
63 myTLLogicCont(tlc),
64 myCurrentEdge(nullptr),
69 myDefaultNodeType(SUMOXMLDefinitions::NodeTypes.hasString(options.getString("default.junctions.type"))
70 ? SUMOXMLDefinitions::NodeTypes.get(options.getString("default.junctions.type")) : SumoXMLNodeType::UNKNOWN),
71 myKeepEdgeShape(!options.getBool("plain.extend-edge-shape")) {
72}
73
74
78
79
80void
82 const SUMOSAXAttributes& attrs) {
83 switch (element) {
85 // infer location for legacy networks that don't have location information
87 break;
89 delete myLocation;
91 break;
92 case SUMO_TAG_EDGE:
93 addEdge(attrs);
94 break;
95 case SUMO_TAG_LANE:
96 addLane(attrs);
97 break;
98 case SUMO_TAG_NEIGH:
99 myCurrentEdge->getLaneStruct((int)myCurrentEdge->getNumLanes() - 1).oppositeID = attrs.getString(SUMO_ATTR_LANE);
100 break;
101 case SUMO_TAG_SPLIT:
102 addSplit(attrs);
103 break;
104 case SUMO_TAG_DEL:
105 deleteEdge(attrs);
106 break;
108 addRoundabout(attrs);
109 break;
110 case SUMO_TAG_PARAM:
111 if (myLastParameterised.size() != 0 && myCurrentEdge != nullptr) {
112 bool ok = true;
113 const std::string key = attrs.get<std::string>(SUMO_ATTR_KEY, nullptr, ok);
114 // circumventing empty string test
115 const std::string val = attrs.hasAttribute(SUMO_ATTR_VALUE) ? attrs.getString(SUMO_ATTR_VALUE) : "";
116 myLastParameterised.back()->setParameter(key, val);
117 }
118 break;
119 case SUMO_TAG_STOPOFFSET: {
120 bool ok = true;
121 const StopOffset stopOffset(attrs, ok);
122 if (!ok) {
123 std::stringstream ss;
124 ss << "(Error encountered at lane " << myCurrentLaneIndex << " of edge '" << myCurrentID << "' while parsing stopOffsets.)";
125 WRITE_ERROR(ss.str());
126 } else {
127 if (myCurrentEdge->getLaneStopOffset(myCurrentLaneIndex).isDefined()) {
128 std::stringstream ss;
129 ss << "Duplicate definition of stopOffset for ";
130 if (myCurrentLaneIndex != -1) {
131 ss << "lane " << myCurrentLaneIndex << " on ";
132 }
133 ss << "edge " << myCurrentEdge->getID() << ". Ignoring duplicate specification.";
134 WRITE_WARNING(ss.str());
135 } else if ((stopOffset.getOffset() > myCurrentEdge->getLength()) || (stopOffset.getOffset() < 0)) {
136 std::stringstream ss;
137 ss << "Ignoring invalid stopOffset for ";
138 if (myCurrentLaneIndex != -1) {
139 ss << "lane " << myCurrentLaneIndex << " on ";
140 }
141 ss << "edge " << myCurrentEdge->getID();
142 if (stopOffset.getOffset() > myCurrentEdge->getLength()) {
143 ss << " (offset larger than the edge length).";
144 } else {
145 ss << " (negative offset).";
146 }
147 WRITE_WARNING(ss.str());
148 } else {
149 myCurrentEdge->setEdgeStopOffset(myCurrentLaneIndex, stopOffset);
150 }
151 }
152 }
153 break;
154 default:
155 break;
156 }
157}
158
159
160void
162 myIsUpdate = false;
163 bool ok = true;
164 // initialise the edge
165 myCurrentEdge = nullptr;
166 mySplits.clear();
167 // get the id, report an error if not given or empty...
168 myCurrentID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
169 if (!ok) {
170 return;
171 }
173 // check deprecated (unused) attributes
174 // use default values, first
175 myCurrentType = myCurrentEdge == nullptr ? myOptions.getString("default.type") : myCurrentEdge->getTypeID();
176 // check whether a type's values shall be used
177 if (attrs.hasAttribute(SUMO_ATTR_TYPE)) {
178 myCurrentType = attrs.get<std::string>(SUMO_ATTR_TYPE, myCurrentID.c_str(), ok);
179 if (!ok) {
180 return;
181 }
182 if (!myTypeCont.knows(myCurrentType) && !myOptions.getBool("ignore-errors.edge-type")) {
183 WRITE_ERRORF("Type '%' used by edge '%' was not defined (ignore with option --ignore-errors.edge-type).", myCurrentType, myCurrentID);
184 return;
185 }
186 }
188 if (myCurrentEdge != nullptr) {
189 // update existing edge. only update lane-specific settings when explicitly requested
190 myIsUpdate = true;
193 myCurrentPriority = myCurrentEdge->getPriority();
194 myCurrentLaneNo = myCurrentEdge->getNumLanes();
197 myLanesSpread = myCurrentEdge->getLaneSpreadFunction();
200 } else {
201 // this is a completely new edge. get the type specific defaults
202 myCurrentSpeed = myTypeCont.getEdgeTypeSpeed(myCurrentType);
203 myCurrentFriction = myTypeCont.getEdgeTypeFriction(myCurrentType);
204 myCurrentPriority = myTypeCont.getEdgeTypePriority(myCurrentType);
205 myCurrentLaneNo = myTypeCont.getEdgeTypeNumLanes(myCurrentType);
206 myPermissions = myTypeCont.getEdgeTypePermissions(myCurrentType);
207 myCurrentWidth = myTypeCont.getEdgeTypeWidth(myCurrentType);
208 myLanesSpread = myTypeCont.getEdgeTypeSpreadType(myCurrentType);
210 myLanesSpread = SUMOXMLDefinitions::LaneSpreadFunctions.get(myOptions.getString("default.spreadtype"));
211 }
212 mySidewalkWidth = myTypeCont.getEdgeTypeSidewalkWidth(myCurrentType);
213 myBikeLaneWidth = myTypeCont.getEdgeTypeBikeLaneWidth(myCurrentType);
214 }
218 myReinitKeepEdgeShape = false;
219
220 // use values from the edge to overwrite if existing, then
221 if (myIsUpdate) {
223 WRITE_MESSAGEF(TL("Duplicate edge id occurred ('%'); assuming overwriting is wished."), myCurrentID);
225 }
226 if (attrs.hasAttribute(SUMO_ATTR_TYPE) && myCurrentType != myCurrentEdge->getTypeID()) {
228 WRITE_MESSAGEF(TL("Edge '%' changed its type; assuming type override is wished."), myCurrentID);
230 }
231 }
232 if (attrs.getOpt<bool>(SUMO_ATTR_REMOVE, myCurrentID.c_str(), ok, false)) {
234 myCurrentEdge = nullptr;
235 return;
236 }
237 if (!myCurrentEdge->hasDefaultGeometry()) {
238 myShape = myCurrentEdge->getGeometry();
240 }
241 if (myCurrentEdge->hasLoadedLength()) {
242 myLength = myCurrentEdge->getLoadedLength();
243 }
244 myCurrentStreetName = myCurrentEdge->getStreetName();
245 }
246 // speed, priority and the number of lanes have now default values;
247 // try to read the real values from the file
248 if (attrs.hasAttribute(SUMO_ATTR_SPEED)) {
249 myCurrentSpeed = attrs.get<double>(SUMO_ATTR_SPEED, myCurrentID.c_str(), ok);
250 }
251 if (myOptions.getBool("speed-in-kmh") && myCurrentSpeed != NBEdge::UNSPECIFIED_SPEED) {
252 myCurrentSpeed = myCurrentSpeed / (double) 3.6;
253 }
254 // try to read the friction value from file
255 if (attrs.hasAttribute(SUMO_ATTR_FRICTION)) {
256 myCurrentFriction = attrs.get<double>(SUMO_ATTR_FRICTION, myCurrentID.c_str(), ok);
257 }
258 // try to get the number of lanes
259 if (attrs.hasAttribute(SUMO_ATTR_NUMLANES)) {
260 myCurrentLaneNo = attrs.get<int>(SUMO_ATTR_NUMLANES, myCurrentID.c_str(), ok);
261 }
262 // try to get the priority
263 if (attrs.hasAttribute(SUMO_ATTR_PRIORITY)) {
264 myCurrentPriority = attrs.get<int>(SUMO_ATTR_PRIORITY, myCurrentID.c_str(), ok);
265 }
266 // try to get the width
267 if (attrs.hasAttribute(SUMO_ATTR_WIDTH)) {
268 myCurrentWidth = attrs.get<double>(SUMO_ATTR_WIDTH, myCurrentID.c_str(), ok);
269 }
270 // try to get the offset of the stop line from the intersection
272 myCurrentEndOffset = attrs.get<double>(SUMO_ATTR_ENDOFFSET, myCurrentID.c_str(), ok);
273 }
274 // try to get the street name
275 if (attrs.hasAttribute(SUMO_ATTR_NAME)) {
276 myCurrentStreetName = attrs.get<std::string>(SUMO_ATTR_NAME, myCurrentID.c_str(), ok);
277 if (myCurrentStreetName != "" && myOptions.isDefault("output.street-names")) {
278 myOptions.set("output.street-names", "true");
279 }
280 }
281
282 // try to get the allowed/disallowed classes
284 std::string allowS = attrs.hasAttribute(SUMO_ATTR_ALLOW) ? attrs.getStringSecure(SUMO_ATTR_ALLOW, "") : "";
285 std::string disallowS = attrs.hasAttribute(SUMO_ATTR_DISALLOW) ? attrs.getStringSecure(SUMO_ATTR_DISALLOW, "") : "";
286 // XXX matter of interpretation: should updated permissions replace or extend previously set permissions?
287 myPermissions = parseVehicleClasses(allowS, disallowS);
288 }
289 // try to set the nodes
290 if (!setNodes(attrs)) {
291 // return if this failed
292 myCurrentEdge = nullptr;
293 return;
294 }
295 // try to get the shape
296 myShape = tryGetShape(attrs);
297 // try to get the spread type
299 // try to get the length
300 myLength = attrs.getOpt<double>(SUMO_ATTR_LENGTH, myCurrentID.c_str(), ok, myLength);
301 // try to get the sidewalkWidth
303 // try to get the bikeLaneWidth
305 // insert the parsed edge into the edges map
306 if (!ok) {
307 myCurrentEdge = nullptr;
308 return;
309 }
310 if (myFromNode == myToNode) {
311 // this might as well be an error. We make this a warning mostly for
312 // backward compatibility
313 WRITE_WARNINGF(TL("Ignoring self-looped edge '%' at junction '%'"), myCurrentID, myFromNode->getID());
314 myCurrentEdge = nullptr;
315 return;
316 }
317 // check whether a previously defined edge shall be overwritten
318 const bool applyLaneType = myCurrentEdge == nullptr;
319 if (myCurrentEdge != nullptr) {
325 } else {
326 // the edge must be allocated in dependence to whether a shape is given
327 if (myShape.size() == 0) {
331 } else {
336 }
337 }
338 myCurrentEdge->setLoadedLength(myLength);
340 myCurrentEdge->setPermissions(myPermissions);
341 }
342 // apply laneType if given
343 if (applyLaneType && myCurrentType != "" && myTypeCont.knows(myCurrentType)) {
344 const NBTypeCont::EdgeTypeDefinition* eType = myTypeCont.getEdgeType(myCurrentType);
345 if (eType->needsLaneType()) {
346 int lane = 0;
347 for (const NBTypeCont::LaneTypeDefinition& laneType : eType->laneTypeDefinitions) {
348 if (lane >= myCurrentLaneNo) {
349 break;
350 }
351 if (laneType.attrs.count(SUMO_ATTR_SPEED) > 0) {
352 myCurrentEdge->setSpeed(lane, laneType.speed);
353 }
354 if (laneType.attrs.count(SUMO_ATTR_FRICTION) > 0) {
355 myCurrentEdge->setFriction(lane, laneType.friction);
356 }
357 if (laneType.attrs.count(SUMO_ATTR_DISALLOW) > 0 || laneType.attrs.count(SUMO_ATTR_ALLOW) > 0) {
358 myCurrentEdge->setPermissions(laneType.permissions, lane);
359 }
360 if (laneType.attrs.count(SUMO_ATTR_WIDTH) > 0) {
361 myCurrentEdge->setLaneWidth(lane, laneType.width);
362 }
363 lane++;
364 }
365 }
366 }
367 // try to get the kilometrage/mileage
368 myCurrentEdge->setDistance(attrs.getOpt<double>(SUMO_ATTR_DISTANCE, myCurrentID.c_str(), ok, myCurrentEdge->getDistance()));
369 myCurrentEdge->setRoutingType(attrs.getOpt<std::string>(SUMO_ATTR_ROUTINGTYPE, myCurrentID.c_str(), ok, myCurrentEdge->getRoutingType()));
370 // preserve bidi edge (only as bool, the actual edge will be recomputed)
371 const std::string bidi = attrs.getOpt<std::string>(SUMO_ATTR_BIDI, myCurrentID.c_str(), ok, "");
372 myCurrentEdge->setBidi(myCurrentEdge->getBidiEdge() != nullptr || myCurrentEdge->isBidi() || bidi != "");
373
375}
376
377
378void
380 if (myCurrentEdge == nullptr) {
381 if (!OptionsCont::getOptions().isInStringVector("remove-edges.explicit", myCurrentID)) {
382 WRITE_ERRORF("Additional lane information could not be set - the edge with id '%s' is not known.", myCurrentID);
383 }
384 return;
385 }
386 bool ok = true;
387 int lane;
388 if (attrs.hasAttribute(SUMO_ATTR_ID)) {
389 lane = attrs.get<int>(SUMO_ATTR_ID, myCurrentID.c_str(), ok);
392 WRITE_WARNINGF(TL("'%' is deprecated, please use '%' instead."), toString(SUMO_ATTR_ID), toString(SUMO_ATTR_INDEX));
393 }
394 } else {
395 lane = attrs.get<int>(SUMO_ATTR_INDEX, myCurrentID.c_str(), ok);
396 }
397 if (!ok) {
398 return;
399 }
400 // check whether this lane exists
401 if (lane >= myCurrentEdge->getNumLanes()) {
402 WRITE_ERRORF(TL("Lane index is larger than number of lanes (edge '%')."), myCurrentID);
403 return;
404 }
405 myCurrentLaneIndex = lane;
406 // set information about allowed / disallowed vehicle classes (if specified)
408 const std::string allowed = attrs.getOpt<std::string>(SUMO_ATTR_ALLOW, nullptr, ok, "");
409 const std::string disallowed = attrs.getOpt<std::string>(SUMO_ATTR_DISALLOW, nullptr, ok, "");
410 myCurrentEdge->setPermissions(parseVehicleClasses(allowed, disallowed), lane);
411 }
412 if (attrs.hasAttribute(SUMO_ATTR_PREFER)) {
413 const std::string preferred = attrs.get<std::string>(SUMO_ATTR_PREFER, nullptr, ok);
414 myCurrentEdge->setPreferredVehicleClass(parseVehicleClasses(preferred), lane);
415 }
417 const std::string changeLeft = attrs.getOpt<std::string>(SUMO_ATTR_CHANGE_LEFT, nullptr, ok, "");
418 const std::string changeRight = attrs.getOpt<std::string>(SUMO_ATTR_CHANGE_RIGHT, nullptr, ok, "");
419 myCurrentEdge->setPermittedChanging(lane, parseVehicleClasses(changeLeft, ""), parseVehicleClasses(changeRight, ""));
420 }
421 // try to get the width
422 if (attrs.hasAttribute(SUMO_ATTR_WIDTH)) {
423 myCurrentEdge->setLaneWidth(lane, attrs.get<double>(SUMO_ATTR_WIDTH, myCurrentID.c_str(), ok));
424 }
425 // try to get the end-offset (lane shortened due to pedestrian crossing etc..)
427 myCurrentEdge->setEndOffset(lane, attrs.get<double>(SUMO_ATTR_ENDOFFSET, myCurrentID.c_str(), ok));
428 }
429 // try to get lane specific speed (should not occur for german networks)
430 if (attrs.hasAttribute(SUMO_ATTR_SPEED)) {
431 myCurrentEdge->setSpeed(lane, attrs.get<double>(SUMO_ATTR_SPEED, myCurrentID.c_str(), ok));
432 }
433 // try to get lane specific friction
434 if (attrs.hasAttribute(SUMO_ATTR_FRICTION)) {
435 myCurrentEdge->setFriction(lane, attrs.get<double>(SUMO_ATTR_FRICTION, myCurrentID.c_str(), ok));
436 }
437 // check whether this is an acceleration lane
439 myCurrentEdge->setAcceleration(lane, attrs.get<bool>(SUMO_ATTR_ACCELERATION, myCurrentID.c_str(), ok));
440 }
441 // check whether this lane has a custom shape
442 if (attrs.hasAttribute(SUMO_ATTR_SHAPE)) {
443 PositionVector shape = attrs.get<PositionVector>(SUMO_ATTR_SHAPE, myCurrentID.c_str(), ok);
445 const std::string laneID = myCurrentID + "_" + toString(lane);
446 WRITE_ERRORF(TL("Unable to project coordinates for lane '%'."), laneID);
447 }
448 if (shape.size() == 1) {
449 // lane shape of length 1 is not permitted
450 shape.push_front(myCurrentEdge->getFromNode()->getPosition());
451 shape.push_back(myCurrentEdge->getToNode()->getPosition());
452 }
453 shape.removeDoublePoints();
454 if (shape.size() < 2) {
455 // ignore lane shape for very short lanes
456 shape.clear();
457 }
458 myCurrentEdge->setLaneShape(lane, shape);
459 }
460 // set custom lane type
461 if (attrs.hasAttribute(SUMO_ATTR_TYPE)) {
462 myCurrentEdge->setLaneType(lane, attrs.get<std::string>(SUMO_ATTR_TYPE, myCurrentID.c_str(), ok));
463 }
464 myLastParameterised.push_back(&myCurrentEdge->getLaneStruct(lane));
465}
466
467
469 if (myCurrentEdge == nullptr) {
470 if (!OptionsCont::getOptions().isInStringVector("remove-edges.explicit", myCurrentID)) {
471 WRITE_WARNING(TL("Ignoring 'split' because it cannot be assigned to an edge"));
472 }
473 return;
474 }
475 bool ok = true;
477 e.pos = attrs.get<double>(SUMO_ATTR_POSITION, nullptr, ok);
478 if (ok) {
479 if (fabs(e.pos) > myCurrentEdge->getLoadedLength()) {
480 WRITE_ERRORF(TL("Edge '%' has a split at invalid position %."), myCurrentID, toString(e.pos));
481 return;
482 }
483 std::vector<NBEdgeCont::Split>::iterator i = find_if(mySplits.begin(), mySplits.end(), split_by_pos_finder(e.pos));
484 if (i != mySplits.end()) {
485 WRITE_ERRORF(TL("Edge '%' has already a split at position %."), myCurrentID, toString(e.pos));
486 return;
487 }
488 // XXX rounding to int may duplicate the id of another split
489 e.nameID = myCurrentID + "." + toString((int)e.pos);
490 if (e.pos < 0) {
491 e.pos += myCurrentEdge->getLoadedLength();
492 }
493 for (const std::string& id : attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_LANES, myCurrentID.c_str(), ok)) {
494 try {
495 int lane = StringUtils::toInt(id);
496 e.lanes.push_back(lane);
497 } catch (NumberFormatException&) {
498 WRITE_ERRORF(TL("Error on parsing a split (edge '%')."), myCurrentID);
499 } catch (EmptyData&) {
500 WRITE_ERRORF(TL("Error on parsing a split (edge '%')."), myCurrentID);
501 }
502 }
503 if (e.lanes.empty()) {
504 for (int l = 0; l < myCurrentEdge->getNumLanes(); ++l) {
505 e.lanes.push_back(l);
506 }
507 }
508 e.speed = attrs.getOpt(SUMO_ATTR_SPEED, nullptr, ok, myCurrentEdge->getSpeed());
509 if (attrs.hasAttribute(SUMO_ATTR_SPEED) && myOptions.getBool("speed-in-kmh")) {
510 e.speed /= 3.6;
511 }
512 e.idBefore = attrs.getOpt(SUMO_ATTR_ID_BEFORE, nullptr, ok, std::string(""));
513 e.idAfter = attrs.getOpt(SUMO_ATTR_ID_AFTER, nullptr, ok, std::string(""));
514 if (!ok) {
515 return;
516 }
517 const std::string nodeID = attrs.getOpt(SUMO_ATTR_ID, nullptr, ok, e.nameID);
518 if (nodeID == myCurrentEdge->getFromNode()->getID() || nodeID == myCurrentEdge->getToNode()->getID()) {
519 WRITE_ERRORF(TL("Invalid split node id for edge '%' (from- and to-node are forbidden)"), myCurrentEdge->getID());
520 return;
521 }
522 e.node = e.pos != 0 ? myNodeCont.retrieve(nodeID) : myCurrentEdge->getFromNode();
523 e.offset = attrs.getOpt(SUMO_ATTR_OFFSET, nullptr, ok, 0.0);
524 e.offsetFactor = OptionsCont::getOptions().getBool("lefthand") ? -1 : 1;
525 if (e.node == nullptr) {
526 double geomPos = e.pos;
527 if (myCurrentEdge->hasLoadedLength()) {
528 geomPos *= myCurrentEdge->getGeometry().length() / myCurrentEdge->getLoadedLength();
529 }
530 e.node = new NBNode(nodeID, myCurrentEdge->getGeometry().positionAtOffset(geomPos));
531 myNodeCont.insert(e.node);
532 }
535 mySplits.push_back(e);
536 }
537}
538
539
540bool
542 // the names and the coordinates of the beginning and the end node
543 // may be found, try
544 bool ok = true;
545 if (myIsUpdate) {
546 myFromNode = myCurrentEdge->getFromNode();
547 myToNode = myCurrentEdge->getToNode();
548 }
549 if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
550 const std::string begNodeID = attrs.get<std::string>(SUMO_ATTR_FROM, nullptr, ok);
551 if (begNodeID != "") {
552 myFromNode = myNodeCont.retrieve(begNodeID);
553 if (myFromNode == nullptr) {
554 WRITE_ERRORF(TL("Edge's '%' from-node '%' is not known."), myCurrentID, begNodeID);
555 }
556 }
557 } else if (!myIsUpdate) {
558 WRITE_ERRORF(TL("The from-node is not given for edge '%'."), myCurrentID);
559 ok = false;
560 }
561 if (attrs.hasAttribute(SUMO_ATTR_TO)) {
562 const std::string endNodeID = attrs.get<std::string>(SUMO_ATTR_TO, nullptr, ok);
563 if (endNodeID != "") {
564 myToNode = myNodeCont.retrieve(endNodeID);
565 if (myToNode == nullptr) {
566 WRITE_ERRORF(TL("Edge's '%' to-node '%' is not known."), myCurrentID, endNodeID);
567 }
568 }
569 } else if (!myIsUpdate) {
570 WRITE_ERRORF(TL("The to-node is not given for edge '%'."), myCurrentID);
571 ok = false;
572 }
573 return ok && myFromNode != nullptr && myToNode != nullptr;
574}
575
576
579 if (!attrs.hasAttribute(SUMO_ATTR_SHAPE) && myShape.size() > 0) {
580 return myShape;
581 }
582 // try to build shape
583 bool ok = true;
584 if (!attrs.hasAttribute(SUMO_ATTR_SHAPE)) {
585 const double maxSegmentLength = OptionsCont::getOptions().getFloat("geometry.max-segment-length");
586 if (maxSegmentLength > 0) {
587 PositionVector shape;
588 shape.push_back(myFromNode->getPosition());
589 shape.push_back(myToNode->getPosition());
590 // shape is already cartesian but we must use a copy because the original will be modified
591 NBNetBuilder::addGeometrySegments(shape, PositionVector(shape), maxSegmentLength);
592 return shape;
593 } else {
594 myReinitKeepEdgeShape = false;
595 return PositionVector();
596 }
597 }
598 PositionVector shape = attrs.getOpt<PositionVector>(SUMO_ATTR_SHAPE, nullptr, ok, PositionVector());
600 WRITE_ERRORF(TL("Unable to project coordinates for edge '%'."), myCurrentID);
601 }
603 return shape;
604}
605
606
609 bool ok = true;
611 std::string lsfS = toString(result);
612 lsfS = attrs.getOpt<std::string>(SUMO_ATTR_SPREADTYPE, myCurrentID.c_str(), ok, lsfS);
613 if (SUMOXMLDefinitions::LaneSpreadFunctions.hasString(lsfS)) {
615 } else {
616 WRITE_WARNINGF(TL("Ignoring unknown spreadType '%' for edge '%'."), lsfS, myCurrentID);
617 }
618 return result;
619}
620
621
622void
624 bool ok = true;
625 myCurrentID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
626 if (!ok) {
627 return;
628 }
629 NBEdge* edge = myEdgeCont.retrieve(myCurrentID);
630 if (edge == nullptr) {
631 WRITE_WARNING("Ignoring tag '" + toString(SUMO_TAG_DEL) + "' for unknown edge '" +
632 myCurrentID + "'");
633 return;
634 }
635 const int lane = attrs.getOpt<int>(SUMO_ATTR_INDEX, myCurrentID.c_str(), ok, -1);
636 if (lane < 0) {
637 myEdgeCont.extract(myDistrictCont, edge, true);
638 } else {
639 edge->deleteLane(lane, false, true);
640 }
641}
642
643
644void
646 if (element == SUMO_TAG_VIEWSETTINGS_EDGES) {
647 delete myLocation;
648 myLocation = nullptr;
649 return;
650 }
651 if (myCurrentEdge == nullptr) {
652 return;
653 }
654 if (element == SUMO_TAG_EDGE) {
655 myLastParameterised.pop_back();
656 // add bike lane, wait until lanes are loaded to avoid building if it already exists
658 myCurrentEdge->addBikeLane(myBikeLaneWidth);
659 }
660 // add sidewalk, wait until lanes are loaded to avoid building if it already exists
662 myCurrentEdge->addSidewalk(mySidewalkWidth);
663 }
664 // apply default stopOffsets of edge to all lanes without specified stopOffset.
665 const StopOffset stopOffsets = myCurrentEdge->getEdgeStopOffset();
666 if (stopOffsets.isDefined()) {
667 for (int i = 0; i < (int)myCurrentEdge->getLanes().size(); i++) {
668 myCurrentEdge->setEdgeStopOffset(i, stopOffsets, false);
669 }
670 }
671 if (!myIsUpdate) {
672 try {
673 if (!myEdgeCont.insert(myCurrentEdge)) {
674 WRITE_ERRORF(TL("Duplicate edge '%' occurred."), myCurrentID);
675 delete myCurrentEdge;
676 myCurrentEdge = nullptr;
677 return;
678 }
679 } catch (InvalidArgument& e) {
680 WRITE_ERROR(e.what());
681 throw;
682 } catch (...) {
683 WRITE_ERRORF(TL("An important information is missing in edge '%'."), myCurrentID);
684 }
685 }
687 myCurrentEdge = nullptr;
688 } else if (element == SUMO_TAG_LANE && myCurrentLaneIndex != -1) {
689 myLastParameterised.pop_back();
691 }
692}
693
694
695void
697 bool ok = true;
698 const std::vector<std::string>& edgeIDs = attrs.get<std::vector<std::string> >(SUMO_ATTR_EDGES, nullptr, ok);
699 if (ok) {
700 EdgeSet roundabout;
701 for (const std::string& eID : edgeIDs) {
702 NBEdge* edge = myEdgeCont.retrieve(eID);
703 if (edge == nullptr) {
704 if (!myEdgeCont.wasIgnored(eID)) {
705 WRITE_ERRORF(TL("Unknown edge '%' in roundabout."), eID);
706 }
707 } else {
708 roundabout.insert(edge);
709 }
710 }
711 myEdgeCont.addRoundabout(roundabout);
712 }
713}
714
715
716/****************************************************************************/
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
#define WRITE_MESSAGEF(...)
Definition MsgHandler.h:289
#define WRITE_ERRORF(...)
Definition MsgHandler.h:296
#define WRITE_ERROR(msg)
Definition MsgHandler.h:295
#define WRITE_WARNING(msg)
Definition MsgHandler.h:286
#define TL(string)
Definition MsgHandler.h:304
std::set< NBEdge * > EdgeSet
container for unique edges
Definition NBCont.h:50
const SVCPermissions SVC_UNSPECIFIED
permissions not specified
SVCPermissions parseVehicleClasses(const std::string &allowedS)
Parses the given definition of allowed vehicle classes into the given containers Deprecated classes g...
@ UNKNOWN
not defined
@ SUMO_TAG_STOPOFFSET
Information on vClass specific stop offsets at lane end.
@ SUMO_TAG_LOCATION
@ SUMO_TAG_ROUNDABOUT
roundabout defined in junction
@ SUMO_TAG_VIEWSETTINGS_EDGES
@ SUMO_TAG_LANE
begin/end of the description of a single lane
@ SUMO_TAG_PARAM
parameter associated to a certain key
@ SUMO_TAG_NEIGH
begin/end of the description of a neighboring lane
@ SUMO_TAG_SPLIT
split something
@ SUMO_TAG_DEL
delete certain element (note: DELETE is a macro)
@ SUMO_TAG_EDGE
begin/end of the description of an edge
LaneSpreadFunction
Numbers representing special SUMO-XML-attribute values Information how the edge's lateral offset shal...
SumoXMLNodeType
Numbers representing special SUMO-XML-attribute values for representing node- (junction-) types used ...
@ SUMO_ATTR_PREFER
@ SUMO_ATTR_DISALLOW
@ SUMO_ATTR_ALLOW
@ SUMO_ATTR_LANE
@ SUMO_ATTR_REMOVE
@ SUMO_ATTR_SPEED
@ SUMO_ATTR_VALUE
@ SUMO_ATTR_OFFSET
@ SUMO_ATTR_EDGES
the edges of a route
@ SUMO_ATTR_BIDI
@ SUMO_ATTR_PRIORITY
@ SUMO_ATTR_NUMLANES
@ SUMO_ATTR_LANES
@ SUMO_ATTR_SHAPE
edge: the shape in xml-definition
@ SUMO_ATTR_CHANGE_LEFT
@ SUMO_ATTR_INDEX
@ SUMO_ATTR_NAME
@ SUMO_ATTR_SPREADTYPE
The information about how to spread the lanes from the given position.
@ SUMO_ATTR_ENDOFFSET
@ SUMO_ATTR_TO
@ SUMO_ATTR_FROM
@ SUMO_ATTR_ACCELERATION
@ SUMO_ATTR_BIKELANEWIDTH
@ SUMO_ATTR_CHANGE_RIGHT
@ SUMO_ATTR_DISTANCE
@ SUMO_ATTR_ID_AFTER
@ SUMO_ATTR_SIDEWALKWIDTH
@ SUMO_ATTR_TYPE
@ SUMO_ATTR_LENGTH
@ SUMO_ATTR_ID
@ SUMO_ATTR_WIDTH
@ SUMO_ATTR_KEY
@ SUMO_ATTR_POSITION
@ SUMO_ATTR_FRICTION
@ SUMO_ATTR_ID_BEFORE
@ SUMO_ATTR_ROUTINGTYPE
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:49
const std::string & getFileName() const
returns the current file name
static GeoConvHelper * getLoadedPlain(const std::string &plainFile, const std::string &suffix=".edg.xml")
A container for districts.
Storage for edges, including some functionality operating on multiple edges.
Definition NBEdgeCont.h:59
The representation of a single edge during network building.
Definition NBEdge.h:92
static const double UNSPECIFIED_FRICTION
unspecified lane friction
Definition NBEdge.h:355
static const double UNSPECIFIED_LOADED_LENGTH
no length override given
Definition NBEdge.h:364
void deleteLane(int index, bool recompute, bool shiftIndices)
delete lane
Definition NBEdge.cpp:4248
static const double UNSPECIFIED_SPEED
unspecified lane speed
Definition NBEdge.h:352
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition NBEdge.h:346
static const double UNSPECIFIED_OFFSET
unspecified lane offset
Definition NBEdge.h:349
static bool transformCoordinates(PositionVector &from, bool includeInBoundary=true, GeoConvHelper *from_srs=nullptr)
static int addGeometrySegments(PositionVector &from, const PositionVector &cartesian, const double maxLength)
insertion geometry points to ensure maximum segment length between points
Container for nodes during the netbuilding process.
Definition NBNodeCont.h:57
Represents a single node (junction) during network building.
Definition NBNode.h:66
const Position & getPosition() const
Definition NBNode.h:260
A container for traffic light definitions and built programs.
A storage for available edgeTypes of edges.
Definition NBTypeCont.h:52
static GeoConvHelper * loadLocation(const SUMOSAXAttributes &attrs, bool setLoaded=true)
Parses network location description and registers it with GeoConveHelper::setLoaded.
Finds a split at the given position.
std::string myCurrentID
The current edge's id.
SVCPermissions myPermissions
Information about lane permissions.
bool setNodes(const SUMOSAXAttributes &attrs)
Sets from/to node information of the currently parsed edge.
PositionVector myShape
The shape of the edge.
std::string myCurrentStreetName
The current edge's street name.
LaneSpreadFunction tryGetLaneSpread(const SUMOSAXAttributes &attrs)
Tries to parse the spread type.
double myCurrentSpeed
The current edge's maximum speed.
double myBikeLaneWidth
The width of the bike lane that shall be added to the current edge.
~NIXMLEdgesHandler()
Destructor.
int myCurrentLaneNo
The current edge's number of lanes.
GeoConvHelper * myLocation
The coordinate transformation which was used compute the node coordinates.
OptionsCont & myOptions
A reference to the program's options.
void addRoundabout(const SUMOSAXAttributes &attrs)
Parses a roundabout and stores it in myEdgeCont.
double myCurrentWidth
The current edge's lane width.
NIXMLEdgesHandler(NBNodeCont &nc, NBEdgeCont &ec, NBTypeCont &tc, NBDistrictCont &dc, NBTrafficLightLogicCont &tlc, OptionsCont &options)
Constructor.
NBTypeCont & myTypeCont
The types container (for retrieval of type defaults).
double myCurrentEndOffset
The current edge's offset till the destination node.
double myLength
The current edge's length.
int myCurrentPriority
The current edge's priority.
NBNodeCont & myNodeCont
The nodes container (for retrieval of referenced nodes).
PositionVector tryGetShape(const SUMOSAXAttributes &attrs)
Tries to parse the shape definition.
bool myIsUpdate
Whether this edge definition is an update of a previously inserted edge.
void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
LaneSpreadFunction myLanesSpread
Information about how to spread the lanes.
NBDistrictCont & myDistrictCont
The districts container (needed if an edge must be split).
std::vector< Parameterised * > myLastParameterised
element to receive parameters
NBEdgeCont & myEdgeCont
The edges container (for insertion of build edges).
double mySidewalkWidth
The width of the sidewalk that shall be added to the current edge.
void addSplit(const SUMOSAXAttributes &attrs)
Parses a split and stores it in mySplits. Splits are executed Upon reading the end tag of an edge.
std::string myCurrentType
The current edge's type.
NBEdge * myCurrentEdge
The currently processed edge.
NBTrafficLightLogicCont & myTLLogicCont
The traffic lights container to add built tls to (when invalidating tls because of splits).
std::vector< NBEdgeCont::Split > mySplits
The list of this edge's splits.
double myCurrentFriction
The current edge's friction.
int myCurrentLaneIndex
The currently processed lane index.
bool myHaveReportedAboutTypeOverride
Information whether at least one edge's type was changed.
SumoXMLNodeType myDefaultNodeType
the default node type for splits
NBNode * myFromNode
The nodes the edge starts and ends at.
void addLane(const SUMOSAXAttributes &attrs)
Parses a lane and modifies myCurrentEdge according to the given attribures.
void myEndElement(int element)
Called when a closing tag occurs.
const bool myKeepEdgeShape
Whether the edge shape shall be kept generally.
bool myHaveReportedAboutOverwriting
Information whether at least one edge's attributes were overwritten.
void deleteEdge(const SUMOSAXAttributes &attrs)
parses delete tag and deletes the specified edge or lane
bool myReinitKeepEdgeShape
Whether the edge shape shall be kept at reinitilization.
void addEdge(const SUMOSAXAttributes &attrs)
Parses an edge and stores the values in "myCurrentEdge".
static NBNode * processNodeType(const SUMOSAXAttributes &attrs, NBNode *node, const std::string &nodeID, const Position &position, bool updateEdgeGeometries, SumoXMLNodeType type, NBNodeCont &nc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc, GeoConvHelper *from_srs=nullptr)
parses node attributes (not related to positioning)
const std::string & getID() const
Returns the id.
Definition Named.h:73
A storage for options typed value containers).
Definition OptionsCont.h:89
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float).
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool).
static OptionsCont & getOptions()
Retrieves the options.
A list of positions.
void push_front(const Position &p)
insert in front a Position
void removeDoublePoints(double minDist=POSITION_EPS, bool assertLength=false, int beginOffset=0, int endOffset=0, bool resample=false)
Removes positions if too near.
Encapsulated SAX-Attributes.
virtual std::string getString(int id, bool *isPresent=nullptr) const =0
Returns the string-value of the named (by its enum-value) attribute.
T getOpt(int attr, const char *objectid, bool &ok, T defaultValue=T(), bool report=true) const
Tries to read given attribute assuming it is an int.
virtual std::string getStringSecure(int id, const std::string &def) const =0
Returns the string-value of the named (by its enum-value) attribute.
T get(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is an int.
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list.
SUMOSAXHandler(const std::string &file="", const std::string &expectedRoot="")
Constructor.
class for maintaining associations between enums and xml-strings
static StringBijection< LaneSpreadFunction > LaneSpreadFunctions
lane spread functions
stop offset
bool isDefined() const
check if stopOffset was defined
double getOffset() const
get offset
static int toInt(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter,...
A structure which describes changes of lane number or speed along the road.
Definition NBEdgeCont.h:189
int offsetFactor
direction in which to apply the offset (used by netgenerate for lefthand networks)
Definition NBEdgeCont.h:209
double speed
The speed after this change.
Definition NBEdgeCont.h:195
double offset
lateral offset to edge geometry
Definition NBEdgeCont.h:207
std::string nameID
the default node id
Definition NBEdgeCont.h:205
std::string idBefore
The id for the edge before the split.
Definition NBEdgeCont.h:201
double pos
The position of this change.
Definition NBEdgeCont.h:193
std::vector< int > lanes
The lanes after this change.
Definition NBEdgeCont.h:191
std::string idAfter
The id for the edge after the split.
Definition NBEdgeCont.h:203
NBNode * node
The new node that is created for this split.
Definition NBEdgeCont.h:199
edgeType definition
Definition NBTypeCont.h:93
bool needsLaneType() const
whether any lane attributes deviate from the edge attributes
std::vector< LaneTypeDefinition > laneTypeDefinitions
vector with LaneTypeDefinitions
Definition NBTypeCont.h:158
laneType definition
Definition NBTypeCont.h:59
double speed
The maximal velocity on a lane in m/s.
Definition NBTypeCont.h:74
double friction
The default friction on a lane.
Definition NBTypeCont.h:77
SVCPermissions permissions
List of vehicle edgeTypes that are allowed on this lane.
Definition NBTypeCont.h:80
std::set< SumoXMLAttr > attrs
The attributes which have been set.
Definition NBTypeCont.h:89
double width
lane width [m]
Definition NBTypeCont.h:83