maplibre-tilepackage-protocol 1.1.0 → 1.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/README.md CHANGED
@@ -1,78 +1,143 @@
1
1
  # maplibre-tilepackage-protocol
2
2
 
3
- As an ES6 module: `npm add maplibre-tilepackage-protocol`
3
+ Custom MapLibre GL JS protocol for reading Esri `TPKX` (raster) and `VTPK` (vector) TilePackage archives.
4
4
 
5
- ```js
6
- import * as tilePackage from "maplibre-tilepackage-protocol";
7
- ```
5
+ Works with:
6
+
7
+ - Local files selected via an `<input type="file">` (no server required)
8
+ - Relative or absolute HTTP(S) URLs to remote TilePackages
9
+
10
+ The protocol streams tiles, glyphs and sprites directly from the archive. For VTPK it synthesizes a ready-to-use MapLibre style (rewriting sources + sprite + glyphs).
8
11
 
9
- ## MapLibre GL JS
12
+ ## Install
10
13
 
11
- Example of a TPKX/VTPK archive displayed in MapLibre GL JS:
14
+ ```bash
15
+ npm add maplibre-tilepackage-protocol
16
+ ```
17
+
18
+ ## Import (ESM)
12
19
 
13
20
  ```js
14
- import * as tilePackage from "maplibre-tilepackage-protocol";
15
- let protocol = new tilePackage.Protocol();
16
- maplibregl.addProtocol("tilepackage",protocol.package);
17
- var style = {
18
- "version": 8,
19
- "sources": {
20
- "example_source": {
21
- "type": "raster",
22
- "url": "tilepackage://https://example.com/example.tpkx",
23
- ...
21
+ import {
22
+ Protocol,
23
+ FileSource,
24
+ TilePackage,
25
+ } from "maplibre-tilepackage-protocol";
24
26
  ```
25
27
 
26
- ## TPKX
28
+ ## Quick Start (Remote Raster TPKX)
27
29
 
28
- A TPKX file containes a full tile pyramid and you just treat it as any other raster source.
30
+ ```js
31
+ const protocol = new Protocol();
32
+ maplibregl.addProtocol("tilepackage", protocol.package);
33
+
34
+ const style = {
35
+ version: 8,
36
+ sources: {
37
+ raster: {
38
+ type: "raster",
39
+ url: "tilepackage://https://example.com/data/example.tpkx",
40
+ },
41
+ },
42
+ layers: [{ id: "raster", type: "raster", source: "raster" }],
43
+ };
44
+
45
+ new maplibregl.Map({ container: "map", style });
46
+ ```
29
47
 
30
- ## VTPK
48
+ Equivalent explicit tiles form:
31
49
 
32
- Primarily flat VTPK files are supported, see below for indexed VTPK files.
50
+ ```js
51
+ tiles: ["tilepackage://https://example.com/data/example.tpkx/{z}/{x}/{y}"];
52
+ ```
33
53
 
34
- The file also contains everything you need for your map, such as a style with layers, glyphs, and spirits. You can get everything you need using the tilepackage.
54
+ ## Local File VTPK
35
55
 
36
56
  ```js
37
- async initMap(package){
38
- const header = await package.getHeader();
39
- if (header.spatialReference == 3857) {
40
- const style = await package.getStyle();
41
- new maplibregl.Map({
42
- container: "map-element",
43
- localIdeographFontFamily: false,
44
- style: style,
45
- });
46
- }
57
+ const protocol = new Protocol({ debug: true });
58
+ maplibregl.addProtocol("tilepackage", protocol.package);
59
+
60
+ async function initFromFile(file) {
61
+ const pkg = new TilePackage(new FileSource(file)); // coverageCheck defaults ON
62
+ protocol.add(pkg); // register so sprite/glyph URLs resolve
63
+ const style = await pkg.getStyle();
64
+ new maplibregl.Map({ container: "map", style });
47
65
  }
66
+ ```
67
+
68
+ On HTTP(S) you can instead point a style source to a relative URL:
48
69
 
49
- const source = String || tilePackage.FileSource;
50
- const package = new tilePackage.TilePackage(
51
- source,
52
- );
53
- initMap(package)
70
+ ```js
71
+ url: "tilepackage://./data/archive.vtpk";
54
72
  ```
55
73
 
56
- A VTPK file may contain an indexed tile pyramid where some tiles are missing, because of this you should always initialze a vtpk file with:
74
+ ## Vector Style Rewriting
75
+
76
+ `TilePackage#getStyle()` for VTPK replaces any `url` with a `tiles` array (`tilepackage://<key>/{z}/{x}/{y}`), and sets `sprite` & `glyphs` to protocol endpoints. This avoids extra TileJSON requests that fail under `file://`.
77
+
78
+ ## Indexed Pyramids & Overzoom Fallback
79
+
80
+ Some VTPK archives have variable depth (gaps). Missing higher-zoom tiles are automatically synthesized from a parent using an internal subdivision algorithm when a coverage map (`tilemap/root.json`) is present.
81
+
82
+ Behavior:
83
+
84
+ - Parent search ascends until a node with value `1` in the coverage map.
85
+ - The parent vector tile is decoded, features clipped/scaled, and re-encoded to PBF.
86
+ - Generated tiles are cached (`SharedPromiseCache.subdivided`) to avoid repeat work.
87
+
88
+ Disable subdivision by constructing the package with `coverageCheck:false`:
57
89
 
58
90
  ```js
59
- let protocol = new tilePackage.Protocol({
60
- errorOnMissingTile: true,
61
- });
91
+ const pkg = new TilePackage(new FileSource(file), { coverageCheck: false });
62
92
  ```
63
93
 
64
- This will make tiles from lower zoom levels remain in view when you zoom into the map. Unfortunatly it is not possible to get the tiles to over scale in the same way as in ArcGIS Pro without modifying the source cache code in Maplibre. https://github.com/maplibre/maplibre-gl-js/issues/5618
94
+ If you prefer MapLibre's default empty tile behavior (no lower-zoom retention) you can set protocol option `errorOnMissingTile:true` to raise errors for missing PBF tiles.
95
+
96
+ ### Caching
97
+
98
+ Overzoomed tiles are stored in-memory for the session. A simple size-based prune removes half of entries when exceeding `maxCacheEntries * 2`. (Future: LRU + byte-size thresholds.) Subdivision will be skipped entirely if the zoom delta exceeds the hard cap `maxDz` (default `8`).
99
+
100
+ ### Performance Notes
101
+
102
+ - Large zoom jumps (high `dz`) cost more CPU; consider constraining user zoom range.
103
+ - Subdivision adds latency only on first request; subsequent hits are served from cache.
104
+ - Disable with `coverageCheck:false` for pure flat packages when you do not want synthesis.
105
+ - Tune with `maxDz` (e.g. set `maxDz:4`) to limit deep subdivision while allowing shallow overzoom.
106
+
107
+ ## API Summary
65
108
 
66
- # Acknowledgement
109
+ - `new TilePackage(source, { coverageCheck, maxDz })` – `source` is URL string or `FileSource`. `coverageCheck` defaults to `true` enabling coverage map + overzoom; `maxDz` (default `8`) hard‑caps subdivision depth.
110
+ - `TilePackage#getHeader()` – name, zooms, bounds, tile type.
111
+ - `TilePackage#getStyle()` – raster style (TPKX) or rewritten vector style (VTPK).
112
+ - `TilePackage#getZxy(z,x,y)` – raw tile bytes (PBF or raster image ArrayBuffer).
113
+ - `Protocol.add(pkg)` – register local file-backed packages for glyph/sprite resolution.
114
+ - `Protocol` options: `metadata`, `errorOnMissingTile`, `debug`.
67
115
 
68
- The code for this protocol was based on the PMTiles protocol by Protomaps LLC.
116
+ ## Debug Logging
69
117
 
70
- # Sample data
118
+ Enable `debug:true` in `Protocol` for tile fetch + instance events. Coverage ascent & subdivision messages use `[tilepackage coverage]` and `[tilepackage subdivide]` prefixes.
71
119
 
72
- A sample dataset covering Austria can be downloaded from the following link. Note that this file is an indexed VTPK and won't display all tiles correctly without modifying Maplibre.
120
+ ## Demo
73
121
 
122
+ The `example/` directory demonstrates local file selection, remote/relative URL input, auto-load of a demo archive, and overzoom fallback.
123
+
124
+ ## TPKX Notes
125
+
126
+ TPKX contains a full raster pyramid; no style synthesis beyond setting a raster source.
127
+
128
+ ## VTPK Notes
129
+
130
+ Flat and indexed VTPK archives are supported. Indexed packages rely on the overzoom fallback described above for visual continuity.
131
+
132
+ ## Sample Data
133
+
134
+ Austria indexed VTPK sample:
74
135
  https://www.data.gv.at/katalog/de/dataset/basemap-at-verwaltungsgrundkarte-vektor-offline-osterreich#resources
75
136
 
76
- # Supporting my work
137
+ ## Acknowledgement
138
+
139
+ Inspired by concepts from PMTiles protocol (Protomaps LLC).
140
+
141
+ ## Support
77
142
 
78
- If you like my work and would like to support it, please use https://buymeacoffee.com/spatialillusion
143
+ If this project helps you, consider supporting: https://buymeacoffee.com/spatialillusion