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/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 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines