Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
NIXMLNodesHandler.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-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/****************************************************************************/
21// Importer for network nodes stored in XML
22/****************************************************************************/
23#include <config.h>
24
25#include <string>
26#include <iostream>
35#include <netbuild/NBNodeCont.h>
37#include <netbuild/NBOwnTLDef.h>
39#include "NIXMLNodesHandler.h"
40#include "NIImporter_SUMO.h"
41
42
43// ===========================================================================
44// method definitions
45// ===========================================================================
48 OptionsCont& options) :
49 SUMOSAXHandler("xml-nodes - file"),
50 myOptions(options),
51 myNodeCont(nc),
52 myEdgeCont(ec),
53 myTLLogicCont(tlc),
54 myLocation(nullptr),
55 myLastParameterised(nullptr) {
56}
57
58
62
63
64void
66 const SUMOSAXAttributes& attrs) {
67 switch (element) {
69 delete myLocation;
71 if (myLocation) {
73 }
74 break;
75 case SUMO_TAG_NODE:
76 addNode(attrs);
77 break;
78 case SUMO_TAG_JOIN:
79 addJoinCluster(attrs);
80 break;
82 addJoinExclusion(attrs);
83 break;
84 case SUMO_TAG_DEL:
85 deleteNode(attrs);
86 break;
87 case SUMO_TAG_PARAM:
88 if (myLastParameterised != nullptr) {
89 bool ok = true;
90 const std::string key = attrs.get<std::string>(SUMO_ATTR_KEY, nullptr, ok);
91 // circumventing empty string test
92 const std::string val = attrs.hasAttribute(SUMO_ATTR_VALUE) ? attrs.getString(SUMO_ATTR_VALUE) : "";
94 }
95 break;
96 default:
97 break;
98 }
99}
100
101
102void
104 switch (element) {
105 case SUMO_TAG_NODE:
106 myLastParameterised = nullptr;
107 break;
108 default:
109 break;
110 }
111}
112
113
114void
116 bool ok = true;
117 // get the id, report a warning if not given or empty...
118 myID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
119 if (!ok) {
120 return;
121 }
123 // retrieve the position of the node
124 bool xOk = false;
125 bool yOk = false;
126 bool needConversion = true;
127 if (node != nullptr) {
128 myPosition = node->getPosition();
129 xOk = yOk = true;
130 needConversion = false;
131 } else {
132 myPosition.set(0, 0, 0); // better to reset than to reuse the previous (z)-value
133 }
134 if (attrs.hasAttribute(SUMO_ATTR_X)) {
135 myPosition.set(attrs.get<double>(SUMO_ATTR_X, myID.c_str(), ok), myPosition.y());
136 xOk = true;
137 needConversion = true;
138 }
139 if (attrs.hasAttribute(SUMO_ATTR_Y)) {
140 myPosition.set(myPosition.x(), attrs.get<double>(SUMO_ATTR_Y, myID.c_str(), ok));
141 yOk = true;
142 needConversion = true;
143 }
144 if (attrs.hasAttribute(SUMO_ATTR_Z)) {
145 myPosition.set(myPosition.x(), myPosition.y(), attrs.get<double>(SUMO_ATTR_Z, myID.c_str(), ok));
146 }
147 if (xOk && yOk) {
148 if (needConversion && !NBNetBuilder::transformCoordinate(myPosition, true, myLocation)) {
149 WRITE_ERRORF(TL("Unable to project coordinates for node '%'."), myID);
150 }
151 } else {
152 WRITE_ERRORF(TL("Missing position (at node ID='%')."), myID);
153 }
154 bool updateEdgeGeometries = node != nullptr && myPosition != node->getPosition();
155 node = processNodeType(attrs, node, myID, myPosition, updateEdgeGeometries, myNodeCont, myEdgeCont, myTLLogicCont, myLocation);
156 myLastParameterised = node;
157}
158
159
160NBNode*
161NIXMLNodesHandler::processNodeType(const SUMOSAXAttributes& attrs, NBNode* node, const std::string& nodeID, const Position& position,
162 bool updateEdgeGeometries,
164 GeoConvHelper* from_srs) {
165 bool ok = true;
166 // get the type
168 if (node != nullptr) {
169 type = node->getType();
170 }
171 std::string typeS = attrs.getOpt<std::string>(SUMO_ATTR_TYPE, nodeID.c_str(), ok, "");
172 if (SUMOXMLDefinitions::NodeTypes.hasString(typeS)) {
175 // dead end is a computed status. Reset this to unknown so it will
176 // be corrected if additional connections are loaded
178 }
179 }
180 std::set<NBTrafficLightDefinition*> oldTLS;
181 // check whether a prior node shall be modified
182 const bool isPatch = node != nullptr;
183 if (node == nullptr) {
184 node = new NBNode(nodeID, position, type);
185 if (!nc.insert(node)) {
186 throw ProcessError(TLF("Could not insert node though checked this before (id='%').", nodeID));
187 }
188 } else {
189 // patch information
190 oldTLS = node->getControllingTLS();
193 ec.removeRoundabout(node);
194 }
195 node->reinit(position, type, updateEdgeGeometries);
196 }
197 // process traffic light definition
198 if (NBNode::isTrafficLight(type)) {
199 processTrafficLightDefinitions(attrs, node, tlc);
200 } else if (isPatch && typeS != "") {
201 nc.markAsNotTLS(node);
202 }
203 // remove previously set tls if this node is not controlled by them
204 for (std::set<NBTrafficLightDefinition*>::iterator i = oldTLS.begin(); i != oldTLS.end(); ++i) {
205 if ((*i)->getNodes().size() == 0) {
206 tlc.removeFully((*i)->getID());
207 }
208 }
209
210 // set optional shape
211 PositionVector shape;
212 if (attrs.hasAttribute(SUMO_ATTR_SHAPE)) {
213 shape = attrs.getOpt<PositionVector>(SUMO_ATTR_SHAPE, nodeID.c_str(), ok, PositionVector());
214 if (!NBNetBuilder::transformCoordinates(shape, true, from_srs)) {
215 WRITE_ERRORF(TL("Unable to project node shape at node '%'."), node->getID());
216 }
217 if (shape.size() > 2) {
218 shape.closePolygon();
219 }
220 node->setCustomShape(shape);
221 }
222 // set optional radius
223 if (attrs.hasAttribute(SUMO_ATTR_RADIUS)) {
224 node->setRadius(attrs.get<double>(SUMO_ATTR_RADIUS, nodeID.c_str(), ok));
225 }
226 // set optional keepClear flag
228 node->setKeepClear(attrs.get<bool>(SUMO_ATTR_KEEP_CLEAR, nodeID.c_str(), ok));
229 }
230 node->setRightOfWay(attrs.getOpt<RightOfWay>(SUMO_ATTR_RIGHT_OF_WAY, nodeID.c_str(), ok, node->getRightOfWay()));
231 node->setFringeType(attrs.getOpt<FringeType>(SUMO_ATTR_FRINGE, nodeID.c_str(), ok, node->getFringeType()));
232 // set optional name
233 if (attrs.hasAttribute(SUMO_ATTR_NAME)) {
234 node->setName(attrs.get<std::string>(SUMO_ATTR_NAME, nodeID.c_str(), ok));
235 }
236 return node;
237}
238
239
240void
242 bool ok = true;
243 // get the id, report a warning if not given or empty...
244 myID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
245 if (!ok) {
246 return;
247 }
249 if (node == nullptr) {
250 WRITE_WARNING("Ignoring tag '" + toString(SUMO_TAG_DEL) + "' for unknown node '" +
251 myID + "'");
252 return;
253 } else {
254 myNodeCont.extract(node, true);
255 }
256}
257
258
259void
261 bool ok = true;
262 const std::string clusterString = attrs.get<std::string>(SUMO_ATTR_NODES, nullptr, ok);
263 const std::set<std::string>& cluster = StringTokenizer(clusterString).getSet();
264
265 myID = attrs.getOpt<std::string>(SUMO_ATTR_ID, nullptr, ok, myNodeCont.createClusterId(cluster));
266
268 if (attrs.hasAttribute(SUMO_ATTR_X)) {
269 pos.setx(attrs.get<double>(SUMO_ATTR_X, myID.c_str(), ok));
270 }
271 if (attrs.hasAttribute(SUMO_ATTR_Y)) {
272 pos.sety(attrs.get<double>(SUMO_ATTR_Y, myID.c_str(), ok));
273 }
274 if (attrs.hasAttribute(SUMO_ATTR_Z)) {
275 pos.setz(attrs.get<double>(SUMO_ATTR_Z, myID.c_str(), ok));
276 }
277
278 NBNode* node = processNodeType(attrs, nullptr, myID, pos, false, myNodeCont, myEdgeCont, myTLLogicCont, myLocation);
279 if (ok) {
280 myNodeCont.addCluster2Join(cluster, node);
281 }
282}
283
284
285void
287 bool ok = true;
288 const std::vector<std::string> ids = StringTokenizer(
289 attrs.get<std::string>(SUMO_ATTR_NODES, nullptr, ok)).getVector();
290 if (ok) {
292 }
293}
294
295
296void
298 NBNode* currentNode, NBTrafficLightLogicCont& tlc) {
299 // try to get the tl-id
300 // if a tl-id is given, we will look whether this tl already exists
301 // if so, we will add the node to it (and to all programs with this id), otherwise allocate a new one with this id
302 // if no tl-id exists, we will build a tl with the node's id
303 std::set<NBTrafficLightDefinition*> tlDefs;
304 bool ok = true;
305
306 std::string oldTlID = "";
307 std::string oldTypeS = OptionsCont::getOptions().getString("tls.default-type");
308
309 if (currentNode->isTLControlled()) {
310 NBTrafficLightDefinition* oldDef = *(currentNode->getControllingTLS().begin());
311 oldTlID = oldDef->getID();
312 oldTypeS = toString(oldDef->getType());
313 }
314 std::string tlID = attrs.getOpt<std::string>(SUMO_ATTR_TLID, nullptr, ok, oldTlID);
315 std::string typeS = attrs.getOpt<std::string>(SUMO_ATTR_TLTYPE, nullptr, ok, oldTypeS);
316 if (tlID != oldTlID || typeS != oldTypeS) {
317 currentNode->removeTrafficLights();
318 }
319 TrafficLightType type;
320 if (SUMOXMLDefinitions::TrafficLightTypes.hasString(typeS)) {
322 } else {
323 WRITE_ERRORF(TL("Unknown traffic light type '%' for node '%'."), typeS, currentNode->getID());
324 return;
325 }
327 if (attrs.hasAttribute(SUMO_ATTR_TLLAYOUT)) {
328 std::string layoutS = attrs.get<std::string>(SUMO_ATTR_TLLAYOUT, nullptr, ok);
329 if (SUMOXMLDefinitions::TrafficLightLayouts.hasString(layoutS)) {
331 } else {
332 WRITE_ERRORF(TL("Unknown traffic light layout '%' for node '%'."), typeS, currentNode->getID());
333 return;
334 }
335 }
336 if (tlID != "" && tlc.getPrograms(tlID).size() > 0) {
337 // we already have definitions for this tlID
338 for (auto item : tlc.getPrograms(tlID)) {
339 NBTrafficLightDefinition* def = item.second;
340 tlDefs.insert(def);
341 def->addNode(currentNode);
342 if (def->getType() != type && attrs.hasAttribute(SUMO_ATTR_TLTYPE)) {
343 WRITE_WARNINGF(TL("Changing traffic light type '%' to '%' for tl '%'."), toString(def->getType()), typeS, tlID);
344 def->setType(type);
345 if (type != TrafficLightType::STATIC && dynamic_cast<NBLoadedSUMOTLDef*>(def) != nullptr) {
346 dynamic_cast<NBLoadedSUMOTLDef*>(def)->guessMinMaxDuration();
347 }
348 }
349 if (layout != TrafficLightLayout::DEFAULT && dynamic_cast<NBOwnTLDef*>(def) != nullptr) {
350 dynamic_cast<NBOwnTLDef*>(def)->setLayout(layout);
351 }
352 }
353 } else {
354 // we need to add a new defition
355 tlID = (tlID == "" ? currentNode->getID() : tlID);
356 NBOwnTLDef* tlDef = new NBOwnTLDef(tlID, currentNode, 0, type);
357 if (!tlc.insert(tlDef)) {
358 // actually, nothing should fail here
359 delete tlDef;
360 throw ProcessError(TLF("Could not allocate tls '%'.", currentNode->getID()));
361 }
362 tlDef->setLayout(layout);
363 tlDefs.insert(tlDef);
364 }
365 // process inner edges which shall be controlled
366 const std::vector<std::string>& controlledInner = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_CONTROLLED_INNER, nullptr, ok);
367 if (controlledInner.size() != 0) {
368 for (std::set<NBTrafficLightDefinition*>::iterator it = tlDefs.begin(); it != tlDefs.end(); it++) {
369 (*it)->addControlledInnerEdges(controlledInner);
370 }
371 }
372}
373
374
375/****************************************************************************/
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:296
#define WRITE_ERRORF(...)
Definition MsgHandler.h:305
#define WRITE_WARNING(msg)
Definition MsgHandler.h:295
#define TL(string)
Definition MsgHandler.h:315
#define TLF(string,...)
Definition MsgHandler.h:317
@ SUMO_TAG_JOINEXCLUDE
join exlude operation
@ SUMO_TAG_LOCATION
@ SUMO_TAG_JOIN
Join operation.
@ SUMO_TAG_NODE
alternative definition for junction
@ SUMO_TAG_PARAM
parameter associated to a certain key
@ SUMO_TAG_DEL
delete certain element (note: DELETE is a macro)
TrafficLightLayout
FringeType
classifying boundary nodes
SumoXMLNodeType
Numbers representing special SUMO-XML-attribute values for representing node- (junction-) types used ...
RightOfWay
algorithms for computing right of way
@ SUMO_ATTR_NODES
a list of node ids, used for controlling joining
@ SUMO_ATTR_VALUE
@ SUMO_ATTR_RADIUS
The turning radius at an intersection in m.
@ SUMO_ATTR_Y
@ SUMO_ATTR_Z
@ SUMO_ATTR_X
@ SUMO_ATTR_TLLAYOUT
node: the layout of the traffic light program
@ SUMO_ATTR_FRINGE
Fringe type of node.
@ SUMO_ATTR_SHAPE
edge: the shape in xml-definition
@ SUMO_ATTR_TLTYPE
node: the type of traffic light
@ SUMO_ATTR_NAME
@ SUMO_ATTR_TLID
link,node: the traffic light id responsible for this link
@ SUMO_ATTR_TYPE
@ SUMO_ATTR_ID
@ SUMO_ATTR_RIGHT_OF_WAY
How to compute right of way.
@ SUMO_ATTR_CONTROLLED_INNER
@ SUMO_ATTR_KEY
@ SUMO_ATTR_KEEP_CLEAR
Whether vehicles must keep the junction clear.
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
const std::string & getFileName() const
returns the current file name
static methods for processing the coordinates conversion for the current net
static void setLoadedPlain(const std::string &nodFile, const GeoConvHelper &loaded)
registers the coordinate transformation as having been loaded from the given file
Storage for edges, including some functionality operating on multiple edges.
Definition NBEdgeCont.h:59
void removeRoundabout(const NBNode *node)
remove roundabout that contains the given node
A loaded (complete) traffic light logic.
static bool transformCoordinates(PositionVector &from, bool includeInBoundary=true, GeoConvHelper *from_srs=nullptr)
static bool transformCoordinate(Position &from, bool includeInBoundary=true, GeoConvHelper *from_srs=nullptr)
transforms loaded coordinates handles projections, offsets (using GeoConvHelper) and import of height...
Container for nodes during the netbuilding process.
Definition NBNodeCont.h:57
void markAsNotTLS(const NBNode *node)
mark a node as explicitly not controlled by a TLS
Definition NBNodeCont.h:368
std::string createClusterId(const NodeSet &cluster, const std::string &prefix="cluster_")
generate id from cluster node ids
Definition NBNodeCont.h:136
void addJoinExclusion(const std::vector< std::string > &ids)
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
bool extract(NBNode *node, bool remember=false)
Removes the given node but does not delete it.
void addCluster2Join(const std::set< std::string > &cluster, NBNode *node)
add ids of nodes which shall be joined into a single node
Represents a single node (junction) during network building.
Definition NBNode.h:66
RightOfWay getRightOfWay() const
Returns hint on how to compute right of way.
Definition NBNode.h:300
const std::set< NBTrafficLightDefinition * > & getControllingTLS() const
Returns the traffic lights that were assigned to this node (The set of tls that control this node)
Definition NBNode.h:336
void reinit(const Position &position, SumoXMLNodeType type, bool updateEdgeGeometries=false)
Resets initial values.
Definition NBNode.cpp:338
FringeType getFringeType() const
Returns fringe type.
Definition NBNode.h:305
SumoXMLNodeType getType() const
Returns the type of this node.
Definition NBNode.h:285
bool isTrafficLight() const
Definition NBNode.h:822
void setRightOfWay(RightOfWay rightOfWay)
set method for computing right-of-way
Definition NBNode.h:569
void setCustomShape(const PositionVector &shape)
set the junction shape
Definition NBNode.cpp:2673
void setKeepClear(bool keepClear)
set the keepClear flag
Definition NBNode.h:564
void removeTrafficLights(bool setAsPriority=false)
Removes all references to traffic lights that control this tls.
Definition NBNode.cpp:413
void setRadius(double radius)
set the turning radius
Definition NBNode.h:559
void setName(const std::string &name)
set intersection name
Definition NBNode.h:579
const Position & getPosition() const
Definition NBNode.h:260
void setFringeType(FringeType fringeType)
set method for computing right-of-way
Definition NBNode.h:574
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition NBNode.h:331
A traffic light logics which must be computed (only nodes/edges are given)
Definition NBOwnTLDef.h:44
void setLayout(TrafficLightLayout layout)
sets the layout for the generated signal plan
Definition NBOwnTLDef.h:143
The base class for traffic light logic definitions.
TrafficLightType getType() const
get the algorithm type (static etc..)
virtual void addNode(NBNode *node)
Adds a node to the traffic light logic.
virtual void setType(TrafficLightType type)
set the algorithm type (static etc..)
A container for traffic light definitions and built programs.
const std::map< std::string, NBTrafficLightDefinition * > & getPrograms(const std::string &id) const
Returns all programs for the given tl-id.
bool removeFully(const std::string id)
Removes a logic definition (and all programs) from the dictionary.
bool insert(NBTrafficLightDefinition *logic, bool forceInsert=false)
Adds a logic definition to the dictionary.
static GeoConvHelper * loadLocation(const SUMOSAXAttributes &attrs, bool setLoaded=true)
Parses network location description and registers it with GeoConveHelper::setLoaded.
~NIXMLNodesHandler()
Destructor.
std::string myID
The id of the currently parsed node.
void addJoinCluster(const SUMOSAXAttributes &attrs)
GeoConvHelper * myLocation
The coordinate transformation which was used compute the node coordinates.
Position myPosition
The position of the currently parsed node.
NBNodeCont & myNodeCont
The node container to add built nodes to.
void deleteNode(const SUMOSAXAttributes &attrs)
NBTrafficLightLogicCont & myTLLogicCont
The traffic lights container to add built tls to.
static NBNode * processNodeType(const SUMOSAXAttributes &attrs, NBNode *node, const std::string &nodeID, const Position &position, bool updateEdgeGeometries, NBNodeCont &nc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc, GeoConvHelper *from_srs=nullptr)
parses node attributes (not related to positioning)
static void processTrafficLightDefinitions(const SUMOSAXAttributes &attrs, NBNode *currentNode, NBTrafficLightLogicCont &tlc)
Builds the defined traffic light or adds a node to it.
NBEdgeCont & myEdgeCont
The node container to add built nodes to.
Parameterised * myLastParameterised
last item the could receive parameters
void myEndElement(int element)
Called when a closing tag occurs.
void addNode(const SUMOSAXAttributes &attrs)
void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
NIXMLNodesHandler(NBNodeCont &nc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc, OptionsCont &options)
Constructor.
void addJoinExclusion(const SUMOSAXAttributes &attrs)
const std::string & getID() const
Returns the id.
Definition Named.h:74
A storage for options typed value containers)
Definition OptionsCont.h:89
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
static OptionsCont & getOptions()
Retrieves the options.
virtual void setParameter(const std::string &key, const std::string &value)
Sets a parameter.
A point in 2D or 3D with translation and scaling methods.
Definition Position.h:37
void setx(double x)
set position x
Definition Position.h:70
void set(double x, double y)
set positions x and y
Definition Position.h:85
static const Position INVALID
used to indicate that a position is valid
Definition Position.h:322
double x() const
Returns the x-position.
Definition Position.h:55
double y() const
Returns the y-position.
Definition Position.h:60
A list of positions.
void closePolygon()
ensures that the last position equals the first
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.
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.
SAX-handler base for SUMO-files.
static StringBijection< SumoXMLNodeType > NodeTypes
node types
static StringBijection< TrafficLightType > TrafficLightTypes
traffic light types
static StringBijection< TrafficLightLayout > TrafficLightLayouts
traffic light layouts
T get(const std::string &str) const
std::set< std::string > getSet()
return set of strings
std::vector< std::string > getVector()
return vector of strings