|
SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00007 // A reader of pois and polygons stored in OSM-format 00008 /****************************************************************************/ 00009 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/ 00010 // Copyright (C) 2001-2011 DLR (http://www.dlr.de/) and contributors 00011 /****************************************************************************/ 00012 // 00013 // This program is free software; you can redistribute it and/or modify 00014 // it under the terms of the GNU General Public License as published by 00015 // the Free Software Foundation; either version 2 of the License, or 00016 // (at your option) any later version. 00017 // 00018 /****************************************************************************/ 00019 00020 00021 // =========================================================================== 00022 // included modules 00023 // =========================================================================== 00024 #ifdef _MSC_VER 00025 #include <windows_config.h> 00026 #else 00027 #include <config.h> 00028 #endif 00029 00030 #include <string> 00031 #include <map> 00032 #include <fstream> 00033 #include <utils/common/UtilExceptions.h> 00034 #include <utils/common/MsgHandler.h> 00035 #include <utils/common/ToString.h> 00036 #include <utils/options/OptionsCont.h> 00037 #include <utils/options/Option.h> 00038 #include <utils/common/StdDefs.h> 00039 #include <polyconvert/PCPolyContainer.h> 00040 #include "PCLoaderOSM.h" 00041 #include <utils/common/RGBColor.h> 00042 #include <utils/geom/GeomHelper.h> 00043 #include <utils/geom/Position.h> 00044 #include <utils/geom/GeoConvHelper.h> 00045 #include <utils/xml/XMLSubSys.h> 00046 #include <utils/geom/GeomConvHelper.h> 00047 #include <utils/common/FileHelpers.h> 00048 00049 #ifdef CHECK_MEMORY_LEAKS 00050 #include <foreign/nvwa/debug_new.h> 00051 #endif // CHECK_MEMORY_LEAKS 00052 00053 00054 // =========================================================================== 00055 // method definitions 00056 // =========================================================================== 00057 // --------------------------------------------------------------------------- 00058 // static interface 00059 // --------------------------------------------------------------------------- 00060 void 00061 PCLoaderOSM::loadIfSet(OptionsCont& oc, PCPolyContainer& toFill, 00062 PCTypeMap& tm) throw(ProcessError) { 00063 if (!oc.isSet("osm-files")) { 00064 return; 00065 } 00066 // parse file(s) 00067 std::vector<std::string> files = oc.getStringVector("osm-files"); 00068 // load nodes, first 00069 std::map<int, PCOSMNode*> nodes; 00070 NodesHandler nodesHandler(nodes); 00071 for (std::vector<std::string>::const_iterator file=files.begin(); file!=files.end(); ++file) { 00072 // nodes 00073 if (!FileHelpers::exists(*file)) { 00074 WRITE_ERROR("Could not open osm-file '" + *file + "'."); 00075 return; 00076 } 00077 PROGRESS_BEGIN_MESSAGE("Parsing nodes from osm-file '" + *file + "'"); 00078 if (!XMLSubSys::runParser(nodesHandler, *file)) { 00079 throw ProcessError(); 00080 } 00081 PROGRESS_DONE_MESSAGE(); 00082 } 00083 // load edges, then 00084 std::map<std::string, PCOSMEdge*> edges; 00085 EdgesHandler edgesHandler(nodes, edges); 00086 for (std::vector<std::string>::const_iterator file=files.begin(); file!=files.end(); ++file) { 00087 // edges 00088 PROGRESS_BEGIN_MESSAGE("Parsing edges from osm-file '" + *file + "'"); 00089 XMLSubSys::runParser(edgesHandler, *file); 00090 PROGRESS_DONE_MESSAGE(); 00091 } 00092 // build all 00093 RGBColor c = RGBColor::parseColor(oc.getString("color")); 00094 // instatiate polygons 00095 for (std::map<std::string, PCOSMEdge*>::iterator i=edges.begin(); i!=edges.end(); ++i) { 00096 PCOSMEdge* e = (*i).second; 00097 if (!e->myIsAdditional) { 00098 continue; 00099 } 00100 // compute shape 00101 PositionVector vec; 00102 for (std::vector<int>::iterator j=e->myCurrentNodes.begin(); j!=e->myCurrentNodes.end(); ++j) { 00103 PCOSMNode* n = nodes.find(*j)->second; 00104 Position pos(n->lon, n->lat); 00105 if (!GeoConvHelper::getDefaultInstance().x2cartesian(pos)) { 00106 WRITE_WARNING("Unable to project coordinates for polygon '" + e->id + "'."); 00107 } 00108 vec.push_back_noDoublePos(pos); 00109 } 00110 // set type etc. 00111 std::string name = oc.getBool("osm.use-name")&&e->name!="" ? e->name : e->id; 00112 std::string type; 00113 RGBColor color; 00114 bool fill = vec.getBegin()==vec.getEnd(); 00115 bool discard = oc.getBool("discard"); 00116 int layer = oc.getInt("layer"); 00117 if (tm.has(e->myType)) { 00118 const PCTypeMap::TypeDef& def = tm.get(e->myType); 00119 name = def.prefix + name; 00120 type = def.id; 00121 color = RGBColor::parseColor(def.color); 00122 fill = fill && def.allowFill; 00123 discard = def.discard; 00124 layer = def.layer; 00125 } else if (e->myType.find(".")!=std::string::npos&&tm.has(e->myType.substr(0, e->myType.find(".")))) { 00126 const PCTypeMap::TypeDef& def = tm.get(e->myType.substr(0, e->myType.find("."))); 00127 name = def.prefix + name; 00128 type = def.id; 00129 color = RGBColor::parseColor(def.color); 00130 fill = fill && def.allowFill; 00131 discard = def.discard; 00132 layer = def.layer; 00133 } else { 00134 name = oc.getString("prefix") + name; 00135 type = oc.getString("type"); 00136 color = c; 00137 } 00138 if (!discard) { 00139 if (oc.getBool("osm.keep-full-type")) { 00140 type = e->myType; 00141 } 00142 Polygon* poly = new Polygon(name, type, color, vec, fill); 00143 if (!toFill.insert(name, poly, layer)) { 00144 WRITE_ERROR("Polygon '" + name + "' could not been added."); 00145 delete poly; 00146 } 00147 } 00148 } 00149 // instantiate pois 00150 for (std::map<int, PCOSMNode*>::iterator i=nodes.begin(); i!=nodes.end(); ++i) { 00151 PCOSMNode* n = (*i).second; 00152 if (!n->myIsAdditional) { 00153 continue; 00154 } 00155 00156 // patch the values 00157 bool discard = oc.getBool("discard"); 00158 int layer = oc.getInt("layer"); 00159 std::string name = toString(n->id); 00160 std::string type; 00161 RGBColor color; 00162 if (tm.has(n->myType)) { 00163 const PCTypeMap::TypeDef& def = tm.get(n->myType); 00164 name = def.prefix + name; 00165 type = def.id; 00166 color = RGBColor::parseColor(def.color); 00167 discard = def.discard; 00168 layer = def.layer; 00169 } else if (type.find(".")!=std::string::npos&&tm.has(type.substr(0, type.find(".")))) { 00170 const PCTypeMap::TypeDef& def = tm.get(type.substr(0, type.find("."))); 00171 name = def.prefix + name; 00172 type = def.id; 00173 color = RGBColor::parseColor(def.color); 00174 discard = def.discard; 00175 layer = def.layer; 00176 } else { 00177 name = oc.getString("prefix") + name; 00178 type = oc.getString("type"); 00179 color = c; 00180 } 00181 if (!discard) { 00182 if (oc.getBool("osm.keep-full-type")) { 00183 type = n->myType; 00184 } 00185 bool ignorePrunning = false; 00186 if (OptionsCont::getOptions().isInStringVector("prune.keep-list", name)) { 00187 ignorePrunning = true; 00188 } 00189 Position pos(n->lon, n->lat); 00190 if (!GeoConvHelper::getDefaultInstance().x2cartesian(pos)) { 00191 WRITE_WARNING("Unable to project coordinates for POI '" + name + "'."); 00192 } 00193 PointOfInterest* poi = new PointOfInterest(name, type, pos, color); 00194 if (!toFill.insert(name, poi, layer, ignorePrunning)) { 00195 WRITE_ERROR("POI '" + name + "' could not been added."); 00196 delete poi; 00197 } 00198 } 00199 } 00200 00201 00202 // delete nodes 00203 for (std::map<int, PCOSMNode*>::const_iterator i=nodes.begin(); i!=nodes.end(); ++i) { 00204 delete(*i).second; 00205 } 00206 // delete edges 00207 for (std::map<std::string, PCOSMEdge*>::iterator i=edges.begin(); i!=edges.end(); ++i) { 00208 delete(*i).second; 00209 } 00210 } 00211 00212 00213 00214 // --------------------------------------------------------------------------- 00215 // definitions of PCLoaderOSM::NodesHandler-methods 00216 // --------------------------------------------------------------------------- 00217 PCLoaderOSM::NodesHandler::NodesHandler(std::map<int, PCOSMNode*> &toFill) throw() 00218 : SUMOSAXHandler("osm - file"), myToFill(toFill), myLastNodeID(-1) {} 00219 00220 00221 PCLoaderOSM::NodesHandler::~NodesHandler() throw() {} 00222 00223 00224 void 00225 PCLoaderOSM::NodesHandler::myStartElement(int element, const SUMOSAXAttributes& attrs) throw(ProcessError) { 00226 myParentElements.push_back(element); 00227 if (element==SUMO_TAG_NODE) { 00228 bool ok = true; 00229 int id = attrs.getIntReporting(SUMO_ATTR_ID, 0, ok); 00230 if (!ok) { 00231 return; 00232 } 00233 myLastNodeID = -1; 00234 if (myToFill.find(id)==myToFill.end()) { 00235 myLastNodeID = id; 00236 // assume we are loading multiple files... 00237 // ... so we won't report duplicate nodes 00238 PCOSMNode* toAdd = new PCOSMNode(); 00239 toAdd->id = id; 00240 toAdd->myIsAdditional = false; 00241 bool ok = true; 00242 toAdd->lon = attrs.getSUMORealReporting(SUMO_ATTR_LON, toString(id).c_str(), ok); 00243 toAdd->lat = attrs.getSUMORealReporting(SUMO_ATTR_LAT, toString(id).c_str(), ok); 00244 if (!ok) { 00245 delete toAdd; 00246 return; 00247 } 00248 myToFill[toAdd->id] = toAdd; 00249 } 00250 } 00251 if (element==SUMO_TAG_TAG&&myParentElements.size()>2&&myParentElements[myParentElements.size()-2]==SUMO_TAG_NODE) { 00252 bool ok = true; 00253 std::string key = attrs.getStringReporting(SUMO_ATTR_K, toString(myLastNodeID).c_str(), ok); 00254 std::string value = attrs.getOptStringReporting(SUMO_ATTR_V, toString(myLastNodeID).c_str(), ok, ""); 00255 if (!ok) { 00256 return; 00257 } 00258 if (key=="waterway"||key=="aeroway"||key=="aerialway"||key=="power"||key=="man_made"||key=="building" 00259 ||key=="leisure"||key=="amenity"||key=="shop"||key=="tourism"||key=="historic"||key=="landuse" 00260 ||key=="natural"||key=="military"||key=="boundary"||key=="sport"||key=="polygon") { 00261 if (myLastNodeID>=0) { 00262 myToFill[myLastNodeID]->myType = key + "." + value; 00263 myToFill[myLastNodeID]->myIsAdditional = true; 00264 } 00265 } 00266 if (key=="name"&&myLastNodeID!=-1) { 00267 myToFill[myLastNodeID]->myType = key + "." + value; 00268 } 00269 } 00270 } 00271 00272 00273 void 00274 PCLoaderOSM::NodesHandler::myEndElement(int element) throw(ProcessError) { 00275 if (element==SUMO_TAG_NODE) { 00276 myLastNodeID = -1; 00277 } 00278 myParentElements.pop_back(); 00279 } 00280 00281 00282 // --------------------------------------------------------------------------- 00283 // definitions of PCLoaderOSM::EdgesHandler-methods 00284 // --------------------------------------------------------------------------- 00285 PCLoaderOSM::EdgesHandler::EdgesHandler( 00286 const std::map<int, PCOSMNode*> &osmNodes, 00287 std::map<std::string, PCOSMEdge*> &toFill) throw() 00288 : SUMOSAXHandler("osm - file"), 00289 myOSMNodes(osmNodes), myEdgeMap(toFill) { 00290 } 00291 00292 00293 PCLoaderOSM::EdgesHandler::~EdgesHandler() throw() { 00294 } 00295 00296 00297 void 00298 PCLoaderOSM::EdgesHandler::myStartElement(int element, const SUMOSAXAttributes& attrs) throw(ProcessError) { 00299 myParentElements.push_back(element); 00300 // parse "way" elements 00301 if (element==SUMO_TAG_WAY) { 00302 bool ok = true; 00303 std::string id = attrs.getStringReporting(SUMO_ATTR_ID, 0, ok); 00304 if (!ok) { 00305 return; 00306 } 00307 myCurrentEdge = new PCOSMEdge(); 00308 myCurrentEdge->id = id; 00309 myCurrentEdge->myIsAdditional = false; 00310 myCurrentEdge->myIsClosed = false; 00311 } 00312 // parse "nd" (node) elements 00313 if (element==SUMO_TAG_ND) { 00314 bool ok = true; 00315 int ref = attrs.getIntReporting(SUMO_ATTR_REF, 0, ok); 00316 if (ok) { 00317 if (myOSMNodes.find(ref)==myOSMNodes.end()) { 00318 WRITE_WARNING("The referenced geometry information (ref='" + toString(ref) + "') is not known"); 00319 return; 00320 } 00321 myCurrentEdge->myCurrentNodes.push_back(ref); 00322 } 00323 } 00324 // parse values 00325 if (element==SUMO_TAG_TAG&&myParentElements.size()>2&&myParentElements[myParentElements.size()-2]==SUMO_TAG_WAY) { 00326 bool ok = true; 00327 std::string key = attrs.getStringReporting(SUMO_ATTR_K, toString(myCurrentEdge->id).c_str(), ok); 00328 std::string value = attrs.getStringReporting(SUMO_ATTR_V, toString(myCurrentEdge->id).c_str(), ok); 00329 if (!ok) { 00330 return; 00331 } 00332 if (key=="waterway"||key=="aeroway"||key=="aerialway"||key=="power"||key=="man_made" 00333 ||key=="building"||key=="leisure"||key=="amenity"||key=="shop"||key=="tourism" 00334 ||key=="historic"||key=="landuse"||key=="natural"||key=="military"||key=="boundary" 00335 ||key=="sport"||key=="polygon") { 00336 myCurrentEdge->myType = key + "." + value; 00337 myCurrentEdge->myIsAdditional = true; 00338 } else if (key=="name") { 00339 myCurrentEdge->name = value; 00340 } 00341 } 00342 } 00343 00344 00345 void 00346 PCLoaderOSM::EdgesHandler::myEndElement(int element) throw(ProcessError) { 00347 myParentElements.pop_back(); 00348 if (element==SUMO_TAG_WAY) { 00349 if (myCurrentEdge->myIsAdditional) { 00350 myEdgeMap[myCurrentEdge->id] = myCurrentEdge; 00351 } else { 00352 delete myCurrentEdge; 00353 } 00354 myCurrentEdge = 0; 00355 } 00356 } 00357 00358 00359 /****************************************************************************/ 00360