Eclipse SUMO - Simulation of Urban MObility
PCLoaderVisum.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2020 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>
33 #include <utils/common/ToString.h>
36 #include <utils/options/Option.h>
38 #include <utils/common/StdDefs.h>
40 #include "PCLoaderVisum.h"
41 #include <utils/common/RGBColor.h>
42 #include <utils/geom/GeomHelper.h>
43 #include <utils/geom/Boundary.h>
44 #include <utils/geom/Position.h>
47 
48 
49 // ===========================================================================
50 // method definitions
51 // ===========================================================================
52 void
54  PCTypeMap& tm) {
55  if (!oc.isSet("visum-files")) {
56  return;
57  }
58  // parse file(s)
59  std::vector<std::string> files = oc.getStringVector("visum-files");
60  for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
61  if (!FileHelpers::isReadable(*file)) {
62  throw ProcessError("Could not open visum-file '" + *file + "'.");
63  }
64  PROGRESS_BEGIN_MESSAGE("Parsing from visum-file '" + *file + "'");
65  load(*file, oc, toFill, tm);
67  }
68 }
69 
70 
71 
72 void
73 PCLoaderVisum::load(const std::string& file, OptionsCont& oc, PCPolyContainer& toFill,
74  PCTypeMap& tm) {
76  std::string what;
77  std::map<long long int, Position> punkte;
78  std::map<long long int, PositionVector> kanten;
79  std::map<long long int, PositionVector> teilflaechen;
80  std::map<long long int, long long int> flaechenelemente;
81  NamedColumnsParser lineParser;
82  LineReader lr(file);
83  while (lr.hasMore()) {
84  std::string line = lr.readLine();
85  // reset if current is over
86  if (line.length() == 0 || line[0] == '*' || line[0] == '$') {
87  what = "";
88  }
89  // read items
90  if (what == "$PUNKT") {
91  lineParser.parseLine(line);
92  long long int id = StringUtils::toLong(lineParser.get("ID"));
93  double x = StringUtils::toDouble(lineParser.get("XKOORD"));
94  double y = StringUtils::toDouble(lineParser.get("YKOORD"));
95  Position pos(x, y);
96  if (!geoConvHelper.x2cartesian(pos)) {
97  WRITE_WARNING("Unable to project coordinates for point '" + toString(id) + "'.");
98  }
99  punkte[id] = pos;
100  continue;
101  } else if (what == "$KANTE") {
102  lineParser.parseLine(line);
103  long long int id = StringUtils::toLong(lineParser.get("ID"));
104  long long int fromID = StringUtils::toLong(lineParser.get("VONPUNKTID"));
105  long long int toID = StringUtils::toLong(lineParser.get("NACHPUNKTID"));
106  PositionVector vec;
107  vec.push_back(punkte[fromID]);
108  vec.push_back(punkte[toID]);
109  kanten[id] = vec;
110  continue;
111  } else if (what == "$ZWISCHENPUNKT") {
112  lineParser.parseLine(line);
113  long long int id = StringUtils::toLong(lineParser.get("KANTEID"));
114  int index = StringUtils::toInt(lineParser.get("INDEX"));
115  double x = StringUtils::toDouble(lineParser.get("XKOORD"));
116  double y = StringUtils::toDouble(lineParser.get("YKOORD"));
117  Position pos(x, y);
118  if (!geoConvHelper.x2cartesian(pos)) {
119  WRITE_WARNING("Unable to project coordinates for edge '" + toString(id) + "'.");
120  }
121  kanten[id].insert(kanten[id].begin() + index, pos);
122  continue;
123  } else if (what == "$TEILFLAECHENELEMENT") {
124  lineParser.parseLine(line);
125  long long int id = StringUtils::toLong(lineParser.get("TFLAECHEID"));
126  //int index = StringUtils::toInt(lineParser.get("INDEX"));
127  //index = 0; /// hmmmm - assume it's sorted...
128  long long int kid = StringUtils::toLong(lineParser.get("KANTEID"));
129  int dir = StringUtils::toInt(lineParser.get("RICHTUNG"));
130  if (teilflaechen.find(id) == teilflaechen.end()) {
131  teilflaechen[id] = PositionVector();
132  }
133  if (dir == 0) {
134  for (int i = 0; i < (int) kanten[kid].size(); ++i) {
135  teilflaechen[id].push_back_noDoublePos(kanten[kid][i]);
136  }
137  } else {
138  for (int i = (int) kanten[kid].size() - 1; i >= 0; --i) {
139  teilflaechen[id].push_back_noDoublePos(kanten[kid][i]);
140  }
141  }
142  continue;
143  } else if (what == "$FLAECHENELEMENT") {
144  lineParser.parseLine(line);
145  long long int id = StringUtils::toLong(lineParser.get("FLAECHEID"));
146  long long int tid = StringUtils::toLong(lineParser.get("TFLAECHEID"));
147  flaechenelemente[id] = tid;
148  continue;
149  }
150  // set if read
151  if (line[0] == '$') {
152  what = "";
153  if (line.find("$PUNKT") == 0) {
154  what = "$PUNKT";
155  } else if (line.find("$KANTE") == 0) {
156  what = "$KANTE";
157  } else if (line.find("$ZWISCHENPUNKT") == 0) {
158  what = "$ZWISCHENPUNKT";
159  } else if (line.find("$TEILFLAECHENELEMENT") == 0) {
160  what = "$TEILFLAECHENELEMENT";
161  } else if (line.find("$FLAECHENELEMENT") == 0) {
162  what = "$FLAECHENELEMENT";
163  }
164  if (what != "") {
165  lineParser.reinit(line.substr(what.length() + 1));
166  }
167  }
168  }
169 
170  // do some more sane job...
171  RGBColor c = RGBColor::parseColor(oc.getString("color"));
172  std::map<std::string, std::string> typemap;
173  // load the pois/polys
174  lr.reinit();
175  bool parsingCategories = false;
176  bool parsingPOIs = false;
177  bool parsingDistrictsDirectly = false;
178  PositionVector vec;
179  std::string polyType, lastID;
180  bool first = true;
181  while (lr.hasMore()) {
182  std::string line = lr.readLine();
183  // do not parse empty lines
184  if (line.length() == 0) {
185  continue;
186  }
187  // do not parse comment lines
188  if (line[0] == '*') {
189  continue;
190  }
191 
192  if (line[0] == '$') {
193  // reset parsing on new entry type
194  parsingCategories = false;
195  parsingPOIs = false;
196  parsingDistrictsDirectly = false;
197  polyType = "";
198  }
199 
200  if (parsingCategories) {
201  // parse the category
202  StringTokenizer st(line, ";");
203  std::string catid = st.next();
204  std::string catname = st.next();
205  typemap[catid] = catname;
206  }
207  if (parsingPOIs) {
208  // parse the poi
209  // $POI:Nr;CATID;CODE;NAME;Kommentar;XKoord;YKoord;
210  lineParser.parseLine(line);
211  long long int idL = StringUtils::toLong(lineParser.get("Nr"));
212  std::string id = toString(idL);
213  std::string catid = lineParser.get("CATID");
214  // process read values
215  double x = StringUtils::toDouble(lineParser.get("XKoord"));
216  double y = StringUtils::toDouble(lineParser.get("YKoord"));
217  Position pos(x, y);
218  if (!geoConvHelper.x2cartesian(pos)) {
219  WRITE_WARNING("Unable to project coordinates for POI '" + id + "'.");
220  }
221  std::string type = typemap[catid];
222  // patch the values
223  bool discard = oc.getBool("discard");
224  double layer = oc.getFloat("layer");
225  RGBColor color;
226  if (tm.has(type)) {
227  const PCTypeMap::TypeDef& def = tm.get(type);
228  id = def.prefix + id;
229  type = def.id;
230  color = def.color;
231  discard = def.discard;
232  layer = def.layer;
233  } else {
234  id = oc.getString("prefix") + id;
235  type = oc.getString("type");
236  color = c;
237  }
238  if (!discard) {
239  PointOfInterest* poi = new PointOfInterest(id, type, color, pos, false, "", 0, 0, layer);
240  toFill.add(poi);
241  }
242  }
243 
244  // poly
245  if (polyType != "") {
246  StringTokenizer st(line, ";");
247  std::string id = st.next();
248  std::string type;
249  if (!first && lastID != id) {
250  // we have parsed a polygon completely
251  RGBColor color;
252  double layer = oc.getFloat("layer");
253  bool discard = oc.getBool("discard");
254  if (tm.has(polyType)) {
255  const PCTypeMap::TypeDef& def = tm.get(polyType);
256  id = def.prefix + id;
257  type = def.id;
258  color = def.color;
259  discard = def.discard;
260  layer = def.layer;
261  } else {
262  id = oc.getString("prefix") + id;
263  type = oc.getString("type");
264  color = c;
265  }
266  if (!discard) {
267  SUMOPolygon* poly = new SUMOPolygon(id, type, color, vec, false, false, 1, layer);
268  toFill.add(poly);
269  }
270  vec.clear();
271  }
272  lastID = id;
273  first = false;
274  // parse current poly
275  std::string index = st.next();
276  std::string xpos = st.next();
277  std::string ypos = st.next();
278  Position pos2D((double) atof(xpos.c_str()), (double) atof(ypos.c_str()));
279  if (!geoConvHelper.x2cartesian(pos2D)) {
280  WRITE_WARNING("Unable to project coordinates for polygon '" + id + "'.");
281  }
282  vec.push_back(pos2D);
283  }
284 
285  // district refering a shape
286  if (parsingDistrictsDirectly) {
287  //$BEZIRK:NR CODE NAME TYPNR XKOORD YKOORD FLAECHEID BEZART IVANTEIL_Q IVANTEIL_Z OEVANTEIL METHODEANBANTEILE ZWERT1 ZWERT2 ZWERT3 ISTINAUSWAHL OBEZNR NOM_COM COD_COM
288  lineParser.parseLine(line);
289  long long int idL = StringUtils::toLong(lineParser.get("NR"));
290  std::string id = toString(idL);
291  long long int area = StringUtils::toLong(lineParser.get("FLAECHEID"));
292  double x = StringUtils::toDouble(lineParser.get("XKOORD"));
293  double y = StringUtils::toDouble(lineParser.get("YKOORD"));
294  // patch the values
295  std::string type = "district";
296  bool discard = oc.getBool("discard");
297  double layer = oc.getFloat("layer");
298  RGBColor color;
299  if (tm.has(type)) {
300  const PCTypeMap::TypeDef& def = tm.get(type);
301  id = def.prefix + id;
302  type = def.id;
303  color = def.color;
304  discard = def.discard;
305  layer = def.layer;
306  } else {
307  id = oc.getString("prefix") + id;
308  type = oc.getString("type");
309  color = c;
310  }
311  if (!discard) {
312  if (teilflaechen[flaechenelemente[area]].size() > 0) {
313  SUMOPolygon* poly = new SUMOPolygon(id, type, color, teilflaechen[flaechenelemente[area]], false, false, 1, layer);
314  toFill.add(poly);
315  } else {
316  Position pos(x, y);
317  if (!geoConvHelper.x2cartesian(pos)) {
318  WRITE_WARNING("Unable to project coordinates for POI '" + id + "'.");
319  }
320  PointOfInterest* poi = new PointOfInterest(id, type, color, pos, "", nullptr, 0, layer);
321  toFill.add(poi);
322  }
323  }
324  }
325 
326 
327  if (line.find("$POIKATEGORIEDEF:") == 0 || line.find("$POIKATEGORIE:") == 0) {
328  // ok, got categories, begin parsing from next line
329  parsingCategories = true;
330  lineParser.reinit(line.substr(line.find(":") + 1));
331  }
332  if (line.find("$POI:") == 0) {
333  // ok, got pois, begin parsing from next line
334  parsingPOIs = true;
335  lineParser.reinit(line.substr(line.find(":") + 1));
336  }
337  if (line.find("$BEZIRK") == 0 && line.find("FLAECHEID") != std::string::npos) {
338  // ok, have a district header, and it seems like districts would reference shapes...
339  parsingDistrictsDirectly = true;
340  lineParser.reinit(line.substr(line.find(":") + 1));
341  }
342 
343 
344  if (line.find("$BEZIRKPOLY") != std::string::npos) {
345  polyType = "district";
346  }
347  if (line.find("$GEBIETPOLY") != std::string::npos) {
348  polyType = "area";
349  }
350 
351  }
352 }
353 
354 
355 /****************************************************************************/
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:276
#define PROGRESS_DONE_MESSAGE()
Definition: MsgHandler.h:280
#define PROGRESS_BEGIN_MESSAGE(msg)
Definition: MsgHandler.h:279
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:44
static bool isReadable(std::string path)
Checks whether the given file is readable.
Definition: FileHelpers.cpp:48
static methods for processing the coordinates conversion for the current net
Definition: GeoConvHelper.h:53
static GeoConvHelper & getProcessing()
the coordinate transformation to use for input conversion and processing
Definition: GeoConvHelper.h:84
bool x2cartesian(Position &from, bool includeInBoundary=true)
Converts the given coordinate into a cartesian and optionally update myConvBoundary.
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.
Definition: LineReader.cpp:67
void reinit()
Reinitialises the reading (of the previous file)
Definition: LineReader.cpp:193
bool hasMore() const
Returns whether another line may be read (the file was not read completely)
Definition: LineReader.cpp:51
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.
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 void load(const std::string &file, OptionsCont &oc, PCPolyContainer &toFill, PCTypeMap &tm)
Parses pois/polys stored within the given file.
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:69
bool has(const std::string &id)
Returns the information whether the named type is known.
Definition: PCTypeMap.cpp:75
A point-of-interest.
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:36
A list of positions.
static RGBColor parseColor(std::string coldef)
Parses a color information.
Definition: RGBColor.cpp:168
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:56
bool discard
Information whether polygons of this type shall be discarded.
Definition: PCTypeMap.h:70
std::string prefix
The prefix to use.
Definition: PCTypeMap.h:62
double layer
The layer to use.
Definition: PCTypeMap.h:64
std::string id
The new type id to use.
Definition: PCTypeMap.h:58
RGBColor color
The color to use.
Definition: PCTypeMap.h:60