SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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-2015 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  device.writeXMLHeader("net", NWFrame::MAJOR_VERSION + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo.dlr.de/xsd/net_file.xsd\""); // street names may contain non-ascii chars
71  device.lf();
72  // get involved container
73  const NBNodeCont& nc = nb.getNodeCont();
74  const NBEdgeCont& ec = nb.getEdgeCont();
75  const NBDistrictCont& dc = nb.getDistrictCont();
76 
77  // write network offsets and projection
79 
80  // write inner lanes
81  bool origNames = oc.getBool("output.original-names");
82  if (!oc.getBool("no-internal-links")) {
83  bool hadAny = false;
84  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
85  hadAny |= writeInternalEdges(device, *(*i).second, origNames);
86  }
87  if (hadAny) {
88  device.lf();
89  }
90  }
91 
92  // write edges with lanes and connected edges
93  bool noNames = !oc.getBool("output.street-names");
94  for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
95  writeEdge(device, *(*i).second, noNames, origNames);
96  }
97  device.lf();
98 
99  // write tls logics
100  writeTrafficLights(device, nb.getTLLogicCont());
101 
102  // write the nodes (junctions)
103  std::set<NBNode*> roundaboutNodes;
104  const bool checkLaneFoesAll = oc.getBool("check-lane-foes.all");
105  const bool checkLaneFoesRoundabout = !checkLaneFoesAll && oc.getBool("check-lane-foes.roundabout");
106  if (checkLaneFoesRoundabout) {
107  const std::set<EdgeSet>& roundabouts = ec.getRoundabouts();
108  for (std::set<EdgeSet>::const_iterator i = roundabouts.begin(); i != roundabouts.end(); ++i) {
109  for (EdgeSet::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
110  roundaboutNodes.insert((*j)->getToNode());
111  }
112  }
113  }
114  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
115  const bool checkLaneFoes = checkLaneFoesAll || (checkLaneFoesRoundabout && roundaboutNodes.count((*i).second) > 0);
116  writeJunction(device, *(*i).second, checkLaneFoes);
117  }
118  device.lf();
119  const bool includeInternal = !oc.getBool("no-internal-links");
120  if (includeInternal) {
121  // ... internal nodes if not unwanted
122  bool hadAny = false;
123  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
124  hadAny |= writeInternalNodes(device, *(*i).second);
125  }
126  if (hadAny) {
127  device.lf();
128  }
129  }
130 
131  // write the successors of lanes
132  unsigned int numConnections = 0;
133  for (std::map<std::string, NBEdge*>::const_iterator it_edge = ec.begin(); it_edge != ec.end(); it_edge++) {
134  NBEdge* from = it_edge->second;
136  const std::vector<NBEdge::Connection> connections = from->getConnections();
137  numConnections += (unsigned int)connections.size();
138  for (std::vector<NBEdge::Connection>::const_iterator it_c = connections.begin(); it_c != connections.end(); it_c++) {
139  writeConnection(device, *from, *it_c, includeInternal);
140  }
141  }
142  if (numConnections > 0) {
143  device.lf();
144  }
145  if (includeInternal) {
146  // ... internal successors if not unwanted
147  bool hadAny = false;
148  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
149  hadAny |= writeInternalConnections(device, *(*i).second);
150  }
151  if (hadAny) {
152  device.lf();
153  }
154  }
155  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
156  NBNode* node = (*i).second;
157  // write connections from pedestrian crossings
158  const std::vector<NBNode::Crossing>& crossings = node->getCrossings();
159  for (std::vector<NBNode::Crossing>::const_iterator it = crossings.begin(); it != crossings.end(); it++) {
160  NWWriter_SUMO::writeInternalConnection(device, (*it).id, (*it).nextWalkingArea, 0, 0, "");
161  }
162  // write connections from pedestrian walking areas
163  const std::vector<NBNode::WalkingArea>& WalkingAreas = node->getWalkingAreas();
164  for (std::vector<NBNode::WalkingArea>::const_iterator it = WalkingAreas.begin(); it != WalkingAreas.end(); it++) {
165  if ((*it).nextCrossing != "") {
166  const NBNode::Crossing& nextCrossing = node->getCrossing((*it).nextCrossing);
167  // connection to next crossing (may be tls-controlled)
169  device.writeAttr(SUMO_ATTR_FROM, (*it).id);
170  device.writeAttr(SUMO_ATTR_TO, (*it).nextCrossing);
171  device.writeAttr(SUMO_ATTR_FROM_LANE, 0);
172  device.writeAttr(SUMO_ATTR_TO_LANE, 0);
173  if ((*it).tlID != "") {
174  device.writeAttr(SUMO_ATTR_TLID, (*it).tlID);
175  assert(nextCrossing.tlLinkNo >= 0);
176  device.writeAttr(SUMO_ATTR_TLLINKINDEX, nextCrossing.tlLinkNo);
177  }
180  device.closeTag();
181  }
182  // optional connections from/to sidewalk
183  for (std::vector<std::string>::const_iterator it_sw = (*it).nextSidewalks.begin(); it_sw != (*it).nextSidewalks.end(); ++it_sw) {
184  NWWriter_SUMO::writeInternalConnection(device, (*it).id, (*it_sw), 0, 0, "");
185  }
186  for (std::vector<std::string>::const_iterator it_sw = (*it).prevSidewalks.begin(); it_sw != (*it).prevSidewalks.end(); ++it_sw) {
187  NWWriter_SUMO::writeInternalConnection(device, (*it_sw), (*it).id, 0, 0, "");
188  }
189  }
190  }
191 
192  // write loaded prohibitions
193  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
194  writeProhibitions(device, i->second->getProhibitions());
195  }
196 
197  // write roundabout information
198  writeRoundabouts(device, ec.getRoundabouts(), ec);
199 
200  // write the districts
201  for (std::map<std::string, NBDistrict*>::const_iterator i = dc.begin(); i != dc.end(); i++) {
202  writeDistrict(device, *(*i).second);
203  }
204  if (dc.size() != 0) {
205  device.lf();
206  }
207  device.close();
208 }
209 
210 
211 bool
212 NWWriter_SUMO::writeInternalEdges(OutputDevice& into, const NBNode& n, bool origNames) {
213  bool ret = false;
214  const EdgeVector& incoming = n.getIncomingEdges();
215  for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
216  const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
217  if (elv.size() > 0) {
218  bool haveVia = false;
219  NBEdge* toEdge = 0;
220  std::string internalEdgeID = "";
221  // first pass: compute average lengths of non-via edges
222  std::map<NBEdge*, SUMOReal> lengthSum;
223  std::map<NBEdge*, int> numLanes;
224  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
225  lengthSum[(*k).toEdge] += MAX2((*k).shape.length(), POSITION_EPS);
226  numLanes[(*k).toEdge] += 1;
227  }
228  // second pass: write non-via edges
229  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
230  if ((*k).toEdge == 0) {
231  assert(false); // should never happen. tell me when it does
232  continue;
233  }
234  if (toEdge != (*k).toEdge) {
235  internalEdgeID = (*k).id;
236  if (toEdge != 0) {
237  // close the previous edge
238  into.closeTag();
239  }
240  toEdge = (*k).toEdge;
241  into.openTag(SUMO_TAG_EDGE);
242  into.writeAttr(SUMO_ATTR_ID, internalEdgeID);
244  // open a new edge
245  }
246  // to avoid changing to an internal lane which has a successor
247  // with the wrong permissions we need to inherit them from the successor
248  const NBEdge::Lane& successor = (*k).toEdge->getLanes()[(*k).toLane];
249  const SUMOReal length = lengthSum[toEdge] / numLanes[toEdge];
250  // @note the actual length should be used once sumo supports lanes of
251  // varying length within the same edge
252  //const SUMOReal length = MAX2((*k).shape.length(), POSITION_EPS);
253  writeLane(into, internalEdgeID, (*k).getInternalLaneID(), (*k).vmax,
254  successor.permissions, successor.preferred,
255  NBEdge::UNSPECIFIED_OFFSET, successor.width, (*k).shape, (*k).origID,
256  length, (*k).internalLaneIndex, origNames, &n);
257  haveVia = haveVia || (*k).haveVia;
258  }
259  ret = true;
260  into.closeTag(); // close the last edge
261  // third pass: write via edges
262  if (haveVia) {
263  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
264  if (!(*k).haveVia) {
265  continue;
266  }
267  if ((*k).toEdge == 0) {
268  assert(false); // should never happen. tell me when it does
269  continue;
270  }
271  const NBEdge::Lane& successor = (*k).toEdge->getLanes()[(*k).toLane];
272  into.openTag(SUMO_TAG_EDGE);
273  into.writeAttr(SUMO_ATTR_ID, (*k).viaID);
275  writeLane(into, (*k).viaID, (*k).viaID + "_0", (*k).viaVmax, SVCAll, SVCAll,
276  NBEdge::UNSPECIFIED_OFFSET, successor.width, (*k).viaShape, (*k).origID,
277  MAX2((*k).viaShape.length(), POSITION_EPS), // microsim needs positive length
278  0, origNames, &n);
279  into.closeTag();
280  }
281  }
282  }
283  }
284  // write pedestrian crossings
285  const std::vector<NBNode::Crossing>& crossings = n.getCrossings();
286  for (std::vector<NBNode::Crossing>::const_iterator it = crossings.begin(); it != crossings.end(); it++) {
287  into.openTag(SUMO_TAG_EDGE);
288  into.writeAttr(SUMO_ATTR_ID, (*it).id);
290  into.writeAttr(SUMO_ATTR_CROSSING_EDGES, (*it).edges);
291  writeLane(into, (*it).id, (*it).id + "_0", 1, SVC_PEDESTRIAN, 0,
292  NBEdge::UNSPECIFIED_OFFSET, (*it).width, (*it).shape, "", (*it).shape.length(), 0, false, &n);
293  into.closeTag();
294  }
295  // write pedestrian walking areas
296  const std::vector<NBNode::WalkingArea>& WalkingAreas = n.getWalkingAreas();
297  for (std::vector<NBNode::WalkingArea>::const_iterator it = WalkingAreas.begin(); it != WalkingAreas.end(); it++) {
298  const NBNode::WalkingArea& wa = *it;
299  into.openTag(SUMO_TAG_EDGE);
300  into.writeAttr(SUMO_ATTR_ID, wa.id);
302  writeLane(into, wa.id, wa.id + "_0", 1, SVC_PEDESTRIAN, 0,
303  NBEdge::UNSPECIFIED_OFFSET, wa.width, wa.shape, "", wa.length, 0, false, &n);
304  into.closeTag();
305  }
306  return ret;
307 }
308 
309 
310 void
311 NWWriter_SUMO::writeEdge(OutputDevice& into, const NBEdge& e, bool noNames, bool origNames) {
312  // write the edge's begin
315  into.writeAttr(SUMO_ATTR_TO, e.getToNode()->getID());
316  if (!noNames && e.getStreetName() != "") {
318  }
320  if (e.getTypeName() != "") {
322  }
323  if (e.isMacroscopicConnector()) {
325  }
326  // write the spread type if not default ("right")
329  }
330  if (e.hasLoadedLength()) {
332  }
333  if (!e.hasDefaultGeometry()) {
335  }
336  // write the lanes
337  const std::vector<NBEdge::Lane>& lanes = e.getLanes();
338 
339  SUMOReal length = e.getLoadedLength();
340  if (OptionsCont::getOptions().getBool("no-internal-links") && !e.hasLoadedLength()) {
341  // use length to junction center even if a modified geometry was given
342  PositionVector geom = e.getGeometry();
345  length = geom.length();
346  }
347  if (length <= 0) {
348  length = POSITION_EPS;
349  }
350  for (unsigned int i = 0; i < (unsigned int) lanes.size(); i++) {
351  const NBEdge::Lane& l = lanes[i];
352  writeLane(into, e.getID(), e.getLaneID(i), l.speed,
353  l.permissions, l.preferred, l.endOffset, l.width, l.shape, l.origID,
354  length, i, origNames);
355  }
356  // close the edge
357  into.closeTag();
358 }
359 
360 
361 void
362 NWWriter_SUMO::writeLane(OutputDevice& into, const std::string& eID, const std::string& lID,
363  SUMOReal speed, SVCPermissions permissions, SVCPermissions preferred,
364  SUMOReal endOffset, SUMOReal width, PositionVector shape,
365  const std::string& origID, SUMOReal length, unsigned int index, bool origNames,
366  const NBNode* node) {
367  // output the lane's attributes
369  // the first lane of an edge will be the depart lane
370  into.writeAttr(SUMO_ATTR_INDEX, index);
371  // write the list of allowed/disallowed vehicle classes
372  writePermissions(into, permissions);
373  writePreferences(into, preferred);
374  // some further information
375  if (speed == 0) {
376  WRITE_WARNING("Lane #" + toString(index) + " of edge '" + eID + "' has a maximum velocity of 0.");
377  } else if (speed < 0) {
378  throw ProcessError("Negative velocity (" + toString(speed) + " on edge '" + eID + "' lane#" + toString(index) + ".");
379  }
380  if (endOffset > 0) {
381  length = length - endOffset;
382  }
383  into.writeAttr(SUMO_ATTR_SPEED, speed);
384  into.writeAttr(SUMO_ATTR_LENGTH, length);
385  if (endOffset != NBEdge::UNSPECIFIED_OFFSET) {
386  into.writeAttr(SUMO_ATTR_ENDOFFSET, endOffset);
387  }
388  if (width != NBEdge::UNSPECIFIED_WIDTH) {
389  into.writeAttr(SUMO_ATTR_WIDTH, width);
390  }
391  if (node != 0) {
392  const NBNode::CustomShapeMap& cs = node->getCustomLaneShapes();
393  NBNode::CustomShapeMap::const_iterator it = cs.find(lID);
394  if (it != cs.end()) {
395  shape = it->second;
396  into.writeAttr(SUMO_ATTR_CUSTOMSHAPE, true);
397  }
398  }
399  into.writeAttr(SUMO_ATTR_SHAPE, endOffset > 0 ?
400  shape.getSubpart(0, shape.length() - endOffset) : shape);
401  if (origNames && origID != "") {
402  into.openTag(SUMO_TAG_PARAM);
403  into.writeAttr(SUMO_ATTR_KEY, "origId");
404  into.writeAttr(SUMO_ATTR_VALUE, origID);
405  into.closeTag();
406  into.closeTag();
407  } else {
408  into.closeTag();
409  }
410 }
411 
412 
413 void
414 NWWriter_SUMO::writeJunction(OutputDevice& into, const NBNode& n, const bool checkLaneFoes) {
415  // write the attributes
417  into.writeAttr(SUMO_ATTR_TYPE, n.getType());
419  // write the incoming lanes
420  std::string incLanes;
421  const std::vector<NBEdge*>& incoming = n.getIncomingEdges();
422  for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); ++i) {
423  unsigned int noLanes = (*i)->getNumLanes();
424  for (unsigned int j = 0; j < noLanes; j++) {
425  incLanes += (*i)->getLaneID(j);
426  if (i != incoming.end() - 1 || j < noLanes - 1) {
427  incLanes += ' ';
428  }
429  }
430  }
431  const std::vector<NBNode::Crossing>& crossings = n.getCrossings();
432  for (std::vector<NBNode::Crossing>::const_iterator it = crossings.begin(); it != crossings.end(); it++) {
433  incLanes += ' ' + (*it).prevWalkingArea + "_0";
434  }
435  into.writeAttr(SUMO_ATTR_INCLANES, incLanes);
436  // write the internal lanes
437  std::string intLanes;
438  if (!OptionsCont::getOptions().getBool("no-internal-links")) {
439  unsigned int l = 0;
440  for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
441  const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
442  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
443  if ((*k).toEdge == 0) {
444  continue;
445  }
446  if (l != 0) {
447  intLanes += ' ';
448  }
449  if (!(*k).haveVia) {
450  intLanes += (*k).getInternalLaneID();
451  } else {
452  intLanes += (*k).viaID + "_0";
453  }
454  l++;
455  }
456  }
457  }
458  if (n.getType() != NODETYPE_DEAD_END && n.getType() != NODETYPE_NOJUNCTION) {
459  for (std::vector<NBNode::Crossing>::const_iterator it = crossings.begin(); it != crossings.end(); it++) {
460  intLanes += ' ' + (*it).id + "_0";
461  }
462  }
463  into.writeAttr(SUMO_ATTR_INTLANES, intLanes);
464  // close writing
466  // write optional radius
469  }
470  // specify whether a custom shape was used
471  if (n.hasCustomShape()) {
472  into.writeAttr(SUMO_ATTR_CUSTOMSHAPE, true);
473  }
474  if (n.getType() == NODETYPE_DEAD_END) {
475  into.closeTag();
476  } else {
477  // write right-of-way logics
478  n.writeLogic(into, checkLaneFoes);
479  into.closeTag();
480  }
481 }
482 
483 
484 bool
486  bool ret = false;
487  const std::vector<NBEdge*>& incoming = n.getIncomingEdges();
488  // build the list of internal lane ids
489  std::vector<std::string> internalLaneIDs;
490  for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
491  const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
492  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
493  if ((*k).toEdge != 0) {
494  internalLaneIDs.push_back((*k).getInternalLaneID());
495  }
496  }
497  }
498  const std::vector<NBNode::Crossing>& crossings = n.getCrossings();
499  for (std::vector<NBNode::Crossing>::const_iterator it_c = crossings.begin(); it_c != crossings.end(); ++it_c) {
500  internalLaneIDs.push_back((*it_c).id + "_0");
501  }
502  // write the internal nodes
503  for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
504  const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
505  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
506  if ((*k).toEdge == 0 || !(*k).haveVia) {
507  continue;
508  }
509  Position pos = (*k).shape[-1];
510  into.openTag(SUMO_TAG_JUNCTION).writeAttr(SUMO_ATTR_ID, (*k).viaID + "_0");
512  NWFrame::writePositionLong(pos, into);
513  std::string incLanes = (*k).getInternalLaneID();
514  if ((*k).foeIncomingLanes.length() != 0) {
515  incLanes += " " + (*k).foeIncomingLanes;
516  }
517  into.writeAttr(SUMO_ATTR_INCLANES, incLanes);
518  const std::vector<unsigned int>& foes = (*k).foeInternalLinks;
519  std::vector<std::string> foeIDs;
520  for (std::vector<unsigned int>::const_iterator it = foes.begin(); it != foes.end(); ++it) {
521  foeIDs.push_back(internalLaneIDs[*it]);
522  }
523  into.writeAttr(SUMO_ATTR_INTLANES, joinToString(foeIDs, " "));
524  into.closeTag();
525  ret = true;
526  }
527  }
528  return ret;
529 }
530 
531 
532 void
534  bool includeInternal, ConnectionStyle style) {
535  assert(c.toEdge != 0);
537  into.writeAttr(SUMO_ATTR_FROM, from.getID());
538  into.writeAttr(SUMO_ATTR_TO, c.toEdge->getID());
541  if (c.mayDefinitelyPass && style != TLL) {
543  }
544  if (style != PLAIN) {
545  if (includeInternal) {
547  }
548  // set information about the controlling tl if any
549  if (c.tlID != "") {
550  into.writeAttr(SUMO_ATTR_TLID, c.tlID);
552  }
553  if (style == SUMONET) {
554  // write the direction information
555  LinkDirection dir = from.getToNode()->getDirection(&from, c.toEdge);
556  assert(dir != LINKDIR_NODIR);
557  into.writeAttr(SUMO_ATTR_DIR, toString(dir));
558  // write the state information
559  const LinkState linkState = from.getToNode()->getLinkState(
560  &from, c.toEdge, c.fromLane, c.mayDefinitelyPass, c.tlID);
561  into.writeAttr(SUMO_ATTR_STATE, linkState);
562  }
563  }
564  into.closeTag();
565 }
566 
567 
568 bool
570  bool ret = false;
571  const std::vector<NBEdge*>& incoming = n.getIncomingEdges();
572  for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); ++i) {
573  NBEdge* from = *i;
574  const std::vector<NBEdge::Connection>& connections = from->getConnections();
575  for (std::vector<NBEdge::Connection>::const_iterator j = connections.begin(); j != connections.end(); ++j) {
576  const NBEdge::Connection& c = *j;
577  assert(c.toEdge != 0);
578  if (c.haveVia) {
579  // internal split
580  writeInternalConnection(into, c.id, c.toEdge->getID(), c.internalLaneIndex, c.toLane, c.viaID + "_0");
581  writeInternalConnection(into, c.viaID, c.toEdge->getID(), 0, c.toLane, "");
582  } else {
583  // no internal split
585  }
586  ret = true;
587  }
588  }
589  return ret;
590 }
591 
592 
593 void
595  const std::string& from, const std::string& to,
596  int fromLane, int toLane, const std::string& via) {
598  into.writeAttr(SUMO_ATTR_FROM, from);
599  into.writeAttr(SUMO_ATTR_TO, to);
600  into.writeAttr(SUMO_ATTR_FROM_LANE, fromLane);
601  into.writeAttr(SUMO_ATTR_TO_LANE, toLane);
602  if (via != "") {
603  into.writeAttr(SUMO_ATTR_VIA, via);
604  }
605  into.writeAttr(SUMO_ATTR_DIR, "s");
606  into.writeAttr(SUMO_ATTR_STATE, (via != "" ? "m" : "M"));
607  into.closeTag();
608 }
609 
610 
611 void
612 NWWriter_SUMO::writeRoundabouts(OutputDevice& into, const std::set<EdgeSet>& roundabouts,
613  const NBEdgeCont& ec) {
614  // make output deterministic
615  std::vector<std::vector<std::string> > edgeIDs;
616  for (std::set<EdgeSet>::const_iterator i = roundabouts.begin(); i != roundabouts.end(); ++i) {
617  std::vector<std::string> tEdgeIDs;
618  for (EdgeSet::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
619  tEdgeIDs.push_back((*j)->getID());
620  }
621  std::sort(tEdgeIDs.begin(), tEdgeIDs.end());
622  edgeIDs.push_back(tEdgeIDs);
623  }
624  std::sort(edgeIDs.begin(), edgeIDs.end());
625  // write
626  for (std::vector<std::vector<std::string> >::const_iterator i = edgeIDs.begin(); i != edgeIDs.end(); ++i) {
627  writeRoundabout(into, *i, ec);
628  }
629  if (roundabouts.size() != 0) {
630  into.lf();
631  }
632 }
633 
634 
635 void
636 NWWriter_SUMO::writeRoundabout(OutputDevice& into, const std::vector<std::string>& edgeIDs,
637  const NBEdgeCont& ec) {
638  std::vector<std::string> validEdgeIDs;
639  std::vector<std::string> invalidEdgeIDs;
640  std::vector<std::string> nodeIDs;
641  for (std::vector<std::string>::const_iterator i = edgeIDs.begin(); i != edgeIDs.end(); ++i) {
642  const NBEdge* edge = ec.retrieve(*i);
643  if (edge != 0) {
644  nodeIDs.push_back(edge->getToNode()->getID());
645  validEdgeIDs.push_back(edge->getID());
646  } else {
647  invalidEdgeIDs.push_back(*i);
648  }
649  }
650  std::sort(nodeIDs.begin(), nodeIDs.end());
651  if (validEdgeIDs.size() > 0) {
653  into.writeAttr(SUMO_ATTR_NODES, joinToString(nodeIDs, " "));
654  into.writeAttr(SUMO_ATTR_EDGES, joinToString(validEdgeIDs, " "));
655  into.closeTag();
656  if (invalidEdgeIDs.size() > 0) {
657  WRITE_WARNING("Writing incomplete roundabout. Edges: '"
658  + joinToString(invalidEdgeIDs, " ") + "' no longer exist'");
659  }
660  }
661 }
662 
663 
664 void
666  std::vector<SUMOReal> sourceW = d.getSourceWeights();
668  std::vector<SUMOReal> sinkW = d.getSinkWeights();
670  // write the head and the id of the district
672  if (d.getShape().size() > 0) {
674  }
675  size_t i;
676  // write all sources
677  const std::vector<NBEdge*>& sources = d.getSourceEdges();
678  for (i = 0; i < sources.size(); i++) {
679  // write the head and the id of the source
680  into.openTag(SUMO_TAG_TAZSOURCE).writeAttr(SUMO_ATTR_ID, sources[i]->getID()).writeAttr(SUMO_ATTR_WEIGHT, sourceW[i]);
681  into.closeTag();
682  }
683  // write all sinks
684  const std::vector<NBEdge*>& sinks = d.getSinkEdges();
685  for (i = 0; i < sinks.size(); i++) {
686  // write the head and the id of the sink
687  into.openTag(SUMO_TAG_TAZSINK).writeAttr(SUMO_ATTR_ID, sinks[i]->getID()).writeAttr(SUMO_ATTR_WEIGHT, sinkW[i]);
688  into.closeTag();
689  }
690  // write the tail
691  into.closeTag();
692 }
693 
694 
695 std::string
697  SUMOReal time = STEPS2TIME(steps);
698  if (time == std::floor(time)) {
699  return toString(int(time));
700  } else {
701  return toString(time);
702  }
703 }
704 
705 
706 void
708  for (NBConnectionProhibits::const_iterator j = prohibitions.begin(); j != prohibitions.end(); j++) {
709  NBConnection prohibited = (*j).first;
710  const NBConnectionVector& prohibiting = (*j).second;
711  for (NBConnectionVector::const_iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
712  NBConnection prohibitor = *k;
716  into.closeTag();
717  }
718  }
719 }
720 
721 
722 std::string
724  return c.getFrom()->getID() + "->" + c.getTo()->getID();
725 }
726 
727 
728 void
730  std::vector<NBTrafficLightLogic*> logics = tllCont.getComputed();
731  for (std::vector<NBTrafficLightLogic*>::iterator it = logics.begin(); it != logics.end(); it++) {
733  into.writeAttr(SUMO_ATTR_ID, (*it)->getID());
734  into.writeAttr(SUMO_ATTR_TYPE, (*it)->getType());
735  into.writeAttr(SUMO_ATTR_PROGRAMID, (*it)->getProgramID());
736  into.writeAttr(SUMO_ATTR_OFFSET, writeSUMOTime((*it)->getOffset()));
737  // write params
738  const std::map<std::string, std::string>& params = (*it)->getMap();
739  for (std::map<std::string, std::string>::const_iterator i = params.begin(); i != params.end(); ++i) {
740  into.openTag(SUMO_TAG_PARAM);
741  into.writeAttr(SUMO_ATTR_KEY, (*i).first);
742  into.writeAttr(SUMO_ATTR_VALUE, (*i).second);
743  into.closeTag();
744  }
745  // write the phases
746  const std::vector<NBTrafficLightLogic::PhaseDefinition>& phases = (*it)->getPhases();
747  for (std::vector<NBTrafficLightLogic::PhaseDefinition>::const_iterator j = phases.begin(); j != phases.end(); ++j) {
748  into.openTag(SUMO_TAG_PHASE);
749  into.writeAttr(SUMO_ATTR_DURATION, writeSUMOTime(j->duration));
750  into.writeAttr(SUMO_ATTR_STATE, j->state);
751  into.closeTag();
752  }
753  into.closeTag();
754  }
755  if (logics.size() > 0) {
756  into.lf();
757  }
758 }
759 
760 
761 void
763  if (permissions == SVCAll) {
764  return;
765  } else if (permissions == 0) {
766  into.writeAttr(SUMO_ATTR_DISALLOW, "all");
767  return;
768  } else {
769  size_t num_allowed = 0;
770  for (int mask = 1; mask <= SUMOVehicleClass_MAX; mask = mask << 1) {
771  if ((mask & permissions) == mask) {
772  ++num_allowed;
773  }
774  }
775  if (num_allowed <= (SumoVehicleClassStrings.size() - num_allowed) && num_allowed > 0) {
776  into.writeAttr(SUMO_ATTR_ALLOW, getVehicleClassNames(permissions));
777  } else {
779  }
780  }
781 }
782 
783 
784 void
786  if (preferred == SVCAll || preferred == 0) {
787  return;
788  } else {
790  }
791 }
792 /****************************************************************************/
793 
static void writeRoundabout(OutputDevice &into, const std::vector< std::string > &r, const NBEdgeCont &ec)
Writes a roundabout.
std::string id
Definition: NBEdge.h:177
The information about how to spread the lanes from the given position.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:257
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges.
Definition: NBNode.h:251
void close()
Closes the device and removes it from the dictionary.
static void writeLocation(OutputDevice &into)
writes the location element
SUMOReal endOffset
This lane's offset to the intersection begin.
Definition: NBEdge.h:136
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:148
int toLane
The lane the connections yields in.
Definition: NBEdge.h:166
Position getCenter() const
Returns a position that is guaranteed to lie within the node shape.
Definition: NBNode.cpp:2242
a list of node ids, used for controlling joining
static const SUMOReal UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:201
PositionVector shape
The lane's shape.
Definition: NBEdge.h:128
whether a given shape is user-defined
is a pedestrian
static void writeDistrict(OutputDevice &into, const NBDistrict &d)
Writes a district.
const std::string & getTypeName() const
Returns the type name.
Definition: NBEdge.h:502
std::string viaID
Definition: NBEdge.h:182
NBEdge * toEdge
The edge the connections yields in.
Definition: NBEdge.h:164
bool hasDefaultGeometry() const
Returns whether the geometry consists only of the node positions.
Definition: NBEdge.cpp:400
SUMOReal getRadius() const
Returns the turning radius of this node.
Definition: NBNode.h:283
const std::set< EdgeSet > getRoundabouts() const
Returns the determined roundabouts.
Definition: NBEdgeCont.cpp:912
size_t size() const
Returns the number of districts inside the container.
A container for traffic light definitions and built programs.
SUMOReal length
This lane's width.
Definition: NBNode.h:174
SUMOReal width
This lane's width.
Definition: NBNode.h:172
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
Definition: NBEdge.h:510
const Crossing & getCrossing(const std::string &id) const
return the crossing with the given id
Definition: NBNode.cpp:2218
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
static std::string escapeXML(const std::string &orig)
Replaces the standard escapes by their XML entities.
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:624
T MAX2(T a, T b)
Definition: StdDefs.h:74
the weight of a district's source or sink
bool hasCustomShape() const
return whether the shape was set by the user
Definition: NBNode.h:516
bool mayDefinitelyPass
Information about being definitely free to drive (on-ramps)
Definition: NBEdge.h:172
std::string id
the (edge)-id of this walkingArea
Definition: NBNode.h:170
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:203
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 void writePermissions(OutputDevice &into, SVCPermissions permissions)
writes allowed disallowed attributes if needed;
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:67
bool priority
whether the pedestrians have priority
Definition: NBNode.h:153
LinkDirection
The different directions a link between two lanes may take (or a stream between two edges)...
bool writeXMLHeader(const std::string &rootElement, const std::string &attrs="", const std::string &comment="")
Writes an XML header with optional configuration.
The link is a straight direction.
The state of a link.
SUMOReal speed
The speed allowed on this lane.
Definition: NBEdge.h:130
A class representing a single district.
Definition: NBDistrict.h:72
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
Definition: NBNode.h:83
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't set.
Definition: NBEdge.h:415
An (internal) definition of a single lane of an edge.
Definition: NBEdge.h:123
const std::string & getID() const
Returns the id.
Definition: Named.h:60
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.
void push_front_noDoublePos(const Position &p)
const int SUMOVehicleClass_MAX
const Position & getPosition() const
Returns the position of this node.
Definition: NBNode.h:239
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:355
std::map< std::string, NBDistrict * >::const_iterator begin() const
Returns the pointer to the begin of the stored districts.
std::string getLaneID(unsigned int lane) const
Definition: NBEdge.cpp:2048
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:168
SVCPermissions preferred
List of vehicle types that are preferred on this lane.
Definition: NBEdge.h:134
std::string getInternalLaneID() const
Definition: NBEdge.cpp:76
This is an uncontrolled, minor link, has to brake.
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:162
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:46
std::map< std::string, NBDistrict * >::const_iterator end() const
Returns the pointer to the end of the stored districts.
NBEdgeCont & getEdgeCont()
Returns the edge container.
Definition: NBNetBuilder.h:154
A list of positions.
static void writeLane(OutputDevice &into, const std::string &eID, const std::string &lID, SUMOReal speed, SVCPermissions permissions, SVCPermissions preferred, SUMOReal endOffset, SUMOReal width, PositionVector shape, const std::string &origID, SUMOReal length, unsigned int index, bool origNames, const NBNode *node=0)
Writes a lane (
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:276
static void writeEdge(OutputDevice &into, const NBEdge &e, bool noNames, bool origNames)
Writes an edge (
bool hasLoadedLength() const
Returns whether a length was set explicitly.
Definition: NBEdge.h:423
#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.
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:66
#define POSITION_EPS
Definition: config.h:189
const CustomShapeMap & getCustomLaneShapes() const
sets a custom shape for an internal lane
Definition: NBNode.h:506
static void writePositionLong(const Position &pos, OutputDevice &dev)
Writes the given position to device in long format (one attribute per dimension)
Definition: NWFrame.cpp:143
std::vector< NBTrafficLightLogic * > getComputed() const
Returns a list of all computed logics.
std::map< std::string, NBNode * >::const_iterator end() const
Returns the pointer to the end of the stored nodes.
Definition: NBNodeCont.h:135
StringBijection< SUMOVehicleClass > SumoVehicleClassStrings(sumoVehicleClassStringInitializer, SVC_CUSTOM2, false)
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:53
const PositionVector & getShape() const
retrieve the junction shape
Definition: NBNode.cpp:1461
std::string getVehicleClassNames(SVCPermissions permissions)
Returns the ids of the given classes, divided using a ' '.
std::vector< NBConnection > NBConnectionVector
Definition of a connection vector.
static void normaliseSum(std::vector< T > &v, T msum=1.0)
Definition: VectorHelper.h:58
std::string origID
An original ID, if given (.
Definition: NBEdge.h:140
std::map< std::string, NBEdge * >::const_iterator begin() const
Returns the pointer to the begin of the stored edges.
Definition: NBEdgeCont.h:190
static bool writeInternalEdges(OutputDevice &into, const NBNode &n, bool origNames)
Writes internal edges (
SUMOReal length() const
Returns the length.
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:371
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:258
LinkState getLinkState(const NBEdge *incoming, NBEdge *outgoing, int fromLane, bool mayDefinitelyPass, const std::string &tlID) const
Definition: NBNode.cpp:1357
NBNodeCont & getNodeCont()
Returns the node container.
Definition: NBNetBuilder.h:162
Instance responsible for building networks.
Definition: NBNetBuilder.h:113
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
std::vector< NBEdge * > EdgeVector
Definition: NBCont.h:41
static bool writeInternalNodes(OutputDevice &into, const NBNode &n)
Writes internal junctions (
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:531
A definition of a pedestrian walking area.
Definition: NBNode.h:162
bool isMacroscopicConnector() const
Returns whether this edge was marked as a macroscopic connector.
Definition: NBEdge.h:859
A storage for options typed value containers)
Definition: OptionsCont.h:108
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:847
NBTrafficLightLogicCont & getTLLogicCont()
Returns the traffic light logics container.
Definition: NBNetBuilder.h:178
static void writePreferences(OutputDevice &into, SVCPermissions preferred)
writes allowed disallowed attributes if needed;
int SUMOTime
Definition: SUMOTime.h:43
unsigned int tlLinkNo
The index of this connection within the controlling traffic light.
Definition: NBEdge.h:170
NBEdge * getTo() const
returns the to-edge (end of the connection)
The abstract direction of a link.
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge's lanes' lateral offset is computed.
Definition: NBEdge.h:611
Represents a single node (junction) during network building.
Definition: NBNode.h:75
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:159
A definition of a pedestrian crossing.
Definition: NBNode.h:134
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:218
static const SUMOReal UNSPECIFIED_RADIUS
unspecified lane width
Definition: NBNode.h:197
static void writeJunction(OutputDevice &into, const NBNode &n, const bool checkLaneFoes)
Writes a junction (
bool writeLogic(OutputDevice &into, const bool checkLaneFoes) const
Definition: NBNode.cpp:701
const std::vector< SUMOReal > & getSourceWeights() const
Returns the weights of the sources.
Definition: NBDistrict.h:190
void push_back_noDoublePos(const Position &p)
const std::vector< SUMOReal > & getSinkWeights() const
Returns the weights of the sinks.
Definition: NBDistrict.h:206
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:64
unsigned int internalLaneIndex
The lane index of this internal lane within the internal edge.
Definition: NBEdge.h:190
const std::vector< WalkingArea > & getWalkingAreas() const
return this junctions pedestrian walking areas
Definition: NBNode.h:629
NBDistrictCont & getDistrictCont()
Returns the districts container.
Definition: NBNetBuilder.h:186
const std::string & getStreetName() const
Returns the street name of this edge.
Definition: NBEdge.h:465
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:761
static const std::string MAJOR_VERSION
The version number for written files.
Definition: NWFrame.h:77
std::map< std::string, NBNode * >::const_iterator begin() const
Returns the pointer to the begin of the stored nodes.
Definition: NBNodeCont.h:127
static void writeRoundabouts(OutputDevice &into, const std::set< EdgeSet > &roundabouts, const NBEdgeCont &ec)
Writes roundabouts.
PositionVector getSubpart(SUMOReal beginOffset, SUMOReal endOffset) const
static std::string writeSUMOTime(SUMOTime time)
writes a SUMOTime as int if possible, otherwise as a float
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
void lf()
writes a line feed if applicable
Definition: OutputDevice.h:235
SUMOReal width
This lane's width.
Definition: NBEdge.h:138
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:176
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)
LinkDirection getDirection(const NBEdge *const incoming, const NBEdge *const outgoing) const
Returns the representation of the described stream's direction.
Definition: NBNode.cpp:1311
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:363