SUMO - Simulation of Urban MObility
NWWriter_SUMO.cpp
Go to the documentation of this file.
1 /****************************************************************************/
9 // Exporter writing networks using the SUMO format
10 /****************************************************************************/
11 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
12 // Copyright (C) 2001-2017 DLR (http://www.dlr.de/) and contributors
13 /****************************************************************************/
14 //
15 // This file is part of SUMO.
16 // SUMO is free software: you can redistribute it and/or modify
17 // it under the terms of the GNU General Public License as published by
18 // the Free Software Foundation, either version 3 of the License, or
19 // (at your option) any later version.
20 //
21 /****************************************************************************/
22 
23 
24 // ===========================================================================
25 // included modules
26 // ===========================================================================
27 #ifdef _MSC_VER
28 #include <windows_config.h>
29 #else
30 #include <config.h>
31 #endif
32 #include <cmath>
33 #include <algorithm>
37 #include <utils/common/ToString.h>
41 #include <netbuild/NBEdge.h>
42 #include <netbuild/NBEdgeCont.h>
43 #include <netbuild/NBNode.h>
44 #include <netbuild/NBNodeCont.h>
45 #include <netbuild/NBNetBuilder.h>
47 #include <netbuild/NBDistrict.h>
48 #include "NWFrame.h"
49 #include "NWWriter_SUMO.h"
50 
51 #ifdef CHECK_MEMORY_LEAKS
52 #include <foreign/nvwa/debug_new.h>
53 #endif // CHECK_MEMORY_LEAKS
54 
55 
56 
57 // ===========================================================================
58 // method definitions
59 // ===========================================================================
60 // ---------------------------------------------------------------------------
61 // static methods
62 // ---------------------------------------------------------------------------
63 void
65  // check whether a sumo net-file shall be generated
66  if (!oc.isSet("output-file")) {
67  return;
68  }
69  OutputDevice& device = OutputDevice::getDevice(oc.getString("output-file"));
70  std::map<SumoXMLAttr, std::string> attrs;
72  if (oc.getBool("lefthand")) {
73  attrs[SUMO_ATTR_LEFTHAND] = "true";
74  }
75  const int cornerDetail = oc.getInt("junctions.corner-detail");
76  if (cornerDetail > 0) {
77  attrs[SUMO_ATTR_CORNERDETAIL] = toString(cornerDetail);
78  }
79  if (!oc.isDefault("junctions.internal-link-detail")) {
80  attrs[SUMO_ATTR_LINKDETAIL] = toString(oc.getInt("junctions.internal-link-detail"));
81  }
82  device.writeXMLHeader("net", "net_file.xsd", attrs); // street names may contain non-ascii chars
83  device.lf();
84  // get involved container
85  const NBNodeCont& nc = nb.getNodeCont();
86  const NBEdgeCont& ec = nb.getEdgeCont();
87  const NBDistrictCont& dc = nb.getDistrictCont();
88 
89  // write network offsets and projection
91 
92  // write edge types and restrictions
93  nb.getTypeCont().writeTypes(device);
94 
95  // write inner lanes
96  bool origNames = oc.getBool("output.original-names");
97  if (!oc.getBool("no-internal-links")) {
98  bool hadAny = false;
99  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
100  hadAny |= writeInternalEdges(device, ec, *(*i).second, origNames);
101  }
102  if (hadAny) {
103  device.lf();
104  }
105  }
106 
107  // write edges with lanes and connected edges
108  bool noNames = !oc.getBool("output.street-names");
109  for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
110  writeEdge(device, *(*i).second, noNames, origNames);
111  }
112  device.lf();
113 
114  // write tls logics
115  writeTrafficLights(device, nb.getTLLogicCont());
116 
117  // write the nodes (junctions)
118  std::set<NBNode*> roundaboutNodes;
119  const bool checkLaneFoesAll = oc.getBool("check-lane-foes.all");
120  const bool checkLaneFoesRoundabout = !checkLaneFoesAll && oc.getBool("check-lane-foes.roundabout");
121  if (checkLaneFoesRoundabout) {
122  const std::set<EdgeSet>& roundabouts = ec.getRoundabouts();
123  for (std::set<EdgeSet>::const_iterator i = roundabouts.begin(); i != roundabouts.end(); ++i) {
124  for (EdgeSet::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
125  roundaboutNodes.insert((*j)->getToNode());
126  }
127  }
128  }
129  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
130  const bool checkLaneFoes = checkLaneFoesAll || (checkLaneFoesRoundabout && roundaboutNodes.count((*i).second) > 0);
131  writeJunction(device, *(*i).second, checkLaneFoes);
132  }
133  device.lf();
134  const bool includeInternal = !oc.getBool("no-internal-links");
135  if (includeInternal) {
136  // ... internal nodes if not unwanted
137  bool hadAny = false;
138  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
139  hadAny |= writeInternalNodes(device, *(*i).second);
140  }
141  if (hadAny) {
142  device.lf();
143  }
144  }
145 
146  // write the successors of lanes
147  int numConnections = 0;
148  for (std::map<std::string, NBEdge*>::const_iterator it_edge = ec.begin(); it_edge != ec.end(); it_edge++) {
149  NBEdge* from = it_edge->second;
151  const std::vector<NBEdge::Connection> connections = from->getConnections();
152  numConnections += (int)connections.size();
153  for (std::vector<NBEdge::Connection>::const_iterator it_c = connections.begin(); it_c != connections.end(); it_c++) {
154  writeConnection(device, *from, *it_c, includeInternal);
155  }
156  }
157  if (numConnections > 0) {
158  device.lf();
159  }
160  if (includeInternal) {
161  // ... internal successors if not unwanted
162  bool hadAny = false;
163  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
164  hadAny |= writeInternalConnections(device, *(*i).second);
165  }
166  if (hadAny) {
167  device.lf();
168  }
169  }
170  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
171  NBNode* node = (*i).second;
172  // write connections from pedestrian crossings
173  const std::vector<NBNode::Crossing>& crossings = node->getCrossings();
174  for (std::vector<NBNode::Crossing>::const_iterator it = crossings.begin(); it != crossings.end(); it++) {
175  NWWriter_SUMO::writeInternalConnection(device, (*it).id, (*it).nextWalkingArea, 0, 0, "");
176  }
177  // write connections from pedestrian walking areas
178  const std::vector<NBNode::WalkingArea>& WalkingAreas = node->getWalkingAreas();
179  for (std::vector<NBNode::WalkingArea>::const_iterator it = WalkingAreas.begin(); it != WalkingAreas.end(); it++) {
180  if ((*it).nextCrossing != "") {
181  const NBNode::Crossing& nextCrossing = node->getCrossing((*it).nextCrossing);
182  // connection to next crossing (may be tls-controlled)
184  device.writeAttr(SUMO_ATTR_FROM, (*it).id);
185  device.writeAttr(SUMO_ATTR_TO, (*it).nextCrossing);
186  device.writeAttr(SUMO_ATTR_FROM_LANE, 0);
187  device.writeAttr(SUMO_ATTR_TO_LANE, 0);
188  if (nextCrossing.tlID != "") {
189  device.writeAttr(SUMO_ATTR_TLID, nextCrossing.tlID);
190  assert(nextCrossing.tlLinkNo >= 0);
191  device.writeAttr(SUMO_ATTR_TLLINKINDEX, nextCrossing.tlLinkNo);
192  }
195  device.closeTag();
196  }
197  // optional connections from/to sidewalk
198  for (std::vector<std::string>::const_iterator it_sw = (*it).nextSidewalks.begin(); it_sw != (*it).nextSidewalks.end(); ++it_sw) {
199  NWWriter_SUMO::writeInternalConnection(device, (*it).id, (*it_sw), 0, 0, "");
200  }
201  for (std::vector<std::string>::const_iterator it_sw = (*it).prevSidewalks.begin(); it_sw != (*it).prevSidewalks.end(); ++it_sw) {
202  NWWriter_SUMO::writeInternalConnection(device, (*it_sw), (*it).id, 0, 0, "");
203  }
204  }
205  }
206 
207  // write loaded prohibitions
208  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
209  writeProhibitions(device, i->second->getProhibitions());
210  }
211 
212  // write roundabout information
213  writeRoundabouts(device, ec.getRoundabouts(), ec);
214 
215  // write the districts
216  for (std::map<std::string, NBDistrict*>::const_iterator i = dc.begin(); i != dc.end(); i++) {
217  writeDistrict(device, *(*i).second);
218  }
219  if (dc.size() != 0) {
220  device.lf();
221  }
222  device.close();
223 }
224 
225 
226 std::string
228  const NBEdge::Lane& succ = con.toEdge->getLanes()[con.toLane];
229  const NBEdge::Lane& pred = from->getLanes()[con.fromLane];
230  if (succ.oppositeID != "" && succ.oppositeID != "-" && pred.oppositeID != "" && pred.oppositeID != "-") {
231  // find the connection that connects succ.oppositeID to pred.oppositeID
232  const NBEdge* succOpp = ec.retrieve(succ.oppositeID.substr(0, succ.oppositeID.rfind("_")));
233  const NBEdge* predOpp = ec.retrieve(pred.oppositeID.substr(0, pred.oppositeID.rfind("_")));
234  assert(succOpp != 0);
235  assert(predOpp != 0);
236  const std::vector<NBEdge::Connection>& connections = succOpp->getConnections();
237  for (std::vector<NBEdge::Connection>::const_iterator it_c = connections.begin(); it_c != connections.end(); it_c++) {
238  const NBEdge::Connection& conOpp = *it_c;
239  if (succOpp != from && // turnaround
240  succOpp->getLaneID(conOpp.fromLane) == succ.oppositeID &&
241  predOpp == conOpp.toEdge &&
242  predOpp->getLaneID(conOpp.toLane) == pred.oppositeID) {
243  return conOpp.getInternalLaneID();
244  }
245  }
246  return "";
247  } else {
248  return "";
249  }
250 }
251 
252 
253 bool
254 NWWriter_SUMO::writeInternalEdges(OutputDevice& into, const NBEdgeCont& ec, const NBNode& n, bool origNames) {
255  bool ret = false;
256  const EdgeVector& incoming = n.getIncomingEdges();
257  for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
258  const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
259  if (elv.size() > 0) {
260  bool haveVia = false;
261  NBEdge* toEdge = 0;
262  std::string internalEdgeID = "";
263  // first pass: compute average lengths of non-via edges
264  std::map<NBEdge*, SUMOReal> lengthSum;
265  std::map<NBEdge*, int> numLanes;
266  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
267  lengthSum[(*k).toEdge] += MAX2((*k).shape.length(), POSITION_EPS);
268  numLanes[(*k).toEdge] += 1;
269  }
270  // second pass: write non-via edges
271  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
272  if ((*k).toEdge == 0) {
273  assert(false); // should never happen. tell me when it does
274  continue;
275  }
276  if (toEdge != (*k).toEdge) {
277  internalEdgeID = (*k).id;
278  if (toEdge != 0) {
279  // close the previous edge
280  into.closeTag();
281  }
282  toEdge = (*k).toEdge;
283  into.openTag(SUMO_TAG_EDGE);
284  into.writeAttr(SUMO_ATTR_ID, internalEdgeID);
286  // open a new edge
287  }
288  // to avoid changing to an internal lane which has a successor
289  // with the wrong permissions we need to inherit them from the successor
290  const NBEdge::Lane& successor = (*k).toEdge->getLanes()[(*k).toLane];
291  const SUMOReal length = lengthSum[toEdge] / numLanes[toEdge];
292  // @note the actual length should be used once sumo supports lanes of
293  // varying length within the same edge
294  //const SUMOReal length = MAX2((*k).shape.length(), POSITION_EPS);
295  writeLane(into, (*k).getInternalLaneID(), (*k).vmax,
296  successor.permissions, successor.preferred,
297  NBEdge::UNSPECIFIED_OFFSET, successor.width, (*k).shape, (*k).origID,
298  length, (*k).internalLaneIndex, origNames, getOppositeInternalID(ec, *i, *k), &n);
299  haveVia = haveVia || (*k).haveVia;
300  }
301  ret = true;
302  into.closeTag(); // close the last edge
303  // third pass: write via edges
304  if (haveVia) {
305  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
306  if (!(*k).haveVia) {
307  continue;
308  }
309  if ((*k).toEdge == 0) {
310  assert(false); // should never happen. tell me when it does
311  continue;
312  }
313  const NBEdge::Lane& successor = (*k).toEdge->getLanes()[(*k).toLane];
314  into.openTag(SUMO_TAG_EDGE);
315  into.writeAttr(SUMO_ATTR_ID, (*k).viaID);
317  writeLane(into, (*k).viaID + "_0", (*k).viaVmax, SVCAll, SVCAll,
318  NBEdge::UNSPECIFIED_OFFSET, successor.width, (*k).viaShape, (*k).origID,
319  MAX2((*k).viaShape.length(), POSITION_EPS), // microsim needs positive length
320  0, origNames, "", &n);
321  into.closeTag();
322  }
323  }
324  }
325  }
326  // write pedestrian crossings
327  const std::vector<NBNode::Crossing>& crossings = n.getCrossings();
328  for (std::vector<NBNode::Crossing>::const_iterator it = crossings.begin(); it != crossings.end(); it++) {
329  into.openTag(SUMO_TAG_EDGE);
330  into.writeAttr(SUMO_ATTR_ID, (*it).id);
332  into.writeAttr(SUMO_ATTR_CROSSING_EDGES, (*it).edges);
333  writeLane(into, (*it).id + "_0", 1, SVC_PEDESTRIAN, 0,
334  NBEdge::UNSPECIFIED_OFFSET, (*it).width, (*it).shape, "", (*it).shape.length(), 0, false, "", &n);
335  into.closeTag();
336  }
337  // write pedestrian walking areas
338  const std::vector<NBNode::WalkingArea>& WalkingAreas = n.getWalkingAreas();
339  for (std::vector<NBNode::WalkingArea>::const_iterator it = WalkingAreas.begin(); it != WalkingAreas.end(); it++) {
340  const NBNode::WalkingArea& wa = *it;
341  into.openTag(SUMO_TAG_EDGE);
342  into.writeAttr(SUMO_ATTR_ID, wa.id);
344  writeLane(into, wa.id + "_0", 1, SVC_PEDESTRIAN, 0,
345  NBEdge::UNSPECIFIED_OFFSET, wa.width, wa.shape, "", wa.length, 0, false, "", &n);
346  into.closeTag();
347  }
348  return ret;
349 }
350 
351 
352 void
353 NWWriter_SUMO::writeEdge(OutputDevice& into, const NBEdge& e, bool noNames, bool origNames) {
354  // write the edge's begin
357  into.writeAttr(SUMO_ATTR_TO, e.getToNode()->getID());
358  if (!noNames && e.getStreetName() != "") {
360  }
362  if (e.getTypeID() != "") {
364  }
365  if (e.isMacroscopicConnector()) {
367  }
368  // write the spread type if not default ("right")
371  }
372  if (e.hasLoadedLength()) {
374  }
375  if (!e.hasDefaultGeometry()) {
377  }
378  // write the lanes
379  const std::vector<NBEdge::Lane>& lanes = e.getLanes();
380 
381  const SUMOReal length = e.getFinalLength();
382  for (int i = 0; i < (int) lanes.size(); i++) {
383  const NBEdge::Lane& l = lanes[i];
384  writeLane(into, e.getLaneID(i), l.speed,
385  l.permissions, l.preferred, l.endOffset, l.width, l.shape, l.origID,
386  length, i, origNames, l.oppositeID);
387  }
388  // close the edge
389  into.closeTag();
390 }
391 
392 
393 void
394 NWWriter_SUMO::writeLane(OutputDevice& into, const std::string& lID,
395  SUMOReal speed, SVCPermissions permissions, SVCPermissions preferred,
396  SUMOReal endOffset, SUMOReal width, PositionVector shape,
397  const std::string& origID, SUMOReal length, int index, bool origNames,
398  const std::string& oppositeID, const NBNode* node) {
399  // output the lane's attributes
401  // the first lane of an edge will be the depart lane
402  into.writeAttr(SUMO_ATTR_INDEX, index);
403  // write the list of allowed/disallowed vehicle classes
404  if (permissions != SVC_UNSPECIFIED) {
405  writePermissions(into, permissions);
406  }
407  writePreferences(into, preferred);
408  // some further information
409  if (speed == 0) {
410  WRITE_WARNING("Lane '" + lID + "' has a maximum allowed speed of 0.");
411  } else if (speed < 0) {
412  throw ProcessError("Negative allowed speed (" + toString(speed) + ") on lane '" + lID + "', use --speed.minimum to prevent this.");
413  }
414  if (endOffset > 0) {
415  length = length - endOffset;
416  }
417  into.writeAttr(SUMO_ATTR_SPEED, speed);
418  into.writeAttr(SUMO_ATTR_LENGTH, length);
419  if (endOffset != NBEdge::UNSPECIFIED_OFFSET) {
420  into.writeAttr(SUMO_ATTR_ENDOFFSET, endOffset);
421  }
422  if (width != NBEdge::UNSPECIFIED_WIDTH) {
423  into.writeAttr(SUMO_ATTR_WIDTH, width);
424  }
425  if (node != 0) {
426  const NBNode::CustomShapeMap& cs = node->getCustomLaneShapes();
427  NBNode::CustomShapeMap::const_iterator it = cs.find(lID);
428  if (it != cs.end()) {
429  shape = it->second;
430  into.writeAttr(SUMO_ATTR_CUSTOMSHAPE, true);
431  }
432  }
433  into.writeAttr(SUMO_ATTR_SHAPE, endOffset > 0 ?
434  shape.getSubpart(0, shape.length() - endOffset) : shape);
435  if (oppositeID != "" && oppositeID != "-") {
436  into.openTag(SUMO_TAG_NEIGH);
437  into.writeAttr(SUMO_ATTR_LANE, oppositeID);
438  into.closeTag();
439  }
440  if (origNames && origID != "") {
441  into.openTag(SUMO_TAG_PARAM);
442  into.writeAttr(SUMO_ATTR_KEY, "origId");
443  into.writeAttr(SUMO_ATTR_VALUE, origID);
444  into.closeTag();
445  }
446  into.closeTag();
447 }
448 
449 
450 void
451 NWWriter_SUMO::writeJunction(OutputDevice& into, const NBNode& n, const bool checkLaneFoes) {
452  // write the attributes
454  into.writeAttr(SUMO_ATTR_TYPE, n.getType());
456  // write the incoming lanes
457  std::string incLanes;
458  const std::vector<NBEdge*>& incoming = n.getIncomingEdges();
459  for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); ++i) {
460  int noLanes = (*i)->getNumLanes();
461  for (int j = 0; j < noLanes; j++) {
462  incLanes += (*i)->getLaneID(j);
463  if (i != incoming.end() - 1 || j < noLanes - 1) {
464  incLanes += ' ';
465  }
466  }
467  }
468  const std::vector<NBNode::Crossing>& crossings = n.getCrossings();
469  for (std::vector<NBNode::Crossing>::const_iterator it = crossings.begin(); it != crossings.end(); it++) {
470  incLanes += ' ' + (*it).prevWalkingArea + "_0";
471  }
472  into.writeAttr(SUMO_ATTR_INCLANES, incLanes);
473  // write the internal lanes
474  std::string intLanes;
475  if (!OptionsCont::getOptions().getBool("no-internal-links")) {
476  int l = 0;
477  for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
478  const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
479  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
480  if ((*k).toEdge == 0) {
481  continue;
482  }
483  if (l != 0) {
484  intLanes += ' ';
485  }
486  if (!(*k).haveVia) {
487  intLanes += (*k).getInternalLaneID();
488  } else {
489  intLanes += (*k).viaID + "_0";
490  }
491  l++;
492  }
493  }
494  }
495  if (n.getType() != NODETYPE_DEAD_END && n.getType() != NODETYPE_NOJUNCTION) {
496  for (std::vector<NBNode::Crossing>::const_iterator it = crossings.begin(); it != crossings.end(); it++) {
497  intLanes += ' ' + (*it).id + "_0";
498  }
499  }
500  into.writeAttr(SUMO_ATTR_INTLANES, intLanes);
501  // close writing
503  // write optional radius
506  }
507  // specify whether a custom shape was used
508  if (n.hasCustomShape()) {
509  into.writeAttr(SUMO_ATTR_CUSTOMSHAPE, true);
510  }
511  if (n.getType() == NODETYPE_DEAD_END) {
512  into.closeTag();
513  } else {
514  // write right-of-way logics
515  n.writeLogic(into, checkLaneFoes);
516  into.closeTag();
517  }
518 }
519 
520 
521 bool
523  bool ret = false;
524  const std::vector<NBEdge*>& incoming = n.getIncomingEdges();
525  // build the list of internal lane ids
526  std::vector<std::string> internalLaneIDs;
527  for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
528  const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
529  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
530  if ((*k).toEdge != 0) {
531  internalLaneIDs.push_back((*k).getInternalLaneID());
532  }
533  }
534  }
535  const std::vector<NBNode::Crossing>& crossings = n.getCrossings();
536  for (std::vector<NBNode::Crossing>::const_iterator it_c = crossings.begin(); it_c != crossings.end(); ++it_c) {
537  internalLaneIDs.push_back((*it_c).id + "_0");
538  }
539  // write the internal nodes
540  for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
541  const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
542  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
543  if ((*k).toEdge == 0 || !(*k).haveVia) {
544  continue;
545  }
546  Position pos = (*k).shape[-1];
547  into.openTag(SUMO_TAG_JUNCTION).writeAttr(SUMO_ATTR_ID, (*k).viaID + "_0");
549  NWFrame::writePositionLong(pos, into);
550  std::string incLanes = (*k).getInternalLaneID();
551  if ((*k).foeIncomingLanes.length() != 0) {
552  incLanes += " " + (*k).foeIncomingLanes;
553  }
554  into.writeAttr(SUMO_ATTR_INCLANES, incLanes);
555  const std::vector<int>& foes = (*k).foeInternalLinks;
556  std::vector<std::string> foeIDs;
557  for (std::vector<int>::const_iterator it = foes.begin(); it != foes.end(); ++it) {
558  foeIDs.push_back(internalLaneIDs[*it]);
559  }
560  into.writeAttr(SUMO_ATTR_INTLANES, joinToString(foeIDs, " "));
561  into.closeTag();
562  ret = true;
563  }
564  }
565  return ret;
566 }
567 
568 
569 void
571  bool includeInternal, ConnectionStyle style) {
572  assert(c.toEdge != 0);
574  into.writeAttr(SUMO_ATTR_FROM, from.getID());
575  into.writeAttr(SUMO_ATTR_TO, c.toEdge->getID());
578  if (c.mayDefinitelyPass && style != TLL) {
580  }
581  if ((from.getToNode()->getKeepClear() == false || c.keepClear == false) && style != TLL) {
582  into.writeAttr<bool>(SUMO_ATTR_KEEP_CLEAR, false);
583  }
584  if (c.contPos != NBEdge::UNSPECIFIED_CONTPOS && style != TLL) {
586  }
589  }
590  if (style != PLAIN) {
591  if (includeInternal) {
593  }
594  // set information about the controlling tl if any
595  if (c.tlID != "") {
596  into.writeAttr(SUMO_ATTR_TLID, c.tlID);
598  }
599  if (style == SUMONET) {
600  // write the direction information
601  LinkDirection dir = from.getToNode()->getDirection(&from, c.toEdge, OptionsCont::getOptions().getBool("lefthand"));
602  assert(dir != LINKDIR_NODIR);
603  into.writeAttr(SUMO_ATTR_DIR, toString(dir));
604  // write the state information
605  const LinkState linkState = from.getToNode()->getLinkState(
606  &from, c.toEdge, c.fromLane, c.toLane, c.mayDefinitelyPass, c.tlID);
607  into.writeAttr(SUMO_ATTR_STATE, linkState);
608  }
609  }
610  into.closeTag();
611 }
612 
613 
614 bool
616  bool ret = false;
617  const std::vector<NBEdge*>& incoming = n.getIncomingEdges();
618  for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); ++i) {
619  NBEdge* from = *i;
620  const std::vector<NBEdge::Connection>& connections = from->getConnections();
621  for (std::vector<NBEdge::Connection>::const_iterator j = connections.begin(); j != connections.end(); ++j) {
622  const NBEdge::Connection& c = *j;
623  assert(c.toEdge != 0);
624  if (c.haveVia) {
625  // internal split
626  writeInternalConnection(into, c.id, c.toEdge->getID(), c.internalLaneIndex, c.toLane, c.viaID + "_0");
627  writeInternalConnection(into, c.viaID, c.toEdge->getID(), 0, c.toLane, "");
628  } else {
629  // no internal split
631  }
632  ret = true;
633  }
634  }
635  return ret;
636 }
637 
638 
639 void
641  const std::string& from, const std::string& to,
642  int fromLane, int toLane, const std::string& via) {
644  into.writeAttr(SUMO_ATTR_FROM, from);
645  into.writeAttr(SUMO_ATTR_TO, to);
646  into.writeAttr(SUMO_ATTR_FROM_LANE, fromLane);
647  into.writeAttr(SUMO_ATTR_TO_LANE, toLane);
648  if (via != "") {
649  into.writeAttr(SUMO_ATTR_VIA, via);
650  }
651  into.writeAttr(SUMO_ATTR_DIR, "s");
652  into.writeAttr(SUMO_ATTR_STATE, (via != "" ? "m" : "M"));
653  into.closeTag();
654 }
655 
656 
657 void
658 NWWriter_SUMO::writeRoundabouts(OutputDevice& into, const std::set<EdgeSet>& roundabouts,
659  const NBEdgeCont& ec) {
660  // make output deterministic
661  std::vector<std::vector<std::string> > edgeIDs;
662  for (std::set<EdgeSet>::const_iterator i = roundabouts.begin(); i != roundabouts.end(); ++i) {
663  std::vector<std::string> tEdgeIDs;
664  for (EdgeSet::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
665  // the edges may have been erased from NBEdgeCont but their pointers are still valid
666  // we verify their existance in writeRoundabout()
667  tEdgeIDs.push_back((*j)->getID());
668  }
669  std::sort(tEdgeIDs.begin(), tEdgeIDs.end());
670  edgeIDs.push_back(tEdgeIDs);
671  }
672  std::sort(edgeIDs.begin(), edgeIDs.end());
673  // write
674  for (std::vector<std::vector<std::string> >::const_iterator i = edgeIDs.begin(); i != edgeIDs.end(); ++i) {
675  writeRoundabout(into, *i, ec);
676  }
677  if (roundabouts.size() != 0) {
678  into.lf();
679  }
680 }
681 
682 
683 void
684 NWWriter_SUMO::writeRoundabout(OutputDevice& into, const std::vector<std::string>& edgeIDs,
685  const NBEdgeCont& ec) {
686  std::vector<std::string> validEdgeIDs;
687  std::vector<std::string> invalidEdgeIDs;
688  std::vector<std::string> nodeIDs;
689  for (std::vector<std::string>::const_iterator i = edgeIDs.begin(); i != edgeIDs.end(); ++i) {
690  const NBEdge* edge = ec.retrieve(*i);
691  if (edge != 0) {
692  nodeIDs.push_back(edge->getToNode()->getID());
693  validEdgeIDs.push_back(edge->getID());
694  } else {
695  invalidEdgeIDs.push_back(*i);
696  }
697  }
698  std::sort(nodeIDs.begin(), nodeIDs.end());
699  if (validEdgeIDs.size() > 0) {
701  into.writeAttr(SUMO_ATTR_NODES, joinToString(nodeIDs, " "));
702  into.writeAttr(SUMO_ATTR_EDGES, joinToString(validEdgeIDs, " "));
703  into.closeTag();
704  if (invalidEdgeIDs.size() > 0) {
705  WRITE_WARNING("Writing incomplete roundabout. Edges: '"
706  + joinToString(invalidEdgeIDs, " ") + "' no longer exist'");
707  }
708  }
709 }
710 
711 
712 void
714  std::vector<SUMOReal> sourceW = d.getSourceWeights();
716  std::vector<SUMOReal> sinkW = d.getSinkWeights();
718  // write the head and the id of the district
720  if (d.getShape().size() > 0) {
722  }
723  // write all sources
724  const std::vector<NBEdge*>& sources = d.getSourceEdges();
725  for (int i = 0; i < (int)sources.size(); i++) {
726  // write the head and the id of the source
727  into.openTag(SUMO_TAG_TAZSOURCE).writeAttr(SUMO_ATTR_ID, sources[i]->getID()).writeAttr(SUMO_ATTR_WEIGHT, sourceW[i]);
728  into.closeTag();
729  }
730  // write all sinks
731  const std::vector<NBEdge*>& sinks = d.getSinkEdges();
732  for (int i = 0; i < (int)sinks.size(); i++) {
733  // write the head and the id of the sink
734  into.openTag(SUMO_TAG_TAZSINK).writeAttr(SUMO_ATTR_ID, sinks[i]->getID()).writeAttr(SUMO_ATTR_WEIGHT, sinkW[i]);
735  into.closeTag();
736  }
737  // write the tail
738  into.closeTag();
739 }
740 
741 
742 std::string
744  SUMOReal time = STEPS2TIME(steps);
745  if (time == std::floor(time)) {
746  return toString(int(time));
747  } else {
748  return toString(time);
749  }
750 }
751 
752 
753 void
755  for (NBConnectionProhibits::const_iterator j = prohibitions.begin(); j != prohibitions.end(); j++) {
756  NBConnection prohibited = (*j).first;
757  const NBConnectionVector& prohibiting = (*j).second;
758  for (NBConnectionVector::const_iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
759  NBConnection prohibitor = *k;
763  into.closeTag();
764  }
765  }
766 }
767 
768 
769 std::string
771  return c.getFrom()->getID() + "->" + c.getTo()->getID();
772 }
773 
774 
775 void
777  std::vector<NBTrafficLightLogic*> logics = tllCont.getComputed();
778  for (std::vector<NBTrafficLightLogic*>::iterator it = logics.begin(); it != logics.end(); it++) {
780  into.writeAttr(SUMO_ATTR_ID, (*it)->getID());
781  into.writeAttr(SUMO_ATTR_TYPE, (*it)->getType());
782  into.writeAttr(SUMO_ATTR_PROGRAMID, (*it)->getProgramID());
783  into.writeAttr(SUMO_ATTR_OFFSET, writeSUMOTime((*it)->getOffset()));
784  // write params
785  (*it)->writeParams(into);
786  // write the phases
787  const std::vector<NBTrafficLightLogic::PhaseDefinition>& phases = (*it)->getPhases();
788  for (std::vector<NBTrafficLightLogic::PhaseDefinition>::const_iterator j = phases.begin(); j != phases.end(); ++j) {
789  into.openTag(SUMO_TAG_PHASE);
790  into.writeAttr(SUMO_ATTR_DURATION, writeSUMOTime(j->duration));
791  into.writeAttr(SUMO_ATTR_STATE, j->state);
792  into.closeTag();
793  }
794  into.closeTag();
795  }
796  if (logics.size() > 0) {
797  into.lf();
798  }
799 }
800 /****************************************************************************/
801 
static void writeRoundabout(OutputDevice &into, const std::vector< std::string > &r, const NBEdgeCont &ec)
Writes a roundabout.
std::string id
id of Connection
Definition: NBEdge.h:206
The information about how to spread the lanes from the given position.
int tlLinkNo
The index of this connection within the controlling traffic light.
Definition: NBEdge.h:188
void writePermissions(OutputDevice &into, SVCPermissions permissions)
writes allowed disallowed attributes if needed;
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:256
const EdgeVector & getIncomingEdges() const
Returns this node&#39;s incoming edges (The edges which yield in this node)
Definition: NBNode.h:240
void close()
Closes the device and removes it from the dictionary.
static void writeLocation(OutputDevice &into)
writes the location element
const std::string & getTypeID() const
get ID of type
Definition: NBEdge.h:946
SUMOReal endOffset
This lane&#39;s offset to the intersection begin.
Definition: NBEdge.h:141
bool getKeepClear() const
Returns the keepClear flag.
Definition: NBNode.h:267
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:157
int toLane
The lane the connections yields in.
Definition: NBEdge.h:182
long long int SUMOTime
Definition: SUMOTime.h:43
a list of node ids, used for controlling joining
static const SUMOReal UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:244
NBTypeCont & getTypeCont()
Returns a reference to the type container.
Definition: NBNetBuilder.h:154
Whether vehicles must keep the junction clear.
PositionVector shape
The lane&#39;s shape.
Definition: NBEdge.h:129
whether a given shape is user-defined
a source within a district (connection road)
is a pedestrian
static void writeDistrict(OutputDevice &into, const NBDistrict &d)
Writes a district.
std::string viaID
if Connection have a via, ID of it
Definition: NBEdge.h:218
NBEdge * toEdge
The edge the connections yields in.
Definition: NBEdge.h:179
bool hasDefaultGeometry() const
Returns whether the geometry consists only of the node positions.
Definition: NBEdge.cpp:486
begin/end of the description of a junction
begin/end of the description of a single lane
SUMOReal getRadius() const
Returns the turning radius of this node.
Definition: NBNode.h:262
const std::set< EdgeSet > getRoundabouts() const
Returns the determined roundabouts.
A container for traffic light definitions and built programs.
a traffic assignment zone
SUMOReal length
This lane&#39;s width.
Definition: NBNode.h:182
SUMOReal width
This lane&#39;s width.
Definition: NBNode.h:180
static bool writeInternalEdges(OutputDevice &into, const NBEdgeCont &ec, const NBNode &n, bool origNames)
Writes internal edges (<edge ... with id[0]==&#39;:&#39;) of the given node.
void writePreferences(OutputDevice &into, SVCPermissions preferred)
writes allowed disallowed attributes if needed;
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
Definition: NBEdge.h:559
connectio between two lanes
const Crossing & getCrossing(const std::string &id) const
return the crossing with the given id
Definition: NBNode.cpp:2571
int SVCPermissions
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
The representation of a single edge during network building.
Definition: NBEdge.h:71
foe visibility distance of a link
static void writeProhibitions(OutputDevice &into, const NBConnectionProhibits &prohibitions)
writes the given prohibitions
const std::vector< NBEdge * > & getSinkEdges() const
Returns the sinks.
Definition: NBDistrict.h:214
A container for districts.
const std::vector< Crossing > & getCrossings() const
return this junctions pedestrian crossings
Definition: NBNode.h:620
link,node: the traffic light id responsible for this link
T MAX2(T a, T b)
Definition: StdDefs.h:70
bool hasCustomShape() const
return whether the shape was set by the user
Definition: NBNode.h:493
bool mayDefinitelyPass
Information about being definitely free to drive (on-ramps)
Definition: NBEdge.h:191
std::string id
the (edge)-id of this walkingArea
Definition: NBNode.h:178
static const SUMOReal UNSPECIFIED_CONTPOS
unspecified internal junction position
Definition: NBEdge.h:253
const SVCPermissions SVCAll
static void writeTrafficLights(OutputDevice &into, const NBTrafficLightLogicCont &tllCont)
writes the traffic light logics to the given device
static const SUMOReal UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:247
static void writeInternalConnection(OutputDevice &into, const std::string &from, const std::string &to, int fromLane, int toLane, const std::string &via)
Writes a single internal connection.
NBEdge * getFrom() const
returns the from-edge (start of the connection)
static std::string getOppositeInternalID(const NBEdgeCont &ec, const NBEdge *from, const NBEdge::Connection &con)
retrieve the id of the opposite direction internal lane if it exists
prohibition of circulation between two edges
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:69
bool priority
whether the pedestrians have priority
Definition: NBNode.h:159
LinkDirection
The different directions a link between two lanes may take (or a stream between two edges)...
The link is a straight direction.
The state of a link.
SUMOReal speed
The speed allowed on this lane.
Definition: NBEdge.h:132
A class representing a single district.
Definition: NBDistrict.h:72
bool keepClear
whether the junction must be kept clear when using this connection
Definition: NBEdge.h:194
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
std::map< std::string, PositionVector > CustomShapeMap
map for custon shapes
Definition: NBNode.h:85
static std::string prohibitionConnection(const NBConnection &c)
the attribute value for a prohibition
SUMOReal getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn&#39;t set.
Definition: NBEdge.h:479
An (internal) definition of a single lane of an edge.
Definition: NBEdge.h:124
const std::string & getID() const
Returns the id.
Definition: Named.h:66
SVCPermissions permissions
List of vehicle types that are allowed on this lane.
Definition: NBEdge.h:135
static void writeNetwork(const OptionsCont &oc, NBNetBuilder &nb)
Writes the network into a SUMO-file.
const Position & getPosition() const
Definition: NBNode.h:232
The turning radius at an intersection in m.
std::map< std::string, NBEdge * >::const_iterator end() const
Returns the pointer to the end of the stored edges.
Definition: NBEdgeCont.h:198
the edges of a route
int getPriority() const
Returns the priority of the edge.
Definition: NBEdge.h:409
PositionVector simplified() const
return the same shape with intermediate colinear points removed
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:55
std::map< std::string, NBDistrict * >::const_iterator begin() const
Returns the pointer to the begin of the stored districts.
const std::vector< NBEdge * > & getSourceEdges() const
Returns the sources.
Definition: NBDistrict.h:198
std::string tlID
The id of the traffic light that controls this connection.
Definition: NBEdge.h:185
SVCPermissions preferred
List of vehicle types that are preferred on this lane.
Definition: NBEdge.h:138
std::string getInternalLaneID() const
get ID of internal lane
Definition: NBEdge.cpp:82
This is an uncontrolled, minor link, has to brake.
static bool writeInternalConnections(OutputDevice &into, const NBNode &n)
Writes inner connections within the node.
static void writeLane(OutputDevice &into, const std::string &lID, SUMOReal speed, SVCPermissions permissions, SVCPermissions preferred, SUMOReal endOffset, SUMOReal width, PositionVector shape, const std::string &origID, SUMOReal length, int index, bool origNames, const std::string &oppositeID, const NBNode *node=0)
Writes a lane (<lane ...) of an edge.
int fromLane
The lane the connections starts at.
Definition: NBEdge.h:176
bool writeXMLHeader(const std::string &rootElement, const std::string &schemaFile, std::map< SumoXMLAttr, std::string > attrs=std::map< SumoXMLAttr, std::string >())
Writes an XML header with optional configuration.
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:46
parameter associated to a certain key
std::map< std::string, NBDistrict * >::const_iterator end() const
Returns the pointer to the end of the stored districts.
NBEdgeCont & getEdgeCont()
Definition: NBNetBuilder.h:144
A list of positions.
static const SUMOReal UNSPECIFIED_VISIBILITY_DISTANCE
unspecified foe visibility for connections
Definition: NBEdge.h:256
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:257
static void writeEdge(OutputDevice &into, const NBEdge &e, bool noNames, bool origNames)
Writes an edge (<edge ...)
bool hasLoadedLength() const
Returns whether a length was set explicitly.
Definition: NBEdge.h:489
#define STEPS2TIME(x)
Definition: SUMOTime.h:65
const PositionVector & getShape() const
Returns the shape.
Definition: NBDistrict.h:222
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic, in MSLink and GNEInternalLane.
SUMOReal contPos
custom position for internal junction on this connection
Definition: NBEdge.h:197
roundabout defined in junction
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:66
#define POSITION_EPS
Definition: config.h:182
const CustomShapeMap & getCustomLaneShapes() const
sets a custom shape for an internal lane
Definition: NBNode.h:478
LinkState getLinkState(const NBEdge *incoming, NBEdge *outgoing, int fromLane, int toLane, bool mayDefinitelyPass, const std::string &tlID) const
get link state
Definition: NBNode.cpp:1617
static void writePositionLong(const Position &pos, OutputDevice &dev)
Writes the given position to device in long format (one attribute per dimension)
Definition: NWFrame.cpp:167
edge: the shape in xml-definition
std::vector< NBTrafficLightLogic * > getComputed() const
Returns a list of all computed logics.
bool isDefault(const std::string &name) const
Returns the information whether the named option has still the default value.
std::map< std::string, NBNode * >::const_iterator end() const
Returns the pointer to the end of the stored nodes.
Definition: NBNodeCont.h:119
begin/end of the description of a neighboring lane
LinkDirection getDirection(const NBEdge *const incoming, const NBEdge *const outgoing, bool leftHand=false) const
Returns the representation of the described stream&#39;s direction.
Definition: NBNode.cpp:1553
const PositionVector & getShape() const
retrieve the junction shape
Definition: NBNode.cpp:1720
static std::string escapeXML(const std::string &orig, const bool maskDoubleHyphen=false)
Replaces the standard escapes by their XML entities.
std::vector< NBConnection > NBConnectionVector
Definition of a connection vector.
begin/end of the description of an edge
static void normaliseSum(std::vector< T > &v, T msum=1.0)
Definition: VectorHelper.h:58
void writeTypes(OutputDevice &into) const
writes all types a s XML
Definition: NBTypeCont.cpp:131
std::string origID
An original ID, if given.
Definition: NBEdge.h:147
int internalLaneIndex
The lane index of this internal lane within the internal edge.
Definition: NBEdge.h:233
std::map< std::string, NBEdge * >::const_iterator begin() const
Returns the pointer to the begin of the stored edges.
Definition: NBEdgeCont.h:190
SUMOReal length() const
Returns the length.
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:423
std::map< NBConnection, NBConnectionVector > NBConnectionProhibits
Definition of a container for connection block dependencies Includes a list of all connections which ...
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
Definition: NBEdgeCont.cpp:255
std::string oppositeID
An opposite lane ID, if given.
Definition: NBEdge.h:150
a sink within a district (connection road)
the edges crossed by a pedestrian crossing
NBNodeCont & getNodeCont()
Returns a reference to the node container.
Definition: NBNetBuilder.h:149
Instance responsible for building networks.
Definition: NBNetBuilder.h:112
static OutputDevice & getDevice(const std::string &name)
Returns the described OutputDevice.
int tlLinkNo
the traffic light index of this crossing (if controlled)
Definition: NBNode.h:161
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:41
static bool writeInternalNodes(OutputDevice &into, const NBNode &n)
Writes internal junctions (<junction with id[0]==&#39;:&#39; ...) of the given node.
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:584
A definition of a pedestrian walking area.
Definition: NBNode.h:170
bool isMacroscopicConnector() const
Returns whether this edge was marked as a macroscopic connector.
Definition: NBEdge.h:904
A storage for options typed value containers)
Definition: OptionsCont.h:99
This is an uncontrolled, major link, may pass.
void sortOutgoingConnectionsByIndex()
sorts the outgoing connections by their from-lane-index and their to-lane-index
Definition: NBEdge.cpp:1078
NBTrafficLightLogicCont & getTLLogicCont()
Returns a reference to the traffic light logics container.
Definition: NBNetBuilder.h:159
NBEdge * getTo() const
returns the to-edge (end of the connection)
The abstract direction of a link.
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge&#39;s lanes&#39; lateral offset is computed.
Definition: NBEdge.h:653
Represents a single node (junction) during network building.
Definition: NBNode.h:75
A definition of a pedestrian crossing.
Definition: NBNode.h:135
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:71
bool closeTag()
Closes the most recently opened tag.
#define SUMOReal
Definition: config.h:208
static const SUMOReal UNSPECIFIED_RADIUS
unspecified lane width
Definition: NBNode.h:200
static void writeJunction(OutputDevice &into, const NBNode &n, const bool checkLaneFoes)
Writes a junction (<junction ...)
bool writeLogic(OutputDevice &into, const bool checkLaneFoes) const
writes the XML-representation of the logic as a bitset-logic XML representation
Definition: NBNode.cpp:775
link: the index of the link within the traffic light
const std::vector< SUMOReal > & getSourceWeights() const
Returns the weights of the sources.
Definition: NBDistrict.h:190
std::string tlID
The id of the traffic light that controls this connection.
Definition: NBNode.h:163
std::string getLaneID(int lane) const
get Lane ID (Secure)
Definition: NBEdge.cpp:2536
const std::vector< SUMOReal > & getSinkWeights() const
Returns the weights of the sinks.
Definition: NBDistrict.h:206
a traffic light logic
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:63
SUMOReal getFinalLength() const
get length that will be assigned to the lanes in the final network
Definition: NBEdge.cpp:2978
bool haveVia
check if Connection have a Via
Definition: NBEdge.h:215
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
const std::vector< WalkingArea > & getWalkingAreas() const
return this junctions pedestrian walking areas
Definition: NBNode.h:625
NBDistrictCont & getDistrictCont()
Returns a reference the districts container.
Definition: NBNetBuilder.h:164
const std::string & getStreetName() const
Returns the street name of this edge.
Definition: NBEdge.h:525
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:810
static const std::string MAJOR_VERSION
The version number for written files.
Definition: NWFrame.h:69
std::map< std::string, NBNode * >::const_iterator begin() const
Returns the pointer to the begin of the stored nodes.
Definition: NBNodeCont.h:114
static void writeRoundabouts(OutputDevice &into, const std::set< EdgeSet > &roundabouts, const NBEdgeCont &ec)
Writes roundabouts.
PositionVector getSubpart(SUMOReal beginOffset, SUMOReal endOffset) const
get subpart of a position vector
int size() const
Returns the number of districts inside the container.
a single phase description
static std::string writeSUMOTime(SUMOTime time)
writes a SUMOTime as int if possible, otherwise as a float
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
Definition: ToString.h:188
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
void lf()
writes a line feed if applicable
Definition: OutputDevice.h:234
const SVCPermissions SVC_UNSPECIFIED
SUMOReal width
This lane&#39;s width.
Definition: NBEdge.h:144
static void writeConnection(OutputDevice &into, const NBEdge &from, const NBEdge::Connection &c, bool includeInternal, ConnectionStyle style=SUMONET)
Writes connections outgoing from the given edge (also used in NWWriter_XML)
PositionVector shape
The polygonal shape.
Definition: NBNode.h:184
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
The link has no direction (is a dead end link)
SUMOReal visibility
custom foe visiblity for connection
Definition: NBEdge.h:200
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:416