SUMO - Simulation of Urban MObility
PCLoaderVisum.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // A reader of pois and polygons stored in VISUM-format
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
13 // Copyright (C) 2001-2017 DLR (http://www.dlr.de/) and contributors
14 /****************************************************************************/
15 //
16 // This file is part of SUMO.
17 // SUMO is free software: you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation, either version 3 of the License, or
20 // (at your option) any later version.
21 //
22 /****************************************************************************/
23 
24 
25 // ===========================================================================
26 // included modules
27 // ===========================================================================
28 #ifdef _MSC_VER
29 #include <windows_config.h>
30 #else
31 #include <config.h>
32 #endif
33 
34 #include <string>
35 #include <map>
36 #include <fstream>
42 #include <utils/common/ToString.h>
45 #include <utils/options/Option.h>
47 #include <utils/common/StdDefs.h>
49 #include "PCLoaderVisum.h"
50 #include <utils/common/RGBColor.h>
51 #include <utils/geom/GeomHelper.h>
52 #include <utils/geom/Boundary.h>
53 #include <utils/geom/Position.h>
56 
57 
58 // ===========================================================================
59 // method definitions
60 // ===========================================================================
61 void
63  PCTypeMap& tm) {
64  if (!oc.isSet("visum-files")) {
65  return;
66  }
67  // parse file(s)
68  std::vector<std::string> files = oc.getStringVector("visum-files");
69  for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
70  if (!FileHelpers::isReadable(*file)) {
71  throw ProcessError("Could not open visum-file '" + *file + "'.");
72  }
73  PROGRESS_BEGIN_MESSAGE("Parsing from visum-file '" + *file + "'");
74  load(*file, oc, toFill, tm);
76  }
77 }
78 
79 
80 
81 void
82 PCLoaderVisum::load(const std::string& file, OptionsCont& oc, PCPolyContainer& toFill,
83  PCTypeMap& tm) {
85  std::string what;
86  std::map<long long int, Position> punkte;
87  std::map<long long int, PositionVector> kanten;
88  std::map<long long int, PositionVector> teilflaechen;
89  std::map<long long int, long long int> flaechenelemente;
90  NamedColumnsParser lineParser;
91  LineReader lr(file);
92  while (lr.hasMore()) {
93  std::string line = lr.readLine();
94  // reset if current is over
95  if (line.length() == 0 || line[0] == '*' || line[0] == '$') {
96  what = "";
97  }
98  // read items
99  if (what == "$PUNKT") {
100  lineParser.parseLine(line);
101  long long int id = TplConvert::_2long(lineParser.get("ID").c_str());
102  double x = TplConvert::_2double(lineParser.get("XKOORD").c_str());
103  double y = TplConvert::_2double(lineParser.get("YKOORD").c_str());
104  Position pos(x, y);
105  if (!geoConvHelper.x2cartesian(pos)) {
106  WRITE_WARNING("Unable to project coordinates for point '" + toString(id) + "'.");
107  }
108  punkte[id] = pos;
109  continue;
110  } else if (what == "$KANTE") {
111  lineParser.parseLine(line);
112  long long int id = TplConvert::_2long(lineParser.get("ID").c_str());
113  long long int fromID = TplConvert::_2long(lineParser.get("VONPUNKTID").c_str());
114  long long int toID = TplConvert::_2long(lineParser.get("NACHPUNKTID").c_str());
115  PositionVector vec;
116  vec.push_back(punkte[fromID]);
117  vec.push_back(punkte[toID]);
118  kanten[id] = vec;
119  continue;
120  } else if (what == "$ZWISCHENPUNKT") {
121  lineParser.parseLine(line);
122  long long int id = TplConvert::_2long(lineParser.get("KANTEID").c_str());
123  int index = TplConvert::_2int(lineParser.get("INDEX").c_str());
124  double x = TplConvert::_2double(lineParser.get("XKOORD").c_str());
125  double y = TplConvert::_2double(lineParser.get("YKOORD").c_str());
126  Position pos(x, y);
127  if (!geoConvHelper.x2cartesian(pos)) {
128  WRITE_WARNING("Unable to project coordinates for edge '" + toString(id) + "'.");
129  }
130  kanten[id].insert(kanten[id].begin() + index, pos);
131  continue;
132  } else if (what == "$TEILFLAECHENELEMENT") {
133  lineParser.parseLine(line);
134  long long int id = TplConvert::_2long(lineParser.get("TFLAECHEID").c_str());
135  //int index = TplConvert::_2int(lineParser.get("INDEX").c_str());
136  //index = 0; /// hmmmm - assume it's sorted...
137  long long int kid = TplConvert::_2long(lineParser.get("KANTEID").c_str());
138  int dir = TplConvert::_2int(lineParser.get("RICHTUNG").c_str());
139  if (teilflaechen.find(id) == teilflaechen.end()) {
140  teilflaechen[id] = PositionVector();
141  }
142  if (dir == 0) {
143  for (int i = 0; i < (int) kanten[kid].size(); ++i) {
144  teilflaechen[id].push_back_noDoublePos(kanten[kid][i]);
145  }
146  } else {
147  for (int i = (int) kanten[kid].size() - 1; i >= 0; --i) {
148  teilflaechen[id].push_back_noDoublePos(kanten[kid][i]);
149  }
150  }
151  continue;
152  } else if (what == "$FLAECHENELEMENT") {
153  lineParser.parseLine(line);
154  long long int id = TplConvert::_2long(lineParser.get("FLAECHEID").c_str());
155  long long int tid = TplConvert::_2long(lineParser.get("TFLAECHEID").c_str());
156  flaechenelemente[id] = tid;
157  continue;
158  }
159  // set if read
160  if (line[0] == '$') {
161  what = "";
162  if (line.find("$PUNKT") == 0) {
163  what = "$PUNKT";
164  } else if (line.find("$KANTE") == 0) {
165  what = "$KANTE";
166  } else if (line.find("$ZWISCHENPUNKT") == 0) {
167  what = "$ZWISCHENPUNKT";
168  } else if (line.find("$TEILFLAECHENELEMENT") == 0) {
169  what = "$TEILFLAECHENELEMENT";
170  } else if (line.find("$FLAECHENELEMENT") == 0) {
171  what = "$FLAECHENELEMENT";
172  }
173  if (what != "") {
174  lineParser.reinit(line.substr(what.length() + 1));
175  }
176  }
177  }
178 
179  // do some more sane job...
180  RGBColor c = RGBColor::parseColor(oc.getString("color"));
181  std::map<std::string, std::string> typemap;
182  // load the pois/polys
183  lr.reinit();
184  bool parsingCategories = false;
185  bool parsingPOIs = false;
186  bool parsingDistrictsDirectly = false;
187  PositionVector vec;
188  std::string polyType, lastID;
189  bool first = true;
190  while (lr.hasMore()) {
191  std::string line = lr.readLine();
192  // do not parse empty lines
193  if (line.length() == 0) {
194  continue;
195  }
196  // do not parse comment lines
197  if (line[0] == '*') {
198  continue;
199  }
200 
201  if (line[0] == '$') {
202  // reset parsing on new entry type
203  parsingCategories = false;
204  parsingPOIs = false;
205  parsingDistrictsDirectly = false;
206  polyType = "";
207  }
208 
209  if (parsingCategories) {
210  // parse the category
211  StringTokenizer st(line, ";");
212  std::string catid = st.next();
213  std::string catname = st.next();
214  typemap[catid] = catname;
215  }
216  if (parsingPOIs) {
217  // parse the poi
218  // $POI:Nr;CATID;CODE;NAME;Kommentar;XKoord;YKoord;
219  lineParser.parseLine(line);
220  long long int idL = TplConvert::_2long(lineParser.get("Nr").c_str());
221  std::string id = toString(idL);
222  std::string catid = lineParser.get("CATID");
223  // process read values
224  double x = TplConvert::_2double(lineParser.get("XKoord").c_str());
225  double y = TplConvert::_2double(lineParser.get("YKoord").c_str());
226  Position pos(x, y);
227  if (!geoConvHelper.x2cartesian(pos)) {
228  WRITE_WARNING("Unable to project coordinates for POI '" + id + "'.");
229  }
230  std::string type = typemap[catid];
231  // patch the values
232  bool discard = oc.getBool("discard");
233  double layer = oc.getFloat("layer");
234  RGBColor color;
235  if (tm.has(type)) {
236  const PCTypeMap::TypeDef& def = tm.get(type);
237  id = def.prefix + id;
238  type = def.id;
239  color = def.color;
240  discard = def.discard;
241  layer = def.layer;
242  } else {
243  id = oc.getString("prefix") + id;
244  type = oc.getString("type");
245  color = c;
246  }
247  if (!discard) {
248  PointOfInterest* poi = new PointOfInterest(id, type, color, pos, layer);
249  toFill.add(poi);
250  }
251  }
252 
253  // poly
254  if (polyType != "") {
255  StringTokenizer st(line, ";");
256  std::string id = st.next();
257  std::string type;
258  if (!first && lastID != id) {
259  // we have parsed a polygon completely
260  RGBColor color;
261  double layer = oc.getFloat("layer");
262  bool discard = oc.getBool("discard");
263  if (tm.has(polyType)) {
264  const PCTypeMap::TypeDef& def = tm.get(polyType);
265  id = def.prefix + id;
266  type = def.id;
267  color = def.color;
268  discard = def.discard;
269  layer = def.layer;
270  } else {
271  id = oc.getString("prefix") + id;
272  type = oc.getString("type");
273  color = c;
274  }
275  if (!discard) {
276  SUMO::Polygon* poly = new SUMO::Polygon(id, type, color, vec, false, layer);
277  toFill.add(poly);
278  }
279  vec.clear();
280  }
281  lastID = id;
282  first = false;
283  // parse current poly
284  std::string index = st.next();
285  std::string xpos = st.next();
286  std::string ypos = st.next();
287  Position pos2D((double) atof(xpos.c_str()), (double) atof(ypos.c_str()));
288  if (!geoConvHelper.x2cartesian(pos2D)) {
289  WRITE_WARNING("Unable to project coordinates for polygon '" + id + "'.");
290  }
291  vec.push_back(pos2D);
292  }
293 
294  // district refering a shape
295  if (parsingDistrictsDirectly) {
296  //$BEZIRK:NR CODE NAME TYPNR XKOORD YKOORD FLAECHEID BEZART IVANTEIL_Q IVANTEIL_Z OEVANTEIL METHODEANBANTEILE ZWERT1 ZWERT2 ZWERT3 ISTINAUSWAHL OBEZNR NOM_COM COD_COM
297  lineParser.parseLine(line);
298  long long int idL = TplConvert::_2long(lineParser.get("NR").c_str());
299  std::string id = toString(idL);
300  long long int area = TplConvert::_2long(lineParser.get("FLAECHEID").c_str());
301  double x = TplConvert::_2double(lineParser.get("XKOORD").c_str());
302  double y = TplConvert::_2double(lineParser.get("YKOORD").c_str());
303  // patch the values
304  std::string type = "district";
305  bool discard = oc.getBool("discard");
306  double layer = oc.getFloat("layer");
307  RGBColor color;
308  if (tm.has(type)) {
309  const PCTypeMap::TypeDef& def = tm.get(type);
310  id = def.prefix + id;
311  type = def.id;
312  color = def.color;
313  discard = def.discard;
314  layer = def.layer;
315  } else {
316  id = oc.getString("prefix") + id;
317  type = oc.getString("type");
318  color = c;
319  }
320  if (!discard) {
321  if (teilflaechen[flaechenelemente[area]].size() > 0) {
322  SUMO::Polygon* poly = new SUMO::Polygon(id, type, color, teilflaechen[flaechenelemente[area]], false, layer);
323  toFill.add(poly);
324  } else {
325  Position pos(x, y);
326  if (!geoConvHelper.x2cartesian(pos)) {
327  WRITE_WARNING("Unable to project coordinates for POI '" + id + "'.");
328  }
329  PointOfInterest* poi = new PointOfInterest(id, type, color, pos, layer);
330  toFill.add(poi);
331  }
332  }
333  }
334 
335 
336  if (line.find("$POIKATEGORIEDEF:") == 0 || line.find("$POIKATEGORIE:") == 0) {
337  // ok, got categories, begin parsing from next line
338  parsingCategories = true;
339  lineParser.reinit(line.substr(line.find(":") + 1));
340  }
341  if (line.find("$POI:") == 0) {
342  // ok, got pois, begin parsing from next line
343  parsingPOIs = true;
344  lineParser.reinit(line.substr(line.find(":") + 1));
345  }
346  if (line.find("$BEZIRK") == 0 && line.find("FLAECHEID") != std::string::npos) {
347  // ok, have a district header, and it seems like districts would reference shapes...
348  parsingDistrictsDirectly = true;
349  lineParser.reinit(line.substr(line.find(":") + 1));
350  }
351 
352 
353  if (line.find("$BEZIRKPOLY") != std::string::npos) {
354  polyType = "district";
355  }
356  if (line.find("$GEBIETPOLY") != std::string::npos) {
357  polyType = "area";
358  }
359 
360  }
361 }
362 
363 
364 
365 /****************************************************************************/
366 
std::string id
The new type id to use.
Definition: PCTypeMap.h:68
static RGBColor parseColor(std::string coldef)
Parses a color information.
Definition: RGBColor.cpp:168
A single definition of values that shall be used for a given type.
Definition: PCTypeMap.h:66
std::string next()
static bool isReadable(std::string path)
Checks whether the given file is readable.
Definition: FileHelpers.cpp:54
bool readLine(LineHandler &lh)
Reads a single (the next) line from the file and reports it to the given LineHandler.
Definition: LineReader.cpp:76
Retrieves a file linewise and reports the lines to a handler.
Definition: LineReader.h:58
static GeoConvHelper & getProcessing()
the coordinate transformation to use for input conversion and processing
Definition: GeoConvHelper.h:98
bool x2cartesian(Position &from, bool includeInBoundary=true)
static void load(const std::string &file, OptionsCont &oc, PCPolyContainer &toFill, PCTypeMap &tm)
Parses pois/polys stored within the given file.
double layer
The layer to use.
Definition: PCTypeMap.h:74
static long long int _2long(const E *const data)
converts a char-type array into the long value described by it
Definition: TplConvert.h:200
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
std::string get(const std::string &name, bool prune=false) const
Returns the named information.
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
bool discard
Information whether polygons of this type shall be discarded.
Definition: PCTypeMap.h:76
A storage for loaded polygons and pois.
RGBColor color
The color to use.
Definition: PCTypeMap.h:70
A 2D- or 3D-polygon.
Definition: Polygon.h:57
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
void reinit(const std::string &def, const std::string &defDelim=";", const std::string &lineDelim=";", bool chomp=false, bool ignoreCase=true)
Reinitialises the parser.
A storage for type mappings.
Definition: PCTypeMap.h:52
const TypeDef & get(const std::string &id)
Returns a type definition.
Definition: PCTypeMap.cpp:75
static methods for processing the coordinates conversion for the current net
Definition: GeoConvHelper.h:60
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:56
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:46
A list of positions.
static void loadIfSet(OptionsCont &oc, PCPolyContainer &toFill, PCTypeMap &tm)
Loads pois/polygons assumed to be stored using VISUM-format.
bool has(const std::string &id)
Returns the information whether the named type is known.
Definition: PCTypeMap.cpp:81
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
std::vector< std::string > getStringVector(const std::string &name) const
Returns the list of string-vector-value of the named option (only for Option_String) ...
#define PROGRESS_BEGIN_MESSAGE(msg)
Definition: MsgHandler.h:202
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
bool add(SUMO::Polygon *poly, bool ignorePruning=false)
Adds a polygon to the storage.
static int _2int(const E *const data)
converts a char-type array into the integer value described by it
Definition: TplConvert.h:149
std::string prefix
The prefix to use.
Definition: PCTypeMap.h:72
bool hasMore() const
Returns whether another line may be read (the file was not read completely)
Definition: LineReader.cpp:60
A storage for options typed value containers)
Definition: OptionsCont.h:99
static double _2double(const E *const data)
converts a char-type array into the double value described by it
Definition: TplConvert.h:297
void reinit()
Reinitialises the reading (of the previous file)
Definition: LineReader.cpp:199
A parser to retrieve information from a table with known columns.
A point-of-interest.
#define PROGRESS_DONE_MESSAGE()
Definition: MsgHandler.h:203
void parseLine(const std::string &line)
Parses the contents of the line.