Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/polyconvert/polyconvert_main.cpp
169666 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2005-2025 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 polyconvert_main.cpp
15
/// @author Daniel Krajzewicz
16
/// @author Jakob Erdmann
17
/// @author Christoph Sommer
18
/// @author Michael Behrisch
19
/// @author Melanie Knocke
20
/// @date Mon, 05 Dec 2005
21
///
22
// Main for POLYCONVERT
23
/****************************************************************************/
24
#include <config.h>
25
26
#ifdef HAVE_VERSION_H
27
#include <version.h>
28
#endif
29
30
#include <iostream>
31
#include <string>
32
#include <utils/options/OptionsIO.h>
33
#include <utils/options/OptionsCont.h>
34
#include <utils/common/UtilExceptions.h>
35
#include <utils/common/StringTokenizer.h>
36
#include <utils/common/SystemFrame.h>
37
#include <utils/common/MsgHandler.h>
38
#include <utils/common/StringUtils.h>
39
#include <utils/common/ToString.h>
40
#include <utils/iodevices/OutputDevice.h>
41
#include <utils/importio/LineReader.h>
42
#include <utils/geom/GeoConvHelper.h>
43
#include <utils/geom/GeomConvHelper.h>
44
#include <utils/geom/Boundary.h>
45
#include <utils/xml/SUMOSAXReader.h>
46
#include <utils/xml/XMLSubSys.h>
47
#include <polyconvert/PCLoaderVisum.h>
48
#include <polyconvert/PCLoaderDlrNavteq.h>
49
#include <polyconvert/PCLoaderXML.h>
50
#include <polyconvert/PCLoaderOSM.h>
51
#include <polyconvert/PCLoaderArcView.h>
52
#include <polyconvert/PCTypeMap.h>
53
#include <polyconvert/PCTypeDefHandler.h>
54
#include <polyconvert/PCNetProjectionLoader.h>
55
#include <polyconvert/pc_typemap.h>
56
57
58
// ===========================================================================
59
// method definitions
60
// ===========================================================================
61
void
62
fillOptions() {
63
OptionsCont& oc = OptionsCont::getOptions();
64
oc.addCallExample("-c <CONFIGURATION>", "run with configuration options set in file");
65
66
// insert options sub-topics
67
SystemFrame::addConfigurationOptions(oc); // fill this subtopic, too
68
oc.addOptionSubTopic("Input");
69
oc.addOptionSubTopic("Output");
70
GeoConvHelper::addProjectionOptions(oc);
71
oc.addOptionSubTopic("Pruning");
72
oc.addOptionSubTopic("Processing");
73
oc.addOptionSubTopic("Building Defaults");
74
75
76
// register options
77
// add i/o options
78
// original network
79
oc.doRegister("net-file", 'n', new Option_FileName());
80
oc.addSynonyme("net-file", "net");
81
oc.addDescription("net-file", "Input", TL("Loads SUMO-network FILE as reference to offset and projection"));
82
83
// dlrnavteq import
84
oc.doRegister("dlr-navteq-poly-files", new Option_FileName());
85
oc.addDescription("dlr-navteq-poly-files", "Input", TL("Reads polygons from FILE assuming they're coded in DLR-Navteq (Elmar)-format"));
86
oc.doRegister("dlr-navteq-poi-files", new Option_FileName());
87
oc.addDescription("dlr-navteq-poi-files", "Input", TL("Reads pois from FILE assuming they're coded in DLR-Navteq (Elmar)-format"));
88
89
// visum import
90
oc.doRegister("visum-files", new Option_FileName());
91
oc.addSynonyme("visum-files", "visum");
92
oc.addDescription("visum-files", "Input", TL("Reads polygons from FILE assuming it's a Visum-net"));
93
94
oc.doRegister("visum.language-file", new Option_FileName());
95
oc.addDescription("visum.language-file", "Input", TL("Load language mappings from FILE"));
96
97
// xml import
98
oc.doRegister("xml-files", new Option_FileName());
99
oc.addSynonyme("xml-files", "xml");
100
oc.addDescription("xml-files", "Input", TL("Reads pois and shapes from FILE assuming they're coded in XML"));
101
102
// osm import
103
oc.doRegister("osm-files", new Option_FileName());
104
oc.addSynonyme("osm-files", "osm");
105
oc.addDescription("osm-files", "Input", TL("Reads pois from FILE assuming they're coded in OSM"));
106
oc.doRegister("osm.keep-full-type", new Option_Bool(false));
107
oc.addDescription("osm.keep-full-type", "Input", TL("The type will be made of the key-value - pair"));
108
oc.doRegister("osm.use-name", new Option_Bool(false));
109
oc.addDescription("osm.use-name", "Input", TL("The id will be set from the given 'name' attribute"));
110
oc.doRegister("osm.merge-relations", new Option_Float(-1));
111
oc.addDescription("osm.merge-relations", "Input", TL("If FLOAT >= 0, assemble one polygon from all ways of a relation if they all connect with gaps below FLOAT"));
112
113
// geojson import
114
oc.doRegister("geojson-files", new Option_FileName());
115
oc.addDescription("geojson-files", "Input", TL("Reads shapes from geojson FILE"));
116
117
// arcview import
118
oc.doRegister("shapefile-prefixes", new Option_FileName());
119
oc.addSynonyme("shapefile-prefixes", "shapefile-prefix");
120
oc.addSynonyme("shapefile-prefixes", "shapefile");
121
oc.addSynonyme("shapefile-prefixes", "shape-files", true);
122
oc.addDescription("shapefile-prefixes", "Input", TL("Reads shapes from shapefiles FILE"));
123
124
oc.doRegister("shapefile.guess-projection", new Option_Bool(false));
125
oc.addSynonyme("shapefile.guess-projection", "arcview.guess-projection", true);
126
oc.addDescription("shapefile.guess-projection", "Input", TL("Guesses the shapefile's projection"));
127
128
oc.doRegister("shapefile.traditional-axis-mapping", new Option_Bool(false));
129
oc.addDescription("shapefile.traditional-axis-mapping", "Input", TL("Use traditional axis order (lon, lat)"));
130
131
oc.doRegister("shapefile.id-column", new Option_String());
132
oc.addSynonyme("shapefile.id-column", "shapefile.id-name", true);
133
oc.addSynonyme("shapefile.id-column", "shape-files.id-name", true);
134
oc.addDescription("shapefile.id-column", "Input", TL("Defines in which column the id can be found"));
135
136
oc.doRegister("shapefile.type-columns", new Option_StringVector());
137
oc.addSynonyme("shapefile.type-columns", "shapefile.type-column");
138
oc.addDescription("shapefile.type-columns", "Input", TL("Defines which columns form the type id (comma separated list)"));
139
140
oc.doRegister("shapefile.use-running-id", new Option_Bool(false));
141
oc.addDescription("shapefile.use-running-id", "Input", TL("A running number will be used as id"));
142
143
oc.doRegister("shapefile.add-param", new Option_Bool(false));
144
oc.addDescription("shapefile.add-param", "Input", TL("Extract all additional columns as params"));
145
146
oc.doRegister("shapefile.fill", new Option_String());
147
oc.addDescription("shapefile.fill", "Input", TL("[auto|true|false]. Forces the 'fill' status to the given value. Default 'auto' tries to determine it from the data type"));
148
149
// typemap reading
150
oc.doRegister("type-file", new Option_FileName());
151
oc.addSynonyme("type-file", "typemap", true);
152
oc.addDescription("type-file", "Input", TL("Reads types from FILE"));
153
154
// need to do this here to be able to check for network and route input options
155
SystemFrame::addReportOptions(oc);
156
157
// output
158
oc.doRegister("output-file", 'o', new Option_FileName());
159
oc.addSynonyme("output-file", "output");
160
oc.addDescription("output-file", "Output", TL("Write generated polygons/pois to FILE"));
161
162
oc.doRegister("dlr-tdp-output", new Option_FileName());
163
oc.addDescription("dlr-tdp-output", "Output", TL("Write generated polygons/pois to a dlr-tdp file with the given prefix"));
164
165
166
// pruning options
167
oc.doRegister("prune.in-net", new Option_Bool(false));
168
oc.addSynonyme("prune.in-net", "prune.on-net", true);
169
oc.addDescription("prune.in-net", TL("Pruning"), TL("Enables pruning on net boundaries"));
170
171
oc.doRegister("prune.in-net.offsets", new Option_String("0,0,0,0"));
172
oc.addSynonyme("prune.in-net.offsets", "prune.on-net.offsets", true);
173
oc.addDescription("prune.in-net.offsets", TL("Pruning"), TL("Uses FLOAT,FLOAT,FLOAT,FLOAT as offset definition added to the net boundary. Positive values grow the boundary on all sides while negative values shrink it."));
174
175
oc.doRegister("prune.boundary", new Option_String());
176
oc.addDescription("prune.boundary", TL("Pruning"), TL("Uses STR as pruning boundary"));
177
178
oc.doRegister("prune.keep-list", new Option_String());
179
oc.addSynonyme("prune.keep-list", "prune.keep");
180
oc.addSynonyme("prune.keep-list", "prune.ignore", true);
181
oc.addDescription("prune.keep-list", TL("Pruning"), TL("Items in STR will be kept though out of boundary"));
182
183
oc.doRegister("prune.explicit", new Option_StringVector(StringVector({ "" })));
184
oc.addSynonyme("prune.explicit", "remove");
185
oc.addDescription("prune.explicit", TL("Pruning"), TL("Items with names in STR[] will be removed"));
186
187
188
oc.doRegister("offset.x", new Option_Float(0));
189
oc.addSynonyme("offset.x", "x-offset-to-apply", true);
190
oc.addDescription("offset.x", "Processing", TL("Adds FLOAT to net x-positions"));
191
192
oc.doRegister("offset.y", new Option_Float(0));
193
oc.addSynonyme("offset.y", "y-offset-to-apply", true);
194
oc.addDescription("offset.y", "Processing", TL("Adds FLOAT to net y-positions"));
195
196
oc.doRegister("offset.z", new Option_Float(0));
197
oc.addDescription("offset.z", "Processing", TL("Adds FLOAT to net z-positions"));
198
199
oc.doRegister("all-attributes", new Option_Bool(false));
200
oc.addDescription("all-attributes", "Processing", TL("Imports all attributes as key/value pairs"));
201
202
oc.doRegister("ignore-errors", new Option_Bool(false));
203
oc.addDescription("ignore-errors", "Processing", TL("Continue on broken input"));
204
205
oc.doRegister("poi-layer-offset", new Option_Float(0));
206
oc.addDescription("poi-layer-offset", "Processing", TL("Adds FLOAT to the layer value for each poi (i.e. to raise it above polygons)"));
207
208
oc.doRegister("flatten", new Option_Bool(false));
209
oc.addDescription("flatten", "Processing", TL("Remove all z-data"));
210
211
// building defaults options
212
oc.doRegister("color", new Option_String("0.2,0.5,1."));
213
oc.addDescription("color", "Building Defaults", TL("Sets STR as default color"));
214
215
oc.doRegister("prefix", new Option_String(""));
216
oc.addDescription("prefix", "Building Defaults", TL("Sets STR as default prefix"));
217
218
oc.doRegister("type", new Option_String("unknown"));
219
oc.addDescription("type", "Building Defaults", TL("Sets STR as default type"));
220
221
oc.doRegister("fill", new Option_Bool(true));
222
oc.addDescription("fill", "Building Defaults", TL("Fills polygons by default"));
223
224
oc.doRegister("icon", new Option_String(SUMOXMLDefinitions::POIIcons.getString(POIIcon::NONE)));
225
oc.addDescription("icon", "Building Defaults", TL("Sets STR as default icon"));
226
227
oc.doRegister("layer", new Option_Float(-1));
228
oc.addDescription("layer", "Building Defaults", TL("Sets FLOAT as default layer"));
229
230
oc.doRegister("discard", new Option_Bool(false));
231
oc.addDescription("discard", "Building Defaults", TL("Sets default action to discard"));
232
233
// projection
234
oc.doRegister("proj.plain-geo", new Option_Bool(false));
235
oc.addDescription("proj.plain-geo", "Projection", TL("Write geo coordinates in output"));
236
}
237
238
239
int
240
main(int argc, char** argv) {
241
OptionsCont& oc = OptionsCont::getOptions();
242
oc.setApplicationDescription(TL("Importer of polygons and POIs for the microscopic, multi-modal traffic simulation SUMO."));
243
oc.setApplicationName("polyconvert", "Eclipse SUMO polyconvert " VERSION_STRING);
244
int ret = 0;
245
try {
246
// initialise subsystems
247
XMLSubSys::init();
248
fillOptions();
249
OptionsIO::setArgs(argc, argv);
250
OptionsIO::getOptions();
251
if (oc.processMetaOptions(argc < 2)) {
252
SystemFrame::close();
253
return 0;
254
}
255
SystemFrame::checkOptions(oc);
256
XMLSubSys::setValidation(oc.getString("xml-validation"), oc.getString("xml-validation.net"), "never");
257
if (oc.isDefault("aggregate-warnings")) {
258
oc.setDefault("aggregate-warnings", "5");
259
}
260
MsgHandler::initOutputOptions();
261
// build the projection
262
double scale = 1.0;
263
if ((oc.isSet("dlr-navteq-poly-files") || oc.isSet("dlr-navteq-poi-files")) && oc.isDefault("proj.scale")) {
264
scale = 1e-5;
265
}
266
if (!oc.isSet("net")) {
267
// from the given options
268
#ifdef PROJ_API_FILE
269
const int numProjections = oc.getBool("simple-projection") + oc.getBool("proj.utm") + oc.getBool("proj.dhdn") + (oc.getString("proj").length() > 1);
270
if ((oc.isSet("osm-files")
271
|| oc.isSet("dlr-navteq-poly-files")
272
|| oc.isSet("dlr-navteq-poi-files")
273
|| oc.isSet("geojson-files")
274
|| oc.isSet("shapefile-prefixes"))
275
&& numProjections == 0) {
276
// input is lon,lat and projecting it to UTM ensures accurate handling of geometry
277
oc.set("proj.utm", "true");
278
if (oc.isDefault("proj.plain-geo")) {
279
// without reference to a network, raw UTM isn't helpful so we better write the data out as lon,lat
280
oc.set("proj.plain-geo", "true");
281
}
282
}
283
if (oc.isDefault("proj.scale")) {
284
oc.set("proj.scale", toString(scale, 5));
285
}
286
#endif
287
if (!GeoConvHelper::init(oc)) {
288
throw ProcessError(TL("Could not build projection!"));
289
}
290
} else {
291
// from the supplied network
292
// @todo warn about given options being ignored
293
PCNetProjectionLoader::load(oc.getString("net"), scale);
294
}
295
Boundary pruningBoundary = GeoConvHelper::getFinal().getConvBoundary();
296
// check whether the input shall be pruned
297
bool prune = false;
298
if (oc.getBool("prune.in-net")) {
299
if (!oc.isSet("net")) {
300
throw ProcessError(TL("In order to prune the input on the net, you have to supply a network."));
301
}
302
bool ok = true;
303
// !!! no proper error handling
304
Boundary offsets = GeomConvHelper::parseBoundaryReporting(
305
oc.getString("prune.in-net.offsets"), "--prune.on-net.offsets", nullptr, ok, true, true);
306
pruningBoundary.setOffsets(
307
pruningBoundary.xmin() - offsets.xmin(),
308
pruningBoundary.ymin() - offsets.ymin(),
309
pruningBoundary.xmax() + offsets.xmax(),
310
pruningBoundary.ymax() + offsets.ymax());
311
prune = true;
312
}
313
if (oc.isSet("prune.boundary")) {
314
bool ok = true;
315
// !!! no proper error handling
316
pruningBoundary = GeomConvHelper::parseBoundaryReporting(oc.getString("prune.boundary"), "--prune.boundary", nullptr, ok);
317
prune = true;
318
}
319
if (oc.isSet("osm-files") && oc.isDefault("poi-layer-offset")) {
320
oc.setDefault("poi-layer-offset", "5"); // sufficient when using the default typemap
321
}
322
323
PCPolyContainer toFill(prune, pruningBoundary, oc.getStringVector("remove"));
324
325
// read in the type defaults
326
if (!oc.isSet("type-file")) {
327
const char* sumoPath = std::getenv("SUMO_HOME");
328
if (sumoPath == nullptr) {
329
WRITE_WARNING(TL("Environment variable SUMO_HOME is not set, using built in type maps."));
330
} else {
331
const std::string path = sumoPath + std::string("/data/typemap/");
332
if (oc.isSet("dlr-navteq-poly-files")) {
333
oc.setDefault("type-file", path + "navteqPolyconvert.typ.xml");
334
}
335
if (oc.isSet("osm-files")) {
336
oc.setDefault("type-file", path + "osmPolyconvert.typ.xml");
337
}
338
if (oc.isSet("visum-files")) {
339
oc.setDefault("type-file", path + "visumPolyconvert.typ.xml");
340
}
341
}
342
}
343
PCTypeMap tm(oc);
344
PCTypeDefHandler handler(oc, tm);
345
if (oc.isSet("type-file")) {
346
if (!XMLSubSys::runParser(handler, oc.getString("type-file"))) {
347
// something failed
348
throw ProcessError();
349
}
350
} else {
351
handler.setFileName("built in type map");
352
SUMOSAXReader* reader = XMLSubSys::getSAXReader(handler);
353
if (oc.isSet("dlr-navteq-poly-files")) {
354
reader->parseString(navteqTypemap);
355
}
356
if (oc.isSet("osm-files")) {
357
reader->parseString(osmTypemap);
358
}
359
if (oc.isSet("visum-files")) {
360
reader->parseString(visumTypemap);
361
}
362
delete reader;
363
}
364
// read in the data
365
PCLoaderXML::loadIfSet(oc, toFill, tm); // SUMO-XML
366
PCLoaderOSM::loadIfSet(oc, toFill, tm); // OSM-XML
367
PCLoaderDlrNavteq::loadIfSet(oc, toFill, tm); // Elmar-files
368
PCLoaderVisum::loadIfSet(oc, toFill, tm); // VISUM
369
PCLoaderArcView::loadIfSet(oc, toFill, tm); // shape-files
370
GeoConvHelper::computeFinal();
371
// error processing
372
if (MsgHandler::getErrorInstance()->wasInformed() && !oc.getBool("ignore-errors")) {
373
throw ProcessError();
374
}
375
// output
376
if (!oc.isSet("output-file") && !oc.isSet("dlr-tdp-output")) {
377
std::string out = "polygons.xml";
378
if (oc.isSet("configuration-file")) {
379
out = FileHelpers::getConfigurationRelative(oc.getString("configuration-file"), out);
380
}
381
oc.setDefault("output-file", out);
382
}
383
if (oc.isSet("output-file")) {
384
toFill.save(oc.getString("output-file"), oc.getBool("proj.plain-geo"));
385
}
386
if (oc.isSet("dlr-tdp-output")) {
387
toFill.saveDlrTDP(oc.getString("dlr-tdp-output"));
388
}
389
390
} catch (const ProcessError& e) {
391
if (std::string(e.what()) != std::string("Process Error") && std::string(e.what()) != std::string("")) {
392
WRITE_ERROR(e.what());
393
}
394
MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
395
ret = 1;
396
#ifndef _DEBUG
397
} catch (const std::exception& e) {
398
if (std::string(e.what()) != std::string("")) {
399
WRITE_ERROR(e.what());
400
}
401
MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
402
ret = 1;
403
} catch (...) {
404
MsgHandler::getErrorInstance()->inform("Quitting (on unknown error).", false);
405
ret = 1;
406
#endif
407
}
408
SystemFrame::close();
409
// report about ending
410
if (ret == 0) {
411
std::cout << "Success." << std::endl;
412
}
413
return ret;
414
}
415
416
417
/****************************************************************************/
418
419