isard 0.2.0 → 0.3.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.
Files changed (93) hide show
  1. package/CHANGELOG.md +134 -14
  2. package/README.md +2 -2
  3. package/dist/animation.d.ts +18 -0
  4. package/dist/animation.js +84 -0
  5. package/dist/animation.js.map +1 -0
  6. package/dist/basemap.worker.d.ts +26 -1
  7. package/dist/basemap.worker.js +2 -2
  8. package/dist/basemap.worker.js.map +8 -4
  9. package/dist/basemaps.d.ts +5 -3
  10. package/dist/basemaps.js +5 -3
  11. package/dist/basemaps.js.map +1 -1
  12. package/dist/crs.d.ts +72 -0
  13. package/dist/crs.js +243 -0
  14. package/dist/crs.js.map +1 -0
  15. package/dist/decoder.worker.js +4 -4
  16. package/dist/decoder.worker.js.map +4 -4
  17. package/dist/engine-loader.d.ts +27 -0
  18. package/dist/engine-loader.js +112 -0
  19. package/dist/engine-loader.js.map +1 -0
  20. package/dist/extrusions.js +11 -2
  21. package/dist/extrusions.js.map +1 -1
  22. package/dist/features.d.ts +8 -0
  23. package/dist/features.js +17 -10
  24. package/dist/features.js.map +1 -1
  25. package/dist/geo.d.ts +16 -0
  26. package/dist/geo.js +32 -0
  27. package/dist/geo.js.map +1 -0
  28. package/dist/geoplateforme.d.ts +21 -5
  29. package/dist/geoplateforme.js +47 -12
  30. package/dist/geoplateforme.js.map +1 -1
  31. package/dist/glyphs.d.ts +10 -3
  32. package/dist/glyphs.js +14 -2
  33. package/dist/glyphs.js.map +1 -1
  34. package/dist/gpx.d.ts +11 -0
  35. package/dist/gpx.js +74 -0
  36. package/dist/gpx.js.map +1 -0
  37. package/dist/grid.d.ts +81 -0
  38. package/dist/grid.js +270 -0
  39. package/dist/grid.js.map +1 -0
  40. package/dist/index.d.ts +7 -1
  41. package/dist/index.js +5 -0
  42. package/dist/index.js.map +1 -1
  43. package/dist/interaction.d.ts +3 -4
  44. package/dist/interaction.js +27 -7
  45. package/dist/interaction.js.map +1 -1
  46. package/dist/isard_bg.wasm +0 -0
  47. package/dist/isard_core_bg.wasm +0 -0
  48. package/dist/kml.d.ts +12 -0
  49. package/dist/kml.js +159 -0
  50. package/dist/kml.js.map +1 -0
  51. package/dist/layers.d.ts +5 -2
  52. package/dist/layers.js +22 -18
  53. package/dist/layers.js.map +1 -1
  54. package/dist/lru.d.ts +22 -0
  55. package/dist/lru.js +52 -0
  56. package/dist/lru.js.map +1 -0
  57. package/dist/map.d.ts +26 -6
  58. package/dist/map.js +196 -287
  59. package/dist/map.js.map +1 -1
  60. package/dist/resample.d.ts +41 -0
  61. package/dist/resample.js +164 -0
  62. package/dist/resample.js.map +1 -0
  63. package/dist/settings.d.ts +39 -0
  64. package/dist/settings.js +104 -0
  65. package/dist/settings.js.map +1 -0
  66. package/dist/symbols.d.ts +12 -1
  67. package/dist/symbols.js +124 -26
  68. package/dist/symbols.js.map +1 -1
  69. package/dist/terrain.d.ts +19 -7
  70. package/dist/terrain.js +50 -26
  71. package/dist/terrain.js.map +1 -1
  72. package/dist/topojson.d.ts +29 -0
  73. package/dist/topojson.js +66 -0
  74. package/dist/topojson.js.map +1 -0
  75. package/dist/types.d.ts +23 -7
  76. package/dist/types.js.map +1 -1
  77. package/dist/vectortiles.d.ts +13 -3
  78. package/dist/vectortiles.js +85 -46
  79. package/dist/vectortiles.js.map +1 -1
  80. package/dist/wasm/isard.d.ts +14 -7
  81. package/dist/wasm/isard.js +33 -10
  82. package/dist/wasm/isard_core.d.ts +6 -5
  83. package/dist/wasm/isard_core.js +41 -10
  84. package/dist/wmts.d.ts +14 -0
  85. package/dist/wmts.js +76 -0
  86. package/dist/wmts.js.map +1 -0
  87. package/dist/xml.d.ts +26 -0
  88. package/dist/xml.js +109 -0
  89. package/dist/xml.js.map +1 -0
  90. package/package.json +1 -1
  91. package/dist/equirectangular.d.ts +0 -35
  92. package/dist/equirectangular.js +0 -113
  93. package/dist/equirectangular.js.map +0 -1
package/dist/grid.d.ts ADDED
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Rasters in another tile grid, the planning half: a WMTS-like tile matrix set in any CRS (Lambert-93, UTM, longitudes
3
+ * and latitudes…), or a WMS asked for a box in that CRS, reprojected into the Web Mercator tiles the engine draws. For
4
+ * each Mercator tile the page projects a mesh of 17 × 17 points of the tile into the source CRS (the only projection
5
+ * work: 289 points a tile, whatever its size), picks the source level of the same pixel size, and lists the source
6
+ * images the tile spans; the drawing (`resample.ts`) is done by a worker of the map, or in the page without workers.
7
+ */
8
+ import { type Crs, type CrsLike } from './crs.ts';
9
+ import { type Job } from './resample.ts';
10
+ /** One level of a tile grid, as a `TileMatrix` of WMTS */
11
+ export interface TileMatrix {
12
+ /** What replaces {z} in the URL (the `TILEMATRIX` of a WMTS; default the index of the matrix in the grid) */
13
+ id?: string | number;
14
+ /** Size of a pixel, CRS units (WMTS: its `ScaleDenominator` × 0.00028 m, in CRS units) */
15
+ resolution: number;
16
+ /** Top-left corner of the tile (0, 0), CRS units (x east, y north) */
17
+ origin: [x: number, y: number];
18
+ /** Size of a tile, pixels (default 256) */
19
+ tileWidth?: number;
20
+ tileHeight?: number;
21
+ /** Tiles across and down (default unbounded) */
22
+ matrixWidth?: number;
23
+ matrixHeight?: number;
24
+ /** The tiles the source has (a WMTS's `TileMatrixLimits`), inclusive: none is asked for outside */
25
+ limits?: [minCol: number, minRow: number, maxCol: number, maxRow: number];
26
+ }
27
+ /**
28
+ * A raster's tile grid in a CRS of its own, reprojected into Web Mercator by the map: `matrices` for tiles ({z}, {x},
29
+ * {y} in the URL: matrix, column, row, rows from the north), none for a WMS whose URL has `{bbox}` (the box of each
30
+ * Mercator tile in that CRS: minimum x, minimum y, maximum x, maximum y, asked for at the tile's size)
31
+ */
32
+ export interface TileGrid {
33
+ /** `'EPSG:2154'`, another built-in or registered name, or an object with `forward` and `inverse` (proj4's) */
34
+ crs: CrsLike;
35
+ /** The levels of the grid, in any order */
36
+ matrices?: TileMatrix[];
37
+ /** Longitudes and latitudes the source covers (west, south, east, north): nothing is asked for outside */
38
+ bounds?: [west: number, south: number, east: number, north: number];
39
+ /** Identifier of the tile matrix set (a WMTS's `TILEMATRIXSET`), for the helpers that write the URL */
40
+ name?: string;
41
+ }
42
+ interface Matrix extends Required<Omit<TileMatrix, 'limits' | 'id'>> {
43
+ id: string | number;
44
+ limits: [number, number, number, number] | undefined;
45
+ }
46
+ interface Resolved {
47
+ crs: Crs;
48
+ /** Coarsest first */
49
+ matrices: Matrix[];
50
+ bounds: [number, number, number, number] | undefined;
51
+ /** The bounds in the CRS: minimum x, minimum y, maximum x, maximum y */
52
+ extent: [number, number, number, number] | undefined;
53
+ }
54
+ /** A tile grid ready to plan tiles: its CRS found, its matrices completed, its bounds projected */
55
+ export declare function resolveGrid(grid: TileGrid): Resolved;
56
+ /** The longitudes and latitudes of tiles in longitudes and latitudes, two 256 px tiles side by side at level 0, rows
57
+ * from the north (NASA's Trek, WorldCRS84Quad), levels `minLevel` to `maxLevel` ({z} is the level) */
58
+ export declare function equirectangularGrid(minLevel: number, maxLevel: number): TileGrid;
59
+ /**
60
+ * The plan of Mercator tile `z`/`x`/`y` (`size` pixels a side) from a source of URL template `url` in grid `g`; null
61
+ * where the source has nothing
62
+ */
63
+ export declare function planTile(g: Resolved, url: string, z: number, x: number, y: number, size: number): Job | null;
64
+ /**
65
+ * The map zooms a grid's matrices span (the pixel size of the finest and of the coarsest, two levels coarser, where
66
+ * the tiles still fit a mosaic), measured at the middle of its bounds, or of its coarsest matrix
67
+ */
68
+ export declare function gridZooms(g: Resolved): {
69
+ minZoom: number;
70
+ maxZoom: number;
71
+ };
72
+ /** Draws a Mercator tile `z`/`x`/`y`: its image, null where the source has nothing; rejects on errors */
73
+ type Draw = (z: number, x: number, y: number, signal: AbortSignal) => Promise<ImageBitmap | null>;
74
+ /** A planned tile drawn in a worker; undefined when the map has no workers (drawn in the page) */
75
+ export type RemoteReprojection = (job: Job, tile: [z: number, x: number, y: number], signal: AbortSignal) => Promise<ImageBitmap | null> | undefined;
76
+ /**
77
+ * A raster loader drawing Web Mercator tiles of `size` pixels from a source of URL template `url` in tile grid `grid`:
78
+ * planned here, drawn in a worker of the map through `remote` when it can, else in the page
79
+ */
80
+ export declare function gridLoader(url: string, grid: Resolved, size: number, remote?: RemoteReprojection): Draw;
81
+ export {};
package/dist/grid.js ADDED
@@ -0,0 +1,270 @@
1
+ /**
2
+ * Rasters in another tile grid, the planning half: a WMTS-like tile matrix set in any CRS (Lambert-93, UTM, longitudes
3
+ * and latitudes…), or a WMS asked for a box in that CRS, reprojected into the Web Mercator tiles the engine draws. For
4
+ * each Mercator tile the page projects a mesh of 17 × 17 points of the tile into the source CRS (the only projection
5
+ * work: 289 points a tile, whatever its size), picks the source level of the same pixel size, and lists the source
6
+ * images the tile spans; the drawing (`resample.ts`) is done by a worker of the map, or in the page without workers.
7
+ */
8
+ import { getCrs } from "./crs.js";
9
+ import { latitude, longitude, mercatorX, mercatorY } from "./geo.js";
10
+ import { resampler } from "./resample.js";
11
+ /** Cells of the mesh along each side of a tile */
12
+ const N = 16;
13
+ /** Source levels finer at most than the pixel size across, where the grid stretches one axis (towards the poles in
14
+ * longitudes and latitudes) */
15
+ const MAX_BOOST = 3;
16
+ /** Pixels of a mosaic at most: coarser levels beyond, nothing if even the coarsest is larger */
17
+ const MAX_MOSAIC = 2048 * 2048;
18
+ /** A box of the CRS around points of it (x, y, x, y…), NaN ignored; undefined without any */
19
+ function box(points) {
20
+ let [x0, y0, x1, y1] = [Infinity, Infinity, -Infinity, -Infinity];
21
+ for (let k = 0; k + 1 < points.length; k += 2) {
22
+ const [x, y] = [points[k], points[k + 1]];
23
+ if (!Number.isFinite(x) || !Number.isFinite(y))
24
+ continue;
25
+ x0 = Math.min(x0, x);
26
+ y0 = Math.min(y0, y);
27
+ x1 = Math.max(x1, x);
28
+ y1 = Math.max(y1, y);
29
+ }
30
+ return x0 <= x1 ? [x0, y0, x1, y1] : undefined;
31
+ }
32
+ /** A tile grid ready to plan tiles: its CRS found, its matrices completed, its bounds projected */
33
+ export function resolveGrid(grid) {
34
+ const crs = getCrs(grid.crs);
35
+ const matrices = (grid.matrices ?? [])
36
+ .map((m, i) => ({
37
+ id: m.id ?? i,
38
+ resolution: m.resolution,
39
+ origin: m.origin,
40
+ tileWidth: m.tileWidth ?? 256,
41
+ tileHeight: m.tileHeight ?? 256,
42
+ matrixWidth: m.matrixWidth ?? Infinity,
43
+ matrixHeight: m.matrixHeight ?? Infinity,
44
+ limits: m.limits,
45
+ }))
46
+ .sort((a, b) => b.resolution - a.resolution);
47
+ let extent;
48
+ if (grid.bounds) {
49
+ // Its outline and inside, projected: the box of the CRS around them, a little larger (curved edges)
50
+ const [w, s, e, n] = grid.bounds;
51
+ const points = [];
52
+ for (let i = 0; i <= 8; i += 1) {
53
+ for (let j = 0; j <= 8; j += 1)
54
+ points.push(...crs.forward([w + ((e - w) * i) / 8, s + ((n - s) * j) / 8]));
55
+ }
56
+ const b = box(points);
57
+ if (b) {
58
+ const margin = 0.01 * Math.max(b[2] - b[0], b[3] - b[1]);
59
+ extent = [b[0] - margin, b[1] - margin, b[2] + margin, b[3] + margin];
60
+ }
61
+ }
62
+ return { crs, matrices, bounds: grid.bounds, extent };
63
+ }
64
+ /** The longitudes and latitudes of tiles in longitudes and latitudes, two 256 px tiles side by side at level 0, rows
65
+ * from the north (NASA's Trek, WorldCRS84Quad), levels `minLevel` to `maxLevel` ({z} is the level) */
66
+ export function equirectangularGrid(minLevel, maxLevel) {
67
+ const matrices = [];
68
+ for (let level = minLevel; level <= maxLevel; level += 1) {
69
+ const n = 2 ** level;
70
+ matrices.push({ id: level, resolution: 180 / 256 / n, origin: [-180, 90], matrixWidth: 2 * n, matrixHeight: n });
71
+ }
72
+ return { crs: 'EPSG:4326', matrices };
73
+ }
74
+ /** A URL of the source: {z}, {x}, {y}, {bbox}, {width} and {height} replaced */
75
+ function sourceUrl(template, z, x, y, bbox, w, h) {
76
+ return template
77
+ .replaceAll('{z}', String(z))
78
+ .replaceAll('{x}', String(x))
79
+ .replaceAll('{y}', String(y))
80
+ .replaceAll('{bbox}', bbox.join(','))
81
+ .replaceAll('{width}', String(w))
82
+ .replaceAll('{height}', String(h));
83
+ }
84
+ /** CRS units per pixel along the mesh's x and y around its middle (NaN where the CRS has nothing there) */
85
+ function pixelSize(points, size) {
86
+ const c = N / 2;
87
+ const at = (i, j) => 2 * (j * (N + 1) + i);
88
+ const d = (p, q) => Math.hypot(points[q] - points[p], points[q + 1] - points[p + 1]);
89
+ const step = (2 * size) / N;
90
+ return [d(at(c - 1, c), at(c + 1, c)) / step, d(at(c, c - 1), at(c, c + 1)) / step];
91
+ }
92
+ /**
93
+ * The box (CRS) of the points a tile samples: the centers of its edge pixels, interpolated in the mesh as `resample`
94
+ * does, and the inner points of the mesh (should the projection bend); within `clip`. Undefined if none is
95
+ */
96
+ function sampled(points, size, clip) {
97
+ const at = (i, j, k) => points[2 * (j * (N + 1) + i) + k];
98
+ const centers = [];
99
+ for (let j = 1; j < N; j += 1)
100
+ for (let i = 1; i < N; i += 1)
101
+ centers.push(at(i, j, 0), at(i, j, 1));
102
+ const cell = size / N;
103
+ const add = (px, py) => {
104
+ const [fx, fy] = [px / cell, py / cell];
105
+ const [i, j] = [Math.min(N - 1, Math.floor(fx)), Math.min(N - 1, Math.floor(fy))];
106
+ const [tx, ty] = [fx - i, fy - j];
107
+ for (const k of [0, 1]) {
108
+ const top = at(i, j, k) + (at(i + 1, j, k) - at(i, j, k)) * tx;
109
+ const bottom = at(i, j + 1, k) + (at(i + 1, j + 1, k) - at(i, j + 1, k)) * tx;
110
+ centers.push(top + (bottom - top) * ty);
111
+ }
112
+ };
113
+ for (let p = 0.5; p < size; p += 1) {
114
+ add(p, 0.5);
115
+ add(p, size - 0.5);
116
+ add(0.5, p);
117
+ add(size - 0.5, p);
118
+ }
119
+ const b = box(centers);
120
+ if (!b)
121
+ return undefined;
122
+ const out = [
123
+ Math.max(b[0], clip[0]),
124
+ Math.max(b[1], clip[1]),
125
+ Math.min(b[2], clip[2]),
126
+ Math.min(b[3], clip[3]),
127
+ ];
128
+ return out[0] <= out[2] && out[1] <= out[3] ? out : undefined;
129
+ }
130
+ /**
131
+ * The plan of Mercator tile `z`/`x`/`y` (`size` pixels a side) from a source of URL template `url` in grid `g`; null
132
+ * where the source has nothing
133
+ */
134
+ export function planTile(g, url, z, x, y, size) {
135
+ const tiles = 2 ** z;
136
+ if (g.bounds) {
137
+ const [w, s, e, n] = g.bounds;
138
+ if (longitude((x + 1) / tiles) <= w || longitude(x / tiles) >= e)
139
+ return null;
140
+ if (latitude(y / tiles) <= s || latitude((y + 1) / tiles) >= n)
141
+ return null;
142
+ }
143
+ // The mesh in the source CRS
144
+ const points = new Float64Array(2 * (N + 1) ** 2);
145
+ for (let j = 0; j <= N; j += 1) {
146
+ const lat = latitude((y + j / N) / tiles);
147
+ for (let i = 0; i <= N; i += 1) {
148
+ const [px = Number.NaN, py = Number.NaN] = g.crs.forward([longitude((x + i / N) / tiles), lat]);
149
+ points[2 * (j * (N + 1) + i)] = px;
150
+ points[2 * (j * (N + 1) + i) + 1] = py;
151
+ }
152
+ }
153
+ let b = box(points);
154
+ if (!b)
155
+ return null;
156
+ if (g.extent) {
157
+ const e = g.extent;
158
+ b = [Math.max(b[0], e[0]), Math.max(b[1], e[1]), Math.min(b[2], e[2]), Math.min(b[3], e[3])];
159
+ if (b[0] >= b[2] || b[1] >= b[3])
160
+ return null;
161
+ }
162
+ const mesh = new Float32Array(points.length);
163
+ if (g.matrices.length === 0) {
164
+ // One image of the tile's box, a pixel larger on each side
165
+ const [sx, sy] = pixelSize(points, size);
166
+ const m = Number.isFinite(sx + sy) ? Math.max(sx, sy) : 0;
167
+ const [x0, y0, x1, y1] = [b[0] - m, b[1] - m, b[2] + m, b[3] + m];
168
+ for (let k = 0; k < points.length; k += 2) {
169
+ mesh[k] = ((points[k] - x0) / (x1 - x0)) * size;
170
+ mesh[k + 1] = ((y1 - points[k + 1]) / (y1 - y0)) * size;
171
+ }
172
+ const source = { url: sourceUrl(url, z, x, y, [x0, y0, x1, y1], size, size), x: 0, y: 0, w: size, h: size };
173
+ return { size, width: size, height: size, sources: [source], n: N, mesh };
174
+ }
175
+ // The level of the same pixel size, along the axis the grid stretches least (up to MAX_BOOST levels finer)
176
+ const [sx, sy] = pixelSize(points, size);
177
+ const across = Math.max(sx, sy);
178
+ const target = Number.isFinite(across) ? Math.max(Math.min(sx, sy), across / 2 ** MAX_BOOST) : (b[2] - b[0]) / size;
179
+ // Where the pixels of the tile are sampled: the centers of its edge pixels and the mesh, within the source's extent
180
+ const centers = sampled(points, size, b);
181
+ if (!centers)
182
+ return null;
183
+ let best = 0;
184
+ g.matrices.forEach((m, i) => {
185
+ const r = g.matrices[best]?.resolution ?? m.resolution;
186
+ if (Math.abs(Math.log2(m.resolution / target)) < Math.abs(Math.log2(r / target)))
187
+ best = i;
188
+ });
189
+ for (let level = best; level >= 0; level -= 1) {
190
+ const m = g.matrices[level];
191
+ const [ox, oy] = m.origin;
192
+ const [tw, th, res] = [m.tileWidth, m.tileHeight, m.resolution];
193
+ const [l0, r0, l1, r1] = m.limits ?? [0, 0, Infinity, Infinity];
194
+ // The tiles of the source pixels sampled (those of a weight over a thousandth: a tile edge on a source tile edge
195
+ // does not fetch the next source tile for nothing)
196
+ const c0 = Math.max(0, l0, Math.floor(((centers[0] - ox) / res - 0.5 + 1e-3) / tw));
197
+ const c1 = Math.min(m.matrixWidth - 1, l1, Math.floor(((centers[2] - ox) / res + 0.5 - 1e-3) / tw));
198
+ const t0 = Math.max(0, r0, Math.floor(((oy - centers[3]) / res - 0.5 + 1e-3) / th));
199
+ const t1 = Math.min(m.matrixHeight - 1, r1, Math.floor(((oy - centers[1]) / res + 0.5 - 1e-3) / th));
200
+ if (c0 > c1 || t0 > t1)
201
+ return null;
202
+ const [width, height] = [(c1 - c0 + 1) * tw, (t1 - t0 + 1) * th];
203
+ if (width * height > MAX_MOSAIC)
204
+ continue;
205
+ const sources = [];
206
+ for (let row = t0; row <= t1; row += 1) {
207
+ for (let col = c0; col <= c1; col += 1) {
208
+ const bbox = [ox + col * tw * res, oy - (row + 1) * th * res, ox + (col + 1) * tw * res, oy - row * th * res];
209
+ const placed = { x: (col - c0) * tw, y: (row - t0) * th, w: tw, h: th };
210
+ sources.push({ url: sourceUrl(url, m.id, col, row, bbox, tw, th), ...placed });
211
+ }
212
+ }
213
+ for (let k = 0; k < points.length; k += 2) {
214
+ mesh[k] = (points[k] - ox) / res - c0 * tw;
215
+ mesh[k + 1] = (oy - points[k + 1]) / res - t0 * th;
216
+ }
217
+ return { size, width, height, sources, n: N, mesh };
218
+ }
219
+ return null;
220
+ }
221
+ /**
222
+ * The map zooms a grid's matrices span (the pixel size of the finest and of the coarsest, two levels coarser, where
223
+ * the tiles still fit a mosaic), measured at the middle of its bounds, or of its coarsest matrix
224
+ */
225
+ export function gridZooms(g) {
226
+ const coarse = g.matrices[0];
227
+ const fine = g.matrices.at(-1);
228
+ if (!coarse || !fine)
229
+ return { minZoom: 0, maxZoom: 19 };
230
+ let lonLat = [0, 0];
231
+ if (g.bounds)
232
+ lonLat = [(g.bounds[0] + g.bounds[2]) / 2, (g.bounds[1] + g.bounds[3]) / 2];
233
+ else {
234
+ const [l0, r0, l1, r1] = coarse.limits ?? [0, 0, coarse.matrixWidth - 1, coarse.matrixHeight - 1];
235
+ const span = coarse.resolution * coarse.tileWidth;
236
+ const [cx, cy] = [(l0 + l1 + 1) / 2, (r0 + r1 + 1) / 2];
237
+ if (Number.isFinite(cx + cy))
238
+ lonLat = g.crs.inverse([coarse.origin[0] + cx * span, coarse.origin[1] - cy * span]);
239
+ }
240
+ // CRS units per pixel of a 256 px tile at zoom 0 there
241
+ const [mx, my] = [mercatorX(lonLat[0] ?? 0), mercatorY(lonLat[1] ?? 0)];
242
+ const d = 1e-7;
243
+ const p = g.crs.forward([longitude(mx), latitude(my)]);
244
+ const q = g.crs.forward([longitude(mx + d), latitude(my)]);
245
+ const zero = Math.hypot((q[0] ?? 0) - (p[0] ?? 0), (q[1] ?? 0) - (p[1] ?? 0)) / (d * 256);
246
+ if (!(zero > 0))
247
+ return { minZoom: 0, maxZoom: 19 };
248
+ return {
249
+ minZoom: Math.max(0, Math.floor(Math.log2(zero / coarse.resolution)) - 2),
250
+ maxZoom: Math.max(0, Math.round(Math.log2(zero / fine.resolution))),
251
+ };
252
+ }
253
+ /**
254
+ * A raster loader drawing Web Mercator tiles of `size` pixels from a source of URL template `url` in tile grid `grid`:
255
+ * planned here, drawn in a worker of the map through `remote` when it can, else in the page
256
+ */
257
+ export function gridLoader(url, grid, size, remote) {
258
+ let local;
259
+ return async (z, x, y, signal) => {
260
+ const job = planTile(grid, url, z, x, y, size);
261
+ if (!job)
262
+ return null;
263
+ const drawn = remote?.(job, [z, x, y], signal);
264
+ if (drawn)
265
+ return drawn;
266
+ local ??= resampler().draw;
267
+ return local(job, signal);
268
+ };
269
+ }
270
+ //# sourceMappingURL=grid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grid.js","sourceRoot":"","sources":["../src/grid.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Rasters in another tile grid, the planning half: a WMTS-like tile matrix set in any CRS (Lambert-93, UTM, longitudes\n * and latitudes…), or a WMS asked for a box in that CRS, reprojected into the Web Mercator tiles the engine draws. For\n * each Mercator tile the page projects a mesh of 17 × 17 points of the tile into the source CRS (the only projection\n * work: 289 points a tile, whatever its size), picks the source level of the same pixel size, and lists the source\n * images the tile spans; the drawing (`resample.ts`) is done by a worker of the map, or in the page without workers.\n */\nimport { type Crs, type CrsLike, getCrs } from './crs.ts';\nimport { latitude, longitude, mercatorX, mercatorY } from './geo.ts';\nimport { type Job, type Placed, resampler } from './resample.ts';\n\n/** One level of a tile grid, as a `TileMatrix` of WMTS */\nexport interface TileMatrix {\n /** What replaces {z} in the URL (the `TILEMATRIX` of a WMTS; default the index of the matrix in the grid) */\n id?: string | number;\n /** Size of a pixel, CRS units (WMTS: its `ScaleDenominator` × 0.00028 m, in CRS units) */\n resolution: number;\n /** Top-left corner of the tile (0, 0), CRS units (x east, y north) */\n origin: [x: number, y: number];\n /** Size of a tile, pixels (default 256) */\n tileWidth?: number;\n tileHeight?: number;\n /** Tiles across and down (default unbounded) */\n matrixWidth?: number;\n matrixHeight?: number;\n /** The tiles the source has (a WMTS's `TileMatrixLimits`), inclusive: none is asked for outside */\n limits?: [minCol: number, minRow: number, maxCol: number, maxRow: number];\n}\n\n/**\n * A raster's tile grid in a CRS of its own, reprojected into Web Mercator by the map: `matrices` for tiles ({z}, {x},\n * {y} in the URL: matrix, column, row, rows from the north), none for a WMS whose URL has `{bbox}` (the box of each\n * Mercator tile in that CRS: minimum x, minimum y, maximum x, maximum y, asked for at the tile's size)\n */\nexport interface TileGrid {\n /** `'EPSG:2154'`, another built-in or registered name, or an object with `forward` and `inverse` (proj4's) */\n crs: CrsLike;\n /** The levels of the grid, in any order */\n matrices?: TileMatrix[];\n /** Longitudes and latitudes the source covers (west, south, east, north): nothing is asked for outside */\n bounds?: [west: number, south: number, east: number, north: number];\n /** Identifier of the tile matrix set (a WMTS's `TILEMATRIXSET`), for the helpers that write the URL */\n name?: string;\n}\n\n/** Cells of the mesh along each side of a tile */\nconst N = 16;\n/** Source levels finer at most than the pixel size across, where the grid stretches one axis (towards the poles in\n * longitudes and latitudes) */\nconst MAX_BOOST = 3;\n/** Pixels of a mosaic at most: coarser levels beyond, nothing if even the coarsest is larger */\nconst MAX_MOSAIC = 2048 * 2048;\n\ninterface Matrix extends Required<Omit<TileMatrix, 'limits' | 'id'>> {\n id: string | number;\n limits: [number, number, number, number] | undefined;\n}\n\ninterface Resolved {\n crs: Crs;\n /** Coarsest first */\n matrices: Matrix[];\n bounds: [number, number, number, number] | undefined;\n /** The bounds in the CRS: minimum x, minimum y, maximum x, maximum y */\n extent: [number, number, number, number] | undefined;\n}\n\n/** A box of the CRS around points of it (x, y, x, y…), NaN ignored; undefined without any */\nfunction box(points: ArrayLike<number>): [number, number, number, number] | undefined {\n let [x0, y0, x1, y1] = [Infinity, Infinity, -Infinity, -Infinity];\n for (let k = 0; k + 1 < points.length; k += 2) {\n const [x, y] = [points[k] as number, points[k + 1] as number];\n if (!Number.isFinite(x) || !Number.isFinite(y)) continue;\n x0 = Math.min(x0, x);\n y0 = Math.min(y0, y);\n x1 = Math.max(x1, x);\n y1 = Math.max(y1, y);\n }\n return x0 <= x1 ? [x0, y0, x1, y1] : undefined;\n}\n\n/** A tile grid ready to plan tiles: its CRS found, its matrices completed, its bounds projected */\nexport function resolveGrid(grid: TileGrid): Resolved {\n const crs = getCrs(grid.crs);\n const matrices = (grid.matrices ?? [])\n .map(\n (m, i): Matrix => ({\n id: m.id ?? i,\n resolution: m.resolution,\n origin: m.origin,\n tileWidth: m.tileWidth ?? 256,\n tileHeight: m.tileHeight ?? 256,\n matrixWidth: m.matrixWidth ?? Infinity,\n matrixHeight: m.matrixHeight ?? Infinity,\n limits: m.limits,\n }),\n )\n .sort((a, b) => b.resolution - a.resolution);\n let extent: Resolved['extent'];\n if (grid.bounds) {\n // Its outline and inside, projected: the box of the CRS around them, a little larger (curved edges)\n const [w, s, e, n] = grid.bounds;\n const points: number[] = [];\n for (let i = 0; i <= 8; i += 1) {\n for (let j = 0; j <= 8; j += 1) points.push(...crs.forward([w + ((e - w) * i) / 8, s + ((n - s) * j) / 8]));\n }\n const b = box(points);\n if (b) {\n const margin = 0.01 * Math.max(b[2] - b[0], b[3] - b[1]);\n extent = [b[0] - margin, b[1] - margin, b[2] + margin, b[3] + margin];\n }\n }\n return { crs, matrices, bounds: grid.bounds, extent };\n}\n\n/** The longitudes and latitudes of tiles in longitudes and latitudes, two 256 px tiles side by side at level 0, rows\n * from the north (NASA's Trek, WorldCRS84Quad), levels `minLevel` to `maxLevel` ({z} is the level) */\nexport function equirectangularGrid(minLevel: number, maxLevel: number): TileGrid {\n const matrices: TileMatrix[] = [];\n for (let level = minLevel; level <= maxLevel; level += 1) {\n const n = 2 ** level;\n matrices.push({ id: level, resolution: 180 / 256 / n, origin: [-180, 90], matrixWidth: 2 * n, matrixHeight: n });\n }\n return { crs: 'EPSG:4326', matrices };\n}\n\n/** A URL of the source: {z}, {x}, {y}, {bbox}, {width} and {height} replaced */\nfunction sourceUrl(template: string, z: string | number, x: number, y: number, bbox: number[], w: number, h: number) {\n return template\n .replaceAll('{z}', String(z))\n .replaceAll('{x}', String(x))\n .replaceAll('{y}', String(y))\n .replaceAll('{bbox}', bbox.join(','))\n .replaceAll('{width}', String(w))\n .replaceAll('{height}', String(h));\n}\n\n/** CRS units per pixel along the mesh's x and y around its middle (NaN where the CRS has nothing there) */\nfunction pixelSize(points: Float64Array, size: number): [number, number] {\n const c = N / 2;\n const at = (i: number, j: number) => 2 * (j * (N + 1) + i);\n const d = (p: number, q: number) =>\n Math.hypot((points[q] as number) - (points[p] as number), (points[q + 1] as number) - (points[p + 1] as number));\n const step = (2 * size) / N;\n return [d(at(c - 1, c), at(c + 1, c)) / step, d(at(c, c - 1), at(c, c + 1)) / step];\n}\n\n/**\n * The box (CRS) of the points a tile samples: the centers of its edge pixels, interpolated in the mesh as `resample`\n * does, and the inner points of the mesh (should the projection bend); within `clip`. Undefined if none is\n */\nfunction sampled(points: Float64Array, size: number, clip: number[]): [number, number, number, number] | undefined {\n const at = (i: number, j: number, k: number) => points[2 * (j * (N + 1) + i) + k] as number;\n const centers: number[] = [];\n for (let j = 1; j < N; j += 1) for (let i = 1; i < N; i += 1) centers.push(at(i, j, 0), at(i, j, 1));\n const cell = size / N;\n const add = (px: number, py: number) => {\n const [fx, fy] = [px / cell, py / cell];\n const [i, j] = [Math.min(N - 1, Math.floor(fx)), Math.min(N - 1, Math.floor(fy))];\n const [tx, ty] = [fx - i, fy - j];\n for (const k of [0, 1]) {\n const top = at(i, j, k) + (at(i + 1, j, k) - at(i, j, k)) * tx;\n const bottom = at(i, j + 1, k) + (at(i + 1, j + 1, k) - at(i, j + 1, k)) * tx;\n centers.push(top + (bottom - top) * ty);\n }\n };\n for (let p = 0.5; p < size; p += 1) {\n add(p, 0.5);\n add(p, size - 0.5);\n add(0.5, p);\n add(size - 0.5, p);\n }\n const b = box(centers);\n if (!b) return undefined;\n const out: [number, number, number, number] = [\n Math.max(b[0], clip[0] as number),\n Math.max(b[1], clip[1] as number),\n Math.min(b[2], clip[2] as number),\n Math.min(b[3], clip[3] as number),\n ];\n return out[0] <= out[2] && out[1] <= out[3] ? out : undefined;\n}\n\n/**\n * The plan of Mercator tile `z`/`x`/`y` (`size` pixels a side) from a source of URL template `url` in grid `g`; null\n * where the source has nothing\n */\nexport function planTile(g: Resolved, url: string, z: number, x: number, y: number, size: number): Job | null {\n const tiles = 2 ** z;\n if (g.bounds) {\n const [w, s, e, n] = g.bounds;\n if (longitude((x + 1) / tiles) <= w || longitude(x / tiles) >= e) return null;\n if (latitude(y / tiles) <= s || latitude((y + 1) / tiles) >= n) return null;\n }\n // The mesh in the source CRS\n const points = new Float64Array(2 * (N + 1) ** 2);\n for (let j = 0; j <= N; j += 1) {\n const lat = latitude((y + j / N) / tiles);\n for (let i = 0; i <= N; i += 1) {\n const [px = Number.NaN, py = Number.NaN] = g.crs.forward([longitude((x + i / N) / tiles), lat]);\n points[2 * (j * (N + 1) + i)] = px;\n points[2 * (j * (N + 1) + i) + 1] = py;\n }\n }\n let b = box(points);\n if (!b) return null;\n if (g.extent) {\n const e = g.extent;\n b = [Math.max(b[0], e[0]), Math.max(b[1], e[1]), Math.min(b[2], e[2]), Math.min(b[3], e[3])];\n if (b[0] >= b[2] || b[1] >= b[3]) return null;\n }\n const mesh = new Float32Array(points.length);\n if (g.matrices.length === 0) {\n // One image of the tile's box, a pixel larger on each side\n const [sx, sy] = pixelSize(points, size);\n const m = Number.isFinite(sx + sy) ? Math.max(sx, sy) : 0;\n const [x0, y0, x1, y1] = [b[0] - m, b[1] - m, b[2] + m, b[3] + m];\n for (let k = 0; k < points.length; k += 2) {\n mesh[k] = (((points[k] as number) - x0) / (x1 - x0)) * size;\n mesh[k + 1] = ((y1 - (points[k + 1] as number)) / (y1 - y0)) * size;\n }\n const source = { url: sourceUrl(url, z, x, y, [x0, y0, x1, y1], size, size), x: 0, y: 0, w: size, h: size };\n return { size, width: size, height: size, sources: [source], n: N, mesh };\n }\n // The level of the same pixel size, along the axis the grid stretches least (up to MAX_BOOST levels finer)\n const [sx, sy] = pixelSize(points, size);\n const across = Math.max(sx, sy);\n const target = Number.isFinite(across) ? Math.max(Math.min(sx, sy), across / 2 ** MAX_BOOST) : (b[2] - b[0]) / size;\n // Where the pixels of the tile are sampled: the centers of its edge pixels and the mesh, within the source's extent\n const centers = sampled(points, size, b);\n if (!centers) return null;\n let best = 0;\n g.matrices.forEach((m, i) => {\n const r = g.matrices[best]?.resolution ?? m.resolution;\n if (Math.abs(Math.log2(m.resolution / target)) < Math.abs(Math.log2(r / target))) best = i;\n });\n for (let level = best; level >= 0; level -= 1) {\n const m = g.matrices[level] as Matrix;\n const [ox, oy] = m.origin;\n const [tw, th, res] = [m.tileWidth, m.tileHeight, m.resolution];\n const [l0, r0, l1, r1] = m.limits ?? [0, 0, Infinity, Infinity];\n // The tiles of the source pixels sampled (those of a weight over a thousandth: a tile edge on a source tile edge\n // does not fetch the next source tile for nothing)\n const c0 = Math.max(0, l0, Math.floor(((centers[0] - ox) / res - 0.5 + 1e-3) / tw));\n const c1 = Math.min(m.matrixWidth - 1, l1, Math.floor(((centers[2] - ox) / res + 0.5 - 1e-3) / tw));\n const t0 = Math.max(0, r0, Math.floor(((oy - centers[3]) / res - 0.5 + 1e-3) / th));\n const t1 = Math.min(m.matrixHeight - 1, r1, Math.floor(((oy - centers[1]) / res + 0.5 - 1e-3) / th));\n if (c0 > c1 || t0 > t1) return null;\n const [width, height] = [(c1 - c0 + 1) * tw, (t1 - t0 + 1) * th];\n if (width * height > MAX_MOSAIC) continue;\n const sources: Placed[] = [];\n for (let row = t0; row <= t1; row += 1) {\n for (let col = c0; col <= c1; col += 1) {\n const bbox = [ox + col * tw * res, oy - (row + 1) * th * res, ox + (col + 1) * tw * res, oy - row * th * res];\n const placed = { x: (col - c0) * tw, y: (row - t0) * th, w: tw, h: th };\n sources.push({ url: sourceUrl(url, m.id, col, row, bbox, tw, th), ...placed });\n }\n }\n for (let k = 0; k < points.length; k += 2) {\n mesh[k] = ((points[k] as number) - ox) / res - c0 * tw;\n mesh[k + 1] = (oy - (points[k + 1] as number)) / res - t0 * th;\n }\n return { size, width, height, sources, n: N, mesh };\n }\n return null;\n}\n\n/**\n * The map zooms a grid's matrices span (the pixel size of the finest and of the coarsest, two levels coarser, where\n * the tiles still fit a mosaic), measured at the middle of its bounds, or of its coarsest matrix\n */\nexport function gridZooms(g: Resolved): { minZoom: number; maxZoom: number } {\n const coarse = g.matrices[0];\n const fine = g.matrices.at(-1);\n if (!coarse || !fine) return { minZoom: 0, maxZoom: 19 };\n let lonLat: readonly number[] = [0, 0];\n if (g.bounds) lonLat = [(g.bounds[0] + g.bounds[2]) / 2, (g.bounds[1] + g.bounds[3]) / 2];\n else {\n const [l0, r0, l1, r1] = coarse.limits ?? [0, 0, coarse.matrixWidth - 1, coarse.matrixHeight - 1];\n const span = coarse.resolution * coarse.tileWidth;\n const [cx, cy] = [(l0 + l1 + 1) / 2, (r0 + r1 + 1) / 2];\n if (Number.isFinite(cx + cy)) lonLat = g.crs.inverse([coarse.origin[0] + cx * span, coarse.origin[1] - cy * span]);\n }\n // CRS units per pixel of a 256 px tile at zoom 0 there\n const [mx, my] = [mercatorX(lonLat[0] ?? 0), mercatorY(lonLat[1] ?? 0)];\n const d = 1e-7;\n const p = g.crs.forward([longitude(mx), latitude(my)]);\n const q = g.crs.forward([longitude(mx + d), latitude(my)]);\n const zero = Math.hypot((q[0] ?? 0) - (p[0] ?? 0), (q[1] ?? 0) - (p[1] ?? 0)) / (d * 256);\n if (!(zero > 0)) return { minZoom: 0, maxZoom: 19 };\n return {\n minZoom: Math.max(0, Math.floor(Math.log2(zero / coarse.resolution)) - 2),\n maxZoom: Math.max(0, Math.round(Math.log2(zero / fine.resolution))),\n };\n}\n\n/** Draws a Mercator tile `z`/`x`/`y`: its image, null where the source has nothing; rejects on errors */\ntype Draw = (z: number, x: number, y: number, signal: AbortSignal) => Promise<ImageBitmap | null>;\n\n/** A planned tile drawn in a worker; undefined when the map has no workers (drawn in the page) */\nexport type RemoteReprojection = (\n job: Job,\n tile: [z: number, x: number, y: number],\n signal: AbortSignal,\n) => Promise<ImageBitmap | null> | undefined;\n\n/**\n * A raster loader drawing Web Mercator tiles of `size` pixels from a source of URL template `url` in tile grid `grid`:\n * planned here, drawn in a worker of the map through `remote` when it can, else in the page\n */\nexport function gridLoader(url: string, grid: Resolved, size: number, remote?: RemoteReprojection): Draw {\n let local: ReturnType<typeof resampler>['draw'] | undefined;\n return async (z, x, y, signal) => {\n const job = planTile(grid, url, z, x, y, size);\n if (!job) return null;\n const drawn = remote?.(job, [z, x, y], signal);\n if (drawn) return drawn;\n local ??= resampler().draw;\n return local(job, signal);\n };\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -13,6 +13,7 @@
13
13
  */
14
14
  export { OPENFREEMAP_ATTRIBUTION, TERRAIN_TILES_ATTRIBUTION } from './basemaps.ts';
15
15
  export { AttributionControl, type AttributionOptions, type Control, type ControlPosition, DEFAULT_ATTRIBUTION, NavigationControl, type NavigationOptions, } from './controls.ts';
16
+ export { type Crs, type CrsLike, getCrs, lambertConformalConic, registerCrs, reproject, transverseMercator, } from './crs.ts';
16
17
  export type { DecoderUrls } from './decoders.ts';
17
18
  export type { ExtrusionOptions, ExtrusionStyle, PolygonArrays, TileKey } from './extrusions.ts';
18
19
  export { ExtrusionLayer } from './extrusions.ts';
@@ -21,14 +22,19 @@ export { CircleLayer, FeatureLayer, FillLayer, interpolate, LineLayer, parseColo
21
22
  export { geoplateformeWfs, geoplateformeWms, geoplateformeWmts, IGN_ATTRIBUTION } from './geoplateforme.ts';
22
23
  export type { TextPart } from './glyphs.ts';
23
24
  export { DEFAULT_FONT, GLYPHS_URL } from './glyphs.ts';
25
+ export { parseGpx } from './gpx.ts';
26
+ export type { TileGrid, TileMatrix } from './grid.ts';
27
+ export { parseKml } from './kml.ts';
24
28
  export type { GroundOptions, GroundTexture } from './layers.ts';
25
29
  export { GroundLayer, Layer, NetworkLayer, RasterLayer, Tiles3dLayer } from './layers.ts';
26
30
  export { GeoMap } from './map.ts';
27
31
  export { type Anchor, Marker, type MarkerEvent, type MarkerEvents, type MarkerOptions, Popup, type PopupEvents, type PopupOptions, } from './overlay.ts';
28
32
  export type { SymbolOptions, SymbolStyle } from './symbols.ts';
29
33
  export { SymbolLayer } from './symbols.ts';
30
- export type { AnimationOptions, AtmosphereOptions, Basemap, BasemapName, BodyOptions, CelestialBody, FeatureHit, FlyToOptions, GeoMapOptions, LegacyBasemap, LoadingMode, LonLat, MapEvents, MapHoverFeatureEvent, MapPointerEvent, NetworkOptions, NetworkStyle, Point, Projection, RasterGrid, RasterOptions, TerrainEncoding, TerrainModel, TerrainOptions, Tiles3dOptions, Tiles3dStyle, } from './types.ts';
34
+ export { parseTopoJson, type TopoGeometry, type Topology } from './topojson.ts';
35
+ export type { AnimationOptions, AtmosphereOptions, Basemap, BasemapName, BodyOptions, CelestialBody, FeatureHit, FlyToOptions, GeoMapOptions, LegacyBasemap, LoadingMode, LonLat, MapEvents, MapHoverFeatureEvent, MapPointerEvent, NetworkOptions, NetworkStyle, Point, Projection, RasterGrid, RasterOptions, RasterStyle, TerrainEncoding, TerrainModel, TerrainOptions, Tiles3dOptions, Tiles3dStyle, } from './types.ts';
31
36
  export type { Json, LabelCandidate, RasterSource, Style, StyleLayer } from './vectorstyle.ts';
32
37
  export type { VectorTilesOptions } from './vectortiles.ts';
33
38
  export { OPENFREEMAP_STYLES, PLAN_STYLES, VectorTiles } from './vectortiles.ts';
34
39
  export type { Camera, NetworkStats, PickHit, PickResult, RasterLayerStats, Tiles3dStats } from './wasm/isard.js';
40
+ export { parseWmtsGrid, wmtsGrid } from './wmts.ts';
package/dist/index.js CHANGED
@@ -13,13 +13,18 @@
13
13
  */
14
14
  export { OPENFREEMAP_ATTRIBUTION, TERRAIN_TILES_ATTRIBUTION } from "./basemaps.js";
15
15
  export { AttributionControl, DEFAULT_ATTRIBUTION, NavigationControl, } from "./controls.js";
16
+ export { getCrs, lambertConformalConic, registerCrs, reproject, transverseMercator, } from "./crs.js";
16
17
  export { ExtrusionLayer } from "./extrusions.js";
17
18
  export { CircleLayer, FeatureLayer, FillLayer, interpolate, LineLayer, parseColor } from "./features.js";
18
19
  export { geoplateformeWfs, geoplateformeWms, geoplateformeWmts, IGN_ATTRIBUTION } from "./geoplateforme.js";
19
20
  export { DEFAULT_FONT, GLYPHS_URL } from "./glyphs.js";
21
+ export { parseGpx } from "./gpx.js";
22
+ export { parseKml } from "./kml.js";
20
23
  export { GroundLayer, Layer, NetworkLayer, RasterLayer, Tiles3dLayer } from "./layers.js";
21
24
  export { GeoMap } from "./map.js";
22
25
  export { Marker, Popup, } from "./overlay.js";
23
26
  export { SymbolLayer } from "./symbols.js";
27
+ export { parseTopoJson } from "./topojson.js";
24
28
  export { OPENFREEMAP_STYLES, PLAN_STYLES, VectorTiles } from "./vectortiles.js";
29
+ export { parseWmtsGrid, wmtsGrid } from "./wmts.js";
25
30
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AACnF,OAAO,EACL,kBAAkB,EAIlB,mBAAmB,EACnB,iBAAiB,GAElB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAqBjD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACzG,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE5G,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEvD,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC1F,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAEL,MAAM,EAIN,KAAK,GAGN,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AA+B3C,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC","sourcesContent":["/**\n * isard: a WebGL2 map engine for large, interactive data layers, labels and 3D Tiles.\n *\n * ```ts\n * import { GeoMap } from 'isard';\n * const map = await GeoMap.create(container, { center: [2.4246, 48.8457], zoom: 13 });\n * const network = map.addNetwork({ nodes, edges, max: 1800, contour: 300 });\n * map.on('hover', ({ lonLat }) => lonLat && network.setValues(travelTimes(lonLat)));\n * map.addTiles3d({ url: 'https://…/tileset.json' });\n * map.addControl(new NavigationControl());\n * new Marker().setLonLat([2.4246, 48.8457]).setPopup(new Popup({ offset: [0, -34] }).setText('Here')).addTo(map);\n * ```\n */\nexport { OPENFREEMAP_ATTRIBUTION, TERRAIN_TILES_ATTRIBUTION } from './basemaps.ts';\nexport {\n AttributionControl,\n type AttributionOptions,\n type Control,\n type ControlPosition,\n DEFAULT_ATTRIBUTION,\n NavigationControl,\n type NavigationOptions,\n} from './controls.ts';\nexport type { DecoderUrls } from './decoders.ts';\nexport type { ExtrusionOptions, ExtrusionStyle, PolygonArrays, TileKey } from './extrusions.ts';\nexport { ExtrusionLayer } from './extrusions.ts';\nexport type {\n CircleOptions,\n CircleStyle,\n Feature,\n FeatureCollection,\n FeatureData,\n FeatureLayerStyle,\n FillOptions,\n FillStyle,\n Geometry,\n LineOptions,\n LineStyle,\n Placement,\n Position,\n Properties,\n Ramp,\n Size,\n Stops,\n Styled,\n} from './features.ts';\nexport { CircleLayer, FeatureLayer, FillLayer, interpolate, LineLayer, parseColor } from './features.ts';\nexport { geoplateformeWfs, geoplateformeWms, geoplateformeWmts, IGN_ATTRIBUTION } from './geoplateforme.ts';\nexport type { TextPart } from './glyphs.ts';\nexport { DEFAULT_FONT, GLYPHS_URL } from './glyphs.ts';\nexport type { GroundOptions, GroundTexture } from './layers.ts';\nexport { GroundLayer, Layer, NetworkLayer, RasterLayer, Tiles3dLayer } from './layers.ts';\nexport { GeoMap } from './map.ts';\nexport {\n type Anchor,\n Marker,\n type MarkerEvent,\n type MarkerEvents,\n type MarkerOptions,\n Popup,\n type PopupEvents,\n type PopupOptions,\n} from './overlay.ts';\nexport type { SymbolOptions, SymbolStyle } from './symbols.ts';\nexport { SymbolLayer } from './symbols.ts';\nexport type {\n AnimationOptions,\n AtmosphereOptions,\n Basemap,\n BasemapName,\n BodyOptions,\n CelestialBody,\n FeatureHit,\n FlyToOptions,\n GeoMapOptions,\n LegacyBasemap,\n LoadingMode,\n LonLat,\n MapEvents,\n MapHoverFeatureEvent,\n MapPointerEvent,\n NetworkOptions,\n NetworkStyle,\n Point,\n Projection,\n RasterGrid,\n RasterOptions,\n TerrainEncoding,\n TerrainModel,\n TerrainOptions,\n Tiles3dOptions,\n Tiles3dStyle,\n} from './types.ts';\nexport type { Json, LabelCandidate, RasterSource, Style, StyleLayer } from './vectorstyle.ts';\nexport type { VectorTilesOptions } from './vectortiles.ts';\nexport { OPENFREEMAP_STYLES, PLAN_STYLES, VectorTiles } from './vectortiles.ts';\nexport type { Camera, NetworkStats, PickHit, PickResult, RasterLayerStats, Tiles3dStats } from './wasm/isard.js';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AACnF,OAAO,EACL,kBAAkB,EAIlB,mBAAmB,EACnB,iBAAiB,GAElB,MAAM,eAAe,CAAC;AACvB,OAAO,EAGL,MAAM,EACN,qBAAqB,EACrB,WAAW,EACX,SAAS,EACT,kBAAkB,GACnB,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAqBjD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACzG,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE5G,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC1F,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAEL,MAAM,EAIN,KAAK,GAGN,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAoC,MAAM,eAAe,CAAC;AAgChF,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEhF,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC","sourcesContent":["/**\n * isard: a WebGL2 map engine for large, interactive data layers, labels and 3D Tiles.\n *\n * ```ts\n * import { GeoMap } from 'isard';\n * const map = await GeoMap.create(container, { center: [2.4246, 48.8457], zoom: 13 });\n * const network = map.addNetwork({ nodes, edges, max: 1800, contour: 300 });\n * map.on('hover', ({ lonLat }) => lonLat && network.setValues(travelTimes(lonLat)));\n * map.addTiles3d({ url: 'https://…/tileset.json' });\n * map.addControl(new NavigationControl());\n * new Marker().setLonLat([2.4246, 48.8457]).setPopup(new Popup({ offset: [0, -34] }).setText('Here')).addTo(map);\n * ```\n */\nexport { OPENFREEMAP_ATTRIBUTION, TERRAIN_TILES_ATTRIBUTION } from './basemaps.ts';\nexport {\n AttributionControl,\n type AttributionOptions,\n type Control,\n type ControlPosition,\n DEFAULT_ATTRIBUTION,\n NavigationControl,\n type NavigationOptions,\n} from './controls.ts';\nexport {\n type Crs,\n type CrsLike,\n getCrs,\n lambertConformalConic,\n registerCrs,\n reproject,\n transverseMercator,\n} from './crs.ts';\nexport type { DecoderUrls } from './decoders.ts';\nexport type { ExtrusionOptions, ExtrusionStyle, PolygonArrays, TileKey } from './extrusions.ts';\nexport { ExtrusionLayer } from './extrusions.ts';\nexport type {\n CircleOptions,\n CircleStyle,\n Feature,\n FeatureCollection,\n FeatureData,\n FeatureLayerStyle,\n FillOptions,\n FillStyle,\n Geometry,\n LineOptions,\n LineStyle,\n Placement,\n Position,\n Properties,\n Ramp,\n Size,\n Stops,\n Styled,\n} from './features.ts';\nexport { CircleLayer, FeatureLayer, FillLayer, interpolate, LineLayer, parseColor } from './features.ts';\nexport { geoplateformeWfs, geoplateformeWms, geoplateformeWmts, IGN_ATTRIBUTION } from './geoplateforme.ts';\nexport type { TextPart } from './glyphs.ts';\nexport { DEFAULT_FONT, GLYPHS_URL } from './glyphs.ts';\nexport { parseGpx } from './gpx.ts';\nexport type { TileGrid, TileMatrix } from './grid.ts';\nexport { parseKml } from './kml.ts';\nexport type { GroundOptions, GroundTexture } from './layers.ts';\nexport { GroundLayer, Layer, NetworkLayer, RasterLayer, Tiles3dLayer } from './layers.ts';\nexport { GeoMap } from './map.ts';\nexport {\n type Anchor,\n Marker,\n type MarkerEvent,\n type MarkerEvents,\n type MarkerOptions,\n Popup,\n type PopupEvents,\n type PopupOptions,\n} from './overlay.ts';\nexport type { SymbolOptions, SymbolStyle } from './symbols.ts';\nexport { SymbolLayer } from './symbols.ts';\nexport { parseTopoJson, type TopoGeometry, type Topology } from './topojson.ts';\nexport type {\n AnimationOptions,\n AtmosphereOptions,\n Basemap,\n BasemapName,\n BodyOptions,\n CelestialBody,\n FeatureHit,\n FlyToOptions,\n GeoMapOptions,\n LegacyBasemap,\n LoadingMode,\n LonLat,\n MapEvents,\n MapHoverFeatureEvent,\n MapPointerEvent,\n NetworkOptions,\n NetworkStyle,\n Point,\n Projection,\n RasterGrid,\n RasterOptions,\n RasterStyle,\n TerrainEncoding,\n TerrainModel,\n TerrainOptions,\n Tiles3dOptions,\n Tiles3dStyle,\n} from './types.ts';\nexport type { Json, LabelCandidate, RasterSource, Style, StyleLayer } from './vectorstyle.ts';\nexport type { VectorTilesOptions } from './vectortiles.ts';\nexport { OPENFREEMAP_STYLES, PLAN_STYLES, VectorTiles } from './vectortiles.ts';\nexport type { Camera, NetworkStats, PickHit, PickResult, RasterLayerStats, Tiles3dStats } from './wasm/isard.js';\nexport { parseWmtsGrid, wmtsGrid } from './wmts.ts';\n"]}
@@ -1,7 +1,3 @@
1
- /**
2
- * Mouse, touch and keyboard controls. Every gesture only updates the camera and asks for a frame: the engine draws at most
3
- * once per display refresh, whatever the event rate of the device.
4
- */
5
1
  import type { GeoMap } from './map.ts';
6
2
  import type { Point } from './types.ts';
7
3
  import type { Camera } from './wasm/isard.js';
@@ -31,6 +27,9 @@ export declare class Interaction {
31
27
  /** Recent pan moves, for the release speed: [time, dx, dy] */
32
28
  private trail;
33
29
  private moved;
30
+ /** The canvas's place on the page, read once: reading it on every pointer move would force a layout each time.
31
+ * Read again after a resize, a scroll, and when a pointer comes in or goes down */
32
+ private rect;
34
33
  constructor(map: GeoMap, options?: {
35
34
  keyboard?: boolean;
36
35
  });
@@ -1,3 +1,8 @@
1
+ /**
2
+ * Mouse, touch and keyboard controls. Every gesture only updates the camera and asks for a frame: the engine draws at most
3
+ * once per display refresh, whatever the event rate of the device.
4
+ */
5
+ import { latitude, mercatorX, mercatorY } from "./geo.js";
1
6
  /** Zoom levels per wheel pixel (a mouse notch is about 100 px: 1/3 of a level) */
2
7
  const WHEEL_RATE = 1 / 300;
3
8
  /** Share of the remaining wheel zoom applied per frame (smooth, about 150 ms to settle) */
@@ -58,11 +63,10 @@ export function keyCamera(action, camera) {
58
63
  const dx = (sx * Math.cos(b) - sy * Math.sin(b)) / world;
59
64
  const dy = (sx * Math.sin(b) + sy * Math.cos(b)) / world;
60
65
  const [lon, lat] = camera.center;
61
- const phi = (Math.max(-85.0511, Math.min(85.0511, lat)) * Math.PI) / 180;
62
- const x = (lon + 180) / 360 + dx;
63
- const y = Math.max(0, Math.min(1, (1 - Math.log(Math.tan(phi) + 1 / Math.cos(phi)) / Math.PI) / 2 + dy));
66
+ const x = mercatorX(lon) + dx;
67
+ const y = Math.max(0, Math.min(1, mercatorY(lat) + dy));
64
68
  const wrapped = ((((x * 360) % 360) + 360) % 360) - 180;
65
- return { center: [wrapped, (Math.atan(Math.sinh(Math.PI * (1 - 2 * y))) * 180) / Math.PI] };
69
+ return { center: [wrapped, latitude(y)] };
66
70
  }
67
71
  /** An element that takes the keys typed in it */
68
72
  function editable(target) {
@@ -78,6 +82,9 @@ export class Interaction {
78
82
  /** Recent pan moves, for the release speed: [time, dx, dy] */
79
83
  trail = [];
80
84
  moved = false;
85
+ /** The canvas's place on the page, read once: reading it on every pointer move would force a layout each time.
86
+ * Read again after a resize, a scroll, and when a pointer comes in or goes down */
87
+ rect;
81
88
  constructor(map, options = {}) {
82
89
  this.map = map;
83
90
  const canvas = map.canvas;
@@ -85,7 +92,20 @@ export class Interaction {
85
92
  canvas.addEventListener(type, handler, options);
86
93
  this.cleanup.push(() => canvas.removeEventListener(type, handler));
87
94
  };
88
- listen('pointerdown', (e) => this.down(e));
95
+ const moved = () => {
96
+ this.rect = undefined;
97
+ };
98
+ listen('pointerenter', moved);
99
+ // Scrolls of the page or of any element holding the map
100
+ if (typeof addEventListener === 'function') {
101
+ addEventListener('scroll', moved, { capture: true, passive: true });
102
+ this.cleanup.push(() => removeEventListener('scroll', moved, { capture: true }));
103
+ }
104
+ this.cleanup.push(map.on('resize', moved));
105
+ listen('pointerdown', (e) => {
106
+ this.rect = undefined;
107
+ this.down(e);
108
+ });
89
109
  listen('pointermove', (e) => this.move(e));
90
110
  listen('pointerup', (e) => this.up(e));
91
111
  listen('pointercancel', (e) => this.up(e));
@@ -118,8 +138,8 @@ export class Interaction {
118
138
  return this.pointers.size > 0;
119
139
  }
120
140
  local(e) {
121
- const r = this.map.canvas.getBoundingClientRect();
122
- return [e.clientX - r.left, e.clientY - r.top];
141
+ this.rect ??= this.map.canvas.getBoundingClientRect();
142
+ return [e.clientX - this.rect.left, e.clientY - this.rect.top];
123
143
  }
124
144
  down(e) {
125
145
  this.map.canvas.setPointerCapture(e.pointerId);