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