NIImporter_OpenStreetMap.cpp

Go to the documentation of this file.
00001 /****************************************************************************/
00007 // Importer for networks stored in OpenStreetMap format
00008 /****************************************************************************/
00009 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00010 // Copyright 2001-2010 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 #include "NIImporter_OpenStreetMap.h"
00030 #include <algorithm>
00031 #include <functional>
00032 #include <sstream>
00033 #include <utils/xml/SUMOSAXHandler.h>
00034 #include <utils/common/UtilExceptions.h>
00035 #include <utils/common/TplConvert.h>
00036 #include <utils/common/ToString.h>
00037 #include <utils/common/MsgHandler.h>
00038 #include <netbuild/NBEdge.h>
00039 #include <netbuild/NBEdgeCont.h>
00040 #include <netbuild/NBNode.h>
00041 #include <netbuild/NBNodeCont.h>
00042 #include <netbuild/NBNetBuilder.h>
00043 #include <netbuild/NBOwnTLDef.h>
00044 #include <utils/xml/SUMOXMLDefinitions.h>
00045 #include <utils/geom/GeoConvHelper.h>
00046 #include <utils/geom/GeomConvHelper.h>
00047 #include <utils/options/OptionsCont.h>
00048 #include <utils/common/FileHelpers.h>
00049 #include <utils/xml/XMLSubSys.h>
00050 #include <utils/iodevices/BinaryInputDevice.h>
00051 
00052 #ifdef CHECK_MEMORY_LEAKS
00053 #include <foreign/nvwa/debug_new.h>
00054 #endif // CHECK_MEMORY_LEAKS
00055 
00056 
00057 
00058 // ===========================================================================
00059 // Private classes
00060 // ===========================================================================
00061 
00068 class NIImporter_OpenStreetMap::CompareNodesInPairs: public std::unary_function<
00069             std::pair<int, NIOSMNode*>, bool> {
00070 public:
00077     CompareNodesInPairs(const std::pair<int, NIOSMNode*>& p0) :
00078             myP0(p0) {
00079     }
00088     bool operator()(const std::pair<int, NIOSMNode*>& p1) const {
00089         return (p1.second->lat == myP0.second->lat) && (p1.second->lon
00090                 == myP0.second->lon);
00091     }
00092 
00093 private:
00094     std::pair<int, NIOSMNode*> myP0;
00095 };
00096 
00099 class NIImporter_OpenStreetMap::SubstituteNode: public std::unary_function<
00100             std::pair<std::string, Edge*>, void> {
00101 public:
00111     SubstituteNode(const NIOSMNode* const toSubstitute,
00112                    const NIOSMNode* const substituteWith) :
00113             myToSubstitute(toSubstitute), mySubstituteWith(substituteWith) {
00114     }
00123     void operator()(const std::pair<std::string, Edge*>& p) const {
00124         std::vector<int>& edgeNodes = p.second->myCurrentNodes;
00125         // Substitute nodes
00126         std::replace_if(edgeNodes.begin(), edgeNodes.end(), std::bind2nd(
00127                             std::equal_to<int>(), myToSubstitute->id), mySubstituteWith->id);
00128 
00129         // Remove adjacent duplicates
00130         std::vector<int>::iterator newEnd = std::unique(edgeNodes.begin(),
00131                                             edgeNodes.end());
00132         edgeNodes.erase(newEnd, edgeNodes.end());
00133     }
00134 
00135 private:
00136     const NIOSMNode * const myToSubstitute, * const mySubstituteWith;
00137 };
00138 
00141 class NIImporter_OpenStreetMap::SimilarEdge : public std::unary_function<
00142             std::pair<std::string, Edge*>, bool> {
00143 public:
00148     SimilarEdge(const std::pair<std::string, Edge*>& p0) :
00149             myP0(p0) {
00150     }
00151 
00159     bool operator()(const std::pair<std::string, Edge*>& p1) const {
00160         return
00161             myP0.second->myNoLanes==p1.second->myNoLanes &&
00162             myP0.second->myMaxSpeed==p1.second->myMaxSpeed &&
00163             myP0.second->myHighWayType==p1.second->myHighWayType &&
00164             myP0.second->myIsOneWay==p1.second->myIsOneWay &&
00165             myP0.second->myCurrentNodes==p1.second->myCurrentNodes &&
00166             myP0.second->myCurrentIsRoad==p1.second->myCurrentIsRoad;
00167     }
00168 
00169 private:
00170     std::pair<std::string, Edge*> myP0;
00171 };
00172 
00173 
00174 
00175 // ===========================================================================
00176 // method definitions
00177 // ===========================================================================
00178 // ---------------------------------------------------------------------------
00179 // static methods
00180 // ---------------------------------------------------------------------------
00181 void
00182 NIImporter_OpenStreetMap::loadNetwork(const OptionsCont &oc, NBNetBuilder &nb) {
00183     // check whether the option is set (properly)
00184     if (!oc.isSet("osm-files")) {
00185         return;
00186     }
00187     // preset types
00188     //  for highways
00189     NBTypeCont &tc = nb.getTypeCont();
00190     tc.insert("highway.motorway", 3, (SUMOReal)(160./3.6), 13, SVC_UNKNOWN, true);
00191     tc.insert("highway.motorway_link", 1, (SUMOReal)(80./3.6), 12, SVC_UNKNOWN, true);
00192     tc.insert("highway.trunk", 2, (SUMOReal)(100./3.6), 11);  // !!! 130km/h?
00193     tc.insert("highway.trunk_link", 1, (SUMOReal)(80./3.6), 10);
00194     tc.insert("highway.primary", 2, (SUMOReal)(100./3.6), 9);
00195     tc.insert("highway.primary_link", 1, (SUMOReal)(80./3.6), 8);
00196     tc.insert("highway.secondary", 2, (SUMOReal)(100./3.6), 7);
00197     tc.insert("highway.tertiary", 1, (SUMOReal)(80./3.6), 6);
00198     tc.insert("highway.unclassified", 1, (SUMOReal)(80./3.6), 5);
00199     tc.insert("highway.residential", 1, (SUMOReal)(50./3.6), 4);  // actually, maybe one lane for parking would be nice...
00200     tc.insert("highway.living_street", 1, (SUMOReal)(10./3.6), 3);
00201     tc.insert("highway.service", 1, (SUMOReal)(20./3.6), 2, SVC_DELIVERY);
00202     tc.insert("highway.track", 1, (SUMOReal)(20./3.6), 1);
00203     tc.insert("highway.services", 1, (SUMOReal)(30./3.6), 1);
00204     tc.insert("highway.unsurfaced", 1, (SUMOReal)(30./3.6), 1);  // additional
00205     tc.insert("highway.footway", 1, (SUMOReal)(30./3.6), 1, SVC_PEDESTRIAN);  // additional
00206     tc.insert("highway.pedestrian", 1, (SUMOReal)(30./3.6), 1, SVC_PEDESTRIAN);
00207 
00208     tc.insert("highway.path", 1, (SUMOReal)(10./3.6), 1, SVC_PEDESTRIAN);
00209     tc.insert("highway.bridleway", 1, (SUMOReal)(10./3.6), 1, SVC_PEDESTRIAN);  // no horse stuff
00210     tc.insert("highway.cycleway", 1, (SUMOReal)(20./3.6), 1, SVC_BICYCLE);
00211     tc.insert("highway.footway", 1, (SUMOReal)(10./3.6), 1, SVC_PEDESTRIAN);
00212     tc.insert("highway.step", 1, (SUMOReal)(5./3.6), 1, SVC_PEDESTRIAN);  // additional
00213     tc.insert("highway.steps", 1, (SUMOReal)(5./3.6), 1, SVC_PEDESTRIAN);  // :-) do not run too fast
00214     tc.insert("highway.stairs", 1, (SUMOReal)(5./3.6), 1, SVC_PEDESTRIAN);  // additional
00215     tc.insert("highway.bus_guideway", 1, (SUMOReal)(30./3.6), 1, SVC_BUS);
00216 
00217     //  for railways
00218     tc.insert("railway.rail", 1, (SUMOReal)(30./3.6), 1, SVC_RAIL_FAST);
00219     tc.insert("railway.tram", 1, (SUMOReal)(30./3.6), 1, SVC_CITYRAIL);
00220     tc.insert("railway.light_rail", 1, (SUMOReal)(30./3.6), 1, SVC_LIGHTRAIL);
00221     tc.insert("railway.subway", 1, (SUMOReal)(30./3.6), 1, SVC_CITYRAIL);
00222     tc.insert("railway.preserved", 1, (SUMOReal)(30./3.6), 1, SVC_LIGHTRAIL);
00223     tc.insert("railway.monorail", 1, (SUMOReal)(30./3.6), 1, SVC_LIGHTRAIL);  // rail stuff has to be discussed
00224 
00225 
00226     /* Parse file(s)
00227      * Each file is parsed twice: first for nodes, second for edges. */
00228     std::vector<std::string> files = oc.getStringVector("osm-files");
00229     // load nodes, first
00230     std::map<int, NIOSMNode*> nodes;
00231     NodesHandler nodesHandler(nodes);
00232     for (std::vector<std::string>::const_iterator file=files.begin(); file!=files.end(); ++file) {
00233         // nodes
00234         if (!FileHelpers::exists(*file)) {
00235             MsgHandler::getErrorInstance()->inform("Could not open osm-file '" + *file + "'.");
00236             return;
00237         }
00238         nodesHandler.setFileName(*file);
00239         MsgHandler::getMessageInstance()->beginProcessMsg("Parsing nodes from osm-file '" + *file + "'...");
00240         XMLSubSys::runParser(nodesHandler, *file);
00241         MsgHandler::getMessageInstance()->endProcessMsg("done.");
00242     }
00243     // load edges, then
00244     std::map<std::string, Edge*> edges;
00245     EdgesHandler edgesHandler(nodes, edges);
00246     for (std::vector<std::string>::const_iterator file=files.begin(); file!=files.end(); ++file) {
00247         // edges
00248         edgesHandler.setFileName(*file);
00249         MsgHandler::getMessageInstance()->beginProcessMsg("Parsing edges from osm-file '" + *file + "'...");
00250         XMLSubSys::runParser(edgesHandler, *file);
00251         MsgHandler::getMessageInstance()->endProcessMsg("done.");
00252     }
00253 
00254     /* Remove duplicate nodes with the same coordinates
00255      *
00256      * Without that, insertEdge can fail, if both nodes start
00257      * the shape of an edge. (NBEdge::init calls Position2DVector::push_front
00258      * with the second, which has the same coordinates as the first.) */
00259     MsgHandler::getMessageInstance()->beginProcessMsg("Removing duplicate nodes...");
00260     if (nodes.size() > 1) {
00261         // The algorithm compares a node (it) with the remaining part
00262         // of the list ( [itnext; end()[ ).
00263         for (std::map<int, NIOSMNode*>::iterator it = nodes.begin(), itnext =++nodes.begin(); itnext != nodes.end(); ++it, ++itnext) {
00264             std::map<int, NIOSMNode*>::iterator dupNode = find_if(itnext, nodes.end(), CompareNodesInPairs(*it));
00265             if (dupNode != nodes.end()) {
00266                 MsgHandler::getMessageInstance()->inform("Found duplicate nodes. Substitute " + toString(dupNode->second->id) + " with " + toString(it->second->id));
00267                 for_each(edges.begin(), edges.end(), SubstituteNode(dupNode->second, it->second));
00268             }
00269         }
00270     }
00271     MsgHandler::getMessageInstance()->endProcessMsg(" done.");
00272 
00273     /* Remove duplicate edges with the same shape and attributes */
00274     MsgHandler::getMessageInstance()->beginProcessMsg("Removing duplicate edges...");
00275     if (edges.size() > 1) {
00276         std::set<std::string> toRemove;
00277         for (std::map<std::string, Edge*>::iterator it = edges.begin(), itnext =++edges.begin(); itnext != edges.end(); ++it, ++itnext) {
00278             std::map<std::string, Edge*>::iterator dupEdge = find_if(itnext, edges.end(), SimilarEdge(*it));
00279             while (dupEdge != edges.end()) {
00280                 MsgHandler::getMessageInstance()->inform("Found duplicate edges. Removing " + toString(dupEdge->first));
00281                 toRemove.insert(dupEdge->first);
00282                 dupEdge = find_if(++dupEdge, edges.end(), SimilarEdge(*it));
00283             }
00284         }
00285         for (std::set<std::string>::iterator i=toRemove.begin(); i!=toRemove.end(); ++i) {
00286             std::map<std::string, Edge*>::iterator j=edges.find(*i);
00287             delete(*j).second;
00288             edges.erase(j);
00289         }
00290     }
00291     MsgHandler::getMessageInstance()->endProcessMsg(" done.");
00292 
00293     /* Mark which nodes are used (by edges or traffic lights).
00294      * This is necessary to detect which OpenStreetMap nodes are for
00295      * geometry only */
00296     std::map<int, int> nodeUsage;
00297     // Mark which nodes are used by edges (begin and end)
00298     for (std::map<std::string, Edge*>::const_iterator i = edges.begin(); i != edges.end(); ++i) {
00299         Edge *e = (*i).second;
00300         if (!e->myCurrentIsRoad) {
00301             continue;
00302         }
00303         for (std::vector<int>::const_iterator j = e->myCurrentNodes.begin(); j != e->myCurrentNodes.end(); ++j) {
00304             if (nodeUsage.find(*j)==nodeUsage.end()) {
00305                 nodeUsage[*j] = 0;
00306             }
00307             nodeUsage[*j] = nodeUsage[*j] + 1;
00308         }
00309     }
00310     // Mark which nodes are used by traffic lights
00311     for (std::map<int, NIOSMNode*>::const_iterator nodesIt = nodes.begin(); nodesIt != nodes.end(); ++nodesIt) {
00312         if (nodesIt->second->tlsControlled) {
00313             // If the key is not found in the map, the value is automatically
00314             // initialized with 0.
00315             nodeUsage[nodesIt->first] += 1;
00316         }
00317     }
00318     /* Instantiate edges
00319      * Only those nodes in the middle of an edge which are used by more than
00320      * one edge are instantiated. Other nodes are considered as geometry nodes. */
00321     NBNodeCont &nc = nb.getNodeCont();
00322     NBEdgeCont &ec = nb.getEdgeCont();
00323     NBTrafficLightLogicCont &tlsc = nb.getTLLogicCont();
00324     for (std::map<std::string, Edge*>::iterator i=edges.begin(); i!=edges.end(); ++i) {
00325         Edge *e = (*i).second;
00326         if (!e->myCurrentIsRoad) {
00327             continue;
00328         }
00329         // build nodes;
00330         //  the from- and to-nodes must be built in any case
00331         //  the geometry nodes are only built if more than one edge references them
00332         NBNode *currentFrom = insertNodeChecking(*e->myCurrentNodes.begin(), nodes, nc, tlsc);
00333         NBNode *last = insertNodeChecking(*(e->myCurrentNodes.end()-1), nodes, nc, tlsc);
00334         int running = 0;
00335         std::vector<int> passed;
00336         for (std::vector<int>::iterator j=e->myCurrentNodes.begin(); j!=e->myCurrentNodes.end(); ++j) {
00337             passed.push_back(*j);
00338             if (nodeUsage[*j] > 1 && j != e->myCurrentNodes.end()-1 && j != e->myCurrentNodes.begin()) {
00339                 NBNode *currentTo = insertNodeChecking(*j, nodes, nc, tlsc);
00340                 insertEdge(e, running, currentFrom, currentTo, passed, nodes, nc, ec, tc);
00341                 currentFrom = currentTo;
00342                 running++;
00343                 passed.clear();
00344             }
00345         }
00346         if (running==0) {
00347             running = -1;
00348         }
00349         insertEdge(e, running, currentFrom, last, passed, nodes, nc, ec, tc);
00350     }
00351     /* Clean up */
00352     // delete nodes
00353     for (std::map<int, NIOSMNode*>::const_iterator i=nodes.begin(); i!=nodes.end(); ++i) {
00354         delete(*i).second;
00355     }
00356     // delete edges
00357     for (std::map<std::string, Edge*>::iterator i=edges.begin(); i!=edges.end(); ++i) {
00358         delete(*i).second;
00359     }
00360 }
00361 
00362 
00363 NBNode *
00364 NIImporter_OpenStreetMap::insertNodeChecking(int id, const std::map<int, NIOSMNode*> &osmNodes, NBNodeCont &nc,
00365         NBTrafficLightLogicCont &tlsc) throw(ProcessError) {
00366     NBNode *from = nc.retrieve(toString(id));
00367     if (from==0) {
00368         NIOSMNode *n = osmNodes.find(id)->second;
00369         Position2D pos(n->lon, n->lat);
00370         if (!GeoConvHelper::x2cartesian(pos, true, n->lon, n->lat)) {
00371             MsgHandler::getErrorInstance()->inform("Unable to project coordinates for node " + toString(id) + ".");
00372             delete from;
00373             return 0;
00374         }
00375         from = new NBNode(toString(id), pos);
00376         if (!nc.insert(from)) {
00377             MsgHandler::getErrorInstance()->inform("Could not insert node '" + toString(id) + "').");
00378             delete from;
00379             return 0;
00380         }
00381         if (n->tlsControlled) {
00382             // ok, this node is a traffic light node where no other nodes
00383             //  participate
00384             NBOwnTLDef *tlDef = new NBOwnTLDef(toString(id), from);
00385             if (!tlsc.insert(tlDef)) {
00386                 // actually, nothing should fail here
00387                 delete tlDef;
00388                 throw ProcessError("Could not allocate tls '" + toString(id) + "'.");
00389             }
00390         }
00391     }
00392     return from;
00393 }
00394 
00395 
00396 void
00397 NIImporter_OpenStreetMap::insertEdge(Edge *e, int index, NBNode *from, NBNode *to,
00398                                      const std::vector<int> &passed, const std::map<int, NIOSMNode*> &osmNodes,
00399                                      NBNodeCont &nc, NBEdgeCont &ec, NBTypeCont &tc) throw(ProcessError) {
00400     // patch the id
00401     std::string id = e->id;
00402     if (index>=0) {
00403         id = id + "#" + toString(index);
00404     }
00405     // convert the shape
00406     Position2DVector shape;
00407     for (std::vector<int>::const_iterator i=passed.begin(); i!=passed.end(); ++i) {
00408         NIOSMNode *n = osmNodes.find(*i)->second;
00409         Position2D pos(n->lon, n->lat);
00410         if (!GeoConvHelper::x2cartesian(pos, true, n->lon, n->lat)) {
00411             throw ProcessError("Unable to project coordinates for edge " + id + ".");
00412         }
00413         shape.push_back_noDoublePos(pos);
00414     }
00415     if (!tc.knows(e->myHighWayType)) {
00416         // we do not know the type -> something else, ignore
00417         return;
00418     }
00419     // otherwise it is not an edge and will be ignored
00420     int noLanes = tc.getNoLanes(e->myHighWayType);
00421     SUMOReal speed = tc.getSpeed(e->myHighWayType);
00422     bool defaultsToOneWay = tc.getIsOneWay(e->myHighWayType);
00423     std::vector<SUMOVehicleClass> allowedClasses = tc.getAllowedClasses(e->myHighWayType);
00424     std::vector<SUMOVehicleClass> disallowedClasses = tc.getDisallowedClasses(e->myHighWayType);
00425     // check directions
00426     bool addSecond = true;
00427     if (e->myIsOneWay=="true"||e->myIsOneWay=="yes"||e->myIsOneWay=="1"||(defaultsToOneWay && e->myIsOneWay!="no" && e->myIsOneWay!="false" && e->myIsOneWay!="0")) {
00428         addSecond = false;
00429     }
00430     // if we had been able to extract the number of lanes, override the highway type default
00431     if (e->myNoLanes >= 0) {
00432         if (!addSecond) {
00433             noLanes = e->myNoLanes;
00434         } else {
00435             noLanes = e->myNoLanes / 2;
00436         }
00437     }
00438     // if we had been able to extract the maximum speed, override the highway type default
00439     if (e->myMaxSpeed >= 0) {
00440         speed = (SUMOReal)(e->myMaxSpeed / 3.6);
00441     }
00442 
00443     if (noLanes!=0&&speed!=0) {
00444         if (e->myIsOneWay!=""&&e->myIsOneWay!="false"&&e->myIsOneWay!="no"&&e->myIsOneWay!="true"&&e->myIsOneWay!="yes"&&e->myIsOneWay!="-1"&&e->myIsOneWay!="1") {
00445             WRITE_WARNING("New value for oneway found: " + e->myIsOneWay);
00446         }
00447         NBEdge::LaneSpreadFunction lsf = addSecond ? NBEdge::LANESPREAD_RIGHT : NBEdge::LANESPREAD_CENTER;
00448         if (e->myIsOneWay!="-1") {
00449             NBEdge *nbe = new NBEdge(id, from, to, e->myHighWayType, speed, noLanes, tc.getPriority(e->myHighWayType), shape, lsf);
00450             nbe->setVehicleClasses(allowedClasses, disallowedClasses);
00451             if (!ec.insert(nbe)) {
00452                 delete nbe;
00453                 throw ProcessError("Could not add edge '" + id + "'.");
00454             }
00455         }
00456         if (addSecond) {
00457             if (e->myIsOneWay!="-1") {
00458                 id = "-" + id;
00459             }
00460             NBEdge *nbe = new NBEdge(id, to, from, e->myHighWayType, speed, noLanes, tc.getPriority(e->myHighWayType), shape.reverse(), lsf);
00461             nbe->setVehicleClasses(allowedClasses, disallowedClasses);
00462             if (!ec.insert(nbe)) {
00463                 delete nbe;
00464                 throw ProcessError("Could not add edge '-" + id + "'.");
00465             }
00466         }
00467     }
00468 }
00469 
00470 
00471 // ---------------------------------------------------------------------------
00472 // definitions of NIImporter_OpenStreetMap::NodesHandler-methods
00473 // ---------------------------------------------------------------------------
00474 NIImporter_OpenStreetMap::NodesHandler::NodesHandler(std::map<int, NIOSMNode*> &toFill) throw()
00475         : SUMOSAXHandler("osm - file"), myToFill(toFill), myLastNodeID(-1), myIsInValidNodeTag(false), myHierarchyLevel(0) {}
00476 
00477 
00478 NIImporter_OpenStreetMap::NodesHandler::~NodesHandler() throw() {}
00479 
00480 
00481 void
00482 NIImporter_OpenStreetMap::NodesHandler::myStartElement(SumoXMLTag element, const SUMOSAXAttributes &attrs) throw(ProcessError) {
00483     ++myHierarchyLevel;
00484     if (element == SUMO_TAG_NODE) {
00485         if (myHierarchyLevel != 2) {
00486             MsgHandler::getErrorInstance()->inform("Node element on wrong XML hierarchy level.");
00487             return;
00488         }
00489         bool ok = true;
00490         int id = attrs.getIntReporting(SUMO_ATTR_ID, "node", 0, ok);
00491         std::string action = attrs.hasAttribute("action") ? attrs.getStringSecure("action", "") : "";
00492         if (action=="delete") {
00493             return;
00494         }
00495         if (!ok) {
00496             return;
00497         }
00498         myLastNodeID = -1;
00499         if (myToFill.find(id) == myToFill.end()) {
00500             myLastNodeID = id;
00501             // assume we are loading multiple files...
00502             //  ... so we won't report duplicate nodes
00503             bool ok = true;
00504             double tlat, tlon;
00505             std::istringstream lon(attrs.getStringReporting(SUMO_ATTR_LON, "node", toString(id).c_str(), ok));
00506             if (!ok) {
00507                 return;
00508             }
00509             lon >> tlon;
00510             if (lon.fail()) {
00511                 MsgHandler::getErrorInstance()->inform("Node's '" + toString(id) + "' lon information is not numeric.");
00512                 return;
00513             }
00514             std::istringstream lat(attrs.getStringReporting(SUMO_ATTR_LAT, "node", toString(id).c_str(), ok));
00515             if (!ok) {
00516                 return;
00517             }
00518             lat >> tlat;
00519             if (lat.fail()) {
00520                 MsgHandler::getErrorInstance()->inform("Node's '" + toString(id) + "' lat information is not numeric.");
00521                 return;
00522             }
00523             NIOSMNode *toAdd = new NIOSMNode();
00524             toAdd->id = id;
00525             toAdd->tlsControlled = false;
00526             toAdd->lat = tlat;
00527             toAdd->lon = tlon;
00528             myToFill[toAdd->id] = toAdd;
00529             myIsInValidNodeTag = true;
00530         }
00531     }
00532     if (element == SUMO_TAG_TAG && myIsInValidNodeTag) {
00533         if (myHierarchyLevel != 3) {
00534             MsgHandler::getErrorInstance()->inform("Tag element on wrong XML hierarchy level.");
00535             return;
00536         }
00537         bool ok = true;
00538         std::string key = attrs.getStringReporting(SUMO_ATTR_K, "tag", toString(myLastNodeID).c_str(), ok);
00539         std::string value = attrs.getStringReporting(SUMO_ATTR_V, "tag", toString(myLastNodeID).c_str(), ok);
00540         if (!ok) {
00541             return;
00542         }
00543         if (key == "highway" && value.find("traffic_signal") != std::string::npos) {
00544             myToFill[myLastNodeID]->tlsControlled = true;
00545         }
00546     }
00547 }
00548 
00549 
00550 void
00551 NIImporter_OpenStreetMap::NodesHandler::myEndElement(SumoXMLTag element) throw(ProcessError) {
00552     if (element==SUMO_TAG_NODE && myHierarchyLevel == 2) {
00553         myLastNodeID = -1;
00554         myIsInValidNodeTag = false;
00555     }
00556     --myHierarchyLevel;
00557 }
00558 
00559 
00560 // ---------------------------------------------------------------------------
00561 // definitions of NIImporter_OpenStreetMap::EdgesHandler-methods
00562 // ---------------------------------------------------------------------------
00563 NIImporter_OpenStreetMap::EdgesHandler::EdgesHandler(
00564     const std::map<int, NIOSMNode*> &osmNodes,
00565     std::map<std::string, Edge*> &toFill) throw()
00566         : SUMOSAXHandler("osm - file"),
00567         myOSMNodes(osmNodes), myEdgeMap(toFill) {
00568 }
00569 
00570 
00571 NIImporter_OpenStreetMap::EdgesHandler::~EdgesHandler() throw() {
00572 }
00573 
00574 
00575 void
00576 NIImporter_OpenStreetMap::EdgesHandler::myStartElement(SumoXMLTag element,
00577         const SUMOSAXAttributes &attrs) throw(ProcessError) {
00578     myParentElements.push_back(element);
00579     // parse "way" elements
00580     if (element==SUMO_TAG_WAY) {
00581         bool ok = true;
00582         std::string id = attrs.getStringReporting(SUMO_ATTR_ID, "way", 0, ok);
00583         std::string action = attrs.hasAttribute("action") ? attrs.getStringSecure("action", "") : "";
00584         if (action=="delete") {
00585             myCurrentEdge = 0;
00586             return;
00587         }
00588         if (!ok) {
00589             myCurrentEdge = 0;
00590             return;
00591         }
00592         myCurrentEdge = new Edge();
00593         myCurrentEdge->id = id;
00594         myCurrentEdge->myNoLanes = -1;
00595         myCurrentEdge->myMaxSpeed = -1;
00596         myCurrentEdge->myCurrentIsRoad = false;
00597     }
00598     // parse "nd" (node) elements
00599     if (element==SUMO_TAG_ND) {
00600         bool ok = true;
00601         int ref = attrs.getIntReporting(SUMO_ATTR_REF, "nd", 0, ok);
00602         if (ok) {
00603             if (myOSMNodes.find(ref)==myOSMNodes.end()) {
00604                 MsgHandler::getErrorInstance()->inform("The referenced geometry information (ref='" + toString(ref) + "') is not known");
00605                 return;
00606             }
00607             myCurrentEdge->myCurrentNodes.push_back(ref);
00608         }
00609     }
00610     // parse values
00611     if (element==SUMO_TAG_TAG&&myParentElements.size()>2&&myParentElements[myParentElements.size()-2]==SUMO_TAG_WAY) {
00612         if (myCurrentEdge==0) {
00613             return;
00614         }
00615         bool ok = true;
00616         std::string key = attrs.getStringReporting(SUMO_ATTR_K, "way", toString(myCurrentEdge->id).c_str(), ok);
00617         std::string value = attrs.getStringReporting(SUMO_ATTR_V, "way", toString(myCurrentEdge->id).c_str(), ok);
00618         if (!ok) {
00619             return;
00620         }
00621         if (key=="highway"||key=="railway") {
00622             myCurrentEdge->myHighWayType = key + "." + value;
00623             myCurrentEdge->myCurrentIsRoad = true;
00624         } else if (key=="lanes") {
00625             try {
00626                 myCurrentEdge->myNoLanes = TplConvert<char>::_2int(value.c_str());
00627             } catch (NumberFormatException &) {
00628                 MsgHandler::getErrorInstance()->inform("Value of key '" + key + "' is not numeric ('" + value + "') in edge '" + myCurrentEdge->id + "'.");
00629             }
00630         } else if (key=="maxspeed") {
00631             try {
00632                 myCurrentEdge->myMaxSpeed = TplConvert<char>::_2SUMOReal(value.c_str());
00633             } catch (NumberFormatException &) {
00634                 WRITE_WARNING("Value of key '" + key + "' is not numeric ('" + value + "') in edge '" + myCurrentEdge->id + "'.");
00635             }
00636         } else if (key=="junction") {
00637             if ((value == "roundabout") && (myCurrentEdge->myIsOneWay == "")) {
00638                 myCurrentEdge->myIsOneWay = "yes";
00639             }
00640         } else if (key=="oneway") {
00641             myCurrentEdge->myIsOneWay = value;
00642         }
00643     }
00644 }
00645 
00646 
00647 void
00648 NIImporter_OpenStreetMap::EdgesHandler::myEndElement(SumoXMLTag element) throw(ProcessError) {
00649     myParentElements.pop_back();
00650     if (element==SUMO_TAG_WAY) {
00651         if (myCurrentEdge!=0 && myCurrentEdge->myCurrentIsRoad) {
00652             myEdgeMap[myCurrentEdge->id] = myCurrentEdge;
00653         } else {
00654             delete myCurrentEdge;
00655         }
00656         myCurrentEdge = 0;
00657     }
00658 }
00659 
00660 
00661 
00662 
00663 /****************************************************************************/
00664 

Generated on Wed May 5 00:06:34 2010 for Sumo - Simulation of Urban MObility by  doxygen 1.5.6