vulture-wasm 0.2.0 → 0.4.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/README.md +55 -4
- package/package.json +1 -1
- package/vulture_wasm.d.ts +24 -8
- package/vulture_wasm.js +44 -11
- package/vulture_wasm_bg.wasm +0 -0
package/README.md
CHANGED
|
@@ -47,15 +47,16 @@ const tt = new VultureTimetable(
|
|
|
47
47
|
- `tt.nStops()`, `tt.nRoutes()` — counts.
|
|
48
48
|
- `tt.stopIdx(gtfsId)` — GTFS stop id → opaque `StopIdx`, or `undefined`.
|
|
49
49
|
- `tt.stopName(stopIdx)`, `tt.stopCoords(stopIdx)`, `tt.routeName(routeIdx)`, `tt.routeAgency(routeIdx)` — display-data accessors.
|
|
50
|
-
- `tt.allStops()` — bulk catalogue of `{idx, id, name, lat, lon}` per stop.
|
|
51
|
-
- `tt.allRoutes()` — bulk catalogue of `{idx, id, name, agency, route_type, route_color}` per route. `route_type` is the GTFS integer (0=tram, 1=metro, 2=rail, 3=bus, 4=ferry, 5=cable, 6=aerial, 7=funicular, …); `route_color` is `"#rrggbb"` or `null`.
|
|
50
|
+
- `tt.allStops()` — bulk catalogue of `{idx, id, name, lat, lon, location_type, parent_station}` per stop. `location_type` is the GTFS integer (0 = stop or platform, 1 = parent station, 2 = entrance/exit, 3 = generic node, 4 = boarding area); `parent_station` is the parent's GTFS id or `null`.
|
|
51
|
+
- `tt.allRoutes()` — bulk catalogue of `{idx, id, name, agency, route_type, route_color}` per route. `route_type` is the GTFS integer (0 = tram, 1 = metro, 2 = rail, 3 = bus, 4 = ferry, 5 = cable, 6 = aerial, 7 = funicular, …); `route_color` is `"#rrggbb"` or `null`.
|
|
52
|
+
- `tt.stationStops(parentId)` — given a parent station's GTFS id, returns a `Uint32Array` of the platform stop indices that hang off it. Pass the result as `originStops` / `targetStops` to query against every platform of a station; queries rooted at a `location_type = 1` stop return zero journeys without this expansion, because in GTFS vehicles only board at platform-level stops.
|
|
52
53
|
- `tt.withWalkingFootpaths(maxDistMeters, walkSpeedMetersPerSec)` — replace the footpath set with one derived from stop coordinates.
|
|
53
54
|
- `tt.resetFootpaths()` — restore the original `transfers.txt` set.
|
|
54
55
|
|
|
55
56
|
Free functions:
|
|
56
57
|
|
|
57
58
|
- `runArrival(tt, originStops, targetStops, maxTransfers, departSeconds, requireWheelchair)` — single-departure query. Returns an array of journeys with timed legs.
|
|
58
|
-
- `runRange(tt,
|
|
59
|
+
- `runRange(tt, originStops, targetStops, maxTransfers, departures, requireWheelchair)` — depart-in-window Pareto profile. Returns `[{depart, journey}]` where each `journey` has the same shape as a `runArrival` entry (`origin`, `target`, `arrival`, `legs`).
|
|
59
60
|
|
|
60
61
|
Each leg in `journey.legs` is `{board_stop, alight_stop, route, trip, route_id, depart, arrive, shape}`. `shape` is a `[lat, lon][]` polyline for that leg's segment of the trip's `shapes.txt` geometry, or `null` if the feed has no shape for the trip.
|
|
61
62
|
|
|
@@ -132,7 +133,14 @@ const departures = new Uint32Array(
|
|
|
132
133
|
Array.from({ length: 13 }, (_, i) => 9 * 3600 + i * 300),
|
|
133
134
|
);
|
|
134
135
|
|
|
135
|
-
const profile = runRange(
|
|
136
|
+
const profile = runRange(
|
|
137
|
+
tt,
|
|
138
|
+
new Uint32Array([origin]),
|
|
139
|
+
new Uint32Array([target]),
|
|
140
|
+
10,
|
|
141
|
+
departures,
|
|
142
|
+
false,
|
|
143
|
+
);
|
|
136
144
|
|
|
137
145
|
for (const entry of profile) {
|
|
138
146
|
console.log(
|
|
@@ -175,6 +183,49 @@ console.log(`with footpaths: ${after.length} journey(s)`);
|
|
|
175
183
|
|
|
176
184
|
`tt.resetFootpaths()` restores the original `transfers.txt` set.
|
|
177
185
|
|
|
186
|
+
### 4. Querying entire stations (parent-station expansion)
|
|
187
|
+
|
|
188
|
+
GTFS feeds with deep station hierarchies (regional German rail, French SNCF, UK NaPTAN, etc.) model a single station as one parent stop (`location_type = 1`) with many child platforms (`location_type = 0`) hanging off it. Vehicles only board at platforms; querying directly against a parent station returns zero journeys. Detect parents and expand them into the platform set:
|
|
189
|
+
|
|
190
|
+
```js
|
|
191
|
+
import init, { VultureTimetable, runArrival } from "vulture-wasm";
|
|
192
|
+
|
|
193
|
+
await init();
|
|
194
|
+
|
|
195
|
+
const tt = new VultureTimetable(
|
|
196
|
+
new Uint8Array(await (await fetch("/path/to/feed.zip")).arrayBuffer()),
|
|
197
|
+
"2026-05-04",
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
// Resolve a stop record (from `tt.allStops()` or any other lookup
|
|
201
|
+
// path) into the array of stop indices to query against.
|
|
202
|
+
function endpointsFor(stop) {
|
|
203
|
+
if (stop.location_type === 1) {
|
|
204
|
+
const platforms = tt.stationStops(stop.id);
|
|
205
|
+
if (platforms.length > 0) return platforms;
|
|
206
|
+
}
|
|
207
|
+
return new Uint32Array([stop.idx]);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const stops = tt.allStops();
|
|
211
|
+
const stopByName = new Map(stops.map((s) => [s.name, s]));
|
|
212
|
+
|
|
213
|
+
const from = stopByName.get("Karlsruhe Hauptbahnhof"); // a parent station
|
|
214
|
+
const to = stopByName.get("Basel SBB"); // also a parent
|
|
215
|
+
|
|
216
|
+
const journeys = runArrival(
|
|
217
|
+
tt,
|
|
218
|
+
endpointsFor(from),
|
|
219
|
+
endpointsFor(to),
|
|
220
|
+
/* maxTransfers */ 10,
|
|
221
|
+
/* depart */ 9 * 3600,
|
|
222
|
+
/* wheelchair */ false,
|
|
223
|
+
);
|
|
224
|
+
console.log(`${journeys.length} journey(s) across all platform combinations`);
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
The same `endpointsFor(stop)` helper is what the bundled demo uses across all three panels.
|
|
228
|
+
|
|
178
229
|
## Build from source
|
|
179
230
|
|
|
180
231
|
```sh
|
package/package.json
CHANGED
package/vulture_wasm.d.ts
CHANGED
|
@@ -58,6 +58,19 @@ export class VultureTimetable {
|
|
|
58
58
|
* routes by stop-pattern.
|
|
59
59
|
*/
|
|
60
60
|
routeName(idx: number): string | undefined;
|
|
61
|
+
/**
|
|
62
|
+
* Expand a parent station's GTFS id into the platform stop
|
|
63
|
+
* indices that hang off it. Returns an empty array if `parent_id`
|
|
64
|
+
* is not a parent station in the feed (or has no children).
|
|
65
|
+
*
|
|
66
|
+
* Useful for the "any platform of this station" pattern: in
|
|
67
|
+
* GTFS, vehicles only board at platform-level stops
|
|
68
|
+
* (`location_type = 0`), so a query rooted at the parent station
|
|
69
|
+
* (`location_type = 1`) returns nothing. Pass this method's
|
|
70
|
+
* result as `originStops` / `targetStops` to query against every
|
|
71
|
+
* platform.
|
|
72
|
+
*/
|
|
73
|
+
stationStops(parent_id: string): Uint32Array;
|
|
61
74
|
/**
|
|
62
75
|
* Returns the GTFS `[lat, lon]` for the given stop index, or
|
|
63
76
|
* `undefined` if the stop has no coordinates set.
|
|
@@ -94,15 +107,17 @@ export function runArrival(tt: VultureTimetable, origins: Uint32Array, targets:
|
|
|
94
107
|
|
|
95
108
|
/**
|
|
96
109
|
* Range query: run RAPTOR across a window of departure times. JS
|
|
97
|
-
* passes `
|
|
98
|
-
*
|
|
99
|
-
* `
|
|
110
|
+
* passes `origins` / `targets` as `Uint32Array`s of stop indices
|
|
111
|
+
* (each entry gets walk-time zero), and `departures` as a
|
|
112
|
+
* `Uint32Array` of seconds-since-midnight values. Returns
|
|
113
|
+
* `[{depart, journey}]` Pareto-filtered on `(later depart, fewer
|
|
114
|
+
* transfers, earlier arrival)`.
|
|
100
115
|
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
116
|
+
* Multi-source / multi-target so the "any platform of this station"
|
|
117
|
+
* pattern (via `tt.stationStops(parent_id)`) works the same way as
|
|
118
|
+
* in `runArrival`.
|
|
104
119
|
*/
|
|
105
|
-
export function runRange(tt: VultureTimetable,
|
|
120
|
+
export function runRange(tt: VultureTimetable, origins: Uint32Array, targets: Uint32Array, max_transfers: number, departures: Uint32Array, require_wheelchair: boolean): any;
|
|
106
121
|
|
|
107
122
|
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
|
108
123
|
|
|
@@ -110,7 +125,7 @@ export interface InitOutput {
|
|
|
110
125
|
readonly memory: WebAssembly.Memory;
|
|
111
126
|
readonly __wbg_vulturetimetable_free: (a: number, b: number) => void;
|
|
112
127
|
readonly runArrival: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => [number, number, number];
|
|
113
|
-
readonly runRange: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => [number, number, number];
|
|
128
|
+
readonly runRange: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => [number, number, number];
|
|
114
129
|
readonly vulturetimetable_allRoutes: (a: number) => [number, number, number];
|
|
115
130
|
readonly vulturetimetable_allStops: (a: number) => [number, number, number];
|
|
116
131
|
readonly vulturetimetable_nRoutes: (a: number) => number;
|
|
@@ -119,6 +134,7 @@ export interface InitOutput {
|
|
|
119
134
|
readonly vulturetimetable_resetFootpaths: (a: number) => [number, number];
|
|
120
135
|
readonly vulturetimetable_routeAgency: (a: number, b: number) => [number, number];
|
|
121
136
|
readonly vulturetimetable_routeName: (a: number, b: number) => [number, number];
|
|
137
|
+
readonly vulturetimetable_stationStops: (a: number, b: number, c: number) => [number, number];
|
|
122
138
|
readonly vulturetimetable_stopCoords: (a: number, b: number) => [number, number];
|
|
123
139
|
readonly vulturetimetable_stopIdx: (a: number, b: number, c: number) => number;
|
|
124
140
|
readonly vulturetimetable_stopName: (a: number, b: number) => [number, number];
|
package/vulture_wasm.js
CHANGED
|
@@ -126,6 +126,28 @@ export class VultureTimetable {
|
|
|
126
126
|
}
|
|
127
127
|
return v1;
|
|
128
128
|
}
|
|
129
|
+
/**
|
|
130
|
+
* Expand a parent station's GTFS id into the platform stop
|
|
131
|
+
* indices that hang off it. Returns an empty array if `parent_id`
|
|
132
|
+
* is not a parent station in the feed (or has no children).
|
|
133
|
+
*
|
|
134
|
+
* Useful for the "any platform of this station" pattern: in
|
|
135
|
+
* GTFS, vehicles only board at platform-level stops
|
|
136
|
+
* (`location_type = 0`), so a query rooted at the parent station
|
|
137
|
+
* (`location_type = 1`) returns nothing. Pass this method's
|
|
138
|
+
* result as `originStops` / `targetStops` to query against every
|
|
139
|
+
* platform.
|
|
140
|
+
* @param {string} parent_id
|
|
141
|
+
* @returns {Uint32Array}
|
|
142
|
+
*/
|
|
143
|
+
stationStops(parent_id) {
|
|
144
|
+
const ptr0 = passStringToWasm0(parent_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
145
|
+
const len0 = WASM_VECTOR_LEN;
|
|
146
|
+
const ret = wasm.vulturetimetable_stationStops(this.__wbg_ptr, ptr0, len0);
|
|
147
|
+
var v2 = getArrayU32FromWasm0(ret[0], ret[1]).slice();
|
|
148
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
|
|
149
|
+
return v2;
|
|
150
|
+
}
|
|
129
151
|
/**
|
|
130
152
|
* Returns the GTFS `[lat, lon]` for the given stop index, or
|
|
131
153
|
* `undefined` if the stop has no coordinates set.
|
|
@@ -212,26 +234,32 @@ export function runArrival(tt, origins, targets, max_transfers, depart, require_
|
|
|
212
234
|
|
|
213
235
|
/**
|
|
214
236
|
* Range query: run RAPTOR across a window of departure times. JS
|
|
215
|
-
* passes `
|
|
216
|
-
*
|
|
217
|
-
* `
|
|
237
|
+
* passes `origins` / `targets` as `Uint32Array`s of stop indices
|
|
238
|
+
* (each entry gets walk-time zero), and `departures` as a
|
|
239
|
+
* `Uint32Array` of seconds-since-midnight values. Returns
|
|
240
|
+
* `[{depart, journey}]` Pareto-filtered on `(later depart, fewer
|
|
241
|
+
* transfers, earlier arrival)`.
|
|
218
242
|
*
|
|
219
|
-
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
243
|
+
* Multi-source / multi-target so the "any platform of this station"
|
|
244
|
+
* pattern (via `tt.stationStops(parent_id)`) works the same way as
|
|
245
|
+
* in `runArrival`.
|
|
222
246
|
* @param {VultureTimetable} tt
|
|
223
|
-
* @param {
|
|
224
|
-
* @param {
|
|
247
|
+
* @param {Uint32Array} origins
|
|
248
|
+
* @param {Uint32Array} targets
|
|
225
249
|
* @param {number} max_transfers
|
|
226
250
|
* @param {Uint32Array} departures
|
|
227
251
|
* @param {boolean} require_wheelchair
|
|
228
252
|
* @returns {any}
|
|
229
253
|
*/
|
|
230
|
-
export function runRange(tt,
|
|
254
|
+
export function runRange(tt, origins, targets, max_transfers, departures, require_wheelchair) {
|
|
231
255
|
_assertClass(tt, VultureTimetable);
|
|
232
|
-
const ptr0 = passArray32ToWasm0(
|
|
256
|
+
const ptr0 = passArray32ToWasm0(origins, wasm.__wbindgen_malloc);
|
|
233
257
|
const len0 = WASM_VECTOR_LEN;
|
|
234
|
-
const
|
|
258
|
+
const ptr1 = passArray32ToWasm0(targets, wasm.__wbindgen_malloc);
|
|
259
|
+
const len1 = WASM_VECTOR_LEN;
|
|
260
|
+
const ptr2 = passArray32ToWasm0(departures, wasm.__wbindgen_malloc);
|
|
261
|
+
const len2 = WASM_VECTOR_LEN;
|
|
262
|
+
const ret = wasm.runRange(tt.__wbg_ptr, ptr0, len0, ptr1, len1, max_transfers, ptr2, len2, require_wheelchair);
|
|
235
263
|
if (ret[2]) {
|
|
236
264
|
throw takeFromExternrefTable0(ret[1]);
|
|
237
265
|
}
|
|
@@ -343,6 +371,11 @@ function getArrayF64FromWasm0(ptr, len) {
|
|
|
343
371
|
return getFloat64ArrayMemory0().subarray(ptr / 8, ptr / 8 + len);
|
|
344
372
|
}
|
|
345
373
|
|
|
374
|
+
function getArrayU32FromWasm0(ptr, len) {
|
|
375
|
+
ptr = ptr >>> 0;
|
|
376
|
+
return getUint32ArrayMemory0().subarray(ptr / 4, ptr / 4 + len);
|
|
377
|
+
}
|
|
378
|
+
|
|
346
379
|
let cachedDataViewMemory0 = null;
|
|
347
380
|
function getDataViewMemory0() {
|
|
348
381
|
if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
|
package/vulture_wasm_bg.wasm
CHANGED
|
Binary file
|