NIImporter_OpenStreetMap Class Reference

#include <NIImporter_OpenStreetMap.h>


Detailed Description

Importer for networks stored in OpenStreetMap format.

Definition at line 59 of file NIImporter_OpenStreetMap.h.


Static Public Member Functions

static void loadNetwork (const OptionsCont &oc, NBNetBuilder &nb)
 Loads content of the optionally given OSM file.

Static Private Member Functions

static void insertEdge (Edge *e, int index, NBNode *from, NBNode *to, const std::vector< int > &passed, const std::map< int, NIOSMNode * > &osmNodes, NBNodeCont &nc, NBEdgeCont &ec, NBTypeCont &tc) throw (ProcessError)
 Builds an NBEdge.
static NBNodeinsertNodeChecking (int id, const std::map< int, NIOSMNode * > &osmNodes, NBNodeCont &nc, NBTrafficLightLogicCont &tlsc) throw (ProcessError)
 Builds an NBNode.

Data Structures

class  CompareNodesInPairs
 Functor which compares two NIOSMNodes according to their coordinates. More...
struct  Edge
 An internal definition of a loaded edge. More...
class  EdgesHandler
 A class which extracts OSM-edges from a parsed OSM-file. More...
struct  NIOSMNode
 An internal representation of an OSM-node. More...
class  NodesHandler
 A class which extracts OSM-nodes from a parsed OSM-file. More...
class  SimilarEdge
 Functor which compares two Edges according to all values but id. More...
class  SubstituteNode
 A functor to substitute a node in the node list of an Edge. More...

Member Function Documentation

void NIImporter_OpenStreetMap::insertEdge ( Edge e,
int  index,
NBNode from,
NBNode to,
const std::vector< int > &  passed,
const std::map< int, NIOSMNode * > &  osmNodes,
NBNodeCont nc,
NBEdgeCont ec,
NBTypeCont tc 
) throw (ProcessError) [static, private]

Builds an NBEdge.

Parameters:
[in] e The definition of the edge
[in] index The index of the edge (in the case it is split along her nodes)
[in] from The origin node of the edge
[in] to The destination node of the edge
[in] passed The list of passed nodes (geometry information)
[in] osmNodes Container of node definitions for getting information about nodes from
[in] nc The container for built nodes
[in,out] The edge container to add the built edge to
[in] tc The type container to get information about the edge from
Exceptions:
ProcessError If the edge could not be added to the container

Definition at line 397 of file NIImporter_OpenStreetMap.cpp.

References NBEdge::LANESPREAD_CENTER, NBEdge::LANESPREAD_RIGHT, NIImporter_OpenStreetMap::NIOSMNode::lat, NIImporter_OpenStreetMap::NIOSMNode::lon, Position2DVector::push_back_noDoublePos(), Position2DVector::reverse(), NBEdge::setVehicleClasses(), SUMOReal, toString(), WRITE_WARNING, and GeoConvHelper::x2cartesian().

Referenced by loadNetwork().

00399                                                                                                          {
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 }

NBNode * NIImporter_OpenStreetMap::insertNodeChecking ( int  id,
const std::map< int, NIOSMNode * > &  osmNodes,
NBNodeCont nc,
NBTrafficLightLogicCont tlsc 
) throw (ProcessError) [static, private]

Builds an NBNode.

If a node with the given id is already known, nothing is done. Otherwise, the position and other information of the node is retrieved from the given node map, the node is built and added to the given node container. If the node is controlled by a tls, the according tls is built and added to the tls container.

Parameters:
[in] id The id of the node to build
[in] osmNodes Map of node ids to information about these
[in,out] nc The node container to add the built node to
[in,out] tlsc The traffic lights logic container to add the built tls to
Returns:
The built/found node
Exceptions:
ProcessError If the tls could not be added to the container

Definition at line 364 of file NIImporter_OpenStreetMap.cpp.

References MsgHandler::getErrorInstance(), MsgHandler::inform(), NIImporter_OpenStreetMap::NIOSMNode::lat, NIImporter_OpenStreetMap::NIOSMNode::lon, NIImporter_OpenStreetMap::NIOSMNode::tlsControlled, toString(), and GeoConvHelper::x2cartesian().

Referenced by loadNetwork().

00365                                                            {
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 }

void NIImporter_OpenStreetMap::loadNetwork ( const OptionsCont oc,
NBNetBuilder nb 
) [static]

Loads content of the optionally given OSM file.

If the option "osm-files" is set, the file(s) stored therein is read and the network definition stored therein is stored within the given network builder.

If the option "osm-files" is not set, this method simply returns.

Parameters:
[in] oc The options to use
[in] nb The network builder to fill

Definition at line 182 of file NIImporter_OpenStreetMap.cpp.

References MsgHandler::beginProcessMsg(), MsgHandler::endProcessMsg(), FileHelpers::exists(), NBNetBuilder::getEdgeCont(), MsgHandler::getErrorInstance(), MsgHandler::getMessageInstance(), NBNetBuilder::getNodeCont(), OptionsCont::getStringVector(), NBNetBuilder::getTLLogicCont(), NBNetBuilder::getTypeCont(), MsgHandler::inform(), NBTypeCont::insert(), insertEdge(), insertNodeChecking(), OptionsCont::isSet(), NIImporter_OpenStreetMap::Edge::myCurrentIsRoad, NIImporter_OpenStreetMap::Edge::myCurrentNodes, XMLSubSys::runParser(), GenericSAXHandler::setFileName(), SUMOReal, SVC_BICYCLE, SVC_BUS, SVC_CITYRAIL, SVC_DELIVERY, SVC_LIGHTRAIL, SVC_PEDESTRIAN, SVC_RAIL_FAST, SVC_UNKNOWN, and toString().

Referenced by NILoader::load().

00182                                                                              {
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 }


The documentation for this class was generated from the following files:

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