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