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 2225 : NWWriter_XML::writeNetwork(const OptionsCont& oc, const std::string& prefix, NBNetBuilder& nb) {
52 : // check whether plain-output files shall be generated
53 2225 : if (prefix != "") {
54 181 : const bool haveTypes = nb.getTypeCont().size() > 0;
55 181 : writeNodes(oc, prefix, nb.getNodeCont());
56 179 : if (haveTypes) {
57 16 : writeTypes(prefix, nb.getEdgeCont(), nb.getTypeCont());
58 : }
59 179 : writeEdgesAndConnections(oc, prefix, nb.getNodeCont(), nb.getEdgeCont());
60 179 : writeTrafficLights(prefix, nb.getTLLogicCont(), nb.getEdgeCont());
61 179 : writeConfig(oc, prefix, haveTypes);
62 : }
63 2233 : 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 2225 : if (oc.isSet("street-sign-output") && (oc.getString("street-sign-output").size() > 0)) {
67 1 : writeStreetSigns(oc, nb.getEdgeCont());
68 : }
69 4525 : if (oc.exists("ptstop-output") && oc.isSet("ptstop-output") && (oc.getString("ptstop-output").size() > 0)) {
70 82 : writePTStops(oc, nb.getPTStopCont());
71 : }
72 4465 : if (oc.exists("ptline-output") && oc.isSet("ptline-output") && (oc.getString("ptline-output").size() > 0)) {
73 52 : writePTLines(oc, nb.getPTLineCont());
74 : }
75 4367 : 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 4363 : if (oc.exists("taz-output") && oc.isSet("taz-output") && (oc.getString("taz-output").size() > 0)) {
79 1 : writeDistricts(oc, nb.getDistrictCont());
80 : }
81 2223 : }
82 :
83 :
84 : void
85 179 : NWWriter_XML::writeConfig(const OptionsCont& oc, const std::string& prefix, bool haveTypes) {
86 358 : if (!oc.exists("node-files")) {
87 : // do not write configuration for netgen
88 1 : return;
89 : }
90 178 : const std::string ext = oc.getString("output.format");
91 178 : OptionsCont* tmp = oc.clone();
92 534 : tmp->set("node-files", prefix + ".nod." + ext);
93 534 : tmp->set("edge-files", prefix + ".edg." + ext);
94 534 : tmp->set("connection-files", prefix + ".con." + ext);
95 534 : tmp->set("tllogic-files", prefix + ".tll." + ext);
96 178 : if (haveTypes) {
97 64 : tmp->set("type-files", prefix + ".typ." + ext);
98 : }
99 356 : tmp->setDefault("sumo-net-file", "");
100 356 : tmp->setDefault("plain-output-prefix", "");
101 :
102 178 : const std::string configPath = prefix + ".netccfg";
103 178 : std::ofstream out(configPath.c_str());
104 178 : if (!out.good()) {
105 0 : delete tmp;
106 0 : throw ProcessError(TLF("Could not save configuration to '%'", configPath));
107 : } else {
108 356 : tmp->writeConfiguration(out, true, false, false);
109 : }
110 178 : delete tmp;
111 178 : }
112 :
113 :
114 : void
115 181 : NWWriter_XML::writeNodes(const OptionsCont& oc, const std::string& prefix, NBNodeCont& nc) {
116 181 : const std::string ext = oc.getString("output.format");
117 : const GeoConvHelper& gch = GeoConvHelper::getFinal();
118 360 : bool useGeo = oc.exists("proj.plain-geo") && oc.getBool("proj.plain-geo");
119 181 : 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 181 : const bool geoAccuracy = useGeo || gch.usingInverseGeoProjection();
124 :
125 541 : OutputDevice& device = OutputDevice::getDevice(prefix + ".nod." + ext);
126 181 : device.setExpectedAttributes(0, 4);
127 : std::map<SumoXMLAttr, std::string> attrs;
128 179 : attrs[SUMO_ATTR_VERSION] = toString(NETWORK_VERSION);
129 358 : device.writeXMLHeader("nodes", "nodes_file.xsd", attrs);
130 :
131 : // write network offsets and projection to allow reconstruction of original coordinates
132 179 : if (!useGeo) {
133 175 : GeoConvHelper::writeLocation(device);
134 : }
135 :
136 : // write nodes
137 358 : TrafficLightType tlsDefaultType = SUMOXMLDefinitions::TrafficLightTypes.get(oc.getString("tls.default-type"));
138 2157 : for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
139 1978 : NBNode* n = (*i).second;
140 1978 : device.openTag(SUMO_TAG_NODE);
141 1978 : device.writeAttr(SUMO_ATTR_ID, n->getID());
142 : // write position
143 1978 : Position pos = n->getPosition();
144 1978 : if (useGeo) {
145 99 : gch.cartesian2geo(pos);
146 : }
147 1978 : if (geoAccuracy) {
148 99 : device.setPrecision(gPrecisionGeo);
149 : }
150 1978 : NWFrame::writePositionLong(pos, device);
151 1978 : if (geoAccuracy) {
152 99 : device.setPrecision();
153 : }
154 :
155 1978 : device.writeAttr(SUMO_ATTR_TYPE, toString(n->getType()));
156 : // std::set is already sorted, so the output is stable
157 : std::set<std::string> tlsIDs;
158 : std::set<std::string> controlledInnerEdges;
159 1978 : std::string tlType = "";
160 2086 : for (NBTrafficLightDefinition* tl : n->getControllingTLS()) {
161 : tlsIDs.insert(tl->getID());
162 108 : std::vector<std::string> cie = tl->getControlledInnerEdges();
163 : controlledInnerEdges.insert(cie.begin(), cie.end());
164 108 : if (tl->getType() != tlsDefaultType) {
165 8 : tlType = toString(tl->getType());
166 : }
167 108 : }
168 1978 : device.writeOptionalAttr(SUMO_ATTR_TLID, tlsIDs, tlsIDs.empty());
169 3956 : device.writeOptionalAttr(SUMO_ATTR_TLTYPE, tlType, tlType == "");
170 1978 : device.writeOptionalAttr(SUMO_ATTR_CONTROLLED_INNER, controlledInnerEdges, controlledInnerEdges.empty());
171 3956 : NWWriter_SUMO::writeShape(device, gch, n->getShape(), SUMO_ATTR_SHAPE, useGeo, geoAccuracy, n->hasCustomShape());
172 3956 : device.writeOptionalAttr(SUMO_ATTR_RADIUS, n->getRadius(), n->getRadius() == NBNode::UNSPECIFIED_RADIUS);
173 3956 : device.writeOptionalAttr<bool>(SUMO_ATTR_KEEP_CLEAR, n->getKeepClear(), n->getKeepClear());
174 3956 : device.writeOptionalAttr(SUMO_ATTR_RIGHT_OF_WAY, toString(n->getRightOfWay()), n->getRightOfWay() == RightOfWay::DEFAULT);
175 3956 : device.writeOptionalAttr(SUMO_ATTR_FRINGE, toString(n->getFringeType()), n->getFringeType() == FringeType::DEFAULT);
176 3956 : device.writeOptionalAttr(SUMO_ATTR_ROUNDABOUT, toString(n->getRoundaboutType()), n->getRoundaboutType() == RoundaboutType::DEFAULT);
177 3956 : device.writeOptionalAttr(SUMO_ATTR_NAME, StringUtils::escapeXML(n->getName()), n->getName() == "");
178 1978 : n->writeParams(device);
179 3956 : device.closeTag();
180 : }
181 179 : device.close();
182 179 : }
183 :
184 :
185 : void
186 16 : NWWriter_XML::writeTypes(const std::string& prefix, NBEdgeCont& ec, NBTypeCont& tc) {
187 16 : const std::string ext = OptionsCont::getOptions().getString("output.format");
188 48 : OutputDevice& device = OutputDevice::getDevice(prefix + ".typ." + ext);
189 16 : device.setExpectedAttributes(0, 4);
190 : std::map<SumoXMLAttr, std::string> attrs;
191 16 : attrs[SUMO_ATTR_VERSION] = toString(NETWORK_VERSION);
192 32 : device.writeXMLHeader(toString(SUMO_TAG_TYPES), "types_file.xsd", attrs);
193 16 : std::set<std::string> usedTypes = ec.getUsedTypes();
194 16 : tc.writeEdgeTypes(device, usedTypes);
195 16 : device.close();
196 16 : }
197 :
198 :
199 : void
200 179 : NWWriter_XML::writeEdgesAndConnections(const OptionsCont& oc, const std::string& prefix, NBNodeCont& nc, NBEdgeCont& ec) {
201 179 : const std::string ext = oc.getString("output.format");
202 : const GeoConvHelper& gch = GeoConvHelper::getFinal();
203 357 : bool useGeo = oc.exists("proj.plain-geo") && oc.getBool("proj.plain-geo");
204 179 : const bool geoAccuracy = useGeo || gch.usingInverseGeoProjection();
205 :
206 : std::map<SumoXMLAttr, std::string> attrs;
207 179 : attrs[SUMO_ATTR_VERSION] = toString(NETWORK_VERSION);
208 537 : OutputDevice& edevice = OutputDevice::getDevice(prefix + ".edg." + ext);
209 179 : edevice.setExpectedAttributes(0, 4);
210 358 : edevice.writeXMLHeader("edges", "edges_file.xsd", attrs);
211 537 : OutputDevice& cdevice = OutputDevice::getDevice(prefix + ".con." + ext);
212 358 : cdevice.writeXMLHeader("connections", "connections_file.xsd", attrs);
213 179 : const bool writeNames = oc.getBool("output.street-names");
214 179 : const bool writeLanes = oc.getBool("plain-output.lanes");
215 :
216 : // write network offsets and projection to allow reconstruction of original coordinates at least for geo-referenced networks
217 179 : if (!useGeo && gch.usingGeoProjection()) {
218 24 : GeoConvHelper::writeLocation(edevice);
219 : }
220 358 : LaneSpreadFunction defaultSpread = SUMOXMLDefinitions::LaneSpreadFunctions.get(oc.getString("default.spreadtype"));
221 3615 : for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
222 : // write the edge itself to the edges-files
223 3436 : NBEdge* e = (*i).second;
224 3436 : edevice.openTag(SUMO_TAG_EDGE);
225 3436 : edevice.writeAttr(SUMO_ATTR_ID, e->getID());
226 3436 : edevice.writeAttr(SUMO_ATTR_FROM, e->getFromNode()->getID());
227 3436 : edevice.writeAttr(SUMO_ATTR_TO, e->getToNode()->getID());
228 6872 : edevice.writeOptionalAttr(SUMO_ATTR_NAME, StringUtils::escapeXML(e->getStreetName()), 0, !writeNames || e->getStreetName() == "");
229 3436 : edevice.writeAttr(SUMO_ATTR_PRIORITY, e->getPriority());
230 : // write the type if given
231 3436 : edevice.writeOptionalAttr(SUMO_ATTR_TYPE, e->getTypeID(), 0, e->getTypeID() == "");
232 3436 : edevice.writeOptionalAttr(SUMO_ATTR_ROUTINGTYPE, e->getRoutingType(), 0, e->getRoutingType() == "");
233 3436 : edevice.writeAttr(SUMO_ATTR_NUMLANES, e->getNumLanes());
234 3436 : edevice.writeOptionalAttr(SUMO_ATTR_SPEED, e->getSpeed(), 0, e->hasLaneSpecificSpeed());
235 6869 : edevice.writeOptionalAttr(SUMO_ATTR_FRICTION, e->getFriction(), 0, e->getFriction() == NBEdge::UNSPECIFIED_FRICTION || e->hasLaneSpecificFriction());
236 : // write non-default geometry
237 3436 : NWWriter_SUMO::writeShape(edevice, gch, e->getGeometry(), SUMO_ATTR_SHAPE, useGeo, geoAccuracy, !e->hasDefaultGeometry());
238 : // write the spread type if not default ("right")
239 6872 : edevice.writeOptionalAttr(SUMO_ATTR_SPREADTYPE, toString(e->getLaneSpreadFunction()), 0, e->getLaneSpreadFunction() == defaultSpread);
240 : // write the length if it was specified
241 6869 : edevice.writeOptionalAttr(SUMO_ATTR_LENGTH, e->getLoadedLength(), 0, !e->hasLoadedLength());
242 : // some attributes can be set by edge default or per lane. Write as default if possible (efficiency)
243 6621 : edevice.writeOptionalAttr(SUMO_ATTR_WIDTH, e->getLaneWidth(), 0, e->getLaneWidth() == NBEdge::UNSPECIFIED_WIDTH || e->hasLaneSpecificWidth());
244 6865 : edevice.writeOptionalAttr(SUMO_ATTR_ENDOFFSET, e->getEndOffset(), 0, e->getEndOffset() == NBEdge::UNSPECIFIED_OFFSET || e->hasLaneSpecificEndOffset());
245 : // SVC_UNSPECIFIED is here a shortcut for do not write
246 3436 : writePermissions(edevice, e->hasLaneSpecificPermissions() ? SVC_UNSPECIFIED : e->getPermissions(0));
247 3436 : if (!e->hasLaneSpecificStopOffsets() && e->getEdgeStopOffset().isDefined()) {
248 0 : NWWriter_SUMO::writeStopOffsets(edevice, e->getEdgeStopOffset());
249 : }
250 3436 : edevice.writeOptionalAttr(SUMO_ATTR_DISTANCE, e->getDistance(), 0, e->getDistance() == 0);
251 3466 : edevice.writeOptionalAttr(SUMO_ATTR_BIDI, e->getBidiEdge() == nullptr ? "" : e->getBidiEdge()->getID(), 0, e->getBidiEdge() == nullptr);
252 3436 : if (e->needsLaneSpecificOutput() || writeLanes) {
253 : int idx = 0;
254 3630 : for (const NBEdge::Lane& lane : e->getLanes()) {
255 2622 : edevice.openTag(SUMO_TAG_LANE);
256 2622 : edevice.writeAttr(SUMO_ATTR_INDEX, idx++);
257 : // write allowed lanes
258 2622 : if (e->hasLaneSpecificPermissions() || writeLanes) {
259 2455 : writePermissions(edevice, lane.permissions);
260 : }
261 2622 : writePreferences(edevice, lane.preferred);
262 : // write other attributes
263 2622 : if (lane.width != NBEdge::UNSPECIFIED_WIDTH && (e->hasLaneSpecificWidth() || writeLanes)) {
264 1118 : edevice.writeAttr(SUMO_ATTR_WIDTH, lane.width);
265 : }
266 2622 : if (lane.endOffset != NBEdge::UNSPECIFIED_OFFSET && (e->hasLaneSpecificEndOffset() || writeLanes)) {
267 8 : edevice.writeAttr(SUMO_ATTR_ENDOFFSET, lane.endOffset);
268 : }
269 2622 : if (e->hasLaneSpecificSpeed() || writeLanes) {
270 25 : edevice.writeAttr(SUMO_ATTR_SPEED, lane.speed);
271 : }
272 2622 : if (lane.accelRamp) {
273 1 : edevice.writeAttr(SUMO_ATTR_ACCELERATION, lane.accelRamp);
274 : }
275 5249 : NWWriter_SUMO::writeShape(edevice, gch, lane.customShape.size() > 0 ? lane.customShape : lane.shape, SUMO_ATTR_SHAPE, useGeo, geoAccuracy, lane.customShape.size() > 0 || writeLanes);
276 2622 : if (lane.type != "") {
277 3 : edevice.writeAttr(SUMO_ATTR_TYPE, lane.type);
278 : }
279 2622 : if (lane.changeLeft != SVCAll && lane.changeLeft != SVC_UNSPECIFIED && lane.changeLeft != SVC_IGNORING) {
280 6 : edevice.writeAttr(SUMO_ATTR_CHANGE_LEFT, getVehicleClassNames(lane.changeLeft));
281 : }
282 2622 : if (lane.changeRight != SVCAll && lane.changeRight != SVC_UNSPECIFIED && lane.changeRight != SVC_IGNORING) {
283 7 : edevice.writeAttr(SUMO_ATTR_CHANGE_RIGHT, getVehicleClassNames(lane.changeRight));
284 : }
285 2622 : if (lane.oppositeID != "") {
286 47 : edevice.openTag(SUMO_TAG_NEIGH);
287 47 : edevice.writeAttr(SUMO_ATTR_LANE, lane.oppositeID);
288 94 : edevice.closeTag();
289 : }
290 2622 : lane.writeParams(edevice);
291 2622 : NWWriter_SUMO::writeStopOffsets(edevice, lane.laneStopOffset);
292 5244 : edevice.closeTag();
293 : }
294 : }
295 3436 : e->writeParams(edevice);
296 6872 : edevice.closeTag();
297 : // write this edge's connections to the connections-files
298 3436 : const std::vector<NBEdge::Connection> connections = e->getConnections();
299 3436 : if (connections.empty()) {
300 : // if there are no connections and this appears to be customized, preserve the information
301 401 : const int numOutgoing = (int)e->getToNode()->getOutgoingEdges().size();
302 401 : if (numOutgoing > 0) {
303 227 : const SVCPermissions inPerm = e->getPermissions();
304 : SVCPermissions outPerm = 0;
305 557 : for (auto out : e->getToNode()->getOutgoingEdges()) {
306 330 : outPerm |= out->getPermissions();
307 : }
308 227 : if ((inPerm & outPerm) != 0 && (inPerm & outPerm) != SVC_PEDESTRIAN) {
309 122 : cdevice.openTag(SUMO_TAG_CONNECTION);
310 122 : cdevice.writeAttr(SUMO_ATTR_FROM, e->getID());
311 122 : cdevice.closeTag();
312 122 : cdevice.lf();
313 : }
314 : }
315 : } else {
316 11349 : for (NBEdge::Connection c : connections) {
317 8314 : NWWriter_SUMO::writeConnection(cdevice, *e, c, false, NWWriter_SUMO::PLAIN, useGeo, geoAccuracy);
318 8314 : }
319 3035 : cdevice.lf();
320 : }
321 3436 : }
322 : // write roundabout information to the edges-files
323 358 : if (ec.getRoundabouts().size() > 0) {
324 8 : edevice.lf();
325 16 : NWWriter_SUMO::writeRoundabouts(edevice, ec.getRoundabouts(), ec);
326 : }
327 :
328 : // write loaded prohibitions to the connections-file
329 2157 : for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
330 1978 : NWWriter_SUMO::writeProhibitions(cdevice, i->second->getProhibitions(), ec);
331 : }
332 : // write pedestrian crossings to the connections-file
333 2157 : for (std::map<std::string, NBNode*>::const_iterator it_node = nc.begin(); it_node != nc.end(); ++it_node) {
334 1978 : const std::vector<NBNode::Crossing*>& crossings = (*it_node).second->getCrossings();
335 2063 : for (auto c : crossings) {
336 85 : cdevice.openTag(SUMO_TAG_CROSSING);
337 85 : cdevice.writeAttr(SUMO_ATTR_NODE, (*it_node).second->getID());
338 85 : cdevice.writeAttr(SUMO_ATTR_EDGES, c->edges);
339 85 : cdevice.writeAttr(SUMO_ATTR_PRIORITY, c->priority);
340 85 : if (c->customWidth != NBEdge::UNSPECIFIED_WIDTH) {
341 39 : cdevice.writeAttr(SUMO_ATTR_WIDTH, c->customWidth);
342 : }
343 85 : if (c->customTLIndex != -1) {
344 24 : cdevice.writeAttr(SUMO_ATTR_TLLINKINDEX, c->customTLIndex);
345 : }
346 85 : if (c->customTLIndex2 != -1) {
347 4 : cdevice.writeAttr(SUMO_ATTR_TLLINKINDEX2, c->customTLIndex2);
348 : }
349 85 : NWWriter_SUMO::writeShape(cdevice, gch, c->customShape, SUMO_ATTR_SHAPE, useGeo, geoAccuracy, c->customShape.size() != 0);
350 85 : NWWriter_SUMO::writeShape(cdevice, gch, c->outlineShape, SUMO_ATTR_OUTLINESHAPE, useGeo, geoAccuracy, c->outlineShape.size() != 0);
351 85 : c->writeParams(cdevice);
352 170 : cdevice.closeTag();
353 : }
354 1978 : }
355 : // write custom walkingarea shapes to the connections file
356 2157 : for (std::map<std::string, NBNode*>::const_iterator it_node = nc.begin(); it_node != nc.end(); ++it_node) {
357 1985 : for (const auto& wacs : it_node->second->getWalkingAreaCustomShapes()) {
358 7 : cdevice.openTag(SUMO_TAG_WALKINGAREA);
359 7 : cdevice.writeAttr(SUMO_ATTR_NODE, it_node->first);
360 7 : cdevice.writeAttr(SUMO_ATTR_EDGES, joinNamedToString(wacs.edges, " "));
361 7 : NWWriter_SUMO::writeShape(cdevice, gch, wacs.shape, SUMO_ATTR_SHAPE, useGeo, geoAccuracy, wacs.shape.size() != 0);
362 7 : if (wacs.width != NBEdge::UNSPECIFIED_WIDTH) {
363 1 : cdevice.writeAttr(SUMO_ATTR_WIDTH, wacs.width);
364 : }
365 14 : cdevice.closeTag();
366 : }
367 : }
368 :
369 179 : edevice.close();
370 179 : cdevice.close();
371 179 : }
372 :
373 :
374 : void
375 179 : NWWriter_XML::writeTrafficLights(const std::string& prefix, NBTrafficLightLogicCont& tc, NBEdgeCont& ec) {
376 358 : const std::string ext = OptionsCont::getOptions().getString("output.format");
377 : std::map<SumoXMLAttr, std::string> attrs;
378 179 : attrs[SUMO_ATTR_VERSION] = toString(NETWORK_VERSION);
379 537 : OutputDevice& device = OutputDevice::getDevice(prefix + ".tll." + ext);
380 179 : device.setExpectedAttributes(0, 4);
381 358 : device.writeXMLHeader("tlLogics", "tllogic_file.xsd", attrs);
382 179 : NWWriter_SUMO::writeTrafficLights(device, tc);
383 : // we also need to remember the associations between tlLogics and connections
384 : // since the information in con.xml is insufficient
385 3615 : for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
386 3436 : NBEdge* e = (*i).second;
387 : // write this edge's tl-controlled connections
388 3436 : const std::vector<NBEdge::Connection> connections = e->getConnections();
389 11750 : for (std::vector<NBEdge::Connection>::const_iterator c = connections.begin(); c != connections.end(); ++c) {
390 8314 : if (c->tlID != "") {
391 1129 : NWWriter_SUMO::writeConnection(device, *e, *c, false, NWWriter_SUMO::TLL);
392 : }
393 : }
394 3436 : }
395 179 : device.close();
396 179 : }
397 :
398 :
399 : void
400 5 : NWWriter_XML::writeJoinedJunctions(const std::string& filename, NBNodeCont& nc) {
401 : std::map<SumoXMLAttr, std::string> attrs;
402 5 : attrs[SUMO_ATTR_VERSION] = toString(NETWORK_VERSION);
403 5 : OutputDevice& device = OutputDevice::getDevice(filename);
404 10 : device.writeXMLHeader("nodes", "nodes_file.xsd", attrs);
405 10 : for (const std::set<std::string>& joined : nc.getJoinedClusters()) {
406 : assert(joined.size() > 0);
407 10 : device.openTag(SUMO_TAG_JOIN).writeAttr(SUMO_ATTR_NODES, joined).closeTag();
408 : }
409 5 : device.close();
410 5 : }
411 :
412 :
413 : void
414 1 : NWWriter_XML::writeStreetSigns(const OptionsCont& oc, NBEdgeCont& ec) {
415 2 : OutputDevice& device = OutputDevice::getDevice(oc.getString("street-sign-output"));
416 2 : device.writeXMLHeader("additional", "additional_file.xsd");
417 23 : for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
418 22 : NBEdge* e = (*i).second;
419 : const std::vector<NBSign>& signs = e->getSigns();
420 30 : for (std::vector<NBSign>::const_iterator it = signs.begin(); it != signs.end(); ++it) {
421 8 : it->writeAsPOI(device, e);
422 : }
423 : }
424 1 : device.close();
425 1 : }
426 :
427 :
428 : void
429 82 : NWWriter_XML::writePTStops(const OptionsCont& oc, NBPTStopCont& sc) {
430 164 : OutputDevice& device = OutputDevice::getDevice(oc.getString("ptstop-output"));
431 164 : device.writeXMLHeader("additional", "additional_file.xsd");
432 894 : for (const auto& stopIt : sc.getStops()) {
433 812 : stopIt.second->write(device);
434 : }
435 82 : device.close();
436 82 : }
437 :
438 :
439 52 : void NWWriter_XML::writePTLines(const OptionsCont& oc, NBPTLineCont& lc) {
440 104 : OutputDevice& device = OutputDevice::getDevice(oc.getString("ptline-output"));
441 104 : device.writeXMLHeader("ptLines", "ptlines_file.xsd");
442 448 : for (const auto& item : lc.getLines()) {
443 396 : item.second->write(device);
444 : }
445 52 : device.close();
446 52 : }
447 :
448 :
449 3 : void NWWriter_XML::writeParkingAreas(const OptionsCont& oc, NBParkingCont& pc, NBEdgeCont& ec) {
450 6 : OutputDevice& device = OutputDevice::getDevice(oc.getString("parking-output"));
451 6 : device.writeXMLHeader("additional", "additional_file.xsd");
452 297 : for (NBParking& p : pc) {
453 294 : p.write(device, ec);
454 : }
455 3 : device.close();
456 3 : }
457 :
458 :
459 : void
460 1 : NWWriter_XML::writeDistricts(const OptionsCont& oc, NBDistrictCont& dc) {
461 2 : OutputDevice& device = OutputDevice::getDevice(oc.getString("taz-output"));
462 2 : device.writeXMLHeader("additional", "additional_file.xsd");
463 30 : for (std::map<std::string, NBDistrict*>::const_iterator i = dc.begin(); i != dc.end(); i++) {
464 29 : NWWriter_SUMO::writeDistrict(device, *(*i).second);
465 : }
466 1 : }
467 :
468 :
469 : /****************************************************************************/
|