Eclipse 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-2020 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
21 // Exporter writing networks using the SUMO format
22 /****************************************************************************/
23 #include <config.h>
24 #include <cmath>
25 #include <algorithm>
29 #include <utils/common/ToString.h>
34 #include <netbuild/NBEdge.h>
35 #include <netbuild/NBEdgeCont.h>
36 #include <netbuild/NBNode.h>
37 #include <netbuild/NBNodeCont.h>
38 #include <netbuild/NBNetBuilder.h>
40 #include <netbuild/NBDistrict.h>
41 #include <netbuild/NBHelpers.h>
42 #include "NWFrame.h"
43 #include "NWWriter_SUMO.h"
44 
45 
46 //#define DEBUG_OPPOSITE_INTERNAL
47 
48 // ===========================================================================
49 // method definitions
50 // ===========================================================================
51 // ---------------------------------------------------------------------------
52 // static methods
53 // ---------------------------------------------------------------------------
54 void
56  // check whether a sumo net-file shall be generated
57  if (!oc.isSet("output-file")) {
58  return;
59  }
60  OutputDevice& device = OutputDevice::getDevice(oc.getString("output-file"));
61  std::map<SumoXMLAttr, std::string> attrs;
63  if (oc.getBool("lefthand") != oc.getBool("flip-y-axis")) {
64  attrs[SUMO_ATTR_LEFTHAND] = "true";
65  } else if (oc.getBool("lefthand")) {
66  // network was flipped, correct written link directions
68  OptionsCont::getOptions().set("lefthand", "false");
69  }
70  const int cornerDetail = oc.getInt("junctions.corner-detail");
71  if (cornerDetail > 0) {
72  attrs[SUMO_ATTR_CORNERDETAIL] = toString(cornerDetail);
73  }
74  if (!oc.isDefault("junctions.internal-link-detail")) {
75  attrs[SUMO_ATTR_LINKDETAIL] = toString(oc.getInt("junctions.internal-link-detail"));
76  }
77  if (oc.getBool("rectangular-lane-cut")) {
78  attrs[SUMO_ATTR_RECTANGULAR_LANE_CUT] = "true";
79  }
80  if (oc.getBool("crossings.guess") || oc.getBool("walkingareas")) {
81  attrs[SUMO_ATTR_WALKINGAREAS] = "true";
82  }
83  if (oc.getFloat("junctions.limit-turn-speed") > 0) {
84  attrs[SUMO_ATTR_LIMIT_TURN_SPEED] = toString(oc.getFloat("junctions.limit-turn-speed"));
85  }
86  if (!oc.isDefault("check-lane-foes.all")) {
87  attrs[SUMO_ATTR_CHECKLANEFOES_ALL] = toString(oc.getBool("check-lane-foes.all"));
88  }
89  if (!oc.isDefault("check-lane-foes.roundabout")) {
90  attrs[SUMO_ATTR_CHECKLANEFOES_ROUNDABOUT] = toString(oc.getBool("check-lane-foes.roundabout"));
91  }
92  if (!oc.isDefault("tls.ignore-internal-junction-jam")) {
93  attrs[SUMO_ATTR_TLS_IGNORE_INTERNAL_JUNCTION_JAM] = toString(oc.getBool("tls.ignore-internal-junction-jam"));
94  }
95  if (oc.getString("default.spreadtype") != "right") {
96  attrs[SUMO_ATTR_SPREADTYPE] = oc.getString("default.spreadtype");
97  }
98  if (oc.exists("geometry.avoid-overlap") && !oc.getBool("geometry.avoid-overlap")) {
99  attrs[SUMO_ATTR_AVOID_OVERLAP] = toString(oc.getBool("geometry.avoid-overlap"));
100  }
101  device.writeXMLHeader("net", "net_file.xsd", attrs); // street names may contain non-ascii chars
102  device.lf();
103  // get involved container
104  const NBNodeCont& nc = nb.getNodeCont();
105  const NBEdgeCont& ec = nb.getEdgeCont();
106  const NBDistrictCont& dc = nb.getDistrictCont();
107 
108  // write network offsets and projection
110 
111  // write edge types and restrictions
112  nb.getTypeCont().writeEdgeTypes(device);
113 
114  // write inner lanes
115  if (!oc.getBool("no-internal-links")) {
116  bool hadAny = false;
117  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
118  hadAny |= writeInternalEdges(device, ec, *(*i).second);
119  }
120  if (hadAny) {
121  device.lf();
122  }
123  }
124 
125  // write edges with lanes and connected edges
126  bool noNames = !oc.getBool("output.street-names");
127  for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
128  writeEdge(device, *(*i).second, noNames);
129  }
130  device.lf();
131 
132  // write tls logics
133  writeTrafficLights(device, nb.getTLLogicCont());
134 
135  // write the nodes (junctions)
136  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
137  writeJunction(device, *(*i).second);
138  }
139  device.lf();
140  const bool includeInternal = !oc.getBool("no-internal-links");
141  if (includeInternal) {
142  // ... internal nodes if not unwanted
143  bool hadAny = false;
144  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
145  hadAny |= writeInternalNodes(device, *(*i).second);
146  }
147  if (hadAny) {
148  device.lf();
149  }
150  }
151 
152  // write the successors of lanes
153  int numConnections = 0;
154  for (std::map<std::string, NBEdge*>::const_iterator it_edge = ec.begin(); it_edge != ec.end(); it_edge++) {
155  NBEdge* from = it_edge->second;
156  const std::vector<NBEdge::Connection> connections = from->getConnections();
157  numConnections += (int)connections.size();
158  for (std::vector<NBEdge::Connection>::const_iterator it_c = connections.begin(); it_c != connections.end(); it_c++) {
159  writeConnection(device, *from, *it_c, includeInternal);
160  }
161  }
162  if (numConnections > 0) {
163  device.lf();
164  }
165  if (includeInternal) {
166  // ... internal successors if not unwanted
167  bool hadAny = false;
168  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
169  hadAny |= writeInternalConnections(device, *(*i).second);
170  }
171  if (hadAny) {
172  device.lf();
173  }
174  }
175  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
176  NBNode* node = (*i).second;
177  // write connections from pedestrian crossings
178  std::vector<NBNode::Crossing*> crossings = node->getCrossings();
179  for (auto c : crossings) {
180  NWWriter_SUMO::writeInternalConnection(device, c->id, c->nextWalkingArea, 0, 0, "", LinkDirection::STRAIGHT, c->tlID, c->tlLinkIndex2);
181  }
182  // write connections from pedestrian walking areas
183  for (const NBNode::WalkingArea& wa : node->getWalkingAreas()) {
184  for (const std::string& cID : wa.nextCrossings) {
185  const NBNode::Crossing& nextCrossing = *node->getCrossing(cID);
186  // connection to next crossing (may be tls-controlled)
188  device.writeAttr(SUMO_ATTR_FROM, wa.id);
189  device.writeAttr(SUMO_ATTR_TO, cID);
190  device.writeAttr(SUMO_ATTR_FROM_LANE, 0);
191  device.writeAttr(SUMO_ATTR_TO_LANE, 0);
192  if (nextCrossing.tlID != "") {
193  device.writeAttr(SUMO_ATTR_TLID, nextCrossing.tlID);
194  assert(nextCrossing.tlLinkIndex >= 0);
195  device.writeAttr(SUMO_ATTR_TLLINKINDEX, nextCrossing.tlLinkIndex);
196  }
199  device.closeTag();
200  }
201  // optional connections from/to sidewalk
202  std::string edgeID;
203  int laneIndex;
204  for (const std::string& sw : wa.nextSidewalks) {
205  NBHelpers::interpretLaneID(sw, edgeID, laneIndex);
206  NWWriter_SUMO::writeInternalConnection(device, wa.id, edgeID, 0, laneIndex, "");
207  }
208  for (const std::string& sw : wa.prevSidewalks) {
209  NBHelpers::interpretLaneID(sw, edgeID, laneIndex);
210  NWWriter_SUMO::writeInternalConnection(device, edgeID, wa.id, laneIndex, 0, "");
211  }
212  }
213  }
214 
215  // write loaded prohibitions
216  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
217  writeProhibitions(device, i->second->getProhibitions());
218  }
219 
220  // write roundabout information
221  writeRoundabouts(device, ec.getRoundabouts(), ec);
222 
223  // write the districts
224  if (dc.size() != 0 && oc.isDefault("taz-output")) {
225  WRITE_WARNING("Embedding TAZ-data inside the network is deprecated. Use option --taz-output instead");
226  for (std::map<std::string, NBDistrict*>::const_iterator i = dc.begin(); i != dc.end(); i++) {
227  writeDistrict(device, *(*i).second);
228  }
229  device.lf();
230  }
231  device.close();
232 }
233 
234 
235 std::string
236 NWWriter_SUMO::getOppositeInternalID(const NBEdgeCont& ec, const NBEdge* from, const NBEdge::Connection& con, double& oppositeLength) {
237  const NBEdge::Lane& succ = con.toEdge->getLanes()[con.toLane];
238  const NBEdge::Lane& pred = from->getLanes()[con.fromLane];
239  const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
240  if (succ.oppositeID != "" && succ.oppositeID != "-" && pred.oppositeID != "" && pred.oppositeID != "-") {
241 #ifdef DEBUG_OPPOSITE_INTERNAL
242  std::cout << "getOppositeInternalID con=" << con.getDescription(from) << " (" << con.getInternalLaneID() << ")\n";
243 #endif
244  // find the connection that connects succ.oppositeID to pred.oppositeID
245  const NBEdge* succOpp = ec.retrieve(succ.oppositeID.substr(0, succ.oppositeID.rfind("_")));
246  const NBEdge* predOpp = ec.retrieve(pred.oppositeID.substr(0, pred.oppositeID.rfind("_")));
247  assert(succOpp != 0);
248  assert(predOpp != 0);
249  const std::vector<NBEdge::Connection>& connections = succOpp->getConnections();
250  for (std::vector<NBEdge::Connection>::const_iterator it_c = connections.begin(); it_c != connections.end(); it_c++) {
251  const NBEdge::Connection& conOpp = *it_c;
252  if (succOpp != from // turnaround
253  && predOpp == conOpp.toEdge
254  && succOpp->getLaneID(conOpp.fromLane) == succ.oppositeID
255  && predOpp->getLaneID(conOpp.toLane) == pred.oppositeID
256  && from->getToNode()->getDirection(from, con.toEdge, lefthand) == LinkDirection::STRAIGHT
257  && from->getToNode()->getDirection(succOpp, predOpp, lefthand) == LinkDirection::STRAIGHT
258  ) {
259 #ifdef DEBUG_OPPOSITE_INTERNAL
260  std::cout << " found " << conOpp.getInternalLaneID() << "\n";
261 #endif
262  oppositeLength = conOpp.length;
263  return conOpp.getInternalLaneID();
264  } else {
265  /*
266  #ifdef DEBUG_OPPOSITE_INTERNAL
267  std::cout << " rejected " << conOpp.getInternalLaneID()
268  << "\n succ.oppositeID=" << succ.oppositeID
269  << "\n succOppLane=" << succOpp->getLaneID(conOpp.fromLane)
270  << "\n pred.oppositeID=" << pred.oppositeID
271  << "\n predOppLane=" << predOpp->getLaneID(conOpp.toLane)
272  << "\n predOpp=" << predOpp->getID()
273  << "\n conOppTo=" << conOpp.toEdge->getID()
274  << "\n len1=" << con.shape.length()
275  << "\n len2=" << conOpp.shape.length()
276  << "\n";
277  #endif
278  */
279  }
280  }
281  return "";
282  } else {
283  return "";
284  }
285 }
286 
287 
288 bool
290  bool ret = false;
291  const EdgeVector& incoming = n.getIncomingEdges();
292  // first pass: determine opposite internal edges and average their length
293  std::map<std::string, std::string> oppositeLaneID;
294  std::map<std::string, double> oppositeLengths;
295  for (NBEdge* e : incoming) {
296  for (const NBEdge::Connection& c : e->getConnections()) {
297  double oppositeLength = 0;
298  const std::string op = getOppositeInternalID(ec, e, c, oppositeLength);
299  oppositeLaneID[c.getInternalLaneID()] = op;
300  if (op != "") {
301  oppositeLengths[c.id] = oppositeLength;
302  }
303  }
304  }
305  if (oppositeLengths.size() > 0) {
306  for (NBEdge* e : incoming) {
307  for (NBEdge::Connection& c : e->getConnections()) {
308  if (oppositeLengths.count(c.id) > 0) {
309  c.length = (c.length + oppositeLengths[c.id]) / 2;
310  }
311  }
312  }
313  }
314 
315  for (NBEdge* e : incoming) {
316  const std::vector<NBEdge::Connection>& elv = e->getConnections();
317  if (elv.size() > 0) {
318  bool haveVia = false;
319  std::string edgeID = "";
320  // second pass: write non-via edges
321  for (const NBEdge::Connection& k : elv) {
322  if (k.toEdge == nullptr) {
323  assert(false); // should never happen. tell me when it does
324  continue;
325  }
326  if (edgeID != k.id) {
327  if (edgeID != "") {
328  // close the previous edge
329  into.closeTag();
330  }
331  edgeID = k.id;
332  into.openTag(SUMO_TAG_EDGE);
333  into.writeAttr(SUMO_ATTR_ID, edgeID);
335  if (e->isBidiRail() && k.toEdge->isBidiRail() &&
336  e != k.toEdge->getTurnDestination(true)) {
337  try {
339  0, e->getTurnDestination(true), 0);
340  into.writeAttr(SUMO_ATTR_BIDI, bidiCon.id);
341  } catch (ProcessError&) {
342  WRITE_WARNINGF("Could not find bidi-connection for edge '%'", edgeID)
343  }
344  }
345  // open a new edge
346  }
347  // to avoid changing to an internal lane which has a successor
348  // with the wrong permissions we need to inherit them from the successor
349  const NBEdge::Lane& successor = k.toEdge->getLanes()[k.toLane];
350  SVCPermissions permissions = (k.permissions != SVC_UNSPECIFIED) ? k.permissions : (
351  successor.permissions & e->getPermissions(k.fromLane));
352  const double width = n.isConstantWidthTransition() && e->getNumLanes() > k.toEdge->getNumLanes() ? e->getLaneWidth(k.fromLane) : successor.width;
353  writeLane(into, k.getInternalLaneID(), k.vmax,
354  permissions, successor.preferred,
356  std::map<int, double>(), width, k.shape, &k,
357  k.length, k.internalLaneIndex, oppositeLaneID[k.getInternalLaneID()], "");
358  haveVia = haveVia || k.haveVia;
359  }
360  ret = true;
361  into.closeTag(); // close the last edge
362  // third pass: write via edges
363  if (haveVia) {
364  for (const NBEdge::Connection& k : elv) {
365  if (!k.haveVia) {
366  continue;
367  }
368  if (k.toEdge == nullptr) {
369  assert(false); // should never happen. tell me when it does
370  continue;
371  }
372  const NBEdge::Lane& successor = k.toEdge->getLanes()[k.toLane];
373  into.openTag(SUMO_TAG_EDGE);
374  into.writeAttr(SUMO_ATTR_ID, k.viaID);
376  SVCPermissions permissions = (k.permissions != SVC_UNSPECIFIED) ? k.permissions : (
377  successor.permissions & e->getPermissions(k.fromLane));
378  writeLane(into, k.viaID + "_0", k.vmax, permissions, successor.preferred,
380  std::map<int, double>(), successor.width, k.viaShape, &k,
381  MAX2(k.viaLength, POSITION_EPS), // microsim needs positive length
382  0, "", "");
383  into.closeTag();
384  }
385  }
386  }
387  }
388  // write pedestrian crossings
389  for (auto c : n.getCrossings()) {
390  into.openTag(SUMO_TAG_EDGE);
391  into.writeAttr(SUMO_ATTR_ID, c->id);
393  into.writeAttr(SUMO_ATTR_CROSSING_EDGES, c->edges);
394  writeLane(into, c->id + "_0", 1, SVC_PEDESTRIAN, 0,
396  std::map<int, double>(), c->width, c->shape, nullptr,
397  MAX2(c->shape.length(), POSITION_EPS), 0, "", "", false, c->customShape.size() != 0);
398  into.closeTag();
399  }
400  // write pedestrian walking areas
401  const std::vector<NBNode::WalkingArea>& WalkingAreas = n.getWalkingAreas();
402  for (std::vector<NBNode::WalkingArea>::const_iterator it = WalkingAreas.begin(); it != WalkingAreas.end(); it++) {
403  const NBNode::WalkingArea& wa = *it;
404  into.openTag(SUMO_TAG_EDGE);
405  into.writeAttr(SUMO_ATTR_ID, wa.id);
407  writeLane(into, wa.id + "_0", 1, SVC_PEDESTRIAN, 0,
409  std::map<int, double>(), wa.width, wa.shape, nullptr, wa.length, 0, "", "", false, wa.hasCustomShape);
410  into.closeTag();
411  }
412  return ret;
413 }
414 
415 
416 void
417 NWWriter_SUMO::writeEdge(OutputDevice& into, const NBEdge& e, bool noNames) {
418  // write the edge's begin
421  into.writeAttr(SUMO_ATTR_TO, e.getToNode()->getID());
422  if (!noNames && e.getStreetName() != "") {
424  }
426  if (e.getTypeID() != "") {
428  }
429  if (e.isMacroscopicConnector()) {
431  }
432  // write the spread type if not default ("right")
435  }
436  if (e.hasLoadedLength()) {
438  }
439  if (!e.hasDefaultGeometry()) {
441  }
442  if (e.getStopOffsets().size() != 0) {
443  writeStopOffsets(into, e.getStopOffsets());
444  }
445  if (e.isBidiRail()) {
447  }
448  if (e.getDistance() != 0) {
450  }
451 
452  // write the lanes
453  const std::vector<NBEdge::Lane>& lanes = e.getLanes();
454 
455  const double length = e.getFinalLength();
456  double startOffset = e.isBidiRail() ? e.getTurnDestination(true)->getEndOffset() : 0;
457  for (int i = 0; i < (int) lanes.size(); i++) {
458  const NBEdge::Lane& l = lanes[i];
459  std::map<int, double> stopOffsets;
460  if (l.stopOffsets != e.getStopOffsets()) {
461  stopOffsets = l.stopOffsets;
462  }
463  writeLane(into, e.getLaneID(i), l.speed,
464  l.permissions, l.preferred,
465  startOffset, l.endOffset,
466  stopOffsets, l.width, l.shape, &l,
467  length, i, l.oppositeID, l.type, l.accelRamp, l.customShape.size() > 0);
468  }
469  // close the edge
470  e.writeParams(into);
471  into.closeTag();
472 }
473 
474 
475 void
476 NWWriter_SUMO::writeLane(OutputDevice& into, const std::string& lID,
477  double speed, SVCPermissions permissions, SVCPermissions preferred,
478  double startOffset, double endOffset,
479  std::map<SVCPermissions, double> stopOffsets, double width, PositionVector shape,
480  const Parameterised* params, double length, int index,
481  const std::string& oppositeID,
482  const std::string& type,
483  bool accelRamp, bool customShape) {
484  // output the lane's attributes
486  // the first lane of an edge will be the depart lane
487  into.writeAttr(SUMO_ATTR_INDEX, index);
488  // write the list of allowed/disallowed vehicle classes
489  if (permissions != SVC_UNSPECIFIED) {
490  writePermissions(into, permissions);
491  }
492  writePreferences(into, preferred);
493  // some further information
494  if (speed == 0) {
495  WRITE_WARNINGF("Lane '%' has a maximum allowed speed of 0.", lID);
496  } else if (speed < 0) {
497  throw ProcessError("Negative allowed speed (" + toString(speed) + ") on lane '" + lID + "', use --speed.minimum to prevent this.");
498  }
499  into.writeAttr(SUMO_ATTR_SPEED, speed);
500  into.writeAttr(SUMO_ATTR_LENGTH, length);
501  if (endOffset != NBEdge::UNSPECIFIED_OFFSET) {
502  into.writeAttr(SUMO_ATTR_ENDOFFSET, endOffset);
503  }
504  if (width != NBEdge::UNSPECIFIED_WIDTH) {
505  into.writeAttr(SUMO_ATTR_WIDTH, width);
506  }
507  if (accelRamp) {
508  into.writeAttr<bool>(SUMO_ATTR_ACCELERATION, accelRamp);
509  }
510  if (customShape) {
511  into.writeAttr(SUMO_ATTR_CUSTOMSHAPE, true);
512  }
513  if (endOffset > 0 || startOffset > 0) {
514  if (startOffset + endOffset < shape.length()) {
515  shape = shape.getSubpart(startOffset, shape.length() - endOffset);
516  } else {
517  WRITE_ERROR("Invalid endOffset " + toString(endOffset) + " at lane '" + lID
518  + "' with length " + toString(shape.length()) + " (startOffset " + toString(startOffset) + ")");
519  if (!OptionsCont::getOptions().getBool("ignore-errors")) {
520  throw ProcessError();
521  }
522  }
523  }
524  into.writeAttr(SUMO_ATTR_SHAPE, shape);
525  if (type != "") {
526  into.writeAttr(SUMO_ATTR_TYPE, type);
527  }
528 
529  if (stopOffsets.size() != 0) {
530  writeStopOffsets(into, stopOffsets);
531  }
532 
533  if (oppositeID != "" && oppositeID != "-") {
534  into.openTag(SUMO_TAG_NEIGH);
535  into.writeAttr(SUMO_ATTR_LANE, oppositeID);
536  into.closeTag();
537  }
538 
539  if (params != nullptr) {
540  params->writeParams(into);
541  }
542 
543  into.closeTag();
544 }
545 
546 
547 void
549  // write the attributes
551  into.writeAttr(SUMO_ATTR_TYPE, n.getType());
553  // write the incoming lanes
554  std::vector<std::string> incLanes;
555  const std::vector<NBEdge*>& incoming = n.getIncomingEdges();
556  for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); ++i) {
557  int noLanes = (*i)->getNumLanes();
558  for (int j = 0; j < noLanes; j++) {
559  incLanes.push_back((*i)->getLaneID(j));
560  }
561  }
562  std::vector<NBNode::Crossing*> crossings = n.getCrossings();
563  std::set<std::string> prevWAs;
564  // avoid duplicates
565  for (auto c : crossings) {
566  if (prevWAs.count(c->prevWalkingArea) == 0) {
567  incLanes.push_back(c->prevWalkingArea + "_0");
568  prevWAs.insert(c->prevWalkingArea);
569  }
570  }
571  into.writeAttr(SUMO_ATTR_INCLANES, incLanes);
572  // write the internal lanes
573  std::vector<std::string> intLanes;
574  if (!OptionsCont::getOptions().getBool("no-internal-links")) {
575  for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
576  const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
577  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
578  if ((*k).toEdge == nullptr) {
579  continue;
580  }
581  if (!(*k).haveVia) {
582  intLanes.push_back((*k).getInternalLaneID());
583  } else {
584  intLanes.push_back((*k).viaID + "_0");
585  }
586  }
587  }
588  }
590  for (auto c : crossings) {
591  intLanes.push_back(c->id + "_0");
592  }
593  }
594  into.writeAttr(SUMO_ATTR_INTLANES, intLanes);
595  // close writing
597  // write optional radius
600  }
601  // specify whether a custom shape was used
602  if (n.hasCustomShape()) {
603  into.writeAttr(SUMO_ATTR_CUSTOMSHAPE, true);
604  }
605  if (n.getRightOfWay() != RightOfWay::DEFAULT) {
606  into.writeAttr<std::string>(SUMO_ATTR_RIGHT_OF_WAY, toString(n.getRightOfWay()));
607  }
608  if (n.getFringeType() != FringeType::DEFAULT) {
609  into.writeAttr<std::string>(SUMO_ATTR_FRINGE, toString(n.getFringeType()));
610  }
611  if (n.getName() != "") {
612  into.writeAttr<std::string>(SUMO_ATTR_NAME, n.getName());
613  }
614  if (n.getType() != SumoXMLNodeType::DEAD_END) {
615  // write right-of-way logics
616  n.writeLogic(into);
617  }
618  n.writeParams(into);
619  into.closeTag();
620 }
621 
622 
623 bool
625  bool ret = false;
626  const std::vector<NBEdge*>& incoming = n.getIncomingEdges();
627  // build the list of internal lane ids
628  std::vector<std::string> internalLaneIDs;
629  std::map<std::string, std::string> viaIDs;
630  for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
631  const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
632  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
633  if ((*k).toEdge != nullptr) {
634  internalLaneIDs.push_back((*k).getInternalLaneID());
635  viaIDs[(*k).getInternalLaneID()] = ((*k).viaID);
636  }
637  }
638  }
639  for (auto c : n.getCrossings()) {
640  internalLaneIDs.push_back(c->id + "_0");
641  }
642  // write the internal nodes
643  for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
644  const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
645  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
646  if ((*k).toEdge == nullptr || !(*k).haveVia) {
647  continue;
648  }
649  Position pos = (*k).shape[-1];
650  into.openTag(SUMO_TAG_JUNCTION).writeAttr(SUMO_ATTR_ID, (*k).viaID + "_0");
652  NWFrame::writePositionLong(pos, into);
653  std::string incLanes = (*k).getInternalLaneID();
654  std::vector<std::string> foeIDs;
655  for (std::string incLane : (*k).foeIncomingLanes) {
656  incLanes += " " + incLane;
657  if (incLane[0] == ':' && viaIDs[incLane] != "") {
658  // intersecting left turns
659  foeIDs.push_back(viaIDs[incLane] + "_0");
660  }
661  }
662  into.writeAttr(SUMO_ATTR_INCLANES, incLanes);
663  const std::vector<int>& foes = (*k).foeInternalLinks;
664  for (std::vector<int>::const_iterator it = foes.begin(); it != foes.end(); ++it) {
665  foeIDs.push_back(internalLaneIDs[*it]);
666  }
667  into.writeAttr(SUMO_ATTR_INTLANES, joinToString(foeIDs, " "));
668  into.closeTag();
669  ret = true;
670  }
671  }
672  return ret;
673 }
674 
675 
676 void
678  bool includeInternal, ConnectionStyle style, bool geoAccuracy) {
679  assert(c.toEdge != 0);
681  into.writeAttr(SUMO_ATTR_FROM, from.getID());
682  into.writeAttr(SUMO_ATTR_TO, c.toEdge->getID());
685  if (style != TLL) {
686  if (c.mayDefinitelyPass) {
688  }
689  if (c.keepClear == KEEPCLEAR_FALSE) {
690  into.writeAttr<bool>(SUMO_ATTR_KEEP_CLEAR, false);
691  }
694  }
695  if (c.permissions != SVC_UNSPECIFIED) {
696  writePermissions(into, c.permissions);
697  }
698  if (c.speed != NBEdge::UNSPECIFIED_SPEED) {
700  }
703  }
704  if (c.customShape.size() != 0) {
705  if (geoAccuracy) {
707  }
709  if (geoAccuracy) {
710  into.setPrecision();
711  }
712  }
713  if (c.uncontrolled != false) {
715  }
716  }
717  if (style != PLAIN) {
718  if (includeInternal) {
720  }
721  // set information about the controlling tl if any
722  if (c.tlID != "") {
723  into.writeAttr(SUMO_ATTR_TLID, c.tlID);
725  if (c.tlLinkIndex2 >= 0) {
727  }
728  }
729  }
730  if (style != TLL) {
731  if (style == SUMONET) {
732  // write the direction information
733  LinkDirection dir = from.getToNode()->getDirection(&from, c.toEdge, OptionsCont::getOptions().getBool("lefthand"));
734  assert(dir != LinkDirection::NODIR);
735  into.writeAttr(SUMO_ATTR_DIR, toString(dir));
736  // write the state information
737  const LinkState linkState = from.getToNode()->getLinkState(
738  &from, c.toEdge, c.fromLane, c.toLane, c.mayDefinitelyPass, c.tlID);
739  into.writeAttr(SUMO_ATTR_STATE, linkState);
740  if (linkState == LINKSTATE_MINOR
742  && c.toEdge->getJunctionPriority(c.toEdge->getToNode()) == NBEdge::JunctionPriority::ROUNDABOUT) {
743  const double visibilityDistance = OptionsCont::getOptions().getFloat("roundabouts.visibility-distance");
744  if (visibilityDistance != NBEdge::UNSPECIFIED_VISIBILITY_DISTANCE) {
745  into.writeAttr(SUMO_ATTR_VISIBILITY_DISTANCE, visibilityDistance);
746  }
747  }
748  }
751  }
752  }
753  c.writeParams(into);
754  into.closeTag();
755 }
756 
757 
758 bool
760  bool ret = false;
761  const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
762  const std::vector<NBEdge*>& incoming = n.getIncomingEdges();
763  for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); ++i) {
764  NBEdge* from = *i;
765  const std::vector<NBEdge::Connection>& connections = from->getConnections();
766  for (std::vector<NBEdge::Connection>::const_iterator j = connections.begin(); j != connections.end(); ++j) {
767  const NBEdge::Connection& c = *j;
768  LinkDirection dir = n.getDirection(from, c.toEdge, lefthand);
769  assert(c.toEdge != 0);
770  if (c.haveVia) {
771  // internal split with optional signal
772  std::string tlID = "";
773  int linkIndex2 = NBConnection::InvalidTlIndex;
775  linkIndex2 = c.tlLinkIndex2;
776  tlID = c.tlID;
777  }
778  writeInternalConnection(into, c.id, c.toEdge->getID(), c.internalLaneIndex, c.toLane, c.viaID + "_0", dir, tlID, linkIndex2);
779  writeInternalConnection(into, c.viaID, c.toEdge->getID(), 0, c.toLane, "", dir);
780  } else {
781  // no internal split
782  writeInternalConnection(into, c.id, c.toEdge->getID(), c.internalLaneIndex, c.toLane, "", dir);
783  }
784  ret = true;
785  }
786  }
787  return ret;
788 }
789 
790 
791 void
793  const std::string& from, const std::string& to,
794  int fromLane, int toLane, const std::string& via,
795  LinkDirection dir, const std::string& tlID, int linkIndex) {
797  into.writeAttr(SUMO_ATTR_FROM, from);
798  into.writeAttr(SUMO_ATTR_TO, to);
799  into.writeAttr(SUMO_ATTR_FROM_LANE, fromLane);
800  into.writeAttr(SUMO_ATTR_TO_LANE, toLane);
801  if (via != "") {
802  into.writeAttr(SUMO_ATTR_VIA, via);
803  }
804  if (tlID != "" && linkIndex != NBConnection::InvalidTlIndex) {
805  // used for the reverse direction of pedestrian crossings
806  into.writeAttr(SUMO_ATTR_TLID, tlID);
807  into.writeAttr(SUMO_ATTR_TLLINKINDEX, linkIndex);
808  }
809  into.writeAttr(SUMO_ATTR_DIR, dir);
810  into.writeAttr(SUMO_ATTR_STATE, (via != "" ? "m" : "M"));
811  into.closeTag();
812 }
813 
814 
815 void
816 NWWriter_SUMO::writeRoundabouts(OutputDevice& into, const std::set<EdgeSet>& roundabouts,
817  const NBEdgeCont& ec) {
818  // make output deterministic
819  std::vector<std::vector<std::string> > edgeIDs;
820  for (std::set<EdgeSet>::const_iterator i = roundabouts.begin(); i != roundabouts.end(); ++i) {
821  std::vector<std::string> tEdgeIDs;
822  for (EdgeSet::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
823  // the edges may have been erased from NBEdgeCont but their pointers are still valid
824  // we verify their existance in writeRoundabout()
825  tEdgeIDs.push_back((*j)->getID());
826  }
827  std::sort(tEdgeIDs.begin(), tEdgeIDs.end());
828  edgeIDs.push_back(tEdgeIDs);
829  }
830  std::sort(edgeIDs.begin(), edgeIDs.end());
831  // write
832  for (std::vector<std::vector<std::string> >::const_iterator i = edgeIDs.begin(); i != edgeIDs.end(); ++i) {
833  writeRoundabout(into, *i, ec);
834  }
835  if (roundabouts.size() != 0) {
836  into.lf();
837  }
838 }
839 
840 
841 void
842 NWWriter_SUMO::writeRoundabout(OutputDevice& into, const std::vector<std::string>& edgeIDs,
843  const NBEdgeCont& ec) {
844  std::vector<std::string> validEdgeIDs;
845  std::vector<std::string> invalidEdgeIDs;
846  std::vector<std::string> nodeIDs;
847  for (std::vector<std::string>::const_iterator i = edgeIDs.begin(); i != edgeIDs.end(); ++i) {
848  const NBEdge* edge = ec.retrieve(*i);
849  if (edge != nullptr) {
850  nodeIDs.push_back(edge->getToNode()->getID());
851  validEdgeIDs.push_back(edge->getID());
852  } else {
853  invalidEdgeIDs.push_back(*i);
854  }
855  }
856  std::sort(nodeIDs.begin(), nodeIDs.end());
857  if (validEdgeIDs.size() > 0) {
859  into.writeAttr(SUMO_ATTR_NODES, joinToString(nodeIDs, " "));
860  into.writeAttr(SUMO_ATTR_EDGES, joinToString(validEdgeIDs, " "));
861  into.closeTag();
862  if (invalidEdgeIDs.size() > 0) {
863  WRITE_WARNING("Writing incomplete roundabout. Edges: '"
864  + joinToString(invalidEdgeIDs, " ") + "' no longer exist'");
865  }
866  }
867 }
868 
869 
870 void
872  std::vector<double> sourceW = d.getSourceWeights();
874  std::vector<double> sinkW = d.getSinkWeights();
876  // write the head and the id of the district
878  if (d.getShape().size() > 0) {
880  }
881  // write all sources
882  const std::vector<NBEdge*>& sources = d.getSourceEdges();
883  for (int i = 0; i < (int)sources.size(); i++) {
884  // write the head and the id of the source
885  into.openTag(SUMO_TAG_TAZSOURCE).writeAttr(SUMO_ATTR_ID, sources[i]->getID()).writeAttr(SUMO_ATTR_WEIGHT, sourceW[i]);
886  into.closeTag();
887  }
888  // write all sinks
889  const std::vector<NBEdge*>& sinks = d.getSinkEdges();
890  for (int i = 0; i < (int)sinks.size(); i++) {
891  // write the head and the id of the sink
892  into.openTag(SUMO_TAG_TAZSINK).writeAttr(SUMO_ATTR_ID, sinks[i]->getID()).writeAttr(SUMO_ATTR_WEIGHT, sinkW[i]);
893  into.closeTag();
894  }
895  // write the tail
896  into.closeTag();
897 }
898 
899 
900 std::string
902  double time = STEPS2TIME(steps);
903  if (time == std::floor(time)) {
904  return toString(int(time));
905  } else {
906  return toString(time);
907  }
908 }
909 
910 
911 void
913  for (NBConnectionProhibits::const_iterator j = prohibitions.begin(); j != prohibitions.end(); j++) {
914  NBConnection prohibited = (*j).first;
915  const NBConnectionVector& prohibiting = (*j).second;
916  for (NBConnectionVector::const_iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
917  NBConnection prohibitor = *k;
921  into.closeTag();
922  }
923  }
924 }
925 
926 
927 std::string
929  return c.getFrom()->getID() + "->" + c.getTo()->getID();
930 }
931 
932 
933 void
935  std::vector<NBTrafficLightLogic*> logics = tllCont.getComputed();
936  for (NBTrafficLightLogic* logic : logics) {
937  writeTrafficLight(into, logic);
938  }
939  if (logics.size() > 0) {
940  into.lf();
941  }
942 }
943 
944 
945 void
948  into.writeAttr(SUMO_ATTR_ID, logic->getID());
949  into.writeAttr(SUMO_ATTR_TYPE, logic->getType());
952  // write the phases
953  const bool varPhaseLength = logic->getType() != TrafficLightType::STATIC;
954  for (const NBTrafficLightLogic::PhaseDefinition& phase : logic->getPhases()) {
955  into.openTag(SUMO_TAG_PHASE);
956  into.writeAttr(SUMO_ATTR_DURATION, writeSUMOTime(phase.duration));
957  if (phase.duration < TIME2STEPS(10)) {
958  into.writePadding(" ");
959  }
960  into.writeAttr(SUMO_ATTR_STATE, phase.state);
961  if (varPhaseLength) {
963  into.writeAttr(SUMO_ATTR_MINDURATION, writeSUMOTime(phase.minDur));
964  }
966  into.writeAttr(SUMO_ATTR_MAXDURATION, writeSUMOTime(phase.maxDur));
967  }
968  }
969  if (phase.name != "") {
970  into.writeAttr(SUMO_ATTR_NAME, phase.name);
971  }
972  if (phase.next.size() > 0) {
973  into.writeAttr(SUMO_ATTR_NEXT, phase.next);
974  }
975  into.closeTag();
976  }
977  // write params
978  logic->writeParams(into);
979  into.closeTag();
980 }
981 
982 
983 void
984 NWWriter_SUMO::writeStopOffsets(OutputDevice& into, const std::map<SVCPermissions, double>& stopOffsets) {
985  if (stopOffsets.size() == 0) {
986  return;
987  }
988  assert(stopOffsets.size() == 1);
989  std::pair<int, double> offset = *stopOffsets.begin();
990  std::string ss_vclasses = getVehicleClassNames(offset.first);
991  if (ss_vclasses.length() == 0) {
992  // This stopOffset would have no effect...
993  return;
994  }
996  std::string ss_exceptions = getVehicleClassNames(~offset.first);
997  if (ss_vclasses.length() <= ss_exceptions.length()) {
998  into.writeAttr(SUMO_ATTR_VCLASSES, ss_vclasses);
999  } else {
1000  if (ss_exceptions.length() == 0) {
1001  into.writeAttr(SUMO_ATTR_VCLASSES, "all");
1002  } else {
1003  into.writeAttr(SUMO_ATTR_EXCEPTIONS, ss_exceptions);
1004  }
1005  }
1006  into.writeAttr(SUMO_ATTR_VALUE, offset.second);
1007  into.closeTag();
1008 }
1009 
1010 
1011 /****************************************************************************/
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:277
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:284
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:276
std::map< NBConnection, NBConnectionVector > NBConnectionProhibits
Definition of a container for connection block dependencies Includes a list of all connections which ...
std::vector< NBConnection > NBConnectionVector
Definition of a connection vector.
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:34
@ KEEPCLEAR_FALSE
Definition: NBCont.h:58
#define STEPS2TIME(x)
Definition: SUMOTime.h:53
#define TIME2STEPS(x)
Definition: SUMOTime.h:55
long long int SUMOTime
Definition: SUMOTime.h:31
const SVCPermissions SVC_UNSPECIFIED
permissions not specified
const std::string & getVehicleClassNames(SVCPermissions permissions, bool expand)
Returns the ids of the given classes, divided using a ' '.
void writePermissions(OutputDevice &into, SVCPermissions permissions)
writes allowed disallowed attributes if needed;
void writePreferences(OutputDevice &into, SVCPermissions preferred)
writes allowed disallowed attributes if needed;
@ SVC_PEDESTRIAN
pedestrian
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
@ SUMO_TAG_PHASE
a single phase description
@ SUMO_TAG_STOPOFFSET
Information on vClass specific stop offsets at lane end.
@ SUMO_TAG_TAZ
a traffic assignment zone
@ SUMO_TAG_TAZSINK
a sink within a district (connection road)
@ SUMO_TAG_PROHIBITION
prohibition of circulation between two edges
@ SUMO_TAG_CONNECTION
connectio between two lanes
@ SUMO_TAG_ROUNDABOUT
roundabout defined in junction
@ SUMO_TAG_TLLOGIC
a traffic light logic
@ SUMO_TAG_JUNCTION
begin/end of the description of a junction
@ SUMO_TAG_LANE
begin/end of the description of a single lane
@ SUMO_TAG_TAZSOURCE
a source within a district (connection road)
@ SUMO_TAG_NEIGH
begin/end of the description of a neighboring lane
@ SUMO_TAG_EDGE
begin/end of the description of an edge
LinkDirection
The different directions a link between two lanes may take (or a stream between two edges)....
@ STRAIGHT
The link is a straight direction.
@ NODIR
The link has no direction (is a dead end link)
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic,...
@ LINKSTATE_MAJOR
This is an uncontrolled, major link, may pass.
@ LINKSTATE_MINOR
This is an uncontrolled, minor link, has to brake.
@ SUMO_ATTR_LANE
@ SUMO_ATTR_NODES
a list of node ids, used for controlling joining
@ SUMO_ATTR_TLLINKINDEX2
link: the index of the opposite direction link of a pedestrian crossing
@ SUMO_ATTR_SPEED
@ SUMO_ATTR_LINKDETAIL
@ SUMO_ATTR_VALUE
@ SUMO_ATTR_VIA
@ SUMO_ATTR_CORNERDETAIL
@ SUMO_ATTR_RADIUS
The turning radius at an intersection in m.
@ SUMO_ATTR_RECTANGULAR_LANE_CUT
@ SUMO_ATTR_FROM_LANE
@ SUMO_ATTR_LIMIT_TURN_SPEED
@ SUMO_ATTR_CHECKLANEFOES_ROUNDABOUT
@ SUMO_ATTR_OFFSET
@ SUMO_ATTR_AVOID_OVERLAP
@ SUMO_ATTR_CUSTOMSHAPE
whether a given shape is user-defined
@ SUMO_ATTR_INTLANES
@ SUMO_ATTR_EDGES
the edges of a route
@ SUMO_ATTR_FRINGE
Fringe type of node.
@ SUMO_ATTR_BIDI
@ SUMO_ATTR_PROHIBITED
@ SUMO_ATTR_PRIORITY
@ SUMO_ATTR_SHAPE
edge: the shape in xml-definition
@ SUMO_ATTR_LEFTHAND
@ SUMO_ATTR_WEIGHT
@ SUMO_ATTR_NEXT
succesor phase index
@ SUMO_ATTR_INCLANES
@ SUMO_ATTR_INDEX
@ SUMO_ATTR_VCLASSES
@ SUMO_ATTR_NAME
@ SUMO_ATTR_EXCEPTIONS
@ SUMO_ATTR_CHECKLANEFOES_ALL
@ SUMO_ATTR_SPREADTYPE
The information about how to spread the lanes from the given position.
@ SUMO_ATTR_PASS
@ SUMO_ATTR_ENDOFFSET
@ SUMO_ATTR_TO
@ SUMO_ATTR_FROM
@ SUMO_ATTR_ACCELERATION
@ SUMO_ATTR_TLID
link,node: the traffic light id responsible for this link
@ SUMO_ATTR_DISTANCE
@ SUMO_ATTR_TO_LANE
@ SUMO_ATTR_UNCONTROLLED
@ SUMO_ATTR_TYPE
@ SUMO_ATTR_LENGTH
@ SUMO_ATTR_VERSION
@ SUMO_ATTR_ID
@ SUMO_ATTR_MAXDURATION
maximum duration of a phase
@ SUMO_ATTR_RIGHT_OF_WAY
How to compute right of way.
@ SUMO_ATTR_PROGRAMID
@ SUMO_ATTR_FUNCTION
@ SUMO_ATTR_VISIBILITY_DISTANCE
foe visibility distance of a link
@ SUMO_ATTR_PROHIBITOR
@ SUMO_ATTR_DURATION
@ SUMO_ATTR_CONTPOS
@ SUMO_ATTR_WIDTH
@ SUMO_ATTR_CROSSING_EDGES
the edges crossed by a pedestrian crossing
@ SUMO_ATTR_DIR
The abstract direction of a link.
@ SUMO_ATTR_TLS_IGNORE_INTERNAL_JUNCTION_JAM
@ SUMO_ATTR_TLLINKINDEX
link: the index of the link within the traffic light
@ SUMO_ATTR_MINDURATION
@ SUMO_ATTR_KEEP_CLEAR
Whether vehicles must keep the junction clear.
@ SUMO_ATTR_STATE
The state of a link.
@ SUMO_ATTR_WALKINGAREAS
int gPrecisionGeo
Definition: StdDefs.cpp:26
const double NETWORK_VERSION
version for written networks and default version for loading
Definition: StdDefs.h:65
T MAX2(T a, T b)
Definition: StdDefs.h:79
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
Definition: ToString.h:250
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:44
static void writeLocation(OutputDevice &into)
writes the location element
NBEdge * getFrom() const
returns the from-edge (start of the connection)
static const int InvalidTlIndex
Definition: NBConnection.h:123
NBEdge * getTo() const
returns the to-edge (end of the connection)
A container for districts.
std::map< std::string, NBDistrict * >::const_iterator begin() const
Returns the pointer to the begin of the stored districts.
std::map< std::string, NBDistrict * >::const_iterator end() const
Returns the pointer to the end of the stored districts.
int size() const
Returns the number of districts inside the container.
A class representing a single district.
Definition: NBDistrict.h:62
const std::vector< double > & getSourceWeights() const
Returns the weights of the sources.
Definition: NBDistrict.h:180
const std::vector< double > & getSinkWeights() const
Returns the weights of the sinks.
Definition: NBDistrict.h:196
const PositionVector & getShape() const
Returns the shape.
Definition: NBDistrict.h:212
const std::vector< NBEdge * > & getSourceEdges() const
Returns the sources.
Definition: NBDistrict.h:188
const std::vector< NBEdge * > & getSinkEdges() const
Returns the sinks.
Definition: NBDistrict.h:204
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:59
std::map< std::string, NBEdge * >::const_iterator begin() const
Returns the pointer to the begin of the stored edges.
Definition: NBEdgeCont.h:183
const std::set< EdgeSet > getRoundabouts() const
Returns the determined roundabouts.
std::map< std::string, NBEdge * >::const_iterator end() const
Returns the pointer to the end of the stored edges.
Definition: NBEdgeCont.h:191
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
Definition: NBEdgeCont.cpp:275
The representation of a single edge during network building.
Definition: NBEdge.h:91
double getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn't set.
Definition: NBEdge.h:572
const std::string & getStreetName() const
Returns the street name of this edge.
Definition: NBEdge.h:618
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge's lanes' lateral offset is computed.
Definition: NBEdge.h:803
bool isBidiRail(bool ignoreSpread=false) const
whether this edge is part of a bidirectional railway
Definition: NBEdge.cpp:713
bool hasLoadedLength() const
Returns whether a length was set explicitly.
Definition: NBEdge.h:582
const std::string & getID() const
Definition: NBEdge.h:1423
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
Definition: NBEdge.h:677
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:516
double getDistance() const
Definition: NBEdge.h:634
static const double UNSPECIFIED_LOADED_LENGTH
no length override given
Definition: NBEdge.h:339
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:716
static const double UNSPECIFIED_CONTPOS
unspecified internal junction position
Definition: NBEdge.h:333
static const double UNSPECIFIED_VISIBILITY_DISTANCE
unspecified foe visibility for connections
Definition: NBEdge.h:336
const std::map< int, double > & getStopOffsets() const
Returns the stopOffset to the end of the edge.
Definition: NBEdge.h:641
std::string getLaneID(int lane) const
get lane ID
Definition: NBEdge.cpp:3345
static const double UNSPECIFIED_SPEED
unspecified lane speed
Definition: NBEdge.h:330
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
Definition: NBEdge.cpp:1920
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition: NBEdge.cpp:3336
bool hasDefaultGeometry() const
Returns whether the geometry consists only of the node positions.
Definition: NBEdge.cpp:575
int getPriority() const
Returns the priority of the edge.
Definition: NBEdge.h:497
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:324
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:964
const std::string & getTypeID() const
get ID of type
Definition: NBEdge.h:1104
double getEndOffset() const
Returns the offset to the destination node.
Definition: NBEdge.h:630
static const double UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:327
bool isMacroscopicConnector() const
Returns whether this edge was marked as a macroscopic connector.
Definition: NBEdge.h:1059
Connection getConnection(int fromLane, const NBEdge *to, int toLane) const
Returns the specified connection This method goes through "myConnections" and returns the specified o...
Definition: NBEdge.cpp:1166
double getFinalLength() const
get length that will be assigned to the lanes in the final network
Definition: NBEdge.cpp:3954
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:509
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:119
Instance responsible for building networks.
Definition: NBNetBuilder.h:107
NBDistrictCont & getDistrictCont()
Returns a reference the districts container.
Definition: NBNetBuilder.h:168
NBTypeCont & getTypeCont()
Returns a reference to the type container.
Definition: NBNetBuilder.h:158
NBEdgeCont & getEdgeCont()
Definition: NBNetBuilder.h:148
NBNodeCont & getNodeCont()
Returns a reference to the node container.
Definition: NBNetBuilder.h:153
NBTrafficLightLogicCont & getTLLogicCont()
Returns a reference to the traffic light logics container.
Definition: NBNetBuilder.h:163
A definition of a pedestrian crossing.
Definition: NBNode.h:129
int tlLinkIndex
the traffic light index of this crossing (if controlled)
Definition: NBNode.h:154
std::string tlID
The id of the traffic light that controls this connection.
Definition: NBNode.h:160
bool priority
whether the pedestrians have priority
Definition: NBNode.h:150
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:58
std::map< std::string, NBNode * >::const_iterator begin() const
Returns the pointer to the begin of the stored nodes.
Definition: NBNodeCont.h:113
std::map< std::string, NBNode * >::const_iterator end() const
Returns the pointer to the end of the stored nodes.
Definition: NBNodeCont.h:118
Represents a single node (junction) during network building.
Definition: NBNode.h:66
LinkState getLinkState(const NBEdge *incoming, NBEdge *outgoing, int fromLane, int toLane, bool mayDefinitelyPass, const std::string &tlID) const
get link state
Definition: NBNode.cpp:2156
LinkDirection getDirection(const NBEdge *const incoming, const NBEdge *const outgoing, bool leftHand=false) const
Returns the representation of the described stream's direction.
Definition: NBNode.cpp:2078
RightOfWay getRightOfWay() const
Returns hint on how to compute right of way.
Definition: NBNode.h:286
static const double UNSPECIFIED_RADIUS
unspecified lane width
Definition: NBNode.h:207
Crossing * getCrossing(const std::string &id) const
return the crossing with the given id
Definition: NBNode.cpp:3270
FringeType getFringeType() const
Returns fringe type.
Definition: NBNode.h:291
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:271
const std::string & getName() const
Returns intersection name.
Definition: NBNode.h:296
bool hasCustomShape() const
return whether the shape was set by the user
Definition: NBNode.h:553
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
Definition: NBNode.h:254
std::vector< Crossing * > getCrossings() const
return this junctions pedestrian crossings
Definition: NBNode.cpp:2585
bool writeLogic(OutputDevice &into) const
writes the XML-representation of the logic as a bitset-logic XML representation
Definition: NBNode.cpp:993
bool isConstantWidthTransition() const
detects whether a given junction splits or merges lanes while keeping constant road width
Definition: NBNode.cpp:787
const PositionVector & getShape() const
retrieve the junction shape
Definition: NBNode.cpp:2285
const Position & getPosition() const
Definition: NBNode.h:246
double getRadius() const
Returns the turning radius of this node.
Definition: NBNode.h:276
const std::vector< WalkingArea > & getWalkingAreas() const
return this junctions pedestrian walking areas
Definition: NBNode.h:707
static const SUMOTime UNSPECIFIED_DURATION
The definition of a single phase of the logic.
A container for traffic light definitions and built programs.
std::vector< NBTrafficLightLogic * > getComputed() const
Returns a list of all computed logics.
A SUMO-compliant built logic for a traffic light.
SUMOTime getOffset() const
Returns the offset of first switch.
const std::vector< PhaseDefinition > & getPhases() const
Returns the phases.
const std::string & getProgramID() const
Returns the ProgramID.
TrafficLightType getType() const
get the algorithm type (static etc..)
void writeEdgeTypes(OutputDevice &into) const
writes all EdgeTypes (and their lanes) as XML
Definition: NBTypeCont.cpp:344
static void writePositionLong(const Position &pos, OutputDevice &dev)
Writes the given position to device in long format (one attribute per dimension)
Definition: NWFrame.cpp:187
static void writeLane(OutputDevice &into, const std::string &lID, double speed, SVCPermissions permissions, SVCPermissions preferred, double startOffset, double endOffset, std::map< SVCPermissions, double > stopOffsets, double width, PositionVector shape, const Parameterised *params, double length, int index, const std::string &oppositeID, const std::string &type, bool accelRamp=false, bool customShape=false)
Writes a lane (<lane ...) of an edge.
static void writeConnection(OutputDevice &into, const NBEdge &from, const NBEdge::Connection &c, bool includeInternal, ConnectionStyle style=SUMONET, bool geoAccuracy=false)
Writes connections outgoing from the given edge (also used in NWWriter_XML)
static void writeStopOffsets(OutputDevice &into, const std::map< SVCPermissions, double > &stopOffsets)
Write a stopOffset element into output device.
static void writeNetwork(const OptionsCont &oc, NBNetBuilder &nb)
Writes the network into a SUMO-file.
static bool writeInternalNodes(OutputDevice &into, const NBNode &n)
Writes internal junctions (<junction with id[0]==':' ...) of the given node.
static void writeProhibitions(OutputDevice &into, const NBConnectionProhibits &prohibitions)
writes the given prohibitions
static void writeEdge(OutputDevice &into, const NBEdge &e, bool noNames)
Writes an edge (<edge ...)
static std::string getOppositeInternalID(const NBEdgeCont &ec, const NBEdge *from, const NBEdge::Connection &con, double &oppositeLength)
retrieve the id of the opposite direction internal lane if it exists
static std::string writeSUMOTime(SUMOTime time)
writes a SUMOTime as int if possible, otherwise as a float
static void writeJunction(OutputDevice &into, const NBNode &n)
Writes a junction (<junction ...)
static void writeInternalConnection(OutputDevice &into, const std::string &from, const std::string &to, int fromLane, int toLane, const std::string &via, LinkDirection dir=LinkDirection::STRAIGHT, const std::string &tlID="", int linkIndex=NBConnection::InvalidTlIndex)
Writes a single internal connection.
static bool writeInternalEdges(OutputDevice &into, const NBEdgeCont &ec, const NBNode &n)
Writes internal edges (<edge ... with id[0]==':') of the given node.
static bool writeInternalConnections(OutputDevice &into, const NBNode &n)
Writes inner connections within the node.
static void writeDistrict(OutputDevice &into, const NBDistrict &d)
Writes a district.
static void writeRoundabouts(OutputDevice &into, const std::set< EdgeSet > &roundabouts, const NBEdgeCont &ec)
Writes roundabouts.
static void writeRoundabout(OutputDevice &into, const std::vector< std::string > &r, const NBEdgeCont &ec)
Writes a roundabout.
static void writeTrafficLight(OutputDevice &into, const NBTrafficLightLogic *logic)
writes a single traffic light logic to the given device
static std::string prohibitionConnection(const NBConnection &c)
the attribute value for a prohibition
static void writeTrafficLights(OutputDevice &into, const NBTrafficLightLogicCont &tllCont)
writes the traffic light logics to the given device
const std::string & getID() const
Returns the id.
Definition: Named.h:73
A storage for options typed value containers)
Definition: OptionsCont.h:89
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
bool set(const std::string &name, const std::string &value)
Sets the given value for the named option.
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
bool isDefault(const std::string &name) const
Returns the information whether the named option has still the default value.
bool exists(const std::string &name) const
Returns the information whether the named option is known.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
void resetWritable()
Resets all options to be writeable.
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:60
void lf()
writes a line feed if applicable
Definition: OutputDevice.h:227
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.
void close()
Closes the device and removes it from the dictionary.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:239
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
void setPrecision(int precision=gPrecision)
Sets the precison or resets it to default.
OutputDevice & writePadding(const std::string &val)
writes padding (ignored for binary output)
Definition: OutputDevice.h:283
static OutputDevice & getDevice(const std::string &name)
Returns the described OutputDevice.
An upper class for objects with additional parameters.
Definition: Parameterised.h:39
void writeParams(OutputDevice &device) const
write Params in the given outputdevice
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:36
A list of positions.
double length() const
Returns the length.
PositionVector simplified() const
return the same shape with intermediate colinear points removed
PositionVector getSubpart(double beginOffset, double endOffset) const
get subpart of a position vector
static std::string escapeXML(const std::string &orig, const bool maskDoubleHyphen=false)
Replaces the standard escapes by their XML entities.
static void normaliseSum(std::vector< T > &v, T msum=1.0)
Definition: VectorHelper.h:46
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:188
int fromLane
The lane the connections starts at.
Definition: NBEdge.h:209
std::string viaID
if Connection have a via, ID of it
Definition: NBEdge.h:263
int toLane
The lane the connections yields in.
Definition: NBEdge.h:215
SVCPermissions permissions
List of vehicle types that are allowed on this connection.
Definition: NBEdge.h:248
double speed
custom speed for connection
Definition: NBEdge.h:239
NBEdge * toEdge
The edge the connections yields in.
Definition: NBEdge.h:212
KeepClear keepClear
whether the junction must be kept clear when using this connection
Definition: NBEdge.h:230
double customLength
custom length for connection
Definition: NBEdge.h:242
bool uncontrolled
check if Connection is uncontrolled
Definition: NBEdge.h:281
PositionVector customShape
custom shape for connection
Definition: NBEdge.h:245
bool mayDefinitelyPass
Information about being definitely free to drive (on-ramps)
Definition: NBEdge.h:227
std::string getDescription(const NBEdge *parent) const
get string describing this connection
Definition: NBEdge.cpp:92
double contPos
custom position for internal junction on this connection
Definition: NBEdge.h:233
std::string getInternalLaneID() const
get ID of internal lane
Definition: NBEdge.cpp:86
int internalLaneIndex
The lane index of this internal lane within the internal edge.
Definition: NBEdge.h:278
std::string tlID
The id of the traffic light that controls this connection.
Definition: NBEdge.h:218
double visibility
custom foe visiblity for connection
Definition: NBEdge.h:236
int tlLinkIndex2
The index of the internal junction within the controlling traffic light (optional)
Definition: NBEdge.h:224
double length
computed length (average of all internal lane shape lengths that share an internal edge)
Definition: NBEdge.h:290
std::string id
id of Connection
Definition: NBEdge.h:251
bool haveVia
check if Connection have a Via
Definition: NBEdge.h:260
int tlLinkIndex
The index of this connection within the controlling traffic light.
Definition: NBEdge.h:221
An (internal) definition of a single lane of an edge.
Definition: NBEdge.h:142
double width
This lane's width.
Definition: NBEdge.h:166
std::map< int, double > stopOffsets
stopOffsets.second - The stop offset for vehicles stopping at the lane's end. Applies if vClass is in...
Definition: NBEdge.h:163
PositionVector customShape
A custom shape for this lane set by the user.
Definition: NBEdge.h:179
double endOffset
This lane's offset to the intersection begin.
Definition: NBEdge.h:159
std::string type
the type of this lane
Definition: NBEdge.h:182
SVCPermissions preferred
List of vehicle types that are preferred on this lane.
Definition: NBEdge.h:156
double speed
The speed allowed on this lane.
Definition: NBEdge.h:150
std::string oppositeID
An opposite lane ID, if given.
Definition: NBEdge.h:169
SVCPermissions permissions
List of vehicle types that are allowed on this lane.
Definition: NBEdge.h:153
bool accelRamp
Whether this lane is an acceleration lane.
Definition: NBEdge.h:172
PositionVector shape
The lane's shape.
Definition: NBEdge.h:147
A definition of a pedestrian walking area.
Definition: NBNode.h:169
std::string id
the (edge)-id of this walkingArea
Definition: NBNode.h:176
bool hasCustomShape
whether this walkingArea has a custom shape
Definition: NBNode.h:190
double width
This lane's width.
Definition: NBNode.h:178
PositionVector shape
The polygonal shape.
Definition: NBNode.h:182
double length
This lane's width.
Definition: NBNode.h:180