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