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