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-2013 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  WRITE_ERROR("Polygon '" + id + "' could not be added.");
236  delete poly;
237  return index;
238  } else {
239  return index + 1;
240  }
241  }
242 }
243 
244 int
245 PCLoaderOSM::addPOI(const PCOSMNode* node, const Position& pos, const PCTypeMap::TypeDef& def, const std::string& fullType,
246  int index, PCPolyContainer& toFill, bool ignorePruning, bool withAttributes) {
247  if (def.discard) {
248  return index;
249  } else {
250  const std::string idSuffix = (index == 0 ? "" : "#" + toString(index));
251  const std::string id = def.prefix + toString(node->id) + idSuffix;
252  PointOfInterest* poi = new PointOfInterest(
254  StringUtils::escapeXML(OptionsCont::getOptions().getBool("osm.keep-full-type") ? fullType : def.id),
255  def.color, pos, (SUMOReal)def.layer);
256  if (withAttributes) {
257  poi->addParameter(node->myAttributes);
258  }
259  if (!toFill.insert(id, poi, def.layer, ignorePruning)) {
260  WRITE_ERROR("POI '" + id + "' could not be added.");
261  delete poi;
262  return index;
263  } else {
264  return index + 1;
265  }
266  }
267 }
268 
269 
270 // ---------------------------------------------------------------------------
271 // definitions of PCLoaderOSM::NodesHandler-methods
272 // ---------------------------------------------------------------------------
273 PCLoaderOSM::NodesHandler::NodesHandler(std::map<SUMOLong, PCOSMNode*>& toFill,
274  bool withAttributes, MsgHandler& errorHandler) :
275  SUMOSAXHandler("osm - file"), myWithAttributes(withAttributes), myErrorHandler(errorHandler),
276  myToFill(toFill), myLastNodeID(-1) {}
277 
278 
280 
281 
282 void
284  myParentElements.push_back(element);
285  if (element == SUMO_TAG_NODE) {
286  bool ok = true;
287  SUMOLong id = attrs.get<SUMOLong>(SUMO_ATTR_ID, 0, ok);
288  if (!ok) {
289  return;
290  }
291  myLastNodeID = -1;
292  if (myToFill.find(id) == myToFill.end()) {
293  myLastNodeID = id;
294  // assume we are loading multiple files...
295  // ... so we won't report duplicate nodes
296  PCOSMNode* toAdd = new PCOSMNode();
297  toAdd->id = id;
298  bool ok = true;
299  toAdd->lon = attrs.get<SUMOReal>(SUMO_ATTR_LON, toString(id).c_str(), ok);
300  toAdd->lat = attrs.get<SUMOReal>(SUMO_ATTR_LAT, toString(id).c_str(), ok);
301  if (!ok) {
302  delete toAdd;
303  return;
304  }
305  myToFill[toAdd->id] = toAdd;
306  }
307  }
308  if (element == SUMO_TAG_TAG && myParentElements.size() > 2 && myParentElements[myParentElements.size() - 2] == SUMO_TAG_NODE
309  && myLastNodeID != -1) {
310  bool ok = true;
311  std::string key = attrs.getOpt<std::string>(SUMO_ATTR_K, toString(myLastNodeID).c_str(), ok, "", false);
312  std::string value = attrs.getOpt<std::string>(SUMO_ATTR_V, toString(myLastNodeID).c_str(), ok, "", false);
313  if (key == "") {
314  myErrorHandler.inform("Empty key in a a tag while parsing node '" + toString(myLastNodeID) + "' occured.");
315  ok = false;
316  }
317  if (!ok) {
318  return;
319  }
320  myToFill[myLastNodeID]->myAttributes[key] = value;
321  }
322 }
323 
324 
325 void
327  if (element == SUMO_TAG_NODE) {
328  myLastNodeID = -1;
329  }
330  myParentElements.pop_back();
331 }
332 
333 
334 // ---------------------------------------------------------------------------
335 // definitions of PCLoaderOSM::EdgesHandler-methods
336 // ---------------------------------------------------------------------------
337 PCLoaderOSM::EdgesHandler::EdgesHandler(const std::map<SUMOLong, PCOSMNode*>& osmNodes,
338  std::map<std::string, PCOSMEdge*>& toFill, bool withAttributes, MsgHandler& errorHandler)
339  : SUMOSAXHandler("osm - file"), myWithAttributes(withAttributes), myErrorHandler(errorHandler),
340  myOSMNodes(osmNodes), myEdgeMap(toFill) {
341 }
342 
343 
345 }
346 
347 
348 void
350  myParentElements.push_back(element);
351  // parse "way" elements
352  if (element == SUMO_TAG_WAY) {
353  bool ok = true;
354  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
355  if (!ok) {
356  return;
357  }
358  myCurrentEdge = new PCOSMEdge();
359  myCurrentEdge->id = id;
360  myCurrentEdge->myIsClosed = false;
361  myKeep = false;
362  }
363  // parse "nd" (node) elements
364  if (element == SUMO_TAG_ND) {
365  bool ok = true;
366  SUMOLong ref = attrs.get<SUMOLong>(SUMO_ATTR_REF, 0, ok);
367  if (ok) {
368  if (myOSMNodes.find(ref) == myOSMNodes.end()) {
369  WRITE_WARNING("The referenced geometry information (ref='" + toString(ref) + "') is not known");
370  return;
371  }
372  myCurrentEdge->myCurrentNodes.push_back(ref);
373  }
374  }
375  // parse values
376  if (element == SUMO_TAG_TAG && myParentElements.size() > 2 && myParentElements[myParentElements.size() - 2] == SUMO_TAG_WAY
377  && myCurrentEdge != 0) {
378  bool ok = true;
379  std::string key = attrs.getOpt<std::string>(SUMO_ATTR_K, toString(myCurrentEdge->id).c_str(), ok, "", false);
380  std::string value = attrs.getOpt<std::string>(SUMO_ATTR_V, toString(myCurrentEdge->id).c_str(), ok, "", false);
381  if (key == "") {
382  myErrorHandler.inform("Empty key in a a tag while parsing way '" + toString(myCurrentEdge->id) + "' occured.");
383  ok = false;
384  }
385  if (!ok) {
386  return;
387  }
388  if (key == "name") {
389  myCurrentEdge->name = value;
390  } else if (MyKeysToInclude.count(key) > 0) {
391  myKeep = true;
392  }
393  myCurrentEdge->myAttributes[key] = value;
394  }
395 }
396 
397 
398 void
400  myParentElements.pop_back();
401  if (element == SUMO_TAG_WAY) {
402  if (myKeep) {
403  myEdgeMap[myCurrentEdge->id] = myCurrentEdge;
404  } else {
405  delete myCurrentEdge;
406  }
407  myCurrentEdge = 0;
408  }
409 }
410 
411 
412 /****************************************************************************/
413