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-2026 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_DlrNavteq.h"
44#include "NWWriter_SUMO.h"
45
46
47//#define DEBUG_OPPOSITE_INTERNAL
48
49// ===========================================================================
50// method definitions
51// ===========================================================================
52// ---------------------------------------------------------------------------
53// static methods
54// ---------------------------------------------------------------------------
55void
57 // check whether a sumo net-file shall be generated
58 if (!oc.isSet("output-file")) {
59 return;
60 }
61 OutputDevice& device = OutputDevice::getDevice(oc.getString("output-file"));
62 std::map<SumoXMLAttr, std::string> attrs;
64 if (oc.getBool("lefthand") != oc.getBool("flip-y-axis")) {
65 attrs[SUMO_ATTR_LEFTHAND] = "true";
66 } else if (oc.getBool("lefthand")) {
67 // network was flipped, correct written link directions
69 OptionsCont::getOptions().set("lefthand", "false");
70 }
71 LaneSpreadFunction defaultSpread = SUMOXMLDefinitions::LaneSpreadFunctions.get(oc.getString("default.spreadtype"));
72 const int cornerDetail = oc.getInt("junctions.corner-detail");
73 if (cornerDetail > 0) {
74 attrs[SUMO_ATTR_CORNERDETAIL] = toString(cornerDetail);
75 }
76 if (!oc.isDefault("junctions.internal-link-detail")) {
77 attrs[SUMO_ATTR_LINKDETAIL] = toString(oc.getInt("junctions.internal-link-detail"));
78 }
79 if (oc.getBool("rectangular-lane-cut")) {
80 attrs[SUMO_ATTR_RECTANGULAR_LANE_CUT] = "true";
81 }
82 if (oc.getBool("crossings.guess") || oc.getBool("walkingareas")) {
83 attrs[SUMO_ATTR_WALKINGAREAS] = "true";
84 }
85 if (oc.getFloat("junctions.limit-turn-speed") > 0) {
86 attrs[SUMO_ATTR_LIMIT_TURN_SPEED] = toString(oc.getFloat("junctions.limit-turn-speed"));
87 }
88 if (!oc.isDefault("check-lane-foes.all")) {
89 attrs[SUMO_ATTR_CHECKLANEFOES_ALL] = toString(oc.getBool("check-lane-foes.all"));
90 }
91 if (!oc.isDefault("check-lane-foes.roundabout")) {
92 attrs[SUMO_ATTR_CHECKLANEFOES_ROUNDABOUT] = toString(oc.getBool("check-lane-foes.roundabout"));
93 }
94 if (!oc.isDefault("tls.ignore-internal-junction-jam")) {
95 attrs[SUMO_ATTR_TLS_IGNORE_INTERNAL_JUNCTION_JAM] = toString(oc.getBool("tls.ignore-internal-junction-jam"));
96 }
97 if (defaultSpread != LaneSpreadFunction::RIGHT) {
98 attrs[SUMO_ATTR_SPREADTYPE] = oc.getString("default.spreadtype");
99 }
100 if (oc.exists("geometry.avoid-overlap") && !oc.getBool("geometry.avoid-overlap")) {
101 attrs[SUMO_ATTR_AVOID_OVERLAP] = toString(oc.getBool("geometry.avoid-overlap"));
102 }
103 if (oc.exists("junctions.higher-speed") && oc.getBool("junctions.higher-speed")) {
104 attrs[SUMO_ATTR_HIGHER_SPEED] = toString(oc.getBool("junctions.higher-speed"));
105 }
106 if (oc.exists("internal-junctions.vehicle-width") && !oc.isDefault("internal-junctions.vehicle-width")) {
107 attrs[SUMO_ATTR_INTERNAL_JUNCTIONS_VEHICLE_WIDTH] = toString(oc.getFloat("internal-junctions.vehicle-width"));
108 }
109 if (!oc.isDefault("junctions.minimal-shape")) {
110 attrs[SUMO_ATTR_JUNCTIONS_MINIMAL_SHAPE] = toString(oc.getBool("junctions.minimal-shape"));
111 }
112 if (!oc.isDefault("junctions.endpoint-shape")) {
113 attrs[SUMO_ATTR_JUNCTIONS_ENDPOINT_SHAPE] = toString(oc.getBool("junctions.endpoint-shape"));
114 }
115 device.writeXMLHeader("net", "net_file.xsd", attrs); // street names may contain non-ascii chars
116 device.lf();
117 // get involved container
118 const NBNodeCont& nc = nb.getNodeCont();
119 const NBEdgeCont& ec = nb.getEdgeCont();
120 const NBDistrictCont& dc = nb.getDistrictCont();
121
122 // write network offsets and projection
124
125 // write edge types and restrictions
126 std::set<std::string> usedTypes = ec.getUsedTypes();
127 nb.getTypeCont().writeEdgeTypes(device, usedTypes);
128
129 // write inner lanes
130 if (!oc.getBool("no-internal-links")) {
131 bool hadAny = false;
132 for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
133 hadAny |= writeInternalEdges(device, ec, *(*i).second);
134 }
135 if (hadAny) {
136 device.lf();
137 }
138 }
139
140 // write edges with lanes and connected edges
141 bool noNames = !oc.getBool("output.street-names");
142 for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
143 writeEdge(device, *(*i).second, noNames, defaultSpread);
144 }
145 device.lf();
146
147 // write tls logics
149
150 // write the nodes (junctions)
151 for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
152 writeJunction(device, *(*i).second);
153 }
154 device.lf();
155 const bool includeInternal = !oc.getBool("no-internal-links");
156 if (includeInternal) {
157 // ... internal nodes if not unwanted
158 bool hadAny = false;
159 for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
160 hadAny |= writeInternalNodes(device, *(*i).second);
161 }
162 if (hadAny) {
163 device.lf();
164 }
165 }
166
167 // write the successors of lanes
168 int numConnections = 0;
169 for (std::map<std::string, NBEdge*>::const_iterator it_edge = ec.begin(); it_edge != ec.end(); it_edge++) {
170 NBEdge* from = it_edge->second;
171 const std::vector<NBEdge::Connection>& connections = from->getConnections();
172 numConnections += (int)connections.size();
173 for (const NBEdge::Connection& con : connections) {
174 writeConnection(device, *from, con, includeInternal);
175 }
176 }
177 if (numConnections > 0) {
178 device.lf();
179 }
180 if (includeInternal) {
181 // ... internal successors if not unwanted
182 bool hadAny = false;
183 for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
184 hadAny |= writeInternalConnections(device, *(*i).second);
185 }
186 if (hadAny) {
187 device.lf();
188 }
189 }
190 for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
191 NBNode* node = (*i).second;
192 // write connections from pedestrian crossings
193 std::vector<NBNode::Crossing*> crossings = node->getCrossings();
194 for (auto c : crossings) {
195 NWWriter_SUMO::writeInternalConnection(device, c->id, c->nextWalkingArea, 0, 0, "", LinkDirection::STRAIGHT, c->tlID, c->tlLinkIndex2);
196 }
197 // write connections from pedestrian walking areas
198 for (const NBNode::WalkingArea& wa : node->getWalkingAreas()) {
199 for (const std::string& cID : wa.nextCrossings) {
200 const NBNode::Crossing& nextCrossing = *node->getCrossing(cID);
201 // connection to next crossing (may be tls-controlled)
203 device.writeAttr(SUMO_ATTR_FROM, wa.id);
204 device.writeAttr(SUMO_ATTR_TO, cID);
206 device.writeAttr(SUMO_ATTR_TO_LANE, 0);
207 if (nextCrossing.tlID != "") {
208 device.writeAttr(SUMO_ATTR_TLID, nextCrossing.tlID);
209 assert(nextCrossing.tlLinkIndex >= 0);
210 device.writeAttr(SUMO_ATTR_TLLINKINDEX, nextCrossing.tlLinkIndex);
211 }
214 device.closeTag();
215 }
216 // optional connections from/to sidewalk
217 std::string edgeID;
218 int laneIndex;
219 for (const std::string& sw : wa.nextSidewalks) {
220 NBHelpers::interpretLaneID(sw, edgeID, laneIndex);
221 NWWriter_SUMO::writeInternalConnection(device, wa.id, edgeID, 0, laneIndex, "");
222 }
223 for (const std::string& sw : wa.prevSidewalks) {
224 NBHelpers::interpretLaneID(sw, edgeID, laneIndex);
225 NWWriter_SUMO::writeInternalConnection(device, edgeID, wa.id, laneIndex, 0, "");
226 }
227 }
228 }
229
230 // write loaded prohibitions
231 for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
232 writeProhibitions(device, i->second->getProhibitions(), ec);
233 }
234
235 // write roundabout information
236 writeRoundabouts(device, ec.getRoundabouts(), ec);
237
238 // write the districts
239 if (dc.size() != 0 && oc.isDefault("taz-output")) {
240 WRITE_WARNING(TL("Embedding TAZ-data inside the network is deprecated. Use option --taz-output instead"));
241 for (std::map<std::string, NBDistrict*>::const_iterator i = dc.begin(); i != dc.end(); i++) {
242 writeDistrict(device, *(*i).second);
243 }
244 device.lf();
245 }
246 device.close();
247}
248
249
250std::string
251NWWriter_SUMO::getOppositeInternalID(const NBEdgeCont& ec, const NBEdge* from, const NBEdge::Connection& con, double& oppositeLength) {
252 const NBEdge::Lane& succ = con.toEdge->getLanes()[con.toLane];
253 const NBEdge::Lane& pred = from->getLanes()[con.fromLane];
254 const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
255 if (succ.oppositeID != "" && succ.oppositeID != "-" && pred.oppositeID != "" && pred.oppositeID != "-") {
256#ifdef DEBUG_OPPOSITE_INTERNAL
257 std::cout << "getOppositeInternalID con=" << con.getDescription(from) << " (" << con.getInternalLaneID() << ")\n";
258#endif
259 // find the connection that connects succ.oppositeID to pred.oppositeID
260 const NBEdge* succOpp = ec.retrieve(succ.oppositeID.substr(0, succ.oppositeID.rfind("_")));
261 const NBEdge* predOpp = ec.retrieve(pred.oppositeID.substr(0, pred.oppositeID.rfind("_")));
262 assert(succOpp != 0);
263 assert(predOpp != 0);
264 const std::vector<NBEdge::Connection>& connections = succOpp->getConnections();
265 for (std::vector<NBEdge::Connection>::const_iterator it_c = connections.begin(); it_c != connections.end(); it_c++) {
266 const NBEdge::Connection& conOpp = *it_c;
267 if (succOpp != from // turnaround
268 && predOpp == conOpp.toEdge
269 && succOpp->getLaneID(conOpp.fromLane) == succ.oppositeID
270 && predOpp->getLaneID(conOpp.toLane) == pred.oppositeID
271 && from->getToNode()->getDirection(from, con.toEdge, lefthand) == LinkDirection::STRAIGHT
272 && from->getToNode()->getDirection(succOpp, predOpp, lefthand) == LinkDirection::STRAIGHT
273 ) {
274#ifdef DEBUG_OPPOSITE_INTERNAL
275 std::cout << " found " << conOpp.getInternalLaneID() << "\n";
276#endif
277 oppositeLength = conOpp.length;
278 return conOpp.getInternalLaneID();
279 } else {
280 /*
281 #ifdef DEBUG_OPPOSITE_INTERNAL
282 std::cout << " rejected " << conOpp.getInternalLaneID()
283 << "\n succ.oppositeID=" << succ.oppositeID
284 << "\n succOppLane=" << succOpp->getLaneID(conOpp.fromLane)
285 << "\n pred.oppositeID=" << pred.oppositeID
286 << "\n predOppLane=" << predOpp->getLaneID(conOpp.toLane)
287 << "\n predOpp=" << predOpp->getID()
288 << "\n conOppTo=" << conOpp.toEdge->getID()
289 << "\n len1=" << con.shape.length()
290 << "\n len2=" << conOpp.shape.length()
291 << "\n";
292 #endif
293 */
294 }
295 }
296 return "";
297 } else {
298 return "";
299 }
300}
301
302
303bool
305 bool ret = false;
306 const EdgeVector& incoming = n.getIncomingEdges();
307 // first pass: determine opposite internal edges and average their length
308 std::map<std::string, std::string> oppositeLaneID;
309 std::map<std::string, double> oppositeLengths;
310 for (NBEdge* e : incoming) {
311 for (const NBEdge::Connection& c : e->getConnections()) {
312 double oppositeLength = 0;
313 const std::string op = getOppositeInternalID(ec, e, c, oppositeLength);
314 oppositeLaneID[c.getInternalLaneID()] = op;
315 if (op != "") {
316 oppositeLengths[c.id] = oppositeLength;
317 }
318 }
319 }
320 if (oppositeLengths.size() > 0) {
321 for (NBEdge* e : incoming) {
322 for (NBEdge::Connection& c : e->getConnections()) {
323 if (oppositeLengths.count(c.id) > 0) {
324 c.length = (c.length + oppositeLengths[c.id]) / 2;
325 }
326 }
327 }
328 }
329
330 for (NBEdge* e : incoming) {
331 const std::vector<NBEdge::Connection>& elv = e->getConnections();
332 if (elv.size() > 0) {
333 bool haveVia = false;
334 std::string edgeID = "";
335 double bidiLength = -1;
336 // second pass: write non-via edges
337 for (const NBEdge::Connection& k : elv) {
338 if (k.toEdge == nullptr) {
339 assert(false); // should never happen. tell me when it does
340 continue;
341 }
342 if (edgeID != k.id) {
343 if (edgeID != "") {
344 // close the previous edge
345 into.closeTag();
346 }
347 edgeID = k.id;
349 into.writeAttr(SUMO_ATTR_ID, edgeID);
351 if (k.edgeType != "") {
352 into.writeAttr(SUMO_ATTR_TYPE, k.edgeType);
353 }
354 bidiLength = -1;
355 if (e->getBidiEdge() && k.toEdge->getBidiEdge() &&
356 e != k.toEdge->getTurnDestination(true)) {
357 const std::string bidiEdge = getInternalBidi(e, k, bidiLength);
358 if (bidiEdge != "") {
359 into.writeAttr(SUMO_ATTR_BIDI, bidiEdge);
360 }
361 }
362 // open a new edge
363 }
364 // to avoid changing to an internal lane which has a successor
365 // with the wrong permissions we need to inherit them from the successor
366 const NBEdge::Lane& successor = k.toEdge->getLanes()[k.toLane];
367 SVCPermissions permissions = (k.permissions != SVC_UNSPECIFIED) ? k.permissions : (
368 successor.permissions & e->getPermissions(k.fromLane));
369 SVCPermissions changeLeft = k.changeLeft != SVC_UNSPECIFIED ? k.changeLeft : SVCAll;
370 SVCPermissions changeRight = k.changeRight != SVC_UNSPECIFIED ? k.changeRight : SVCAll;
371 const double width = e->getInternalLaneWidth(n, k, successor, false);
372 const double length = bidiLength > 0 ? bidiLength : k.length;
373 writeLane(into, k.getInternalLaneID(), k.vmax, k.friction,
374 permissions, successor.preferred,
375 changeLeft, changeRight,
377 StopOffset(), width, k.shape, &k,
378 length, k.internalLaneIndex, oppositeLaneID[k.getInternalLaneID()], "");
379 haveVia = haveVia || k.haveVia;
380 }
381 ret = true;
382 into.closeTag(); // close the last edge
383 // third pass: write via edges
384 if (haveVia) {
385 std::string viaEdgeID = "";
386 for (const NBEdge::Connection& k : elv) {
387 if (!k.haveVia) {
388 continue;
389 }
390 if (k.toEdge == nullptr) {
391 assert(false); // should never happen. tell me when it does
392 continue;
393 }
394 if (viaEdgeID != k.viaID) {
395 if (viaEdgeID != "") {
396 // close the previous edge
397 into.closeTag();
398 }
399 viaEdgeID = k.viaID;
400 // open a new edge
402 into.writeAttr(SUMO_ATTR_ID, viaEdgeID);
404 if (k.edgeType != "") {
405 into.writeAttr(SUMO_ATTR_TYPE, k.edgeType);
406 }
407 }
408 const NBEdge::Lane& successor = k.toEdge->getLanes()[k.toLane];
409 SVCPermissions permissions = (k.permissions != SVC_UNSPECIFIED) ? k.permissions : (
410 successor.permissions & e->getPermissions(k.fromLane));
411 const double width = e->getInternalLaneWidth(n, k, successor, true);
412 writeLane(into, k.getInternalViaLaneID(), k.vmax, k.friction, permissions, successor.preferred,
413 SVCAll, SVCAll, // #XXX todo
415 StopOffset(), width, k.viaShape, &k,
416 MAX2(k.viaLength, POSITION_EPS), // microsim needs positive length
417 k.internalViaLaneIndex, "", "");
418 }
419 into.closeTag();
420 }
421 }
422 }
423 // write pedestrian crossings
424 const double crossingSpeed = OptionsCont::getOptions().getFloat("default.crossing-speed");
425 for (const NBNode::Crossing* c : n.getCrossings()) {
427 into.writeAttr(SUMO_ATTR_CROSSING_EDGES, c->edges);
428 writeLane(into, c->id + "_0", crossingSpeed, NBEdge::UNSPECIFIED_FRICTION, SVC_PEDESTRIAN, 0, SVCAll, SVCAll,
430 StopOffset(), c->width, c->shape, c,
431 MAX2(c->shape.length(), POSITION_EPS), 0, "", "", false, c->customShape.size() != 0, c->outlineShape);
432 into.closeTag();
433 }
434 // write pedestrian walking areas
435 const double walkingareaSpeed = OptionsCont::getOptions().getFloat("default.walkingarea-speed");
436 for (const NBNode::WalkingArea& wa : n.getWalkingAreas()) {
438 writeLane(into, wa.id + "_0", walkingareaSpeed, NBEdge::UNSPECIFIED_FRICTION, SVC_PEDESTRIAN, 0, SVCAll, SVCAll,
440 StopOffset(), wa.width, wa.shape, nullptr, wa.length, 0, "", "", false, wa.hasCustomShape);
441 into.closeTag();
442 }
443 return ret;
444}
445
446
447std::string
448NWWriter_SUMO::getInternalBidi(const NBEdge* e, const NBEdge::Connection& k, double& length) {
449 const NBEdge* fromBidi = e->getTurnDestination(true);
450 const NBEdge* toBidi = k.toEdge->getTurnDestination(true);
451 const std::vector<NBEdge::Connection> cons = toBidi->getConnectionsFromLane(-1, fromBidi, -1);
452 if (cons.size() > 0) {
453 if (e->getNumLanes() == 1 && k.toEdge->getNumLanes() == 1 && fromBidi->getNumLanes() == 1 && toBidi->getNumLanes() == 1) {
454 length = (k.length + cons.back().length) / 2;
455 return cons.back().id;
456 }
457 // do a more careful check in case there are parallel internal edges
458 // note: k is the first connection with the new id
459 for (const NBEdge::Connection& c : e->getConnections()) {
460 if (c.id == k.id) {
461 PositionVector rShape = c.shape.reverse();
462 for (const NBEdge::Connection& k2 : cons) {
463 if (k2.shape.almostSame(rShape, POSITION_EPS)) {
464 length = (c.length + k2.length) / 2;
465 return k2.id;
466 }
467 }
468 }
469 }
470 } else {
471 WRITE_WARNINGF(TL("Could not find bidi-connection for edge '%'"), k.id)
472 }
473 return "";
474}
475
476void
477NWWriter_SUMO::writeEdge(OutputDevice& into, const NBEdge& e, bool noNames, LaneSpreadFunction defaultSpread) {
478 // write the edge's begin
482 if (!noNames && e.getStreetName() != "") {
484 }
486 if (e.getTypeID() != "") {
488 }
489 if (e.getRoutingType() != "") {
491 }
492 if (e.isMacroscopicConnector()) {
494 }
495 // write the spread type if not default ("right")
496 if (e.getLaneSpreadFunction() != defaultSpread) {
498 }
499 if (e.hasLoadedLength()) {
501 }
502 if (!e.hasDefaultGeometry()) {
504 }
505 if (e.getEdgeStopOffset().isDefined()) {
507 }
508 if (e.getBidiEdge()) {
510 }
511 if (e.getDistance() != 0) {
513 }
514
515 // write the lanes
516 const std::vector<NBEdge::Lane>& lanes = e.getLanes();
517
518 double length = e.getFinalLength();
519 if (e.getBidiEdge() != nullptr) {
520 length = (length + e.getBidiEdge()->getFinalLength()) / 2;
521 }
522 double startOffset = e.isBidiRail() ? e.getTurnDestination(true)->getEndOffset() : 0;
523 for (int i = 0; i < (int) lanes.size(); i++) {
524 const NBEdge::Lane& l = lanes[i];
525 StopOffset stopOffset;
526 if (l.laneStopOffset != e.getEdgeStopOffset()) {
527 stopOffset = l.laneStopOffset;
528 }
529 writeLane(into, e.getLaneID(i), l.speed, l.friction,
532 startOffset, l.endOffset,
533 stopOffset, l.width, l.shape, &l,
534 length, i, l.oppositeID, l.type, l.accelRamp, l.customShape.size() > 0);
535 }
536 // close the edge
537 e.writeParams(into);
538 into.closeTag();
539}
540
541
542void
543NWWriter_SUMO::writeLane(OutputDevice& into, const std::string& lID,
544 double speed, double friction,
545 SVCPermissions permissions, SVCPermissions preferred,
546 SVCPermissions changeLeft, SVCPermissions changeRight,
547 double startOffset, double endOffset,
548 const StopOffset& stopOffset, double width, PositionVector shape,
549 const Parameterised* params, double length, int index,
550 const std::string& oppositeID,
551 const std::string& type,
552 bool accelRamp, bool customShape,
553 const PositionVector& outlineShape) {
554 // output the lane's attributes
556 // the first lane of an edge will be the depart lane
557 into.writeAttr(SUMO_ATTR_INDEX, index);
558 // write the list of allowed/disallowed vehicle classes
559 if (permissions != SVC_UNSPECIFIED) {
560 writePermissions(into, permissions);
561 }
562 writePreferences(into, preferred);
563 // some further information
564 into.writeAttr(SUMO_ATTR_SPEED, MAX2(0.0, speed));
565 if (friction != NBEdge::UNSPECIFIED_FRICTION) {
566 into.writeAttr(SUMO_ATTR_FRICTION, friction);
567 }
568 into.writeAttr(SUMO_ATTR_LENGTH, length);
569 if (endOffset != NBEdge::UNSPECIFIED_OFFSET) {
570 into.writeAttr(SUMO_ATTR_ENDOFFSET, endOffset);
571 }
572 if (width != NBEdge::UNSPECIFIED_WIDTH) {
573 into.writeAttr(SUMO_ATTR_WIDTH, width);
574 }
575 if (accelRamp) {
576 into.writeAttr<bool>(SUMO_ATTR_ACCELERATION, accelRamp);
577 }
578 if (customShape) {
580 }
581 if (endOffset > 0 || startOffset > 0) {
582 startOffset = MIN2(startOffset, shape.length() - POSITION_EPS);
583 endOffset = MIN2(endOffset, shape.length() - startOffset - POSITION_EPS);
584 assert(startOffset + endOffset < shape.length());
585 shape = shape.getSubpart(startOffset, shape.length() - endOffset);
586 }
587 into.writeAttr(SUMO_ATTR_SHAPE, shape);
588 if (type != "") {
589 into.writeAttr(SUMO_ATTR_TYPE, type);
590 }
591 if (changeLeft != SVC_UNSPECIFIED && changeLeft != SVCAll && changeLeft != SVC_IGNORING) {
593 }
594 if (changeRight != SVC_UNSPECIFIED && changeRight != SVCAll && changeRight != SVC_IGNORING) {
596 }
597 if (stopOffset.isDefined()) {
598 writeStopOffsets(into, stopOffset);
599 }
600 if (outlineShape.size() != 0) {
601 into.writeAttr(SUMO_ATTR_OUTLINESHAPE, outlineShape);
602 }
603
604 if (oppositeID != "" && oppositeID != "-") {
606 into.writeAttr(SUMO_ATTR_LANE, oppositeID);
607 into.closeTag();
608 }
609
610 if (params != nullptr) {
611 params->writeParams(into);
612 }
613
614 into.closeTag();
615}
616
617
618void
620 // write the attributes
624 // write the incoming lanes
625 std::vector<std::string> incLanes;
626 const std::vector<NBEdge*>& incoming = n.getIncomingEdges();
627 for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); ++i) {
628 int noLanes = (*i)->getNumLanes();
629 for (int j = 0; j < noLanes; j++) {
630 incLanes.push_back((*i)->getLaneID(j));
631 }
632 }
633 std::vector<NBNode::Crossing*> crossings = n.getCrossings();
634 std::set<std::string> prevWAs;
635 // avoid duplicates
636 for (auto c : crossings) {
637 if (prevWAs.count(c->prevWalkingArea) == 0) {
638 incLanes.push_back(c->prevWalkingArea + "_0");
639 prevWAs.insert(c->prevWalkingArea);
640 }
641 }
642 into.writeAttr(SUMO_ATTR_INCLANES, incLanes);
643 // write the internal lanes
644 std::vector<std::string> intLanes;
645 if (!OptionsCont::getOptions().getBool("no-internal-links")) {
646 for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
647 const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
648 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
649 if ((*k).toEdge == nullptr) {
650 continue;
651 }
652 if (!(*k).haveVia) {
653 intLanes.push_back((*k).getInternalLaneID());
654 } else {
655 intLanes.push_back((*k).getInternalViaLaneID());
656 }
657 }
658 }
659 }
661 for (auto c : crossings) {
662 intLanes.push_back(c->id + "_0");
663 }
664 }
665 into.writeAttr(SUMO_ATTR_INTLANES, intLanes);
666 // close writing
668 // write optional radius
671 }
672 // specify whether a custom shape was used
673 if (n.hasCustomShape()) {
675 }
678 }
680 into.writeAttr<std::string>(SUMO_ATTR_FRINGE, toString(n.getFringeType()));
681 }
684 }
685 if (n.getName() != "") {
687 }
689 // write right-of-way logics
690 n.writeLogic(into);
691 }
692 n.writeParams(into);
693 into.closeTag();
694}
695
696
697bool
699 bool ret = false;
700 const std::vector<NBEdge*>& incoming = n.getIncomingEdges();
701 // build the list of internal lane ids
702 std::vector<std::string> internalLaneIDs;
703 std::map<std::string, std::string> viaIDs;
704 for (const NBEdge* in : incoming) {
705 for (const auto& con : in->getConnections()) {
706 if (con.toEdge != nullptr) {
707 internalLaneIDs.push_back(con.getInternalLaneID());
708 if (con.viaID != "") {
709 viaIDs[con.getInternalLaneID()] = (con.getInternalViaLaneID());
710 }
711 }
712 }
713 }
714 for (auto c : n.getCrossings()) {
715 internalLaneIDs.push_back(c->id + "_0");
716 }
717 // write the internal nodes
718 for (const NBEdge* in : incoming) {
719 for (const auto& con : in->getConnections()) {
720 if (con.toEdge == nullptr || !con.haveVia) {
721 continue;
722 }
723 Position pos = con.shape[-1];
724 into.openTag(SUMO_TAG_JUNCTION).writeAttr(SUMO_ATTR_ID, con.getInternalViaLaneID());
727 std::string incLanes = con.getInternalLaneID();
728 std::vector<std::string> foeIDs;
729 for (std::string incLane : con.foeIncomingLanes) {
730 if (incLane[0] == ':') {
731 // intersecting left turns
732 const int index = StringUtils::toInt(incLane.substr(1));
733 incLane = internalLaneIDs[index];
734 if (viaIDs[incLane] != "") {
735 foeIDs.push_back(viaIDs[incLane]);
736 }
737 }
738 incLanes += " " + incLane;
739 }
740 into.writeAttr(SUMO_ATTR_INCLANES, incLanes);
741 const std::vector<int>& foes = con.foeInternalLinks;
742 for (int foe : foes) {
743 foeIDs.push_back(internalLaneIDs[foe]);
744 }
745 into.writeAttr(SUMO_ATTR_INTLANES, joinToString(foeIDs, " "));
746 into.closeTag();
747 ret = true;
748 }
749 }
750 return ret;
751}
752
753
754void
756 bool includeInternal, ConnectionStyle style, bool useGeo, bool geoAccuracy) {
757 assert(c.toEdge != nullptr);
759 into.writeAttr(SUMO_ATTR_FROM, from.getID());
763 if (style != TLL) {
768 const bool changeLeft = (c.changeLeft != SVC_UNSPECIFIED && c.changeLeft != SVCAll && c.changeLeft != SVC_IGNORING);
770 const bool changeRight = (c.changeRight != SVC_UNSPECIFIED && c.changeRight != SVCAll && c.changeRight != SVC_IGNORING);
774 writeShape(into, GeoConvHelper::getFinal(), c.customShape, SUMO_ATTR_SHAPE, useGeo, geoAccuracy, c.customShape.size() != 0);
778 }
779 if (style != PLAIN && style != PLAIN_NAVTEQ) {
780 if (includeInternal) {
782 }
783 // set information about the controlling tl if any
784 if (c.tlID != "") {
787 if (c.tlLinkIndex2 >= 0) {
789 }
790 }
791 }
792 if (style != TLL) {
793 if (style == SUMONET) {
794 // write the direction information
795 LinkDirection dir = from.getToNode()->getDirection(&from, c.toEdge, OptionsCont::getOptions().getBool("lefthand"));
796 assert(dir != LinkDirection::NODIR);
797 into.writeAttr(SUMO_ATTR_DIR, toString(dir));
798 // write the state information
799 const LinkState linkState = from.getToNode()->getLinkState(
800 &from, c.toEdge, c.fromLane, c.toLane, c.mayDefinitelyPass, c.tlID);
801 into.writeAttr(SUMO_ATTR_STATE, linkState);
802 if (linkState == LINKSTATE_MINOR
805 const double visibilityDistance = OptionsCont::getOptions().getFloat("roundabouts.visibility-distance");
806 if (visibilityDistance != NBEdge::UNSPECIFIED_VISIBILITY_DISTANCE) {
807 into.writeAttr(SUMO_ATTR_VISIBILITY_DISTANCE, visibilityDistance);
808 }
809 }
810 }
813 }
814 }
815 if (style == PLAIN_NAVTEQ) {
817 }
818 c.writeParams(into);
819 into.closeTag();
820}
821
822
823bool
825 bool ret = false;
826 const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
827 for (const NBEdge* const from : n.getIncomingEdges()) {
828 for (const NBEdge::Connection& c : from->getConnections()) {
829 LinkDirection dir = n.getDirection(from, c.toEdge, lefthand);
830 assert(c.toEdge != 0);
831 if (c.haveVia) {
832 // internal split with optional signal
833 std::string tlID = "";
834 int linkIndex2 = NBConnection::InvalidTlIndex;
835 if (c.tlLinkIndex2 != NBConnection::InvalidTlIndex) {
836 linkIndex2 = c.tlLinkIndex2;
837 tlID = c.tlID;
838 }
839 writeInternalConnection(into, c.id, c.toEdge->getID(), c.internalLaneIndex, c.toLane, c.getInternalViaLaneID(), dir, tlID, linkIndex2, false, c.visibility);
840 writeInternalConnection(into, c.viaID, c.toEdge->getID(), c.internalViaLaneIndex, c.toLane, "", dir, "", NBConnection::InvalidTlIndex,
841 n.brakeForCrossingOnExit(c.toEdge, dir, c.indirectLeft));
842 } else {
843 // no internal split
844 writeInternalConnection(into, c.id, c.toEdge->getID(), c.internalLaneIndex, c.toLane, "", dir);
845 }
846 ret = true;
847 }
848 }
849 return ret;
850}
851
852
853void
855 const std::string& from, const std::string& to,
856 int fromLane, int toLane, const std::string& via,
857 LinkDirection dir,
858 const std::string& tlID, int linkIndex,
859 bool minor,
860 double visibility) {
862 into.writeAttr(SUMO_ATTR_FROM, from);
863 into.writeAttr(SUMO_ATTR_TO, to);
864 into.writeAttr(SUMO_ATTR_FROM_LANE, fromLane);
865 into.writeAttr(SUMO_ATTR_TO_LANE, toLane);
866 if (via != "") {
867 into.writeAttr(SUMO_ATTR_VIA, via);
868 }
869 if (tlID != "" && linkIndex != NBConnection::InvalidTlIndex) {
870 // used for the reverse direction of pedestrian crossings
871 into.writeAttr(SUMO_ATTR_TLID, tlID);
872 into.writeAttr(SUMO_ATTR_TLLINKINDEX, linkIndex);
873 }
874 into.writeAttr(SUMO_ATTR_DIR, dir);
875 into.writeAttr(SUMO_ATTR_STATE, ((via != "" || minor) ? "m" : "M"));
876 if (visibility != NBEdge::UNSPECIFIED_VISIBILITY_DISTANCE) {
878 }
879 into.closeTag();
880}
881
882
883void
884NWWriter_SUMO::writeRoundabouts(OutputDevice& into, const std::set<EdgeSet>& roundabouts,
885 const NBEdgeCont& ec) {
886 // make output deterministic
887 std::vector<std::vector<std::string> > edgeIDs;
888 for (std::set<EdgeSet>::const_iterator i = roundabouts.begin(); i != roundabouts.end(); ++i) {
889 std::vector<std::string> tEdgeIDs;
890 for (EdgeSet::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
891 // the edges may have been erased from NBEdgeCont but their pointers are still valid
892 // we verify their existance in writeRoundabout()
893 tEdgeIDs.push_back((*j)->getID());
894 }
895 std::sort(tEdgeIDs.begin(), tEdgeIDs.end());
896 edgeIDs.push_back(tEdgeIDs);
897 }
898 std::sort(edgeIDs.begin(), edgeIDs.end());
899 // write
900 for (std::vector<std::vector<std::string> >::const_iterator i = edgeIDs.begin(); i != edgeIDs.end(); ++i) {
901 writeRoundabout(into, *i, ec);
902 }
903 if (roundabouts.size() != 0) {
904 into.lf();
905 }
906}
907
908
909void
910NWWriter_SUMO::writeRoundabout(OutputDevice& into, const std::vector<std::string>& edgeIDs,
911 const NBEdgeCont& ec) {
912 std::vector<std::string> validEdgeIDs;
913 std::vector<std::string> invalidEdgeIDs;
914 std::vector<std::string> nodeIDs;
915 for (std::vector<std::string>::const_iterator i = edgeIDs.begin(); i != edgeIDs.end(); ++i) {
916 const NBEdge* edge = ec.retrieve(*i);
917 if (edge != nullptr) {
918 nodeIDs.push_back(edge->getToNode()->getID());
919 validEdgeIDs.push_back(edge->getID());
920 } else {
921 invalidEdgeIDs.push_back(*i);
922 }
923 }
924 std::sort(nodeIDs.begin(), nodeIDs.end());
925 if (validEdgeIDs.size() > 0) {
927 into.writeAttr(SUMO_ATTR_NODES, joinToString(nodeIDs, " "));
928 into.writeAttr(SUMO_ATTR_EDGES, joinToString(validEdgeIDs, " "));
929 into.closeTag();
930 if (invalidEdgeIDs.size() > 0) {
931 WRITE_WARNING("Writing incomplete roundabout. Edges: '"
932 + joinToString(invalidEdgeIDs, " ") + "' no longer exist'");
933 }
934 }
935}
936
937
938void
940 std::vector<double> sourceW = d.getSourceWeights();
942 std::vector<double> sinkW = d.getSinkWeights();
944 // write the head and the id of the district
946 if (d.getShape().size() > 0) {
948 }
949 // write all sources
950 const std::vector<NBEdge*>& sources = d.getSourceEdges();
951 for (int i = 0; i < (int)sources.size(); i++) {
952 // write the head and the id of the source
953 into.openTag(SUMO_TAG_TAZSOURCE).writeAttr(SUMO_ATTR_ID, sources[i]->getID()).writeAttr(SUMO_ATTR_WEIGHT, sourceW[i]);
954 into.closeTag();
955 }
956 // write all sinks
957 const std::vector<NBEdge*>& sinks = d.getSinkEdges();
958 for (int i = 0; i < (int)sinks.size(); i++) {
959 // write the head and the id of the sink
960 into.openTag(SUMO_TAG_TAZSINK).writeAttr(SUMO_ATTR_ID, sinks[i]->getID()).writeAttr(SUMO_ATTR_WEIGHT, sinkW[i]);
961 into.closeTag();
962 }
963 // write the tail
964 into.closeTag();
965}
966
967
968std::string
970 double time = STEPS2TIME(steps);
971 if (time == std::floor(time)) {
972 return toString(int(time));
973 } else {
974 return toString(time);
975 }
976}
977
978void
980 // the edges may have been erased from NBEdgeCont but their pointers are still valid so we need to check
981 for (NBConnectionProhibits::const_iterator j = prohibitions.begin(); j != prohibitions.end(); j++) {
982 NBConnection prohibited = (*j).first;
983 if (ec.retrieve(prohibited.getFrom()->getID()) == nullptr
984 || ec.retrieve(prohibited.getTo()->getID()) == nullptr) {
985 continue;
986 }
987 const NBConnectionVector& prohibiting = (*j).second;
988 for (NBConnectionVector::const_iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
989 NBConnection prohibitor = *k;
990 if (ec.retrieve(prohibitor.getFrom()->getID()) == nullptr
991 || ec.retrieve(prohibitor.getTo()->getID()) == nullptr) {
992 continue;
993 }
997 into.closeTag();
998 }
999 }
1000}
1001
1002
1003std::string
1005 return c.getFrom()->getID() + "->" + c.getTo()->getID();
1006}
1007
1008
1009void
1011 std::vector<NBTrafficLightLogic*> logics = tllCont.getComputed();
1012 for (NBTrafficLightLogic* logic : logics) {
1013 NBTrafficLightDefinition* def = tllCont.getDefinition(logic->getID(), logic->getProgramID());
1014 writeTrafficLight(into, logic, def, style);
1015 // only raise warnings on write instead of on compute (to avoid cluttering netedit)
1016 assert(def != nullptr);
1017 def->finalChecks();
1018 }
1019 if (logics.size() > 0) {
1020 into.lf();
1021 }
1022}
1023
1024
1025void
1028 into.writeAttr(SUMO_ATTR_ID, logic->getID());
1029 into.writeAttr(SUMO_ATTR_TYPE, logic->getType());
1031 into.writeAttr(SUMO_ATTR_OFFSET, logic->getOffset() == SUMOTime_MAX ? "begin" : writeSUMOTime(logic->getOffset()));
1032 if (style == PLAIN_NAVTEQ) {
1034 PositionVector nodePos;
1035 for (const NBNode* n : def->getNodes()) {
1036 Position pos = n->getPosition();
1038 nodePos.push_back(pos);
1039 }
1040 into.writeAttr(SUMO_ATTR_POSITION, nodePos);
1041 }
1042 // write the phases
1043 const bool varPhaseLength = logic->getType() != TrafficLightType::STATIC;
1044 for (const NBTrafficLightLogic::PhaseDefinition& phase : logic->getPhases()) {
1045 into.openTag(SUMO_TAG_PHASE);
1046 into.writeAttr(SUMO_ATTR_DURATION, writeSUMOTime(phase.duration));
1047 if (phase.duration < TIME2STEPS(10)) {
1048 into.writePadding(" ");
1049 }
1050 into.writeAttr(SUMO_ATTR_STATE, phase.state);
1051 into.writeOptionalAttr(SUMO_ATTR_MINDURATION, writeSUMOTime(phase.minDur), !varPhaseLength || phase.minDur == NBTrafficLightDefinition::UNSPECIFIED_DURATION);
1052 into.writeOptionalAttr(SUMO_ATTR_MAXDURATION, writeSUMOTime(phase.maxDur), !varPhaseLength || phase.maxDur == NBTrafficLightDefinition::UNSPECIFIED_DURATION);
1053 into.writeOptionalAttr(SUMO_ATTR_EARLIEST_END, writeSUMOTime(phase.earliestEnd), !varPhaseLength || phase.earliestEnd == NBTrafficLightDefinition::UNSPECIFIED_DURATION);
1054 into.writeOptionalAttr(SUMO_ATTR_LATEST_END, writeSUMOTime(phase.latestEnd), !varPhaseLength || phase.latestEnd == NBTrafficLightDefinition::UNSPECIFIED_DURATION);
1055 // NEMA attributes
1057 into.writeOptionalAttr(SUMO_ATTR_YELLOW, writeSUMOTime(phase.yellow), !varPhaseLength || phase.yellow == NBTrafficLightDefinition::UNSPECIFIED_DURATION);
1058 into.writeOptionalAttr(SUMO_ATTR_RED, writeSUMOTime(phase.red), !varPhaseLength || phase.red == NBTrafficLightDefinition::UNSPECIFIED_DURATION);
1059
1060 into.writeOptionalAttr(SUMO_ATTR_NAME, phase.name, phase.name == "", true);
1061 into.writeOptionalAttr(SUMO_ATTR_NEXT, phase.next, phase.next.empty());
1062 into.closeTag();
1063 }
1064 // write params
1065 logic->writeParams(into);
1066 into.closeTag();
1067}
1068
1069
1070void
1072 if (stopOffset.isDefined()) {
1073 const std::string ss_vclasses = getVehicleClassNames(stopOffset.getPermissions());
1074 if (ss_vclasses.length() == 0) {
1075 // This stopOffset would have no effect...
1076 return;
1077 }
1079 const std::string ss_exceptions = getVehicleClassNames(~stopOffset.getPermissions());
1080 if (ss_vclasses.length() <= ss_exceptions.length()) {
1081 into.writeAttr(SUMO_ATTR_VCLASSES, ss_vclasses);
1082 } else {
1083 if (ss_exceptions.length() == 0) {
1084 into.writeAttr(SUMO_ATTR_VCLASSES, "all");
1085 } else {
1086 into.writeAttr(SUMO_ATTR_EXCEPTIONS, ss_exceptions);
1087 }
1088 }
1089 into.writeAttr(SUMO_ATTR_VALUE, stopOffset.getOffset());
1090 into.closeTag();
1091 }
1092}
1093
1094
1095void
1096NWWriter_SUMO::writeShape(OutputDevice& out, const GeoConvHelper& gch, PositionVector shape, SumoXMLAttr attr, bool useGeo, bool geoAccuracy, bool needsWrite) {
1097 if (!needsWrite) {
1098 out.writeOptionalAttr(attr, shape, true);
1099 return;
1100 }
1101 if (useGeo) {
1102 for (int i = 0; i < (int) shape.size(); i++) {
1103 gch.cartesian2geo(shape[i]);
1104 }
1105 }
1106 if (geoAccuracy) {
1108 }
1109 out.writeAttr(attr, shape);
1110 if (geoAccuracy) {
1111 out.setPrecision();
1112 }
1113}
1114
1115
1116/****************************************************************************/
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:58
constexpr SUMOTime TIME2STEPS(double x)
Definition SUMOTime.h:60
#define SUMOTime_MAX
Definition SUMOTime.h:34
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.
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
@ 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_POSITION
@ 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:314
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:49
static methods for processing the coordinates conversion for the current net
static void writeLocation(OutputDevice &into)
writes the location element
static const GeoConvHelper & getFinal()
the coordinate transformation for writing the location element and for tracking the original coordina...
void cartesian2geo(Position &cartesian) const
Converts the given cartesian (shifted) position to its geo (lat/long) representation.
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:4396
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:4181
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:2160
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:4172
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:4894
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:137
int tlLinkIndex
the traffic light index of this crossing (if controlled)
Definition NBNode.h:164
std::string tlID
The id of the traffic light that controls this connection.
Definition NBNode.h:170
bool priority
whether the pedestrians have priority
Definition NBNode.h:160
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:118
std::map< std::string, NBNode * >::const_iterator end() const
Returns the pointer to the end of the stored nodes.
Definition NBNodeCont.h:123
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:2507
RightOfWay getRightOfWay() const
Returns hint on how to compute right of way.
Definition NBNode.h:302
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:2592
static const double UNSPECIFIED_RADIUS
unspecified lane width
Definition NBNode.h:222
FringeType getFringeType() const
Returns fringe type.
Definition NBNode.h:307
SumoXMLNodeType getType() const
Returns the type of this node.
Definition NBNode.h:287
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
Definition NBNode.h:270
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:2176
bool hasCustomShape() const
return whether the shape was set by the user
Definition NBNode.h:603
std::vector< Crossing * > getCrossings() const
return this junctions pedestrian crossings
Definition NBNode.cpp:3107
const std::string & getName() const
Returns intersection name.
Definition NBNode.h:317
bool writeLogic(OutputDevice &into) const
writes the XML-representation of the logic as a bitset-logic XML representation
Definition NBNode.cpp:1140
const Position & getPosition() const
Definition NBNode.h:262
const PositionVector & getShape() const
retrieve the junction shape
Definition NBNode.cpp:2792
RoundaboutType getRoundaboutType() const
Returns roundabout type.
Definition NBNode.h:312
double getRadius() const
Returns the turning radius of this node.
Definition NBNode.h:292
const std::vector< WalkingArea > & getWalkingAreas() const
return this junctions pedestrian walking areas
Definition NBNode.h:766
The base class for traffic light logic definitions.
const std::vector< NBNode * > & getNodes() const
Returns the list of controlled nodes.
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 writeConnectionAttrs(OutputDevice &device, const NBEdge::Connection &c)
static void writeShape(OutputDevice &out, const GeoConvHelper &gch, PositionVector shape, SumoXMLAttr attr, bool useGeo, bool geoAccuracy, bool needsWrite)
static void writeConnection(OutputDevice &into, const NBEdge &from, const NBEdge::Connection &c, bool includeInternal, ConnectionStyle style=SUMONET, bool useGeo=false, bool geoAccuracy=false)
Writes connections outgoing from the given edge (also used in NWWriter_XML)
static void writeProhibitions(OutputDevice &into, const NBConnectionProhibits &prohibitions, const NBEdgeCont &ec)
writes the given prohibitions
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, const NBTrafficLightDefinition *def, ConnectionStyle style=SUMONET)
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 void writeTrafficLights(OutputDevice &into, const NBTrafficLightLogicCont &tllCont, ConnectionStyle style=SUMONET)
writes the traffic light logics to the given device
static std::string prohibitionConnection(const NBConnection &c)
the attribute value for a prohibition
const std::string & getID() const
Returns the id.
Definition Named.h:73
A storage for options typed value containers)
Definition OptionsCont.h:89
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
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 & 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.
OutputDevice & writeAttr(const ATTR_TYPE &attr, const T &val, const bool isNull=false, const bool escape=false)
writes a named attribute
OutputDevice & writeOptionalAttr(const SumoXMLAttr attr, const T &val, const bool isNull=false, const bool escape=false)
writes a named attribute unless null
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)
unsigned node
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:179