routx 1.0.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- routx-1.0.2/.github/workflows/check.yml +54 -0
- routx-1.0.2/.gitignore +8 -0
- routx-1.0.2/LICENSE.txt +21 -0
- routx-1.0.2/PKG-INFO +7 -0
- routx-1.0.2/README.md +536 -0
- routx-1.0.2/build_wheels.py +165 -0
- routx-1.0.2/cross/aarch64-linux-gnu.ini +13 -0
- routx-1.0.2/cross/aarch64-macos.ini +13 -0
- routx-1.0.2/cross/aarch64-windows.ini +13 -0
- routx-1.0.2/cross/x86_64-linux-gnu.ini +13 -0
- routx-1.0.2/cross/x86_64-macos.ini +13 -0
- routx-1.0.2/cross/x86_64-windows.ini +13 -0
- routx-1.0.2/meson.build +15 -0
- routx-1.0.2/pyproject.toml +23 -0
- routx-1.0.2/requirements.dev.txt +4 -0
- routx-1.0.2/requirements.txt +1 -0
- routx-1.0.2/routx/__init__.py +41 -0
- routx-1.0.2/routx/test.py +372 -0
- routx-1.0.2/routx/wrapper.py +873 -0
- routx-1.0.2/subprojects/routx.wrap +7 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
name: Automatic checks
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ "main" ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ "main" ]
|
|
8
|
+
|
|
9
|
+
env:
|
|
10
|
+
CARGO_TERM_COLOR: always
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
build:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
|
|
17
|
+
- name: Checkout repository
|
|
18
|
+
uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Set up Python
|
|
21
|
+
uses: actions/setup-python@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: "3.10"
|
|
24
|
+
|
|
25
|
+
- name: Install dependencies
|
|
26
|
+
run: pip install -r requirements.dev.txt
|
|
27
|
+
|
|
28
|
+
- name: Cache build artifacts
|
|
29
|
+
uses: actions/cache@v4
|
|
30
|
+
with:
|
|
31
|
+
path: |
|
|
32
|
+
builddir/
|
|
33
|
+
key: ${{ runner.os }}-build-${{ hashFiles('meson.build', 'pyproject.toml', 'subprojects/routx.wrap') }}
|
|
34
|
+
|
|
35
|
+
- name: Build
|
|
36
|
+
run: |
|
|
37
|
+
[[ -e builddir ]] || meson setup builddir
|
|
38
|
+
meson compile -C builddir
|
|
39
|
+
ln -fs ../builddir/subprojects/routx/libroutx.so routx
|
|
40
|
+
|
|
41
|
+
- name: Test
|
|
42
|
+
run: python -m unittest
|
|
43
|
+
|
|
44
|
+
- name: Type check
|
|
45
|
+
uses: jakebailey/pyright-action@v2
|
|
46
|
+
with:
|
|
47
|
+
pylance-version: latest-release
|
|
48
|
+
extra-args: "routx/"
|
|
49
|
+
|
|
50
|
+
- name: Check formatting
|
|
51
|
+
run: black --check routx/
|
|
52
|
+
|
|
53
|
+
- name: Check import ordering
|
|
54
|
+
run: isort --check routx/
|
routx-1.0.2/.gitignore
ADDED
routx-1.0.2/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Mikołaj Kuranowski
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
routx-1.0.2/PKG-INFO
ADDED
routx-1.0.2/README.md
ADDED
|
@@ -0,0 +1,536 @@
|
|
|
1
|
+
# routx-python
|
|
2
|
+
|
|
3
|
+
[GitHub](https://github.com/MKuranowski/routx-python) |
|
|
4
|
+
[Documentation](#reference) |
|
|
5
|
+
[Issue Tracker](https://github.com/MKuranowski/routx-python/issues) |
|
|
6
|
+
[PyPI](https://pypi.org/project/routx/)
|
|
7
|
+
|
|
8
|
+
Python bindings for [routx](https://github.com/mkuranowski/routx) -
|
|
9
|
+
library for simple routing over [OpenStreetMap](https://www.openstreetmap.org/) data.
|
|
10
|
+
|
|
11
|
+
Routx converts OSM data into a standard weighted directed graph representation,
|
|
12
|
+
and runs A* to find shortest paths between nodes. Interpretation of OSM data
|
|
13
|
+
is customizable via profiles. Routx supports one-way streets,
|
|
14
|
+
access tags (on ways only) and turn restrictions.
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
`pip install routx` in a [virtual environment](https://docs.python.org/3/library/venv.html).
|
|
19
|
+
|
|
20
|
+
Precompiled wheels are available for most popular platforms (aarch64, x86-64 × GNU Linux, MacOS and Windows).
|
|
21
|
+
On anything else, [cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html)
|
|
22
|
+
(please don't `curl | sh` and install from your system's package manager),
|
|
23
|
+
[ninja and C/C++ compiler toolchain](https://mesonbuild.com/Getting-meson.html#dependencies)
|
|
24
|
+
are required to properly compile the library.
|
|
25
|
+
|
|
26
|
+
Of note is the lack of support for musl-based Linux systems, due to [lacking Rust support](https://github.com/rust-lang/rust/issues/59302).
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
import routx
|
|
30
|
+
|
|
31
|
+
g = routx.Graph()
|
|
32
|
+
g.add_from_osm_file("path/to/monaco.pbf", routx.OsmProfile.CAR)
|
|
33
|
+
|
|
34
|
+
start_node = g.find_nearest_node(43.7384, 7.4246)
|
|
35
|
+
end_node = g.find_nearest_node(43.7478, 7.4323)
|
|
36
|
+
route = g.find_route(start_node.id, end_node.id)
|
|
37
|
+
|
|
38
|
+
for node_id in route:
|
|
39
|
+
node = g[node_id]
|
|
40
|
+
print(node.lat, node.lon)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Reference
|
|
44
|
+
|
|
45
|
+
Unless noted otherwise, `__init__` methods behave as expected for standard
|
|
46
|
+
NamedTuple/dataclass/IntEnum objects.
|
|
47
|
+
|
|
48
|
+
### routx.DEFAULT_STEP_LIMIT
|
|
49
|
+
|
|
50
|
+
```py
|
|
51
|
+
DEFAULT_STEP_LIMIT: Final[int] = 1000000
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Recommended A* step limit for routx.Graph.find_route.
|
|
55
|
+
|
|
56
|
+
### routx.Node
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
class Node(NamedTuple):
|
|
60
|
+
id: int
|
|
61
|
+
osm_id: int
|
|
62
|
+
lat: float
|
|
63
|
+
lon: float
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
An element of a [Graph](#routxgraph). A [named tuple](https://docs.python.org/3/library/typing.html#typing.NamedTuple).
|
|
67
|
+
|
|
68
|
+
Due to turn restriction processing, one OpenStreetMap node may be represented by
|
|
69
|
+
multiple nodes in the graph. If that is the case, a "canonical" node
|
|
70
|
+
(not bound by any turn restriction) will have `id == osm_id`.
|
|
71
|
+
|
|
72
|
+
Nodes with `id == 0` are used by the underlying library to signify the absence of a node,
|
|
73
|
+
are considered false-y and must not be used by consumers.
|
|
74
|
+
|
|
75
|
+
*Methods*:
|
|
76
|
+
- `__bool__(self) -> bool` - True if id is not zero.
|
|
77
|
+
|
|
78
|
+
*Read-only properties*:
|
|
79
|
+
- `is_canonical: bool` - True if `id == osm_id`.
|
|
80
|
+
|
|
81
|
+
### routx.Edge
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
class Edge(NamedTuple):
|
|
85
|
+
to: int
|
|
86
|
+
cost: float
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Outgoing (one-way) connection from a [Node](#routxnode). A [named tuple](https://docs.python.org/3/library/typing.html#typing.NamedTuple).
|
|
90
|
+
|
|
91
|
+
`cost` must be greater than the crow-flies distance between the two nodes.
|
|
92
|
+
|
|
93
|
+
### routx.Graph
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
class Graph(MutableMapping[int, Node]):
|
|
97
|
+
pass # no attributes, constructor accepts no arguments
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
OpenStreetMap-based network representation as a set of [nodes](#routexnode) and [edges](#routxedge) between them.
|
|
101
|
+
|
|
102
|
+
Node access is implemented through the standard
|
|
103
|
+
[MutableMapping interface](https://docs.python.org/3/library/collections.abc.html#collections.abc.MutableMapping)
|
|
104
|
+
from ids (integers) to [nodes](#routxnode).
|
|
105
|
+
|
|
106
|
+
Note that overwriting existing nodes preserves all outgoing and incoming edges. Thus updating
|
|
107
|
+
a node position might result in violation of the Edge invariant and break route finding.
|
|
108
|
+
It **is discouraged** to update nodes, and it is the caller's responsibility not to break
|
|
109
|
+
this invariant.
|
|
110
|
+
|
|
111
|
+
*Methods* (other than the implemented for and inherited from `MutableMapping[int, Node]`):
|
|
112
|
+
|
|
113
|
+
- `find_nearest_node(lat: float, lon: float) -> Node` - find the closest canonical (`id == osm_id`) Node to the given position.
|
|
114
|
+
|
|
115
|
+
This function requires computing distance to every Node in the graph
|
|
116
|
+
and is not suitable for large graphs or for multiple searches.
|
|
117
|
+
Use [KDTree](#routxkdtree) for faster NN finding.
|
|
118
|
+
|
|
119
|
+
If the graph is empty, raises KeyError.
|
|
120
|
+
|
|
121
|
+
- `get_edges(self, from_: int) -> list[Edge]` - gets all outgoing edges from a node with a given id.
|
|
122
|
+
|
|
123
|
+
- `get_edge(self, from_: int, to: int) -> float` - gets the cost of traversing an edge between nodes with provided ids.
|
|
124
|
+
Returns positive infinity when the provided edge does not exist.
|
|
125
|
+
|
|
126
|
+
- `set_edge(self, from_: int, to: int, cost: float) -> bool` - creates or updates an Edge from one node to another.
|
|
127
|
+
|
|
128
|
+
The `cost` must not be smaller than the crow-flies distance between nodes,
|
|
129
|
+
as this would violate the A* invariant and break route finding. It is the
|
|
130
|
+
caller's responsibility to uphold this invariant.
|
|
131
|
+
|
|
132
|
+
Returns True if an existing edge was overwritten, False otherwise.
|
|
133
|
+
|
|
134
|
+
Note that given an `Edge` object, this method may be called with `graph.set_edge(from_, *edge)`.
|
|
135
|
+
|
|
136
|
+
- `delete_edge(self, from_: int, to: int, /, missing_ok: bool = True) -> None` -
|
|
137
|
+
ensures an Edge from one node to another does not exist.
|
|
138
|
+
If no such edge exists and `missing_ok` is set to `False`, raises KeyError.
|
|
139
|
+
|
|
140
|
+
- ```
|
|
141
|
+
find_route(
|
|
142
|
+
self,
|
|
143
|
+
from_: int,
|
|
144
|
+
to: int,
|
|
145
|
+
/,
|
|
146
|
+
without_turn_around: bool = True,
|
|
147
|
+
step_limit: int = DEFAULT_STEP_LIMIT,
|
|
148
|
+
) -> list[int]
|
|
149
|
+
```
|
|
150
|
+
Finds the cheapest way between two nodes using the [A* algorithm](https://en.wikipedia.org/wiki/A*_search_algorithm).
|
|
151
|
+
Returns a list node IDs of such route. The list may be empty if no route exists.
|
|
152
|
+
|
|
153
|
+
`without_turn_around` defaults to `True` and prevents the algorithm from circumventing
|
|
154
|
+
turn restrictions by suppressing unrealistic turn-around instructions (A-B-A).
|
|
155
|
+
This introduces an extra dimension to the search space, so if the graph doesn't contain
|
|
156
|
+
any turn restriction, this parameter should be set to `False`.
|
|
157
|
+
|
|
158
|
+
`step_limit` limits how many nodes can be expanded during search before raising StepLimitExceeded.
|
|
159
|
+
Concluding that no route exists requires expanding all nodes accessible from the start,
|
|
160
|
+
which is usually very time consuming, especially on large datasets.
|
|
161
|
+
|
|
162
|
+
- ```
|
|
163
|
+
add_from_osm_file(
|
|
164
|
+
self,
|
|
165
|
+
filename: str | bytes | PathLike[str] | PathLike[bytes],
|
|
166
|
+
profile: OsmProfile | OsmCustomProfile,
|
|
167
|
+
/,
|
|
168
|
+
format: OsmFormat = OsmFormat.UNKNOWN,
|
|
169
|
+
bbox: tuple[float, float, float, float] = (0.0, 0.0, 0.0, 0.0),
|
|
170
|
+
) -> None
|
|
171
|
+
```
|
|
172
|
+
Parses OSM data from the provided file and adds them to this graph.
|
|
173
|
+
|
|
174
|
+
`profile` describes how the OSM data should be interpreted.
|
|
175
|
+
|
|
176
|
+
`format` describes the file format of the input OSM data. Defaults to auto-detection.
|
|
177
|
+
|
|
178
|
+
`bbox` filters features by a specific bounding box, in order:
|
|
179
|
+
left (min lon), bottom (min lat), right (max lon), top (max lat).
|
|
180
|
+
Ignored if all values are zero (default).
|
|
181
|
+
|
|
182
|
+
- ```
|
|
183
|
+
add_from_osm_memory(
|
|
184
|
+
self,
|
|
185
|
+
mv: memoryview,
|
|
186
|
+
profile: OsmProfile | OsmCustomProfile,
|
|
187
|
+
/,
|
|
188
|
+
format: OsmFormat = OsmFormat.UNKNOWN,
|
|
189
|
+
bbox: tuple[float, float, float, float] = (0.0, 0.0, 0.0, 0.0),
|
|
190
|
+
) -> None
|
|
191
|
+
```
|
|
192
|
+
Parses OSM data from the provided contents of a memory file.
|
|
193
|
+
The buffer must be contiguous and also mutable (for reasons only known to
|
|
194
|
+
[ctypes](https://docs.python.org/3/library/ctypes.html#ctypes._CData.from_buffer),
|
|
195
|
+
because the underlying library takes a const pointer).
|
|
196
|
+
|
|
197
|
+
`profile` describes how the OSM data should be interpreted.
|
|
198
|
+
|
|
199
|
+
`format` describes the file format of the input OSM data. Defaults to auto-detection.
|
|
200
|
+
|
|
201
|
+
`bbox` filters features by a specific bounding box, in order:
|
|
202
|
+
left (min lon), bottom (min lat), right (max lon), top (max lat).
|
|
203
|
+
Ignored if all values are zero (default).
|
|
204
|
+
|
|
205
|
+
### routx.KDTree
|
|
206
|
+
|
|
207
|
+
```
|
|
208
|
+
class KDTree:
|
|
209
|
+
pass # no attributes, private constructor
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
*Methods*:
|
|
213
|
+
- `find_nearest_node(self, lat: float, lon: float) -> Node` - finds the closest node to the provided position and returns its id.
|
|
214
|
+
Raises KeyError when the k-d tree contains no nodes.
|
|
215
|
+
|
|
216
|
+
*Class Methods*:
|
|
217
|
+
- `KDTree.build(graph: Graph) -> Self` - builds a k-d tree with all canonical
|
|
218
|
+
(`id == osm_id`) nodes contained in the provided graph.
|
|
219
|
+
|
|
220
|
+
### routx.OsmProfile
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
class OsmProfile(IntEnum):
|
|
224
|
+
CAR = 1
|
|
225
|
+
BUS = 2
|
|
226
|
+
BICYCLE = 3
|
|
227
|
+
FOOT = 4
|
|
228
|
+
RAILWAY = 5
|
|
229
|
+
TRAM = 6
|
|
230
|
+
SUBWAY = 7
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Predefined OSM conversion profiles. An [IntEnum](https://docs.python.org/3/library/enum.html#enum.IntEnum).
|
|
234
|
+
|
|
235
|
+
<details>
|
|
236
|
+
<summary>CAR</summary>
|
|
237
|
+
Penalties:
|
|
238
|
+
|
|
239
|
+
| Tag | Penalty |
|
|
240
|
+
|------------------------|---------|
|
|
241
|
+
| highway=motorway | 1.0 |
|
|
242
|
+
| highway=motorway_link | 1.0 |
|
|
243
|
+
| highway=trunk | 2.0 |
|
|
244
|
+
| highway=trunk_link | 2.0 |
|
|
245
|
+
| highway=primary | 5.0 |
|
|
246
|
+
| highway=primary_link | 5.0 |
|
|
247
|
+
| highway=secondary | 6.5 |
|
|
248
|
+
| highway=secondary_link | 6.5 |
|
|
249
|
+
| highway=tertiary | 10.0 |
|
|
250
|
+
| highway=tertiary_link | 10.0 |
|
|
251
|
+
| highway=unclassified | 10.0 |
|
|
252
|
+
| highway=minor | 10.0 |
|
|
253
|
+
| highway=residential | 15.0 |
|
|
254
|
+
| highway=living_street | 20.0 |
|
|
255
|
+
| highway=track | 20.0 |
|
|
256
|
+
| highway=service | 20.0 |
|
|
257
|
+
|
|
258
|
+
Access tags: `access`, `vehicle`, `motor_vehicle`, `motorcar`.
|
|
259
|
+
|
|
260
|
+
Allows [motorroads](https://wiki.openstreetmap.org/wiki/Key:motorroad) and considers turn restrictions.
|
|
261
|
+
</details>
|
|
262
|
+
|
|
263
|
+
<details>
|
|
264
|
+
<summary>BUS</summary>
|
|
265
|
+
Penalties:
|
|
266
|
+
|
|
267
|
+
| Tag | Penalty |
|
|
268
|
+
|------------------------|---------|
|
|
269
|
+
| highway=motorway | 1.0 |
|
|
270
|
+
| highway=motorway_link | 1.0 |
|
|
271
|
+
| highway=trunk | 1.0 |
|
|
272
|
+
| highway=trunk_link | 1.0 |
|
|
273
|
+
| highway=primary | 1.1 |
|
|
274
|
+
| highway=primary_link | 1.1 |
|
|
275
|
+
| highway=secondary | 1.15 |
|
|
276
|
+
| highway=secondary_link | 1.15 |
|
|
277
|
+
| highway=tertiary | 1.15 |
|
|
278
|
+
| highway=tertiary_link | 1.15 |
|
|
279
|
+
| highway=unclassified | 1.5 |
|
|
280
|
+
| highway=minor | 1.5 |
|
|
281
|
+
| highway=residential | 2.5 |
|
|
282
|
+
| highway=living_street | 2.5 |
|
|
283
|
+
| highway=track | 5.0 |
|
|
284
|
+
| highway=service | 5.0 |
|
|
285
|
+
|
|
286
|
+
Access tags: `access`, `vehicle`, `motor_vehicle`, `psv`, `bus`, `routing:ztm`.
|
|
287
|
+
|
|
288
|
+
Allows [motorroads](https://wiki.openstreetmap.org/wiki/Key:motorroad) and considers turn restrictions.
|
|
289
|
+
</details>
|
|
290
|
+
|
|
291
|
+
<details>
|
|
292
|
+
<summary>BICYCLE</summary>
|
|
293
|
+
Penalties:
|
|
294
|
+
|
|
295
|
+
| Tag | Penalty |
|
|
296
|
+
|------------------------|---------|
|
|
297
|
+
| highway=trunk | 50.0 |
|
|
298
|
+
| highway=trunk_link | 50.0 |
|
|
299
|
+
| highway=primary | 10.0 |
|
|
300
|
+
| highway=primary_link | 10.0 |
|
|
301
|
+
| highway=secondary | 3.0 |
|
|
302
|
+
| highway=secondary_link | 3.0 |
|
|
303
|
+
| highway=tertiary | 2.5 |
|
|
304
|
+
| highway=tertiary_link | 2.5 |
|
|
305
|
+
| highway=unclassified | 2.5 |
|
|
306
|
+
| highway=minor | 2.5 |
|
|
307
|
+
| highway=cycleway | 1.0 |
|
|
308
|
+
| highway=residential | 1.0 |
|
|
309
|
+
| highway=living_street | 1.5 |
|
|
310
|
+
| highway=track | 2.0 |
|
|
311
|
+
| highway=service | 2.0 |
|
|
312
|
+
| highway=bridleway | 3.0 |
|
|
313
|
+
| highway=footway | 3.0 |
|
|
314
|
+
| highway=steps | 5.0 |
|
|
315
|
+
| highway=path | 2.0 |
|
|
316
|
+
|
|
317
|
+
Access tags: `access`, `vehicle`, `bicycle`.
|
|
318
|
+
|
|
319
|
+
Disallows [motorroads](https://wiki.openstreetmap.org/wiki/Key:motorroad) and considers turn restrictions.
|
|
320
|
+
</details>
|
|
321
|
+
|
|
322
|
+
<details>
|
|
323
|
+
<summary>FOOT</summary>
|
|
324
|
+
Penalties:
|
|
325
|
+
|
|
326
|
+
| Tag | Penalty |
|
|
327
|
+
|---------------------------|---------|
|
|
328
|
+
| highway=trunk | 4.0 |
|
|
329
|
+
| highway=trunk_link | 4.0 |
|
|
330
|
+
| highway=primary | 2.0 |
|
|
331
|
+
| highway=primary_link | 2.0 |
|
|
332
|
+
| highway=secondary | 1.3 |
|
|
333
|
+
| highway=secondary_link | 1.3 |
|
|
334
|
+
| highway=tertiary | 1.2 |
|
|
335
|
+
| highway=tertiary_link | 1.2 |
|
|
336
|
+
| highway=unclassified | 1.2 |
|
|
337
|
+
| highway=minor | 1.2 |
|
|
338
|
+
| highway=residential | 1.2 |
|
|
339
|
+
| highway=living_street | 1.2 |
|
|
340
|
+
| highway=track | 1.2 |
|
|
341
|
+
| highway=service | 1.2 |
|
|
342
|
+
| highway=bridleway | 1.2 |
|
|
343
|
+
| highway=footway | 1.05 |
|
|
344
|
+
| highway=path | 1.05 |
|
|
345
|
+
| highway=steps | 1.15 |
|
|
346
|
+
| highway=pedestrian | 1.0 |
|
|
347
|
+
| highway=platform | 1.1 |
|
|
348
|
+
| railway=platform | 1.1 |
|
|
349
|
+
| public_transport=platform | 1.1 |
|
|
350
|
+
|
|
351
|
+
Access tags: `access`, `foot`.
|
|
352
|
+
|
|
353
|
+
Disallows [motorroads](https://wiki.openstreetmap.org/wiki/Key:motorroad).
|
|
354
|
+
|
|
355
|
+
One-way is only considered when explicitly tagged with `oneway:foot` or on
|
|
356
|
+
`highway=footway`, `highway=path`, `highway=steps`, `highway/public_transport/railway=platform`.
|
|
357
|
+
|
|
358
|
+
Turn restrictions are only considered when explicitly tagged with `restriction:foot`.
|
|
359
|
+
</details>
|
|
360
|
+
|
|
361
|
+
<details>
|
|
362
|
+
<summary>RAILWAY</summary>
|
|
363
|
+
Penalties:
|
|
364
|
+
|
|
365
|
+
| Tag | Penalty |
|
|
366
|
+
|----------------------|---------|
|
|
367
|
+
| railway=rail | 1.0 |
|
|
368
|
+
| railway=light_rail | 1.0 |
|
|
369
|
+
| railway=subway | 1.0 |
|
|
370
|
+
| railway=narrow_gauge | 1.0 |
|
|
371
|
+
|
|
372
|
+
Access tags: `access`, `train`.
|
|
373
|
+
|
|
374
|
+
Allows [motorroads](https://wiki.openstreetmap.org/wiki/Key:motorroad) and considers turn restrictions.
|
|
375
|
+
</details>
|
|
376
|
+
|
|
377
|
+
<details>
|
|
378
|
+
<summary>TRAM</summary>
|
|
379
|
+
Penalties:
|
|
380
|
+
|
|
381
|
+
| Tag | Penalty |
|
|
382
|
+
|----------------------|---------|
|
|
383
|
+
| railway=tram | 1.0 |
|
|
384
|
+
| railway=light_rail | 1.0 |
|
|
385
|
+
|
|
386
|
+
Access tags: `access`, `tram`.
|
|
387
|
+
|
|
388
|
+
Allows [motorroads](https://wiki.openstreetmap.org/wiki/Key:motorroad) and considers turn restrictions.
|
|
389
|
+
</details>
|
|
390
|
+
|
|
391
|
+
<details>
|
|
392
|
+
<summary>SUBWAY</summary>
|
|
393
|
+
Penalties:
|
|
394
|
+
|
|
395
|
+
| Tag | Penalty |
|
|
396
|
+
|----------------|---------|
|
|
397
|
+
| railway=subway | 1.0 |
|
|
398
|
+
|
|
399
|
+
Access tags: `access`, `subway`.
|
|
400
|
+
|
|
401
|
+
Allows [motorroads](https://wiki.openstreetmap.org/wiki/Key:motorroad) and considers turn restrictions.
|
|
402
|
+
</details>
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
### routx.OsmFormat
|
|
406
|
+
|
|
407
|
+
```
|
|
408
|
+
class OsmFormat(IntEnum):
|
|
409
|
+
UNKNOWN = 0
|
|
410
|
+
XML = 1
|
|
411
|
+
XML_GZ = 2
|
|
412
|
+
XML_BZ2 = 3
|
|
413
|
+
PBF = 4
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
Format of the input OSM file. An [IntEnum](https://docs.python.org/3/library/enum.html#enum.IntEnum).
|
|
417
|
+
|
|
418
|
+
*Values*:
|
|
419
|
+
- `UNKNOWN` - unknown format - guess based on content.
|
|
420
|
+
- `XML` - force uncompressed [OSM XML](https://wiki.openstreetmap.org/wiki/OSM_XML).
|
|
421
|
+
- `XML_GZ` - force [OSM XML](https://wiki.openstreetmap.org/wiki/OSM_XML) with [gzip](https://en.wikipedia.org/wiki/Gzip) compression.
|
|
422
|
+
- `XML_BZ2` - force [OSM XML](https://wiki.openstreetmap.org/wiki/OSM_XML)
|
|
423
|
+
with [bzip2](https://en.wikipedia.org/wiki/Bzip2) compression.
|
|
424
|
+
- `PBF` - force [OSM PBF](https://wiki.openstreetmap.org/wiki/PBF_Format).
|
|
425
|
+
|
|
426
|
+
### routx.OsmPenalty
|
|
427
|
+
|
|
428
|
+
```
|
|
429
|
+
class OsmPenalty(NamedTuple):
|
|
430
|
+
key: str
|
|
431
|
+
value: str
|
|
432
|
+
penalty: float
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
Numeric multiplier for OSM ways with specific keys and values. A [named tuple](https://docs.python.org/3/library/typing.html#typing.NamedTuple).
|
|
436
|
+
|
|
437
|
+
*Attributes*:
|
|
438
|
+
- `key: str` - key of an OSM way for which this penalty applies, used for `value` comparison (e.g. "highway" or "railway").
|
|
439
|
+
- `value: str` - value under `key` of an OSM way for which this penalty applies.E.g. "motorway", "residential", or "rail".
|
|
440
|
+
- `penalty: float` - multiplier of the length, to express preference for a specific way. Must be not less than one and be finite.
|
|
441
|
+
|
|
442
|
+
### routx.OsmCustomProfile
|
|
443
|
+
|
|
444
|
+
```
|
|
445
|
+
@dataclass
|
|
446
|
+
class OsmCustomProfile:
|
|
447
|
+
name: str
|
|
448
|
+
penalties: list[OsmPenalty]
|
|
449
|
+
access: list[str]
|
|
450
|
+
disallow_motorroad: bool = False
|
|
451
|
+
disable_restrictions: bool = False
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
Describes how to convert OSM data into a [Graph](#routxgraph). A [dataclass](https://docs.python.org/3/library/dataclasses.html).
|
|
455
|
+
|
|
456
|
+
If possible, usage of pre-defined [OsmProfiles](#routxosmprofile) should be preferred.
|
|
457
|
+
Using custom profile involves reallocation of all arrays and strings
|
|
458
|
+
two times to match ABIs (first from Python to C, then from C to Rust).
|
|
459
|
+
This is only a constant cost incurred on call to Graph.add_from_file or Graph.add_from_memory.
|
|
460
|
+
|
|
461
|
+
*Attributes*:
|
|
462
|
+
|
|
463
|
+
- `name: str` - human readable name of the routing profile, customary the most specific [access tag](https://wiki.openstreetmap.org/wiki/Key:access).
|
|
464
|
+
|
|
465
|
+
This value is not used for actual OSM data interpretation,
|
|
466
|
+
except when set to "foot", which adds the following logic:
|
|
467
|
+
- `oneway` tags are ignored - only `oneway:foot` tags are considered, except on:
|
|
468
|
+
- `highway=footway`,
|
|
469
|
+
- `highway=path`,
|
|
470
|
+
- `highway=steps`,
|
|
471
|
+
- `highway=platform`
|
|
472
|
+
- `public_transport=platform`,
|
|
473
|
+
- `railway=platform`;
|
|
474
|
+
- only `restriction:foot` turn restrictions are considered.
|
|
475
|
+
|
|
476
|
+
- `penalties: list[OsmPenalty]` - tags of OSM ways which can be used for routing.
|
|
477
|
+
|
|
478
|
+
A way is matched against all OsmPenalty objects in order, and once an exact key and value match
|
|
479
|
+
is found; the way is used for routing, and each connection between two nodes gets
|
|
480
|
+
a resulting cost equal to the distance between nodes multiplied the penalty.
|
|
481
|
+
|
|
482
|
+
All penalties must be normal and not less than zero.
|
|
483
|
+
|
|
484
|
+
For example, if there are two penalties:
|
|
485
|
+
1. highway=motorway, penalty=1
|
|
486
|
+
2. highway=trunk, penalty=1.5
|
|
487
|
+
|
|
488
|
+
This will result in:
|
|
489
|
+
- a highway=motorway stretch of 100 meters will be used for routing with a cost of 100.
|
|
490
|
+
- a highway=trunk motorway of 100 meters will be used for routing with a cost of 150.
|
|
491
|
+
- a highway=motorway_link or highway=primary won't be used for routing, as they do not any penalty.
|
|
492
|
+
|
|
493
|
+
- `access: list[str]` - list of OSM [access tags](https://wiki.openstreetmap.org/wiki/Key:access#Land-based_transportation) (in order from least to most specific) to consider when checking for road prohibitions.
|
|
494
|
+
|
|
495
|
+
This list is used mainly to follow the access tags, but also to follow mode-specific one-way and turn restrictions.
|
|
496
|
+
|
|
497
|
+
- `disallow_motorroad: bool` - force no routing over [motorroad=yes](https://wiki.openstreetmap.org/wiki/Key:motorroad) ways.
|
|
498
|
+
|
|
499
|
+
- `disable_restrictions: bool` - force ignoring of [turn restrictions](https://wiki.openstreetmap.org/wiki/Turn_restriction).
|
|
500
|
+
|
|
501
|
+
### routx.OsmLoadingError
|
|
502
|
+
|
|
503
|
+
```
|
|
504
|
+
class OsmLoadingError(ValueError):
|
|
505
|
+
pass # attributes and constructor the same as for ValueError
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
Raised with the underlying library has failed to load OSM data data. See logs for details.
|
|
509
|
+
|
|
510
|
+
### routx.StepLimitExceeded
|
|
511
|
+
|
|
512
|
+
```
|
|
513
|
+
class StepLimitExceeded(ValueError):
|
|
514
|
+
pass # attributes and constructor the same as for ValueError
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
Raised when Graph.find_route exceeded its step limit.
|
|
518
|
+
|
|
519
|
+
### routx.earth_distance
|
|
520
|
+
|
|
521
|
+
```
|
|
522
|
+
def earth_distance(
|
|
523
|
+
lat1: float,
|
|
524
|
+
lon1: float,
|
|
525
|
+
lat2: float,
|
|
526
|
+
lon2: float,
|
|
527
|
+
) -> float:
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
Calculates the great-circle distance between two positions using the [haversine formula](https://en.wikipedia.org/wiki/Haversine_formula).
|
|
531
|
+
|
|
532
|
+
Returns the result in kilometers.
|
|
533
|
+
|
|
534
|
+
## License
|
|
535
|
+
|
|
536
|
+
routx and routx-python are made available under the MIT license.
|