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.dev/sumo
3 // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
21 // 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") == "roadCenter") {
96  // it makes no sense to store the default=center in the net since
97  // centered edges would have the attribute written anyway and edges that
98  // should have 'right' would be misinterpreted
99  attrs[SUMO_ATTR_SPREADTYPE] = oc.getString("default.spreadtype");
100  }
101  if (oc.exists("geometry.avoid-overlap") && !oc.getBool("geometry.avoid-overlap")) {
102  attrs[SUMO_ATTR_AVOID_OVERLAP] = toString(oc.getBool("geometry.avoid-overlap"));
103  }
104  if (oc.exists("junctions.higher-speed") && oc.getBool("junctions.higher-speed")) {
105  attrs[SUMO_ATTR_HIGHER_SPEED] = toString(oc.getBool("junctions.higher-speed"));
106  }
107  if (oc.exists("internal-junctions.vehicle-width") && !oc.isDefault("internal-junctions.vehicle-width")) {
108  attrs[SUMO_ATTR_INTERNAL_JUNCTIONS_VEHICLE_WIDTH] = toString(oc.getFloat("internal-junctions.vehicle-width"));
109  }
110  if (!oc.isDefault("junctions.minimal-shape")) {
111  attrs[SUMO_ATTR_JUNCTIONS_MINIMAL_SHAPE] = toString(oc.getBool("junctions.minimal-shape"));
112  }
113  if (!oc.isDefault("junctions.endpoint-shape")) {
114  attrs[SUMO_ATTR_JUNCTIONS_ENDPOINT_SHAPE] = toString(oc.getBool("junctions.endpoint-shape"));
115  }
116  device.writeXMLHeader("net", "net_file.xsd", attrs); // street names may contain non-ascii chars
117  device.lf();
118  // get involved container
119  const NBNodeCont& nc = nb.getNodeCont();
120  const NBEdgeCont& ec = nb.getEdgeCont();
121  const NBDistrictCont& dc = nb.getDistrictCont();
122 
123  // write network offsets and projection
125 
126  // write edge types and restrictions
127  std::set<std::string> usedTypes = ec.getUsedTypes();
128  nb.getTypeCont().writeEdgeTypes(device, usedTypes);
129 
130  // write inner lanes
131  if (!oc.getBool("no-internal-links")) {
132  bool hadAny = false;
133  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
134  hadAny |= writeInternalEdges(device, ec, *(*i).second);
135  }
136  if (hadAny) {
137  device.lf();
138  }
139  }
140 
141  // write edges with lanes and connected edges
142  bool noNames = !oc.getBool("output.street-names");
143  for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
144  writeEdge(device, *(*i).second, noNames);
145  }
146  device.lf();
147 
148  // write tls logics
149  writeTrafficLights(device, nb.getTLLogicCont());
150 
151  // write the nodes (junctions)
152  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
153  writeJunction(device, *(*i).second);
154  }
155  device.lf();
156  const bool includeInternal = !oc.getBool("no-internal-links");
157  if (includeInternal) {
158  // ... internal nodes if not unwanted
159  bool hadAny = false;
160  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
161  hadAny |= writeInternalNodes(device, *(*i).second);
162  }
163  if (hadAny) {
164  device.lf();
165  }
166  }
167 
168  // write the successors of lanes
169  int numConnections = 0;
170  for (std::map<std::string, NBEdge*>::const_iterator it_edge = ec.begin(); it_edge != ec.end(); it_edge++) {
171  NBEdge* from = it_edge->second;
172  const std::vector<NBEdge::Connection>& connections = from->getConnections();
173  numConnections += (int)connections.size();
174  for (const NBEdge::Connection& con : connections) {
175  writeConnection(device, *from, con, includeInternal);
176  }
177  }
178  if (numConnections > 0) {
179  device.lf();
180  }
181  if (includeInternal) {
182  // ... internal successors if not unwanted
183  bool hadAny = false;
184  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
185  hadAny |= writeInternalConnections(device, *(*i).second);
186  }
187  if (hadAny) {
188  device.lf();
189  }
190  }
191  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
192  NBNode* node = (*i).second;
193  // write connections from pedestrian crossings
194  std::vector<NBNode::Crossing*> crossings = node->getCrossings();
195  for (auto c : crossings) {
196  NWWriter_SUMO::writeInternalConnection(device, c->id, c->nextWalkingArea, 0, 0, "", LinkDirection::STRAIGHT, c->tlID, c->tlLinkIndex2);
197  }
198  // write connections from pedestrian walking areas
199  for (const NBNode::WalkingArea& wa : node->getWalkingAreas()) {
200  for (const std::string& cID : wa.nextCrossings) {
201  const NBNode::Crossing& nextCrossing = *node->getCrossing(cID);
202  // connection to next crossing (may be tls-controlled)
204  device.writeAttr(SUMO_ATTR_FROM, wa.id);
205  device.writeAttr(SUMO_ATTR_TO, cID);
206  device.writeAttr(SUMO_ATTR_FROM_LANE, 0);
207  device.writeAttr(SUMO_ATTR_TO_LANE, 0);
208  if (nextCrossing.tlID != "") {
209  device.writeAttr(SUMO_ATTR_TLID, nextCrossing.tlID);
210  assert(nextCrossing.tlLinkIndex >= 0);
211  device.writeAttr(SUMO_ATTR_TLLINKINDEX, nextCrossing.tlLinkIndex);
212  }
215  device.closeTag();
216  }
217  // optional connections from/to sidewalk
218  std::string edgeID;
219  int laneIndex;
220  for (const std::string& sw : wa.nextSidewalks) {
221  NBHelpers::interpretLaneID(sw, edgeID, laneIndex);
222  NWWriter_SUMO::writeInternalConnection(device, wa.id, edgeID, 0, laneIndex, "");
223  }
224  for (const std::string& sw : wa.prevSidewalks) {
225  NBHelpers::interpretLaneID(sw, edgeID, laneIndex);
226  NWWriter_SUMO::writeInternalConnection(device, edgeID, wa.id, laneIndex, 0, "");
227  }
228  }
229  }
230 
231  // write loaded prohibitions
232  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
233  writeProhibitions(device, i->second->getProhibitions());
234  }
235 
236  // write roundabout information
237  writeRoundabouts(device, ec.getRoundabouts(), ec);
238 
239  // write the districts
240  if (dc.size() != 0 && oc.isDefault("taz-output")) {
241  WRITE_WARNING(TL("Embedding TAZ-data inside the network is deprecated. Use option --taz-output instead"));
242  for (std::map<std::string, NBDistrict*>::const_iterator i = dc.begin(); i != dc.end(); i++) {
243  writeDistrict(device, *(*i).second);
244  }
245  device.lf();
246  }
247  device.close();
248 }
249 
250 
251 std::string
252 NWWriter_SUMO::getOppositeInternalID(const NBEdgeCont& ec, const NBEdge* from, const NBEdge::Connection& con, double& oppositeLength) {
253  const NBEdge::Lane& succ = con.toEdge->getLanes()[con.toLane];
254  const NBEdge::Lane& pred = from->getLanes()[con.fromLane];
255  const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
256  if (succ.oppositeID != "" && succ.oppositeID != "-" && pred.oppositeID != "" && pred.oppositeID != "-") {
257 #ifdef DEBUG_OPPOSITE_INTERNAL
258  std::cout << "getOppositeInternalID con=" << con.getDescription(from) << " (" << con.getInternalLaneID() << ")\n";
259 #endif
260  // find the connection that connects succ.oppositeID to pred.oppositeID
261  const NBEdge* succOpp = ec.retrieve(succ.oppositeID.substr(0, succ.oppositeID.rfind("_")));
262  const NBEdge* predOpp = ec.retrieve(pred.oppositeID.substr(0, pred.oppositeID.rfind("_")));
263  assert(succOpp != 0);
264  assert(predOpp != 0);
265  const std::vector<NBEdge::Connection>& connections = succOpp->getConnections();
266  for (std::vector<NBEdge::Connection>::const_iterator it_c = connections.begin(); it_c != connections.end(); it_c++) {
267  const NBEdge::Connection& conOpp = *it_c;
268  if (succOpp != from // turnaround
269  && predOpp == conOpp.toEdge
270  && succOpp->getLaneID(conOpp.fromLane) == succ.oppositeID
271  && predOpp->getLaneID(conOpp.toLane) == pred.oppositeID
272  && from->getToNode()->getDirection(from, con.toEdge, lefthand) == LinkDirection::STRAIGHT
273  && from->getToNode()->getDirection(succOpp, predOpp, lefthand) == LinkDirection::STRAIGHT
274  ) {
275 #ifdef DEBUG_OPPOSITE_INTERNAL
276  std::cout << " found " << conOpp.getInternalLaneID() << "\n";
277 #endif
278  oppositeLength = conOpp.length;
279  return conOpp.getInternalLaneID();
280  } else {
281  /*
282  #ifdef DEBUG_OPPOSITE_INTERNAL
283  std::cout << " rejected " << conOpp.getInternalLaneID()
284  << "\n succ.oppositeID=" << succ.oppositeID
285  << "\n succOppLane=" << succOpp->getLaneID(conOpp.fromLane)
286  << "\n pred.oppositeID=" << pred.oppositeID
287  << "\n predOppLane=" << predOpp->getLaneID(conOpp.toLane)
288  << "\n predOpp=" << predOpp->getID()
289  << "\n conOppTo=" << conOpp.toEdge->getID()
290  << "\n len1=" << con.shape.length()
291  << "\n len2=" << conOpp.shape.length()
292  << "\n";
293  #endif
294  */
295  }
296  }
297  return "";
298  } else {
299  return "";
300  }
301 }
302 
303 
304 bool
306  bool ret = false;
307  const EdgeVector& incoming = n.getIncomingEdges();
308  // first pass: determine opposite internal edges and average their length
309  std::map<std::string, std::string> oppositeLaneID;
310  std::map<std::string, double> oppositeLengths;
311  for (NBEdge* e : incoming) {
312  for (const NBEdge::Connection& c : e->getConnections()) {
313  double oppositeLength = 0;
314  const std::string op = getOppositeInternalID(ec, e, c, oppositeLength);
315  oppositeLaneID[c.getInternalLaneID()] = op;
316  if (op != "") {
317  oppositeLengths[c.id] = oppositeLength;
318  }
319  }
320  }
321  if (oppositeLengths.size() > 0) {
322  for (NBEdge* e : incoming) {
323  for (NBEdge::Connection& c : e->getConnections()) {
324  if (oppositeLengths.count(c.id) > 0) {
325  c.length = (c.length + oppositeLengths[c.id]) / 2;
326  }
327  }
328  }
329  }
330 
331  for (NBEdge* e : incoming) {
332  const std::vector<NBEdge::Connection>& elv = e->getConnections();
333  if (elv.size() > 0) {
334  bool haveVia = false;
335  std::string edgeID = "";
336  double bidiLength = -1;
337  // second pass: write non-via edges
338  for (const NBEdge::Connection& k : elv) {
339  if (k.toEdge == nullptr) {
340  assert(false); // should never happen. tell me when it does
341  continue;
342  }
343  if (edgeID != k.id) {
344  if (edgeID != "") {
345  // close the previous edge
346  into.closeTag();
347  }
348  edgeID = k.id;
349  into.openTag(SUMO_TAG_EDGE);
350  into.writeAttr(SUMO_ATTR_ID, edgeID);
352  if (k.edgeType != "") {
353  into.writeAttr(SUMO_ATTR_TYPE, k.edgeType);
354  }
355  bidiLength = -1;
356  if (e->getBidiEdge() && k.toEdge->getBidiEdge() &&
357  e != k.toEdge->getTurnDestination(true)) {
358  const std::string bidiEdge = getInternalBidi(e, k, bidiLength);
359  if (bidiEdge != "") {
360  into.writeAttr(SUMO_ATTR_BIDI, bidiEdge);
361  }
362  }
363  // open a new edge
364  }
365  // to avoid changing to an internal lane which has a successor
366  // with the wrong permissions we need to inherit them from the successor
367  const NBEdge::Lane& successor = k.toEdge->getLanes()[k.toLane];
368  SVCPermissions permissions = (k.permissions != SVC_UNSPECIFIED) ? k.permissions : (
369  successor.permissions & e->getPermissions(k.fromLane));
370  SVCPermissions changeLeft = k.changeLeft != SVC_UNSPECIFIED ? k.changeLeft : SVCAll;
371  SVCPermissions changeRight = k.changeRight != SVC_UNSPECIFIED ? k.changeRight : SVCAll;
372  const double width = e->getInternalLaneWidth(n, k, successor, false);
373  const double length = bidiLength > 0 ? bidiLength : k.length;
374  writeLane(into, k.getInternalLaneID(), k.vmax, k.friction,
375  permissions, successor.preferred,
376  changeLeft, changeRight,
378  StopOffset(), width, k.shape, &k,
379  length, k.internalLaneIndex, oppositeLaneID[k.getInternalLaneID()], "");
380  haveVia = haveVia || k.haveVia;
381  }
382  ret = true;
383  into.closeTag(); // close the last edge
384  // third pass: write via edges
385  if (haveVia) {
386  for (const NBEdge::Connection& k : elv) {
387  if (!k.haveVia) {
388  continue;
389  }
390  if (k.toEdge == nullptr) {
391  assert(false); // should never happen. tell me when it does
392  continue;
393  }
394  const NBEdge::Lane& successor = k.toEdge->getLanes()[k.toLane];
395  into.openTag(SUMO_TAG_EDGE);
396  into.writeAttr(SUMO_ATTR_ID, k.viaID);
398  if (k.edgeType != "") {
399  into.writeAttr(SUMO_ATTR_TYPE, k.edgeType);
400  }
401  SVCPermissions permissions = (k.permissions != SVC_UNSPECIFIED) ? k.permissions : (
402  successor.permissions & e->getPermissions(k.fromLane));
403  const double width = e->getInternalLaneWidth(n, k, successor, true);
404  writeLane(into, k.viaID + "_0", k.vmax, k.friction, permissions, successor.preferred,
405  SVCAll, SVCAll, // #XXX todo
407  StopOffset(), width, k.viaShape, &k,
408  MAX2(k.viaLength, POSITION_EPS), // microsim needs positive length
409  0, "", "");
410  into.closeTag();
411  }
412  }
413  }
414  }
415  // write pedestrian crossings
416  const double crossingSpeed = OptionsCont::getOptions().getFloat("default.crossing-speed");
417  for (auto c : n.getCrossings()) {
418  into.openTag(SUMO_TAG_EDGE);
419  into.writeAttr(SUMO_ATTR_ID, c->id);
421  into.writeAttr(SUMO_ATTR_CROSSING_EDGES, c->edges);
422  writeLane(into, c->id + "_0", crossingSpeed, NBEdge::UNSPECIFIED_FRICTION, SVC_PEDESTRIAN, 0, SVCAll, SVCAll,
424  StopOffset(), c->width, c->shape, c,
425  MAX2(c->shape.length(), POSITION_EPS), 0, "", "", false, c->customShape.size() != 0, c->outlineShape);
426  into.closeTag();
427  }
428  // write pedestrian walking areas
429  const double walkingareaSpeed = OptionsCont::getOptions().getFloat("default.walkingarea-speed");
430  const std::vector<NBNode::WalkingArea>& WalkingAreas = n.getWalkingAreas();
431  for (std::vector<NBNode::WalkingArea>::const_iterator it = WalkingAreas.begin(); it != WalkingAreas.end(); it++) {
432  const NBNode::WalkingArea& wa = *it;
433  into.openTag(SUMO_TAG_EDGE);
434  into.writeAttr(SUMO_ATTR_ID, wa.id);
436  writeLane(into, wa.id + "_0", walkingareaSpeed, NBEdge::UNSPECIFIED_FRICTION, SVC_PEDESTRIAN, 0, SVCAll, SVCAll,
438  StopOffset(), wa.width, wa.shape, nullptr, wa.length, 0, "", "", false, wa.hasCustomShape);
439  into.closeTag();
440  }
441  return ret;
442 }
443 
444 
445 std::string
446 NWWriter_SUMO::getInternalBidi(const NBEdge* e, const NBEdge::Connection& k, double& length) {
447  const NBEdge* fromBidi = e->getTurnDestination(true);
448  const NBEdge* toBidi = k.toEdge->getTurnDestination(true);
449  const std::vector<NBEdge::Connection> cons = toBidi->getConnectionsFromLane(-1, fromBidi, -1);
450  if (cons.size() > 0) {
451  if (e->getNumLanes() == 1 && k.toEdge->getNumLanes() == 1 && fromBidi->getNumLanes() == 1 && toBidi->getNumLanes() == 1) {
452  length = (k.length + cons.back().length) / 2;
453  return cons.back().id;
454  }
455  // do a more careful check in case there are parallel internal edges
456  // note: k is the first connection with the new id
457  for (const NBEdge::Connection& c : e->getConnections()) {
458  if (c.id == k.id) {
459  PositionVector rShape = c.shape.reverse();
460  for (const NBEdge::Connection& k2 : cons) {
461  if (k2.shape.almostSame(rShape, POSITION_EPS)) {
462  length = (c.length + k2.length) / 2;
463  return k2.id;
464  }
465  }
466  }
467  }
468  } else {
469  WRITE_WARNINGF(TL("Could not find bidi-connection for edge '%'"), k.id)
470  }
471  return "";
472 }
473 
474 void
475 NWWriter_SUMO::writeEdge(OutputDevice& into, const NBEdge& e, bool noNames) {
476  // write the edge's begin
479  into.writeAttr(SUMO_ATTR_TO, e.getToNode()->getID());
480  if (!noNames && e.getStreetName() != "") {
482  }
484  if (e.getTypeID() != "") {
486  }
487  if (e.isMacroscopicConnector()) {
489  }
490  // write the spread type if not default ("right")
493  }
494  if (e.hasLoadedLength()) {
496  }
497  if (!e.hasDefaultGeometry()) {
499  }
500  if (e.getEdgeStopOffset().isDefined()) {
502  }
503  if (e.getBidiEdge()) {
505  }
506  if (e.getDistance() != 0) {
508  }
509 
510  // write the lanes
511  const std::vector<NBEdge::Lane>& lanes = e.getLanes();
512 
513  double length = e.getFinalLength();
514  if (e.getBidiEdge() != nullptr) {
515  length = (length + e.getBidiEdge()->getFinalLength()) / 2;
516  }
517  double startOffset = e.isBidiRail() ? e.getTurnDestination(true)->getEndOffset() : 0;
518  for (int i = 0; i < (int) lanes.size(); i++) {
519  const NBEdge::Lane& l = lanes[i];
520  StopOffset stopOffset;
521  if (l.laneStopOffset != e.getEdgeStopOffset()) {
522  stopOffset = l.laneStopOffset;
523  }
524  writeLane(into, e.getLaneID(i), l.speed, l.friction,
525  l.permissions, l.preferred,
526  l.changeLeft, l.changeRight,
527  startOffset, l.endOffset,
528  stopOffset, l.width, l.shape, &l,
529  length, i, l.oppositeID, l.type, l.accelRamp, l.customShape.size() > 0);
530  }
531  // close the edge
532  e.writeParams(into);
533  into.closeTag();
534 }
535 
536 
537 void
538 NWWriter_SUMO::writeLane(OutputDevice& into, const std::string& lID,
539  double speed, double friction,
540  SVCPermissions permissions, SVCPermissions preferred,
541  SVCPermissions changeLeft, SVCPermissions changeRight,
542  double startOffset, double endOffset,
543  const StopOffset& stopOffset, double width, PositionVector shape,
544  const Parameterised* params, double length, int index,
545  const std::string& oppositeID,
546  const std::string& type,
547  bool accelRamp, bool customShape,
548  const PositionVector& outlineShape) {
549  // output the lane's attributes
551  // the first lane of an edge will be the depart lane
552  into.writeAttr(SUMO_ATTR_INDEX, index);
553  // write the list of allowed/disallowed vehicle classes
554  if (permissions != SVC_UNSPECIFIED) {
555  writePermissions(into, permissions);
556  }
557  writePreferences(into, preferred);
558  // some further information
559  into.writeAttr(SUMO_ATTR_SPEED, MAX2(0.0, speed));
560  if (friction != NBEdge::UNSPECIFIED_FRICTION) {
561  into.writeAttr(SUMO_ATTR_FRICTION, friction);
562  }
563  into.writeAttr(SUMO_ATTR_LENGTH, length);
564  if (endOffset != NBEdge::UNSPECIFIED_OFFSET) {
565  into.writeAttr(SUMO_ATTR_ENDOFFSET, endOffset);
566  }
567  if (width != NBEdge::UNSPECIFIED_WIDTH) {
568  into.writeAttr(SUMO_ATTR_WIDTH, width);
569  }
570  if (accelRamp) {
571  into.writeAttr<bool>(SUMO_ATTR_ACCELERATION, accelRamp);
572  }
573  if (customShape) {
574  into.writeAttr(SUMO_ATTR_CUSTOMSHAPE, true);
575  }
576  if (endOffset > 0 || startOffset > 0) {
577  startOffset = MIN2(startOffset, shape.length() - POSITION_EPS);
578  endOffset = MIN2(endOffset, shape.length() - startOffset - POSITION_EPS);
579  assert(startOffset + endOffset < shape.length());
580  shape = shape.getSubpart(startOffset, shape.length() - endOffset);
581  }
582  into.writeAttr(SUMO_ATTR_SHAPE, shape);
583  if (type != "") {
584  into.writeAttr(SUMO_ATTR_TYPE, type);
585  }
586  if (changeLeft != SVC_UNSPECIFIED && changeLeft != SVCAll && changeLeft != SVC_IGNORING) {
588  }
589  if (changeRight != SVC_UNSPECIFIED && changeRight != SVCAll && changeRight != SVC_IGNORING) {
591  }
592  if (stopOffset.isDefined()) {
593  writeStopOffsets(into, stopOffset);
594  }
595  if (outlineShape.size() != 0) {
596  into.writeAttr(SUMO_ATTR_OUTLINESHAPE, outlineShape);
597  }
598 
599  if (oppositeID != "" && oppositeID != "-") {
600  into.openTag(SUMO_TAG_NEIGH);
601  into.writeAttr(SUMO_ATTR_LANE, oppositeID);
602  into.closeTag();
603  }
604 
605  if (params != nullptr) {
606  params->writeParams(into);
607  }
608 
609  into.closeTag();
610 }
611 
612 
613 void
615  // write the attributes
617  into.writeAttr(SUMO_ATTR_TYPE, n.getType());
619  // write the incoming lanes
620  std::vector<std::string> incLanes;
621  const std::vector<NBEdge*>& incoming = n.getIncomingEdges();
622  for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); ++i) {
623  int noLanes = (*i)->getNumLanes();
624  for (int j = 0; j < noLanes; j++) {
625  incLanes.push_back((*i)->getLaneID(j));
626  }
627  }
628  std::vector<NBNode::Crossing*> crossings = n.getCrossings();
629  std::set<std::string> prevWAs;
630  // avoid duplicates
631  for (auto c : crossings) {
632  if (prevWAs.count(c->prevWalkingArea) == 0) {
633  incLanes.push_back(c->prevWalkingArea + "_0");
634  prevWAs.insert(c->prevWalkingArea);
635  }
636  }
637  into.writeAttr(SUMO_ATTR_INCLANES, incLanes);
638  // write the internal lanes
639  std::vector<std::string> intLanes;
640  if (!OptionsCont::getOptions().getBool("no-internal-links")) {
641  for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
642  const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
643  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
644  if ((*k).toEdge == nullptr) {
645  continue;
646  }
647  if (!(*k).haveVia) {
648  intLanes.push_back((*k).getInternalLaneID());
649  } else {
650  intLanes.push_back((*k).viaID + "_0");
651  }
652  }
653  }
654  }
656  for (auto c : crossings) {
657  intLanes.push_back(c->id + "_0");
658  }
659  }
660  into.writeAttr(SUMO_ATTR_INTLANES, intLanes);
661  // close writing
663  // write optional radius
666  }
667  // specify whether a custom shape was used
668  if (n.hasCustomShape()) {
669  into.writeAttr(SUMO_ATTR_CUSTOMSHAPE, true);
670  }
671  if (n.getRightOfWay() != RightOfWay::DEFAULT) {
672  into.writeAttr<std::string>(SUMO_ATTR_RIGHT_OF_WAY, toString(n.getRightOfWay()));
673  }
674  if (n.getFringeType() != FringeType::DEFAULT) {
675  into.writeAttr<std::string>(SUMO_ATTR_FRINGE, toString(n.getFringeType()));
676  }
677  if (n.getName() != "") {
678  into.writeAttr<std::string>(SUMO_ATTR_NAME, StringUtils::escapeXML(n.getName()));
679  }
680  if (n.getType() != SumoXMLNodeType::DEAD_END) {
681  // write right-of-way logics
682  n.writeLogic(into);
683  }
684  n.writeParams(into);
685  into.closeTag();
686 }
687 
688 
689 bool
691  bool ret = false;
692  const std::vector<NBEdge*>& incoming = n.getIncomingEdges();
693  // build the list of internal lane ids
694  std::vector<std::string> internalLaneIDs;
695  std::map<std::string, std::string> viaIDs;
696  for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
697  const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
698  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
699  if ((*k).toEdge != nullptr) {
700  internalLaneIDs.push_back((*k).getInternalLaneID());
701  viaIDs[(*k).getInternalLaneID()] = ((*k).viaID);
702  }
703  }
704  }
705  for (auto c : n.getCrossings()) {
706  internalLaneIDs.push_back(c->id + "_0");
707  }
708  // write the internal nodes
709  for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
710  const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
711  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
712  if ((*k).toEdge == nullptr || !(*k).haveVia) {
713  continue;
714  }
715  Position pos = (*k).shape[-1];
716  into.openTag(SUMO_TAG_JUNCTION).writeAttr(SUMO_ATTR_ID, (*k).viaID + "_0");
718  NWFrame::writePositionLong(pos, into);
719  std::string incLanes = (*k).getInternalLaneID();
720  std::vector<std::string> foeIDs;
721  for (std::string incLane : (*k).foeIncomingLanes) {
722  if (incLane[0] == ':') {
723  // intersecting left turns
724  const int index = StringUtils::toInt(incLane.substr(1));
725  incLane = internalLaneIDs[index];
726  if (viaIDs[incLane] != "") {
727  foeIDs.push_back(viaIDs[incLane] + "_0");
728  }
729  }
730  incLanes += " " + incLane;
731  }
732  into.writeAttr(SUMO_ATTR_INCLANES, incLanes);
733  const std::vector<int>& foes = (*k).foeInternalLinks;
734  for (std::vector<int>::const_iterator it = foes.begin(); it != foes.end(); ++it) {
735  foeIDs.push_back(internalLaneIDs[*it]);
736  }
737  into.writeAttr(SUMO_ATTR_INTLANES, joinToString(foeIDs, " "));
738  into.closeTag();
739  ret = true;
740  }
741  }
742  return ret;
743 }
744 
745 
746 void
748  bool includeInternal, ConnectionStyle style, bool geoAccuracy) {
749  assert(c.toEdge != 0);
751  into.writeAttr(SUMO_ATTR_FROM, from.getID());
752  into.writeAttr(SUMO_ATTR_TO, c.toEdge->getID());
755  if (style != TLL) {
756  if (c.mayDefinitelyPass) {
758  }
759  if (c.keepClear == KEEPCLEAR_FALSE) {
760  into.writeAttr<bool>(SUMO_ATTR_KEEP_CLEAR, false);
761  }
764  }
765  if (c.permissions != SVC_UNSPECIFIED) {
766  writePermissions(into, c.permissions);
767  }
770  }
773  }
774  if (c.speed != NBEdge::UNSPECIFIED_SPEED) {
776  }
779  }
780  if (c.customShape.size() != 0) {
781  if (geoAccuracy) {
783  }
785  if (geoAccuracy) {
786  into.setPrecision();
787  }
788  }
789  if (c.uncontrolled != false) {
791  }
792  if (c.indirectLeft != false) {
794  }
795  if (c.edgeType != "") {
797  }
798  }
799  if (style != PLAIN) {
800  if (includeInternal) {
802  }
803  // set information about the controlling tl if any
804  if (c.tlID != "") {
805  into.writeAttr(SUMO_ATTR_TLID, c.tlID);
807  if (c.tlLinkIndex2 >= 0) {
809  }
810  }
811  }
812  if (style != TLL) {
813  if (style == SUMONET) {
814  // write the direction information
815  LinkDirection dir = from.getToNode()->getDirection(&from, c.toEdge, OptionsCont::getOptions().getBool("lefthand"));
816  assert(dir != LinkDirection::NODIR);
817  into.writeAttr(SUMO_ATTR_DIR, toString(dir));
818  // write the state information
819  const LinkState linkState = from.getToNode()->getLinkState(
820  &from, c.toEdge, c.fromLane, c.toLane, c.mayDefinitelyPass, c.tlID);
821  into.writeAttr(SUMO_ATTR_STATE, linkState);
822  if (linkState == LINKSTATE_MINOR
824  && c.toEdge->getJunctionPriority(c.toEdge->getToNode()) == NBEdge::JunctionPriority::ROUNDABOUT) {
825  const double visibilityDistance = OptionsCont::getOptions().getFloat("roundabouts.visibility-distance");
826  if (visibilityDistance != NBEdge::UNSPECIFIED_VISIBILITY_DISTANCE) {
827  into.writeAttr(SUMO_ATTR_VISIBILITY_DISTANCE, visibilityDistance);
828  }
829  }
830  }
833  }
834  }
835  c.writeParams(into);
836  into.closeTag();
837 }
838 
839 
840 bool
842  bool ret = false;
843  const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
844  for (const NBEdge* const from : n.getIncomingEdges()) {
845  for (const NBEdge::Connection& c : from->getConnections()) {
846  LinkDirection dir = n.getDirection(from, c.toEdge, lefthand);
847  assert(c.toEdge != 0);
848  if (c.haveVia) {
849  // internal split with optional signal
850  std::string tlID = "";
851  int linkIndex2 = NBConnection::InvalidTlIndex;
852  if (c.tlLinkIndex2 != NBConnection::InvalidTlIndex) {
853  linkIndex2 = c.tlLinkIndex2;
854  tlID = c.tlID;
855  }
856  writeInternalConnection(into, c.id, c.toEdge->getID(), c.internalLaneIndex, c.toLane, c.viaID + "_0", dir, tlID, linkIndex2, false, c.visibility);
857  writeInternalConnection(into, c.viaID, c.toEdge->getID(), 0, c.toLane, "", dir, "", NBConnection::InvalidTlIndex, n.brakeForCrossingOnExit(c.toEdge));
858  } else {
859  // no internal split
860  writeInternalConnection(into, c.id, c.toEdge->getID(), c.internalLaneIndex, c.toLane, "", dir);
861  }
862  ret = true;
863  }
864  }
865  return ret;
866 }
867 
868 
869 void
871  const std::string& from, const std::string& to,
872  int fromLane, int toLane, const std::string& via,
873  LinkDirection dir,
874  const std::string& tlID, int linkIndex,
875  bool minor,
876  double visibility) {
878  into.writeAttr(SUMO_ATTR_FROM, from);
879  into.writeAttr(SUMO_ATTR_TO, to);
880  into.writeAttr(SUMO_ATTR_FROM_LANE, fromLane);
881  into.writeAttr(SUMO_ATTR_TO_LANE, toLane);
882  if (via != "") {
883  into.writeAttr(SUMO_ATTR_VIA, via);
884  }
885  if (tlID != "" && linkIndex != NBConnection::InvalidTlIndex) {
886  // used for the reverse direction of pedestrian crossings
887  into.writeAttr(SUMO_ATTR_TLID, tlID);
888  into.writeAttr(SUMO_ATTR_TLLINKINDEX, linkIndex);
889  }
890  into.writeAttr(SUMO_ATTR_DIR, dir);
891  into.writeAttr(SUMO_ATTR_STATE, ((via != "" || minor) ? "m" : "M"));
892  if (visibility != NBEdge::UNSPECIFIED_VISIBILITY_DISTANCE) {
893  into.writeAttr(SUMO_ATTR_VISIBILITY_DISTANCE, visibility);
894  }
895  into.closeTag();
896 }
897 
898 
899 void
900 NWWriter_SUMO::writeRoundabouts(OutputDevice& into, const std::set<EdgeSet>& roundabouts,
901  const NBEdgeCont& ec) {
902  // make output deterministic
903  std::vector<std::vector<std::string> > edgeIDs;
904  for (std::set<EdgeSet>::const_iterator i = roundabouts.begin(); i != roundabouts.end(); ++i) {
905  std::vector<std::string> tEdgeIDs;
906  for (EdgeSet::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
907  // the edges may have been erased from NBEdgeCont but their pointers are still valid
908  // we verify their existance in writeRoundabout()
909  tEdgeIDs.push_back((*j)->getID());
910  }
911  std::sort(tEdgeIDs.begin(), tEdgeIDs.end());
912  edgeIDs.push_back(tEdgeIDs);
913  }
914  std::sort(edgeIDs.begin(), edgeIDs.end());
915  // write
916  for (std::vector<std::vector<std::string> >::const_iterator i = edgeIDs.begin(); i != edgeIDs.end(); ++i) {
917  writeRoundabout(into, *i, ec);
918  }
919  if (roundabouts.size() != 0) {
920  into.lf();
921  }
922 }
923 
924 
925 void
926 NWWriter_SUMO::writeRoundabout(OutputDevice& into, const std::vector<std::string>& edgeIDs,
927  const NBEdgeCont& ec) {
928  std::vector<std::string> validEdgeIDs;
929  std::vector<std::string> invalidEdgeIDs;
930  std::vector<std::string> nodeIDs;
931  for (std::vector<std::string>::const_iterator i = edgeIDs.begin(); i != edgeIDs.end(); ++i) {
932  const NBEdge* edge = ec.retrieve(*i);
933  if (edge != nullptr) {
934  nodeIDs.push_back(edge->getToNode()->getID());
935  validEdgeIDs.push_back(edge->getID());
936  } else {
937  invalidEdgeIDs.push_back(*i);
938  }
939  }
940  std::sort(nodeIDs.begin(), nodeIDs.end());
941  if (validEdgeIDs.size() > 0) {
943  into.writeAttr(SUMO_ATTR_NODES, joinToString(nodeIDs, " "));
944  into.writeAttr(SUMO_ATTR_EDGES, joinToString(validEdgeIDs, " "));
945  into.closeTag();
946  if (invalidEdgeIDs.size() > 0) {
947  WRITE_WARNING("Writing incomplete roundabout. Edges: '"
948  + joinToString(invalidEdgeIDs, " ") + "' no longer exist'");
949  }
950  }
951 }
952 
953 
954 void
956  std::vector<double> sourceW = d.getSourceWeights();
958  std::vector<double> sinkW = d.getSinkWeights();
960  // write the head and the id of the district
962  if (d.getShape().size() > 0) {
964  }
965  // write all sources
966  const std::vector<NBEdge*>& sources = d.getSourceEdges();
967  for (int i = 0; i < (int)sources.size(); i++) {
968  // write the head and the id of the source
969  into.openTag(SUMO_TAG_TAZSOURCE).writeAttr(SUMO_ATTR_ID, sources[i]->getID()).writeAttr(SUMO_ATTR_WEIGHT, sourceW[i]);
970  into.closeTag();
971  }
972  // write all sinks
973  const std::vector<NBEdge*>& sinks = d.getSinkEdges();
974  for (int i = 0; i < (int)sinks.size(); i++) {
975  // write the head and the id of the sink
976  into.openTag(SUMO_TAG_TAZSINK).writeAttr(SUMO_ATTR_ID, sinks[i]->getID()).writeAttr(SUMO_ATTR_WEIGHT, sinkW[i]);
977  into.closeTag();
978  }
979  // write the tail
980  into.closeTag();
981 }
982 
983 
984 std::string
986  double time = STEPS2TIME(steps);
987  if (time == std::floor(time)) {
988  return toString(int(time));
989  } else {
990  return toString(time);
991  }
992 }
993 
994 
995 void
997  for (NBConnectionProhibits::const_iterator j = prohibitions.begin(); j != prohibitions.end(); j++) {
998  NBConnection prohibited = (*j).first;
999  const NBConnectionVector& prohibiting = (*j).second;
1000  for (NBConnectionVector::const_iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
1001  NBConnection prohibitor = *k;
1005  into.closeTag();
1006  }
1007  }
1008 }
1009 
1010 
1011 std::string
1013  return c.getFrom()->getID() + "->" + c.getTo()->getID();
1014 }
1015 
1016 
1017 void
1019  std::vector<NBTrafficLightLogic*> logics = tllCont.getComputed();
1020  for (NBTrafficLightLogic* logic : logics) {
1021  writeTrafficLight(into, logic);
1022  // only raise warnings on write instead of on compute (to avoid cluttering netedit)
1023  NBTrafficLightDefinition* def = tllCont.getDefinition(logic->getID(), logic->getProgramID());
1024  assert(def != nullptr);
1025  def->finalChecks();
1026  }
1027  if (logics.size() > 0) {
1028  into.lf();
1029  }
1030 }
1031 
1032 
1033 void
1035  into.openTag(SUMO_TAG_TLLOGIC);
1036  into.writeAttr(SUMO_ATTR_ID, logic->getID());
1037  into.writeAttr(SUMO_ATTR_TYPE, logic->getType());
1038  into.writeAttr(SUMO_ATTR_PROGRAMID, logic->getProgramID());
1040  // write the phases
1041  const bool varPhaseLength = logic->getType() != TrafficLightType::STATIC;
1042  for (const NBTrafficLightLogic::PhaseDefinition& phase : logic->getPhases()) {
1043  into.openTag(SUMO_TAG_PHASE);
1044  into.writeAttr(SUMO_ATTR_DURATION, writeSUMOTime(phase.duration));
1045  if (phase.duration < TIME2STEPS(10)) {
1046  into.writePadding(" ");
1047  }
1048  into.writeAttr(SUMO_ATTR_STATE, phase.state);
1049  if (varPhaseLength) {
1050  if (phase.minDur != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
1051  into.writeAttr(SUMO_ATTR_MINDURATION, writeSUMOTime(phase.minDur));
1052  }
1053  if (phase.maxDur != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
1054  into.writeAttr(SUMO_ATTR_MAXDURATION, writeSUMOTime(phase.maxDur));
1055  }
1056  if (phase.earliestEnd != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
1057  into.writeAttr(SUMO_ATTR_EARLIEST_END, writeSUMOTime(phase.earliestEnd));
1058  }
1059  if (phase.latestEnd != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
1060  into.writeAttr(SUMO_ATTR_LATEST_END, writeSUMOTime(phase.latestEnd));
1061  }
1062  // NEMA attributes
1063  if (phase.vehExt != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
1064  into.writeAttr(SUMO_ATTR_VEHICLEEXTENSION, writeSUMOTime(phase.vehExt));
1065  }
1066  if (phase.yellow != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
1067  into.writeAttr(SUMO_ATTR_YELLOW, writeSUMOTime(phase.yellow));
1068  }
1070  into.writeAttr(SUMO_ATTR_RED, writeSUMOTime(phase.red));
1071  }
1072  }
1073  if (phase.name != "") {
1074  into.writeAttr(SUMO_ATTR_NAME, StringUtils::escapeXML(phase.name));
1075  }
1076  if (phase.next.size() > 0) {
1077  into.writeAttr(SUMO_ATTR_NEXT, phase.next);
1078  }
1079  into.closeTag();
1080  }
1081  // write params
1082  logic->writeParams(into);
1083  into.closeTag();
1084 }
1085 
1086 
1087 void
1089  if (stopOffset.isDefined()) {
1090  const std::string ss_vclasses = getVehicleClassNames(stopOffset.getPermissions());
1091  if (ss_vclasses.length() == 0) {
1092  // This stopOffset would have no effect...
1093  return;
1094  }
1096  const std::string ss_exceptions = getVehicleClassNames(~stopOffset.getPermissions());
1097  if (ss_vclasses.length() <= ss_exceptions.length()) {
1098  into.writeAttr(SUMO_ATTR_VCLASSES, ss_vclasses);
1099  } else {
1100  if (ss_exceptions.length() == 0) {
1101  into.writeAttr(SUMO_ATTR_VCLASSES, "all");
1102  } else {
1103  into.writeAttr(SUMO_ATTR_EXCEPTIONS, ss_exceptions);
1104  }
1105  }
1106  into.writeAttr(SUMO_ATTR_VALUE, stopOffset.getOffset());
1107  into.closeTag();
1108  }
1109 }
1110 
1111 
1112 /****************************************************************************/
long long int SUMOTime
Definition: GUI.h:35
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:296
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:295
#define TL(string)
Definition: MsgHandler.h:315
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:35
@ KEEPCLEAR_FALSE
Definition: NBCont.h:59
#define STEPS2TIME(x)
Definition: SUMOTime.h:55
#define TIME2STEPS(x)
Definition: SUMOTime.h:57
const SVCPermissions SVCAll
all VClasses are allowed
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;
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
@ SVC_IGNORING
vehicles ignoring classes
@ SVC_PEDESTRIAN
pedestrian
@ 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
connectioon 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_JUNCTIONS_MINIMAL_SHAPE
@ SUMO_ATTR_LANE
@ SUMO_ATTR_NODES
a list of node ids, used for controlling joining
@ SUMO_ATTR_LATEST_END
The maximum time within the cycle for switching (for coordinated actuation)
@ SUMO_ATTR_TLLINKINDEX2
link: the index of the opposite direction link of a pedestrian crossing
@ SUMO_ATTR_RED
red duration of a phase
@ 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_INDIRECT
Whether this connection is an indirect (left) turn.
@ 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_YELLOW
yellow duration of a phase
@ SUMO_ATTR_CUSTOMSHAPE
whether a given shape is user-defined
@ SUMO_ATTR_INTLANES
@ SUMO_ATTR_VEHICLEEXTENSION
vehicle extension time of a phase
@ 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_CHANGE_LEFT
@ SUMO_ATTR_INDEX
@ SUMO_ATTR_VCLASSES
@ SUMO_ATTR_NAME
@ SUMO_ATTR_EXCEPTIONS
@ SUMO_ATTR_JUNCTIONS_ENDPOINT_SHAPE
@ 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_HIGHER_SPEED
@ SUMO_ATTR_TO
@ SUMO_ATTR_FROM
@ SUMO_ATTR_ACCELERATION
@ SUMO_ATTR_CHANGE_RIGHT
@ 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_OUTLINESHAPE
edge: the outline shape in xml-definition
@ 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_INTERNAL_JUNCTIONS_VEHICLE_WIDTH
@ SUMO_ATTR_STATE
The state of a link.
@ SUMO_ATTR_FRICTION
@ SUMO_ATTR_WALKINGAREAS
@ SUMO_ATTR_EARLIEST_END
The minimum time within the cycle for switching (for coordinated actuation)
int gPrecisionGeo
Definition: StdDefs.cpp:27
T MIN2(T a, T b)
Definition: StdDefs.h:76
T MAX2(T a, T b)
Definition: StdDefs.h:82
const MMVersion NETWORK_VERSION(1, 20)
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
Definition: ToString.h:283
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
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:171
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:178
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
Definition: NBEdgeCont.cpp:281
std::set< std::string > getUsedTypes() const
return all edge types in used
The representation of a single edge during network building.
Definition: NBEdge.h:92
double getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn't set.
Definition: NBEdge.h:598
static const double UNSPECIFIED_FRICTION
unspecified lane friction
Definition: NBEdge.h:351
const std::string & getStreetName() const
Returns the street name of this edge.
Definition: NBEdge.h:665
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge's lanes' lateral offset is computed.
Definition: NBEdge.cpp:992
bool isBidiRail(bool ignoreSpread=false) const
whether this edge is part of a bidirectional railway
Definition: NBEdge.cpp:743
bool hasLoadedLength() const
Returns whether a length was set explicitly.
Definition: NBEdge.h:608
const std::string & getID() const
Definition: NBEdge.h:1524
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
Definition: NBEdge.h:726
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:542
double getDistance() const
get distance
Definition: NBEdge.h:675
static const double UNSPECIFIED_LOADED_LENGTH
no length override given
Definition: NBEdge.h:360
const StopOffset & getEdgeStopOffset() const
Returns the stopOffset to the end of the edge.
Definition: NBEdge.cpp:4221
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:516
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:779
std::vector< Connection > getConnectionsFromLane(int lane, const NBEdge *to=nullptr, int toLane=-1) const
Returns connections from a given lane.
Definition: NBEdge.cpp:1280
static const double UNSPECIFIED_CONTPOS
unspecified internal junction position
Definition: NBEdge.h:354
static const double UNSPECIFIED_VISIBILITY_DISTANCE
unspecified foe visibility for connections
Definition: NBEdge.h:357
std::string getLaneID(int lane) const
get lane ID
Definition: NBEdge.cpp:4006
static const double UNSPECIFIED_SPEED
unspecified lane speed
Definition: NBEdge.h:348
const NBEdge * getBidiEdge() const
Definition: NBEdge.h:1510
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
Definition: NBEdge.cpp:2122
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition: NBEdge.cpp:3997
bool hasDefaultGeometry() const
Returns whether the geometry consists only of the node positions.
Definition: NBEdge.cpp:590
int getPriority() const
Returns the priority of the edge.
Definition: NBEdge.h:523
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:342
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:1037
const std::string & getTypeID() const
get ID of type
Definition: NBEdge.h:1177
double getEndOffset() const
Returns the offset to the destination node.
Definition: NBEdge.h:685
static const double UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:345
bool isMacroscopicConnector() const
Returns whether this edge was marked as a macroscopic connector.
Definition: NBEdge.h:1132
double getFinalLength() const
get length that will be assigned to the lanes in the final network
Definition: NBEdge.cpp:4704
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:535
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:159
NBTypeCont & getTypeCont()
Returns a reference to the type container.
Definition: NBNetBuilder.h:149
NBEdgeCont & getEdgeCont()
Definition: NBNetBuilder.h:139
NBNodeCont & getNodeCont()
Returns a reference to the node container.
Definition: NBNetBuilder.h:144
NBTrafficLightLogicCont & getTLLogicCont()
Returns a reference to the traffic light logics container.
Definition: NBNetBuilder.h:154
A definition of a pedestrian crossing.
Definition: NBNode.h:135
int tlLinkIndex
the traffic light index of this crossing (if controlled)
Definition: NBNode.h:162
std::string tlID
The id of the traffic light that controls this connection.
Definition: NBNode.h:168
bool priority
whether the pedestrians have priority
Definition: NBNode.h:158
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:57
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
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:2358
RightOfWay getRightOfWay() const
Returns hint on how to compute right of way.
Definition: NBNode.h:300
LinkState getLinkState(const NBEdge *incoming, const NBEdge *outgoing, int fromLane, int toLane, bool mayDefinitelyPass, const std::string &tlID) const
get link state
Definition: NBNode.cpp:2441
static const double UNSPECIFIED_RADIUS
unspecified lane width
Definition: NBNode.h:220
Crossing * getCrossing(const std::string &id) const
return the crossing with the given id
Definition: NBNode.cpp:3866
FringeType getFringeType() const
Returns fringe type.
Definition: NBNode.h:305
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:285
const std::string & getName() const
Returns intersection name.
Definition: NBNode.h:310
bool hasCustomShape() const
return whether the shape was set by the user
Definition: NBNode.h:584
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
Definition: NBNode.h:268
bool brakeForCrossingOnExit(const NBEdge *to) const
whether a connection to the given edge must brake for a crossing when leaving the intersection
Definition: NBNode.cpp:2029
std::vector< Crossing * > getCrossings() const
return this junctions pedestrian crossings
Definition: NBNode.cpp:2927
bool writeLogic(OutputDevice &into) const
writes the XML-representation of the logic as a bitset-logic XML representation
Definition: NBNode.cpp:1088
const PositionVector & getShape() const
retrieve the junction shape
Definition: NBNode.cpp:2614
const Position & getPosition() const
Definition: NBNode.h:260
double getRadius() const
Returns the turning radius of this node.
Definition: NBNode.h:290
const std::vector< WalkingArea > & getWalkingAreas() const
return this junctions pedestrian walking areas
Definition: NBNode.h:747
The base class for traffic light logic definitions.
virtual void finalChecks() const
perform optional final checks
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.
NBTrafficLightDefinition * getDefinition(const std::string &id, const std::string &programID) const
Returns the named definition.
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 std::set< std::string > &typeIDs=std::set< std::string >()) const
writes all EdgeTypes (and their lanes) as XML
Definition: NBTypeCont.cpp:377
static void writePositionLong(const Position &pos, OutputDevice &dev)
Writes the given position to device in long format (one attribute per dimension)
Definition: NWFrame.cpp:201
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 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 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 writeLane(OutputDevice &into, const std::string &lID, double speed, double friction, SVCPermissions permissions, SVCPermissions preferred, SVCPermissions changeLeft, SVCPermissions changeRight, double startOffset, double endOffset, const StopOffset &stopOffset, 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, const PositionVector &outlineShape=PositionVector())
Writes a lane (<lane ...) of an edge.
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 std::string getInternalBidi(const NBEdge *e, const NBEdge::Connection &k, double &length)
retrieve bidi edge id for internal corresponding to the given connection
static void writeRoundabout(OutputDevice &into, const std::vector< std::string > &r, const NBEdgeCont &ec)
Writes a roundabout.
static void writeStopOffsets(OutputDevice &into, const StopOffset &stopOffset)
Write a stopOffset element into output device.
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, bool minor=false, double visibility=NBEdge::UNSPECIFIED_VISIBILITY_DISTANCE)
Writes a single internal connection.
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:74
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)
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 set(const std::string &name, const std::string &value, const bool append=false)
Sets the given value for the named option.
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:60
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
void lf()
writes a line feed if applicable
Definition: OutputDevice.h:242
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:254
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
void setPrecision(int precision=gPrecision)
Sets the precision or resets it to default.
OutputDevice & writePadding(const std::string &val)
writes padding (ignored for binary output)
Definition: OutputDevice.h:325
static OutputDevice & getDevice(const std::string &name, bool usePrefix=true)
Returns the described OutputDevice.
bool writeXMLHeader(const std::string &rootElement, const std::string &schemaFile, std::map< SumoXMLAttr, std::string > attrs=std::map< SumoXMLAttr, std::string >(), bool includeConfig=true)
Writes an XML header with optional configuration.
An upper class for objects with additional parameters.
Definition: Parameterised.h:41
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:37
A list of positions.
double length() const
Returns the length.
PositionVector simplified() const
return the same shape with intermediate colinear points removed
PositionVector reverse() const
reverse position vector
PositionVector getSubpart(double beginOffset, double endOffset) const
get subpart of a position vector
stop offset
bool isDefined() const
check if stopOffset was defined
SVCPermissions getPermissions() const
get permissions
double getOffset() const
get offset
static std::string escapeXML(const std::string &orig, const bool maskDoubleHyphen=false)
Replaces the standard escapes by their XML entities.
static int toInt(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter,...
static void normaliseSum(std::vector< T > &v, T msum=1.0)
Definition: VectorHelper.h:47
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:201
bool indirectLeft
Whether this connection is an indirect left turn.
Definition: NBEdge.h:261
int fromLane
The lane the connections starts at.
Definition: NBEdge.h:210
int toLane
The lane the connections yields in.
Definition: NBEdge.h:216
SVCPermissions permissions
List of vehicle types that are allowed on this connection.
Definition: NBEdge.h:252
double speed
custom speed for connection
Definition: NBEdge.h:240
NBEdge * toEdge
The edge the connections yields in.
Definition: NBEdge.h:213
KeepClear keepClear
whether the junction must be kept clear when using this connection
Definition: NBEdge.h:231
double customLength
custom length for connection
Definition: NBEdge.h:246
std::string edgeType
optional type of Connection
Definition: NBEdge.h:264
bool uncontrolled
check if Connection is uncontrolled
Definition: NBEdge.h:297
PositionVector customShape
custom shape for connection
Definition: NBEdge.h:249
bool mayDefinitelyPass
Information about being definitely free to drive (on-ramps)
Definition: NBEdge.h:228
SVCPermissions changeLeft
List of vehicle types that are allowed to change Left from this connections internal lane(s)
Definition: NBEdge.h:255
SVCPermissions changeRight
List of vehicle types that are allowed to change right from this connections internal lane(s)
Definition: NBEdge.h:258
std::string getDescription(const NBEdge *parent) const
get string describing this connection
Definition: NBEdge.cpp:98
double contPos
custom position for internal junction on this connection
Definition: NBEdge.h:234
std::string getInternalLaneID() const
get ID of internal lane
Definition: NBEdge.cpp:92
std::string tlID
The id of the traffic light that controls this connection.
Definition: NBEdge.h:219
double visibility
custom foe visiblity for connection
Definition: NBEdge.h:237
int tlLinkIndex2
The index of the internal junction within the controlling traffic light (optional)
Definition: NBEdge.h:225
double length
computed length (average of all internal lane shape lengths that share an internal edge)
Definition: NBEdge.h:306
std::string id
id of Connection
Definition: NBEdge.h:267
int tlLinkIndex
The index of this connection within the controlling traffic light.
Definition: NBEdge.h:222
An (internal) definition of a single lane of an edge.
Definition: NBEdge.h:143
double width
This lane's width.
Definition: NBEdge.h:176
StopOffset laneStopOffset
stopOffsets.second - The stop offset for vehicles stopping at the lane's end. Applies if vClass is in...
Definition: NBEdge.h:173
PositionVector customShape
A custom shape for this lane set by the user.
Definition: NBEdge.h:189
double endOffset
This lane's offset to the intersection begin.
Definition: NBEdge.h:169
std::string type
the type of this lane
Definition: NBEdge.h:192
SVCPermissions preferred
List of vehicle types that are preferred on this lane.
Definition: NBEdge.h:160
double speed
The speed allowed on this lane.
Definition: NBEdge.h:151
std::string oppositeID
An opposite lane ID, if given.
Definition: NBEdge.h:179
SVCPermissions changeRight
List of vehicle types that are allowed to change right from this lane.
Definition: NBEdge.h:166
double friction
The friction on this lane.
Definition: NBEdge.h:154
SVCPermissions changeLeft
List of vehicle types that are allowed to change Left from this lane.
Definition: NBEdge.h:163
SVCPermissions permissions
List of vehicle types that are allowed on this lane.
Definition: NBEdge.h:157
bool accelRamp
Whether this lane is an acceleration lane.
Definition: NBEdge.h:182
PositionVector shape
The lane's shape.
Definition: NBEdge.h:148
A definition of a pedestrian walking area.
Definition: NBNode.h:177
std::string id
the (edge)-id of this walkingArea
Definition: NBNode.h:184
bool hasCustomShape
whether this walkingArea has a custom shape
Definition: NBNode.h:200
double width
This lane's width.
Definition: NBNode.h:186
PositionVector shape
The polygonal shape.
Definition: NBNode.h:190
double length
This lane's width.
Definition: NBNode.h:188