pyroutelib3.osm¶
Graph¶
- class pyroutelib3.osm.Graph(profile: Profile)¶
Bases:
SimpleGraph[GraphNode]Graph implements
GraphLikeover OpenStreetMap data.- add_features(features: Iterable[Node | Way | Relation]) None¶
add_features adds OpenStreetMap data to the graph.
While it is permitted to call this function multiple times on the same graph, each call must be made with a complete, self-contained dataset. That is, ways may only refer to nodes from the
featuresiterable, and relations as well may only refer to ways and nodes from thefeaturesiterable.If called on a non-empty graph the data is merged:
for duplicate nodes - the already-existing data takes precedence,
for duplicate edges between two nodes - the incoming data takes precedence,
- for duplicate turn restrictions - the incoming restriction is processed,
which should be a no-op, as the restriction was already applied.
Due to linear processing of the provided iterable, a feature may only refer to features that were defined beforehand. The easiest way to satisfy this condition is to ensure that features are listed grouped by type, first nodes, followed by ways, followed by relations. Most OSM XML files exported by other tools follow this ordering.
Any issues with incoming OSM data are reported as warnings through the
pyroutelib3.osmlogger.
- find_nearest_node(position: Tuple[float, float]) GraphNode¶
find_nearest_node finds the closest node to the provided
Position. Phantom nodesnd.id != nd.osm_idcreated by turn restrictions are not considered.This function iterates over every contained
GraphNode, and can be very slow for big graphs. Use a helper data structure (like a K-D tree) if this function becomes a performance bottleneck.
- classmethod from_features(profile: Profile, features: Iterable[Node | Way | Relation]) Self¶
Creates a
Graphbased on the providedprofileandfeatures.
- classmethod from_file(profile: Profile, buf: IO[bytes], format: Literal['xml', 'gz', 'bz2', 'pbf'] | None = None, chunk_size: int = 8192) Self¶
Creates a
Graphbased on the providedProfileand features from the provided possibly-compressed OSM XML or a OSM PBF file.formatandchunk_sizeare passed through toosm.reader.read_features().
- class pyroutelib3.osm.LiveGraph(profile: ~pyroutelib3.osm.profile.Profile, tile_cache_directory: str | ~os.PathLike[str] = 'tilecache', tile_expiry_seconds: int = 2592000, tile_zoom: int = 15, osm_api_url: str = 'https://api.openstreetmap.org/api/0.6/map?bbox={left},{bottom},{right},{top}', file_lock: ~typing.Callable[[~pathlib.Path], ~typing.ContextManager[~typing.Any]] = <class 'filelock._unix.UnixFileLock'>)¶
Bases:
GraphLiveGraph extends the
osm.Graphby automatically downloading data from the OpenStreetMap API in tiles.Tiles downloads can be triggered by
find_nearest_node()andget_edges().The inherited
from_fileandfrom_featuresmethods should not be used.Usage of this class is discouraged, it is much more wise to use
osm.Graphdirectly with OSM data extracts, further filtered with osmosis <https://wiki.openstreetmap.org/wiki/Osmosis>. Example command:osmosis \ --read-pbf-fast south-korea-latest.osm.pbf \ --bounding-box top=35.3207 left=128.8298 bottom=35.0303 right=129.1608 \ --tag-filter accept-ways 'highway=*' \ --tag-filter accept-relations 'type=restriction' \ --used-node \ --write-pbf south-korea-trimmed-simplified.osm.pbf
- download_tile(tile: Tuple[int, int], tile_file: Path) None¶
Downloads the provided tile (using
osm_api_url) to the provided path.
- find_nearest_node(position: Tuple[float, float]) GraphNode¶
find_nearest_node finds the closest node to the provided
Position. Phantom nodesnd.id != nd.osm_idcreated by turn restrictions are not considered.This function iterates over every contained
GraphNode, and can be very slow for big graphs. Use a helper data structure (like a K-D tree) if this function becomes a performance bottleneck.
- classmethod from_features(profile: Profile, features: Iterable[Node | Way | Relation]) Self¶
Creates a
Graphbased on the providedprofileandfeatures.
- classmethod from_file(profile: Profile, buf: IO[bytes], format: Literal['xml', 'gz', 'bz2', 'pbf'] | None = None, chunk_size: int = 8192) Self¶
Creates a
Graphbased on the providedProfileand features from the provided possibly-compressed OSM XML or a OSM PBF file.formatandchunk_sizeare passed through toosm.reader.read_features().
- get_edges(id: int) Iterable[Tuple[int, float]]¶
get_edges must return all edges outgoing from a node with the provided ID. The edges are a pair of (node_id, cost). All returned neighbor nodes must exist in the graph.
If there are no outgoing edges from the provided node, must return an empty iterable. If a node with the given ID, may return an empty iterable, or raise KeyError.
- get_tile_directory(tile: Tuple[int, int]) Path¶
Returns the directory in which the provided
tiledata should be stored.
- has_up_to_date_tile(tile_file: Path) bool¶
Checks if a tile stored at the provided path is reasonably up-to-date (as defined by
tile_expiry_seconds). If the provided file doesn’t exist, returnsFalse.
- load_tile(tile: Tuple[int, int], tile_file: Path) None¶
Loads the provided tile into the graph.
- load_tile_around(position: Tuple[float, float]) None¶
Ensures the tile in which
positionfalls is loaded into the graph.If that tile is loaded, this function does nothing.
If that tile is cached (present in
tile_cache_directory) and reasonably up-to-date (as defined bytile_expiry_seconds) it is simply loaded.Otherwise, this function downloads the tile before loading it.
- file_lock: Callable[[Path], ContextManager[Any]]¶
Context manager used to ensure tiles are not downloaded simultaneously. Useful if multiple LiveGraphs use the same tile cache directory at the same time. Defaults to filelock.FileLock.
- osm_api_url: str¶
Format string used for generating URLs with tile data. Must have
left,bottom,rightandtopplaceholders.
- tile_cache_directory: Path¶
tile_cache_directory is the directory where downloaded tiles are stored. Defaults to “tilecache” in current directory. If missing, this directory (and its parents) are created.
- tile_expiry_seconds: int¶
Tiles are re-downloaded if older than tile_expiry_seconds. Defaults to 30 days.
- tile_zoom: int¶
How large should the downloaded tiles be? See https://wiki.openstreetmap.org/wiki/Zoom_levels. Note that the OSM API rejects requests with too much data with “400 Bad Request” - if that is the case, increase the zoom level.
- class pyroutelib3.osm.GraphNode(id: int, position: Tuple[float, float], external_id: int)¶
Bases:
SimpleExternalNodeGraphNode is a node in a
Graph.- property osm_id: int¶
Profiles¶
Concrete Profiles¶
Highway-based
- class pyroutelib3.osm.BicycleProfile(name: str | None = None, penalties: Dict[str, float] | None = None, access: List[str] | None = None)¶
Bases:
NonMotorroadHighwayProfileBicycleProfile is a
NonMotorroadHighwayProfilewith default parameters which can be used for bicycle routing.
- class pyroutelib3.osm.BusProfile(name: str | None = None, penalties: Dict[str, float] | None = None, access: List[str] | None = None)¶
Bases:
HighwayProfileBusProfile is a
HighwayProfilewith default parameters which can be used for bus routing.
- class pyroutelib3.osm.CarProfile(name: str | None = None, penalties: Dict[str, float] | None = None, access: List[str] | None = None)¶
Bases:
HighwayProfileCarProfile is a
HighwayProfilewith default parameters which can be used for car routing.
- class pyroutelib3.osm.FootProfile(name: str | None = None, penalties: Dict[str, float] | None = None, access: List[str] | None = None)¶
Bases:
NonMotorroadHighwayProfileFootProfile is a
NonMotorroadHighwayProfilewith default parameters which can be used for on-foot routing.FootProfile treats several tags differently to
HighwayProfile:public_transport=platformandrailway=platformare treated as-ifhighway=platformonewaytags are ignored, unless onhighway=footway,highway=path,highway=stepsorhighway=platform. On other ways, onlyoneway:footis used.
Only
restriction:footturn restrictions are considered.
- get_active_highway_value(tags: Mapping[str, str]) str¶
get_active_highway_value gets the string to lookup in
penalties- the value of the “highway” tag, normalized throughEQUIVALENT_TAGS.
- get_active_oneway_value(tags: Mapping[str, str]) str¶
get_active_oneway_value returns the most specific “oneway:MODE” tag, falling back to “oneway” - to use when checking way directionality.
- get_active_restriction_value(tags: Mapping[str, str]) str¶
get_active_restriction_value returns the most specific “restriction:MODE” tag, falling back to “restriction” - to use when checking turn restriction type.
Railway-based
- class pyroutelib3.osm.RailwayProfile(name: str = 'railway', penalties: ~typing.Dict[str, float] = <factory>)¶
Bases:
objectRailwayProfile implements
Profilefor routing over railway=* ways.Only
access=nooraccess=privatecan prevent a way from being excluded from the graph. There are no default one ways, and onlyonewayvalues ofyesand-1are accepted. Alltype=restrictionwithrestrictiontag set to only/no right_turn/left_turn/u_turn/straight_on are passed through.RailwayProfile()can be used as a profile for routing overrailway=rail,light_rail,subwayandnarrow_gauge.- is_turn_restriction(tags: Mapping[str, str]) TurnRestriction¶
- way_direction(tags: Mapping[str, str]) Tuple[bool, bool]¶
- way_penalty(tags: Mapping[str, str]) float | None¶
- name: str = 'railway'¶
- penalties: Dict[str, float]¶
- class pyroutelib3.osm.SubwayProfile¶
Bases:
RailwayProfileSubwayProfile is a
RailwayProfilewhich allows routing only overrailway=subwayways.
- class pyroutelib3.osm.TramProfile¶
Bases:
RailwayProfileTramProfile is a
RailwayProfilewhich allows routing only overrailway=tramorlight_railways.
Other
- class pyroutelib3.osm.SkeletonProfile(*args, **kwargs)¶
Bases:
ProfileSkeletonProfile implements
Profilefor routing over every way in OSM data, regardless of used tags. This profile is meant for holding graphs in OSM XML/OSM PBF formats, without following OpenStreetMap mapping conventions. All relations (and thus turn restrictions) are ignored.The only introspected tag is
oneway, which may be set toyesor-1.- is_turn_restriction(relation_tags: Mapping[str, str]) TurnRestriction¶
is_turn_restriction must determine whether the relation (given by its tags) is an applicable turn restriction.
If the relation is not a turn restriction, or is a turn restriction not applicable to this Profile, must return
TurnRestriction.INAPPLICABLE.If following the route of the restriction is forbidden, must return
TurnRestriction.PROHIBITORY.If following the route of the restriction is forced, must return
TurnRestriction.MANDATORY.
- way_direction(way_tags: Mapping[str, str]) Tuple[bool, bool]¶
way_direction must determine whether a way with the provided tags is traversable forward and backward. First element in the returned tuple must represent the forward direction, while the second - backward direction.
- way_penalty(way_tags: Mapping[str, str]) float | None¶
way_penalty must return the penalty for traversing a way with the provided tags, or
Noneif the way is not traversable.The returned penalty is then multiplied by the each way’s segment length to get the cost of traversing an edge.
The returned value must be finite and at least 1.
Base classes¶
- class pyroutelib3.osm.Profile(*args, **kwargs)¶
Bases:
ProtocolProfile instructs how
Graphshould convert OSM features into a routing graph.- is_turn_restriction(_Profile__relation_tags: Mapping[str, str]) TurnRestriction¶
is_turn_restriction must determine whether the relation (given by its tags) is an applicable turn restriction.
If the relation is not a turn restriction, or is a turn restriction not applicable to this Profile, must return
TurnRestriction.INAPPLICABLE.If following the route of the restriction is forbidden, must return
TurnRestriction.PROHIBITORY.If following the route of the restriction is forced, must return
TurnRestriction.MANDATORY.
- way_direction(_Profile__way_tags: Mapping[str, str]) Tuple[bool, bool]¶
way_direction must determine whether a way with the provided tags is traversable forward and backward. First element in the returned tuple must represent the forward direction, while the second - backward direction.
- way_penalty(_Profile__way_tags: Mapping[str, str]) float | None¶
way_penalty must return the penalty for traversing a way with the provided tags, or
Noneif the way is not traversable.The returned penalty is then multiplied by the each way’s segment length to get the cost of traversing an edge.
The returned value must be finite and at least 1.
- class pyroutelib3.osm.HighwayProfile(name: str, penalties: Dict[str, float], access: List[str])¶
Bases:
ProfileHighwayProfile implements
Profilefor routing over highway=* ways.- get_active_highway_value(tags: Mapping[str, str]) str¶
get_active_highway_value gets the string to lookup in
penalties- the value of the “highway” tag, normalized throughEQUIVALENT_TAGS.
- get_active_oneway_value(tags: Mapping[str, str]) str¶
get_active_oneway_value returns the most specific “oneway:MODE” tag, falling back to “oneway” - to use when checking way directionality.
- get_active_restriction_value(tags: Mapping[str, str]) str¶
get_active_restriction_value returns the most specific “restriction:MODE” tag, falling back to “restriction” - to use when checking turn restriction type.
- is_allowed(way_tags: Mapping[str, str]) bool¶
is_allowed checks if a way is allowed, as per the access tags and the hierarchy defined in
access. Only values of “no” and “private” can exclude a way, any other value (even “destination” or “permit”) is assumed to allow a way to be used.
- is_exempted(restriction_tags: Mapping[str, str]) bool¶
is_exempted returns
Trueif any of the transportation modes under theexcepttag are present inaccess.
- is_turn_restriction(tags: Mapping[str, str]) TurnRestriction¶
is_turn_restriction checks relation tags to determine what kind of
TurnRestrictionthis is. The relation must have a “type=restriction” tag, however, the restriction type may be under “restriction” or “restriction:MODE” keys (seeget_active_restriction_value()), andis_exempted()must return False. Only only/no right_turn/left_turn/u_turn/straight_on restrictions are accepted.
- way_direction(way_tags: Mapping[str, str]) Tuple[bool, bool]¶
way_direction returns the direction of travel of the provided way. Apart from considering the oneway tag (as returned by
get_active_oneway_value()),highway=motorway,highway=motorway_link,junction=roundaboutandjunction=circulardefault to being oneway.
- way_penalty(way_tags: Mapping[str, str]) float | None¶
way_penalty returns the penalty of using this way, by looking up the return value of
get_active_highway_value()inpenalties, unlessis_allowed()return False.
- EQUIVALENT_TAGS: ClassVar[Mapping[str, str]] = {'minor': 'unclassified', 'motorway_link': 'motorway', 'primary_link': 'primary', 'secondary_link': 'secondary', 'tertiary_link': 'tertiary', 'trunk_link': 'trunk'}¶
- access: List[str]¶
access is the hierarchy of access tags to consider when checking if a route is traversable. Keys must be listed from least-specific first.
- name: str¶
- penalties: Dict[str, float]¶
penalties maps highway tag values (after transformation through
EQUIVALENT_TAGS) into their corresponding penalties. All penalties must be finite and not smaller than 1.
- class pyroutelib3.osm.NonMotorroadHighwayProfile(name: str, penalties: Dict[str, float], access: List[str])¶
Bases:
HighwayProfileNonMotorroadHighwayProfile is a base class for profiles over highway=* ways, for which motorroad=yes implies no access.
- is_allowed(way_tags: Mapping[str, str]) bool¶
is_allowed checks if a way is allowed, as per the access tags and the hierarchy defined in
access. Only values of “no” and “private” can exclude a way, any other value (even “destination” or “permit”) is assumed to allow a way to be used.
- class pyroutelib3.osm.TurnRestriction(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)¶
Bases:
EnumTurnRestriction indicates whether an OSM relation is an applicable turn restriction. Used as the return value of
Profile.is_turn_restriction().- MANDATORY = 2¶
Mandatory (only_*) restriction, stepping from the “from” onto the “via” member forces the use of the restriction’s route.
- PROHIBITORY = 1¶
Prohibitory (no_*) restriction, following the route of restriction is not allowed.