SUMO - Simulation of Urban MObility

PCLoaderOSM.cpp

Go to the documentation of this file.
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 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines