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, 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  assert(startOffset + endOffset < shape.length());
578  shape = shape.getSubpart(startOffset, shape.length() - endOffset);
579  }
580  into.writeAttr(SUMO_ATTR_SHAPE, shape);
581  if (type != "") {
582  into.writeAttr(SUMO_ATTR_TYPE, type);
583  }
584  if (changeLeft != SVC_UNSPECIFIED && changeLeft != SVCAll && changeLeft != SVC_IGNORING) {
586  }
587  if (changeRight != SVC_UNSPECIFIED && changeRight != SVCAll && changeRight != SVC_IGNORING) {
589  }
590  if (stopOffset.isDefined()) {
591  writeStopOffsets(into, stopOffset);
592  }
593  if (outlineShape.size() != 0) {
594  into.writeAttr(SUMO_ATTR_OUTLINESHAPE, outlineShape);
595  }
596 
597  if (oppositeID != "" && oppositeID != "-") {
598  into.openTag(SUMO_TAG_NEIGH);
599  into.writeAttr(SUMO_ATTR_LANE, oppositeID);
600  into.closeTag();
601  }
602 
603  if (params != nullptr) {
604  params->writeParams(into);
605  }
606 
607  into.closeTag();
608 }
609 
610 
611 void
613  // write the attributes
615  into.writeAttr(SUMO_ATTR_TYPE, n.getType());
617  // write the incoming lanes
618  std::vector<std::string> incLanes;
619  const std::vector<NBEdge*>& incoming = n.getIncomingEdges();
620  for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); ++i) {
621  int noLanes = (*i)->getNumLanes();
622  for (int j = 0; j < noLanes; j++) {
623  incLanes.push_back((*i)->getLaneID(j));
624  }
625  }
626  std::vector<NBNode::Crossing*> crossings = n.getCrossings();
627  std::set<std::string> prevWAs;
628  // avoid duplicates
629  for (auto c : crossings) {
630  if (prevWAs.count(c->prevWalkingArea) == 0) {
631  incLanes.push_back(c->prevWalkingArea + "_0");
632  prevWAs.insert(c->prevWalkingArea);
633  }
634  }
635  into.writeAttr(SUMO_ATTR_INCLANES, incLanes);
636  // write the internal lanes
637  std::vector<std::string> intLanes;
638  if (!OptionsCont::getOptions().getBool("no-internal-links")) {
639  for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
640  const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
641  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
642  if ((*k).toEdge == nullptr) {
643  continue;
644  }
645  if (!(*k).haveVia) {
646  intLanes.push_back((*k).getInternalLaneID());
647  } else {
648  intLanes.push_back((*k).viaID + "_0");
649  }
650  }
651  }
652  }
654  for (auto c : crossings) {
655  intLanes.push_back(c->id + "_0");
656  }
657  }
658  into.writeAttr(SUMO_ATTR_INTLANES, intLanes);
659  // close writing
661  // write optional radius
664  }
665  // specify whether a custom shape was used
666  if (n.hasCustomShape()) {
667  into.writeAttr(SUMO_ATTR_CUSTOMSHAPE, true);
668  }
669  if (n.getRightOfWay() != RightOfWay::DEFAULT) {
670  into.writeAttr<std::string>(SUMO_ATTR_RIGHT_OF_WAY, toString(n.getRightOfWay()));
671  }
672  if (n.getFringeType() != FringeType::DEFAULT) {
673  into.writeAttr<std::string>(SUMO_ATTR_FRINGE, toString(n.getFringeType()));
674  }
675  if (n.getName() != "") {
676  into.writeAttr<std::string>(SUMO_ATTR_NAME, StringUtils::escapeXML(n.getName()));
677  }
678  if (n.getType() != SumoXMLNodeType::DEAD_END) {
679  // write right-of-way logics
680  n.writeLogic(into);
681  }
682  n.writeParams(into);
683  into.closeTag();
684 }
685 
686 
687 bool
689  bool ret = false;
690  const std::vector<NBEdge*>& incoming = n.getIncomingEdges();
691  // build the list of internal lane ids
692  std::vector<std::string> internalLaneIDs;
693  std::map<std::string, std::string> viaIDs;
694  for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
695  const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
696  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
697  if ((*k).toEdge != nullptr) {
698  internalLaneIDs.push_back((*k).getInternalLaneID());
699  viaIDs[(*k).getInternalLaneID()] = ((*k).viaID);
700  }
701  }
702  }
703  for (auto c : n.getCrossings()) {
704  internalLaneIDs.push_back(c->id + "_0");
705  }
706  // write the internal nodes
707  for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
708  const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
709  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
710  if ((*k).toEdge == nullptr || !(*k).haveVia) {
711  continue;
712  }
713  Position pos = (*k).shape[-1];
714  into.openTag(SUMO_TAG_JUNCTION).writeAttr(SUMO_ATTR_ID, (*k).viaID + "_0");
716  NWFrame::writePositionLong(pos, into);
717  std::string incLanes = (*k).getInternalLaneID();
718  std::vector<std::string> foeIDs;
719  for (std::string incLane : (*k).foeIncomingLanes) {
720  if (incLane[0] == ':') {
721  // intersecting left turns
722  const int index = StringUtils::toInt(incLane.substr(1));
723  incLane = internalLaneIDs[index];
724  if (viaIDs[incLane] != "") {
725  foeIDs.push_back(viaIDs[incLane] + "_0");
726  }
727  }
728  incLanes += " " + incLane;
729  }
730  into.writeAttr(SUMO_ATTR_INCLANES, incLanes);
731  const std::vector<int>& foes = (*k).foeInternalLinks;
732  for (std::vector<int>::const_iterator it = foes.begin(); it != foes.end(); ++it) {
733  foeIDs.push_back(internalLaneIDs[*it]);
734  }
735  into.writeAttr(SUMO_ATTR_INTLANES, joinToString(foeIDs, " "));
736  into.closeTag();
737  ret = true;
738  }
739  }
740  return ret;
741 }
742 
743 
744 void
746  bool includeInternal, ConnectionStyle style, bool geoAccuracy) {
747  assert(c.toEdge != 0);
749  into.writeAttr(SUMO_ATTR_FROM, from.getID());
750  into.writeAttr(SUMO_ATTR_TO, c.toEdge->getID());
753  if (style != TLL) {
754  if (c.mayDefinitelyPass) {
756  }
757  if (c.keepClear == KEEPCLEAR_FALSE) {
758  into.writeAttr<bool>(SUMO_ATTR_KEEP_CLEAR, false);
759  }
762  }
763  if (c.permissions != SVC_UNSPECIFIED) {
764  writePermissions(into, c.permissions);
765  }
768  }
771  }
772  if (c.speed != NBEdge::UNSPECIFIED_SPEED) {
774  }
777  }
778  if (c.customShape.size() != 0) {
779  if (geoAccuracy) {
781  }
783  if (geoAccuracy) {
784  into.setPrecision();
785  }
786  }
787  if (c.uncontrolled != false) {
789  }
790  if (c.indirectLeft != false) {
792  }
793  if (c.edgeType != "") {
795  }
796  }
797  if (style != PLAIN) {
798  if (includeInternal) {
800  }
801  // set information about the controlling tl if any
802  if (c.tlID != "") {
803  into.writeAttr(SUMO_ATTR_TLID, c.tlID);
805  if (c.tlLinkIndex2 >= 0) {
807  }
808  }
809  }
810  if (style != TLL) {
811  if (style == SUMONET) {
812  // write the direction information
813  LinkDirection dir = from.getToNode()->getDirection(&from, c.toEdge, OptionsCont::getOptions().getBool("lefthand"));
814  assert(dir != LinkDirection::NODIR);
815  into.writeAttr(SUMO_ATTR_DIR, toString(dir));
816  // write the state information
817  const LinkState linkState = from.getToNode()->getLinkState(
818  &from, c.toEdge, c.fromLane, c.toLane, c.mayDefinitelyPass, c.tlID);
819  into.writeAttr(SUMO_ATTR_STATE, linkState);
820  if (linkState == LINKSTATE_MINOR
822  && c.toEdge->getJunctionPriority(c.toEdge->getToNode()) == NBEdge::JunctionPriority::ROUNDABOUT) {
823  const double visibilityDistance = OptionsCont::getOptions().getFloat("roundabouts.visibility-distance");
824  if (visibilityDistance != NBEdge::UNSPECIFIED_VISIBILITY_DISTANCE) {
825  into.writeAttr(SUMO_ATTR_VISIBILITY_DISTANCE, visibilityDistance);
826  }
827  }
828  }
831  }
832  }
833  c.writeParams(into);
834  into.closeTag();
835 }
836 
837 
838 bool
840  bool ret = false;
841  const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
842  for (const NBEdge* const from : n.getIncomingEdges()) {
843  for (const NBEdge::Connection& c : from->getConnections()) {
844  LinkDirection dir = n.getDirection(from, c.toEdge, lefthand);
845  assert(c.toEdge != 0);
846  if (c.haveVia) {
847  // internal split with optional signal
848  std::string tlID = "";
849  int linkIndex2 = NBConnection::InvalidTlIndex;
850  if (c.tlLinkIndex2 != NBConnection::InvalidTlIndex) {
851  linkIndex2 = c.tlLinkIndex2;
852  tlID = c.tlID;
853  }
854  writeInternalConnection(into, c.id, c.toEdge->getID(), c.internalLaneIndex, c.toLane, c.viaID + "_0", dir, tlID, linkIndex2, false, c.visibility);
855  writeInternalConnection(into, c.viaID, c.toEdge->getID(), 0, c.toLane, "", dir, "", NBConnection::InvalidTlIndex, n.brakeForCrossingOnExit(c.toEdge));
856  } else {
857  // no internal split
858  writeInternalConnection(into, c.id, c.toEdge->getID(), c.internalLaneIndex, c.toLane, "", dir);
859  }
860  ret = true;
861  }
862  }
863  return ret;
864 }
865 
866 
867 void
869  const std::string& from, const std::string& to,
870  int fromLane, int toLane, const std::string& via,
871  LinkDirection dir,
872  const std::string& tlID, int linkIndex,
873  bool minor,
874  double visibility) {
876  into.writeAttr(SUMO_ATTR_FROM, from);
877  into.writeAttr(SUMO_ATTR_TO, to);
878  into.writeAttr(SUMO_ATTR_FROM_LANE, fromLane);
879  into.writeAttr(SUMO_ATTR_TO_LANE, toLane);
880  if (via != "") {
881  into.writeAttr(SUMO_ATTR_VIA, via);
882  }
883  if (tlID != "" && linkIndex != NBConnection::InvalidTlIndex) {
884  // used for the reverse direction of pedestrian crossings
885  into.writeAttr(SUMO_ATTR_TLID, tlID);
886  into.writeAttr(SUMO_ATTR_TLLINKINDEX, linkIndex);
887  }
888  into.writeAttr(SUMO_ATTR_DIR, dir);
889  into.writeAttr(SUMO_ATTR_STATE, ((via != "" || minor) ? "m" : "M"));
890  if (visibility != NBEdge::UNSPECIFIED_VISIBILITY_DISTANCE) {
891  into.writeAttr(SUMO_ATTR_VISIBILITY_DISTANCE, visibility);
892  }
893  into.closeTag();
894 }
895 
896 
897 void
898 NWWriter_SUMO::writeRoundabouts(OutputDevice& into, const std::set<EdgeSet>& roundabouts,
899  const NBEdgeCont& ec) {
900  // make output deterministic
901  std::vector<std::vector<std::string> > edgeIDs;
902  for (std::set<EdgeSet>::const_iterator i = roundabouts.begin(); i != roundabouts.end(); ++i) {
903  std::vector<std::string> tEdgeIDs;
904  for (EdgeSet::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
905  // the edges may have been erased from NBEdgeCont but their pointers are still valid
906  // we verify their existance in writeRoundabout()
907  tEdgeIDs.push_back((*j)->getID());
908  }
909  std::sort(tEdgeIDs.begin(), tEdgeIDs.end());
910  edgeIDs.push_back(tEdgeIDs);
911  }
912  std::sort(edgeIDs.begin(), edgeIDs.end());
913  // write
914  for (std::vector<std::vector<std::string> >::const_iterator i = edgeIDs.begin(); i != edgeIDs.end(); ++i) {
915  writeRoundabout(into, *i, ec);
916  }
917  if (roundabouts.size() != 0) {
918  into.lf();
919  }
920 }
921 
922 
923 void
924 NWWriter_SUMO::writeRoundabout(OutputDevice& into, const std::vector<std::string>& edgeIDs,
925  const NBEdgeCont& ec) {
926  std::vector<std::string> validEdgeIDs;
927  std::vector<std::string> invalidEdgeIDs;
928  std::vector<std::string> nodeIDs;
929  for (std::vector<std::string>::const_iterator i = edgeIDs.begin(); i != edgeIDs.end(); ++i) {
930  const NBEdge* edge = ec.retrieve(*i);
931  if (edge != nullptr) {
932  nodeIDs.push_back(edge->getToNode()->getID());
933  validEdgeIDs.push_back(edge->getID());
934  } else {
935  invalidEdgeIDs.push_back(*i);
936  }
937  }
938  std::sort(nodeIDs.begin(), nodeIDs.end());
939  if (validEdgeIDs.size() > 0) {
941  into.writeAttr(SUMO_ATTR_NODES, joinToString(nodeIDs, " "));
942  into.writeAttr(SUMO_ATTR_EDGES, joinToString(validEdgeIDs, " "));
943  into.closeTag();
944  if (invalidEdgeIDs.size() > 0) {
945  WRITE_WARNING("Writing incomplete roundabout. Edges: '"
946  + joinToString(invalidEdgeIDs, " ") + "' no longer exist'");
947  }
948  }
949 }
950 
951 
952 void
954  std::vector<double> sourceW = d.getSourceWeights();
956  std::vector<double> sinkW = d.getSinkWeights();
958  // write the head and the id of the district
960  if (d.getShape().size() > 0) {
962  }
963  // write all sources
964  const std::vector<NBEdge*>& sources = d.getSourceEdges();
965  for (int i = 0; i < (int)sources.size(); i++) {
966  // write the head and the id of the source
967  into.openTag(SUMO_TAG_TAZSOURCE).writeAttr(SUMO_ATTR_ID, sources[i]->getID()).writeAttr(SUMO_ATTR_WEIGHT, sourceW[i]);
968  into.closeTag();
969  }
970  // write all sinks
971  const std::vector<NBEdge*>& sinks = d.getSinkEdges();
972  for (int i = 0; i < (int)sinks.size(); i++) {
973  // write the head and the id of the sink
974  into.openTag(SUMO_TAG_TAZSINK).writeAttr(SUMO_ATTR_ID, sinks[i]->getID()).writeAttr(SUMO_ATTR_WEIGHT, sinkW[i]);
975  into.closeTag();
976  }
977  // write the tail
978  into.closeTag();
979 }
980 
981 
982 std::string
984  double time = STEPS2TIME(steps);
985  if (time == std::floor(time)) {
986  return toString(int(time));
987  } else {
988  return toString(time);
989  }
990 }
991 
992 
993 void
995  for (NBConnectionProhibits::const_iterator j = prohibitions.begin(); j != prohibitions.end(); j++) {
996  NBConnection prohibited = (*j).first;
997  const NBConnectionVector& prohibiting = (*j).second;
998  for (NBConnectionVector::const_iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
999  NBConnection prohibitor = *k;
1003  into.closeTag();
1004  }
1005  }
1006 }
1007 
1008 
1009 std::string
1011  return c.getFrom()->getID() + "->" + c.getTo()->getID();
1012 }
1013 
1014 
1015 void
1017  std::vector<NBTrafficLightLogic*> logics = tllCont.getComputed();
1018  for (NBTrafficLightLogic* logic : logics) {
1019  writeTrafficLight(into, logic);
1020  // only raise warnings on write instead of on compute (to avoid cluttering netedit)
1021  NBTrafficLightDefinition* def = tllCont.getDefinition(logic->getID(), logic->getProgramID());
1022  assert(def != nullptr);
1023  def->finalChecks();
1024  }
1025  if (logics.size() > 0) {
1026  into.lf();
1027  }
1028 }
1029 
1030 
1031 void
1033  into.openTag(SUMO_TAG_TLLOGIC);
1034  into.writeAttr(SUMO_ATTR_ID, logic->getID());
1035  into.writeAttr(SUMO_ATTR_TYPE, logic->getType());
1036  into.writeAttr(SUMO_ATTR_PROGRAMID, logic->getProgramID());
1038  // write the phases
1039  const bool varPhaseLength = logic->getType() != TrafficLightType::STATIC;
1040  for (const NBTrafficLightLogic::PhaseDefinition& phase : logic->getPhases()) {
1041  into.openTag(SUMO_TAG_PHASE);
1042  into.writeAttr(SUMO_ATTR_DURATION, writeSUMOTime(phase.duration));
1043  if (phase.duration < TIME2STEPS(10)) {
1044  into.writePadding(" ");
1045  }
1046  into.writeAttr(SUMO_ATTR_STATE, phase.state);
1047  if (varPhaseLength) {
1048  if (phase.minDur != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
1049  into.writeAttr(SUMO_ATTR_MINDURATION, writeSUMOTime(phase.minDur));
1050  }
1051  if (phase.maxDur != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
1052  into.writeAttr(SUMO_ATTR_MAXDURATION, writeSUMOTime(phase.maxDur));
1053  }
1054  if (phase.earliestEnd != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
1055  into.writeAttr(SUMO_ATTR_EARLIEST_END, writeSUMOTime(phase.earliestEnd));
1056  }
1057  if (phase.latestEnd != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
1058  into.writeAttr(SUMO_ATTR_LATEST_END, writeSUMOTime(phase.latestEnd));
1059  }
1060  // NEMA attributes
1061  if (phase.vehExt != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
1062  into.writeAttr(SUMO_ATTR_VEHICLEEXTENSION, writeSUMOTime(phase.vehExt));
1063  }
1064  if (phase.yellow != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
1065  into.writeAttr(SUMO_ATTR_YELLOW, writeSUMOTime(phase.yellow));
1066  }
1068  into.writeAttr(SUMO_ATTR_RED, writeSUMOTime(phase.red));
1069  }
1070  }
1071  if (phase.name != "") {
1072  into.writeAttr(SUMO_ATTR_NAME, StringUtils::escapeXML(phase.name));
1073  }
1074  if (phase.next.size() > 0) {
1075  into.writeAttr(SUMO_ATTR_NEXT, phase.next);
1076  }
1077  into.closeTag();
1078  }
1079  // write params
1080  logic->writeParams(into);
1081  into.closeTag();
1082 }
1083 
1084 
1085 void
1087  if (stopOffset.isDefined()) {
1088  const std::string ss_vclasses = getVehicleClassNames(stopOffset.getPermissions());
1089  if (ss_vclasses.length() == 0) {
1090  // This stopOffset would have no effect...
1091  return;
1092  }
1094  const std::string ss_exceptions = getVehicleClassNames(~stopOffset.getPermissions());
1095  if (ss_vclasses.length() <= ss_exceptions.length()) {
1096  into.writeAttr(SUMO_ATTR_VCLASSES, ss_vclasses);
1097  } else {
1098  if (ss_exceptions.length() == 0) {
1099  into.writeAttr(SUMO_ATTR_VCLASSES, "all");
1100  } else {
1101  into.writeAttr(SUMO_ATTR_EXCEPTIONS, ss_exceptions);
1102  }
1103  }
1104  into.writeAttr(SUMO_ATTR_VALUE, stopOffset.getOffset());
1105  into.closeTag();
1106  }
1107 }
1108 
1109 
1110 /****************************************************************************/
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 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:979
bool isBidiRail(bool ignoreSpread=false) const
whether this edge is part of a bidirectional railway
Definition: NBEdge.cpp:730
bool hasLoadedLength() const
Returns whether a length was set explicitly.
Definition: NBEdge.h:608
const std::string & getID() const
Definition: NBEdge.h:1522
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:4161
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:1252
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:3946
static const double UNSPECIFIED_SPEED
unspecified lane speed
Definition: NBEdge.h:348
const NBEdge * getBidiEdge() const
Definition: NBEdge.h:1508
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
Definition: NBEdge.cpp:2084
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition: NBEdge.cpp:3937
bool hasDefaultGeometry() const
Returns whether the geometry consists only of the node positions.
Definition: NBEdge.cpp:589
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:1035
const std::string & getTypeID() const
get ID of type
Definition: NBEdge.h:1175
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:1130
double getFinalLength() const
get length that will be assigned to the lanes in the final network
Definition: NBEdge.cpp:4644
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:2349
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:2432
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:3838
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:2020
std::vector< Crossing * > getCrossings() const
return this junctions pedestrian crossings
Definition: NBNode.cpp:2918
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:2605
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:97
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:91
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