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.sourceforge.net/
13 // Copyright (C) 2001-2012 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 
59 // ===========================================================================
60 // method definitions
61 // ===========================================================================
62 // ---------------------------------------------------------------------------
63 // static interface
64 // ---------------------------------------------------------------------------
65 void
67  PCTypeMap& tm) {
68  if (!oc.isSet("osm-files")) {
69  return;
70  }
71  // parse file(s)
72  std::vector<std::string> files = oc.getStringVector("osm-files");
73  // load nodes, first
74  std::map<long, PCOSMNode*> nodes;
75  NodesHandler nodesHandler(nodes);
76  for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
77  // nodes
78  if (!FileHelpers::exists(*file)) {
79  WRITE_ERROR("Could not open osm-file '" + *file + "'.");
80  return;
81  }
82  PROGRESS_BEGIN_MESSAGE("Parsing nodes from osm-file '" + *file + "'");
83  if (!XMLSubSys::runParser(nodesHandler, *file)) {
84  throw ProcessError();
85  }
87  }
88  // load edges, then
89  std::map<std::string, PCOSMEdge*> edges;
90  EdgesHandler edgesHandler(nodes, edges);
91  for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
92  // edges
93  PROGRESS_BEGIN_MESSAGE("Parsing edges from osm-file '" + *file + "'");
94  XMLSubSys::runParser(edgesHandler, *file);
96  }
97  // build all
98  RGBColor c = RGBColor::parseColor(oc.getString("color"));
99  // instatiate polygons
100  for (std::map<std::string, PCOSMEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
101  PCOSMEdge* e = (*i).second;
102  if (!e->myIsAdditional) {
103  continue;
104  }
105  // compute shape
106  PositionVector vec;
107  for (std::vector<long>::iterator j = e->myCurrentNodes.begin(); j != e->myCurrentNodes.end(); ++j) {
108  PCOSMNode* n = nodes.find(*j)->second;
109  Position pos(n->lon, n->lat);
110  if (!GeoConvHelper::getProcessing().x2cartesian(pos)) {
111  WRITE_WARNING("Unable to project coordinates for polygon '" + e->id + "'.");
112  }
113  vec.push_back_noDoublePos(pos);
114  }
115  // set type etc.
116  std::string name = oc.getBool("osm.use-name") && e->name != "" ? e->name : e->id;
117  std::string type;
118  RGBColor color;
119  bool fill = vec.getBegin() == vec.getEnd();
120  bool discard = oc.getBool("discard");
121  int layer = oc.getInt("layer");
122  if (tm.has(e->myType)) {
123  const PCTypeMap::TypeDef& def = tm.get(e->myType);
124  name = def.prefix + name;
125  type = def.id;
126  color = RGBColor::parseColor(def.color);
127  fill = fill && def.allowFill;
128  discard = def.discard;
129  layer = def.layer;
130  } else if (e->myType.find(".") != std::string::npos && tm.has(e->myType.substr(0, e->myType.find(".")))) {
131  const PCTypeMap::TypeDef& def = tm.get(e->myType.substr(0, e->myType.find(".")));
132  name = def.prefix + name;
133  type = def.id;
134  color = RGBColor::parseColor(def.color);
135  fill = fill && def.allowFill;
136  discard = def.discard;
137  layer = def.layer;
138  } else {
139  name = oc.getString("prefix") + name;
140  type = oc.getString("type");
141  color = c;
142  }
143  if (!discard) {
144  if (oc.getBool("osm.keep-full-type")) {
145  type = e->myType;
146  }
147  name = StringUtils::escapeXML(name);
148  type = StringUtils::escapeXML(type);
149  Polygon* poly = new Polygon(name, type, color, vec, fill);
150  if (!toFill.insert(name, poly, layer)) {
151  WRITE_ERROR("Polygon '" + name + "' could not been added.");
152  delete poly;
153  }
154  }
155  }
156  // instantiate pois
157  for (std::map<long, PCOSMNode*>::iterator i = nodes.begin(); i != nodes.end(); ++i) {
158  PCOSMNode* n = (*i).second;
159  if (!n->myIsAdditional) {
160  continue;
161  }
162 
163  // patch the values
164  bool discard = oc.getBool("discard");
165  int layer = oc.getInt("layer");
166  std::string name = toString(n->id);
167  std::string type;
168  RGBColor color;
169  if (tm.has(n->myType)) {
170  const PCTypeMap::TypeDef& def = tm.get(n->myType);
171  name = def.prefix + name;
172  type = def.id;
173  color = RGBColor::parseColor(def.color);
174  discard = def.discard;
175  layer = def.layer;
176  } else if (type.find(".") != std::string::npos && tm.has(type.substr(0, type.find(".")))) {
177  const PCTypeMap::TypeDef& def = tm.get(type.substr(0, type.find(".")));
178  name = def.prefix + name;
179  type = def.id;
180  color = RGBColor::parseColor(def.color);
181  discard = def.discard;
182  layer = def.layer;
183  } else {
184  name = oc.getString("prefix") + name;
185  type = oc.getString("type");
186  color = c;
187  }
188  if (!discard) {
189  if (oc.getBool("osm.keep-full-type")) {
190  type = n->myType;
191  }
192  bool ignorePrunning = false;
193  if (OptionsCont::getOptions().isInStringVector("prune.keep-list", name)) {
194  ignorePrunning = true;
195  }
196  Position pos(n->lon, n->lat);
197  if (!GeoConvHelper::getProcessing().x2cartesian(pos)) {
198  WRITE_WARNING("Unable to project coordinates for POI '" + name + "'.");
199  }
200  name = StringUtils::escapeXML(name);
201  type = StringUtils::escapeXML(type);
202  PointOfInterest* poi = new PointOfInterest(name, type, pos, color);
203  if (!toFill.insert(name, poi, layer, ignorePrunning)) {
204  WRITE_ERROR("POI '" + name + "' could not been added.");
205  delete poi;
206  }
207  }
208  }
209 
210 
211  // delete nodes
212  for (std::map<long, PCOSMNode*>::const_iterator i = nodes.begin(); i != nodes.end(); ++i) {
213  delete(*i).second;
214  }
215  // delete edges
216  for (std::map<std::string, PCOSMEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
217  delete(*i).second;
218  }
219 }
220 
221 
222 
223 // ---------------------------------------------------------------------------
224 // definitions of PCLoaderOSM::NodesHandler-methods
225 // ---------------------------------------------------------------------------
226 PCLoaderOSM::NodesHandler::NodesHandler(std::map<long, PCOSMNode*> &toFill)
227  : SUMOSAXHandler("osm - file"), myToFill(toFill), myLastNodeID(-1) {}
228 
229 
231 
232 
233 void
235  myParentElements.push_back(element);
236  if (element == SUMO_TAG_NODE) {
237  bool ok = true;
238  long id = attrs.getLongReporting(SUMO_ATTR_ID, 0, ok);
239  if (!ok) {
240  return;
241  }
242  myLastNodeID = -1;
243  if (myToFill.find(id) == myToFill.end()) {
244  myLastNodeID = id;
245  // assume we are loading multiple files...
246  // ... so we won't report duplicate nodes
247  PCOSMNode* toAdd = new PCOSMNode();
248  toAdd->id = id;
249  toAdd->myIsAdditional = false;
250  bool ok = true;
251  toAdd->lon = attrs.getSUMORealReporting(SUMO_ATTR_LON, toString(id).c_str(), ok);
252  toAdd->lat = attrs.getSUMORealReporting(SUMO_ATTR_LAT, toString(id).c_str(), ok);
253  if (!ok) {
254  delete toAdd;
255  return;
256  }
257  myToFill[toAdd->id] = toAdd;
258  }
259  }
260  if (element == SUMO_TAG_TAG && myParentElements.size() > 2 && myParentElements[myParentElements.size() - 2] == SUMO_TAG_NODE) {
261  bool ok = true;
262  std::string key = attrs.getStringReporting(SUMO_ATTR_K, toString(myLastNodeID).c_str(), ok);
263  std::string value = attrs.getOptStringReporting(SUMO_ATTR_V, toString(myLastNodeID).c_str(), ok, "");
264  if (!ok) {
265  return;
266  }
267  if (key == "waterway" || key == "aeroway" || key == "aerialway" || key == "power" || key == "man_made" || key == "building"
268  || key == "leisure" || key == "amenity" || key == "shop" || key == "tourism" || key == "historic" || key == "landuse"
269  || key == "natural" || key == "military" || key == "boundary" || key == "sport" || key == "polygon") {
270  if (myLastNodeID >= 0) {
271  myToFill[myLastNodeID]->myType = key + "." + value;
272  myToFill[myLastNodeID]->myIsAdditional = true;
273  }
274  }
275  if (key == "name" && myLastNodeID != -1) {
276  myToFill[myLastNodeID]->myType = key + "." + value;
277  }
278  }
279 }
280 
281 
282 void
284  if (element == SUMO_TAG_NODE) {
285  myLastNodeID = -1;
286  }
287  myParentElements.pop_back();
288 }
289 
290 
291 // ---------------------------------------------------------------------------
292 // definitions of PCLoaderOSM::EdgesHandler-methods
293 // ---------------------------------------------------------------------------
295  const std::map<long, PCOSMNode*> &osmNodes,
296  std::map<std::string, PCOSMEdge*> &toFill)
297  : SUMOSAXHandler("osm - file"),
298  myOSMNodes(osmNodes), myEdgeMap(toFill) {
299 }
300 
301 
303 }
304 
305 
306 void
308  myParentElements.push_back(element);
309  // parse "way" elements
310  if (element == SUMO_TAG_WAY) {
311  bool ok = true;
312  std::string id = attrs.getStringReporting(SUMO_ATTR_ID, 0, ok);
313  if (!ok) {
314  return;
315  }
316  myCurrentEdge = new PCOSMEdge();
317  myCurrentEdge->id = id;
318  myCurrentEdge->myIsAdditional = false;
319  myCurrentEdge->myIsClosed = false;
320  }
321  // parse "nd" (node) elements
322  if (element == SUMO_TAG_ND) {
323  bool ok = true;
324  long ref = attrs.getLongReporting(SUMO_ATTR_REF, 0, ok);
325  if (ok) {
326  if (myOSMNodes.find(ref) == myOSMNodes.end()) {
327  WRITE_WARNING("The referenced geometry information (ref='" + toString(ref) + "') is not known");
328  return;
329  }
330  myCurrentEdge->myCurrentNodes.push_back(ref);
331  }
332  }
333  // parse values
334  if (element == SUMO_TAG_TAG && myParentElements.size() > 2 && myParentElements[myParentElements.size() - 2] == SUMO_TAG_WAY) {
335  bool ok = true;
336  std::string key = attrs.getStringReporting(SUMO_ATTR_K, toString(myCurrentEdge->id).c_str(), ok);
337  std::string value = attrs.getStringReporting(SUMO_ATTR_V, toString(myCurrentEdge->id).c_str(), ok);
338  if (!ok) {
339  return;
340  }
341  if (key == "waterway" || key == "aeroway" || key == "aerialway" || key == "power" || key == "man_made"
342  || key == "building" || key == "leisure" || key == "amenity" || key == "shop" || key == "tourism"
343  || key == "historic" || key == "landuse" || key == "natural" || key == "military" || key == "boundary"
344  || key == "sport" || key == "polygon") {
345  myCurrentEdge->myType = key + "." + value;
346  myCurrentEdge->myIsAdditional = true;
347  } else if (key == "name") {
348  myCurrentEdge->name = value;
349  }
350  }
351 }
352 
353 
354 void
356  myParentElements.pop_back();
357  if (element == SUMO_TAG_WAY) {
358  if (myCurrentEdge->myIsAdditional) {
359  myEdgeMap[myCurrentEdge->id] = myCurrentEdge;
360  } else {
361  delete myCurrentEdge;
362  }
363  myCurrentEdge = 0;
364  }
365 }
366 
367 
368 /****************************************************************************/
369