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