Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2026 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file NWWriter_XML.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @author Leonhard Luecken
19 : /// @date Tue, 11.05.2011
20 : ///
21 : // Exporter writing networks using XML (native input) format
22 : /****************************************************************************/
23 : #include <config.h>
24 : #include <algorithm>
25 : #include <utils/common/MsgHandler.h>
26 : #include <utils/common/ToString.h>
27 : #include <utils/common/StringUtils.h>
28 : #include <utils/options/OptionsCont.h>
29 : #include <utils/iodevices/OutputDevice.h>
30 : #include <utils/geom/GeoConvHelper.h>
31 : #include <netbuild/NBEdge.h>
32 : #include <netbuild/NBEdgeCont.h>
33 : #include <netbuild/NBNode.h>
34 : #include <netbuild/NBNodeCont.h>
35 : #include <netbuild/NBNetBuilder.h>
36 : #include <netbuild/NBPTLineCont.h>
37 : #include <netbuild/NBPTStop.h>
38 : #include <netbuild/NBParking.h>
39 : #include "NWFrame.h"
40 : #include "NWWriter_SUMO.h"
41 : #include "NWWriter_XML.h"
42 :
43 :
44 : // ===========================================================================
45 : // method definitions
46 : // ===========================================================================
47 : // ---------------------------------------------------------------------------
48 : // static methods
49 : // ---------------------------------------------------------------------------
50 : void
51 2235 : NWWriter_XML::writeNetwork(const OptionsCont& oc, const std::string& prefix, NBNetBuilder& nb) {
52 : // check whether plain-output files shall be generated
53 2235 : if (prefix != "") {
54 185 : const bool haveTypes = nb.getTypeCont().size() > 0;
55 185 : writeNodes(oc, prefix, nb.getNodeCont());
56 183 : if (haveTypes) {
57 20 : writeTypes(prefix, nb.getEdgeCont(), nb.getTypeCont());
58 : }
59 183 : writeEdgesAndConnections(oc, prefix, nb.getNodeCont(), nb.getEdgeCont());
60 183 : writeTrafficLights(prefix, nb.getTLLogicCont(), nb.getEdgeCont());
61 183 : writeConfig(oc, prefix, haveTypes);
62 : }
63 2243 : if (oc.isSet("junctions.join-output") && (oc.getString("junctions.join-output").size() > 0)) {
64 10 : writeJoinedJunctions(oc.getString("junctions.join-output"), nb.getNodeCont());
65 : }
66 2235 : if (oc.isSet("street-sign-output") && (oc.getString("street-sign-output").size() > 0)) {
67 1 : writeStreetSigns(oc, nb.getEdgeCont());
68 : }
69 4545 : if (oc.exists("ptstop-output") && oc.isSet("ptstop-output") && (oc.getString("ptstop-output").size() > 0)) {
70 82 : writePTStops(oc, nb.getPTStopCont());
71 : }
72 4485 : if (oc.exists("ptline-output") && oc.isSet("ptline-output") && (oc.getString("ptline-output").size() > 0)) {
73 52 : writePTLines(oc, nb.getPTLineCont());
74 : }
75 4387 : if (oc.exists("parking-output") && oc.isSet("parking-output") && (oc.getString("parking-output").size() > 0)) {
76 3 : writeParkingAreas(oc, nb.getParkingCont(), nb.getEdgeCont());
77 : }
78 4383 : if (oc.exists("taz-output") && oc.isSet("taz-output") && (oc.getString("taz-output").size() > 0)) {
79 1 : writeDistricts(oc, nb.getDistrictCont());
80 : }
81 2233 : }
82 :
83 :
84 : void
85 183 : NWWriter_XML::writeConfig(const OptionsCont& oc, const std::string& prefix, bool haveTypes) {
86 366 : if (!oc.exists("node-files")) {
87 : // do not write configuration for netgen
88 1 : return;
89 : }
90 182 : const std::string ext = oc.getString("output.format");
91 182 : OptionsCont* tmp = oc.clone();
92 546 : tmp->set("node-files", prefix + ".nod." + ext);
93 546 : tmp->set("edge-files", prefix + ".edg." + ext);
94 546 : tmp->set("connection-files", prefix + ".con." + ext);
95 546 : tmp->set("tllogic-files", prefix + ".tll." + ext);
96 182 : if (haveTypes) {
97 80 : tmp->set("type-files", prefix + ".typ." + ext);
98 : }
99 364 : tmp->setDefault("sumo-net-file", "");
100 364 : tmp->setDefault("plain-output-prefix", "");
101 :
102 182 : const std::string configPath = prefix + ".netccfg";
103 182 : std::ofstream out(configPath.c_str());
104 182 : if (!out.good()) {
105 0 : delete tmp;
106 0 : throw ProcessError(TLF("Could not save configuration to '%'", configPath));
107 : } else {
108 364 : tmp->writeConfiguration(out, true, false, false);
109 : }
110 182 : delete tmp;
111 182 : }
112 :
113 :
114 : void
115 185 : NWWriter_XML::writeNodes(const OptionsCont& oc, const std::string& prefix, NBNodeCont& nc) {
116 185 : const std::string ext = oc.getString("output.format");
117 : const GeoConvHelper& gch = GeoConvHelper::getFinal();
118 368 : bool useGeo = oc.exists("proj.plain-geo") && oc.getBool("proj.plain-geo");
119 185 : if (useGeo && !gch.usingGeoProjection()) {
120 0 : WRITE_WARNING(TL("Ignoring option \"proj.plain-geo\" because no geo-conversion has been defined"));
121 : useGeo = false;
122 : }
123 185 : const bool geoAccuracy = useGeo || gch.usingInverseGeoProjection();
124 :
125 555 : OutputDevice& device = OutputDevice::getDevice(prefix + ".nod." + ext);
126 : std::map<SumoXMLAttr, std::string> attrs;
127 183 : attrs[SUMO_ATTR_VERSION] = toString(NETWORK_VERSION);
128 366 : device.writeXMLHeader("nodes", "nodes_file.xsd", attrs);
129 :
130 : // write network offsets and projection to allow reconstruction of original coordinates
131 183 : if (!useGeo) {
132 179 : GeoConvHelper::writeLocation(device);
133 : }
134 :
135 : // write nodes
136 366 : TrafficLightType tlsDefaultType = SUMOXMLDefinitions::TrafficLightTypes.get(oc.getString("tls.default-type"));
137 4901 : for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
138 4718 : NBNode* n = (*i).second;
139 4718 : device.openTag(SUMO_TAG_NODE);
140 4718 : device.writeAttr(SUMO_ATTR_ID, n->getID());
141 : // write position
142 4718 : Position pos = n->getPosition();
143 4718 : if (useGeo) {
144 99 : gch.cartesian2geo(pos);
145 : }
146 4718 : if (geoAccuracy) {
147 99 : device.setPrecision(gPrecisionGeo);
148 : }
149 4718 : NWFrame::writePositionLong(pos, device);
150 4718 : if (geoAccuracy) {
151 99 : device.setPrecision();
152 : }
153 :
154 4718 : device.writeAttr(SUMO_ATTR_TYPE, toString(n->getType()));
155 : // std::set is already sorted, so the output is stable
156 : std::set<std::string> tlsIDs;
157 : std::set<std::string> controlledInnerEdges;
158 4718 : std::string tlType = "";
159 4918 : for (NBTrafficLightDefinition* tl : n->getControllingTLS()) {
160 : tlsIDs.insert(tl->getID());
161 200 : std::vector<std::string> cie = tl->getControlledInnerEdges();
162 : controlledInnerEdges.insert(cie.begin(), cie.end());
163 200 : if (tl->getType() != tlsDefaultType) {
164 192 : tlType = toString(tl->getType());
165 : }
166 200 : }
167 4718 : device.writeOptionalAttr(SUMO_ATTR_TLID, tlsIDs, tlsIDs.empty());
168 9436 : device.writeOptionalAttr(SUMO_ATTR_TLTYPE, tlType, tlType == "");
169 4718 : device.writeOptionalAttr(SUMO_ATTR_CONTROLLED_INNER, controlledInnerEdges, controlledInnerEdges.empty());
170 9436 : NWWriter_SUMO::writeShape(device, gch, n->getShape(), SUMO_ATTR_SHAPE, useGeo, geoAccuracy, n->hasCustomShape());
171 9436 : device.writeOptionalAttr(SUMO_ATTR_RADIUS, n->getRadius(), n->getRadius() == NBNode::UNSPECIFIED_RADIUS);
172 9436 : device.writeOptionalAttr<bool>(SUMO_ATTR_KEEP_CLEAR, n->getKeepClear(), n->getKeepClear());
173 9436 : device.writeOptionalAttr(SUMO_ATTR_RIGHT_OF_WAY, toString(n->getRightOfWay()), n->getRightOfWay() == RightOfWay::DEFAULT);
174 9436 : device.writeOptionalAttr(SUMO_ATTR_FRINGE, toString(n->getFringeType()), n->getFringeType() == FringeType::DEFAULT);
175 9436 : device.writeOptionalAttr(SUMO_ATTR_ROUNDABOUT, toString(n->getRoundaboutType()), n->getRoundaboutType() == RoundaboutType::DEFAULT);
176 9436 : device.writeOptionalAttr(SUMO_ATTR_NAME, StringUtils::escapeXML(n->getName()), n->getName() == "");
177 4718 : n->writeParams(device);
178 9436 : device.closeTag();
179 : }
180 183 : device.close();
181 183 : }
182 :
183 :
184 : void
185 20 : NWWriter_XML::writeTypes(const std::string& prefix, NBEdgeCont& ec, NBTypeCont& tc) {
186 20 : const std::string ext = OptionsCont::getOptions().getString("output.format");
187 60 : OutputDevice& device = OutputDevice::getDevice(prefix + ".typ." + ext);
188 : std::map<SumoXMLAttr, std::string> attrs;
189 20 : attrs[SUMO_ATTR_VERSION] = toString(NETWORK_VERSION);
190 40 : device.writeXMLHeader(toString(SUMO_TAG_TYPES), "types_file.xsd", attrs);
191 20 : std::set<std::string> usedTypes = ec.getUsedTypes();
192 20 : tc.writeEdgeTypes(device, usedTypes);
193 20 : device.close();
194 20 : }
195 :
196 :
197 : void
198 183 : NWWriter_XML::writeEdgesAndConnections(const OptionsCont& oc, const std::string& prefix, NBNodeCont& nc, NBEdgeCont& ec) {
199 183 : const std::string ext = oc.getString("output.format");
200 : const GeoConvHelper& gch = GeoConvHelper::getFinal();
201 365 : bool useGeo = oc.exists("proj.plain-geo") && oc.getBool("proj.plain-geo");
202 183 : const bool geoAccuracy = useGeo || gch.usingInverseGeoProjection();
203 :
204 : std::map<SumoXMLAttr, std::string> attrs;
205 183 : attrs[SUMO_ATTR_VERSION] = toString(NETWORK_VERSION);
206 549 : OutputDevice& edevice = OutputDevice::getDevice(prefix + ".edg." + ext);
207 366 : edevice.writeXMLHeader("edges", "edges_file.xsd", attrs);
208 549 : OutputDevice& cdevice = OutputDevice::getDevice(prefix + ".con." + ext);
209 366 : cdevice.writeXMLHeader("connections", "connections_file.xsd", attrs);
210 183 : const bool writeNames = oc.getBool("output.street-names");
211 183 : const bool writeLanes = oc.getBool("plain-output.lanes");
212 :
213 : // write network offsets and projection to allow reconstruction of original coordinates at least for geo-referenced networks
214 183 : if (!useGeo && gch.usingGeoProjection()) {
215 28 : GeoConvHelper::writeLocation(edevice);
216 : }
217 366 : LaneSpreadFunction defaultSpread = SUMOXMLDefinitions::LaneSpreadFunctions.get(oc.getString("default.spreadtype"));
218 8363 : for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
219 : // write the edge itself to the edges-files
220 8180 : NBEdge* e = (*i).second;
221 8180 : edevice.openTag(SUMO_TAG_EDGE);
222 8180 : edevice.writeAttr(SUMO_ATTR_ID, e->getID());
223 8180 : edevice.writeAttr(SUMO_ATTR_FROM, e->getFromNode()->getID());
224 8180 : edevice.writeAttr(SUMO_ATTR_TO, e->getToNode()->getID());
225 16360 : edevice.writeOptionalAttr(SUMO_ATTR_NAME, StringUtils::escapeXML(e->getStreetName()), !writeNames || e->getStreetName() == "");
226 8180 : edevice.writeAttr(SUMO_ATTR_PRIORITY, e->getPriority());
227 : // write the type if given
228 16360 : edevice.writeOptionalAttr(SUMO_ATTR_TYPE, e->getTypeID(), e->getTypeID() == "");
229 16360 : edevice.writeOptionalAttr(SUMO_ATTR_ROUTINGTYPE, e->getRoutingType(), e->getRoutingType() == "");
230 8180 : edevice.writeAttr(SUMO_ATTR_NUMLANES, e->getNumLanes());
231 16360 : edevice.writeOptionalAttr(SUMO_ATTR_SPEED, e->getSpeed(), e->hasLaneSpecificSpeed());
232 16357 : edevice.writeOptionalAttr(SUMO_ATTR_FRICTION, e->getFriction(), e->getFriction() == NBEdge::UNSPECIFIED_FRICTION || e->hasLaneSpecificFriction());
233 : // write non-default geometry
234 8180 : NWWriter_SUMO::writeShape(edevice, gch, e->getGeometry(), SUMO_ATTR_SHAPE, useGeo, geoAccuracy, !e->hasDefaultGeometry());
235 : // write the spread type if not default ("right")
236 16360 : edevice.writeOptionalAttr(SUMO_ATTR_SPREADTYPE, toString(e->getLaneSpreadFunction()), e->getLaneSpreadFunction() == defaultSpread);
237 : // write the length if it was specified
238 24537 : edevice.writeOptionalAttr(SUMO_ATTR_LENGTH, e->getLoadedLength(), !e->hasLoadedLength());
239 : // some attributes can be set by edge default or per lane. Write as default if possible (efficiency)
240 21977 : edevice.writeOptionalAttr(SUMO_ATTR_WIDTH, e->getLaneWidth(), e->getLaneWidth() == NBEdge::UNSPECIFIED_WIDTH || e->hasLaneSpecificWidth());
241 16353 : edevice.writeOptionalAttr(SUMO_ATTR_ENDOFFSET, e->getEndOffset(), e->getEndOffset() == NBEdge::UNSPECIFIED_OFFSET || e->hasLaneSpecificEndOffset());
242 : // SVC_UNSPECIFIED is here a shortcut for do not write
243 8180 : writePermissions(edevice, e->hasLaneSpecificPermissions() ? SVC_UNSPECIFIED : e->getPermissions(0));
244 8180 : if (!e->hasLaneSpecificStopOffsets() && e->getEdgeStopOffset().isDefined()) {
245 0 : NWWriter_SUMO::writeStopOffsets(edevice, e->getEdgeStopOffset());
246 : }
247 8180 : edevice.writeOptionalAttr(SUMO_ATTR_DISTANCE, e->getDistance(), e->getDistance() == 0);
248 16360 : edevice.writeOptionalAttr(SUMO_ATTR_BIDI, e->getBidiEdge() == nullptr ? "" : e->getBidiEdge()->getID(), e->getBidiEdge() == nullptr);
249 8180 : if (e->needsLaneSpecificOutput() || writeLanes) {
250 : int idx = 0;
251 14750 : for (const NBEdge::Lane& lane : e->getLanes()) {
252 8998 : edevice.openTag(SUMO_TAG_LANE);
253 8998 : edevice.writeAttr(SUMO_ATTR_INDEX, idx++);
254 8998 : writePermissions(edevice, e->hasLaneSpecificPermissions() || writeLanes ? lane.permissions : SVC_UNSPECIFIED);
255 8998 : writePreferences(edevice, lane.preferred);
256 15398 : edevice.writeOptionalAttr(SUMO_ATTR_WIDTH, lane.width, lane.width == NBEdge::UNSPECIFIED_WIDTH || !(e->hasLaneSpecificWidth() || writeLanes));
257 17988 : edevice.writeOptionalAttr(SUMO_ATTR_ENDOFFSET, lane.endOffset, lane.endOffset == NBEdge::UNSPECIFIED_OFFSET || !(e->hasLaneSpecificEndOffset() || writeLanes));
258 9023 : edevice.writeOptionalAttr(SUMO_ATTR_SPEED, lane.speed, !(e->hasLaneSpecificSpeed() || writeLanes));
259 17996 : edevice.writeOptionalAttr(SUMO_ATTR_ACCELERATION, lane.accelRamp, !lane.accelRamp);
260 18001 : NWWriter_SUMO::writeShape(edevice, gch, lane.customShape.size() > 0 ? lane.customShape : lane.shape, SUMO_ATTR_SHAPE, useGeo, geoAccuracy, lane.customShape.size() > 0 || writeLanes);
261 8998 : edevice.writeOptionalAttr(SUMO_ATTR_TYPE, lane.type, lane.type == "");
262 8998 : const bool changeLeft = (lane.changeLeft != SVCAll && lane.changeLeft != SVC_UNSPECIFIED && lane.changeLeft != SVC_IGNORING);
263 8998 : edevice.writeOptionalAttr(SUMO_ATTR_CHANGE_LEFT, getVehicleClassNames(lane.changeLeft), !changeLeft);
264 8998 : const bool changeRight = (lane.changeRight != SVCAll && lane.changeRight != SVC_UNSPECIFIED && lane.changeRight != SVC_IGNORING);
265 8998 : edevice.writeOptionalAttr(SUMO_ATTR_CHANGE_RIGHT, getVehicleClassNames(lane.changeRight), !changeRight);
266 8998 : if (lane.oppositeID != "") {
267 47 : edevice.openTag(SUMO_TAG_NEIGH);
268 47 : edevice.writeAttr(SUMO_ATTR_LANE, lane.oppositeID);
269 94 : edevice.closeTag();
270 : }
271 8998 : lane.writeParams(edevice);
272 8998 : NWWriter_SUMO::writeStopOffsets(edevice, lane.laneStopOffset);
273 17996 : edevice.closeTag();
274 : }
275 : }
276 8180 : e->writeParams(edevice);
277 16360 : edevice.closeTag();
278 : // write this edge's connections to the connections-files
279 8180 : const std::vector<NBEdge::Connection> connections = e->getConnections();
280 8180 : if (connections.empty()) {
281 : // if there are no connections and this appears to be customized, preserve the information
282 2557 : const int numOutgoing = (int)e->getToNode()->getOutgoingEdges().size();
283 2557 : if (numOutgoing > 0) {
284 1847 : const SVCPermissions inPerm = e->getPermissions();
285 : SVCPermissions outPerm = 0;
286 5373 : for (auto out : e->getToNode()->getOutgoingEdges()) {
287 3526 : outPerm |= out->getPermissions();
288 : }
289 1847 : if ((inPerm & outPerm) != 0 && (inPerm & outPerm) != SVC_PEDESTRIAN) {
290 182 : cdevice.openTag(SUMO_TAG_CONNECTION);
291 182 : cdevice.writeAttr(SUMO_ATTR_FROM, e->getID());
292 182 : cdevice.closeTag();
293 182 : cdevice.lf();
294 : }
295 : }
296 : } else {
297 19529 : for (NBEdge::Connection c : connections) {
298 13906 : NWWriter_SUMO::writeConnection(cdevice, *e, c, false, NWWriter_SUMO::PLAIN, useGeo, geoAccuracy);
299 13906 : }
300 5623 : cdevice.lf();
301 : }
302 8180 : }
303 : // write roundabout information to the edges-files
304 366 : if (ec.getRoundabouts().size() > 0) {
305 8 : edevice.lf();
306 16 : NWWriter_SUMO::writeRoundabouts(edevice, ec.getRoundabouts(), ec);
307 : }
308 :
309 : // write loaded prohibitions to the connections-file
310 4901 : for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
311 4718 : NWWriter_SUMO::writeProhibitions(cdevice, i->second->getProhibitions(), ec);
312 : }
313 : // write pedestrian crossings to the connections-file
314 4901 : for (std::map<std::string, NBNode*>::const_iterator it_node = nc.begin(); it_node != nc.end(); ++it_node) {
315 4718 : const std::vector<NBNode::Crossing*>& crossings = (*it_node).second->getCrossings();
316 6039 : for (auto c : crossings) {
317 1321 : cdevice.openTag(SUMO_TAG_CROSSING);
318 1321 : cdevice.writeAttr(SUMO_ATTR_NODE, (*it_node).second->getID());
319 1321 : cdevice.writeAttr(SUMO_ATTR_EDGES, c->edges);
320 1321 : cdevice.writeAttr(SUMO_ATTR_PRIORITY, c->priority);
321 1321 : cdevice.writeOptionalAttr(SUMO_ATTR_WIDTH, c->customWidth, c->customWidth == NBEdge::UNSPECIFIED_WIDTH);
322 1321 : cdevice.writeOptionalAttr(SUMO_ATTR_TLLINKINDEX, c->customTLIndex, c->customTLIndex == -1);
323 2642 : cdevice.writeOptionalAttr(SUMO_ATTR_TLLINKINDEX2, c->customTLIndex2, c->customTLIndex2 == -1);
324 1321 : NWWriter_SUMO::writeShape(cdevice, gch, c->customShape, SUMO_ATTR_SHAPE, useGeo, geoAccuracy, c->customShape.size() != 0);
325 1321 : NWWriter_SUMO::writeShape(cdevice, gch, c->outlineShape, SUMO_ATTR_OUTLINESHAPE, useGeo, geoAccuracy, c->outlineShape.size() != 0);
326 1321 : c->writeParams(cdevice);
327 2642 : cdevice.closeTag();
328 : }
329 4718 : }
330 : // write custom walkingarea shapes to the connections file
331 4901 : for (std::map<std::string, NBNode*>::const_iterator it_node = nc.begin(); it_node != nc.end(); ++it_node) {
332 4725 : for (const auto& wacs : it_node->second->getWalkingAreaCustomShapes()) {
333 7 : cdevice.openTag(SUMO_TAG_WALKINGAREA);
334 7 : cdevice.writeAttr(SUMO_ATTR_NODE, it_node->first);
335 7 : cdevice.writeAttr(SUMO_ATTR_EDGES, joinNamedToString(wacs.edges, " "));
336 7 : NWWriter_SUMO::writeShape(cdevice, gch, wacs.shape, SUMO_ATTR_SHAPE, useGeo, geoAccuracy, wacs.shape.size() != 0);
337 7 : cdevice.writeOptionalAttr(SUMO_ATTR_WIDTH, wacs.width, wacs.width == NBEdge::UNSPECIFIED_WIDTH);
338 14 : cdevice.closeTag();
339 : }
340 : }
341 :
342 183 : edevice.close();
343 183 : cdevice.close();
344 183 : }
345 :
346 :
347 : void
348 183 : NWWriter_XML::writeTrafficLights(const std::string& prefix, NBTrafficLightLogicCont& tc, NBEdgeCont& ec) {
349 366 : const std::string ext = OptionsCont::getOptions().getString("output.format");
350 : std::map<SumoXMLAttr, std::string> attrs;
351 183 : attrs[SUMO_ATTR_VERSION] = toString(NETWORK_VERSION);
352 549 : OutputDevice& device = OutputDevice::getDevice(prefix + ".tll." + ext);
353 366 : device.writeXMLHeader("tlLogics", "tllogic_file.xsd", attrs);
354 183 : NWWriter_SUMO::writeTrafficLights(device, tc);
355 : // we also need to remember the associations between tlLogics and connections
356 : // since the information in con.xml is insufficient
357 8363 : for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
358 8180 : NBEdge* e = (*i).second;
359 : // write this edge's tl-controlled connections
360 8180 : const std::vector<NBEdge::Connection> connections = e->getConnections();
361 22086 : for (std::vector<NBEdge::Connection>::const_iterator c = connections.begin(); c != connections.end(); ++c) {
362 13906 : if (c->tlID != "") {
363 2269 : NWWriter_SUMO::writeConnection(device, *e, *c, false, NWWriter_SUMO::TLL);
364 : }
365 : }
366 8180 : }
367 183 : device.close();
368 183 : }
369 :
370 :
371 : void
372 5 : NWWriter_XML::writeJoinedJunctions(const std::string& filename, NBNodeCont& nc) {
373 : std::map<SumoXMLAttr, std::string> attrs;
374 5 : attrs[SUMO_ATTR_VERSION] = toString(NETWORK_VERSION);
375 5 : OutputDevice& device = OutputDevice::getDevice(filename);
376 10 : device.writeXMLHeader("nodes", "nodes_file.xsd", attrs);
377 10 : for (const std::set<std::string>& joined : nc.getJoinedClusters()) {
378 : assert(joined.size() > 0);
379 10 : device.openTag(SUMO_TAG_JOIN).writeAttr(SUMO_ATTR_NODES, joined).closeTag();
380 : }
381 5 : device.close();
382 5 : }
383 :
384 :
385 : void
386 1 : NWWriter_XML::writeStreetSigns(const OptionsCont& oc, NBEdgeCont& ec) {
387 2 : OutputDevice& device = OutputDevice::getDevice(oc.getString("street-sign-output"));
388 2 : device.writeXMLHeader("additional", "additional_file.xsd");
389 23 : for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
390 22 : NBEdge* e = (*i).second;
391 : const std::vector<NBSign>& signs = e->getSigns();
392 30 : for (std::vector<NBSign>::const_iterator it = signs.begin(); it != signs.end(); ++it) {
393 8 : it->writeAsPOI(device, e);
394 : }
395 : }
396 1 : device.close();
397 1 : }
398 :
399 :
400 : void
401 82 : NWWriter_XML::writePTStops(const OptionsCont& oc, NBPTStopCont& sc) {
402 164 : OutputDevice& device = OutputDevice::getDevice(oc.getString("ptstop-output"));
403 164 : device.writeXMLHeader("additional", "additional_file.xsd");
404 894 : for (const auto& stopIt : sc.getStops()) {
405 812 : stopIt.second->write(device);
406 : }
407 82 : device.close();
408 82 : }
409 :
410 :
411 52 : void NWWriter_XML::writePTLines(const OptionsCont& oc, NBPTLineCont& lc) {
412 104 : OutputDevice& device = OutputDevice::getDevice(oc.getString("ptline-output"));
413 104 : device.writeXMLHeader("ptLines", "ptlines_file.xsd");
414 448 : for (const auto& item : lc.getLines()) {
415 396 : item.second->write(device);
416 : }
417 52 : device.close();
418 52 : }
419 :
420 :
421 3 : void NWWriter_XML::writeParkingAreas(const OptionsCont& oc, NBParkingCont& pc, NBEdgeCont& ec) {
422 6 : OutputDevice& device = OutputDevice::getDevice(oc.getString("parking-output"));
423 6 : device.writeXMLHeader("additional", "additional_file.xsd");
424 297 : for (NBParking& p : pc) {
425 294 : p.write(device, ec);
426 : }
427 3 : device.close();
428 3 : }
429 :
430 :
431 : void
432 1 : NWWriter_XML::writeDistricts(const OptionsCont& oc, NBDistrictCont& dc) {
433 2 : OutputDevice& device = OutputDevice::getDevice(oc.getString("taz-output"));
434 2 : device.writeXMLHeader("additional", "additional_file.xsd");
435 30 : for (std::map<std::string, NBDistrict*>::const_iterator i = dc.begin(); i != dc.end(); i++) {
436 29 : NWWriter_SUMO::writeDistrict(device, *(*i).second);
437 : }
438 1 : }
439 :
440 :
441 : /****************************************************************************/
|