roadgraph-router-v2 0.0.0-stage → 0.2.0
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.
- package/CHANGELOG.md +176 -0
- package/LICENSE +21 -0
- package/README.md +775 -2
- package/dist/chunk-PXL65P3L.js +2064 -0
- package/dist/index.d.ts +941 -0
- package/dist/index.js +971 -0
- package/dist/worker.d.ts +2 -0
- package/dist/worker.js +20 -0
- package/package.json +75 -4
- package/scripts/roadgraph-compile.mjs +670 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project aims
|
|
5
|
+
to follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [0.2.0] - 2026-10-15
|
|
10
|
+
|
|
11
|
+
Multi-vehicle routing. One bundle can now serve a car, a motorcycle and a
|
|
12
|
+
lorry, and a lorry's routes depend on its size and weight. Walking and cycling
|
|
13
|
+
ship too, in a bundle of their own. Alternative routes moved to 0.3.0.
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- **Coordinates in a shared chunk are written as differences**, which takes
|
|
18
|
+
about 6% off a multi-vehicle bundle and loses nothing: Portugal for walking
|
|
19
|
+
and cycling went from 102.3 MB to 96.1 MB, and the three motor vehicles from
|
|
20
|
+
42.8 MB to 40.2 MB. The single-chunk layout a one-vehicle bundle uses is
|
|
21
|
+
untouched, so those stay readable by 0.1.0.
|
|
22
|
+
- **Barriers.** A gate, bollard or stile across a road is read from the node
|
|
23
|
+
and becomes a ban on passing through it, which still lets you turn back the
|
|
24
|
+
way you came. The same barrier stops different travellers differently: a
|
|
25
|
+
bollard is nothing on foot and the end of the road in a car, a stile is the
|
|
26
|
+
reverse. An unfamiliar barrier is left passable rather than guessed at.
|
|
27
|
+
- **`bicycle` and `pedestrian` profiles.** Not motor vehicles with different
|
|
28
|
+
numbers: a posted limit never makes anyone pedal harder, so the way class
|
|
29
|
+
decides the pace and `maxspeed` can only lower it; a one-way sign restrains
|
|
30
|
+
traffic, which a pedestrian is not and a cyclist often has a signed
|
|
31
|
+
contraflow out of; and footways, paths, steps and cycleways are the network
|
|
32
|
+
rather than roads left out of it. They need their own bundle — Portugal is
|
|
33
|
+
102.3 MB for both against 42.8 MB for the three motor vehicles — because
|
|
34
|
+
folding them in would make every driver download the footpaths.
|
|
35
|
+
- **`motorcycle` and `truck` profiles.** The car profile became a factory
|
|
36
|
+
parameterised by the mode name, so all three read the same tags in the same
|
|
37
|
+
order and differ in the key at the bottom of each hierarchy: `motorcar`,
|
|
38
|
+
`motorcycle`, `hgv`. `truck` caps every speed at 90 km/h rather than only
|
|
39
|
+
bounding the A* heuristic, because a heavy vehicle is held below the posted
|
|
40
|
+
limit nearly everywhere.
|
|
41
|
+
- **Physical limits for lorries.** `maxheight`, `maxwidth`, `maxlength` and
|
|
42
|
+
`maxweight` are read per direction, preferring a limit signed for this
|
|
43
|
+
direction, then one signed for lorries, then the general one, and taking the
|
|
44
|
+
stricter of a signed and a `:physical` value. Feet and inches parse. A value
|
|
45
|
+
that states no number reads as unknown rather than as zero.
|
|
46
|
+
- **Vehicle presets** — `van`, `rigid`, `articulated`, `road-train`,
|
|
47
|
+
`us-semi` — resolved from the caller, then the bundle's own
|
|
48
|
+
`--default-vehicle`, then `articulated`. The resolved dimensions are on
|
|
49
|
+
`router.vehicle`, so a default is visible rather than hidden.
|
|
50
|
+
- **EFR2 v7 and EFRB v2.** A tile is written as a shared chunk holding the road
|
|
51
|
+
network and one small chunk per vehicle holding its durations, access mask,
|
|
52
|
+
restriction mask and limits. The directory lists them by `(tile, profile)`,
|
|
53
|
+
so a reader downloads the shared half plus the one vehicle it wants.
|
|
54
|
+
- **`--profile car,truck,motorcycle`** compiles one bundle for several
|
|
55
|
+
vehicles, reading the extract once.
|
|
56
|
+
- **`RoadRouter.profiles`, `RoadRouter.profile`, `RoadRouter.withProfile()`**
|
|
57
|
+
for reading a bundle as another vehicle, reusing every shared chunk already
|
|
58
|
+
downloaded.
|
|
59
|
+
- **Profile metadata in both formats**, in header bytes that were already
|
|
60
|
+
reserved, so nothing published grew.
|
|
61
|
+
|
|
62
|
+
### Changed
|
|
63
|
+
|
|
64
|
+
- **Repeated routes are about four times faster.** The stitched corridor is
|
|
65
|
+
cached between routes, and the stitch itself no longer builds a string key
|
|
66
|
+
per node copy. Porto to Lisbon went from 2107 ms to 534 ms with nothing left
|
|
67
|
+
to download. `mergedCacheSize` controls it; `0` restores the old behaviour.
|
|
68
|
+
- **The A* heuristic and the tile budget take their speed ceiling from the
|
|
69
|
+
graph** rather than from the car profile. The heuristic stayed admissible
|
|
70
|
+
with the wrong ceiling but collapsed towards zero; the tile budget would have
|
|
71
|
+
over-downloaded badly for a slower vehicle.
|
|
72
|
+
- The car profile also reads `oneway:motor_vehicle`, `oneway:motorcar` and
|
|
73
|
+
`maxspeed:motorcar`, which only matter where those tags exist.
|
|
74
|
+
|
|
75
|
+
### Fixed
|
|
76
|
+
|
|
77
|
+
- **`engines.node` was `>=22.5`**, the compiler's requirement, applied to the
|
|
78
|
+
whole package — so installing the library on Node 18 or 20 warned, and failed
|
|
79
|
+
under `engine-strict`. It is now `>=18`, and the CLI checks its own
|
|
80
|
+
requirement at startup rather than after streaming the whole extract.
|
|
81
|
+
- **Switching vehicle threw when the first one had dimensions.** Opening as a
|
|
82
|
+
lorry and asking for the car refused the switch, because the dimensions
|
|
83
|
+
travelled with the options and a car cannot use them. The check moved to
|
|
84
|
+
where a caller pairs a vehicle with a profile; past that, dimensions travel
|
|
85
|
+
with the reader and apply only where they mean something, so truck to car to
|
|
86
|
+
motorcycle and back ends with the dimensions it started with.
|
|
87
|
+
- **Switching vehicle discarded the stitched corridor.** A bundle kept two
|
|
88
|
+
corridors however many vehicles it held, so three vehicles evicted each
|
|
89
|
+
other and every switch re-stitched. It keeps one per vehicle now: a repeated
|
|
90
|
+
Porto to Lisbon fell from about 1500 ms to 257 ms by car, 140 ms by lorry.
|
|
91
|
+
- **A route could fail because an end snapped to a disconnected stub.** The
|
|
92
|
+
nearest road to a point is not always one that leads anywhere: a path behind
|
|
93
|
+
a fence, a service road in a compound, a stretch clipped at a tile edge. A
|
|
94
|
+
failed route is now retried against the piece of the network the other end
|
|
95
|
+
is in. It runs only after a failure, so an ordinary route never pays for it.
|
|
96
|
+
Walking and cycling networks feel this most, being full of small fragments.
|
|
97
|
+
- **Merging tiles dropped per-vehicle data.** Limits, access masks and
|
|
98
|
+
restriction masks are rebased onto the merged numbering, keeping the stricter
|
|
99
|
+
limit where two tiles disagree. A corridor built from more than one tile
|
|
100
|
+
would otherwise have routed a lorry under a bridge it does not fit through.
|
|
101
|
+
- A truck bundle written in the single-chunk layout, which has nowhere to keep
|
|
102
|
+
limits, is refused rather than routed with the dimensions silently ignored.
|
|
103
|
+
|
|
104
|
+
### Documentation
|
|
105
|
+
|
|
106
|
+
- **The README now states plainly what a route does not guarantee.** A route
|
|
107
|
+
is a path over roads the data does not say are forbidden, which is weaker
|
|
108
|
+
than legal or physical suitability. Time-dependent access, seasonal and
|
|
109
|
+
weather rules, temporary closures, zone-level lorry bans and low-emission
|
|
110
|
+
zones, axle load and hazardous goods rules, and untagged limits are all
|
|
111
|
+
listed as unread, with the consequence for a heavy vehicle said directly:
|
|
112
|
+
a route may pass under a bridge too low for it or along a street it is
|
|
113
|
+
banned from at the hour you travel.
|
|
114
|
+
|
|
115
|
+
### Known limitations
|
|
116
|
+
|
|
117
|
+
- An active-travel bundle at country scale cannot be compiled with small
|
|
118
|
+
tiles: Portugal for walking and cycling at 40 km tiles exceeds the
|
|
119
|
+
compiler's 3 GB ceiling and is refused. The default 120 km works, at the
|
|
120
|
+
cost of a larger first download for a short urban route.
|
|
121
|
+
- Alternative routes are not in this release; they are planned for 0.3.0.
|
|
122
|
+
|
|
123
|
+
### Compatibility
|
|
124
|
+
|
|
125
|
+
Bundles compiled by 0.1.0 open and route identically. A single-vehicle compile
|
|
126
|
+
with no physical limits still writes the one-chunk layout byte for byte. The
|
|
127
|
+
new formats appear only when a bundle holds several vehicles or a vehicle whose
|
|
128
|
+
routes depend on its size, and a 0.1.0 reader cannot open those.
|
|
129
|
+
|
|
130
|
+
## [0.1.0] - 2026-10-12
|
|
131
|
+
|
|
132
|
+
First public release. Everything below is new, so this entry describes what the
|
|
133
|
+
package does rather than how it changed.
|
|
134
|
+
|
|
135
|
+
### Added
|
|
136
|
+
|
|
137
|
+
- **Generic OSM compiler.** `roadgraph-compile` turns any `.osm.pbf` extract
|
|
138
|
+
into an EFRB bundle in two passes over the file, with no assumptions about
|
|
139
|
+
which region it describes. Coordinates are indexed on disk through
|
|
140
|
+
`node:sqlite`, tiles are encoded and spilled one at a time, and the bundle is
|
|
141
|
+
streamed out, so peak memory tracks the largest tile rather than the region.
|
|
142
|
+
- **Routing profiles.** Tag handling lives behind a `RoutingProfile`. The
|
|
143
|
+
bundled `car` profile resolves the OSM access hierarchy, `oneway`,
|
|
144
|
+
`junction`, and `maxspeed` including `mph`, falling back to highway-class
|
|
145
|
+
defaults for values it cannot parse.
|
|
146
|
+
- **Turn restrictions.** `no_*` and `only_*` relations are enforced, both the
|
|
147
|
+
`via`-node form and the `via`-way form. A graph carrying restrictions is
|
|
148
|
+
searched with an edge-labelled A*, so a banned turn cannot appear in a result.
|
|
149
|
+
- **Snapping to roads.** A coordinate is projected onto the nearest road rather
|
|
150
|
+
than the nearest junction, which matters after topology simplification, where
|
|
151
|
+
a rural road can run for a kilometre without a node.
|
|
152
|
+
- **Tile selection by distance.** The router loads the tiles that could hold a
|
|
153
|
+
better route, judged by ground distance, so results do not depend on the tile
|
|
154
|
+
size a region was compiled at. `maxDetourFactor` caps how far it will look.
|
|
155
|
+
- **Compact storage.** EFR2 v6 stores each road's geometry once and mirrors it
|
|
156
|
+
for the reverse direction, writes coordinates and edge targets as
|
|
157
|
+
variable-length differences, and rebuilds node offsets from degrees.
|
|
158
|
+
- **Range-addressable bundles.** An `.efrb` holds independently gzipped tiles
|
|
159
|
+
behind a fixed directory, so a route downloads only the tiles it needs.
|
|
160
|
+
- **Formats.** Reads EFRT v1 and EFR2 v2 through v6; writes EFR2 v6 by default
|
|
161
|
+
and the v2-v5 layout on request.
|
|
162
|
+
|
|
163
|
+
### Documentation
|
|
164
|
+
|
|
165
|
+
- **The README now states plainly what a route does not guarantee.** A route
|
|
166
|
+
is a path over roads the data does not say are forbidden, which is weaker
|
|
167
|
+
than legal or physical suitability. Time-dependent access, seasonal and
|
|
168
|
+
weather rules, temporary closures, zone-level lorry bans and low-emission
|
|
169
|
+
zones, axle load and hazardous goods rules, and untagged limits are all
|
|
170
|
+
listed as unread, with the consequence for a heavy vehicle said directly:
|
|
171
|
+
a route may pass under a bridge too low for it or along a street it is
|
|
172
|
+
banned from at the hour you travel.
|
|
173
|
+
|
|
174
|
+
### Known limitations
|
|
175
|
+
|
|
176
|
+
See the "Supported OSM features and limitations" section of the README.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Daniel Sá
|
|
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.
|