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