Path: blob/main/src/netimport/NIImporter_OpenStreetMap.h
169666 views
/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.3// This program and the accompanying materials are made available under the4// terms of the Eclipse Public License 2.0 which is available at5// https://www.eclipse.org/legal/epl-2.0/6// This Source Code may also be made available under the following Secondary7// Licenses when the conditions for such availability set forth in the Eclipse8// Public License 2.0 are satisfied: GNU General Public License, version 29// or later which is available at10// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html11// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later12/****************************************************************************/13/// @file NIImporter_OpenStreetMap.h14/// @author Daniel Krajzewicz15/// @author Jakob Erdmann16/// @author Michael Behrisch17/// @author Walter Bamberger18/// @author Gregor Laemmel19/// @date Mon, 14.04.200820///21// Importer for networks stored in OpenStreetMap format22/****************************************************************************/23#pragma once24#include <config.h>2526#include <string>27#include <map>28#include <utils/xml/SUMOSAXHandler.h>29#include <utils/common/UtilExceptions.h>30#include <utils/common/Parameterised.h>31#include <netbuild/NBPTPlatform.h>323334// ===========================================================================35// class declarations36// ===========================================================================37class NBEdge;38class NBEdgeCont;39class NBNetBuilder;40class NBNode;41class NBNodeCont;42class NBTrafficLightLogicCont;43class NBTypeCont;44class OptionsCont;454647// ===========================================================================48// class definitions49// ===========================================================================50/**51* @class NIImporter_OpenStreetMap52* @brief Importer for networks stored in OpenStreetMap format53*54*/55class NIImporter_OpenStreetMap {56public:57/** @brief Loads content of the optionally given OSM file58*59* If the option "osm-files" is set, the file(s) stored therein is read and60* the network definition stored therein is stored within the given network61* builder.62*63* If the option "osm-files" is not set, this method simply returns.64*65* @param[in] oc The options to use66* @param[in, out] nb The network builder to fill67*/68static void loadNetwork(const OptionsCont& oc, NBNetBuilder& nb);6970protected:7172/** @enum CycleWayType73* @brief details on the kind of cycleway along this road74*/75enum WayType {76WAY_NONE = 0,77WAY_FORWARD = 1,78WAY_BACKWARD = 2,79WAY_BOTH = WAY_FORWARD | WAY_BACKWARD,80WAY_UNKNOWN = 481};8283/** @brief An internal representation of an OSM-node84*/85struct NIOSMNode : public Parameterised {86NIOSMNode(long long int _id, double _lon, double _lat)87:88id(_id), lon(_lon), lat(_lat), ele(0.),89tlsControlled(false),90pedestrianCrossing(false),91railwayCrossing(false),92railwaySignal(false),93railwayBufferStop(false),94ptStopPosition(false), ptStopLength(0), name(""),95permissions(SVC_IGNORING),96positionMeters(std::numeric_limits<double>::max()),97myRailDirection(WAY_UNKNOWN),98node(nullptr) { }99100/// @brief The node's id101const long long int id;102/// @brief The longitude the node is located at103const double lon;104/// @brief The latitude the node is located at105const double lat;106/// @brief The elevation of this node107double ele;108/// @brief Whether this is a tls controlled junction109bool tlsControlled;110/// @brief Whether this is a pedestrian crossing111bool pedestrianCrossing;112/// @brief Whether this is a railway crossing113bool railwayCrossing;114/// @brief Whether this is a railway (main) signal115bool railwaySignal;116/// @brief Whether this is a railway buffer stop117bool railwayBufferStop;118/// @brief Whether this is a public transport stop position119bool ptStopPosition;120/// @brief The length of the pt stop121double ptStopLength;122/// @brief The name of the node123std::string name;124/// @brief type of pt stop125SVCPermissions permissions;126/// @brief kilometrage/mileage127std::string position;128/// @brief position converted to m (using highest precision available)129double positionMeters;130/// @brief Information about the direction(s) of railway usage131WayType myRailDirection;132/// @brief the NBNode that was instantiated133NBNode* node;134135private:136/// invalidated assignment operator137NIOSMNode& operator=(const NIOSMNode& s) = delete;138139140};141142public:143/// @brief translate osm transport designations into sumo vehicle class144static SUMOVehicleClass interpretTransportType(const std::string& type, NIOSMNode* toSet = nullptr);145146protected:147148149enum ParkingType {150PARKING_NONE = 0,151PARKING_LEFT = 1,152PARKING_RIGHT = 2,153PARKING_BOTH = WAY_FORWARD | WAY_BACKWARD,154PARKING_UNKNOWN = 4,155PARKING_FORBIDDEN = 8,156PARKING_PERPENDICULAR = 16,157PARKING_DIAGONAL = 32158};159160enum ChangeType {161CHANGE_YES = 0,162CHANGE_NO_LEFT = 1,163CHANGE_NO_RIGHT = 2,164CHANGE_NO = 3165};166167/** @brief An internal definition of a loaded edge168*/169class Edge : public Parameterised {170public:171explicit Edge(long long int _id) :172id(_id), myNoLanes(-1), myNoLanesForward(0),173myMaxSpeed(MAXSPEED_UNGIVEN),174myMaxSpeedBackward(MAXSPEED_UNGIVEN),175myExtraAllowed(0),176myExtraDisallowed(0),177myCyclewayType(WAY_UNKNOWN), // building of extra lane depends on bikelaneWidth of loaded typemap178myBuswayType(WAY_NONE), // buslanes are always built when declared179mySidewalkType(WAY_UNKNOWN), // building of extra lanes depends on sidewalkWidth of loaded typemap180myRailDirection(WAY_UNKNOWN), // store direction(s) of railway usage181myParkingType(PARKING_NONE), // parking areas exported optionally182myChangeForward(CHANGE_YES),183myChangeBackward(CHANGE_YES),184myLayer(0), // layer is non-zero only in conflict areas185myCurrentIsRoad(false),186myAmInRoundabout(false),187myWidth(-1)188{ }189190virtual ~Edge() {}191192/// @brief The edge's id193const long long int id;194/// @brief The edge's street name195std::string streetName;196/// @brief The edge's track name197std::string ref;198/// @brief number of lanes, or -1 if unknown199int myNoLanes;200/// @brief number of lanes in forward direction or 0 if unknown, negative if backwards lanes are meant201int myNoLanesForward;202/// @brief maximum speed in km/h, or MAXSPEED_UNGIVEN203double myMaxSpeed;204/// @brief maximum speed in km/h, or MAXSPEED_UNGIVEN205double myMaxSpeedBackward;206/// @brief Extra permissions added from tags instead of highway type207SVCPermissions myExtraAllowed;208/// @brief Extra permissions prohibited from tags instead of highway type209SVCPermissions myExtraDisallowed;210/// @brief The type, stored in "highway" key211std::string myHighWayType;212/// @brief Information whether this is an one-way road213std::string myIsOneWay;214/// @brief Information about the kind of cycleway along this road215WayType myCyclewayType;216/// @brief Information about the kind of busway along this road217WayType myBuswayType;218/// @brief Information about the kind of sidwalk along this road219WayType mySidewalkType;220/// @brief Information about the direction(s) of railway usage221WayType myRailDirection;222/// @brief Information about road-side parking223int myParkingType;224/// @brief Information about change prohibitions (forward direction225int myChangeForward;226/// @brief Information about change prohibitions (backward direction227int myChangeBackward;228/// @brief (optional) information about whether the forward lanes are designated to some SVCs229std::vector<bool> myDesignatedLaneForward;230/// @brief (optional) information about whether the backward lanes are designated to some SVCs231std::vector<bool> myDesignatedLaneBackward;232/// @brief (optional) information about additional allowed SVCs on forward lane(s)233std::vector<SVCPermissions> myAllowedLaneForward;234/// @brief (optional) information about additional allowed SVCs on backward lane(s)235std::vector<SVCPermissions> myAllowedLaneBackward;236/// @brief (optional) information about additional disallowed SVCs on forward lane(s)237std::vector<SVCPermissions> myDisallowedLaneForward;238/// @brief (optional) information about additional disallowed SVCs on backward lane(s)239std::vector<SVCPermissions> myDisallowedLaneBackward;240/// @brief Information about the relative z-ordering of ways241int myLayer;242/// @brief The list of nodes this edge is made of243std::vector<long long int> myCurrentNodes;244/// @brief Information whether this is a road245bool myCurrentIsRoad;246/// @brief Information whether this road is part of a roundabout247bool myAmInRoundabout;248/// @brief Additionally tagged information249std::map<std::string, std::string> myExtraTags;250/// @brief turning direction (arrows printed on the road)251std::vector<int> myTurnSignsForward;252std::vector<int> myTurnSignsBackward;253/// @brief Information on lane width254std::vector<double> myWidthLanesForward;255std::vector<double> myWidthLanesBackward;256double myWidth;257258private:259/// invalidated assignment operator260Edge& operator=(const Edge& s) = delete;261};262263264NIImporter_OpenStreetMap();265266~NIImporter_OpenStreetMap();267268void load(const OptionsCont& oc, NBNetBuilder& nb);269270private:271/** @brief Functor which compares two NIOSMNodes according272* to their coordinates273*/274class CompareNodes {275public:276bool operator()(const NIOSMNode* n1, const NIOSMNode* n2) const {277return (n1->lat > n2->lat) || (n1->lat == n2->lat && n1->lon > n2->lon);278}279};280281282/// @brief The separator within newly created compound type names283static const std::string compoundTypeSeparator;284285class CompareEdges;286287/** @brief the map from OSM node ids to actual nodes288* @note: NIOSMNodes may appear multiple times due to substition289*/290std::map<long long int, NIOSMNode*> myOSMNodes;291292/// @brief the set of unique nodes used in NodesHandler, used when freeing memory293std::set<NIOSMNode*, CompareNodes> myUniqueNodes;294295296/** @brief the map from OSM way ids to edge objects */297std::map<long long int, Edge*> myEdges;298299/** @brief the map from OSM way ids to platform shapes */300std::map<long long int, Edge*> myPlatformShapes;301302/// @brief The compounds types that do not contain known types303std::set<std::string> myUnusableTypes;304305/// @brief The compound types that have already been mapped to other known types306std::map<std::string, std::string> myKnownCompoundTypes;307308/// @brief import lane specific access restrictions309bool myImportLaneAccess;310311/// @brief import sidewalks312bool myImportSidewalks;313314/// @brief import sidewalks315bool myOnewayDualSidewalk;316317/// @brief import bike path specific permissions and directions318bool myImportBikeAccess;319320/// @brief import crossings321bool myImportCrossings;322323/// @brief import turning signals (turn:lanes) to guide connection building324bool myImportTurnSigns;325326/// @brief whether edges should carry information on the use of typemap defaults327bool myAnnotateDefaults;328329/// @brief whether additional way and node attributes shall be imported330static bool myAllAttributes;331332/// @brief extra attributes to import333static std::set<std::string> myExtraAttributes;334335/** @brief Builds an NBNode336*337* If a node with the given id is already known, nothing is done.338* Otherwise, the position and other information of the node is retrieved from the339* given node map, the node is built and added to the given node container.340* If the node is controlled by a tls, the according tls is built and added341* to the tls container.342* @param[in] id The id of the node to build343* @param[in] osmNodes Map of node ids to information about these344* @param[in, out] nc The node container to add the built node to345* @param[in, out] tlsc The traffic lights logic container to add the built tls to346* @return The built/found node347* @exception ProcessError If the tls could not be added to the container348*/349NBNode* insertNodeChecking(long long int id, NBNodeCont& nc, NBTrafficLightLogicCont& tlsc);350351352/** @brief Builds an NBEdge353*354* @param[in] e The definition of the edge355* @param[in] index The index of the edge (in the case it is split along her nodes)356* @param[in] from The origin node of the edge357* @param[in] to The destination node of the edge358* @param[in] passed The list of passed nodes (geometry information)359* @param[in] osmNodes Container of node definitions for getting information about nodes from360* @param[in, out] The NetBuilder instance361* @param[in] first The first node of the way362* @param[in] last The last node of the way363* @return the new index if the edge is split364* @exception ProcessError If the edge could not be added to the container365*/366int insertEdge(Edge* e, int index, NBNode* from, NBNode* to,367const std::vector<long long int>& passed, NBNetBuilder& nb,368const NBNode* first, const NBNode* last);369370/// @brief reconstruct elevation from layer info371void reconstructLayerElevation(double layerElevation, NBNetBuilder& nb);372373/// @brief collect neighboring nodes with their road distance and maximum between-speed. Search does not continue beyond knownElevation-nodes374std::map<NBNode*, std::pair<double, double> >375getNeighboringNodes(NBNode* node, double maxDist, const std::set<NBNode*>& knownElevation);376377/// @brief check whether the type is known or consists of known type compounds. return empty string otherwise378std::string usableType(const std::string& type, const std::string& id, NBTypeCont& tc);379380/// @brief extend kilometrage data for all nodes along railway381void extendRailwayDistances(Edge* e, NBTypeCont& tc);382383/// @brief read distance value from node and return value in m384static double interpretDistance(NIOSMNode* node);385386protected:387static const double MAXSPEED_UNGIVEN;388static const long long int INVALID_ID;389390static void applyChangeProhibition(NBEdge* e, int changeProhibition);391/// Applies lane use information from `nie` to `e`. Uses the member values392/// `myLaneAllowedForward`, `myLaneDisallowedForward` and `myLaneDesignatedForward`393/// or the respective backward values to determine the ultimate lane uses.394/// When a value of `e->myLaneDesignatedForward/Backward` is `true`, all permissions for the corresponding395/// lane will be deleted before adding permissions from `e->myLaneAllowedForward/Backward`.396/// SVCs from `e->myLaneAllowedForward/Backward` will be added to the existing permissions (for each lane).397/// SVCs from `e->myLaneDisallowedForward/Backward` will be subtracted from the existing permissions.398/// @brief Applies lane use information from `nie` to `e`.399/// @param e The NBEdge that the new information will be written to.400/// @param nie Ths Edge that the information comes from.401void applyLaneUse(NBEdge* e, NIImporter_OpenStreetMap::Edge* nie, const bool forward);402403static void mergeTurnSigns(std::vector<int>& signs, std::vector<int> signs2);404void applyTurnSigns(NBEdge* e, const std::vector<int>& turnSigns);405406/**407* @class NodesHandler408* @brief A class which extracts OSM-nodes from a parsed OSM-file409*/410class NodesHandler : public SUMOSAXHandler {411public:412/** @brief Constructor413* @param[in, out] toFill The nodes container to fill414* @param[in, out] uniqueNodes The nodes container for ensuring uniqueness415* @param[in] options The options to use416*/417NodesHandler(std::map<long long int, NIOSMNode*>& toFill, std::set<NIOSMNode*,418CompareNodes>& uniqueNodes,419const OptionsCont& cont);420421422/// @brief Destructor423~NodesHandler() override;424425int getDuplicateNodes() const {426return myDuplicateNodes;427}428429void resetHierarchy() {430myHierarchyLevel = 0;431}432433protected:434/// @name inherited from GenericSAXHandler435//@{436437/** @brief Called on the opening of a tag;438*439* @param[in] element ID of the currently opened element440* @param[in] attrs Attributes within the currently opened element441* @exception ProcessError If something fails442* @see GenericSAXHandler::myStartElement443*/444void myStartElement(int element, const SUMOSAXAttributes& attrs) override;445446447/** @brief Called when a closing tag occurs448*449* @param[in] element ID of the currently opened element450* @exception ProcessError If something fails451* @see GenericSAXHandler::myEndElement452*/453void myEndElement(int element) override;454//@}455456457private:458/// @brief The nodes container to fill459std::map<long long int, NIOSMNode*>& myToFill;460461/// @brief id of the currently parsed node462std::string myLastNodeID;463464/// @brief the currently parsed node465NIOSMNode* myCurrentNode;466467bool myIsStation;468std::string myRailwayRef;469470/// @brief The current hierarchy level471int myHierarchyLevel;472473/// @brief the set of unique nodes (used for duplicate detection/substitution)474std::set<NIOSMNode*, CompareNodes>& myUniqueNodes;475476/// @brief whether elevation data should be imported477const bool myImportElevation;478479/// @brief custom requirements for rail signal tagging480StringVector myRailSignalRules;481482/// @brief number of duplicate nodes483int myDuplicateNodes;484485/// @brief the options486const OptionsCont& myOptionsCont;487488private:489/** @brief invalidated copy constructor */490NodesHandler(const NodesHandler& s);491492/** @brief invalidated assignment operator */493NodesHandler& operator=(const NodesHandler& s);494495};496497498/**499* @class EdgesHandler500* @brief A class which extracts OSM-edges from a parsed OSM-file501*/502class EdgesHandler : public SUMOSAXHandler {503public:504/** @brief Constructor505*506* @param[in] osmNodes The previously parsed (osm-)nodes507* @param[in, out] toFill The edges container to fill with read edges508*/509EdgesHandler(const std::map<long long int, NIOSMNode*>& osmNodes,510std::map<long long int, Edge*>& toFill, std::map<long long int, Edge*>& platformShapes,511const NBTypeCont& tc);512513514/// @brief Destructor515~EdgesHandler() override;516517518protected:519/// @name inherited from GenericSAXHandler520//@{521522/** @brief Called on the opening of a tag;523*524* @param[in] element ID of the currently opened element525* @param[in] attrs Attributes within the currently opened element526* @exception ProcessError If something fails527* @see GenericSAXHandler::myStartElement528*/529void myStartElement(int element, const SUMOSAXAttributes& attrs) override;530531532/** @brief Called when a closing tag occurs533*534* @param[in] element ID of the currently opened element535* @exception ProcessError If something fails536* @see GenericSAXHandler::myEndElement537*/538void myEndElement(int element) override;539//@}540541double interpretSpeed(const std::string& key, std::string value);542543int interpretChangeType(const std::string& value) const;544545void interpretLaneUse(const std::string& value, SUMOVehicleClass svc, const bool forward) const;546547void addType(const std::string& singleTypeID);548549550private:551/// @brief The previously parsed nodes552const std::map<long long int, NIOSMNode*>& myOSMNodes;553554/// @brief A map of built edges555std::map<long long int, Edge*>& myEdgeMap;556557/// @brief A map of built edges558std::map<long long int, Edge*>& myPlatformShapesMap;559560/// @brief The currently built edge561Edge* myCurrentEdge = nullptr;562563/// @brief A map of non-numeric speed descriptions to their numeric values564std::map<std::string, double> mySpeedMap;565566const NBTypeCont& myTypeCont;567568private:569/** @brief invalidated copy constructor */570EdgesHandler(const EdgesHandler& s);571572/** @brief invalidated assignment operator */573EdgesHandler& operator=(const EdgesHandler& s);574575};576577/**578* @class RelationHandler579* @brief A class which extracts relevant relation information from a parsed OSM-file580* - turn restrictions581*/582class RelationHandler : public SUMOSAXHandler {583public:584/** @brief Constructor585*586* @param[in] osmNodes The previously parsed OSM-nodes587* @param[in] osmEdges The previously parse OSM-edges588*/589RelationHandler(const std::map<long long int, NIOSMNode*>& osmNodes,590const std::map<long long int, Edge*>& osmEdges, NBPTStopCont* nbptStopCont,591const std::map<long long int, Edge*>& platfromShapes, NBPTLineCont* nbptLineCont,592const OptionsCont& oc);593594595/// @brief Destructor596~RelationHandler() override;597598protected:599/// @name inherited from GenericSAXHandler600//@{601602/** @brief Called on the opening of a tag;603*604* @param[in] element ID of the currently opened element605* @param[in] attrs Attributes within the currently opened element606* @exception ProcessError If something fails607* @see GenericSAXHandler::myStartElement608*/609void myStartElement(int element, const SUMOSAXAttributes& attrs) override;610611612/** @brief Called when a closing tag occurs613*614* @param[in] element ID of the currently opened element615* @exception ProcessError If something fails616* @see GenericSAXHandler::myEndElement617*/618void myEndElement(int element) override;619//@}620621622private:623/// @brief The previously parsed nodes624const std::map<long long int, NIOSMNode*>& myOSMNodes;625626/// @brief The previously parsed edges627const std::map<long long int, Edge*>& myOSMEdges;628629/// @brief The previously parsed platform shapes630const std::map<long long int, Edge*>& myPlatformShapes;631632/// @brief The previously filled pt stop container633NBPTStopCont* myNBPTStopCont;634635/// @brief PT Line container to be filled636NBPTLineCont* myNBPTLineCont;637638/// @brief The currently parsed relation639long long int myCurrentRelation;640641/// @brief whether the currently parsed relation is a restriction642bool myIsRestriction;643644/// @brief exceptions to the restriction currenlty being parsed645SVCPermissions myRestrictionException;646647/// @brief the origination way for the current restriction648long long int myFromWay;649650/// @brief the destination way for the current restriction651long long int myToWay;652653/// @brief the via node/way for the current restriction654long long int myViaNode;655long long int myViaWay;656657/// @brief the station node for the current stop_area658long long int myStation;659660/// @brief the options cont661const OptionsCont& myOptionsCont;662663/** @enum RestrictionType664* @brief whether the only allowed or the only forbidden connection is defined665*/666enum class RestrictionType {667/// @brief The only valid connection is declared668ONLY,669/// @brief The only invalid connection is declared670NO,671/// @brief The relation tag was missing672UNKNOWN673};674RestrictionType myRestrictionType;675676/// @brief reset members to their defaults for parsing a new relation677void resetValues();678679/// @brief check whether a referenced way has a corresponding edge680bool checkEdgeRef(long long int ref) const;681682/// @brief try to apply the parsed restriction and return whether successful683bool applyRestriction() const;684685/// @brief try to find the way segment among candidates686NBEdge* findEdgeRef(long long int wayRef, const std::vector<NBEdge*>& candidates) const;687688private:689/** @brief invalidated copy constructor */690RelationHandler(const RelationHandler& s);691692/** @brief invalidated assignment operator */693RelationHandler& operator=(const RelationHandler& s);694695/// @brief bus stop references696std::vector<long long int> myStops;697698/// @brief myStops which are actually platforms (in case there is no stop_position)699std::set<long long int> myPlatformStops;700701702struct NIIPTPlatform {703long long int ref;704bool isWay;705};706707/// @brief bus stop platforms708std::vector<NIIPTPlatform> myPlatforms;709710/// @brief ways in pt line references711std::vector<long long int> myWays;712713/// @brief indicates whether current relation is a pt stop area714bool myIsStopArea;715716/// @brief indicates whether current relation is a route717bool myIsRoute;718719/// @brief indicates whether current relation is a pt route720std::string myPTRouteType;721722/// @brief official route color723RGBColor myRouteColor;724725/// @brief name of the relation726std::string myName;727728/// @brief ref of the pt line729std::string myRef;730731/// @brief service interval of the pt line in minutes732int myInterval;733734/// @brief night service information of the pt line735std::string myNightService;736737/** @brief the map from stop area member to stop_area id */738std::map<long long int, long long int > myStopAreas;739740};741742};743744745