@glandais/vcyclist-engine 1.2.1 → 2.0.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 +80 -8
- package/kotlin-kotlin-stdlib.js +2681 -1710
- package/kotlin-kotlin-stdlib.js.map +1 -1
- package/kotlinx-atomicfu.js +22 -22
- package/kotlinx-coroutines-core.js +1218 -1211
- package/kotlinx-coroutines-core.js.map +1 -1
- package/kotlinx-serialization-kotlinx-serialization-core.js +1 -1
- package/package.json +3 -2
- package/vcyclist-elevation.js +923 -896
- package/vcyclist-elevation.js.map +1 -1
- package/vcyclist-engine.d.ts +10 -0
- package/vcyclist-engine.js +1174 -2542
- package/vcyclist-engine.js.map +1 -1
- package/vcyclist-fit.js +656 -0
- package/vcyclist-fit.js.map +1 -0
- package/vcyclist-gpx.js +3401 -0
- package/vcyclist-gpx.js.map +1 -0
- package/xmlutil-core.js +2717 -2718
- package/xmlutil-core.js.map +1 -1
package/README.md
CHANGED
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/@glandais/vcyclist-engine)
|
|
4
4
|
[](https://www.npmjs.com/package/@glandais/vcyclist-elevation)
|
|
5
5
|
[](https://central.sonatype.com/artifact/io.github.glandais/vcyclist-engine)
|
|
6
|
+
[](https://central.sonatype.com/artifact/io.github.glandais/vcyclist-gpx)
|
|
7
|
+
[](https://central.sonatype.com/artifact/io.github.glandais/vcyclist-fit)
|
|
8
|
+
[](https://central.sonatype.com/artifact/io.github.glandais/vcyclist-map)
|
|
6
9
|
|
|
7
10
|
Kotlin Multiplatform port of [`@glandais/virtual-cyclist`](https://github.com/glandais/virtual-cyclist):
|
|
8
11
|
physics-based cycling simulator that turns a static GPS trace into a virtualized ride with
|
|
@@ -38,9 +41,21 @@ TypeScript library for elevation data.
|
|
|
38
41
|
| Module | Purpose | Targets |
|
|
39
42
|
|---|---|---|
|
|
40
43
|
| **`:elevation`** | Terrarium tile fetch + DEM lookup + Haversine + Douglas-Peucker 3D + triangular smoother. See [`elevation/README.md`](elevation/README.md). | JVM, JS Node, JS browser, Wasm browser |
|
|
41
|
-
| **`:
|
|
44
|
+
| **`:gpx`** | Path model (36 fields × `DoubleArray`), resamplers, Douglas-Peucker simplifier, elevation steps, GPX I/O. Published to Maven Central; **not** published to npm — its JS output ships inside `@glandais/vcyclist-engine`. | JVM, JS Node, JS browser, Wasm browser |
|
|
45
|
+
| **`:engine`** | Physics (4 resistive `PowerProvider`s + cyclist input + `MaxSpeedComputer` + `VirtualizeService`), `Enhancer` pipeline, JVM CLI, JS/Wasm façades. Re-exports `:gpx` via `api`, so `io.github.glandais.engine.path.*` and `…engine.gpx.*` stay importable from `:engine`. | JVM, JS Node, JS browser, Wasm browser |
|
|
46
|
+
| **`:fit`** | Garmin FIT encoding. `FitCourse` model + unit conversions in commonMain; `expect object FitEncoder` with a JVM `actual` on `com.garmin:fit` and JS/Wasm `actual`s on `@garmin/fitsdk`. | JVM, JS Node, JS browser, Wasm browser |
|
|
47
|
+
| **`:map`** | Static map rendering: Web Mercator projection, image framing, tile download + cache, PNG output (`java.awt` / `ImageIO`). **JVM-only.** No default tile source — see [`map/README.md`](map/README.md) for the usage-policy obligations. | JVM only |
|
|
48
|
+
| **`:cli`** | Command-line tool (picocli). **JVM-only, not published as a library** — distributed as an executable jar. Replaces gpx2web's `gpxtools-cli`. | JVM only |
|
|
42
49
|
| **`:codegen`** | Tiny build-time helper that regenerates `GeneratedPath.kt` + `PointFieldAccessors.kt` from `PointField` (run only when the field list changes). | JVM only |
|
|
43
50
|
|
|
51
|
+
### Migrating from gpx2web
|
|
52
|
+
|
|
53
|
+
vcyclist replaces the `gpx` and `gpxtools-cli` modules of
|
|
54
|
+
[gpx2web](https://github.com/glandais/gpx2web).
|
|
55
|
+
[`docs/gpx2web-coverage.md`](docs/gpx2web-coverage.md) has one row per Java class — ported,
|
|
56
|
+
replaced, or not ported with the reason — plus the deliberate behavioural differences. For the
|
|
57
|
+
command-line options specifically, see [`cli/README.md`](cli/README.md).
|
|
58
|
+
|
|
44
59
|
## Install
|
|
45
60
|
|
|
46
61
|
### npm (Kotlin/JS or Kotlin/Wasm consumers)
|
|
@@ -64,20 +79,32 @@ dependencies {
|
|
|
64
79
|
|
|
65
80
|
Replace `1.0.0` by the latest version shown in the badges above. KMP consumers automatically
|
|
66
81
|
get the platform-specific variant (`-jvm`, `-js`, `-wasm-js`) for their target.
|
|
82
|
+
`vcyclist-gpx` (the `Path` model + GPX I/O) comes in transitively via `vcyclist-engine`, and
|
|
83
|
+
can also be depended on alone if you only need parsing and resampling.
|
|
67
84
|
|
|
68
85
|
See [`docs/publishing.md`](docs/publishing.md) for the release process.
|
|
69
86
|
|
|
70
87
|
## Quick start
|
|
71
88
|
|
|
72
|
-
### Run the
|
|
89
|
+
### Run the CLI
|
|
90
|
+
|
|
91
|
+
The CLI is **not** on Maven Central — it is an application, distributed as a self-contained jar
|
|
92
|
+
attached to each [GitHub release](https://github.com/glandais/vcyclist/releases). Download
|
|
93
|
+
`vcyclist-cli-<version>-all.jar` and run it with Java 21+, or build it yourself:
|
|
73
94
|
|
|
74
95
|
```bash
|
|
75
|
-
#
|
|
76
|
-
./gradlew :
|
|
96
|
+
# Build a self-contained jar, then run it from anywhere:
|
|
97
|
+
./gradlew :cli:executableJar
|
|
98
|
+
java -jar cli/build/libs/vcyclist-cli-*-all.jar enhance route.gpx --gpx out.gpx --csv out.csv
|
|
99
|
+
|
|
100
|
+
# Or, during development:
|
|
101
|
+
./gradlew :cli:run -Pargs="enhance route.gpx --gpx /tmp/out.gpx"
|
|
77
102
|
```
|
|
78
103
|
|
|
79
|
-
|
|
80
|
-
|
|
104
|
+
`enhance` runs the physics pipeline; `export` produces maps, FIT, CSV and JSON from a file you
|
|
105
|
+
already have. Elevation correction is off unless you pass `--fix-elevation`, so nothing touches
|
|
106
|
+
the network by default. Full usage, exit codes and the migration table from gpx2web's
|
|
107
|
+
`gpxtools-cli` are in [`cli/README.md`](cli/README.md).
|
|
81
108
|
|
|
82
109
|
### Try the browser demos (elevation only)
|
|
83
110
|
|
|
@@ -115,10 +142,26 @@ suspend fun virtualize(xml: String): String {
|
|
|
115
142
|
The Kotlin/JS variant (`@glandais/vcyclist-engine`, `@glandais/vcyclist-elevation`) runs
|
|
116
143
|
**in both browser and Node.js / Bun**. The Wasm variants (`*-wasm`) are browser-only.
|
|
117
144
|
|
|
145
|
+
#### Getting at the exports
|
|
146
|
+
|
|
147
|
+
Kotlin/JS emits a **UMD bundle that preserves the package namespace**, so the module has
|
|
148
|
+
exactly one top-level export, `io`. Named imports do not work — `import { parseGpx } from
|
|
149
|
+
'@glandais/vcyclist-engine'` fails under Node ESM with *"Named export 'parseGpx' not found"*.
|
|
150
|
+
Unwrap the namespace once and destructure from it :
|
|
151
|
+
|
|
152
|
+
```js
|
|
153
|
+
import * as engineRaw from '@glandais/vcyclist-engine'; // or: require('@glandais/vcyclist-engine')
|
|
154
|
+
|
|
155
|
+
const engine = engineRaw.io.github.glandais.engine;
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Every snippet below assumes that `engine`. `demo/src/engine-shim.ts` does the same unwrap and
|
|
159
|
+
adds TypeScript types for the DTOs, which Kotlin/JS emits as referenced names only.
|
|
160
|
+
|
|
118
161
|
#### Browser
|
|
119
162
|
|
|
120
163
|
```js
|
|
121
|
-
|
|
164
|
+
const { parseGpx, enhance, writeGpx, pathSize, pathTotalDistance } = engine;
|
|
122
165
|
|
|
123
166
|
const handle = parseGpx(gpxXml);
|
|
124
167
|
console.log('input points:', pathSize(handle));
|
|
@@ -130,7 +173,7 @@ const xml = writeGpx(out);
|
|
|
130
173
|
#### Node.js / Bun (with elevation correction)
|
|
131
174
|
|
|
132
175
|
```js
|
|
133
|
-
|
|
176
|
+
const { parseGpx, enhance, writeGpx } = engine;
|
|
134
177
|
|
|
135
178
|
const handle = parseGpx(gpxXml);
|
|
136
179
|
const out = await enhance(handle, { fixElevation: true }); // fetches DEM tiles, decodes WebP
|
|
@@ -141,6 +184,35 @@ const xml = writeGpx(out);
|
|
|
141
184
|
(mapterhorn Terrarium tiles) and runs the full pipeline (densify → fix elevation → smooth →
|
|
142
185
|
max speeds → virtualize → resample → simplify).
|
|
143
186
|
|
|
187
|
+
#### FIT export
|
|
188
|
+
|
|
189
|
+
```js
|
|
190
|
+
const { parseGpx, enhance, pathToFit } = engine;
|
|
191
|
+
|
|
192
|
+
const out = await enhance(parseGpx(gpxXml), null);
|
|
193
|
+
const fit = pathToFit(out, 'My route', Date.parse('2026-08-01T08:00:00Z'));
|
|
194
|
+
// Kotlin/JS returns an Int8Array; the -wasm build returns a Uint8Array. Both are the same file.
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
FIT has no relative clock, so the start instant is mandatory. The output is a **Course** file
|
|
198
|
+
(a route to follow), which is what a virtualized trace should be — not an Activity.
|
|
199
|
+
|
|
200
|
+
#### Multi-track GPX
|
|
201
|
+
|
|
202
|
+
`parseGpx` returns the **first** track, which is what most files contain. For documents with
|
|
203
|
+
several `<trk>` or several `<trkseg>` :
|
|
204
|
+
|
|
205
|
+
```js
|
|
206
|
+
const { parseGpxTracks, parseGpxSegments, writeGpxTracks } = engine;
|
|
207
|
+
|
|
208
|
+
const tracks = parseGpxTracks(gpxXml); // one path per <trk>, segments concatenated
|
|
209
|
+
const segments = parseGpxSegments(gpxXml); // one path per <trkseg>, always continuous
|
|
210
|
+
const xml = writeGpxTracks(tracks); // one <trk> per path
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Concatenating segments folds the pause between them into `totalDistance` — a `<trkseg>`
|
|
214
|
+
boundary is a physical discontinuity. Use `parseGpxSegments` when that artefact matters.
|
|
215
|
+
|
|
144
216
|
On Node.js / Bun, tile decoding uses [`@jsquash/webp`](https://www.npmjs.com/package/@jsquash/webp)
|
|
145
217
|
(a pure-WASM WebP decoder, ~50 KB, listed as a runtime `dependency` of
|
|
146
218
|
`@glandais/vcyclist-engine` and `@glandais/vcyclist-elevation`). It is loaded lazily via
|