Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
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-2025 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>
34#include <netbuild/NBEdge.h>
35#include <netbuild/NBEdgeCont.h>
36#include <netbuild/NBNode.h>
37#include <netbuild/NBNodeCont.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// ---------------------------------------------------------------------------
54void
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 LaneSpreadFunction defaultSpread = SUMOXMLDefinitions::LaneSpreadFunctions.get(oc.getString("default.spreadtype"));
71 const int cornerDetail = oc.getInt("junctions.corner-detail");
72 if (cornerDetail > 0) {
73 attrs[SUMO_ATTR_CORNERDETAIL] = toString(cornerDetail);
74 }
75 if (!oc.isDefault("junctions.internal-link-detail")) {
76 attrs[SUMO_ATTR_LINKDETAIL] = toString(oc.getInt("junctions.internal-link-detail"));
77 }
78 if (oc.getBool("rectangular-lane-cut")) {
79 attrs[SUMO_ATTR_RECTANGULAR_LANE_CUT] = "true";
80 }
81 if (oc.getBool("crossings.guess") || oc.getBool("walkingareas")) {
82 attrs[SUMO_ATTR_WALKINGAREAS] = "true";
83 }
84 if (oc.getFloat("junctions.limit-turn-speed") > 0) {
85 attrs[SUMO_ATTR_LIMIT_TURN_SPEED] = toString(oc.getFloat("junctions.limit-turn-speed"));
86 }
87 if (!oc.isDefault("check-lane-foes.all")) {
88 attrs[SUMO_ATTR_CHECKLANEFOES_ALL] = toString(oc.getBool("check-lane-foes.all"));
89 }
90 if (!oc.isDefault("check-lane-foes.roundabout")) {
91 attrs[SUMO_ATTR_CHECKLANEFOES_ROUNDABOUT] = toString(oc.getBool("check-lane-foes.roundabout"));
92 }
93 if (!oc.isDefault("tls.ignore-internal-junction-jam")) {
94 attrs[SUMO_ATTR_TLS_IGNORE_INTERNAL_JUNCTION_JAM] = toString(oc.getBool("tls.ignore-internal-junction-jam"));
95 }
96 if (defaultSpread != LaneSpreadFunction::RIGHT) {
97 attrs[SUMO_ATTR_SPREADTYPE] = oc.getString("default.spreadtype");
98 }
99 if (oc.exists("geometry.avoid-overlap") && !oc.getBool("geometry.avoid-overlap")) {
100 attrs[SUMO_ATTR_AVOID_OVERLAP] = toString(oc.getBool("geometry.avoid-overlap"));
101 }
102 if (oc.exists("junctions.higher-speed") && oc.getBool("junctions.higher-speed")) {
103 attrs[SUMO_ATTR_HIGHER_SPEED] = toString(oc.getBool("junctions.higher-speed"));
104 }
105 if (oc.exists("internal-junctions.vehicle-width") && !oc.isDefault("internal-junctions.vehicle-width")) {
106 attrs[SUMO_ATTR_INTERNAL_JUNCTIONS_VEHICLE_WIDTH] = toString(oc.getFloat("internal-junctions.vehicle-width"));
107 }
108 if (!oc.isDefault("junctions.minimal-shape")) {
109 attrs[SUMO_ATTR_JUNCTIONS_MINIMAL_SHAPE] = toString(oc.getBool("junctions.minimal-shape"));
110 }
111 if (!oc.isDefault("junctions.endpoint-shape")) {
112 attrs[SUMO_ATTR_JUNCTIONS_ENDPOINT_SHAPE] = toString(oc.getBool("junctions.endpoint-shape"));
113 }
114 device.writeXMLHeader("net", "net_file.xsd", attrs); // street names may contain non-ascii chars
115 device.lf();
116 // get involved container
117 const NBNodeCont& nc = nb.getNodeCont();
118 const NBEdgeCont& ec = nb.getEdgeCont();
119 const NBDistrictCont& dc = nb.getDistrictCont();
120
121 // write network offsets and projection
123
124 // write edge types and restrictions
125 std::set<std::string> usedTypes = ec.getUsedTypes();
126 nb.getTypeCont().writeEdgeTypes(device, usedTypes);
127
128 // write inner lanes
129 if (!oc.getBool("no-internal-links")) {
130 bool hadAny = false;
131 for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
132 hadAny |= writeInternalEdges(device, ec, *(*i).second);
133 }
134 if (hadAny) {
135 device.lf();
136 }
137 }
138
139 // write edges with lanes and connected edges
140 bool noNames = !oc.getBool("output.street-names");
141 for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
142 writeEdge(device, *(*i).second, noNames, defaultSpread);
143 }
144 device.lf();
145
146 // write tls logics
148
149 // write the nodes (junctions)
150 for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
151 writeJunction(device, *(*i).second);
152 }
153 device.lf();
154 const bool includeInternal = !oc.getBool("no-internal-links");
155 if (includeInternal) {
156 // ... internal nodes if not unwanted
157 bool hadAny = false;
158 for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
159 hadAny |= writeInternalNodes(device, *(*i).second);
160 }
161 if (hadAny) {
162 device.lf();
163 }
164 }
165
166 // write the successors of lanes
167 int numConnections = 0;
168 for (std::map<std::string, NBEdge*>::const_iterator it_edge = ec.begin(); it_edge != ec.end(); it_edge++) {
169 NBEdge* from = it_edge->second;
170 const std::vector<NBEdge::Connection>& connections = from->getConnections();
171 numConnections += (int)connections.size();
172 for (const NBEdge::Connection& con : connections) {
173 writeConnection(device, *from, con, includeInternal);
174 }
175 }
176 if (numConnections > 0) {
177 device.lf();
178 }
179 if (includeInternal) {
180 // ... internal successors if not unwanted
181 bool hadAny = false;
182 for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
183 hadAny |= writeInternalConnections(device, *(*i).second);
184 }
185 if (hadAny) {
186 device.lf();
187 }
188 }
189 for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
190 NBNode* node = (*i).second;
191 // write connections from pedestrian crossings
192 std::vector<NBNode::Crossing*> crossings = node->getCrossings();
193 for (auto c : crossings) {
194 NWWriter_SUMO::writeInternalConnection(device, c->id, c->nextWalkingArea, 0, 0, "", LinkDirection::STRAIGHT, c->tlID, c->tlLinkIndex2);
195 }
196 // write connections from pedestrian walking areas
197 for (const NBNode::WalkingArea& wa : node->getWalkingAreas()) {
198 for (const std::string& cID : wa.nextCrossings) {
199 const NBNode::Crossing& nextCrossing = *node->getCrossing(cID);
200 // connection to next crossing (may be tls-controlled)
202 device.writeAttr(SUMO_ATTR_FROM, wa.id);
203 device.writeAttr(SUMO_ATTR_TO, cID);
205 device.writeAttr(SUMO_ATTR_TO_LANE, 0);
206 if (nextCrossing.tlID != "") {
207 device.writeAttr(SUMO_ATTR_TLID, nextCrossing.tlID);
208 assert(nextCrossing.tlLinkIndex >= 0);
209 device.writeAttr(SUMO_ATTR_TLLINKINDEX, nextCrossing.tlLinkIndex);
210 }
213 device.closeTag();
214 }
215 // optional connections from/to sidewalk
216 std::string edgeID;
217 int laneIndex;
218 for (const std::string& sw : wa.nextSidewalks) {
219 NBHelpers::interpretLaneID(sw, edgeID, laneIndex);
220 NWWriter_SUMO::writeInternalConnection(device, wa.id, edgeID, 0, laneIndex, "");
221 }
222 for (const std::string& sw : wa.prevSidewalks) {
223 NBHelpers::interpretLaneID(sw, edgeID, laneIndex);
224 NWWriter_SUMO::writeInternalConnection(device, edgeID, wa.id, laneIndex, 0, "");
225 }
226 }
227 }
228
229 // write loaded prohibitions
230 for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
231 writeProhibitions(device, i->second->getProhibitions());
232 }
233
234 // write roundabout information
235 writeRoundabouts(device, ec.getRoundabouts(), ec);
236
237 // write the districts
238 if (dc.size() != 0 && oc.isDefault("taz-output")) {
239 WRITE_WARNING(TL("Embedding TAZ-data inside the network is deprecated. Use option --taz-output instead"));
240 for (std::map<std::string, NBDistrict*>::const_iterator i = dc.begin(); i != dc.end(); i++) {
241 writeDistrict(device, *(*i).second);
242 }
243 device.lf();
244 }
245 device.close();
246}
247
248
249std::string
250NWWriter_SUMO::getOppositeInternalID(const NBEdgeCont& ec, const NBEdge* from, const NBEdge::Connection& con, double& oppositeLength) {
251 const NBEdge::Lane& succ = con.toEdge->getLanes()[con.toLane];
252 const NBEdge::Lane& pred = from->getLanes()[con.fromLane];
253 const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
254 if (succ.oppositeID != "" && succ.oppositeID != "-" && pred.oppositeID != "" && pred.oppositeID != "-") {
255#ifdef DEBUG_OPPOSITE_INTERNAL
256 std::cout << "getOppositeInternalID con=" << con.getDescription(from) << " (" << con.getInternalLaneID() << ")\n";
257#endif
258 // find the connection that connects succ.oppositeID to pred.oppositeID
259 const NBEdge* succOpp = ec.retrieve(succ.oppositeID.substr(0, succ.oppositeID.rfind("_")));
260 const NBEdge* predOpp = ec.retrieve(pred.oppositeID.substr(0, pred.oppositeID.rfind("_")));
261 assert(succOpp != 0);
262 assert(predOpp != 0);
263 const std::vector<NBEdge::Connection>& connections = succOpp->getConnections();
264 for (std::vector<NBEdge::Connection>::const_iterator it_c = connections.begin(); it_c != connections.end(); it_c++) {
265 const NBEdge::Connection& conOpp = *it_c;
266 if (succOpp != from // turnaround
267 && predOpp == conOpp.toEdge
268 && succOpp->getLaneID(conOpp.fromLane) == succ.oppositeID
269 && predOpp->getLaneID(conOpp.toLane) == pred.oppositeID
270 && from->getToNode()->getDirection(from, con.toEdge, lefthand) == LinkDirection::STRAIGHT
271 && from->getToNode()->getDirection(succOpp, predOpp, lefthand) == LinkDirection::STRAIGHT
272 ) {
273#ifdef DEBUG_OPPOSITE_INTERNAL
274 std::cout << " found " << conOpp.getInternalLaneID() << "\n";
275#endif
276 oppositeLength = conOpp.length;
277 return conOpp.getInternalLaneID();
278 } else {
279 /*
280 #ifdef DEBUG_OPPOSITE_INTERNAL
281 std::cout << " rejected " << conOpp.getInternalLaneID()
282 << "\n succ.oppositeID=" << succ.oppositeID
283 << "\n succOppLane=" << succOpp->getLaneID(conOpp.fromLane)
284 << "\n pred.oppositeID=" << pred.oppositeID
285 << "\n predOppLane=" << predOpp->getLaneID(conOpp.toLane)
286 << "\n predOpp=" << predOpp->getID()
287 << "\n conOppTo=" << conOpp.toEdge->getID()
288 << "\n len1=" << con.shape.length()
289 << "\n len2=" << conOpp.shape.length()
290 << "\n";
291 #endif
292 */
293 }
294 }
295 return "";
296 } else {
297 return "";
298 }
299}
300
301
302bool
304 bool ret = false;
305 const EdgeVector& incoming = n.getIncomingEdges();
306 // first pass: determine opposite internal edges and average their length
307 std::map<std::string, std::string> oppositeLaneID;
308 std::map<std::string, double> oppositeLengths;
309 for (NBEdge* e : incoming) {
310 for (const NBEdge::Connection& c : e->getConnections()) {
311 double oppositeLength = 0;
312 const std::string op = getOppositeInternalID(ec, e, c, oppositeLength);
313 oppositeLaneID[c.getInternalLaneID()] = op;
314 if (op != "") {
315 oppositeLengths[c.id] = oppositeLength;
316 }
317 }
318 }
319 if (oppositeLengths.size() > 0) {
320 for (NBEdge* e : incoming) {
321 for (NBEdge::Connection& c : e->getConnections()) {
322 if (oppositeLengths.count(c.id) > 0) {
323 c.length = (c.length + oppositeLengths[c.id]) / 2;
324 }
325 }
326 }
327 }
328
329 for (NBEdge* e : incoming) {
330 const std::vector<NBEdge::Connection>& elv = e->getConnections();
331 if (elv.size() > 0) {
332 bool haveVia = false;
333 std::string edgeID = "";
334 double bidiLength = -1;
335 // second pass: write non-via edges
336 for (const NBEdge::Connection& k : elv) {
337 if (k.toEdge == nullptr) {
338 assert(false); // should never happen. tell me when it does
339 continue;
340 }
341 if (edgeID != k.id) {
342 if (edgeID != "") {
343 // close the previous edge
344 into.closeTag();
345 }
346 edgeID = k.id;
348 into.writeAttr(SUMO_ATTR_ID, edgeID);
350 if (k.edgeType != "") {
351 into.writeAttr(SUMO_ATTR_TYPE, k.edgeType);
352 }
353 bidiLength = -1;
354 if (e->getBidiEdge() && k.toEdge->getBidiEdge() &&
355 e != k.toEdge->getTurnDestination(true)) {
356 const std::string bidiEdge = getInternalBidi(e, k, bidiLength);
357 if (bidiEdge != "") {
358 into.writeAttr(SUMO_ATTR_BIDI, bidiEdge);
359 }
360 }
361 // open a new edge
362 }
363 // to avoid changing to an internal lane which has a successor
364 // with the wrong permissions we need to inherit them from the successor
365 const NBEdge::Lane& successor = k.toEdge->getLanes()[k.toLane];
366 SVCPermissions permissions = (k.permissions != SVC_UNSPECIFIED) ? k.permissions : (
367 successor.permissions & e->getPermissions(k.fromLane));
368 SVCPermissions changeLeft = k.changeLeft != SVC_UNSPECIFIED ? k.changeLeft : SVCAll;
369 SVCPermissions changeRight = k.changeRight != SVC_UNSPECIFIED ? k.changeRight : SVCAll;
370 const double width = e->getInternalLaneWidth(n, k, successor, false);
371 const double length = bidiLength > 0 ? bidiLength : k.length;
372 writeLane(into, k.getInternalLaneID(), k.vmax, k.friction,
373 permissions, successor.preferred,
374 changeLeft, changeRight,
376 StopOffset(), width, k.shape, &k,
377 length, k.internalLaneIndex, oppositeLaneID[k.getInternalLaneID()], "");
378 haveVia = haveVia || k.haveVia;
379 }
380 ret = true;
381 into.closeTag(); // close the last edge
382 // third pass: write via edges
383 if (haveVia) {
384 std::string viaEdgeID = "";
385 for (const NBEdge::Connection& k : elv) {
386 if (!k.haveVia) {
387 continue;
388 }
389 if (k.toEdge == nullptr) {
390 assert(false); // should never happen. tell me when it does
391 continue;
392 }
393 if (viaEdgeID != k.viaID) {
394 if (viaEdgeID != "") {
395 // close the previous edge
396 into.closeTag();
397 }
398 viaEdgeID = k.viaID;
399 // open a new edge
401 into.writeAttr(SUMO_ATTR_ID, viaEdgeID);
403 if (k.edgeType != "") {
404 into.writeAttr(SUMO_ATTR_TYPE, k.edgeType);
405 }
406 }
407 const NBEdge::Lane& successor = k.toEdge->getLanes()[k.toLane];
408 SVCPermissions permissions = (k.permissions != SVC_UNSPECIFIED) ? k.permissions : (
409 successor.permissions & e->getPermissions(k.fromLane));
410 const double width = e->getInternalLaneWidth(n, k, successor, true);
411 writeLane(into, k.getInternalViaLaneID(), k.vmax, k.friction, permissions, successor.preferred,
412 SVCAll, SVCAll, // #XXX todo
414 StopOffset(), width, k.viaShape, &k,
415 MAX2(k.viaLength, POSITION_EPS), // microsim needs positive length
416 0, "", "");
417 }
418 into.closeTag();
419 }
420 }
421 }
422 // write pedestrian crossings
423 const double crossingSpeed = OptionsCont::getOptions().getFloat("default.crossing-speed");
424 for (auto c : n.getCrossings()) {
426 into.writeAttr(SUMO_ATTR_ID, c->id);
428 into.writeAttr(SUMO_ATTR_CROSSING_EDGES, c->edges);
429 writeLane(into, c->id + "_0", crossingSpeed, NBEdge::UNSPECIFIED_FRICTION, SVC_PEDESTRIAN, 0, SVCAll, SVCAll,
431 StopOffset(), c->width, c->shape, c,
432 MAX2(c->shape.length(), POSITION_EPS), 0, "", "", false, c->customShape.size() != 0, c->outlineShape);
433 into.closeTag();
434 }
435 // write pedestrian walking areas
436 const double walkingareaSpeed = OptionsCont::getOptions().getFloat("default.walkingarea-speed");
437 const std::vector<NBNode::WalkingArea>& WalkingAreas = n.getWalkingAreas();
438 for (std::vector<NBNode::WalkingArea>::const_iterator it = WalkingAreas.begin(); it != WalkingAreas.end(); it++) {
439 const NBNode::WalkingArea& wa = *it;
441 into.writeAttr(SUMO_ATTR_ID, wa.id);
443 writeLane(into, wa.id + "_0", walkingareaSpeed, NBEdge::UNSPECIFIED_FRICTION, SVC_PEDESTRIAN, 0, SVCAll, SVCAll,
445 StopOffset(), wa.width, wa.shape, nullptr, wa.length, 0, "", "", false, wa.hasCustomShape);
446 into.closeTag();
447 }
448 return ret;
449}
450
451
452std::string
453NWWriter_SUMO::getInternalBidi(const NBEdge* e, const NBEdge::Connection& k, double& length) {
454 const NBEdge* fromBidi = e->getTurnDestination(true);
455 const NBEdge* toBidi = k.toEdge->getTurnDestination(true);
456 const std::vector<NBEdge::Connection> cons = toBidi->getConnectionsFromLane(-1, fromBidi, -1);
457 if (cons.size() > 0) {
458 if (e->getNumLanes() == 1 && k.toEdge->getNumLanes() == 1 && fromBidi->getNumLanes() == 1 && toBidi->getNumLanes() == 1) {
459 length = (k.length + cons.back().length) / 2;
460 return cons.back().id;
461 }
462 // do a more careful check in case there are parallel internal edges
463 // note: k is the first connection with the new id
464 for (const NBEdge::Connection& c : e->getConnections()) {
465 if (c.id == k.id) {
466 PositionVector rShape = c.shape.reverse();
467 for (const NBEdge::Connection& k2 : cons) {
468 if (k2.shape.almostSame(rShape, POSITION_EPS)) {
469 length = (c.length + k2.length) / 2;
470 return k2.id;
471 }
472 }
473 }
474 }
475 } else {
476 WRITE_WARNINGF(TL("Could not find bidi-connection for edge '%'"), k.id)
477 }
478 return "";
479}
480
481void
482NWWriter_SUMO::writeEdge(OutputDevice& into, const NBEdge& e, bool noNames, LaneSpreadFunction defaultSpread) {
483 // write the edge's begin
487 if (!noNames && e.getStreetName() != "") {
489 }
491 if (e.getTypeID() != "") {
493 }
494 if (e.getRoutingType() != "") {
496 }
497 if (e.isMacroscopicConnector()) {
499 }
500 // write the spread type if not default ("right")
501 if (e.getLaneSpreadFunction() != defaultSpread) {
503 }
504 if (e.hasLoadedLength()) {
506 }
507 if (!e.hasDefaultGeometry()) {
509 }
510 if (e.getEdgeStopOffset().isDefined()) {
512 }
513 if (e.getBidiEdge()) {
515 }
516 if (e.getDistance() != 0) {
518 }
519
520 // write the lanes
521 const std::vector<NBEdge::Lane>& lanes = e.getLanes();
522
523 double length = e.getFinalLength();
524 if (e.getBidiEdge() != nullptr) {
525 length = (length + e.getBidiEdge()->getFinalLength()) / 2;
526 }
527 double startOffset = e.isBidiRail() ? e.getTurnDestination(true)->getEndOffset() : 0;
528 for (int i = 0; i < (int) lanes.size(); i++) {
529 const NBEdge::Lane& l = lanes[i];
530 StopOffset stopOffset;
531 if (l.laneStopOffset != e.getEdgeStopOffset()) {
532 stopOffset = l.laneStopOffset;
533 }
534 writeLane(into, e.getLaneID(i), l.speed, l.friction,
537 startOffset, l.endOffset,
538 stopOffset, l.width, l.shape, &l,
539 length, i, l.oppositeID, l.type, l.accelRamp, l.customShape.size() > 0);
540 }
541 // close the edge
542 e.writeParams(into);
543 into.closeTag();
544}
545
546
547void
548NWWriter_SUMO::writeLane(OutputDevice& into, const std::string& lID,
549 double speed, double friction,
550 SVCPermissions permissions, SVCPermissions preferred,
551 SVCPermissions changeLeft, SVCPermissions changeRight,
552 double startOffset, double endOffset,
553 const StopOffset& stopOffset, double width, PositionVector shape,
554 const Parameterised* params, double length, int index,
555 const std::string& oppositeID,
556 const std::string& type,
557 bool accelRamp, bool customShape,
558 const PositionVector& outlineShape) {
559 // output the lane's attributes
561 // the first lane of an edge will be the depart lane
562 into.writeAttr(SUMO_ATTR_INDEX, index);
563 // write the list of allowed/disallowed vehicle classes
564 if (permissions != SVC_UNSPECIFIED) {
565 writePermissions(into, permissions);
566 }
567 writePreferences(into, preferred);
568 // some further information
569 into.writeAttr(SUMO_ATTR_SPEED, MAX2(0.0, speed));
570 if (friction != NBEdge::UNSPECIFIED_FRICTION) {
571 into.writeAttr(SUMO_ATTR_FRICTION, friction);
572 }
573 into.writeAttr(SUMO_ATTR_LENGTH, length);
574 if (endOffset != NBEdge::UNSPECIFIED_OFFSET) {
575 into.writeAttr(SUMO_ATTR_ENDOFFSET, endOffset);
576 }
577 if (width != NBEdge::UNSPECIFIED_WIDTH) {
578 into.writeAttr(SUMO_ATTR_WIDTH, width);
579 }
580 if (accelRamp) {
581 into.writeAttr<bool>(SUMO_ATTR_ACCELERATION, accelRamp);
582 }
583 if (customShape) {
585 }
586 if (endOffset > 0 || startOffset > 0) {
587 startOffset = MIN2(startOffset, shape.length() - POSITION_EPS);
588 endOffset = MIN2(endOffset, shape.length() - startOffset - POSITION_EPS);
589 assert(startOffset + endOffset < shape.length());
590 shape = shape.getSubpart(startOffset, shape.length() - endOffset);
591 }
592 into.writeAttr(SUMO_ATTR_SHAPE, shape);
593 if (type != "") {
594 into.writeAttr(SUMO_ATTR_TYPE, type);
595 }
596 if (changeLeft != SVC_UNSPECIFIED && changeLeft != SVCAll && changeLeft != SVC_IGNORING) {
598 }
599 if (changeRight != SVC_UNSPECIFIED && changeRight != SVCAll && changeRight != SVC_IGNORING) {
601 }
602 if (stopOffset.isDefined()) {
603 writeStopOffsets(into, stopOffset);
604 }
605 if (outlineShape.size() != 0) {
606 into.writeAttr(SUMO_ATTR_OUTLINESHAPE, outlineShape);
607 }
608
609 if (oppositeID != "" && oppositeID != "-") {
611 into.writeAttr(SUMO_ATTR_LANE, oppositeID);
612 into.closeTag();
613 }
614
615 if (params != nullptr) {
616 params->writeParams(into);
617 }
618
619 into.closeTag();
620}
621
622
623void
625 // write the attributes
627 into.writeAttr(SUMO_ATTR_TYPE, n.getType());
628 NWFrame::writePositionLong(n.getPosition(), into);
629 // write the incoming lanes
630 std::vector<std::string> incLanes;
631 const std::vector<NBEdge*>& incoming = n.getIncomingEdges();
632 for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); ++i) {
633 int noLanes = (*i)->getNumLanes();
634 for (int j = 0; j < noLanes; j++) {
635 incLanes.push_back((*i)->getLaneID(j));
636 }
637 }
638 std::vector<NBNode::Crossing*> crossings = n.getCrossings();
639 std::set<std::string> prevWAs;
640 // avoid duplicates
641 for (auto c : crossings) {
642 if (prevWAs.count(c->prevWalkingArea) == 0) {
643 incLanes.push_back(c->prevWalkingArea + "_0");
644 prevWAs.insert(c->prevWalkingArea);
645 }
646 }
647 into.writeAttr(SUMO_ATTR_INCLANES, incLanes);
648 // write the internal lanes
649 std::vector<std::string> intLanes;
650 if (!OptionsCont::getOptions().getBool("no-internal-links")) {
651 for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
652 const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
653 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
654 if ((*k).toEdge == nullptr) {
655 continue;
656 }
657 if (!(*k).haveVia) {
658 intLanes.push_back((*k).getInternalLaneID());
659 } else {
660 intLanes.push_back((*k).getInternalViaLaneID());
661 }
662 }
663 }
664 }
665 if (n.getType() != SumoXMLNodeType::DEAD_END && n.getType() != SumoXMLNodeType::NOJUNCTION) {
666 for (auto c : crossings) {
667 intLanes.push_back(c->id + "_0");
668 }
669 }
670 into.writeAttr(SUMO_ATTR_INTLANES, intLanes);
671 // close writing
672 into.writeAttr(SUMO_ATTR_SHAPE, n.getShape().simplified());
673 // write optional radius
674 if (n.getRadius() != NBNode::UNSPECIFIED_RADIUS) {
675 into.writeAttr(SUMO_ATTR_RADIUS, n.getRadius());
676 }
677 // specify whether a custom shape was used
678 if (n.hasCustomShape()) {
680 }
681 if (n.getRightOfWay() != RightOfWay::DEFAULT) {
682 into.writeAttr<std::string>(SUMO_ATTR_RIGHT_OF_WAY, toString(n.getRightOfWay()));
683 }
684 if (n.getFringeType() != FringeType::DEFAULT) {
685 into.writeAttr<std::string>(SUMO_ATTR_FRINGE, toString(n.getFringeType()));
686 }
687 if (n.getRoundaboutType() != RoundaboutType::DEFAULT) {
688 into.writeAttr<std::string>(SUMO_ATTR_ROUNDABOUT, toString(n.getRoundaboutType()));
689 }
690 if (n.getName() != "") {
691 into.writeAttr<std::string>(SUMO_ATTR_NAME, StringUtils::escapeXML(n.getName()));
692 }
693 if (n.getType() != SumoXMLNodeType::DEAD_END) {
694 // write right-of-way logics
695 n.writeLogic(into);
696 }
697 n.writeParams(into);
698 into.closeTag();
699}
700
701
702bool
704 bool ret = false;
705 const std::vector<NBEdge*>& incoming = n.getIncomingEdges();
706 // build the list of internal lane ids
707 std::vector<std::string> internalLaneIDs;
708 std::map<std::string, std::string> viaIDs;
709 for (const NBEdge* in : incoming) {
710 for (const auto& con : in->getConnections()) {
711 if (con.toEdge != nullptr) {
712 internalLaneIDs.push_back(con.getInternalLaneID());
713 if (con.viaID != "") {
714 viaIDs[con.getInternalLaneID()] = (con.getInternalViaLaneID());
715 }
716 }
717 }
718 }
719 for (auto c : n.getCrossings()) {
720 internalLaneIDs.push_back(c->id + "_0");
721 }
722 // write the internal nodes
723 for (const NBEdge* in : incoming) {
724 for (const auto& con : in->getConnections()) {
725 if (con.toEdge == nullptr || !con.haveVia) {
726 continue;
727 }
728 Position pos = con.shape[-1];
729 into.openTag(SUMO_TAG_JUNCTION).writeAttr(SUMO_ATTR_ID, con.getInternalViaLaneID());
732 std::string incLanes = con.getInternalLaneID();
733 std::vector<std::string> foeIDs;
734 for (std::string incLane : con.foeIncomingLanes) {
735 if (incLane[0] == ':') {
736 // intersecting left turns
737 const int index = StringUtils::toInt(incLane.substr(1));
738 incLane = internalLaneIDs[index];
739 if (viaIDs[incLane] != "") {
740 foeIDs.push_back(viaIDs[incLane]);
741 }
742 }
743 incLanes += " " + incLane;
744 }
745 into.writeAttr(SUMO_ATTR_INCLANES, incLanes);
746 const std::vector<int>& foes = con.foeInternalLinks;
747 for (int foe : foes) {
748 foeIDs.push_back(internalLaneIDs[foe]);
749 }
750 into.writeAttr(SUMO_ATTR_INTLANES, joinToString(foeIDs, " "));
751 into.closeTag();
752 ret = true;
753 }
754 }
755 return ret;
756}
757
758
759void
761 bool includeInternal, ConnectionStyle style, bool geoAccuracy) {
762 assert(c.toEdge != 0);
764 into.writeAttr(SUMO_ATTR_FROM, from.getID());
768 if (style != TLL) {
769 if (c.mayDefinitelyPass) {
771 }
772 if (c.keepClear == KEEPCLEAR_FALSE) {
773 into.writeAttr<bool>(SUMO_ATTR_KEEP_CLEAR, false);
774 }
777 }
778 if (c.permissions != SVC_UNSPECIFIED) {
780 }
783 }
786 }
789 }
792 }
793 if (c.customShape.size() != 0) {
794 if (geoAccuracy) {
796 }
798 if (geoAccuracy) {
799 into.setPrecision();
800 }
801 }
802 if (c.uncontrolled != false) {
804 }
805 if (c.indirectLeft != false) {
807 }
808 if (c.edgeType != "") {
810 }
811 }
812 if (style != PLAIN) {
813 if (includeInternal) {
815 }
816 // set information about the controlling tl if any
817 if (c.tlID != "") {
820 if (c.tlLinkIndex2 >= 0) {
822 }
823 }
824 }
825 if (style != TLL) {
826 if (style == SUMONET) {
827 // write the direction information
828 LinkDirection dir = from.getToNode()->getDirection(&from, c.toEdge, OptionsCont::getOptions().getBool("lefthand"));
829 assert(dir != LinkDirection::NODIR);
830 into.writeAttr(SUMO_ATTR_DIR, toString(dir));
831 // write the state information
832 const LinkState linkState = from.getToNode()->getLinkState(
833 &from, c.toEdge, c.fromLane, c.toLane, c.mayDefinitelyPass, c.tlID);
834 into.writeAttr(SUMO_ATTR_STATE, linkState);
835 if (linkState == LINKSTATE_MINOR
838 const double visibilityDistance = OptionsCont::getOptions().getFloat("roundabouts.visibility-distance");
839 if (visibilityDistance != NBEdge::UNSPECIFIED_VISIBILITY_DISTANCE) {
840 into.writeAttr(SUMO_ATTR_VISIBILITY_DISTANCE, visibilityDistance);
841 }
842 }
843 }
846 }
847 }
848 c.writeParams(into);
849 into.closeTag();
850}
851
852
853bool
855 bool ret = false;
856 const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
857 for (const NBEdge* const from : n.getIncomingEdges()) {
858 for (const NBEdge::Connection& c : from->getConnections()) {
859 LinkDirection dir = n.getDirection(from, c.toEdge, lefthand);
860 assert(c.toEdge != 0);
861 if (c.haveVia) {
862 // internal split with optional signal
863 std::string tlID = "";
864 int linkIndex2 = NBConnection::InvalidTlIndex;
865 if (c.tlLinkIndex2 != NBConnection::InvalidTlIndex) {
866 linkIndex2 = c.tlLinkIndex2;
867 tlID = c.tlID;
868 }
869 writeInternalConnection(into, c.id, c.toEdge->getID(), c.internalLaneIndex, c.toLane, c.getInternalViaLaneID(), dir, tlID, linkIndex2, false, c.visibility);
870 writeInternalConnection(into, c.viaID, c.toEdge->getID(), c.internalViaLaneIndex, c.toLane, "", dir, "", NBConnection::InvalidTlIndex,
871 n.brakeForCrossingOnExit(c.toEdge, dir, c.indirectLeft));
872 } else {
873 // no internal split
874 writeInternalConnection(into, c.id, c.toEdge->getID(), c.internalLaneIndex, c.toLane, "", dir);
875 }
876 ret = true;
877 }
878 }
879 return ret;
880}
881
882
883void
885 const std::string& from, const std::string& to,
886 int fromLane, int toLane, const std::string& via,
887 LinkDirection dir,
888 const std::string& tlID, int linkIndex,
889 bool minor,
890 double visibility) {
892 into.writeAttr(SUMO_ATTR_FROM, from);
893 into.writeAttr(SUMO_ATTR_TO, to);
894 into.writeAttr(SUMO_ATTR_FROM_LANE, fromLane);
895 into.writeAttr(SUMO_ATTR_TO_LANE, toLane);
896 if (via != "") {
897 into.writeAttr(SUMO_ATTR_VIA, via);
898 }
899 if (tlID != "" && linkIndex != NBConnection::InvalidTlIndex) {
900 // used for the reverse direction of pedestrian crossings
901 into.writeAttr(SUMO_ATTR_TLID, tlID);
902 into.writeAttr(SUMO_ATTR_TLLINKINDEX, linkIndex);
903 }
904 into.writeAttr(SUMO_ATTR_DIR, dir);
905 into.writeAttr(SUMO_ATTR_STATE, ((via != "" || minor) ? "m" : "M"));
906 if (visibility != NBEdge::UNSPECIFIED_VISIBILITY_DISTANCE) {
908 }
909 into.closeTag();
910}
911
912
913void
914NWWriter_SUMO::writeRoundabouts(OutputDevice& into, const std::set<EdgeSet>& roundabouts,
915 const NBEdgeCont& ec) {
916 // make output deterministic
917 std::vector<std::vector<std::string> > edgeIDs;
918 for (std::set<EdgeSet>::const_iterator i = roundabouts.begin(); i != roundabouts.end(); ++i) {
919 std::vector<std::string> tEdgeIDs;
920 for (EdgeSet::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
921 // the edges may have been erased from NBEdgeCont but their pointers are still valid
922 // we verify their existance in writeRoundabout()
923 tEdgeIDs.push_back((*j)->getID());
924 }
925 std::sort(tEdgeIDs.begin(), tEdgeIDs.end());
926 edgeIDs.push_back(tEdgeIDs);
927 }
928 std::sort(edgeIDs.begin(), edgeIDs.end());
929 // write
930 for (std::vector<std::vector<std::string> >::const_iterator i = edgeIDs.begin(); i != edgeIDs.end(); ++i) {
931 writeRoundabout(into, *i, ec);
932 }
933 if (roundabouts.size() != 0) {
934 into.lf();
935 }
936}
937
938
939void
940NWWriter_SUMO::writeRoundabout(OutputDevice& into, const std::vector<std::string>& edgeIDs,
941 const NBEdgeCont& ec) {
942 std::vector<std::string> validEdgeIDs;
943 std::vector<std::string> invalidEdgeIDs;
944 std::vector<std::string> nodeIDs;
945 for (std::vector<std::string>::const_iterator i = edgeIDs.begin(); i != edgeIDs.end(); ++i) {
946 const NBEdge* edge = ec.retrieve(*i);
947 if (edge != nullptr) {
948 nodeIDs.push_back(edge->getToNode()->getID());
949 validEdgeIDs.push_back(edge->getID());
950 } else {
951 invalidEdgeIDs.push_back(*i);
952 }
953 }
954 std::sort(nodeIDs.begin(), nodeIDs.end());
955 if (validEdgeIDs.size() > 0) {
957 into.writeAttr(SUMO_ATTR_NODES, joinToString(nodeIDs, " "));
958 into.writeAttr(SUMO_ATTR_EDGES, joinToString(validEdgeIDs, " "));
959 into.closeTag();
960 if (invalidEdgeIDs.size() > 0) {
961 WRITE_WARNING("Writing incomplete roundabout. Edges: '"
962 + joinToString(invalidEdgeIDs, " ") + "' no longer exist'");
963 }
964 }
965}
966
967
968void
970 std::vector<double> sourceW = d.getSourceWeights();
972 std::vector<double> sinkW = d.getSinkWeights();
974 // write the head and the id of the district
976 if (d.getShape().size() > 0) {
978 }
979 // write all sources
980 const std::vector<NBEdge*>& sources = d.getSourceEdges();
981 for (int i = 0; i < (int)sources.size(); i++) {
982 // write the head and the id of the source
983 into.openTag(SUMO_TAG_TAZSOURCE).writeAttr(SUMO_ATTR_ID, sources[i]->getID()).writeAttr(SUMO_ATTR_WEIGHT, sourceW[i]);
984 into.closeTag();
985 }
986 // write all sinks
987 const std::vector<NBEdge*>& sinks = d.getSinkEdges();
988 for (int i = 0; i < (int)sinks.size(); i++) {
989 // write the head and the id of the sink
990 into.openTag(SUMO_TAG_TAZSINK).writeAttr(SUMO_ATTR_ID, sinks[i]->getID()).writeAttr(SUMO_ATTR_WEIGHT, sinkW[i]);
991 into.closeTag();
992 }
993 // write the tail
994 into.closeTag();
995}
996
997
998std::string
1000 double time = STEPS2TIME(steps);
1001 if (time == std::floor(time)) {
1002 return toString(int(time));
1003 } else {
1004 return toString(time);
1005 }
1006}
1007
1008void
1010 for (NBConnectionProhibits::const_iterator j = prohibitions.begin(); j != prohibitions.end(); j++) {
1011 NBConnection prohibited = (*j).first;
1012 const NBConnectionVector& prohibiting = (*j).second;
1013 for (NBConnectionVector::const_iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
1014 NBConnection prohibitor = *k;
1018 into.closeTag();
1019 }
1020 }
1021}
1022
1023
1024std::string
1026 return c.getFrom()->getID() + "->" + c.getTo()->getID();
1027}
1028
1029
1030void
1032 std::vector<NBTrafficLightLogic*> logics = tllCont.getComputed();
1033 for (NBTrafficLightLogic* logic : logics) {
1034 writeTrafficLight(into, logic);
1035 // only raise warnings on write instead of on compute (to avoid cluttering netedit)
1036 NBTrafficLightDefinition* def = tllCont.getDefinition(logic->getID(), logic->getProgramID());
1037 assert(def != nullptr);
1038 def->finalChecks();
1039 }
1040 if (logics.size() > 0) {
1041 into.lf();
1042 }
1043}
1044
1045
1046void
1049 into.writeAttr(SUMO_ATTR_ID, logic->getID());
1050 into.writeAttr(SUMO_ATTR_TYPE, logic->getType());
1052 into.writeAttr(SUMO_ATTR_OFFSET, logic->getOffset() == SUMOTime_MAX ? "begin" : writeSUMOTime(logic->getOffset()));
1053 // write the phases
1054 const bool varPhaseLength = logic->getType() != TrafficLightType::STATIC;
1055 for (const NBTrafficLightLogic::PhaseDefinition& phase : logic->getPhases()) {
1056 into.openTag(SUMO_TAG_PHASE);
1057 into.writeAttr(SUMO_ATTR_DURATION, writeSUMOTime(phase.duration));
1058 if (phase.duration < TIME2STEPS(10)) {
1059 into.writePadding(" ");
1060 }
1061 into.writeAttr(SUMO_ATTR_STATE, phase.state);
1062 if (varPhaseLength) {
1064 into.writeAttr(SUMO_ATTR_MINDURATION, writeSUMOTime(phase.minDur));
1065 }
1067 into.writeAttr(SUMO_ATTR_MAXDURATION, writeSUMOTime(phase.maxDur));
1068 }
1069 if (phase.earliestEnd != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
1070 into.writeAttr(SUMO_ATTR_EARLIEST_END, writeSUMOTime(phase.earliestEnd));
1071 }
1072 if (phase.latestEnd != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
1073 into.writeAttr(SUMO_ATTR_LATEST_END, writeSUMOTime(phase.latestEnd));
1074 }
1075 // NEMA attributes
1078 }
1080 into.writeAttr(SUMO_ATTR_YELLOW, writeSUMOTime(phase.yellow));
1081 }
1083 into.writeAttr(SUMO_ATTR_RED, writeSUMOTime(phase.red));
1084 }
1085 }
1086 if (phase.name != "") {
1088 }
1089 if (phase.next.size() > 0) {
1090 into.writeAttr(SUMO_ATTR_NEXT, phase.next);
1091 }
1092 into.closeTag();
1093 }
1094 // write params
1095 logic->writeParams(into);
1096 into.closeTag();
1097}
1098
1099
1100void
1102 if (stopOffset.isDefined()) {
1103 const std::string ss_vclasses = getVehicleClassNames(stopOffset.getPermissions());
1104 if (ss_vclasses.length() == 0) {
1105 // This stopOffset would have no effect...
1106 return;
1107 }
1109 const std::string ss_exceptions = getVehicleClassNames(~stopOffset.getPermissions());
1110 if (ss_vclasses.length() <= ss_exceptions.length()) {
1111 into.writeAttr(SUMO_ATTR_VCLASSES, ss_vclasses);
1112 } else {
1113 if (ss_exceptions.length() == 0) {
1114 into.writeAttr(SUMO_ATTR_VCLASSES, "all");
1115 } else {
1116 into.writeAttr(SUMO_ATTR_EXCEPTIONS, ss_exceptions);
1117 }
1118 }
1119 into.writeAttr(SUMO_ATTR_VALUE, stopOffset.getOffset());
1120 into.closeTag();
1121 }
1122}
1123
1124
1125/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
#define WRITE_WARNING(msg)
Definition MsgHandler.h:286
#define TL(string)
Definition MsgHandler.h:304
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:42
@ KEEPCLEAR_FALSE
Definition NBCont.h:59
#define STEPS2TIME(x)
Definition SUMOTime.h:55
#define SUMOTime_MAX
Definition SUMOTime.h:34
#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
LaneSpreadFunction
Numbers representing special SUMO-XML-attribute values Information how the edge's lateral offset shal...
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_ROUNDABOUT
Roundabout type of node.
@ 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_ROUTINGTYPE
@ SUMO_ATTR_EARLIEST_END
The minimum time within the cycle for switching (for coordinated actuation).
int gPrecisionGeo
Definition StdDefs.cpp:29
T MIN2(T a, T b)
Definition StdDefs.h:80
T MAX2(T a, T b)
Definition StdDefs.h:86
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:289
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
NBEdge * getTo() const
returns the to-edge (end of the connection)
A container for districts.
std::map< std::string, NBDistrict * >::const_iterator end() const
Returns the pointer to the end of the stored districts.
std::map< std::string, NBDistrict * >::const_iterator begin() const
Returns the pointer to the begin 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 * > & getSinkEdges() const
Returns the sinks.
Definition NBDistrict.h:204
const std::vector< NBEdge * > & getSourceEdges() const
Returns the sources.
Definition NBDistrict.h:188
Storage for edges, including some functionality operating on multiple edges.
Definition NBEdgeCont.h:59
const std::set< EdgeSet > getRoundabouts() const
Returns the determined roundabouts.
std::map< std::string, NBEdge * >::const_iterator begin() const
Returns the pointer to the begin of the stored edges.
Definition NBEdgeCont.h:171
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
std::map< std::string, NBEdge * >::const_iterator end() const
Returns the pointer to the end of the stored edges.
Definition NBEdgeCont.h:178
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
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition NBEdge.h:1047
@ ROUNDABOUT
Definition NBEdge.h:387
double getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn't set.
Definition NBEdge.h:608
NBNode * getToNode() const
Returns the destination node of the edge.
Definition NBEdge.h:552
static const double UNSPECIFIED_FRICTION
unspecified lane friction
Definition NBEdge.h:355
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition NBEdge.h:789
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge's lanes' lateral offset is computed.
Definition NBEdge.cpp:1021
bool isBidiRail(bool ignoreSpread=false) const
whether this edge is part of a bidirectional railway
Definition NBEdge.cpp:772
bool hasLoadedLength() const
Returns whether a length was set explicitly.
Definition NBEdge.h:618
const std::string & getRoutingType() const
return whether this edge should be a bidi edge
Definition NBEdge.h:1446
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
Definition NBEdge.h:736
const std::string & getID() const
Definition NBEdge.h:1551
double getDistance() const
get distance
Definition NBEdge.h:685
static const double UNSPECIFIED_LOADED_LENGTH
no length override given
Definition NBEdge.h:364
const StopOffset & getEdgeStopOffset() const
Returns the stopOffset to the end of the edge.
Definition NBEdge.cpp:4393
int getNumLanes() const
Returns the number of lanes.
Definition NBEdge.h:526
std::vector< Connection > getConnectionsFromLane(int lane, const NBEdge *to=nullptr, int toLane=-1) const
Returns connections from a given lane.
Definition NBEdge.cpp:1310
static const double UNSPECIFIED_CONTPOS
unspecified internal junction position
Definition NBEdge.h:358
static const double UNSPECIFIED_VISIBILITY_DISTANCE
unspecified foe visibility for connections
Definition NBEdge.h:361
std::string getLaneID(int lane) const
get lane ID
Definition NBEdge.cpp:4178
static const double UNSPECIFIED_SPEED
unspecified lane speed
Definition NBEdge.h:352
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build).
Definition NBEdge.cpp:2157
const std::string & getTypeID() const
get ID of type
Definition NBEdge.h:1187
const std::string & getStreetName() const
Returns the street name of this edge.
Definition NBEdge.h:675
const NBEdge * getBidiEdge() const
Definition NBEdge.h:1537
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition NBEdge.h:545
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition NBEdge.cpp:4169
bool hasDefaultGeometry() const
Returns whether the geometry consists only of the node positions.
Definition NBEdge.cpp:619
int getPriority() const
Returns the priority of the edge.
Definition NBEdge.h:533
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition NBEdge.h:346
double getEndOffset() const
Returns the offset to the destination node.
Definition NBEdge.h:695
static const double UNSPECIFIED_OFFSET
unspecified lane offset
Definition NBEdge.h:349
bool isMacroscopicConnector() const
Returns whether this edge was marked as a macroscopic connector.
Definition NBEdge.h:1142
double getFinalLength() const
get length that will be assigned to the lanes in the final network
Definition NBEdge.cpp:4884
static void interpretLaneID(const std::string &lane_id, std::string &edge_id, int &index)
parses edge-id and index from lane-id
Instance responsible for building networks.
NBNodeCont & getNodeCont()
Returns a reference to the node container.
NBEdgeCont & getEdgeCont()
NBDistrictCont & getDistrictCont()
Returns a reference the districts container.
NBTypeCont & getTypeCont()
Returns a reference to the type container.
NBTrafficLightLogicCont & getTLLogicCont()
Returns a reference to the traffic light logics container.
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:2498
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:2583
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:4111
std::vector< Crossing * > getCrossings() const
return this junctions pedestrian crossings
Definition NBNode.cpp:3098
const std::vector< WalkingArea > & getWalkingAreas() const
return this junctions pedestrian walking areas
Definition NBNode.h:764
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.
TrafficLightType getType() const
get the algorithm type (static etc..)
const std::string & getProgramID() const
Returns the ProgramID.
const std::vector< PhaseDefinition > & getPhases() const
Returns the phases.
void writeEdgeTypes(OutputDevice &into, const std::set< std::string > &typeIDs=std::set< std::string >()) const
writes all EdgeTypes (and their lanes) as XML
static void writePositionLong(const Position &pos, OutputDevice &dev)
Writes the given position to device in long format (one attribute per dimension).
Definition NWFrame.cpp:216
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 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 void writeEdge(OutputDevice &into, const NBEdge &e, bool noNames, LaneSpreadFunction defaultSpread)
Writes an edge (<edge ...).
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.
Static storage of an output device and its base (abstract) implementation.
void lf()
writes a line feed if applicable
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
OutputDevice & writePadding(const std::string &val)
writes padding (ignored for binary output)
void close()
Closes the device and removes it from the dictionary.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
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.
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.
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 reverse() const
reverse position vector
PositionVector getSubpart(double beginOffset, double endOffset) const
get subpart of a position vector
static StringBijection< LaneSpreadFunction > LaneSpreadFunctions
lane spread functions
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)
*brief user defined string literal for JSON values *sa std::size_t n
Definition json.hpp:21899
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:298
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:104
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:310
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