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(), ec);
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
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 }
666 for (auto c : crossings) {
667 intLanes.push_back(c->id + "_0");
668 }
669 }
670 into.writeAttr(SUMO_ATTR_INTLANES, intLanes);
671 // close writing
673 // write optional radius
676 }
677 // specify whether a custom shape was used
678 if (n.hasCustomShape()) {
680 }
683 }
685 into.writeAttr<std::string>(SUMO_ATTR_FRINGE, toString(n.getFringeType()));
686 }
689 }
690 if (n.getName() != "") {
692 }
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 // the edges may have been erased from NBEdgeCont but their pointers are still valid so we need to check
1011 for (NBConnectionProhibits::const_iterator j = prohibitions.begin(); j != prohibitions.end(); j++) {
1012 NBConnection prohibited = (*j).first;
1013 if (ec.retrieve(prohibited.getFrom()->getID()) == nullptr
1014 || ec.retrieve(prohibited.getTo()->getID()) == nullptr) {
1015 continue;
1016 }
1017 const NBConnectionVector& prohibiting = (*j).second;
1018 for (NBConnectionVector::const_iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
1019 NBConnection prohibitor = *k;
1020 if (ec.retrieve(prohibitor.getFrom()->getID()) == nullptr
1021 || ec.retrieve(prohibitor.getTo()->getID()) == nullptr) {
1022 continue;
1023 }
1027 into.closeTag();
1028 }
1029 }
1030}
1031
1032
1033std::string
1035 return c.getFrom()->getID() + "->" + c.getTo()->getID();
1036}
1037
1038
1039void
1041 std::vector<NBTrafficLightLogic*> logics = tllCont.getComputed();
1042 for (NBTrafficLightLogic* logic : logics) {
1043 writeTrafficLight(into, logic);
1044 // only raise warnings on write instead of on compute (to avoid cluttering netedit)
1045 NBTrafficLightDefinition* def = tllCont.getDefinition(logic->getID(), logic->getProgramID());
1046 assert(def != nullptr);
1047 def->finalChecks();
1048 }
1049 if (logics.size() > 0) {
1050 into.lf();
1051 }
1052}
1053
1054
1055void
1058 into.writeAttr(SUMO_ATTR_ID, logic->getID());
1059 into.writeAttr(SUMO_ATTR_TYPE, logic->getType());
1061 into.writeAttr(SUMO_ATTR_OFFSET, logic->getOffset() == SUMOTime_MAX ? "begin" : writeSUMOTime(logic->getOffset()));
1062 // write the phases
1063 const bool varPhaseLength = logic->getType() != TrafficLightType::STATIC;
1064 for (const NBTrafficLightLogic::PhaseDefinition& phase : logic->getPhases()) {
1065 into.openTag(SUMO_TAG_PHASE);
1066 into.writeAttr(SUMO_ATTR_DURATION, writeSUMOTime(phase.duration));
1067 if (phase.duration < TIME2STEPS(10)) {
1068 into.writePadding(" ");
1069 }
1070 into.writeAttr(SUMO_ATTR_STATE, phase.state);
1071 if (varPhaseLength) {
1073 into.writeAttr(SUMO_ATTR_MINDURATION, writeSUMOTime(phase.minDur));
1074 }
1076 into.writeAttr(SUMO_ATTR_MAXDURATION, writeSUMOTime(phase.maxDur));
1077 }
1078 if (phase.earliestEnd != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
1079 into.writeAttr(SUMO_ATTR_EARLIEST_END, writeSUMOTime(phase.earliestEnd));
1080 }
1081 if (phase.latestEnd != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
1082 into.writeAttr(SUMO_ATTR_LATEST_END, writeSUMOTime(phase.latestEnd));
1083 }
1084 // NEMA attributes
1087 }
1089 into.writeAttr(SUMO_ATTR_YELLOW, writeSUMOTime(phase.yellow));
1090 }
1092 into.writeAttr(SUMO_ATTR_RED, writeSUMOTime(phase.red));
1093 }
1094 }
1095 if (phase.name != "") {
1097 }
1098 if (phase.next.size() > 0) {
1099 into.writeAttr(SUMO_ATTR_NEXT, phase.next);
1100 }
1101 into.closeTag();
1102 }
1103 // write params
1104 logic->writeParams(into);
1105 into.closeTag();
1106}
1107
1108
1109void
1111 if (stopOffset.isDefined()) {
1112 const std::string ss_vclasses = getVehicleClassNames(stopOffset.getPermissions());
1113 if (ss_vclasses.length() == 0) {
1114 // This stopOffset would have no effect...
1115 return;
1116 }
1118 const std::string ss_exceptions = getVehicleClassNames(~stopOffset.getPermissions());
1119 if (ss_vclasses.length() <= ss_exceptions.length()) {
1120 into.writeAttr(SUMO_ATTR_VCLASSES, ss_vclasses);
1121 } else {
1122 if (ss_exceptions.length() == 0) {
1123 into.writeAttr(SUMO_ATTR_VCLASSES, "all");
1124 } else {
1125 into.writeAttr(SUMO_ATTR_EXCEPTIONS, ss_exceptions);
1126 }
1127 }
1128 into.writeAttr(SUMO_ATTR_VALUE, stopOffset.getOffset());
1129 into.closeTag();
1130 }
1131}
1132
1133
1134/****************************************************************************/
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
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: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
FringeType getFringeType() const
Returns fringe type.
Definition NBNode.h:305
SumoXMLNodeType getType() const
Returns the type of this node.
Definition NBNode.h:285
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, LinkDirection dir, bool indirect) const
whether a connection to the given edge must brake for a crossing when leaving the intersection
Definition NBNode.cpp:2167
bool hasCustomShape() const
return whether the shape was set by the user
Definition NBNode.h:601
std::vector< Crossing * > getCrossings() const
return this junctions pedestrian crossings
Definition NBNode.cpp:3098
const std::string & getName() const
Returns intersection name.
Definition NBNode.h:315
bool writeLogic(OutputDevice &into) const
writes the XML-representation of the logic as a bitset-logic XML representation
Definition NBNode.cpp:1131
const Position & getPosition() const
Definition NBNode.h:260
const PositionVector & getShape() const
retrieve the junction shape
Definition NBNode.cpp:2783
RoundaboutType getRoundaboutType() const
Returns roundabout type.
Definition NBNode.h:310
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: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 writeProhibitions(OutputDevice &into, const NBConnectionProhibits &prohibitions, const NBEdgeCont &ec)
writes the given prohibitions
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 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 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
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
T get(const std::string &str) const
get key
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)
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