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-2024 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
21// Exporter writing networks using the SUMO format
22/****************************************************************************/
23#include <config.h>
24#include <cmath>
25#include <algorithm>
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 if (!oc.isDefault("junctions.minimal-shape")) {
111 attrs[SUMO_ATTR_JUNCTIONS_MINIMAL_SHAPE] = toString(oc.getBool("junctions.minimal-shape"));
112 }
113 if (!oc.isDefault("junctions.endpoint-shape")) {
114 attrs[SUMO_ATTR_JUNCTIONS_ENDPOINT_SHAPE] = toString(oc.getBool("junctions.endpoint-shape"));
115 }
116 device.writeXMLHeader("net", "net_file.xsd", attrs); // street names may contain non-ascii chars
117 device.lf();
118 // get involved container
119 const NBNodeCont& nc = nb.getNodeCont();
120 const NBEdgeCont& ec = nb.getEdgeCont();
121 const NBDistrictCont& dc = nb.getDistrictCont();
122
123 // write network offsets and projection
125
126 // write edge types and restrictions
127 std::set<std::string> usedTypes = ec.getUsedTypes();
128 nb.getTypeCont().writeEdgeTypes(device, usedTypes);
129
130 // write inner lanes
131 if (!oc.getBool("no-internal-links")) {
132 bool hadAny = false;
133 for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
134 hadAny |= writeInternalEdges(device, ec, *(*i).second);
135 }
136 if (hadAny) {
137 device.lf();
138 }
139 }
140
141 // write edges with lanes and connected edges
142 bool noNames = !oc.getBool("output.street-names");
143 for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
144 writeEdge(device, *(*i).second, noNames);
145 }
146 device.lf();
147
148 // write tls logics
150
151 // write the nodes (junctions)
152 for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
153 writeJunction(device, *(*i).second);
154 }
155 device.lf();
156 const bool includeInternal = !oc.getBool("no-internal-links");
157 if (includeInternal) {
158 // ... internal nodes if not unwanted
159 bool hadAny = false;
160 for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
161 hadAny |= writeInternalNodes(device, *(*i).second);
162 }
163 if (hadAny) {
164 device.lf();
165 }
166 }
167
168 // write the successors of lanes
169 int numConnections = 0;
170 for (std::map<std::string, NBEdge*>::const_iterator it_edge = ec.begin(); it_edge != ec.end(); it_edge++) {
171 NBEdge* from = it_edge->second;
172 const std::vector<NBEdge::Connection>& connections = from->getConnections();
173 numConnections += (int)connections.size();
174 for (const NBEdge::Connection& con : connections) {
175 writeConnection(device, *from, con, includeInternal);
176 }
177 }
178 if (numConnections > 0) {
179 device.lf();
180 }
181 if (includeInternal) {
182 // ... internal successors if not unwanted
183 bool hadAny = false;
184 for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
185 hadAny |= writeInternalConnections(device, *(*i).second);
186 }
187 if (hadAny) {
188 device.lf();
189 }
190 }
191 for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
192 NBNode* node = (*i).second;
193 // write connections from pedestrian crossings
194 std::vector<NBNode::Crossing*> crossings = node->getCrossings();
195 for (auto c : crossings) {
196 NWWriter_SUMO::writeInternalConnection(device, c->id, c->nextWalkingArea, 0, 0, "", LinkDirection::STRAIGHT, c->tlID, c->tlLinkIndex2);
197 }
198 // write connections from pedestrian walking areas
199 for (const NBNode::WalkingArea& wa : node->getWalkingAreas()) {
200 for (const std::string& cID : wa.nextCrossings) {
201 const NBNode::Crossing& nextCrossing = *node->getCrossing(cID);
202 // connection to next crossing (may be tls-controlled)
204 device.writeAttr(SUMO_ATTR_FROM, wa.id);
205 device.writeAttr(SUMO_ATTR_TO, cID);
207 device.writeAttr(SUMO_ATTR_TO_LANE, 0);
208 if (nextCrossing.tlID != "") {
209 device.writeAttr(SUMO_ATTR_TLID, nextCrossing.tlID);
210 assert(nextCrossing.tlLinkIndex >= 0);
211 device.writeAttr(SUMO_ATTR_TLLINKINDEX, nextCrossing.tlLinkIndex);
212 }
215 device.closeTag();
216 }
217 // optional connections from/to sidewalk
218 std::string edgeID;
219 int laneIndex;
220 for (const std::string& sw : wa.nextSidewalks) {
221 NBHelpers::interpretLaneID(sw, edgeID, laneIndex);
222 NWWriter_SUMO::writeInternalConnection(device, wa.id, edgeID, 0, laneIndex, "");
223 }
224 for (const std::string& sw : wa.prevSidewalks) {
225 NBHelpers::interpretLaneID(sw, edgeID, laneIndex);
226 NWWriter_SUMO::writeInternalConnection(device, edgeID, wa.id, laneIndex, 0, "");
227 }
228 }
229 }
230
231 // write loaded prohibitions
232 for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
233 writeProhibitions(device, i->second->getProhibitions());
234 }
235
236 // write roundabout information
237 writeRoundabouts(device, ec.getRoundabouts(), ec);
238
239 // write the districts
240 if (dc.size() != 0 && oc.isDefault("taz-output")) {
241 WRITE_WARNING(TL("Embedding TAZ-data inside the network is deprecated. Use option --taz-output instead"));
242 for (std::map<std::string, NBDistrict*>::const_iterator i = dc.begin(); i != dc.end(); i++) {
243 writeDistrict(device, *(*i).second);
244 }
245 device.lf();
246 }
247 device.close();
248}
249
250
251std::string
252NWWriter_SUMO::getOppositeInternalID(const NBEdgeCont& ec, const NBEdge* from, const NBEdge::Connection& con, double& oppositeLength) {
253 const NBEdge::Lane& succ = con.toEdge->getLanes()[con.toLane];
254 const NBEdge::Lane& pred = from->getLanes()[con.fromLane];
255 const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
256 if (succ.oppositeID != "" && succ.oppositeID != "-" && pred.oppositeID != "" && pred.oppositeID != "-") {
257#ifdef DEBUG_OPPOSITE_INTERNAL
258 std::cout << "getOppositeInternalID con=" << con.getDescription(from) << " (" << con.getInternalLaneID() << ")\n";
259#endif
260 // find the connection that connects succ.oppositeID to pred.oppositeID
261 const NBEdge* succOpp = ec.retrieve(succ.oppositeID.substr(0, succ.oppositeID.rfind("_")));
262 const NBEdge* predOpp = ec.retrieve(pred.oppositeID.substr(0, pred.oppositeID.rfind("_")));
263 assert(succOpp != 0);
264 assert(predOpp != 0);
265 const std::vector<NBEdge::Connection>& connections = succOpp->getConnections();
266 for (std::vector<NBEdge::Connection>::const_iterator it_c = connections.begin(); it_c != connections.end(); it_c++) {
267 const NBEdge::Connection& conOpp = *it_c;
268 if (succOpp != from // turnaround
269 && predOpp == conOpp.toEdge
270 && succOpp->getLaneID(conOpp.fromLane) == succ.oppositeID
271 && predOpp->getLaneID(conOpp.toLane) == pred.oppositeID
272 && from->getToNode()->getDirection(from, con.toEdge, lefthand) == LinkDirection::STRAIGHT
273 && from->getToNode()->getDirection(succOpp, predOpp, lefthand) == LinkDirection::STRAIGHT
274 ) {
275#ifdef DEBUG_OPPOSITE_INTERNAL
276 std::cout << " found " << conOpp.getInternalLaneID() << "\n";
277#endif
278 oppositeLength = conOpp.length;
279 return conOpp.getInternalLaneID();
280 } else {
281 /*
282 #ifdef DEBUG_OPPOSITE_INTERNAL
283 std::cout << " rejected " << conOpp.getInternalLaneID()
284 << "\n succ.oppositeID=" << succ.oppositeID
285 << "\n succOppLane=" << succOpp->getLaneID(conOpp.fromLane)
286 << "\n pred.oppositeID=" << pred.oppositeID
287 << "\n predOppLane=" << predOpp->getLaneID(conOpp.toLane)
288 << "\n predOpp=" << predOpp->getID()
289 << "\n conOppTo=" << conOpp.toEdge->getID()
290 << "\n len1=" << con.shape.length()
291 << "\n len2=" << conOpp.shape.length()
292 << "\n";
293 #endif
294 */
295 }
296 }
297 return "";
298 } else {
299 return "";
300 }
301}
302
303
304bool
306 bool ret = false;
307 const EdgeVector& incoming = n.getIncomingEdges();
308 // first pass: determine opposite internal edges and average their length
309 std::map<std::string, std::string> oppositeLaneID;
310 std::map<std::string, double> oppositeLengths;
311 for (NBEdge* e : incoming) {
312 for (const NBEdge::Connection& c : e->getConnections()) {
313 double oppositeLength = 0;
314 const std::string op = getOppositeInternalID(ec, e, c, oppositeLength);
315 oppositeLaneID[c.getInternalLaneID()] = op;
316 if (op != "") {
317 oppositeLengths[c.id] = oppositeLength;
318 }
319 }
320 }
321 if (oppositeLengths.size() > 0) {
322 for (NBEdge* e : incoming) {
323 for (NBEdge::Connection& c : e->getConnections()) {
324 if (oppositeLengths.count(c.id) > 0) {
325 c.length = (c.length + oppositeLengths[c.id]) / 2;
326 }
327 }
328 }
329 }
330
331 for (NBEdge* e : incoming) {
332 const std::vector<NBEdge::Connection>& elv = e->getConnections();
333 if (elv.size() > 0) {
334 bool haveVia = false;
335 std::string edgeID = "";
336 double bidiLength = -1;
337 // second pass: write non-via edges
338 for (const NBEdge::Connection& k : elv) {
339 if (k.toEdge == nullptr) {
340 assert(false); // should never happen. tell me when it does
341 continue;
342 }
343 if (edgeID != k.id) {
344 if (edgeID != "") {
345 // close the previous edge
346 into.closeTag();
347 }
348 edgeID = k.id;
350 into.writeAttr(SUMO_ATTR_ID, edgeID);
352 if (k.edgeType != "") {
353 into.writeAttr(SUMO_ATTR_TYPE, k.edgeType);
354 }
355 bidiLength = -1;
356 if (e->getBidiEdge() && k.toEdge->getBidiEdge() &&
357 e != k.toEdge->getTurnDestination(true)) {
358 const std::string bidiEdge = getInternalBidi(e, k, bidiLength);
359 if (bidiEdge != "") {
360 into.writeAttr(SUMO_ATTR_BIDI, bidiEdge);
361 }
362 }
363 // open a new edge
364 }
365 // to avoid changing to an internal lane which has a successor
366 // with the wrong permissions we need to inherit them from the successor
367 const NBEdge::Lane& successor = k.toEdge->getLanes()[k.toLane];
368 SVCPermissions permissions = (k.permissions != SVC_UNSPECIFIED) ? k.permissions : (
369 successor.permissions & e->getPermissions(k.fromLane));
370 SVCPermissions changeLeft = k.changeLeft != SVC_UNSPECIFIED ? k.changeLeft : SVCAll;
371 SVCPermissions changeRight = k.changeRight != SVC_UNSPECIFIED ? k.changeRight : SVCAll;
372 const double width = e->getInternalLaneWidth(n, k, successor, false);
373 const double length = bidiLength > 0 ? bidiLength : k.length;
374 writeLane(into, k.getInternalLaneID(), k.vmax, k.friction,
375 permissions, successor.preferred,
376 changeLeft, changeRight,
378 StopOffset(), width, k.shape, &k,
379 length, k.internalLaneIndex, oppositeLaneID[k.getInternalLaneID()], "");
380 haveVia = haveVia || k.haveVia;
381 }
382 ret = true;
383 into.closeTag(); // close the last edge
384 // third pass: write via edges
385 if (haveVia) {
386 std::string viaEdgeID = "";
387 for (const NBEdge::Connection& k : elv) {
388 if (!k.haveVia) {
389 continue;
390 }
391 if (k.toEdge == nullptr) {
392 assert(false); // should never happen. tell me when it does
393 continue;
394 }
395 if (viaEdgeID != k.viaID) {
396 if (viaEdgeID != "") {
397 // close the previous edge
398 into.closeTag();
399 }
400 viaEdgeID = k.viaID;
401 // open a new edge
403 into.writeAttr(SUMO_ATTR_ID, viaEdgeID);
405 if (k.edgeType != "") {
406 into.writeAttr(SUMO_ATTR_TYPE, k.edgeType);
407 }
408 }
409 const NBEdge::Lane& successor = k.toEdge->getLanes()[k.toLane];
410 SVCPermissions permissions = (k.permissions != SVC_UNSPECIFIED) ? k.permissions : (
411 successor.permissions & e->getPermissions(k.fromLane));
412 const double width = e->getInternalLaneWidth(n, k, successor, true);
413 writeLane(into, k.getInternalViaLaneID(), k.vmax, k.friction, permissions, successor.preferred,
414 SVCAll, SVCAll, // #XXX todo
416 StopOffset(), width, k.viaShape, &k,
417 MAX2(k.viaLength, POSITION_EPS), // microsim needs positive length
418 0, "", "");
419 }
420 into.closeTag();
421 }
422 }
423 }
424 // write pedestrian crossings
425 const double crossingSpeed = OptionsCont::getOptions().getFloat("default.crossing-speed");
426 for (auto c : n.getCrossings()) {
428 into.writeAttr(SUMO_ATTR_ID, c->id);
430 into.writeAttr(SUMO_ATTR_CROSSING_EDGES, c->edges);
431 writeLane(into, c->id + "_0", crossingSpeed, NBEdge::UNSPECIFIED_FRICTION, SVC_PEDESTRIAN, 0, SVCAll, SVCAll,
433 StopOffset(), c->width, c->shape, c,
434 MAX2(c->shape.length(), POSITION_EPS), 0, "", "", false, c->customShape.size() != 0, c->outlineShape);
435 into.closeTag();
436 }
437 // write pedestrian walking areas
438 const double walkingareaSpeed = OptionsCont::getOptions().getFloat("default.walkingarea-speed");
439 const std::vector<NBNode::WalkingArea>& WalkingAreas = n.getWalkingAreas();
440 for (std::vector<NBNode::WalkingArea>::const_iterator it = WalkingAreas.begin(); it != WalkingAreas.end(); it++) {
441 const NBNode::WalkingArea& wa = *it;
443 into.writeAttr(SUMO_ATTR_ID, wa.id);
445 writeLane(into, wa.id + "_0", walkingareaSpeed, NBEdge::UNSPECIFIED_FRICTION, SVC_PEDESTRIAN, 0, SVCAll, SVCAll,
447 StopOffset(), wa.width, wa.shape, nullptr, wa.length, 0, "", "", false, wa.hasCustomShape);
448 into.closeTag();
449 }
450 return ret;
451}
452
453
454std::string
455NWWriter_SUMO::getInternalBidi(const NBEdge* e, const NBEdge::Connection& k, double& length) {
456 const NBEdge* fromBidi = e->getTurnDestination(true);
457 const NBEdge* toBidi = k.toEdge->getTurnDestination(true);
458 const std::vector<NBEdge::Connection> cons = toBidi->getConnectionsFromLane(-1, fromBidi, -1);
459 if (cons.size() > 0) {
460 if (e->getNumLanes() == 1 && k.toEdge->getNumLanes() == 1 && fromBidi->getNumLanes() == 1 && toBidi->getNumLanes() == 1) {
461 length = (k.length + cons.back().length) / 2;
462 return cons.back().id;
463 }
464 // do a more careful check in case there are parallel internal edges
465 // note: k is the first connection with the new id
466 for (const NBEdge::Connection& c : e->getConnections()) {
467 if (c.id == k.id) {
468 PositionVector rShape = c.shape.reverse();
469 for (const NBEdge::Connection& k2 : cons) {
470 if (k2.shape.almostSame(rShape, POSITION_EPS)) {
471 length = (c.length + k2.length) / 2;
472 return k2.id;
473 }
474 }
475 }
476 }
477 } else {
478 WRITE_WARNINGF(TL("Could not find bidi-connection for edge '%'"), k.id)
479 }
480 return "";
481}
482
483void
484NWWriter_SUMO::writeEdge(OutputDevice& into, const NBEdge& e, bool noNames) {
485 // write the edge's begin
489 if (!noNames && e.getStreetName() != "") {
491 }
493 if (e.getTypeID() != "") {
495 }
496 if (e.isMacroscopicConnector()) {
498 }
499 // write the spread type if not default ("right")
502 }
503 if (e.hasLoadedLength()) {
505 }
506 if (!e.hasDefaultGeometry()) {
508 }
509 if (e.getEdgeStopOffset().isDefined()) {
511 }
512 if (e.getBidiEdge()) {
514 }
515 if (e.getDistance() != 0) {
517 }
518
519 // write the lanes
520 const std::vector<NBEdge::Lane>& lanes = e.getLanes();
521
522 double length = e.getFinalLength();
523 if (e.getBidiEdge() != nullptr) {
524 length = (length + e.getBidiEdge()->getFinalLength()) / 2;
525 }
526 double startOffset = e.isBidiRail() ? e.getTurnDestination(true)->getEndOffset() : 0;
527 for (int i = 0; i < (int) lanes.size(); i++) {
528 const NBEdge::Lane& l = lanes[i];
529 StopOffset stopOffset;
530 if (l.laneStopOffset != e.getEdgeStopOffset()) {
531 stopOffset = l.laneStopOffset;
532 }
533 writeLane(into, e.getLaneID(i), l.speed, l.friction,
536 startOffset, l.endOffset,
537 stopOffset, l.width, l.shape, &l,
538 length, i, l.oppositeID, l.type, l.accelRamp, l.customShape.size() > 0);
539 }
540 // close the edge
541 e.writeParams(into);
542 into.closeTag();
543}
544
545
546void
547NWWriter_SUMO::writeLane(OutputDevice& into, const std::string& lID,
548 double speed, double friction,
549 SVCPermissions permissions, SVCPermissions preferred,
550 SVCPermissions changeLeft, SVCPermissions changeRight,
551 double startOffset, double endOffset,
552 const StopOffset& stopOffset, double width, PositionVector shape,
553 const Parameterised* params, double length, int index,
554 const std::string& oppositeID,
555 const std::string& type,
556 bool accelRamp, bool customShape,
557 const PositionVector& outlineShape) {
558 // output the lane's attributes
560 // the first lane of an edge will be the depart lane
561 into.writeAttr(SUMO_ATTR_INDEX, index);
562 // write the list of allowed/disallowed vehicle classes
563 if (permissions != SVC_UNSPECIFIED) {
564 writePermissions(into, permissions);
565 }
566 writePreferences(into, preferred);
567 // some further information
568 into.writeAttr(SUMO_ATTR_SPEED, MAX2(0.0, speed));
569 if (friction != NBEdge::UNSPECIFIED_FRICTION) {
570 into.writeAttr(SUMO_ATTR_FRICTION, friction);
571 }
572 into.writeAttr(SUMO_ATTR_LENGTH, length);
573 if (endOffset != NBEdge::UNSPECIFIED_OFFSET) {
574 into.writeAttr(SUMO_ATTR_ENDOFFSET, endOffset);
575 }
576 if (width != NBEdge::UNSPECIFIED_WIDTH) {
577 into.writeAttr(SUMO_ATTR_WIDTH, width);
578 }
579 if (accelRamp) {
580 into.writeAttr<bool>(SUMO_ATTR_ACCELERATION, accelRamp);
581 }
582 if (customShape) {
584 }
585 if (endOffset > 0 || startOffset > 0) {
586 startOffset = MIN2(startOffset, shape.length() - POSITION_EPS);
587 endOffset = MIN2(endOffset, shape.length() - startOffset - POSITION_EPS);
588 assert(startOffset + endOffset < shape.length());
589 shape = shape.getSubpart(startOffset, shape.length() - endOffset);
590 }
591 into.writeAttr(SUMO_ATTR_SHAPE, shape);
592 if (type != "") {
593 into.writeAttr(SUMO_ATTR_TYPE, type);
594 }
595 if (changeLeft != SVC_UNSPECIFIED && changeLeft != SVCAll && changeLeft != SVC_IGNORING) {
597 }
598 if (changeRight != SVC_UNSPECIFIED && changeRight != SVCAll && changeRight != SVC_IGNORING) {
600 }
601 if (stopOffset.isDefined()) {
602 writeStopOffsets(into, stopOffset);
603 }
604 if (outlineShape.size() != 0) {
605 into.writeAttr(SUMO_ATTR_OUTLINESHAPE, outlineShape);
606 }
607
608 if (oppositeID != "" && oppositeID != "-") {
610 into.writeAttr(SUMO_ATTR_LANE, oppositeID);
611 into.closeTag();
612 }
613
614 if (params != nullptr) {
615 params->writeParams(into);
616 }
617
618 into.closeTag();
619}
620
621
622void
624 // write the attributes
628 // write the incoming lanes
629 std::vector<std::string> incLanes;
630 const std::vector<NBEdge*>& incoming = n.getIncomingEdges();
631 for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); ++i) {
632 int noLanes = (*i)->getNumLanes();
633 for (int j = 0; j < noLanes; j++) {
634 incLanes.push_back((*i)->getLaneID(j));
635 }
636 }
637 std::vector<NBNode::Crossing*> crossings = n.getCrossings();
638 std::set<std::string> prevWAs;
639 // avoid duplicates
640 for (auto c : crossings) {
641 if (prevWAs.count(c->prevWalkingArea) == 0) {
642 incLanes.push_back(c->prevWalkingArea + "_0");
643 prevWAs.insert(c->prevWalkingArea);
644 }
645 }
646 into.writeAttr(SUMO_ATTR_INCLANES, incLanes);
647 // write the internal lanes
648 std::vector<std::string> intLanes;
649 if (!OptionsCont::getOptions().getBool("no-internal-links")) {
650 for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
651 const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
652 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
653 if ((*k).toEdge == nullptr) {
654 continue;
655 }
656 if (!(*k).haveVia) {
657 intLanes.push_back((*k).getInternalLaneID());
658 } else {
659 intLanes.push_back((*k).getInternalViaLaneID());
660 }
661 }
662 }
663 }
665 for (auto c : crossings) {
666 intLanes.push_back(c->id + "_0");
667 }
668 }
669 into.writeAttr(SUMO_ATTR_INTLANES, intLanes);
670 // close writing
672 // write optional radius
675 }
676 // specify whether a custom shape was used
677 if (n.hasCustomShape()) {
679 }
682 }
684 into.writeAttr<std::string>(SUMO_ATTR_FRINGE, toString(n.getFringeType()));
685 }
686 if (n.getName() != "") {
688 }
690 // write right-of-way logics
691 n.writeLogic(into);
692 }
693 n.writeParams(into);
694 into.closeTag();
695}
696
697
698bool
700 bool ret = false;
701 const std::vector<NBEdge*>& incoming = n.getIncomingEdges();
702 // build the list of internal lane ids
703 std::vector<std::string> internalLaneIDs;
704 std::map<std::string, std::string> viaIDs;
705 for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
706 const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
707 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
708 if ((*k).toEdge != nullptr) {
709 internalLaneIDs.push_back((*k).getInternalLaneID());
710 if ((*k).viaID != "") {
711 viaIDs[(*k).getInternalLaneID()] = ((*k).getInternalViaLaneID());
712 }
713 }
714 }
715 }
716 for (auto c : n.getCrossings()) {
717 internalLaneIDs.push_back(c->id + "_0");
718 }
719 // write the internal nodes
720 for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
721 const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
722 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
723 if ((*k).toEdge == nullptr || !(*k).haveVia) {
724 continue;
725 }
726 Position pos = (*k).shape[-1];
727 into.openTag(SUMO_TAG_JUNCTION).writeAttr(SUMO_ATTR_ID, (*k).getInternalViaLaneID());
730 std::string incLanes = (*k).getInternalLaneID();
731 std::vector<std::string> foeIDs;
732 for (std::string incLane : (*k).foeIncomingLanes) {
733 if (incLane[0] == ':') {
734 // intersecting left turns
735 const int index = StringUtils::toInt(incLane.substr(1));
736 incLane = internalLaneIDs[index];
737 if (viaIDs[incLane] != "") {
738 foeIDs.push_back(viaIDs[incLane]);
739 }
740 }
741 incLanes += " " + incLane;
742 }
743 into.writeAttr(SUMO_ATTR_INCLANES, incLanes);
744 const std::vector<int>& foes = (*k).foeInternalLinks;
745 for (std::vector<int>::const_iterator it = foes.begin(); it != foes.end(); ++it) {
746 foeIDs.push_back(internalLaneIDs[*it]);
747 }
748 into.writeAttr(SUMO_ATTR_INTLANES, joinToString(foeIDs, " "));
749 into.closeTag();
750 ret = true;
751 }
752 }
753 return ret;
754}
755
756
757void
759 bool includeInternal, ConnectionStyle style, bool geoAccuracy) {
760 assert(c.toEdge != 0);
762 into.writeAttr(SUMO_ATTR_FROM, from.getID());
766 if (style != TLL) {
767 if (c.mayDefinitelyPass) {
769 }
770 if (c.keepClear == KEEPCLEAR_FALSE) {
771 into.writeAttr<bool>(SUMO_ATTR_KEEP_CLEAR, false);
772 }
775 }
776 if (c.permissions != SVC_UNSPECIFIED) {
778 }
781 }
784 }
787 }
790 }
791 if (c.customShape.size() != 0) {
792 if (geoAccuracy) {
794 }
796 if (geoAccuracy) {
797 into.setPrecision();
798 }
799 }
800 if (c.uncontrolled != false) {
802 }
803 if (c.indirectLeft != false) {
805 }
806 if (c.edgeType != "") {
808 }
809 }
810 if (style != PLAIN) {
811 if (includeInternal) {
813 }
814 // set information about the controlling tl if any
815 if (c.tlID != "") {
818 if (c.tlLinkIndex2 >= 0) {
820 }
821 }
822 }
823 if (style != TLL) {
824 if (style == SUMONET) {
825 // write the direction information
826 LinkDirection dir = from.getToNode()->getDirection(&from, c.toEdge, OptionsCont::getOptions().getBool("lefthand"));
827 assert(dir != LinkDirection::NODIR);
828 into.writeAttr(SUMO_ATTR_DIR, toString(dir));
829 // write the state information
830 const LinkState linkState = from.getToNode()->getLinkState(
831 &from, c.toEdge, c.fromLane, c.toLane, c.mayDefinitelyPass, c.tlID);
832 into.writeAttr(SUMO_ATTR_STATE, linkState);
833 if (linkState == LINKSTATE_MINOR
836 const double visibilityDistance = OptionsCont::getOptions().getFloat("roundabouts.visibility-distance");
837 if (visibilityDistance != NBEdge::UNSPECIFIED_VISIBILITY_DISTANCE) {
838 into.writeAttr(SUMO_ATTR_VISIBILITY_DISTANCE, visibilityDistance);
839 }
840 }
841 }
844 }
845 }
846 c.writeParams(into);
847 into.closeTag();
848}
849
850
851bool
853 bool ret = false;
854 const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
855 for (const NBEdge* const from : n.getIncomingEdges()) {
856 for (const NBEdge::Connection& c : from->getConnections()) {
857 LinkDirection dir = n.getDirection(from, c.toEdge, lefthand);
858 assert(c.toEdge != 0);
859 if (c.haveVia) {
860 // internal split with optional signal
861 std::string tlID = "";
862 int linkIndex2 = NBConnection::InvalidTlIndex;
863 if (c.tlLinkIndex2 != NBConnection::InvalidTlIndex) {
864 linkIndex2 = c.tlLinkIndex2;
865 tlID = c.tlID;
866 }
867 writeInternalConnection(into, c.id, c.toEdge->getID(), c.internalLaneIndex, c.toLane, c.getInternalViaLaneID(), dir, tlID, linkIndex2, false, c.visibility);
868 writeInternalConnection(into, c.viaID, c.toEdge->getID(), c.internalViaLaneIndex, c.toLane, "", dir, "", NBConnection::InvalidTlIndex, n.brakeForCrossingOnExit(c.toEdge));
869 } else {
870 // no internal split
871 writeInternalConnection(into, c.id, c.toEdge->getID(), c.internalLaneIndex, c.toLane, "", dir);
872 }
873 ret = true;
874 }
875 }
876 return ret;
877}
878
879
880void
882 const std::string& from, const std::string& to,
883 int fromLane, int toLane, const std::string& via,
884 LinkDirection dir,
885 const std::string& tlID, int linkIndex,
886 bool minor,
887 double visibility) {
889 into.writeAttr(SUMO_ATTR_FROM, from);
890 into.writeAttr(SUMO_ATTR_TO, to);
891 into.writeAttr(SUMO_ATTR_FROM_LANE, fromLane);
892 into.writeAttr(SUMO_ATTR_TO_LANE, toLane);
893 if (via != "") {
894 into.writeAttr(SUMO_ATTR_VIA, via);
895 }
896 if (tlID != "" && linkIndex != NBConnection::InvalidTlIndex) {
897 // used for the reverse direction of pedestrian crossings
898 into.writeAttr(SUMO_ATTR_TLID, tlID);
899 into.writeAttr(SUMO_ATTR_TLLINKINDEX, linkIndex);
900 }
901 into.writeAttr(SUMO_ATTR_DIR, dir);
902 into.writeAttr(SUMO_ATTR_STATE, ((via != "" || minor) ? "m" : "M"));
903 if (visibility != NBEdge::UNSPECIFIED_VISIBILITY_DISTANCE) {
905 }
906 into.closeTag();
907}
908
909
910void
911NWWriter_SUMO::writeRoundabouts(OutputDevice& into, const std::set<EdgeSet>& roundabouts,
912 const NBEdgeCont& ec) {
913 // make output deterministic
914 std::vector<std::vector<std::string> > edgeIDs;
915 for (std::set<EdgeSet>::const_iterator i = roundabouts.begin(); i != roundabouts.end(); ++i) {
916 std::vector<std::string> tEdgeIDs;
917 for (EdgeSet::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
918 // the edges may have been erased from NBEdgeCont but their pointers are still valid
919 // we verify their existance in writeRoundabout()
920 tEdgeIDs.push_back((*j)->getID());
921 }
922 std::sort(tEdgeIDs.begin(), tEdgeIDs.end());
923 edgeIDs.push_back(tEdgeIDs);
924 }
925 std::sort(edgeIDs.begin(), edgeIDs.end());
926 // write
927 for (std::vector<std::vector<std::string> >::const_iterator i = edgeIDs.begin(); i != edgeIDs.end(); ++i) {
928 writeRoundabout(into, *i, ec);
929 }
930 if (roundabouts.size() != 0) {
931 into.lf();
932 }
933}
934
935
936void
937NWWriter_SUMO::writeRoundabout(OutputDevice& into, const std::vector<std::string>& edgeIDs,
938 const NBEdgeCont& ec) {
939 std::vector<std::string> validEdgeIDs;
940 std::vector<std::string> invalidEdgeIDs;
941 std::vector<std::string> nodeIDs;
942 for (std::vector<std::string>::const_iterator i = edgeIDs.begin(); i != edgeIDs.end(); ++i) {
943 const NBEdge* edge = ec.retrieve(*i);
944 if (edge != nullptr) {
945 nodeIDs.push_back(edge->getToNode()->getID());
946 validEdgeIDs.push_back(edge->getID());
947 } else {
948 invalidEdgeIDs.push_back(*i);
949 }
950 }
951 std::sort(nodeIDs.begin(), nodeIDs.end());
952 if (validEdgeIDs.size() > 0) {
954 into.writeAttr(SUMO_ATTR_NODES, joinToString(nodeIDs, " "));
955 into.writeAttr(SUMO_ATTR_EDGES, joinToString(validEdgeIDs, " "));
956 into.closeTag();
957 if (invalidEdgeIDs.size() > 0) {
958 WRITE_WARNING("Writing incomplete roundabout. Edges: '"
959 + joinToString(invalidEdgeIDs, " ") + "' no longer exist'");
960 }
961 }
962}
963
964
965void
967 std::vector<double> sourceW = d.getSourceWeights();
969 std::vector<double> sinkW = d.getSinkWeights();
971 // write the head and the id of the district
973 if (d.getShape().size() > 0) {
975 }
976 // write all sources
977 const std::vector<NBEdge*>& sources = d.getSourceEdges();
978 for (int i = 0; i < (int)sources.size(); i++) {
979 // write the head and the id of the source
980 into.openTag(SUMO_TAG_TAZSOURCE).writeAttr(SUMO_ATTR_ID, sources[i]->getID()).writeAttr(SUMO_ATTR_WEIGHT, sourceW[i]);
981 into.closeTag();
982 }
983 // write all sinks
984 const std::vector<NBEdge*>& sinks = d.getSinkEdges();
985 for (int i = 0; i < (int)sinks.size(); i++) {
986 // write the head and the id of the sink
987 into.openTag(SUMO_TAG_TAZSINK).writeAttr(SUMO_ATTR_ID, sinks[i]->getID()).writeAttr(SUMO_ATTR_WEIGHT, sinkW[i]);
988 into.closeTag();
989 }
990 // write the tail
991 into.closeTag();
992}
993
994
995std::string
997 double time = STEPS2TIME(steps);
998 if (time == std::floor(time)) {
999 return toString(int(time));
1000 } else {
1001 return toString(time);
1002 }
1003}
1004
1005void
1007 for (NBConnectionProhibits::const_iterator j = prohibitions.begin(); j != prohibitions.end(); j++) {
1008 NBConnection prohibited = (*j).first;
1009 const NBConnectionVector& prohibiting = (*j).second;
1010 for (NBConnectionVector::const_iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
1011 NBConnection prohibitor = *k;
1015 into.closeTag();
1016 }
1017 }
1018}
1019
1020
1021std::string
1023 return c.getFrom()->getID() + "->" + c.getTo()->getID();
1024}
1025
1026
1027void
1029 std::vector<NBTrafficLightLogic*> logics = tllCont.getComputed();
1030 for (NBTrafficLightLogic* logic : logics) {
1031 writeTrafficLight(into, logic);
1032 // only raise warnings on write instead of on compute (to avoid cluttering netedit)
1033 NBTrafficLightDefinition* def = tllCont.getDefinition(logic->getID(), logic->getProgramID());
1034 assert(def != nullptr);
1035 def->finalChecks();
1036 }
1037 if (logics.size() > 0) {
1038 into.lf();
1039 }
1040}
1041
1042
1043void
1046 into.writeAttr(SUMO_ATTR_ID, logic->getID());
1047 into.writeAttr(SUMO_ATTR_TYPE, logic->getType());
1049 into.writeAttr(SUMO_ATTR_OFFSET, logic->getOffset() == SUMOTime_MAX ? "begin" : writeSUMOTime(logic->getOffset()));
1050 // write the phases
1051 const bool varPhaseLength = logic->getType() != TrafficLightType::STATIC;
1052 for (const NBTrafficLightLogic::PhaseDefinition& phase : logic->getPhases()) {
1053 into.openTag(SUMO_TAG_PHASE);
1054 into.writeAttr(SUMO_ATTR_DURATION, writeSUMOTime(phase.duration));
1055 if (phase.duration < TIME2STEPS(10)) {
1056 into.writePadding(" ");
1057 }
1058 into.writeAttr(SUMO_ATTR_STATE, phase.state);
1059 if (varPhaseLength) {
1061 into.writeAttr(SUMO_ATTR_MINDURATION, writeSUMOTime(phase.minDur));
1062 }
1064 into.writeAttr(SUMO_ATTR_MAXDURATION, writeSUMOTime(phase.maxDur));
1065 }
1066 if (phase.earliestEnd != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
1067 into.writeAttr(SUMO_ATTR_EARLIEST_END, writeSUMOTime(phase.earliestEnd));
1068 }
1069 if (phase.latestEnd != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
1070 into.writeAttr(SUMO_ATTR_LATEST_END, writeSUMOTime(phase.latestEnd));
1071 }
1072 // NEMA attributes
1075 }
1077 into.writeAttr(SUMO_ATTR_YELLOW, writeSUMOTime(phase.yellow));
1078 }
1080 into.writeAttr(SUMO_ATTR_RED, writeSUMOTime(phase.red));
1081 }
1082 }
1083 if (phase.name != "") {
1085 }
1086 if (phase.next.size() > 0) {
1087 into.writeAttr(SUMO_ATTR_NEXT, phase.next);
1088 }
1089 into.closeTag();
1090 }
1091 // write params
1092 logic->writeParams(into);
1093 into.closeTag();
1094}
1095
1096
1097void
1099 if (stopOffset.isDefined()) {
1100 const std::string ss_vclasses = getVehicleClassNames(stopOffset.getPermissions());
1101 if (ss_vclasses.length() == 0) {
1102 // This stopOffset would have no effect...
1103 return;
1104 }
1106 const std::string ss_exceptions = getVehicleClassNames(~stopOffset.getPermissions());
1107 if (ss_vclasses.length() <= ss_exceptions.length()) {
1108 into.writeAttr(SUMO_ATTR_VCLASSES, ss_vclasses);
1109 } else {
1110 if (ss_exceptions.length() == 0) {
1111 into.writeAttr(SUMO_ATTR_VCLASSES, "all");
1112 } else {
1113 into.writeAttr(SUMO_ATTR_EXCEPTIONS, ss_exceptions);
1114 }
1115 }
1116 into.writeAttr(SUMO_ATTR_VALUE, stopOffset.getOffset());
1117 into.closeTag();
1118 }
1119}
1120
1121
1122/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:296
#define WRITE_WARNING(msg)
Definition MsgHandler.h:295
#define TL(string)
Definition MsgHandler.h:315
std::map< NBConnection, NBConnectionVector > NBConnectionProhibits
Definition of a container for connection block dependencies Includes a list of all connections which ...
std::vector< NBConnection > NBConnectionVector
Definition of a connection vector.
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition NBCont.h:42
@ KEEPCLEAR_FALSE
Definition NBCont.h:59
#define STEPS2TIME(x)
Definition SUMOTime.h:55
#define SUMOTime_MAX
Definition SUMOTime.h:34
#define TIME2STEPS(x)
Definition SUMOTime.h:57
const SVCPermissions SVCAll
all VClasses are allowed
const SVCPermissions SVC_UNSPECIFIED
permissions not specified
const std::string & getVehicleClassNames(SVCPermissions permissions, bool expand)
Returns the ids of the given classes, divided using a ' '.
void writePermissions(OutputDevice &into, SVCPermissions permissions)
writes allowed disallowed attributes if needed;
void writePreferences(OutputDevice &into, SVCPermissions preferred)
writes allowed disallowed attributes if needed;
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
@ SVC_IGNORING
vehicles ignoring classes
@ SVC_PEDESTRIAN
pedestrian
@ SUMO_TAG_PHASE
a single phase description
@ SUMO_TAG_STOPOFFSET
Information on vClass specific stop offsets at lane end.
@ SUMO_TAG_TAZ
a traffic assignment zone
@ SUMO_TAG_TAZSINK
a sink within a district (connection road)
@ SUMO_TAG_PROHIBITION
prohibition of circulation between two edges
@ SUMO_TAG_CONNECTION
connectioon between two lanes
@ SUMO_TAG_ROUNDABOUT
roundabout defined in junction
@ SUMO_TAG_TLLOGIC
a traffic light logic
@ SUMO_TAG_JUNCTION
begin/end of the description of a junction
@ SUMO_TAG_LANE
begin/end of the description of a single lane
@ SUMO_TAG_TAZSOURCE
a source within a district (connection road)
@ SUMO_TAG_NEIGH
begin/end of the description of a neighboring lane
@ SUMO_TAG_EDGE
begin/end of the description of an edge
LinkDirection
The different directions a link between two lanes may take (or a stream between two edges)....
@ STRAIGHT
The link is a straight direction.
@ NODIR
The link has no direction (is a dead end link)
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic,...
@ LINKSTATE_MAJOR
This is an uncontrolled, major link, may pass.
@ LINKSTATE_MINOR
This is an uncontrolled, minor link, has to brake.
@ SUMO_ATTR_JUNCTIONS_MINIMAL_SHAPE
@ SUMO_ATTR_LANE
@ SUMO_ATTR_NODES
a list of node ids, used for controlling joining
@ SUMO_ATTR_LATEST_END
The maximum time within the cycle for switching (for coordinated actuation)
@ SUMO_ATTR_TLLINKINDEX2
link: the index of the opposite direction link of a pedestrian crossing
@ SUMO_ATTR_RED
red duration of a phase
@ SUMO_ATTR_SPEED
@ SUMO_ATTR_LINKDETAIL
@ SUMO_ATTR_VALUE
@ SUMO_ATTR_VIA
@ SUMO_ATTR_CORNERDETAIL
@ SUMO_ATTR_RADIUS
The turning radius at an intersection in m.
@ SUMO_ATTR_INDIRECT
Whether this connection is an indirect (left) turn.
@ SUMO_ATTR_RECTANGULAR_LANE_CUT
@ SUMO_ATTR_FROM_LANE
@ SUMO_ATTR_LIMIT_TURN_SPEED
@ SUMO_ATTR_CHECKLANEFOES_ROUNDABOUT
@ SUMO_ATTR_OFFSET
@ SUMO_ATTR_AVOID_OVERLAP
@ SUMO_ATTR_YELLOW
yellow duration of a phase
@ SUMO_ATTR_CUSTOMSHAPE
whether a given shape is user-defined
@ SUMO_ATTR_INTLANES
@ SUMO_ATTR_VEHICLEEXTENSION
vehicle extension time of a phase
@ SUMO_ATTR_EDGES
the edges of a route
@ SUMO_ATTR_FRINGE
Fringe type of node.
@ SUMO_ATTR_BIDI
@ SUMO_ATTR_PROHIBITED
@ SUMO_ATTR_PRIORITY
@ SUMO_ATTR_SHAPE
edge: the shape in xml-definition
@ SUMO_ATTR_LEFTHAND
@ SUMO_ATTR_WEIGHT
@ SUMO_ATTR_NEXT
succesor phase index
@ SUMO_ATTR_INCLANES
@ SUMO_ATTR_CHANGE_LEFT
@ SUMO_ATTR_INDEX
@ SUMO_ATTR_VCLASSES
@ SUMO_ATTR_NAME
@ SUMO_ATTR_EXCEPTIONS
@ SUMO_ATTR_JUNCTIONS_ENDPOINT_SHAPE
@ SUMO_ATTR_CHECKLANEFOES_ALL
@ SUMO_ATTR_SPREADTYPE
The information about how to spread the lanes from the given position.
@ SUMO_ATTR_PASS
@ SUMO_ATTR_ENDOFFSET
@ SUMO_ATTR_HIGHER_SPEED
@ SUMO_ATTR_TO
@ SUMO_ATTR_FROM
@ SUMO_ATTR_ACCELERATION
@ SUMO_ATTR_CHANGE_RIGHT
@ SUMO_ATTR_TLID
link,node: the traffic light id responsible for this link
@ SUMO_ATTR_DISTANCE
@ SUMO_ATTR_TO_LANE
@ SUMO_ATTR_UNCONTROLLED
@ SUMO_ATTR_TYPE
@ SUMO_ATTR_LENGTH
@ SUMO_ATTR_VERSION
@ SUMO_ATTR_ID
@ SUMO_ATTR_MAXDURATION
maximum duration of a phase
@ SUMO_ATTR_RIGHT_OF_WAY
How to compute right of way.
@ SUMO_ATTR_PROGRAMID
@ SUMO_ATTR_OUTLINESHAPE
edge: the outline shape in xml-definition
@ SUMO_ATTR_FUNCTION
@ SUMO_ATTR_VISIBILITY_DISTANCE
foe visibility distance of a link
@ SUMO_ATTR_PROHIBITOR
@ SUMO_ATTR_DURATION
@ SUMO_ATTR_CONTPOS
@ SUMO_ATTR_WIDTH
@ SUMO_ATTR_CROSSING_EDGES
the edges crossed by a pedestrian crossing
@ SUMO_ATTR_DIR
The abstract direction of a link.
@ SUMO_ATTR_TLS_IGNORE_INTERNAL_JUNCTION_JAM
@ SUMO_ATTR_TLLINKINDEX
link: the index of the link within the traffic light
@ SUMO_ATTR_MINDURATION
@ SUMO_ATTR_KEEP_CLEAR
Whether vehicles must keep the junction clear.
@ SUMO_ATTR_INTERNAL_JUNCTIONS_VEHICLE_WIDTH
@ SUMO_ATTR_STATE
The state of a link.
@ SUMO_ATTR_FRICTION
@ SUMO_ATTR_WALKINGAREAS
@ SUMO_ATTR_EARLIEST_END
The minimum time within the cycle for switching (for coordinated actuation)
int gPrecisionGeo
Definition StdDefs.cpp:27
T MIN2(T a, T b)
Definition StdDefs.h:76
T MAX2(T a, T b)
Definition StdDefs.h:82
const MMVersion NETWORK_VERSION(1, 20)
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
Definition ToString.h:283
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
static void writeLocation(OutputDevice &into)
writes the location element
NBEdge * getFrom() const
returns the from-edge (start of the connection)
static const int InvalidTlIndex
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:1041
@ 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:602
NBNode * getToNode() const
Returns the destination node of the edge.
Definition NBEdge.h:546
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:783
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge's lanes' lateral offset is computed.
Definition NBEdge.cpp:998
bool isBidiRail(bool ignoreSpread=false) const
whether this edge is part of a bidirectional railway
Definition NBEdge.cpp:749
bool hasLoadedLength() const
Returns whether a length was set explicitly.
Definition NBEdge.h:612
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
Definition NBEdge.h:730
const std::string & getID() const
Definition NBEdge.h:1528
double getDistance() const
get distance
Definition NBEdge.h:679
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:4232
int getNumLanes() const
Returns the number of lanes.
Definition NBEdge.h:520
std::vector< Connection > getConnectionsFromLane(int lane, const NBEdge *to=nullptr, int toLane=-1) const
Returns connections from a given lane.
Definition NBEdge.cpp:1287
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:4017
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:2133
const std::string & getTypeID() const
get ID of type
Definition NBEdge.h:1181
const std::string & getStreetName() const
Returns the street name of this edge.
Definition NBEdge.h:669
const NBEdge * getBidiEdge() const
Definition NBEdge.h:1514
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition NBEdge.h:539
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition NBEdge.cpp:4008
bool hasDefaultGeometry() const
Returns whether the geometry consists only of the node positions.
Definition NBEdge.cpp:596
int getPriority() const
Returns the priority of the edge.
Definition NBEdge.h:527
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:689
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:1136
double getFinalLength() const
get length that will be assigned to the lanes in the final network
Definition NBEdge.cpp:4715
static void interpretLaneID(const std::string &lane_id, std::string &edge_id, int &index)
parses edge-id and index from lane-id
Instance responsible for building networks.
NBNodeCont & getNodeCont()
Returns a reference to the node container.
NBEdgeCont & getEdgeCont()
NBDistrictCont & getDistrictCont()
Returns a reference the districts container.
NBTypeCont & getTypeCont()
Returns a reference to the type container.
NBTrafficLightLogicCont & getTLLogicCont()
Returns a reference to the traffic light logics container.
A definition of a pedestrian crossing.
Definition NBNode.h:135
int tlLinkIndex
the traffic light index of this crossing (if controlled)
Definition NBNode.h:162
std::string tlID
The id of the traffic light that controls this connection.
Definition NBNode.h:168
bool priority
whether the pedestrians have priority
Definition NBNode.h:158
Container for nodes during the netbuilding process.
Definition NBNodeCont.h:57
std::map< std::string, NBNode * >::const_iterator begin() const
Returns the pointer to the begin of the stored nodes.
Definition NBNodeCont.h:113
std::map< std::string, NBNode * >::const_iterator end() const
Returns the pointer to the end of the stored nodes.
Definition NBNodeCont.h:118
Represents a single node (junction) during network building.
Definition NBNode.h:66
LinkDirection getDirection(const NBEdge *const incoming, const NBEdge *const outgoing, bool leftHand=false) const
Returns the representation of the described stream's direction.
Definition NBNode.cpp:2409
RightOfWay getRightOfWay() const
Returns hint on how to compute right of way.
Definition NBNode.h:300
LinkState getLinkState(const NBEdge *incoming, const NBEdge *outgoing, int fromLane, int toLane, bool mayDefinitelyPass, const std::string &tlID) const
get link state
Definition NBNode.cpp:2494
static const double UNSPECIFIED_RADIUS
unspecified lane width
Definition NBNode.h:220
Crossing * getCrossing(const std::string &id) const
return the crossing with the given id
Definition NBNode.cpp:3921
FringeType getFringeType() const
Returns fringe type.
Definition NBNode.h:305
SumoXMLNodeType getType() const
Returns the type of this node.
Definition NBNode.h:285
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
Definition NBNode.h:268
bool hasCustomShape() const
return whether the shape was set by the user
Definition NBNode.h:584
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:2080
std::vector< Crossing * > getCrossings() const
return this junctions pedestrian crossings
Definition NBNode.cpp:2982
const std::string & getName() const
Returns intersection name.
Definition NBNode.h:310
bool writeLogic(OutputDevice &into) const
writes the XML-representation of the logic as a bitset-logic XML representation
Definition NBNode.cpp:1088
const Position & getPosition() const
Definition NBNode.h:260
const PositionVector & getShape() const
retrieve the junction shape
Definition NBNode.cpp:2667
double getRadius() const
Returns the turning radius of this node.
Definition NBNode.h:290
const std::vector< WalkingArea > & getWalkingAreas() const
return this junctions pedestrian walking areas
Definition NBNode.h:747
The base class for traffic light logic definitions.
virtual void finalChecks() const
perform optional final checks
static const SUMOTime UNSPECIFIED_DURATION
The definition of a single phase of the logic.
A container for traffic light definitions and built programs.
std::vector< NBTrafficLightLogic * > getComputed() const
Returns a list of all computed logics.
NBTrafficLightDefinition * getDefinition(const std::string &id, const std::string &programID) const
Returns the named definition.
A SUMO-compliant built logic for a traffic light.
SUMOTime getOffset() const
Returns the offset of first switch.
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:201
static void writeConnection(OutputDevice &into, const NBEdge &from, const NBEdge::Connection &c, bool includeInternal, ConnectionStyle style=SUMONET, bool geoAccuracy=false)
Writes connections outgoing from the given edge (also used in NWWriter_XML)
static void writeNetwork(const OptionsCont &oc, NBNetBuilder &nb)
Writes the network into a SUMO-file.
static bool writeInternalNodes(OutputDevice &into, const NBNode &n)
Writes internal junctions (<junction with id[0]==':' ...) of the given node.
static void writeProhibitions(OutputDevice &into, const NBConnectionProhibits &prohibitions)
writes the given prohibitions
static void writeEdge(OutputDevice &into, const NBEdge &e, bool noNames)
Writes an edge (<edge ...)
static std::string getOppositeInternalID(const NBEdgeCont &ec, const NBEdge *from, const NBEdge::Connection &con, double &oppositeLength)
retrieve the id of the opposite direction internal lane if it exists
static std::string writeSUMOTime(SUMOTime time)
writes a SUMOTime as int if possible, otherwise as a float
static void writeJunction(OutputDevice &into, const NBNode &n)
Writes a junction (<junction ...)
static bool writeInternalEdges(OutputDevice &into, const NBEdgeCont &ec, const NBNode &n)
Writes internal edges (<edge ... with id[0]==':') of the given node.
static bool writeInternalConnections(OutputDevice &into, const NBNode &n)
Writes inner connections within the node.
static void writeLane(OutputDevice &into, const std::string &lID, double speed, double friction, SVCPermissions permissions, SVCPermissions preferred, SVCPermissions changeLeft, SVCPermissions changeRight, double startOffset, double endOffset, const StopOffset &stopOffset, double width, PositionVector shape, const Parameterised *params, double length, int index, const std::string &oppositeID, const std::string &type, bool accelRamp=false, bool customShape=false, const PositionVector &outlineShape=PositionVector())
Writes a lane (<lane ...) of an edge.
static void writeDistrict(OutputDevice &into, const NBDistrict &d)
Writes a district.
static void writeRoundabouts(OutputDevice &into, const std::set< EdgeSet > &roundabouts, const NBEdgeCont &ec)
Writes roundabouts.
static std::string getInternalBidi(const NBEdge *e, const NBEdge::Connection &k, double &length)
retrieve bidi edge id for internal corresponding to the given connection
static void writeRoundabout(OutputDevice &into, const std::vector< std::string > &r, const NBEdgeCont &ec)
Writes a roundabout.
static void writeStopOffsets(OutputDevice &into, const StopOffset &stopOffset)
Write a stopOffset element into output device.
static void writeInternalConnection(OutputDevice &into, const std::string &from, const std::string &to, int fromLane, int toLane, const std::string &via, LinkDirection dir=LinkDirection::STRAIGHT, const std::string &tlID="", int linkIndex=NBConnection::InvalidTlIndex, bool minor=false, double visibility=NBEdge::UNSPECIFIED_VISIBILITY_DISTANCE)
Writes a single internal connection.
static void writeTrafficLight(OutputDevice &into, const NBTrafficLightLogic *logic)
writes a single traffic light logic to the given device
static std::string prohibitionConnection(const NBConnection &c)
the attribute value for a prohibition
static void writeTrafficLights(OutputDevice &into, const NBTrafficLightLogicCont &tllCont)
writes the traffic light logics to the given device
const std::string & getID() const
Returns the id.
Definition Named.h:74
A storage for options typed value containers)
Definition OptionsCont.h:89
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
bool isDefault(const std::string &name) const
Returns the information whether the named option has still the default value.
bool exists(const std::string &name) const
Returns the information whether the named option is known.
bool set(const std::string &name, const std::string &value, const bool append=false)
Sets the given value for the named option.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
void resetWritable()
Resets all options to be writeable.
static OptionsCont & getOptions()
Retrieves the options.
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
int toLane
The lane the connections yields in.
Definition NBEdge.h:216
SVCPermissions permissions
List of vehicle types that are allowed on this connection.
Definition NBEdge.h:252
double speed
custom speed for connection
Definition NBEdge.h:240
NBEdge * toEdge
The edge the connections yields in.
Definition NBEdge.h:213
KeepClear keepClear
whether the junction must be kept clear when using this connection
Definition NBEdge.h:231
double customLength
custom length for connection
Definition NBEdge.h:246
std::string edgeType
optional type of Connection
Definition NBEdge.h:264
bool uncontrolled
check if Connection is uncontrolled
Definition NBEdge.h:298
PositionVector customShape
custom shape for connection
Definition NBEdge.h:249
bool mayDefinitelyPass
Information about being definitely free to drive (on-ramps)
Definition NBEdge.h:228
SVCPermissions changeLeft
List of vehicle types that are allowed to change Left from this connections internal lane(s)
Definition NBEdge.h:255
SVCPermissions changeRight
List of vehicle types that are allowed to change right from this connections internal lane(s)
Definition NBEdge.h:258
std::string getDescription(const NBEdge *parent) const
get string describing this connection
Definition NBEdge.cpp:104
double contPos
custom position for internal junction on this connection
Definition NBEdge.h:234
std::string getInternalLaneID() const
get ID of internal lane
Definition NBEdge.cpp:92
std::string tlID
The id of the traffic light that controls this connection.
Definition NBEdge.h:219
double visibility
custom foe visiblity for connection
Definition NBEdge.h:237
int tlLinkIndex2
The index of the internal junction within the controlling traffic light (optional)
Definition NBEdge.h:225
double length
computed length (average of all internal lane shape lengths that share an internal edge)
Definition NBEdge.h:310
std::string id
id of Connection
Definition NBEdge.h:267
int tlLinkIndex
The index of this connection within the controlling traffic light.
Definition NBEdge.h:222
An (internal) definition of a single lane of an edge.
Definition NBEdge.h:143
double width
This lane's width.
Definition NBEdge.h:176
StopOffset laneStopOffset
stopOffsets.second - The stop offset for vehicles stopping at the lane's end. Applies if vClass is in...
Definition NBEdge.h:173
PositionVector customShape
A custom shape for this lane set by the user.
Definition NBEdge.h:189
double endOffset
This lane's offset to the intersection begin.
Definition NBEdge.h:169
std::string type
the type of this lane
Definition NBEdge.h:192
SVCPermissions preferred
List of vehicle types that are preferred on this lane.
Definition NBEdge.h:160
double speed
The speed allowed on this lane.
Definition NBEdge.h:151
std::string oppositeID
An opposite lane ID, if given.
Definition NBEdge.h:179
SVCPermissions changeRight
List of vehicle types that are allowed to change right from this lane.
Definition NBEdge.h:166
double friction
The friction on this lane.
Definition NBEdge.h:154
SVCPermissions changeLeft
List of vehicle types that are allowed to change Left from this lane.
Definition NBEdge.h:163
SVCPermissions permissions
List of vehicle types that are allowed on this lane.
Definition NBEdge.h:157
bool accelRamp
Whether this lane is an acceleration lane.
Definition NBEdge.h:182
PositionVector shape
The lane's shape.
Definition NBEdge.h:148
A definition of a pedestrian walking area.
Definition NBNode.h:177
std::string id
the (edge)-id of this walkingArea
Definition NBNode.h:184
bool hasCustomShape
whether this walkingArea has a custom shape
Definition NBNode.h:200
double width
This lane's width.
Definition NBNode.h:186
PositionVector shape
The polygonal shape.
Definition NBNode.h:190
double length
This lane's width.
Definition NBNode.h:188