Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
polyconvert_main.cpp
Go to the documentation of this file.
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/****************************************************************************/
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>
44#include <utils/geom/Boundary.h>
46#include <utils/xml/XMLSubSys.h>
55#include <polyconvert/pc_typemap.h>
56
57
58// ===========================================================================
59// method definitions
60// ===========================================================================
61void
64 oc.addCallExample("-c <CONFIGURATION>", TL("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");
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
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
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
239int
240main(int argc, char** argv) {
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
248 fillOptions();
249 OptionsIO::setArgs(argc, argv);
251 if (oc.processMetaOptions(argc < 2)) {
253 return 0;
254 }
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 }
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 }
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
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
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 }
409 // report about ending
410 if (ret == 0) {
411 std::cout << "Success." << std::endl;
412 }
413 return ret;
414}
415
416
417/****************************************************************************/
#define WRITE_ERROR(msg)
Definition MsgHandler.h:295
#define WRITE_WARNING(msg)
Definition MsgHandler.h:286
#define TL(string)
Definition MsgHandler.h:304
std::vector< std::string > StringVector
Definition of a vector of strings.
Definition Option.h:42
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
A class that stores a 2D geometrical boundary.
Definition Boundary.h:39
double ymin() const
Returns minimum y-coordinate.
Definition Boundary.cpp:127
double xmin() const
Returns minimum x-coordinate.
Definition Boundary.cpp:115
void setOffsets(double xmin, double ymin, double xmax, double ymax)
Sets the boundary to the given values, ignoring min < max constraints.
Definition Boundary.cpp:424
double ymax() const
Returns maximum y-coordinate.
Definition Boundary.cpp:133
double xmax() const
Returns maximum x-coordinate.
Definition Boundary.cpp:121
static std::string getConfigurationRelative(const std::string &configPath, const std::string &path)
Returns the second path as a relative path to the first file.
void setFileName(const std::string &name)
Sets the current file name.
static void addProjectionOptions(OptionsCont &oc)
Adds projection options to the given container.
static const GeoConvHelper & getFinal()
the coordinate transformation for writing the location element and for tracking the original coordina...
static bool init(OptionsCont &oc)
Initialises the processing and the final instance using the given options.
static void computeFinal(bool lefthand=false)
compute the location attributes which will be used for output based on the loaded location data,...
const Boundary & getConvBoundary() const
Returns the converted boundary.
static Boundary parseBoundaryReporting(const std::string &def, const std::string &objecttype, const char *objectid, bool &ok, bool report=true, bool offsets=false)
Builds a boundary from its string representation, reporting occurred errors.
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
virtual void inform(std::string msg, bool addType=true)
adds a new error to the list
static void initOutputOptions()
init output options
A storage for options typed value containers)
Definition OptionsCont.h:89
void addDescription(const std::string &name, const std::string &subtopic, const std::string &description)
Adds a description for an option.
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
void setApplicationName(const std::string &appName, const std::string &fullName)
Sets the application name.
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
void addSynonyme(const std::string &name1, const std::string &name2, bool isDeprecated=false)
Adds a synonyme for an options name (any order)
bool isDefault(const std::string &name) const
Returns the information whether the named option has still the default value.
bool setDefault(const std::string &name, const std::string &value)
Sets the given value for the named option as new default value.
void doRegister(const std::string &name, Option *o)
Adds an option under the given name.
void setApplicationDescription(const std::string &appDesc)
Sets the application description.
bool set(const std::string &name, const std::string &value, const bool append=false)
Sets the given value for the named option.
void addOptionSubTopic(const std::string &topic)
Adds an option subtopic.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
const StringVector & getStringVector(const std::string &name) const
Returns the list of string-value of the named option (only for Option_StringVector)
static OptionsCont & getOptions()
Retrieves the options.
bool processMetaOptions(bool missingOptions)
Checks for help and configuration output, returns whether we should exit.
void addCallExample(const std::string &example, const std::string &desc)
Add a call example.
static void setArgs(int argc, char **argv)
Stores the command line arguments for later parsing.
Definition OptionsIO.cpp:58
static void getOptions(const bool commandLineOnly=false)
Parses the command line arguments and loads the configuration.
Definition OptionsIO.cpp:74
static void loadIfSet(OptionsCont &oc, PCPolyContainer &toFill, PCTypeMap &tm)
Loads pois/polygons assumed to be stored as shape files-files.
static void loadIfSet(OptionsCont &oc, PCPolyContainer &toFill, PCTypeMap &tm)
Loads pois/polygons assumed to be stored as according DLR-Navteq (Elmar)-files.
static void loadIfSet(OptionsCont &oc, PCPolyContainer &toFill, PCTypeMap &tm)
Loads pois/polygons assumed to be stored as OSM-XML.
static void loadIfSet(OptionsCont &oc, PCPolyContainer &toFill, PCTypeMap &tm)
Loads pois/polygons assumed to be stored using VISUM-format.
static void loadIfSet(OptionsCont &oc, PCPolyContainer &toFill, PCTypeMap &tm)
Loads pois/polygons assumed to be stored as XML.
static void load(const std::string &file, double scale)
Loads network projection if wished.
A storage for loaded polygons and pois.
void save(const std::string &file, bool useGeo)
Saves the stored polygons and pois into the given file.
void saveDlrTDP(const std::string &prefix)
Saves the stored polygons and pois into the given file in dlrTDP format.
A handler for loading polygon type maps.
A storage for type mappings.
Definition PCTypeMap.h:42
SAX-reader encapsulation containing binary reader.
void parseString(std::string content)
Parse XML from the given string.
static StringBijection< POIIcon > POIIcons
POI icon values.
static void close()
Closes all of an applications subsystems.
static bool checkOptions(OptionsCont &oc)
checks shared options and sets StdDefs
static void addConfigurationOptions(OptionsCont &oc)
Adds configuration options to the given container.
static void addReportOptions(OptionsCont &oc)
Adds reporting options to the given container.
static void setValidation(const std::string &validationScheme, const std::string &netValidationScheme, const std::string &routeValidationScheme)
Enables or disables validation.
Definition XMLSubSys.cpp:83
static SUMOSAXReader * getSAXReader(SUMOSAXHandler &handler, const bool isNet=false, const bool isRoute=false)
Builds a reader and assigns the handler to it.
static void init()
Initialises the xml-subsystem.
Definition XMLSubSys.cpp:56
static bool runParser(GenericSAXHandler &handler, const std::string &file, const bool isNet=false, const bool isRoute=false, const bool isExternal=false, const bool catchExceptions=true)
Runs the given handler on the given file; returns if everything's ok.
void fillOptions()
int main(int argc, char **argv)