Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
PCLoaderVisum.cpp
Go to the documentation of this file.
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/****************************************************************************/
21// A reader of pois and polygons stored in VISUM-format
22/****************************************************************************/
23#include <config.h>
24
25#include <string>
26#include <map>
27#include <fstream>
40#include "PCLoaderVisum.h"
43#include <utils/geom/Boundary.h>
44#include <utils/geom/Position.h>
47
49 // duplicates NIImporter_VISUM::KEYS_DE due to lack of suitable common location
50 { "VSYS", VISUM_SYS },
51 { "STRECKENTYP", VISUM_LINKTYPE },
52 { "KNOTEN", VISUM_NODE },
53 { "BEZIRK", VISUM_DISTRICT },
54 { "PUNKT", VISUM_POINT },
55 { "STRECKE", VISUM_LINK },
56 { "V0IV", VISUM_V0 },
57 { "VSYSSET", VISUM_TYPES },
58 { "RANG", VISUM_RANK },
59 { "KAPIV", VISUM_CAPACITY },
60 { "XKOORD", VISUM_XCOORD },
61 { "YKOORD", VISUM_YCOORD },
62 { "ID", VISUM_ID },
63 { "CODE", VISUM_CODE },
64 { "VONKNOTNR", VISUM_FROMNODE },
65 { "NACHKNOTNR", VISUM_TONODE },
66 { "TYPNR", VISUM_TYPE },
67 { "TYP", VISUM_TYP },
68 { "ANBINDUNG", VISUM_DISTRICT_CONNECTION },
69 { "BEZNR", VISUM_SOURCE_DISTRICT },
70 { "KNOTNR", VISUM_FROMNODENO },
71 { "RICHTUNG", VISUM_DIRECTION },
72 { "FLAECHEID", VISUM_SURFACEID },
73 { "TFLAECHEID", VISUM_FACEID },
74 { "VONPUNKTID", VISUM_FROMPOINTID },
75 { "NACHPUNKTID", VISUM_TOPOINTID },
76 { "KANTE", VISUM_EDGE },
77 { "ABBIEGER", VISUM_TURN },
78 { "UEBERKNOTNR", VISUM_VIANODENO },
79 { "ANZFAHRSTREIFEN", VISUM_NUMLANES },
80 { "INDEX", VISUM_INDEX },
81 { "STRECKENPOLY", VISUM_LINKPOLY },
82 { "FLAECHENELEMENT", VISUM_SURFACEITEM },
83 { "TEILFLAECHENELEMENT", VISUM_FACEITEM },
84 { "KANTEID", VISUM_EDGEID },
85 { "Q", VISUM_ORIGIN },
86 { "Z", VISUM_DESTINATION },
87 { "KATNR", VISUM_CATID },
88 { "ZWISCHENPUNKT", VISUM_EDGEITEM },
89 { "POIKATEGORIE", VISUM_POICATEGORY },
90 { "NETZ", VISUM_NETWORK },
91 { "DEFKOORD", VISUM_PROJECTIONDEFINITION },
92 { "NR", VISUM_NO } // must be the last one
93};
94
95
97
98
99// ===========================================================================
100// method definitions
101// ===========================================================================
102void
104 PCTypeMap& tm) {
105 if (!oc.isSet("visum-files")) {
106 return;
107 }
108 const std::string languageFile = oc.getString("visum.language-file");
109 if (languageFile != "") {
110 loadLanguage(languageFile);
111 }
112 // parse file(s)
113 std::vector<std::string> files = oc.getStringVector("visum-files");
114 for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
115 if (!FileHelpers::isReadable(*file)) {
116 throw ProcessError(TLF("Could not open visum-file '%'.", *file));
117 }
118 PROGRESS_BEGIN_MESSAGE("Parsing from visum-file '" + *file + "'");
119 load(*file, oc, toFill, tm);
121 }
122}
123
124
125
126void
127PCLoaderVisum::load(const std::string& file, OptionsCont& oc, PCPolyContainer& toFill,
128 PCTypeMap& tm) {
130 std::string what;
131 std::map<long long int, Position> punkte;
132 std::map<long long int, PositionVector> kanten;
133 std::map<long long int, PositionVector> teilflaechen;
134 std::map<long long int, long long int> flaechenelemente;
135 NamedColumnsParser lineParser;
136 LineReader lr(file);
137 while (lr.hasMore()) {
138 std::string line = lr.readLine();
139 // reset if current is over
140 if (line.length() == 0 || line[0] == '*' || line[0] == '$') {
141 what = "";
142 }
143 // read items
144 if (what == "$" + KEYS.getString(VISUM_POINT)) {
145 lineParser.parseLine(line);
146 long long int id = StringUtils::toLong(lineParser.get(KEYS.getString(VISUM_ID)));
147 double x = StringUtils::toDouble(lineParser.get(KEYS.getString(VISUM_XCOORD)));
148 double y = StringUtils::toDouble(lineParser.get(KEYS.getString(VISUM_YCOORD)));
149 Position pos(x, y);
150 if (!geoConvHelper.x2cartesian(pos)) {
151 WRITE_WARNINGF(TL("Unable to project coordinates for point '%'."), toString(id));
152 }
153 punkte[id] = pos;
154 continue;
155 } else if (what == "$" + KEYS.getString(VISUM_EDGE)) {
156 lineParser.parseLine(line);
157 long long int id = StringUtils::toLong(lineParser.get(KEYS.getString(VISUM_ID)));
158 long long int fromID = StringUtils::toLong(lineParser.get(KEYS.getString(VISUM_FROMPOINTID)));
159 long long int toID = StringUtils::toLong(lineParser.get(KEYS.getString(VISUM_TOPOINTID)));
160 PositionVector vec;
161 vec.push_back(punkte[fromID]);
162 vec.push_back(punkte[toID]);
163 kanten[id] = vec;
164 continue;
165 } else if (what == "$" + KEYS.getString(VISUM_EDGEITEM)) {
166 lineParser.parseLine(line);
167 long long int id = StringUtils::toLong(lineParser.get(KEYS.getString(VISUM_EDGEID)));
168 int index = StringUtils::toInt(lineParser.get(KEYS.getString(VISUM_INDEX)));
169 double x = StringUtils::toDouble(lineParser.get(KEYS.getString(VISUM_XCOORD)));
170 double y = StringUtils::toDouble(lineParser.get(KEYS.getString(VISUM_YCOORD)));
171 Position pos(x, y);
172 if (!geoConvHelper.x2cartesian(pos)) {
173 WRITE_WARNINGF(TL("Unable to project coordinates for edge '%'."), toString(id));
174 }
175 kanten[id].insert(kanten[id].begin() + index, pos);
176 continue;
177 } else if (what == "$" + KEYS.getString(VISUM_FACEITEM)) {
178 lineParser.parseLine(line);
179 long long int id = StringUtils::toLong(lineParser.get(KEYS.getString(VISUM_FACEID)));
180 //int index = StringUtils::toInt(lineParser.get("INDEX"));
181 //index = 0; /// hmmmm - assume it's sorted...
182 long long int kid = StringUtils::toLong(lineParser.get(KEYS.getString(VISUM_EDGEID)));
183 int dir = StringUtils::toInt(lineParser.get(KEYS.getString(VISUM_DIRECTION)));
184 if (teilflaechen.find(id) == teilflaechen.end()) {
185 teilflaechen[id] = PositionVector();
186 }
187 if (dir == 0) {
188 for (int i = 0; i < (int) kanten[kid].size(); ++i) {
189 teilflaechen[id].push_back_noDoublePos(kanten[kid][i]);
190 }
191 } else {
192 for (int i = (int) kanten[kid].size() - 1; i >= 0; --i) {
193 teilflaechen[id].push_back_noDoublePos(kanten[kid][i]);
194 }
195 }
196 continue;
197 } else if (what == "$" + KEYS.getString(VISUM_SURFACEITEM)) {
198 lineParser.parseLine(line);
199 long long int id = StringUtils::toLong(lineParser.get(KEYS.getString(VISUM_SURFACEID)));
200 long long int tid = StringUtils::toLong(lineParser.get(KEYS.getString(VISUM_FACEID)));
201 flaechenelemente[id] = tid;
202 continue;
203 }
204 // set if read
205 if (line[0] == '$') {
206 what = "";
207 if (line.find("$" + KEYS.getString(VISUM_POINT) + ":") == 0) {
208 what = "$" + KEYS.getString(VISUM_POINT);
209 } else if (line.find("$" + KEYS.getString(VISUM_EDGE) + ":") == 0) {
210 what = "$" + KEYS.getString(VISUM_EDGE);
211 } else if (line.find("$" + KEYS.getString(VISUM_EDGEITEM) + ":") == 0) {
212 what = "$" + KEYS.getString(VISUM_EDGEITEM);
213 } else if (line.find("$" + KEYS.getString(VISUM_FACEITEM) + ":") == 0) {
214 what = "$" + KEYS.getString(VISUM_FACEITEM);
215 } else if (line.find("$" + KEYS.getString(VISUM_SURFACEITEM) + ":") == 0) {
216 what = "$" + KEYS.getString(VISUM_SURFACEITEM);
217 }
218 if (what != "") {
219 lineParser.reinit(line.substr(what.length() + 1));
220 }
221 }
222 }
223
224 // do some more sane job...
225 RGBColor c = RGBColor::parseColor(oc.getString("color"));
226 std::map<std::string, std::string> typemap;
227 // load the pois/polys
228 lr.reinit();
229 bool parsingCategories = false;
230 bool parsingPOIs = false;
231 bool parsingDistrictsDirectly = false;
232 PositionVector vec;
233 std::string polyType, lastID;
234 bool first = true;
235 while (lr.hasMore()) {
236 std::string line = lr.readLine();
237 // do not parse empty lines
238 if (line.length() == 0) {
239 continue;
240 }
241 // do not parse comment lines
242 if (line[0] == '*') {
243 continue;
244 }
245
246 if (line[0] == '$') {
247 // reset parsing on new entry type
248 parsingCategories = false;
249 parsingPOIs = false;
250 parsingDistrictsDirectly = false;
251 polyType = "";
252 }
253
254 if (parsingCategories) {
255 // parse the category
256 StringTokenizer st(line, ";");
257 std::string catid = st.next();
258 std::string catname = st.next();
259 typemap[catid] = catname;
260 }
261 if (parsingPOIs) {
262 // parse the poi
263 // $POI:Nr;CATID;CODE;NAME;Kommentar;XKoord;YKoord;
264 lineParser.parseLine(line);
265 long long int idL = StringUtils::toLong(lineParser.get(KEYS.getString(VISUM_NO)));
266 std::string id = toString(idL);
267 std::string catid = lineParser.get(KEYS.getString(VISUM_CATID));
268 // process read values
269 double x = StringUtils::toDouble(lineParser.get(KEYS.getString(VISUM_XCOORD)));
270 double y = StringUtils::toDouble(lineParser.get(KEYS.getString(VISUM_YCOORD)));
271 Position pos(x, y);
272 if (!geoConvHelper.x2cartesian(pos)) {
273 WRITE_WARNINGF(TL("Unable to project coordinates for POI '%'."), id);
274 }
275 std::string type = typemap[catid];
276 // patch the values
277 bool discard = oc.getBool("discard");
278 std::string icon = oc.getString("icon");
279 double layer = oc.getFloat("layer");
280 RGBColor color;
281 if (tm.has(type)) {
282 const PCTypeMap::TypeDef& def = tm.get(type);
283 id = def.prefix + id;
284 type = def.id;
285 color = def.color;
286 discard = def.discard;
287 icon = def.icon;
288 layer = def.layer;
289 } else {
290 id = oc.getString("prefix") + id;
291 color = c;
292 }
293 if (!discard) {
294 const std::string origId = id;
295 int index = 1;
296 while (toFill.getPOIs().get(id) != nullptr) {
297 id = origId + "#" + toString(index++);
298 }
299 PointOfInterest* poi = new PointOfInterest(id, type, color, pos, false, "", 0, false, 0, icon, layer);
300 toFill.add(poi);
301 }
302 }
303
304 // poly
305 if (polyType != "") {
306 StringTokenizer st(line, ";");
307 std::string id = st.next();
308 std::string type;
309 if (!first && lastID != id) {
310 // we have parsed a polygon completely
311 RGBColor color;
312 double layer = oc.getFloat("layer");
313 bool discard = oc.getBool("discard");
314 if (tm.has(polyType)) {
315 const PCTypeMap::TypeDef& def = tm.get(polyType);
316 id = def.prefix + id;
317 type = def.id;
318 color = def.color;
319 discard = def.discard;
320 layer = def.layer;
321 } else {
322 id = oc.getString("prefix") + id;
323 type = oc.getString("type");
324 color = c;
325 }
326 if (!discard) {
327 const std::string origId = id;
328 int index = 1;
329 while (toFill.getPolygons().get(id) != nullptr) {
330 id = origId + "#" + toString(index++);
331 }
332 SUMOPolygon* poly = new SUMOPolygon(id, type, color, vec, false, false, 1, layer);
333 toFill.add(poly);
334 }
335 vec.clear();
336 }
337 lastID = id;
338 first = false;
339 // parse current poly
340 std::string index = st.next();
341 std::string xpos = st.next();
342 std::string ypos = st.next();
343 Position pos2D((double) atof(xpos.c_str()), (double) atof(ypos.c_str()));
344 if (!geoConvHelper.x2cartesian(pos2D)) {
345 WRITE_WARNINGF(TL("Unable to project coordinates for polygon '%'."), id);
346 }
347 vec.push_back(pos2D);
348 }
349
350 // district refering a shape
351 if (parsingDistrictsDirectly) {
352 //$BEZIRK:NR CODE NAME TYPNR XKOORD YKOORD FLAECHEID BEZART IVANTEIL_Q IVANTEIL_Z OEVANTEIL METHODEANBANTEILE ZWERT1 ZWERT2 ZWERT3 ISTINAUSWAHL OBEZNR NOM_COM COD_COM
353 lineParser.parseLine(line);
354 long long int idL = StringUtils::toLong(lineParser.get(KEYS.getString(VISUM_NO)));
355 std::string id = toString(idL);
356 long long int area = StringUtils::toLong(lineParser.get(KEYS.getString(VISUM_SURFACEID)));
357 double x = StringUtils::toDouble(lineParser.get(KEYS.getString(VISUM_XCOORD)));
358 double y = StringUtils::toDouble(lineParser.get(KEYS.getString(VISUM_YCOORD)));
359 // patch the values
360 std::string type = "district";
361 bool discard = oc.getBool("discard");
362 std::string icon = oc.getString("icon");
363 double layer = oc.getFloat("layer");
364 RGBColor color;
365 if (tm.has(type)) {
366 const PCTypeMap::TypeDef& def = tm.get(type);
367 id = def.prefix + id;
368 type = def.id;
369 color = def.color;
370 discard = def.discard;
371 icon = def.icon;
372 layer = def.layer;
373 } else {
374 id = oc.getString("prefix") + id;
375 type = oc.getString("type");
376 color = c;
377 }
378 if (!discard) {
379 if (teilflaechen[flaechenelemente[area]].size() > 0) {
380 const std::string origId = id;
381 int index = 1;
382 while (toFill.getPolygons().get(id) != nullptr) {
383 id = origId + "#" + toString(index++);
384 }
385 const auto shape = teilflaechen[flaechenelemente[area]];
386 SUMOPolygon* poly = new SUMOPolygon(id, type, color, shape, false, false, 1, layer);
387 toFill.add(poly);
388 } else {
389 Position pos(x, y);
390 if (!geoConvHelper.x2cartesian(pos)) {
391 WRITE_WARNINGF(TL("Unable to project coordinates for POI '%'."), id);
392 }
393 const std::string origId = id;
394 int index = 1;
395 while (toFill.getPOIs().get(id) != nullptr) {
396 id = origId + "#" + toString(index++);
397 }
398 PointOfInterest* poi = new PointOfInterest(id, type, color, pos, false, "", 0, false, 0, icon, layer);
399 toFill.add(poi);
400 }
401 }
402 }
403
404
405 if (line.find("$POIKATEGORIEDEF:") == 0 || line.find("$" + KEYS.getString(VISUM_POICATEGORY) + ":") == 0) {
406 // ok, got categories, begin parsing from next line
407 parsingCategories = true;
408 lineParser.reinit(line.substr(line.find(":") + 1));
409 }
410 if ((line.find("$POI:") == 0) || line.find("$POIOFCAT") != std::string::npos) {
411 // ok, got pois, begin parsing from next line
412 parsingPOIs = true;
413 lineParser.reinit(line.substr(line.find(":") + 1));
414 }
415 if (line.find("$" + KEYS.getString(VISUM_DISTRICT)) == 0 && line.find(KEYS.getString(VISUM_SURFACEID)) != std::string::npos) {
416 // ok, have a district header, and it seems like districts would reference shapes...
417 parsingDistrictsDirectly = true;
418 lineParser.reinit(line.substr(line.find(":") + 1));
419 }
420
421
422 if (line.find("$BEZIRKPOLY") != std::string::npos) {
423 polyType = "district";
424 }
425 if (line.find("$GEBIETPOLY") != std::string::npos) {
426 polyType = "area";
427 }
428
429 }
430}
431
432
433void
434PCLoaderVisum::loadLanguage(const std::string& file) {
435 std::ifstream strm(file.c_str());
436 if (!strm.good()) {
437 throw ProcessError(TLF("Could not load VISUM language map from '%'.", file));
438 }
439 while (strm.good()) {
440 std::string keyDE;
441 std::string keyNew;
442 strm >> keyDE;
443 strm >> keyNew;
444 if (KEYS.hasString(keyDE)) {
445 VISUM_KEY key = KEYS.get(keyDE);
446 KEYS.remove(keyDE, key);
447 KEYS.insert(keyNew, key);
448 } else if (keyDE != "") {
449 // do not warn about network-related keys (NIImporter_VISUM)
450 //WRITE_WARNINGF(TL("Unknown entry '%' in VISUM language map"), keyDE);
451 }
452 }
453
454}
455
456/****************************************************************************/
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
#define TL(string)
Definition MsgHandler.h:304
#define PROGRESS_DONE_MESSAGE()
Definition MsgHandler.h:291
#define TLF(string,...)
Definition MsgHandler.h:306
#define PROGRESS_BEGIN_MESSAGE(msg)
Definition MsgHandler.h:290
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
static bool isReadable(std::string path)
Checks whether the given file is readable.
static methods for processing the coordinates conversion for the current net
bool x2cartesian(Position &from, bool includeInBoundary=true)
Converts the given coordinate into a cartesian and optionally update myConvBoundary.
static GeoConvHelper & getProcessing()
the coordinate transformation to use for input conversion and processing
Retrieves a file linewise and reports the lines to a handler.
Definition LineReader.h:48
bool readLine(LineHandler &lh)
Reads a single (the next) line from the file and reports it to the given LineHandler.
void reinit()
Reinitialises the reading (of the previous file)
bool hasMore() const
Returns whether another line may be read (the file was not read completely)
A parser to retrieve information from a table with known columns.
void reinit(const std::string &def, const std::string &defDelim=";", const std::string &lineDelim=";", bool chomp=false, bool ignoreCase=true)
Reinitialises the parser.
void parseLine(const std::string &line)
Parses the contents of the line.
std::string get(const std::string &name, bool prune=false) const
Returns the named information.
T get(const std::string &id) const
Retrieves an item.
A storage for options typed value containers)
Definition OptionsCont.h:89
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
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 StringBijection< VISUM_KEY >::Entry KEYS_DE[]
Strings for the keywords.
static void loadLanguage(const std::string &file)
static void load(const std::string &file, OptionsCont &oc, PCPolyContainer &toFill, PCTypeMap &tm)
Parses pois/polys stored within the given file.
static StringBijection< VISUM_KEY > KEYS
link directions
static void loadIfSet(OptionsCont &oc, PCPolyContainer &toFill, PCTypeMap &tm)
Loads pois/polygons assumed to be stored using VISUM-format.
A storage for loaded polygons and pois.
bool add(SUMOPolygon *poly, bool ignorePruning=false)
Adds a polygon to the storage.
A storage for type mappings.
Definition PCTypeMap.h:42
const TypeDef & get(const std::string &id)
Returns a type definition.
Definition PCTypeMap.cpp:70
bool has(const std::string &id)
Returns the information whether the named type is known.
Definition PCTypeMap.cpp:76
A point-of-interest.
A point in 2D or 3D with translation and scaling methods.
Definition Position.h:37
A list of positions.
static RGBColor parseColor(std::string coldef)
Parses a color information.
Definition RGBColor.cpp:239
const Polygons & getPolygons() const
Returns all polygons.
const POIs & getPOIs() const
Returns all pois.
const std::string & getString(const T key) const
get string
void remove(const std::string str, const T key)
remove string
bool hasString(const std::string &str) const
check if the given string exist
T get(const std::string &str) const
get key
void insert(const std::string str, const T key, bool checkDuplicates=true)
insert string and their associated key
std::string next()
returns the next substring when it exists. Otherwise the behaviour is undefined
static long long int toLong(const std::string &sData)
converts a string into the long value described by it by calling the char-type converter,...
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
static int toInt(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter,...
A single definition of values that shall be used for a given type.
Definition PCTypeMap.h:61
std::string icon
the icon to use
Definition PCTypeMap.h:69
bool discard
Information whether polygons of this type shall be discarded.
Definition PCTypeMap.h:77
std::string prefix
The prefix to use.
Definition PCTypeMap.h:67
double layer
The layer to use.
Definition PCTypeMap.h:71
std::string id
The new type id to use.
Definition PCTypeMap.h:63
RGBColor color
The color to use.
Definition PCTypeMap.h:65
bijection entry