SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PCLoaderOSM.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // A reader of pois and polygons stored in OSM-format
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo-sim.org/
13 // Copyright (C) 2001-2014 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>
39 #include <utils/common/ToString.h>
42 #include <utils/options/Option.h>
43 #include <utils/common/StdDefs.h>
45 #include "PCLoaderOSM.h"
46 #include <utils/common/RGBColor.h>
47 #include <utils/geom/GeomHelper.h>
48 #include <utils/geom/Position.h>
50 #include <utils/xml/XMLSubSys.h>
53 
54 #ifdef CHECK_MEMORY_LEAKS
55 #include <foreign/nvwa/debug_new.h>
56 #endif // CHECK_MEMORY_LEAKS
57 // ---------------------------------------------------------------------------
58 // static members
59 // ---------------------------------------------------------------------------
61 
62 // ===========================================================================
63 // method definitions
64 // ===========================================================================
65 // ---------------------------------------------------------------------------
66 // static interface
67 // ---------------------------------------------------------------------------
68 std::set<std::string> PCLoaderOSM::initMyKeysToInclude() {
69  std::set<std::string> result;
70  result.insert("waterway");
71  result.insert("aeroway");
72  result.insert("aerialway");
73  result.insert("power");
74  result.insert("man_made");
75  result.insert("building");
76  result.insert("leisure");
77  result.insert("amenity");
78  result.insert("shop");
79  result.insert("tourism");
80  result.insert("historic");
81  result.insert("landuse");
82  result.insert("natural");
83  result.insert("military");
84  result.insert("boundary");
85  result.insert("admin_level");
86  result.insert("sport");
87  result.insert("polygon");
88  result.insert("place");
89  result.insert("population");
90  result.insert("openGeoDB:population");
91  result.insert("openGeoDB:name");
92  return result;
93 }
94 
95 void
97  PCTypeMap& tm) {
98  if (!oc.isSet("osm-files")) {
99  return;
100  }
101  // parse file(s)
102  std::vector<std::string> files = oc.getStringVector("osm-files");
103  // load nodes, first
104  std::map<SUMOLong, PCOSMNode*> nodes;
105  bool withAttributes = oc.getBool("all-attributes");
107  NodesHandler nodesHandler(nodes, withAttributes, *m);
108  for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
109  // nodes
110  if (!FileHelpers::exists(*file)) {
111  WRITE_ERROR("Could not open osm-file '" + *file + "'.");
112  return;
113  }
114  PROGRESS_BEGIN_MESSAGE("Parsing nodes from osm-file '" + *file + "'");
115  if (!XMLSubSys::runParser(nodesHandler, *file)) {
116  throw ProcessError();
117  }
119  }
120  // load edges, then
121  std::map<std::string, PCOSMEdge*> edges;
122  EdgesHandler edgesHandler(nodes, edges, withAttributes, *m);
123  for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
124  // edges
125  PROGRESS_BEGIN_MESSAGE("Parsing edges from osm-file '" + *file + "'");
126  XMLSubSys::runParser(edgesHandler, *file);
128  }
129 
130  // build all
131  const bool useName = oc.getBool("osm.use-name");
132  // instatiate polygons
133  for (std::map<std::string, PCOSMEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
134  PCOSMEdge* e = (*i).second;
135  if (e->myAttributes.size() == 0) {
136  // cannot be relevant as a polygon
137  continue;
138  }
139  if (e->myCurrentNodes.size() == 0) {
140  WRITE_ERROR("Polygon '" + e->id + "' has no shape.");
141  continue;
142  }
143  // compute shape
144  PositionVector vec;
145  for (std::vector<SUMOLong>::iterator j = e->myCurrentNodes.begin(); j != e->myCurrentNodes.end(); ++j) {
146  PCOSMNode* n = nodes.find(*j)->second;
147  Position pos(n->lon, n->lat);
148  if (!GeoConvHelper::getProcessing().x2cartesian(pos)) {
149  WRITE_WARNING("Unable to project coordinates for polygon '" + e->id + "'.");
150  }
151  vec.push_back_noDoublePos(pos);
152  }
153  const bool ignorePruning = OptionsCont::getOptions().isInStringVector("prune.keep-list", toString(e->id));
154  // add as many polygons as keys match defined types
155  int index = 0;
156  std::string unknownPolyType = "";
157  for (std::map<std::string, std::string>::iterator it = e->myAttributes.begin(); it != e->myAttributes.end(); ++it) {
158  const std::string& key = it->first;
159  const std::string& value = it->second;
160  const std::string fullType = key + "." + value;
161  if (tm.has(key + "." + value)) {
162  index = addPolygon(e, vec, tm.get(fullType), fullType, index, useName, toFill, ignorePruning, withAttributes);
163  } else if (tm.has(key)) {
164  index = addPolygon(e, vec, tm.get(key), fullType, index, useName, toFill, ignorePruning, withAttributes);
165  } else if (MyKeysToInclude.count(key) > 0) {
166  unknownPolyType = fullType;
167  }
168  }
169  const PCTypeMap::TypeDef& def = tm.getDefault();
170  if (index == 0 && !def.discard && unknownPolyType != "") {
171  addPolygon(e, vec, def, unknownPolyType, index, useName, toFill, ignorePruning, withAttributes);
172  }
173  }
174 
175 
176  // instantiate pois
177  for (std::map<SUMOLong, PCOSMNode*>::iterator i = nodes.begin(); i != nodes.end(); ++i) {
178  PCOSMNode* n = (*i).second;
179  if (n->myAttributes.size() == 0) {
180  // cannot be relevant as a poi
181  continue;
182  }
183  Position pos(n->lon, n->lat);
184  if (!GeoConvHelper::getProcessing().x2cartesian(pos)) {
185  WRITE_WARNING("Unable to project coordinates for POI '" + toString(n->id) + "'.");
186  }
187  const bool ignorePruning = OptionsCont::getOptions().isInStringVector("prune.keep-list", toString(n->id));
188  // add as many POIs as keys match defined types
189  int index = 0;
190  std::string unKnownPOIType = "";
191  for (std::map<std::string, std::string>::iterator it = n->myAttributes.begin(); it != n->myAttributes.end(); ++it) {
192  const std::string& key = it->first;
193  const std::string& value = it->second;
194  const std::string fullType = key + "." + value;
195  if (tm.has(key + "." + value)) {
196  index = addPOI(n, pos, tm.get(fullType), fullType, index, toFill, ignorePruning, withAttributes);
197  } else if (tm.has(key)) {
198  index = addPOI(n, pos, tm.get(key), fullType, index, toFill, ignorePruning, withAttributes);
199  } else if (MyKeysToInclude.count(key) > 0) {
200  unKnownPOIType = fullType;
201  }
202  }
203  const PCTypeMap::TypeDef& def = tm.getDefault();
204  if (index == 0 && !def.discard && unKnownPOIType != "") {
205  addPOI(n, pos, def, unKnownPOIType, index, toFill, ignorePruning, withAttributes);
206  }
207  }
208  // delete nodes
209  for (std::map<SUMOLong, PCOSMNode*>::const_iterator i = nodes.begin(); i != nodes.end(); ++i) {
210  delete(*i).second;
211  }
212  // delete edges
213  for (std::map<std::string, PCOSMEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
214  delete(*i).second;
215  }
216 }
217 
218 
219 int
220 PCLoaderOSM::addPolygon(const PCOSMEdge* edge, const PositionVector& vec, const PCTypeMap::TypeDef& def, const std::string& fullType, int index, bool useName, PCPolyContainer& toFill, bool ignorePruning, bool withAttributes) {
221  if (def.discard) {
222  return index;
223  } else {
224  const bool closedShape = vec.front() == vec.back();
225  const std::string idSuffix = (index == 0 ? "" : "#" + toString(index));
226  const std::string id = def.prefix + (useName && edge->name != "" ? edge->name : edge->id) + idSuffix;
227  Polygon* poly = new Polygon(
229  StringUtils::escapeXML(OptionsCont::getOptions().getBool("osm.keep-full-type") ? fullType : def.id),
230  def.color, vec, def.allowFill && closedShape, (SUMOReal)def.layer);
231  if (withAttributes) {
232  poly->addParameter(edge->myAttributes);
233  }
234  if (!toFill.insert(id, poly, def.layer, ignorePruning)) {
235  return index;
236  } else {
237  return index + 1;
238  }
239  }
240 }
241 
242 int
243 PCLoaderOSM::addPOI(const PCOSMNode* node, const Position& pos, const PCTypeMap::TypeDef& def, const std::string& fullType,
244  int index, PCPolyContainer& toFill, bool ignorePruning, bool withAttributes) {
245  if (def.discard) {
246  return index;
247  } else {
248  const std::string idSuffix = (index == 0 ? "" : "#" + toString(index));
249  const std::string id = def.prefix + toString(node->id) + idSuffix;
250  PointOfInterest* poi = new PointOfInterest(
252  StringUtils::escapeXML(OptionsCont::getOptions().getBool("osm.keep-full-type") ? fullType : def.id),
253  def.color, pos, (SUMOReal)def.layer);
254  if (withAttributes) {
255  poi->addParameter(node->myAttributes);
256  }
257  if (!toFill.insert(id, poi, def.layer, ignorePruning)) {
258  return index;
259  } else {
260  return index + 1;
261  }
262  }
263 }
264 
265 
266 // ---------------------------------------------------------------------------
267 // definitions of PCLoaderOSM::NodesHandler-methods
268 // ---------------------------------------------------------------------------
269 PCLoaderOSM::NodesHandler::NodesHandler(std::map<SUMOLong, PCOSMNode*>& toFill,
270  bool withAttributes, MsgHandler& errorHandler) :
271  SUMOSAXHandler("osm - file"), myWithAttributes(withAttributes), myErrorHandler(errorHandler),
272  myToFill(toFill), myLastNodeID(-1) {}
273 
274 
276 
277 
278 void
280  myParentElements.push_back(element);
281  if (element == SUMO_TAG_NODE) {
282  bool ok = true;
283  SUMOLong id = attrs.get<SUMOLong>(SUMO_ATTR_ID, 0, ok);
284  if (!ok) {
285  return;
286  }
287  myLastNodeID = -1;
288  if (myToFill.find(id) == myToFill.end()) {
289  myLastNodeID = id;
290  // assume we are loading multiple files...
291  // ... so we won't report duplicate nodes
292  PCOSMNode* toAdd = new PCOSMNode();
293  toAdd->id = id;
294  bool ok = true;
295  toAdd->lon = attrs.get<SUMOReal>(SUMO_ATTR_LON, toString(id).c_str(), ok);
296  toAdd->lat = attrs.get<SUMOReal>(SUMO_ATTR_LAT, toString(id).c_str(), ok);
297  if (!ok) {
298  delete toAdd;
299  return;
300  }
301  myToFill[toAdd->id] = toAdd;
302  }
303  }
304  if (element == SUMO_TAG_TAG && myParentElements.size() > 2 && myParentElements[myParentElements.size() - 2] == SUMO_TAG_NODE
305  && myLastNodeID != -1) {
306  bool ok = true;
307  std::string key = attrs.getOpt<std::string>(SUMO_ATTR_K, toString(myLastNodeID).c_str(), ok, "", false);
308  std::string value = attrs.getOpt<std::string>(SUMO_ATTR_V, toString(myLastNodeID).c_str(), ok, "", false);
309  if (key == "") {
310  myErrorHandler.inform("Empty key in a a tag while parsing node '" + toString(myLastNodeID) + "' occured.");
311  ok = false;
312  }
313  if (!ok) {
314  return;
315  }
316  myToFill[myLastNodeID]->myAttributes[key] = value;
317  }
318 }
319 
320 
321 void
323  if (element == SUMO_TAG_NODE) {
324  myLastNodeID = -1;
325  }
326  myParentElements.pop_back();
327 }
328 
329 
330 // ---------------------------------------------------------------------------
331 // definitions of PCLoaderOSM::EdgesHandler-methods
332 // ---------------------------------------------------------------------------
333 PCLoaderOSM::EdgesHandler::EdgesHandler(const std::map<SUMOLong, PCOSMNode*>& osmNodes,
334  std::map<std::string, PCOSMEdge*>& toFill, bool withAttributes, MsgHandler& errorHandler)
335  : SUMOSAXHandler("osm - file"), myWithAttributes(withAttributes), myErrorHandler(errorHandler),
336  myOSMNodes(osmNodes), myEdgeMap(toFill) {
337 }
338 
339 
341 }
342 
343 
344 void
346  myParentElements.push_back(element);
347  // parse "way" elements
348  if (element == SUMO_TAG_WAY) {
349  bool ok = true;
350  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
351  if (!ok) {
352  return;
353  }
354  myCurrentEdge = new PCOSMEdge();
355  myCurrentEdge->id = id;
356  myCurrentEdge->myIsClosed = false;
357  myKeep = false;
358  }
359  // parse "nd" (node) elements
360  if (element == SUMO_TAG_ND) {
361  bool ok = true;
362  SUMOLong ref = attrs.get<SUMOLong>(SUMO_ATTR_REF, 0, ok);
363  if (ok) {
364  if (myOSMNodes.find(ref) == myOSMNodes.end()) {
365  WRITE_WARNING("The referenced geometry information (ref='" + toString(ref) + "') is not known");
366  return;
367  }
368  myCurrentEdge->myCurrentNodes.push_back(ref);
369  }
370  }
371  // parse values
372  if (element == SUMO_TAG_TAG && myParentElements.size() > 2 && myParentElements[myParentElements.size() - 2] == SUMO_TAG_WAY
373  && myCurrentEdge != 0) {
374  bool ok = true;
375  std::string key = attrs.getOpt<std::string>(SUMO_ATTR_K, toString(myCurrentEdge->id).c_str(), ok, "", false);
376  std::string value = attrs.getOpt<std::string>(SUMO_ATTR_V, toString(myCurrentEdge->id).c_str(), ok, "", false);
377  if (key == "") {
378  myErrorHandler.inform("Empty key in a a tag while parsing way '" + toString(myCurrentEdge->id) + "' occured.");
379  ok = false;
380  }
381  if (!ok) {
382  return;
383  }
384  if (key == "name") {
385  myCurrentEdge->name = value;
386  } else if (MyKeysToInclude.count(key) > 0) {
387  myKeep = true;
388  }
389  myCurrentEdge->myAttributes[key] = value;
390  }
391 }
392 
393 
394 void
396  myParentElements.pop_back();
397  if (element == SUMO_TAG_WAY) {
398  if (myKeep) {
399  myEdgeMap[myCurrentEdge->id] = myCurrentEdge;
400  } else {
401  delete myCurrentEdge;
402  }
403  myCurrentEdge = 0;
404  }
405 }
406 
407 
408 /****************************************************************************/
409 
std::string id
The new type id to use.
Definition: PCTypeMap.h:67
static MsgHandler * getWarningInstance()
Returns the instance to add warnings to.
Definition: MsgHandler.cpp:71
SUMOReal lat
The latitude the node is located at.
Definition: PCLoaderOSM.h:82
An internal definition of a loaded edge.
Definition: PCLoaderOSM.h:90
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) ...
static int addPOI(const PCOSMNode *node, const Position &pos, const PCTypeMap::TypeDef &def, const std::string &fullType, int index, PCPolyContainer &toFill, bool ignorePruning, bool withAttributes)
try add the POI and return the next index on success
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
Definition: MsgHandler.cpp:80
static void loadIfSet(OptionsCont &oc, PCPolyContainer &toFill, PCTypeMap &tm)
Loads pois/polygons assumed to be stored as OSM-XML.
Definition: PCLoaderOSM.cpp:96
A single definition of values that shall be used for a given type.
Definition: PCTypeMap.h:65
bool isInStringVector(const std::string &optionName, const std::string &itemName)
Returns the named option is a list of string values containing the specified item.
static GeoConvHelper & getProcessing()
the coordinate transformation to use for input conversion and processing
Definition: GeoConvHelper.h:97
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
std::vector< SUMOLong > myCurrentNodes
The list of nodes this edge is made of.
Definition: PCLoaderOSM.h:98
static std::string escapeXML(const std::string &orig)
Replaces the standard escapes by their XML entities.
bool insert(const std::string &id, Polygon *poly, int layer, bool ignorePruning=false)
Adds a polygon to the storage.
EdgesHandler(const std::map< SUMOLong, PCOSMNode * > &osmNodes, std::map< std::string, PCOSMEdge * > &toFill, bool withAttributes, MsgHandler &errorHandler)
Constructor.
void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
static std::set< std::string > initMyKeysToInclude()
Definition: PCLoaderOSM.cpp:68
SAX-handler base for SUMO-files.
static bool runParser(GenericSAXHandler &handler, const std::string &file, const bool isNet=false)
Runs the given handler on the given file; returns if everything's ok.
Definition: XMLSubSys.cpp:114
SUMOReal lon
The longitude the node is located at.
Definition: PCLoaderOSM.h:80
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:196
std::string id
The edge's id.
Definition: PCLoaderOSM.h:92
bool discard
Information whether polygons of this type shall be discarded.
Definition: PCTypeMap.h:75
A storage for loaded polygons and pois.
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:67
NodesHandler(std::map< SUMOLong, PCOSMNode * > &toFill, bool withAttributes, MsgHandler &errorHandler)
Contructor.
RGBColor color
The color to use.
Definition: PCTypeMap.h:69
A 2D- or 3D-polygon.
Definition: Polygon.h:48
static const std::set< std::string > MyKeysToInclude
Definition: PCLoaderOSM.h:114
std::map< std::string, std::string > myAttributes
Additional attributes.
Definition: PCLoaderOSM.h:100
A storage for type mappings.
Definition: PCTypeMap.h:51
const TypeDef & get(const std::string &id)
Returns a type definition.
Definition: PCTypeMap.cpp:77
void myEndElement(int element)
Called when a closing tag occurs.
void myEndElement(int element)
Called when a closing tag occurs.
Encapsulated SAX-Attributes.
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:46
A list of positions.
std::map< std::string, std::string > myAttributes
Additional attributes.
Definition: PCLoaderOSM.h:84
bool has(const std::string &id)
Returns the information whether the named type is known.
Definition: PCTypeMap.cpp:83
static bool exists(std::string path)
Checks whether the given file exists.
Definition: FileHelpers.cpp:57
SUMOLong id
The node's id.
Definition: PCLoaderOSM.h:78
#define PROGRESS_BEGIN_MESSAGE(msg)
Definition: MsgHandler.h:198
#define SUMOLong
Definition: config.h:212
A class which extracts OSM-edges from a parsed OSM-file.
Definition: PCLoaderOSM.h:195
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:52
void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
A class which extracts OSM-nodes from a parsed OSM-file.
Definition: PCLoaderOSM.h:125
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:201
void addParameter(const std::string &key, const std::string &value)
Adds a parameter.
std::string prefix
The prefix to use.
Definition: PCTypeMap.h:71
static int addPolygon(const PCOSMEdge *edge, const PositionVector &vec, const PCTypeMap::TypeDef &def, const std::string &fullType, int index, bool useName, PCPolyContainer &toFill, bool ignorePruning, bool withAttributes)
try add the polygon and return the next index on success
A storage for options typed value containers)
Definition: OptionsCont.h:108
std::string name
The edge's name (if any)
Definition: PCLoaderOSM.h:94
const TypeDef & getDefault()
get the default type according to the given options
Definition: PCTypeMap.h:114
#define SUMOReal
Definition: config.h:215
void push_back_noDoublePos(const Position &p)
A point-of-interest.
int layer
The layer to use.
Definition: PCTypeMap.h:73
T getOpt(int attr, const char *objectid, bool &ok, T defaultValue, bool report=true) const
Tries to read given attribute assuming it is an int.
T get(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is an int.
#define PROGRESS_DONE_MESSAGE()
Definition: MsgHandler.h:199
bool allowFill
Information whether polygons of this type can be filled.
Definition: PCTypeMap.h:77
An internal representation of an OSM-node.
Definition: PCLoaderOSM.h:76
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.