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-2023 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 const int cornerDetail = oc.getInt("junctions.corner-detail");
71 if (cornerDetail > 0) {
72 attrs[SUMO_ATTR_CORNERDETAIL] = toString(cornerDetail);
73 }
74 if (!oc.isDefault("junctions.internal-link-detail")) {
75 attrs[SUMO_ATTR_LINKDETAIL] = toString(oc.getInt("junctions.internal-link-detail"));
76 }
77 if (oc.getBool("rectangular-lane-cut")) {
78 attrs[SUMO_ATTR_RECTANGULAR_LANE_CUT] = "true";
79 }
80 if (oc.getBool("crossings.guess") || oc.getBool("walkingareas")) {
81 attrs[SUMO_ATTR_WALKINGAREAS] = "true";
82 }
83 if (oc.getFloat("junctions.limit-turn-speed") > 0) {
84 attrs[SUMO_ATTR_LIMIT_TURN_SPEED] = toString(oc.getFloat("junctions.limit-turn-speed"));
85 }
86 if (!oc.isDefault("check-lane-foes.all")) {
87 attrs[SUMO_ATTR_CHECKLANEFOES_ALL] = toString(oc.getBool("check-lane-foes.all"));
88 }
89 if (!oc.isDefault("check-lane-foes.roundabout")) {
90 attrs[SUMO_ATTR_CHECKLANEFOES_ROUNDABOUT] = toString(oc.getBool("check-lane-foes.roundabout"));
91 }
92 if (!oc.isDefault("tls.ignore-internal-junction-jam")) {
93 attrs[SUMO_ATTR_TLS_IGNORE_INTERNAL_JUNCTION_JAM] = toString(oc.getBool("tls.ignore-internal-junction-jam"));
94 }
95 if (oc.getString("default.spreadtype") == "roadCenter") {
96 // it makes no sense to store the default=center in the net since
97 // centered edges would have the attribute written anyway and edges that
98 // should have 'right' would be misinterpreted
99 attrs[SUMO_ATTR_SPREADTYPE] = oc.getString("default.spreadtype");
100 }
101 if (oc.exists("geometry.avoid-overlap") && !oc.getBool("geometry.avoid-overlap")) {
102 attrs[SUMO_ATTR_AVOID_OVERLAP] = toString(oc.getBool("geometry.avoid-overlap"));
103 }
104 if (oc.exists("junctions.higher-speed") && oc.getBool("junctions.higher-speed")) {
105 attrs[SUMO_ATTR_HIGHER_SPEED] = toString(oc.getBool("junctions.higher-speed"));
106 }
107 if (oc.exists("internal-junctions.vehicle-width") && !oc.isDefault("internal-junctions.vehicle-width")) {
108 attrs[SUMO_ATTR_INTERNAL_JUNCTIONS_VEHICLE_WIDTH] = toString(oc.getFloat("internal-junctions.vehicle-width"));
109 }
110 device.writeXMLHeader("net", "net_file.xsd", attrs); // street names may contain non-ascii chars
111 device.lf();
112 // get involved container
113 const NBNodeCont& nc = nb.getNodeCont();
114 const NBEdgeCont& ec = nb.getEdgeCont();
115 const NBDistrictCont& dc = nb.getDistrictCont();
116
117 // write network offsets and projection
119
120 // write edge types and restrictions
121 std::set<std::string> usedTypes = ec.getUsedTypes();
122 nb.getTypeCont().writeEdgeTypes(device, usedTypes);
123
124 // write inner lanes
125 if (!oc.getBool("no-internal-links")) {
126 bool hadAny = false;
127 for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
128 hadAny |= writeInternalEdges(device, ec, *(*i).second);
129 }
130 if (hadAny) {
131 device.lf();
132 }
133 }
134
135 // write edges with lanes and connected edges
136 bool noNames = !oc.getBool("output.street-names");
137 for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
138 writeEdge(device, *(*i).second, noNames);
139 }
140 device.lf();
141
142 // write tls logics
144
145 // write the nodes (junctions)
146 for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
147 writeJunction(device, *(*i).second);
148 }
149 device.lf();
150 const bool includeInternal = !oc.getBool("no-internal-links");
151 if (includeInternal) {
152 // ... internal nodes if not unwanted
153 bool hadAny = false;
154 for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
155 hadAny |= writeInternalNodes(device, *(*i).second);
156 }
157 if (hadAny) {
158 device.lf();
159 }
160 }
161
162 // write the successors of lanes
163 int numConnections = 0;
164 for (std::map<std::string, NBEdge*>::const_iterator it_edge = ec.begin(); it_edge != ec.end(); it_edge++) {
165 NBEdge* from = it_edge->second;
166 const std::vector<NBEdge::Connection>& connections = from->getConnections();
167 numConnections += (int)connections.size();
168 for (const NBEdge::Connection& con : connections) {
169 writeConnection(device, *from, con, includeInternal);
170 }
171 }
172 if (numConnections > 0) {
173 device.lf();
174 }
175 if (includeInternal) {
176 // ... internal successors if not unwanted
177 bool hadAny = false;
178 for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
179 hadAny |= writeInternalConnections(device, *(*i).second);
180 }
181 if (hadAny) {
182 device.lf();
183 }
184 }
185 for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
186 NBNode* node = (*i).second;
187 // write connections from pedestrian crossings
188 std::vector<NBNode::Crossing*> crossings = node->getCrossings();
189 for (auto c : crossings) {
190 NWWriter_SUMO::writeInternalConnection(device, c->id, c->nextWalkingArea, 0, 0, "", LinkDirection::STRAIGHT, c->tlID, c->tlLinkIndex2);
191 }
192 // write connections from pedestrian walking areas
193 for (const NBNode::WalkingArea& wa : node->getWalkingAreas()) {
194 for (const std::string& cID : wa.nextCrossings) {
195 const NBNode::Crossing& nextCrossing = *node->getCrossing(cID);
196 // connection to next crossing (may be tls-controlled)
198 device.writeAttr(SUMO_ATTR_FROM, wa.id);
199 device.writeAttr(SUMO_ATTR_TO, cID);
201 device.writeAttr(SUMO_ATTR_TO_LANE, 0);
202 if (nextCrossing.tlID != "") {
203 device.writeAttr(SUMO_ATTR_TLID, nextCrossing.tlID);
204 assert(nextCrossing.tlLinkIndex >= 0);
205 device.writeAttr(SUMO_ATTR_TLLINKINDEX, nextCrossing.tlLinkIndex);
206 }
209 device.closeTag();
210 }
211 // optional connections from/to sidewalk
212 std::string edgeID;
213 int laneIndex;
214 for (const std::string& sw : wa.nextSidewalks) {
215 NBHelpers::interpretLaneID(sw, edgeID, laneIndex);
216 NWWriter_SUMO::writeInternalConnection(device, wa.id, edgeID, 0, laneIndex, "");
217 }
218 for (const std::string& sw : wa.prevSidewalks) {
219 NBHelpers::interpretLaneID(sw, edgeID, laneIndex);
220 NWWriter_SUMO::writeInternalConnection(device, edgeID, wa.id, laneIndex, 0, "");
221 }
222 }
223 }
224
225 // write loaded prohibitions
226 for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
227 writeProhibitions(device, i->second->getProhibitions());
228 }
229
230 // write roundabout information
231 writeRoundabouts(device, ec.getRoundabouts(), ec);
232
233 // write the districts
234 if (dc.size() != 0 && oc.isDefault("taz-output")) {
235 WRITE_WARNING(TL("Embedding TAZ-data inside the network is deprecated. Use option --taz-output instead"));
236 for (std::map<std::string, NBDistrict*>::const_iterator i = dc.begin(); i != dc.end(); i++) {
237 writeDistrict(device, *(*i).second);
238 }
239 device.lf();
240 }
241 device.close();
242}
243
244
245std::string
246NWWriter_SUMO::getOppositeInternalID(const NBEdgeCont& ec, const NBEdge* from, const NBEdge::Connection& con, double& oppositeLength) {
247 const NBEdge::Lane& succ = con.toEdge->getLanes()[con.toLane];
248 const NBEdge::Lane& pred = from->getLanes()[con.fromLane];
249 const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
250 if (succ.oppositeID != "" && succ.oppositeID != "-" && pred.oppositeID != "" && pred.oppositeID != "-") {
251#ifdef DEBUG_OPPOSITE_INTERNAL
252 std::cout << "getOppositeInternalID con=" << con.getDescription(from) << " (" << con.getInternalLaneID() << ")\n";
253#endif
254 // find the connection that connects succ.oppositeID to pred.oppositeID
255 const NBEdge* succOpp = ec.retrieve(succ.oppositeID.substr(0, succ.oppositeID.rfind("_")));
256 const NBEdge* predOpp = ec.retrieve(pred.oppositeID.substr(0, pred.oppositeID.rfind("_")));
257 assert(succOpp != 0);
258 assert(predOpp != 0);
259 const std::vector<NBEdge::Connection>& connections = succOpp->getConnections();
260 for (std::vector<NBEdge::Connection>::const_iterator it_c = connections.begin(); it_c != connections.end(); it_c++) {
261 const NBEdge::Connection& conOpp = *it_c;
262 if (succOpp != from // turnaround
263 && predOpp == conOpp.toEdge
264 && succOpp->getLaneID(conOpp.fromLane) == succ.oppositeID
265 && predOpp->getLaneID(conOpp.toLane) == pred.oppositeID
266 && from->getToNode()->getDirection(from, con.toEdge, lefthand) == LinkDirection::STRAIGHT
267 && from->getToNode()->getDirection(succOpp, predOpp, lefthand) == LinkDirection::STRAIGHT
268 ) {
269#ifdef DEBUG_OPPOSITE_INTERNAL
270 std::cout << " found " << conOpp.getInternalLaneID() << "\n";
271#endif
272 oppositeLength = conOpp.length;
273 return conOpp.getInternalLaneID();
274 } else {
275 /*
276 #ifdef DEBUG_OPPOSITE_INTERNAL
277 std::cout << " rejected " << conOpp.getInternalLaneID()
278 << "\n succ.oppositeID=" << succ.oppositeID
279 << "\n succOppLane=" << succOpp->getLaneID(conOpp.fromLane)
280 << "\n pred.oppositeID=" << pred.oppositeID
281 << "\n predOppLane=" << predOpp->getLaneID(conOpp.toLane)
282 << "\n predOpp=" << predOpp->getID()
283 << "\n conOppTo=" << conOpp.toEdge->getID()
284 << "\n len1=" << con.shape.length()
285 << "\n len2=" << conOpp.shape.length()
286 << "\n";
287 #endif
288 */
289 }
290 }
291 return "";
292 } else {
293 return "";
294 }
295}
296
297
298bool
300 bool ret = false;
301 const EdgeVector& incoming = n.getIncomingEdges();
302 // first pass: determine opposite internal edges and average their length
303 std::map<std::string, std::string> oppositeLaneID;
304 std::map<std::string, double> oppositeLengths;
305 for (NBEdge* e : incoming) {
306 for (const NBEdge::Connection& c : e->getConnections()) {
307 double oppositeLength = 0;
308 const std::string op = getOppositeInternalID(ec, e, c, oppositeLength);
309 oppositeLaneID[c.getInternalLaneID()] = op;
310 if (op != "") {
311 oppositeLengths[c.id] = oppositeLength;
312 }
313 }
314 }
315 if (oppositeLengths.size() > 0) {
316 for (NBEdge* e : incoming) {
317 for (NBEdge::Connection& c : e->getConnections()) {
318 if (oppositeLengths.count(c.id) > 0) {
319 c.length = (c.length + oppositeLengths[c.id]) / 2;
320 }
321 }
322 }
323 }
324
325 for (NBEdge* e : incoming) {
326 const std::vector<NBEdge::Connection>& elv = e->getConnections();
327 if (elv.size() > 0) {
328 bool haveVia = false;
329 std::string edgeID = "";
330 // second pass: write non-via edges
331 for (const NBEdge::Connection& k : elv) {
332 if (k.toEdge == nullptr) {
333 assert(false); // should never happen. tell me when it does
334 continue;
335 }
336 if (edgeID != k.id) {
337 if (edgeID != "") {
338 // close the previous edge
339 into.closeTag();
340 }
341 edgeID = k.id;
343 into.writeAttr(SUMO_ATTR_ID, edgeID);
345 if (k.edgeType != "") {
346 into.writeAttr(SUMO_ATTR_TYPE, k.edgeType);
347 }
348 if (e->getBidiEdge() && k.toEdge->getBidiEdge() &&
349 e != k.toEdge->getTurnDestination(true)) {
350 const std::string bidiEdge = getInternalBidi(e, k);
351 if (bidiEdge != "") {
352 into.writeAttr(SUMO_ATTR_BIDI, bidiEdge);
353 }
354 }
355 // open a new edge
356 }
357 // to avoid changing to an internal lane which has a successor
358 // with the wrong permissions we need to inherit them from the successor
359 const NBEdge::Lane& successor = k.toEdge->getLanes()[k.toLane];
360 SVCPermissions permissions = (k.permissions != SVC_UNSPECIFIED) ? k.permissions : (
361 successor.permissions & e->getPermissions(k.fromLane));
362 SVCPermissions changeLeft = k.changeLeft != SVC_UNSPECIFIED ? k.changeLeft : SVCAll;
363 SVCPermissions changeRight = k.changeRight != SVC_UNSPECIFIED ? k.changeRight : SVCAll;
364 const double width = e->getInternalLaneWidth(n, k, successor, false);
365 writeLane(into, k.getInternalLaneID(), k.vmax, k.friction,
366 permissions, successor.preferred,
367 changeLeft, changeRight,
369 StopOffset(), width, k.shape, &k,
370 k.length, k.internalLaneIndex, oppositeLaneID[k.getInternalLaneID()], "");
371 haveVia = haveVia || k.haveVia;
372 }
373 ret = true;
374 into.closeTag(); // close the last edge
375 // third pass: write via edges
376 if (haveVia) {
377 for (const NBEdge::Connection& k : elv) {
378 if (!k.haveVia) {
379 continue;
380 }
381 if (k.toEdge == nullptr) {
382 assert(false); // should never happen. tell me when it does
383 continue;
384 }
385 const NBEdge::Lane& successor = k.toEdge->getLanes()[k.toLane];
387 into.writeAttr(SUMO_ATTR_ID, k.viaID);
389 if (k.edgeType != "") {
390 into.writeAttr(SUMO_ATTR_TYPE, k.edgeType);
391 }
392 SVCPermissions permissions = (k.permissions != SVC_UNSPECIFIED) ? k.permissions : (
393 successor.permissions & e->getPermissions(k.fromLane));
394 const double width = e->getInternalLaneWidth(n, k, successor, true);
395 writeLane(into, k.viaID + "_0", k.vmax, k.friction, permissions, successor.preferred,
396 SVCAll, SVCAll, // #XXX todo
398 StopOffset(), width, k.viaShape, &k,
399 MAX2(k.viaLength, POSITION_EPS), // microsim needs positive length
400 0, "", "");
401 into.closeTag();
402 }
403 }
404 }
405 }
406 // write pedestrian crossings
407 const double crossingSpeed = OptionsCont::getOptions().getFloat("default.crossing-speed");
408 for (auto c : n.getCrossings()) {
410 into.writeAttr(SUMO_ATTR_ID, c->id);
412 into.writeAttr(SUMO_ATTR_CROSSING_EDGES, c->edges);
413 writeLane(into, c->id + "_0", crossingSpeed, NBEdge::UNSPECIFIED_FRICTION, SVC_PEDESTRIAN, 0, SVCAll, SVCAll,
415 StopOffset(), c->width, c->shape, nullptr,
416 MAX2(c->shape.length(), POSITION_EPS), 0, "", "", false, c->customShape.size() != 0);
417 into.closeTag();
418 }
419 // write pedestrian walking areas
420 const double walkingareaSpeed = OptionsCont::getOptions().getFloat("default.walkingarea-speed");
421 const std::vector<NBNode::WalkingArea>& WalkingAreas = n.getWalkingAreas();
422 for (std::vector<NBNode::WalkingArea>::const_iterator it = WalkingAreas.begin(); it != WalkingAreas.end(); it++) {
423 const NBNode::WalkingArea& wa = *it;
425 into.writeAttr(SUMO_ATTR_ID, wa.id);
427 writeLane(into, wa.id + "_0", walkingareaSpeed, NBEdge::UNSPECIFIED_FRICTION, SVC_PEDESTRIAN, 0, SVCAll, SVCAll,
429 StopOffset(), wa.width, wa.shape, nullptr, wa.length, 0, "", "", false, wa.hasCustomShape);
430 into.closeTag();
431 }
432 return ret;
433}
434
435
436std::string
438 const NBEdge* fromBidi = e->getTurnDestination(true);
439 const NBEdge* toBidi = k.toEdge->getTurnDestination(true);
440 const std::vector<NBEdge::Connection> cons = toBidi->getConnectionsFromLane(-1, fromBidi, -1);
441 if (cons.size() > 0) {
442 if (e->getNumLanes() == 1 && k.toEdge->getNumLanes() == 1 && fromBidi->getNumLanes() == 1 && toBidi->getNumLanes() == 1) {
443 return cons.back().id;
444 }
445 // do a more careful check in case there are parallel internal edges
446 // note: k is the first connection with the new id
447 for (const NBEdge::Connection& c : e->getConnections()) {
448 if (c.id == k.id) {
449 PositionVector rShape = c.shape.reverse();
450 for (const NBEdge::Connection& k2 : cons) {
451 if (k2.shape.almostSame(rShape, POSITION_EPS)) {
452 return k2.id;
453 }
454 }
455 }
456 }
457 } else {
458 WRITE_WARNINGF(TL("Could not find bidi-connection for edge '%'"), k.id)
459 }
460 return "";
461}
462
463void
464NWWriter_SUMO::writeEdge(OutputDevice& into, const NBEdge& e, bool noNames) {
465 // write the edge's begin
469 if (!noNames && e.getStreetName() != "") {
471 }
473 if (e.getTypeID() != "") {
475 }
476 if (e.isMacroscopicConnector()) {
478 }
479 // write the spread type if not default ("right")
482 }
483 if (e.hasLoadedLength()) {
485 }
486 if (!e.hasDefaultGeometry()) {
488 }
489 if (e.getEdgeStopOffset().isDefined()) {
491 }
492 if (e.getBidiEdge()) {
494 }
495 if (e.getDistance() != 0) {
497 }
498
499 // write the lanes
500 const std::vector<NBEdge::Lane>& lanes = e.getLanes();
501
502 const double length = e.getFinalLength();
503 double startOffset = e.isBidiRail() ? e.getTurnDestination(true)->getEndOffset() : 0;
504 for (int i = 0; i < (int) lanes.size(); i++) {
505 const NBEdge::Lane& l = lanes[i];
506 StopOffset stopOffset;
507 if (l.laneStopOffset != e.getEdgeStopOffset()) {
508 stopOffset = l.laneStopOffset;
509 }
510 writeLane(into, e.getLaneID(i), l.speed, l.friction,
513 startOffset, l.endOffset,
514 stopOffset, l.width, l.shape, &l,
515 length, i, l.oppositeID, l.type, l.accelRamp, l.customShape.size() > 0);
516 }
517 // close the edge
518 e.writeParams(into);
519 into.closeTag();
520}
521
522
523void
524NWWriter_SUMO::writeLane(OutputDevice& into, const std::string& lID,
525 double speed, double friction,
526 SVCPermissions permissions, SVCPermissions preferred,
527 SVCPermissions changeLeft, SVCPermissions changeRight,
528 double startOffset, double endOffset,
529 const StopOffset& stopOffset, double width, PositionVector shape,
530 const Parameterised* params, double length, int index,
531 const std::string& oppositeID,
532 const std::string& type,
533 bool accelRamp, bool customShape) {
534 // output the lane's attributes
536 // the first lane of an edge will be the depart lane
537 into.writeAttr(SUMO_ATTR_INDEX, index);
538 // write the list of allowed/disallowed vehicle classes
539 if (permissions != SVC_UNSPECIFIED) {
540 writePermissions(into, permissions);
541 }
542 writePreferences(into, preferred);
543 // some further information
544 if (speed == 0) {
545 WRITE_WARNINGF(TL("Lane '%' has a maximum allowed speed of 0."), lID);
546 } else if (speed < 0) {
547 throw ProcessError("Negative allowed speed (" + toString(speed) + ") on lane '" + lID + "', use --speed.minimum to prevent this.");
548 }
549 into.writeAttr(SUMO_ATTR_SPEED, speed);
550 if (friction != NBEdge::UNSPECIFIED_FRICTION) {
551 into.writeAttr(SUMO_ATTR_FRICTION, friction);
552 }
553 into.writeAttr(SUMO_ATTR_LENGTH, length);
554 if (endOffset != NBEdge::UNSPECIFIED_OFFSET) {
555 into.writeAttr(SUMO_ATTR_ENDOFFSET, endOffset);
556 }
557 if (width != NBEdge::UNSPECIFIED_WIDTH) {
558 into.writeAttr(SUMO_ATTR_WIDTH, width);
559 }
560 if (accelRamp) {
561 into.writeAttr<bool>(SUMO_ATTR_ACCELERATION, accelRamp);
562 }
563 if (customShape) {
565 }
566 if (endOffset > 0 || startOffset > 0) {
567 if (startOffset + endOffset < shape.length()) {
568 shape = shape.getSubpart(startOffset, shape.length() - endOffset);
569 } else {
570 WRITE_ERROR("Invalid endOffset " + toString(endOffset) + " at lane '" + lID
571 + "' with length " + toString(shape.length()) + " (startOffset " + toString(startOffset) + ")");
572 if (!OptionsCont::getOptions().getBool("ignore-errors")) {
573 throw ProcessError();
574 }
575 }
576 }
577 into.writeAttr(SUMO_ATTR_SHAPE, shape);
578 if (type != "") {
579 into.writeAttr(SUMO_ATTR_TYPE, type);
580 }
581 if (changeLeft != SVC_UNSPECIFIED && changeLeft != SVCAll && changeLeft != SVC_IGNORING) {
583 }
584 if (changeRight != SVC_UNSPECIFIED && changeRight != SVCAll && changeRight != SVC_IGNORING) {
586 }
587 if (stopOffset.isDefined()) {
588 writeStopOffsets(into, stopOffset);
589 }
590
591 if (oppositeID != "" && oppositeID != "-") {
593 into.writeAttr(SUMO_ATTR_LANE, oppositeID);
594 into.closeTag();
595 }
596
597 if (params != nullptr) {
598 params->writeParams(into);
599 }
600
601 into.closeTag();
602}
603
604
605void
607 // write the attributes
611 // write the incoming lanes
612 std::vector<std::string> incLanes;
613 const std::vector<NBEdge*>& incoming = n.getIncomingEdges();
614 for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); ++i) {
615 int noLanes = (*i)->getNumLanes();
616 for (int j = 0; j < noLanes; j++) {
617 incLanes.push_back((*i)->getLaneID(j));
618 }
619 }
620 std::vector<NBNode::Crossing*> crossings = n.getCrossings();
621 std::set<std::string> prevWAs;
622 // avoid duplicates
623 for (auto c : crossings) {
624 if (prevWAs.count(c->prevWalkingArea) == 0) {
625 incLanes.push_back(c->prevWalkingArea + "_0");
626 prevWAs.insert(c->prevWalkingArea);
627 }
628 }
629 into.writeAttr(SUMO_ATTR_INCLANES, incLanes);
630 // write the internal lanes
631 std::vector<std::string> intLanes;
632 if (!OptionsCont::getOptions().getBool("no-internal-links")) {
633 for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
634 const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
635 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
636 if ((*k).toEdge == nullptr) {
637 continue;
638 }
639 if (!(*k).haveVia) {
640 intLanes.push_back((*k).getInternalLaneID());
641 } else {
642 intLanes.push_back((*k).viaID + "_0");
643 }
644 }
645 }
646 }
648 for (auto c : crossings) {
649 intLanes.push_back(c->id + "_0");
650 }
651 }
652 into.writeAttr(SUMO_ATTR_INTLANES, intLanes);
653 // close writing
655 // write optional radius
658 }
659 // specify whether a custom shape was used
660 if (n.hasCustomShape()) {
662 }
665 }
667 into.writeAttr<std::string>(SUMO_ATTR_FRINGE, toString(n.getFringeType()));
668 }
669 if (n.getName() != "") {
671 }
673 // write right-of-way logics
674 n.writeLogic(into);
675 }
676 n.writeParams(into);
677 into.closeTag();
678}
679
680
681bool
683 bool ret = false;
684 const std::vector<NBEdge*>& incoming = n.getIncomingEdges();
685 // build the list of internal lane ids
686 std::vector<std::string> internalLaneIDs;
687 std::map<std::string, std::string> viaIDs;
688 for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
689 const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
690 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
691 if ((*k).toEdge != nullptr) {
692 internalLaneIDs.push_back((*k).getInternalLaneID());
693 viaIDs[(*k).getInternalLaneID()] = ((*k).viaID);
694 }
695 }
696 }
697 for (auto c : n.getCrossings()) {
698 internalLaneIDs.push_back(c->id + "_0");
699 }
700 // write the internal nodes
701 for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
702 const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
703 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
704 if ((*k).toEdge == nullptr || !(*k).haveVia) {
705 continue;
706 }
707 Position pos = (*k).shape[-1];
708 into.openTag(SUMO_TAG_JUNCTION).writeAttr(SUMO_ATTR_ID, (*k).viaID + "_0");
711 std::string incLanes = (*k).getInternalLaneID();
712 std::vector<std::string> foeIDs;
713 for (std::string incLane : (*k).foeIncomingLanes) {
714 if (incLane[0] == ':') {
715 // intersecting left turns
716 const int index = StringUtils::toInt(incLane.substr(1));
717 incLane = internalLaneIDs[index];
718 if (viaIDs[incLane] != "") {
719 foeIDs.push_back(viaIDs[incLane] + "_0");
720 }
721 }
722 incLanes += " " + incLane;
723 }
724 into.writeAttr(SUMO_ATTR_INCLANES, incLanes);
725 const std::vector<int>& foes = (*k).foeInternalLinks;
726 for (std::vector<int>::const_iterator it = foes.begin(); it != foes.end(); ++it) {
727 foeIDs.push_back(internalLaneIDs[*it]);
728 }
729 into.writeAttr(SUMO_ATTR_INTLANES, joinToString(foeIDs, " "));
730 into.closeTag();
731 ret = true;
732 }
733 }
734 return ret;
735}
736
737
738void
740 bool includeInternal, ConnectionStyle style, bool geoAccuracy) {
741 assert(c.toEdge != 0);
743 into.writeAttr(SUMO_ATTR_FROM, from.getID());
747 if (style != TLL) {
748 if (c.mayDefinitelyPass) {
750 }
751 if (c.keepClear == KEEPCLEAR_FALSE) {
752 into.writeAttr<bool>(SUMO_ATTR_KEEP_CLEAR, false);
753 }
756 }
757 if (c.permissions != SVC_UNSPECIFIED) {
759 }
762 }
765 }
768 }
771 }
772 if (c.customShape.size() != 0) {
773 if (geoAccuracy) {
775 }
777 if (geoAccuracy) {
778 into.setPrecision();
779 }
780 }
781 if (c.uncontrolled != false) {
783 }
784 if (c.indirectLeft != false) {
786 }
787 if (c.edgeType != "") {
789 }
790 }
791 if (style != PLAIN) {
792 if (includeInternal) {
794 }
795 // set information about the controlling tl if any
796 if (c.tlID != "") {
799 if (c.tlLinkIndex2 >= 0) {
801 }
802 }
803 }
804 if (style != TLL) {
805 if (style == SUMONET) {
806 // write the direction information
807 LinkDirection dir = from.getToNode()->getDirection(&from, c.toEdge, OptionsCont::getOptions().getBool("lefthand"));
808 assert(dir != LinkDirection::NODIR);
809 into.writeAttr(SUMO_ATTR_DIR, toString(dir));
810 // write the state information
811 const LinkState linkState = from.getToNode()->getLinkState(
812 &from, c.toEdge, c.fromLane, c.toLane, c.mayDefinitelyPass, c.tlID);
813 into.writeAttr(SUMO_ATTR_STATE, linkState);
814 if (linkState == LINKSTATE_MINOR
817 const double visibilityDistance = OptionsCont::getOptions().getFloat("roundabouts.visibility-distance");
818 if (visibilityDistance != NBEdge::UNSPECIFIED_VISIBILITY_DISTANCE) {
819 into.writeAttr(SUMO_ATTR_VISIBILITY_DISTANCE, visibilityDistance);
820 }
821 }
822 }
825 }
826 }
827 c.writeParams(into);
828 into.closeTag();
829}
830
831
832bool
834 bool ret = false;
835 const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
836 const std::vector<NBEdge*>& incoming = n.getIncomingEdges();
837 for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); ++i) {
838 NBEdge* from = *i;
839 const std::vector<NBEdge::Connection>& connections = from->getConnections();
840 for (std::vector<NBEdge::Connection>::const_iterator j = connections.begin(); j != connections.end(); ++j) {
841 const NBEdge::Connection& c = *j;
842 LinkDirection dir = n.getDirection(from, c.toEdge, lefthand);
843 assert(c.toEdge != 0);
844 if (c.haveVia) {
845 // internal split with optional signal
846 std::string tlID = "";
847 int linkIndex2 = NBConnection::InvalidTlIndex;
849 linkIndex2 = c.tlLinkIndex2;
850 tlID = c.tlID;
851 }
852 writeInternalConnection(into, c.id, c.toEdge->getID(), c.internalLaneIndex, c.toLane, c.viaID + "_0", dir, tlID, linkIndex2, false, c.visibility);
854 } else {
855 // no internal split
856 writeInternalConnection(into, c.id, c.toEdge->getID(), c.internalLaneIndex, c.toLane, "", dir);
857 }
858 ret = true;
859 }
860 }
861 return ret;
862}
863
864
865void
867 const std::string& from, const std::string& to,
868 int fromLane, int toLane, const std::string& via,
869 LinkDirection dir,
870 const std::string& tlID, int linkIndex,
871 bool minor,
872 double visibility) {
874 into.writeAttr(SUMO_ATTR_FROM, from);
875 into.writeAttr(SUMO_ATTR_TO, to);
876 into.writeAttr(SUMO_ATTR_FROM_LANE, fromLane);
877 into.writeAttr(SUMO_ATTR_TO_LANE, toLane);
878 if (via != "") {
879 into.writeAttr(SUMO_ATTR_VIA, via);
880 }
881 if (tlID != "" && linkIndex != NBConnection::InvalidTlIndex) {
882 // used for the reverse direction of pedestrian crossings
883 into.writeAttr(SUMO_ATTR_TLID, tlID);
884 into.writeAttr(SUMO_ATTR_TLLINKINDEX, linkIndex);
885 }
886 into.writeAttr(SUMO_ATTR_DIR, dir);
887 into.writeAttr(SUMO_ATTR_STATE, ((via != "" || minor) ? "m" : "M"));
888 if (visibility != NBEdge::UNSPECIFIED_VISIBILITY_DISTANCE) {
890 }
891 into.closeTag();
892}
893
894
895void
896NWWriter_SUMO::writeRoundabouts(OutputDevice& into, const std::set<EdgeSet>& roundabouts,
897 const NBEdgeCont& ec) {
898 // make output deterministic
899 std::vector<std::vector<std::string> > edgeIDs;
900 for (std::set<EdgeSet>::const_iterator i = roundabouts.begin(); i != roundabouts.end(); ++i) {
901 std::vector<std::string> tEdgeIDs;
902 for (EdgeSet::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
903 // the edges may have been erased from NBEdgeCont but their pointers are still valid
904 // we verify their existance in writeRoundabout()
905 tEdgeIDs.push_back((*j)->getID());
906 }
907 std::sort(tEdgeIDs.begin(), tEdgeIDs.end());
908 edgeIDs.push_back(tEdgeIDs);
909 }
910 std::sort(edgeIDs.begin(), edgeIDs.end());
911 // write
912 for (std::vector<std::vector<std::string> >::const_iterator i = edgeIDs.begin(); i != edgeIDs.end(); ++i) {
913 writeRoundabout(into, *i, ec);
914 }
915 if (roundabouts.size() != 0) {
916 into.lf();
917 }
918}
919
920
921void
922NWWriter_SUMO::writeRoundabout(OutputDevice& into, const std::vector<std::string>& edgeIDs,
923 const NBEdgeCont& ec) {
924 std::vector<std::string> validEdgeIDs;
925 std::vector<std::string> invalidEdgeIDs;
926 std::vector<std::string> nodeIDs;
927 for (std::vector<std::string>::const_iterator i = edgeIDs.begin(); i != edgeIDs.end(); ++i) {
928 const NBEdge* edge = ec.retrieve(*i);
929 if (edge != nullptr) {
930 nodeIDs.push_back(edge->getToNode()->getID());
931 validEdgeIDs.push_back(edge->getID());
932 } else {
933 invalidEdgeIDs.push_back(*i);
934 }
935 }
936 std::sort(nodeIDs.begin(), nodeIDs.end());
937 if (validEdgeIDs.size() > 0) {
939 into.writeAttr(SUMO_ATTR_NODES, joinToString(nodeIDs, " "));
940 into.writeAttr(SUMO_ATTR_EDGES, joinToString(validEdgeIDs, " "));
941 into.closeTag();
942 if (invalidEdgeIDs.size() > 0) {
943 WRITE_WARNING("Writing incomplete roundabout. Edges: '"
944 + joinToString(invalidEdgeIDs, " ") + "' no longer exist'");
945 }
946 }
947}
948
949
950void
952 std::vector<double> sourceW = d.getSourceWeights();
954 std::vector<double> sinkW = d.getSinkWeights();
956 // write the head and the id of the district
958 if (d.getShape().size() > 0) {
960 }
961 // write all sources
962 const std::vector<NBEdge*>& sources = d.getSourceEdges();
963 for (int i = 0; i < (int)sources.size(); i++) {
964 // write the head and the id of the source
965 into.openTag(SUMO_TAG_TAZSOURCE).writeAttr(SUMO_ATTR_ID, sources[i]->getID()).writeAttr(SUMO_ATTR_WEIGHT, sourceW[i]);
966 into.closeTag();
967 }
968 // write all sinks
969 const std::vector<NBEdge*>& sinks = d.getSinkEdges();
970 for (int i = 0; i < (int)sinks.size(); i++) {
971 // write the head and the id of the sink
972 into.openTag(SUMO_TAG_TAZSINK).writeAttr(SUMO_ATTR_ID, sinks[i]->getID()).writeAttr(SUMO_ATTR_WEIGHT, sinkW[i]);
973 into.closeTag();
974 }
975 // write the tail
976 into.closeTag();
977}
978
979
980std::string
982 double time = STEPS2TIME(steps);
983 if (time == std::floor(time)) {
984 return toString(int(time));
985 } else {
986 return toString(time);
987 }
988}
989
990
991void
993 for (NBConnectionProhibits::const_iterator j = prohibitions.begin(); j != prohibitions.end(); j++) {
994 NBConnection prohibited = (*j).first;
995 const NBConnectionVector& prohibiting = (*j).second;
996 for (NBConnectionVector::const_iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
997 NBConnection prohibitor = *k;
1001 into.closeTag();
1002 }
1003 }
1004}
1005
1006
1007std::string
1009 return c.getFrom()->getID() + "->" + c.getTo()->getID();
1010}
1011
1012
1013void
1015 std::vector<NBTrafficLightLogic*> logics = tllCont.getComputed();
1016 for (NBTrafficLightLogic* logic : logics) {
1017 writeTrafficLight(into, logic);
1018 // only raise warnings on write instead of on compute (to avoid cluttering netedit)
1019 NBTrafficLightDefinition* def = tllCont.getDefinition(logic->getID(), logic->getProgramID());
1020 assert(def != nullptr);
1021 def->finalChecks();
1022 }
1023 if (logics.size() > 0) {
1024 into.lf();
1025 }
1026}
1027
1028
1029void
1032 into.writeAttr(SUMO_ATTR_ID, logic->getID());
1033 into.writeAttr(SUMO_ATTR_TYPE, logic->getType());
1036 // write the phases
1037 const bool varPhaseLength = logic->getType() != TrafficLightType::STATIC;
1038 for (const NBTrafficLightLogic::PhaseDefinition& phase : logic->getPhases()) {
1039 into.openTag(SUMO_TAG_PHASE);
1040 into.writeAttr(SUMO_ATTR_DURATION, writeSUMOTime(phase.duration));
1041 if (phase.duration < TIME2STEPS(10)) {
1042 into.writePadding(" ");
1043 }
1044 into.writeAttr(SUMO_ATTR_STATE, phase.state);
1045 if (varPhaseLength) {
1047 into.writeAttr(SUMO_ATTR_MINDURATION, writeSUMOTime(phase.minDur));
1048 }
1050 into.writeAttr(SUMO_ATTR_MAXDURATION, writeSUMOTime(phase.maxDur));
1051 }
1052 if (phase.earliestEnd != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
1053 into.writeAttr(SUMO_ATTR_EARLIEST_END, writeSUMOTime(phase.earliestEnd));
1054 }
1055 if (phase.latestEnd != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
1056 into.writeAttr(SUMO_ATTR_LATEST_END, writeSUMOTime(phase.latestEnd));
1057 }
1058 // NEMA attributes
1061 }
1063 into.writeAttr(SUMO_ATTR_YELLOW, writeSUMOTime(phase.yellow));
1064 }
1066 into.writeAttr(SUMO_ATTR_RED, writeSUMOTime(phase.red));
1067 }
1068 }
1069 if (phase.name != "") {
1071 }
1072 if (phase.next.size() > 0) {
1073 into.writeAttr(SUMO_ATTR_NEXT, phase.next);
1074 }
1075 into.closeTag();
1076 }
1077 // write params
1078 logic->writeParams(into);
1079 into.closeTag();
1080}
1081
1082
1083void
1085 if (stopOffset.isDefined()) {
1086 const std::string ss_vclasses = getVehicleClassNames(stopOffset.getPermissions());
1087 if (ss_vclasses.length() == 0) {
1088 // This stopOffset would have no effect...
1089 return;
1090 }
1092 const std::string ss_exceptions = getVehicleClassNames(~stopOffset.getPermissions());
1093 if (ss_vclasses.length() <= ss_exceptions.length()) {
1094 into.writeAttr(SUMO_ATTR_VCLASSES, ss_vclasses);
1095 } else {
1096 if (ss_exceptions.length() == 0) {
1097 into.writeAttr(SUMO_ATTR_VCLASSES, "all");
1098 } else {
1099 into.writeAttr(SUMO_ATTR_EXCEPTIONS, ss_exceptions);
1100 }
1101 }
1102 into.writeAttr(SUMO_ATTR_VALUE, stopOffset.getOffset());
1103 into.closeTag();
1104 }
1105}
1106
1107
1108/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:271
#define WRITE_ERROR(msg)
Definition MsgHandler.h:279
#define WRITE_WARNING(msg)
Definition MsgHandler.h:270
#define TL(string)
Definition MsgHandler.h:287
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 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;
@ SVC_IGNORING
vehicles ignoring classes
@ SVC_PEDESTRIAN
pedestrian
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
@ SUMO_TAG_PHASE
a single phase description
@ SUMO_TAG_STOPOFFSET
Information on vClass specific stop offsets at lane end.
@ SUMO_TAG_TAZ
a traffic assignment zone
@ SUMO_TAG_TAZSINK
a sink within a district (connection road)
@ SUMO_TAG_PROHIBITION
prohibition of circulation between two edges
@ SUMO_TAG_CONNECTION
connectioon between two lanes
@ SUMO_TAG_ROUNDABOUT
roundabout defined in junction
@ SUMO_TAG_TLLOGIC
a traffic light logic
@ SUMO_TAG_JUNCTION
begin/end of the description of a junction
@ SUMO_TAG_LANE
begin/end of the description of a single lane
@ SUMO_TAG_TAZSOURCE
a source within a district (connection road)
@ SUMO_TAG_NEIGH
begin/end of the description of a neighboring lane
@ SUMO_TAG_EDGE
begin/end of the description of an edge
LinkDirection
The different directions a link between two lanes may take (or a stream between two edges)....
@ STRAIGHT
The link is a straight direction.
@ NODIR
The link has no direction (is a dead end link)
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic,...
@ LINKSTATE_MAJOR
This is an uncontrolled, major link, may pass.
@ LINKSTATE_MINOR
This is an uncontrolled, minor link, has to brake.
@ SUMO_ATTR_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_CHECKLANEFOES_ALL
@ SUMO_ATTR_SPREADTYPE
The information about how to spread the lanes from the given position.
@ SUMO_ATTR_PASS
@ SUMO_ATTR_ENDOFFSET
@ SUMO_ATTR_HIGHER_SPEED
@ SUMO_ATTR_TO
@ SUMO_ATTR_FROM
@ SUMO_ATTR_ACCELERATION
@ SUMO_ATTR_CHANGE_RIGHT
@ SUMO_ATTR_TLID
link,node: the traffic light id responsible for this link
@ SUMO_ATTR_DISTANCE
@ SUMO_ATTR_TO_LANE
@ SUMO_ATTR_UNCONTROLLED
@ SUMO_ATTR_TYPE
@ SUMO_ATTR_LENGTH
@ SUMO_ATTR_VERSION
@ SUMO_ATTR_ID
@ SUMO_ATTR_MAXDURATION
maximum duration of a phase
@ SUMO_ATTR_RIGHT_OF_WAY
How to compute right of way.
@ SUMO_ATTR_PROGRAMID
@ SUMO_ATTR_FUNCTION
@ SUMO_ATTR_VISIBILITY_DISTANCE
foe visibility distance of a link
@ SUMO_ATTR_PROHIBITOR
@ SUMO_ATTR_DURATION
@ SUMO_ATTR_CONTPOS
@ SUMO_ATTR_WIDTH
@ SUMO_ATTR_CROSSING_EDGES
the edges crossed by a pedestrian crossing
@ SUMO_ATTR_DIR
The abstract direction of a link.
@ SUMO_ATTR_TLS_IGNORE_INTERNAL_JUNCTION_JAM
@ SUMO_ATTR_TLLINKINDEX
link: the index of the link within the traffic light
@ SUMO_ATTR_MINDURATION
@ SUMO_ATTR_KEEP_CLEAR
Whether vehicles must keep the junction clear.
@ SUMO_ATTR_INTERNAL_JUNCTIONS_VEHICLE_WIDTH
@ SUMO_ATTR_STATE
The state of a link.
@ SUMO_ATTR_FRICTION
@ SUMO_ATTR_WALKINGAREAS
@ SUMO_ATTR_EARLIEST_END
The minimum time within the cycle for switching (for coordinated actuation)
int gPrecisionGeo
Definition StdDefs.cpp:27
const MMVersion NETWORK_VERSION(1, 16)
T MAX2(T a, T b)
Definition StdDefs.h:82
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
Definition ToString.h:283
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
static void writeLocation(OutputDevice &into)
writes the location element
NBEdge * getFrom() const
returns the from-edge (start of the connection)
static const int InvalidTlIndex
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:1027
@ ROUNDABOUT
Definition NBEdge.h:377
double getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn't set.
Definition NBEdge.h:592
NBNode * getToNode() const
Returns the destination node of the edge.
Definition NBEdge.h:536
static const double UNSPECIFIED_FRICTION
unspecified lane friction
Definition NBEdge.h:350
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition NBEdge.h:771
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge's lanes' lateral offset is computed.
Definition NBEdge.cpp:948
bool isBidiRail(bool ignoreSpread=false) const
whether this edge is part of a bidirectional railway
Definition NBEdge.cpp:729
bool hasLoadedLength() const
Returns whether a length was set explicitly.
Definition NBEdge.h:602
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
Definition NBEdge.h:720
const std::string & getID() const
Definition NBEdge.h:1515
double getDistance() const
get distance
Definition NBEdge.h:669
static const double UNSPECIFIED_LOADED_LENGTH
no length override given
Definition NBEdge.h:359
const StopOffset & getEdgeStopOffset() const
Returns the stopOffset to the end of the edge.
Definition NBEdge.cpp:4085
int getNumLanes() const
Returns the number of lanes.
Definition NBEdge.h:510
std::vector< Connection > getConnectionsFromLane(int lane, const NBEdge *to=nullptr, int toLane=-1) const
Returns connections from a given lane.
Definition NBEdge.cpp:1221
static const double UNSPECIFIED_CONTPOS
unspecified internal junction position
Definition NBEdge.h:353
static const double UNSPECIFIED_VISIBILITY_DISTANCE
unspecified foe visibility for connections
Definition NBEdge.h:356
std::string getLaneID(int lane) const
get lane ID
Definition NBEdge.cpp:3870
static const double UNSPECIFIED_SPEED
unspecified lane speed
Definition NBEdge.h:347
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
Definition NBEdge.cpp:2051
const std::string & getTypeID() const
get ID of type
Definition NBEdge.h:1167
const std::string & getStreetName() const
Returns the street name of this edge.
Definition NBEdge.h:659
const NBEdge * getBidiEdge() const
Definition NBEdge.h:1501
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition NBEdge.h:529
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition NBEdge.cpp:3861
bool hasDefaultGeometry() const
Returns whether the geometry consists only of the node positions.
Definition NBEdge.cpp:588
int getPriority() const
Returns the priority of the edge.
Definition NBEdge.h:517
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition NBEdge.h:341
double getEndOffset() const
Returns the offset to the destination node.
Definition NBEdge.h:679
static const double UNSPECIFIED_OFFSET
unspecified lane offset
Definition NBEdge.h:344
bool isMacroscopicConnector() const
Returns whether this edge was marked as a macroscopic connector.
Definition NBEdge.h:1122
double getFinalLength() const
get length that will be assigned to the lanes in the final network
Definition NBEdge.cpp:4564
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:160
std::string tlID
The id of the traffic light that controls this connection.
Definition NBNode.h:166
bool priority
whether the pedestrians have priority
Definition NBNode.h:156
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:2315
RightOfWay getRightOfWay() const
Returns hint on how to compute right of way.
Definition NBNode.h:298
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:2398
static const double UNSPECIFIED_RADIUS
unspecified lane width
Definition NBNode.h:218
Crossing * getCrossing(const std::string &id) const
return the crossing with the given id
Definition NBNode.cpp:3686
FringeType getFringeType() const
Returns fringe type.
Definition NBNode.h:303
SumoXMLNodeType getType() const
Returns the type of this node.
Definition NBNode.h:283
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
Definition NBNode.h:266
bool hasCustomShape() const
return whether the shape was set by the user
Definition NBNode.h:582
bool brakeForCrossingOnExit(const NBEdge *to) const
whether a connection to the given edge must brake for a crossing when leaving the intersection
Definition NBNode.cpp:1986
std::vector< Crossing * > getCrossings() const
return this junctions pedestrian crossings
Definition NBNode.cpp:2905
const std::string & getName() const
Returns intersection name.
Definition NBNode.h:308
bool writeLogic(OutputDevice &into) const
writes the XML-representation of the logic as a bitset-logic XML representation
Definition NBNode.cpp:1054
const Position & getPosition() const
Definition NBNode.h:258
const PositionVector & getShape() const
retrieve the junction shape
Definition NBNode.cpp:2571
double getRadius() const
Returns the turning radius of this node.
Definition NBNode.h:288
const std::vector< WalkingArea > & getWalkingAreas() const
return this junctions pedestrian walking areas
Definition NBNode.h:742
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:198
static void writeConnection(OutputDevice &into, const NBEdge &from, const NBEdge::Connection &c, bool includeInternal, ConnectionStyle style=SUMONET, bool geoAccuracy=false)
Writes connections outgoing from the given edge (also used in NWWriter_XML)
static void writeNetwork(const OptionsCont &oc, NBNetBuilder &nb)
Writes the network into a SUMO-file.
static bool writeInternalNodes(OutputDevice &into, const NBNode &n)
Writes internal junctions (<junction with id[0]==':' ...) of the given node.
static void writeProhibitions(OutputDevice &into, const NBConnectionProhibits &prohibitions)
writes the given prohibitions
static void writeEdge(OutputDevice &into, const NBEdge &e, bool noNames)
Writes an edge (<edge ...)
static std::string getOppositeInternalID(const NBEdgeCont &ec, const NBEdge *from, const NBEdge::Connection &con, double &oppositeLength)
retrieve the id of the opposite direction internal lane if it exists
static std::string writeSUMOTime(SUMOTime time)
writes a SUMOTime as int if possible, otherwise as a float
static void writeJunction(OutputDevice &into, const NBNode &n)
Writes a junction (<junction ...)
static bool writeInternalEdges(OutputDevice &into, const NBEdgeCont &ec, const NBNode &n)
Writes internal edges (<edge ... with id[0]==':') of the given node.
static std::string getInternalBidi(const NBEdge *e, const NBEdge::Connection &k)
retrieve bidi edge id for internal corresponding to the given connection
static bool writeInternalConnections(OutputDevice &into, const NBNode &n)
Writes inner connections within the node.
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 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 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)
Writes a lane (<lane ...) of an 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
stop offset
bool isDefined() const
check if stopOffset was defined
SVCPermissions getPermissions() const
get permissions
double getOffset() const
get offset
static std::string escapeXML(const std::string &orig, const bool maskDoubleHyphen=false)
Replaces the standard escapes by their XML entities.
static int toInt(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter,...
static void normaliseSum(std::vector< T > &v, T msum=1.0)
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
std::string viaID
if Connection have a via, ID of it
Definition NBEdge.h:279
int toLane
The lane the connections yields in.
Definition NBEdge.h:216
SVCPermissions permissions
List of vehicle types that are allowed on this connection.
Definition NBEdge.h:252
double speed
custom speed for connection
Definition NBEdge.h:240
NBEdge * toEdge
The edge the connections yields in.
Definition NBEdge.h:213
KeepClear keepClear
whether the junction must be kept clear when using this connection
Definition NBEdge.h:231
double customLength
custom length for connection
Definition NBEdge.h:246
std::string edgeType
optional type of Connection
Definition NBEdge.h:264
bool uncontrolled
check if Connection is uncontrolled
Definition NBEdge.h:297
PositionVector customShape
custom shape for connection
Definition NBEdge.h:249
bool mayDefinitelyPass
Information about being definitely free to drive (on-ramps)
Definition NBEdge.h:228
SVCPermissions changeLeft
List of vehicle types that are allowed to change Left from this connections internal lane(s)
Definition NBEdge.h:255
SVCPermissions changeRight
List of vehicle types that are allowed to change right from this connections internal lane(s)
Definition NBEdge.h:258
std::string getDescription(const NBEdge *parent) const
get string describing this connection
Definition NBEdge.cpp:96
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:90
int internalLaneIndex
The lane index of this internal lane within the internal edge.
Definition NBEdge.h:294
std::string tlID
The id of the traffic light that controls this connection.
Definition NBEdge.h:219
double visibility
custom foe visiblity for connection
Definition NBEdge.h:237
int tlLinkIndex2
The index of the internal junction within the controlling traffic light (optional)
Definition NBEdge.h:225
double length
computed length (average of all internal lane shape lengths that share an internal edge)
Definition NBEdge.h:306
std::string id
id of Connection
Definition NBEdge.h:267
bool haveVia
check if Connection have a Via
Definition NBEdge.h:276
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:175
std::string id
the (edge)-id of this walkingArea
Definition NBNode.h:182
bool hasCustomShape
whether this walkingArea has a custom shape
Definition NBNode.h:198
double width
This lane's width.
Definition NBNode.h:184
PositionVector shape
The polygonal shape.
Definition NBNode.h:188
double length
This lane's width.
Definition NBNode.h:186