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