isard 1.2.0 → 1.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/CHANGELOG.md +124 -0
- package/README.md +46 -39
- package/dist/basemap/basemaps.js +1 -0
- package/dist/basemap/basemaps.js.map +1 -1
- package/dist/basemap/pmtileslayer.d.ts +33 -0
- package/dist/basemap/pmtileslayer.js +97 -0
- package/dist/basemap/pmtileslayer.js.map +1 -0
- package/dist/basemap/trees.d.ts +26 -0
- package/dist/basemap/trees.js +141 -0
- package/dist/basemap/trees.js.map +1 -0
- package/dist/basemap/vectorstyle.d.ts +10 -0
- package/dist/basemap/vectorstyle.js +35 -0
- package/dist/basemap/vectorstyle.js.map +1 -1
- package/dist/basemap/vectortiles.d.ts +93 -44
- package/dist/basemap/vectortiles.js +511 -303
- package/dist/basemap/vectortiles.js.map +1 -1
- package/dist/basemap/workerpool.d.ts +17 -0
- package/dist/basemap/workerpool.js +203 -0
- package/dist/basemap/workerpool.js.map +1 -0
- package/dist/basemap.worker.js +2 -2
- package/dist/basemap.worker.js.map +18 -8
- package/dist/bind/layers.js +10 -0
- package/dist/bind/layers.js.map +1 -1
- package/dist/decoder.worker.js +4 -4
- package/dist/decoder.worker.js.map +3 -3
- package/dist/engine-loader.d.ts +8 -1
- package/dist/engine-loader.js +20 -1
- package/dist/engine-loader.js.map +1 -1
- package/dist/geoplateforme.d.ts +16 -0
- package/dist/geoplateforme.js +23 -0
- package/dist/geoplateforme.js.map +1 -1
- package/dist/grid-module.d.ts +44 -0
- package/dist/grid-module.js +63 -0
- package/dist/grid-module.js.map +1 -0
- package/dist/grids.d.ts +51 -0
- package/dist/grids.js +88 -0
- package/dist/grids.js.map +1 -0
- package/dist/index.d.ts +14 -4
- package/dist/index.js +11 -2
- package/dist/index.js.map +1 -1
- package/dist/isard_bg.wasm +0 -0
- package/dist/isard_core_bg.wasm +0 -0
- package/dist/isard_grid_bg.wasm +0 -0
- package/dist/isard_tess_bg.wasm +0 -0
- package/dist/layers/flow.d.ts +111 -0
- package/dist/layers/flow.js +222 -0
- package/dist/layers/flow.js.map +1 -0
- package/dist/layers/layers.js +9 -0
- package/dist/layers/layers.js.map +1 -1
- package/dist/layers/symbols.d.ts +2 -0
- package/dist/layers/symbols.js +2 -1
- package/dist/layers/symbols.js.map +1 -1
- package/dist/layers/vectors.d.ts +60 -0
- package/dist/layers/vectors.js +130 -0
- package/dist/layers/vectors.js.map +1 -0
- package/dist/map/frame-loop.d.ts +3 -0
- package/dist/map/frame-loop.js +6 -0
- package/dist/map/frame-loop.js.map +1 -1
- package/dist/map/layer-spec.d.ts +4 -1
- package/dist/map/layer-spec.js +2 -0
- package/dist/map/layer-spec.js.map +1 -1
- package/dist/map/raster-source.js +1 -1
- package/dist/map/raster-source.js.map +1 -1
- package/dist/map/workers.d.ts +5 -1
- package/dist/map/workers.js +36 -1
- package/dist/map/workers.js.map +1 -1
- package/dist/map.d.ts +35 -6
- package/dist/map.js +83 -11
- package/dist/map.js.map +1 -1
- package/dist/react/IsardMap.js +1 -0
- package/dist/react/IsardMap.js.map +1 -1
- package/dist/react/Layer.d.ts +2 -0
- package/dist/react/Layer.js.map +1 -1
- package/dist/react/Swipe.d.ts +11 -4
- package/dist/react/Swipe.js +26 -15
- package/dist/react/Swipe.js.map +1 -1
- package/dist/react/VectorGeometry.d.ts +35 -0
- package/dist/react/VectorGeometry.js +82 -0
- package/dist/react/VectorGeometry.js.map +1 -0
- package/dist/react/context.d.ts +2 -1
- package/dist/react/context.js.map +1 -1
- package/dist/react/index.d.ts +2 -1
- package/dist/react/index.js +2 -1
- package/dist/react/index.js.map +1 -1
- package/dist/types.d.ts +30 -3
- package/dist/types.js.map +1 -1
- package/dist/ui/minimap.d.ts +25 -0
- package/dist/ui/minimap.js +90 -0
- package/dist/ui/minimap.js.map +1 -0
- package/dist/ui/scale.d.ts +19 -0
- package/dist/ui/scale.js +44 -0
- package/dist/ui/scale.js.map +1 -0
- package/dist/ui/search.d.ts +25 -0
- package/dist/ui/search.js +119 -0
- package/dist/ui/search.js.map +1 -0
- package/dist/ui/style.js +17 -0
- package/dist/ui/style.js.map +1 -1
- package/dist/util/sun.d.ts +11 -0
- package/dist/util/sun.js +26 -0
- package/dist/util/sun.js.map +1 -0
- package/dist/wasm/isard.d.ts +124 -7
- package/dist/wasm/isard.js +319 -8
- package/dist/wasm/isard_core.d.ts +124 -7
- package/dist/wasm/isard_core.js +319 -8
- package/dist/wasm/isard_grid.d.ts +101 -0
- package/dist/wasm/isard_grid.js +375 -0
- package/dist/wasm/isard_tess.d.ts +109 -0
- package/dist/wasm/isard_tess.js +398 -0
- package/dist/workers/basemap/geometry.d.ts +72 -0
- package/dist/workers/basemap/labels.d.ts +8 -0
- package/dist/workers/basemap/raster.d.ts +10 -0
- package/dist/workers/basemap/street.d.ts +19 -0
- package/dist/workers/basemap/tiles.d.ts +65 -0
- package/dist/workers/basemap/trees.d.ts +19 -0
- package/dist/workers/basemap.worker.d.ts +147 -22
- package/dist/workers/basemap.worker.js +93 -553
- package/dist/workers/basemap.worker.js.map +1 -1
- package/package.json +6 -4
- package/vite.js +11 -2
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The fills and lines of a MapLibre style drawn as geometry, tile by tile (`VectorTiles.vectors`), instead of into the
|
|
3
|
+
* images of a raster layer: sharp at any zoom and pitch, on the relief, picked by feature, restyled without cutting the
|
|
4
|
+
* tiles again. The workers cut each vector tile into polygons and lines and style its features; the engine draws the
|
|
5
|
+
* style's layers in their order, each over its zoom range.
|
|
6
|
+
*/
|
|
7
|
+
import { FLOATS, stops } from "./features.js";
|
|
8
|
+
import { Layer } from "./layers.js";
|
|
9
|
+
export class VectorLayer extends Layer {
|
|
10
|
+
tiles = new Map();
|
|
11
|
+
sublayers = [];
|
|
12
|
+
nextKey = 0;
|
|
13
|
+
/** The whole layer shown (`setVisible`), over each style layer's visibility */
|
|
14
|
+
shown = true;
|
|
15
|
+
/** @internal Resolved once the style is loaded and its layers drawn known (set by its `VectorTiles`) */
|
|
16
|
+
styled = Promise.resolve();
|
|
17
|
+
/** @internal Changes a property of a style layer drawn (set by its `VectorTiles`) */
|
|
18
|
+
restyle;
|
|
19
|
+
/** @internal Asks the workers for the tiles in view again (set by its `VectorTiles`): an engine made anew has none */
|
|
20
|
+
recut;
|
|
21
|
+
/** @internal */
|
|
22
|
+
constructor(map) {
|
|
23
|
+
super(map);
|
|
24
|
+
}
|
|
25
|
+
/** Resolves once the style is loaded, its layers drawn known (`layers`), and the map has drawn the layer; rejected
|
|
26
|
+
* if the style fails */
|
|
27
|
+
get ready() {
|
|
28
|
+
return this.styled.then(() => super.ready);
|
|
29
|
+
}
|
|
30
|
+
/** The style layers drawn, in order */
|
|
31
|
+
get layers() {
|
|
32
|
+
return this.sublayers;
|
|
33
|
+
}
|
|
34
|
+
/** Keys of the tiles held (`z/x/y`) */
|
|
35
|
+
get tileKeys() {
|
|
36
|
+
return [...this.tiles.keys()];
|
|
37
|
+
}
|
|
38
|
+
/** @internal Sets the style layers drawn, in order (the tiles' sublayers) */
|
|
39
|
+
setSublayers(sublayers) {
|
|
40
|
+
this.sublayers = sublayers;
|
|
41
|
+
this.sendSublayers(this.map.engine, this.id);
|
|
42
|
+
this.map.requestRender();
|
|
43
|
+
}
|
|
44
|
+
/** @internal Adds or replaces a tile, cut by the workers (and made ready for the GPU there, with its mesh) */
|
|
45
|
+
setTile(tile, vectors) {
|
|
46
|
+
const key = this.tiles.get(tile)?.key ?? this.nextKey++;
|
|
47
|
+
const { properties, sublayer } = vectors;
|
|
48
|
+
this.tiles.set(tile, { key, vectors: { properties, sublayer } });
|
|
49
|
+
this.sendTile(this.map.engine, this.id, key, vectors);
|
|
50
|
+
this.map.requestRender();
|
|
51
|
+
}
|
|
52
|
+
/** @internal New styles of a tile's features, as the workers evaluated them (the same features) */
|
|
53
|
+
setTileStyles(tile, styles) {
|
|
54
|
+
const t = this.tiles.get(tile);
|
|
55
|
+
if (!t || styles.length !== t.vectors.properties.length * FLOATS)
|
|
56
|
+
return;
|
|
57
|
+
this.map.engine.setFeatureStyle(this.id, styles, t.key);
|
|
58
|
+
this.map.requestRender();
|
|
59
|
+
}
|
|
60
|
+
/** @internal */
|
|
61
|
+
removeTile(tile) {
|
|
62
|
+
const t = this.tiles.get(tile);
|
|
63
|
+
if (!t)
|
|
64
|
+
return;
|
|
65
|
+
this.tiles.delete(tile);
|
|
66
|
+
this.map.engine.removeVectorTile(this.id, t.key);
|
|
67
|
+
this.map.requestRender();
|
|
68
|
+
}
|
|
69
|
+
/** The feature of a picked index (no geometry: the tiles hold it cut), its properties and style layer. Tiles are
|
|
70
|
+
* numbered one after the other, in the order they were first added */
|
|
71
|
+
featureAt(index) {
|
|
72
|
+
const tiles = [...this.tiles.values()].sort((a, b) => a.key - b.key);
|
|
73
|
+
// The tile holding the index, and the index among its features (one pass, the features of the tiles before
|
|
74
|
+
// taken off)
|
|
75
|
+
const { tile, rest } = tiles.reduce((found, t) => {
|
|
76
|
+
if (found.tile)
|
|
77
|
+
return found;
|
|
78
|
+
const count = t.vectors.properties.length;
|
|
79
|
+
return found.rest < count ? { tile: t, rest: found.rest } : { rest: found.rest - count };
|
|
80
|
+
}, { rest: index });
|
|
81
|
+
if (!tile)
|
|
82
|
+
return undefined;
|
|
83
|
+
const properties = tile.vectors.properties[rest];
|
|
84
|
+
const sublayer = this.sublayers[tile.vectors.sublayer[rest] ?? -1];
|
|
85
|
+
if (properties === undefined || !sublayer)
|
|
86
|
+
return undefined;
|
|
87
|
+
return { type: 'Feature', properties, geometry: null, layer: sublayer.id, sourceLayer: sublayer.sourceLayer };
|
|
88
|
+
}
|
|
89
|
+
/** Changes a paint property of a style layer drawn, as MapLibre's `setPaintProperty`: the tiles are restyled, not cut
|
|
90
|
+
* again */
|
|
91
|
+
setPaintProperty(layer, name, value) {
|
|
92
|
+
this.restyle?.(layer, 'paint', name, value);
|
|
93
|
+
}
|
|
94
|
+
/** Changes a layout property of a style layer drawn (`visibility`: shown or hidden at once), as MapLibre's
|
|
95
|
+
* `setLayoutProperty` */
|
|
96
|
+
setLayoutProperty(layer, name, value) {
|
|
97
|
+
this.restyle?.(layer, 'layout', name, value);
|
|
98
|
+
}
|
|
99
|
+
setVisible(visible) {
|
|
100
|
+
this.shown = visible;
|
|
101
|
+
this.sendSublayers(this.map.engine, this.id);
|
|
102
|
+
this.map.requestRender();
|
|
103
|
+
}
|
|
104
|
+
sendSublayers(engine, id) {
|
|
105
|
+
const s = this.sublayers;
|
|
106
|
+
engine.setVectorSublayers(id, Uint8Array.from(s, (l) => ({ fill: 0, line: 1, extrusion: 2 })[l.kind]), Float64Array.from(s.flatMap((l) => [l.minZoom, l.maxZoom])), Uint8Array.from(s, (l) => (l.visible && this.shown ? 1 : 0)), Float32Array.from(s.flatMap((l) => l.dash)), Float32Array.from(s.flatMap((l) => stops(l.opacity))), Uint8Array.from(s, (l) => ({ butt: 0, round: 1, square: 2 })[l.cap]), Uint8Array.from(s, (l) => (l.lit ? 1 : 0)));
|
|
107
|
+
}
|
|
108
|
+
/** A tile to the engine: its mesh uploaded as it is, or without one its geometry, which the engine makes ready */
|
|
109
|
+
sendTile(engine, id, key, vectors) {
|
|
110
|
+
const { fills, lines, styles, properties, mesh } = vectors;
|
|
111
|
+
if (mesh) {
|
|
112
|
+
engine.setVectorTileMesh(id, key, fills.points, fills.ringStart, fills.polygonStart, fills.feature, fills.fillStart, mesh.vertices, mesh.indices, mesh.fillRanges, mesh.prism, mesh.pieces, mesh.lineTable, mesh.lineRanges, mesh.blocks, mesh.blockIndices, mesh.blockRanges, mesh.bounds, properties.length);
|
|
113
|
+
engine.setFeatureStyle(id, styles, key);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
engine.setVectorTile(id, key, fills.points, fills.ringStart, fills.polygonStart, fills.feature, fills.fillStart, lines.points, lines.start, lines.feature, lines.lineStart, properties.length, vectors.tile ?? new Float64Array());
|
|
117
|
+
engine.setFeatureStyle(id, styles, key);
|
|
118
|
+
}
|
|
119
|
+
/** @internal */
|
|
120
|
+
create(engine) {
|
|
121
|
+
const id = engine.addVectorTiles();
|
|
122
|
+
this.sendSublayers(engine, id);
|
|
123
|
+
// An engine made anew (after a context loss, or the one with 3D Tiles): its tiles cut again by the workers, once
|
|
124
|
+
// the layer has its id there. Keeping their geometry here would double the memory they take
|
|
125
|
+
this.tiles.clear();
|
|
126
|
+
queueMicrotask(() => this.recut?.());
|
|
127
|
+
return id;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=vectors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vectors.js","sourceRoot":"","sources":["../../src/layers/vectors.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The fills and lines of a MapLibre style drawn as geometry, tile by tile (`VectorTiles.vectors`), instead of into the\n * images of a raster layer: sharp at any zoom and pitch, on the relief, picked by feature, restyled without cutting the\n * tiles again. The workers cut each vector tile into polygons and lines and style its features; the engine draws the\n * style's layers in their order, each over its zoom range.\n */\n\nimport type { LayerHost } from '../types.ts';\nimport type { Engine } from '../wasm/isard.js';\nimport type { TileVectors } from '../workers/basemap.worker.ts';\nimport { type Feature, FLOATS, type Size, stops } from './features.ts';\nimport { Layer } from './layers.ts';\n\n/** A style layer as the engine draws it: its kind, zoom range, visibility and dashes (dash, gap, dash, gap, in line\n * widths; zeros: solid) */\nexport interface VectorSublayer {\n /** The style layer's id */\n id: string;\n /** Its source layer, if any (not for a background) */\n sourceLayer: string | undefined;\n kind: 'fill' | 'line' | 'extrusion';\n minZoom: number;\n maxZoom: number;\n visible: boolean;\n /** Its opacity when it depends on the zoom only, evaluated at the camera's zoom (else 1: the features' colors hold\n * it) */\n opacity: Size;\n dash: [number, number, number, number];\n /** The caps of its lines' ends (`line-cap`; the joins between their pieces are round) */\n cap: 'butt' | 'round' | 'square';\n /** Its lines glow at night (the streets: its id names a road, not its casing; `setSun`) */\n lit: boolean;\n}\n\n/** The properties of a picked feature, with the style layer that drew it */\nexport type VectorFeature = Feature<Record<string, unknown>> & { layer: string; sourceLayer: string | undefined };\n\ninterface Tile {\n /** Its number in the engine: tiles are numbered for picking in this order */\n key: number;\n /** What picking needs (its geometry and styles are the engine's only: an engine made anew asks the tiles again) */\n vectors: Pick<TileVectors, 'properties' | 'sublayer'>;\n}\n\nexport class VectorLayer extends Layer {\n private readonly tiles = new Map<string, Tile>();\n private sublayers: VectorSublayer[] = [];\n private nextKey = 0;\n /** The whole layer shown (`setVisible`), over each style layer's visibility */\n private shown = true;\n /** @internal Resolved once the style is loaded and its layers drawn known (set by its `VectorTiles`) */\n styled: Promise<void> = Promise.resolve();\n /** @internal Changes a property of a style layer drawn (set by its `VectorTiles`) */\n restyle: ((layer: string, group: 'paint' | 'layout', name: string, value: unknown) => void) | undefined;\n /** @internal Asks the workers for the tiles in view again (set by its `VectorTiles`): an engine made anew has none */\n recut: (() => void) | undefined;\n\n /** @internal */\n constructor(map: LayerHost) {\n super(map);\n }\n\n /** Resolves once the style is loaded, its layers drawn known (`layers`), and the map has drawn the layer; rejected\n * if the style fails */\n override get ready(): Promise<void> {\n return this.styled.then(() => super.ready);\n }\n\n /** The style layers drawn, in order */\n get layers(): readonly VectorSublayer[] {\n return this.sublayers;\n }\n\n /** Keys of the tiles held (`z/x/y`) */\n get tileKeys(): string[] {\n return [...this.tiles.keys()];\n }\n\n /** @internal Sets the style layers drawn, in order (the tiles' sublayers) */\n setSublayers(sublayers: VectorSublayer[]): void {\n this.sublayers = sublayers;\n this.sendSublayers(this.map.engine, this.id);\n this.map.requestRender();\n }\n\n /** @internal Adds or replaces a tile, cut by the workers (and made ready for the GPU there, with its mesh) */\n setTile(tile: string, vectors: TileVectors): void {\n const key = this.tiles.get(tile)?.key ?? this.nextKey++;\n const { properties, sublayer } = vectors;\n\n this.tiles.set(tile, { key, vectors: { properties, sublayer } });\n this.sendTile(this.map.engine, this.id, key, vectors);\n this.map.requestRender();\n }\n\n /** @internal New styles of a tile's features, as the workers evaluated them (the same features) */\n setTileStyles(tile: string, styles: Float32Array): void {\n const t = this.tiles.get(tile);\n\n if (!t || styles.length !== t.vectors.properties.length * FLOATS) return;\n this.map.engine.setFeatureStyle(this.id, styles, t.key);\n this.map.requestRender();\n }\n\n /** @internal */\n removeTile(tile: string): void {\n const t = this.tiles.get(tile);\n\n if (!t) return;\n this.tiles.delete(tile);\n this.map.engine.removeVectorTile(this.id, t.key);\n this.map.requestRender();\n }\n\n /** The feature of a picked index (no geometry: the tiles hold it cut), its properties and style layer. Tiles are\n * numbered one after the other, in the order they were first added */\n featureAt(index: number): VectorFeature | undefined {\n const tiles = [...this.tiles.values()].sort((a, b) => a.key - b.key);\n // The tile holding the index, and the index among its features (one pass, the features of the tiles before\n // taken off)\n const { tile, rest } = tiles.reduce<{ tile?: Tile; rest: number }>(\n (found, t) => {\n if (found.tile) return found;\n\n const count = t.vectors.properties.length;\n\n return found.rest < count ? { tile: t, rest: found.rest } : { rest: found.rest - count };\n },\n { rest: index },\n );\n\n if (!tile) return undefined;\n\n const properties = tile.vectors.properties[rest];\n const sublayer = this.sublayers[tile.vectors.sublayer[rest] ?? -1];\n\n if (properties === undefined || !sublayer) return undefined;\n\n return { type: 'Feature', properties, geometry: null, layer: sublayer.id, sourceLayer: sublayer.sourceLayer };\n }\n\n /** Changes a paint property of a style layer drawn, as MapLibre's `setPaintProperty`: the tiles are restyled, not cut\n * again */\n setPaintProperty(layer: string, name: string, value: unknown): void {\n this.restyle?.(layer, 'paint', name, value);\n }\n\n /** Changes a layout property of a style layer drawn (`visibility`: shown or hidden at once), as MapLibre's\n * `setLayoutProperty` */\n setLayoutProperty(layer: string, name: string, value: unknown): void {\n this.restyle?.(layer, 'layout', name, value);\n }\n\n setVisible(visible: boolean): void {\n this.shown = visible;\n this.sendSublayers(this.map.engine, this.id);\n this.map.requestRender();\n }\n\n private sendSublayers(engine: Engine, id: number): void {\n const s = this.sublayers;\n\n engine.setVectorSublayers(\n id,\n Uint8Array.from(s, (l) => ({ fill: 0, line: 1, extrusion: 2 })[l.kind]),\n Float64Array.from(s.flatMap((l) => [l.minZoom, l.maxZoom])),\n Uint8Array.from(s, (l) => (l.visible && this.shown ? 1 : 0)),\n Float32Array.from(s.flatMap((l) => l.dash)),\n Float32Array.from(s.flatMap((l) => stops(l.opacity))),\n Uint8Array.from(s, (l) => ({ butt: 0, round: 1, square: 2 })[l.cap]),\n Uint8Array.from(s, (l) => (l.lit ? 1 : 0)),\n );\n }\n\n /** A tile to the engine: its mesh uploaded as it is, or without one its geometry, which the engine makes ready */\n private sendTile(engine: Engine, id: number, key: number, vectors: TileVectors): void {\n const { fills, lines, styles, properties, mesh } = vectors;\n\n if (mesh) {\n engine.setVectorTileMesh(\n id,\n key,\n fills.points,\n fills.ringStart,\n fills.polygonStart,\n fills.feature,\n fills.fillStart,\n mesh.vertices,\n mesh.indices,\n mesh.fillRanges,\n mesh.prism,\n mesh.pieces,\n mesh.lineTable,\n mesh.lineRanges,\n mesh.blocks,\n mesh.blockIndices,\n mesh.blockRanges,\n mesh.bounds,\n properties.length,\n );\n engine.setFeatureStyle(id, styles, key);\n\n return;\n }\n engine.setVectorTile(\n id,\n key,\n fills.points,\n fills.ringStart,\n fills.polygonStart,\n fills.feature,\n fills.fillStart,\n lines.points,\n lines.start,\n lines.feature,\n lines.lineStart,\n properties.length,\n vectors.tile ?? new Float64Array(),\n );\n engine.setFeatureStyle(id, styles, key);\n }\n\n /** @internal */\n protected create(engine: Engine): number {\n const id = engine.addVectorTiles();\n\n this.sendSublayers(engine, id);\n // An engine made anew (after a context loss, or the one with 3D Tiles): its tiles cut again by the workers, once\n // the layer has its id there. Keeping their geometry here would double the memory they take\n this.tiles.clear();\n queueMicrotask(() => this.recut?.());\n\n return id;\n }\n}\n"]}
|
package/dist/map/frame-loop.d.ts
CHANGED
|
@@ -46,6 +46,9 @@ export declare class FrameLoop {
|
|
|
46
46
|
get camera(): Camera | undefined;
|
|
47
47
|
/** Asks for a frame; several calls before the next frame draw it once */
|
|
48
48
|
request(): void;
|
|
49
|
+
/** Asks for a frame that sends 'idle' once everything is loaded, even if the last one already did: the waiters of
|
|
50
|
+
* `whenIdle` on a map already idle (else no frame would change from loading to loaded, and none would send it) */
|
|
51
|
+
requestIdle(): void;
|
|
49
52
|
/** Runs `step` every frame until it returns false; replaces the running animation */
|
|
50
53
|
animate(step: Step | undefined): void;
|
|
51
54
|
/** The pointer's position for the next frame (undefined: none) */
|
package/dist/map/frame-loop.js
CHANGED
|
@@ -38,6 +38,12 @@ export class FrameLoop {
|
|
|
38
38
|
return;
|
|
39
39
|
this.requested ||= requestAnimationFrame((now) => this.frame(now));
|
|
40
40
|
}
|
|
41
|
+
/** Asks for a frame that sends 'idle' once everything is loaded, even if the last one already did: the waiters of
|
|
42
|
+
* `whenIdle` on a map already idle (else no frame would change from loading to loaded, and none would send it) */
|
|
43
|
+
requestIdle() {
|
|
44
|
+
this.#settled = false;
|
|
45
|
+
this.request();
|
|
46
|
+
}
|
|
41
47
|
/** Runs `step` every frame until it returns false; replaces the running animation */
|
|
42
48
|
animate(step) {
|
|
43
49
|
// A flight cut short no longer needs its destination
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frame-loop.js","sourceRoot":"","sources":["../../src/map/frame-loop.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The frame loop of a map: frames drawn on demand only (an idle map costs nothing), the running animation stepped in\n * each, and the events of a frame sent with it: the camera's moves, the pointer's position (coalesced to one per\n * frame, so the values computed for it are drawn in the same frame), 'render', and 'idle' once everything is loaded.\n */\n\nimport type { Point } from '../types.ts';\nimport type { Step } from '../util/animation.ts';\nimport type { Camera, Engine } from '../wasm/isard.js';\nimport type { MapListeners } from './events.ts';\n\n/** What the frame loop needs of its map */\nexport interface FrameHost {\n /** The map's engine of the moment */\n engine(): Engine;\n /** The map's camera */\n camera(): Camera;\n /** The WebGL context is lost: nothing is drawn */\n lost(): boolean;\n /** The pointer or the keys are moving the camera: no 'moveend' yet */\n interacting(): boolean;\n /** Custom layers are drawn: they read the camera of the frame */\n customLayers(): boolean;\n /** The engine with 3D Tiles is loading: not idle */\n upgrading(): boolean;\n /** The frame is drawn: what follows it (the overlays placed, the hover picking asked for at `hovered`) */\n drawn(hovered: Point | undefined): void;\n}\n\n/** The frames of a map, asked for and drawn */\nexport class FrameLoop {\n private readonly host: FrameHost;\n private readonly listeners: MapListeners;\n /** Frame asked for, 0 if none */\n private requested = 0;\n private inFrame = false;\n private animation: Step | undefined;\n /** The pointer's position for the next frame */\n private hoverPoint: Point | undefined;\n private lastCamera = '';\n /** The camera moved since the last 'moveend' */\n private moving = false;\n #settled = false;\n #camera: Camera | undefined;\n\n /** `listeners`: the map's, told of the frame's events */\n constructor(host: FrameHost, listeners: MapListeners) {\n this.host = host;\n this.listeners = listeners;\n }\n\n /** The last frame found everything loaded ('idle' sent) */\n get settled(): boolean {\n return this.#settled;\n }\n\n /** The camera of the frame being drawn: what `getCamera` gives the custom layers while the engine is busy */\n get camera(): Camera | undefined {\n return this.#camera;\n }\n\n /** Asks for a frame; several calls before the next frame draw it once */\n request(): void {\n // Changes made by listeners during a frame are drawn by that frame; nothing is drawn without a context\n if (this.inFrame || this.host.lost()) return;\n this.requested ||= requestAnimationFrame((now) => this.frame(now));\n }\n\n /** Runs `step` every frame until it returns false; replaces the running animation */\n animate(step: Step | undefined): void {\n // A flight cut short no longer needs its destination\n if (this.animation) this.host.engine().clearPreload();\n this.animation = step;\n this.request();\n }\n\n /** The pointer's position for the next frame (undefined: none) */\n hover(point: Point | undefined): void {\n this.hoverPoint = point;\n }\n\n /** Draws a frame now, in place of the one asked for (a resized canvas is cleared: waiting one frame would flash) */\n drawNow(): void {\n cancelAnimationFrame(this.requested);\n this.frame(performance.now());\n }\n\n /** Cancels the frame asked for (the context is lost); a new one can be asked for */\n cancel(): void {\n cancelAnimationFrame(this.requested);\n this.requested = 0;\n }\n\n /** Cancels the frame asked for, for good (the map is destroyed): it stays marked as asked for */\n stop(): void {\n cancelAnimationFrame(this.requested);\n }\n\n private frame(now: number): void {\n this.requested = 0;\n try {\n this.inFrame = true;\n this.draw(now);\n } finally {\n // Whatever throws in a frame, the next ones are still drawn\n this.inFrame = false;\n }\n }\n\n private draw(now: number): void {\n if (this.animation && !this.animation(now)) this.animation = undefined;\n\n const { host, listeners } = this;\n const camera = host.camera();\n const key = `${camera.center}|${camera.zoom}|${camera.pitch}|${camera.bearing}`;\n const moved = key !== this.lastCamera;\n\n if (moved) {\n // The first frame is no move\n if (!this.moving && this.lastCamera !== '') {\n this.moving = true;\n listeners.emit('movestart', camera);\n }\n this.lastCamera = key;\n listeners.emit('move', camera);\n } else if (this.moving && !this.animation && !host.interacting()) {\n this.moving = false;\n listeners.emit('moveend', camera);\n }\n\n // Values for the pointer position are computed before drawing, in the same frame\n const hovered = this.hoverPoint;\n\n if (hovered) {\n this.hoverPoint = undefined;\n // The position under the pointer for its listeners only (a 'hoverfeature' alone does not need it)\n if (listeners.has('hover')) {\n listeners.emit('hover', { point: hovered, lonLat: host.engine().ground(hovered[0], hovered[1]) });\n }\n }\n\n const t0 = performance.now();\n\n // The engine asks for the next frame while it draws (uploads past the frame budget, fades): not ignored\n this.inFrame = false;\n // As the engine has it now (a listener may have moved it), for the custom layers drawn in the frame\n this.#camera = host.customLayers() ? host.engine().camera() : undefined;\n\n const render = (): boolean => {\n try {\n return host.engine().render();\n } finally {\n this.#camera = undefined;\n }\n };\n const loading = render();\n\n this.inFrame = true;\n host.drawn(hovered);\n listeners.emit('render', { ms: performance.now() - t0 });\n this.inFrame = false;\n // A move goes on until a frame finds the camera still: that frame sends 'moveend'\n if (this.animation || (moved && this.moving)) this.request();\n // Idle: nothing loading (the engine with 3D Tiles neither), no animation, no frame asked for (uploads waiting,\n // fades, listeners)\n if (loading || host.upgrading() || this.animation || this.requested !== 0) {\n this.#settled = false;\n } else if (!this.#settled) {\n this.#settled = true;\n listeners.emit('idle', {});\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"frame-loop.js","sourceRoot":"","sources":["../../src/map/frame-loop.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAyBH,+CAA+C;AAC/C,MAAM,OAAO,SAAS;IACH,IAAI,CAAY;IAChB,SAAS,CAAe;IACzC,iCAAiC;IACzB,SAAS,GAAG,CAAC,CAAC;IACd,OAAO,GAAG,KAAK,CAAC;IAChB,SAAS,CAAmB;IACpC,gDAAgD;IACxC,UAAU,CAAoB;IAC9B,UAAU,GAAG,EAAE,CAAC;IACxB,gDAAgD;IACxC,MAAM,GAAG,KAAK,CAAC;IACvB,QAAQ,GAAG,KAAK,CAAC;IACjB,OAAO,CAAqB;IAE5B,yDAAyD;IACzD,YAAY,IAAe,EAAE,SAAuB;QAClD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IAED,2DAA2D;IAC3D,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,6GAA6G;IAC7G,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,yEAAyE;IACzE,OAAO;QACL,uGAAuG;QACvG,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;YAAE,OAAO;QAC7C,IAAI,CAAC,SAAS,KAAK,qBAAqB,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IACrE,CAAC;IAED;sHACkH;IAClH,WAAW;QACT,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACtB,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,qFAAqF;IACrF,OAAO,CAAC,IAAsB;QAC5B,qDAAqD;QACrD,IAAI,IAAI,CAAC,SAAS;YAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,YAAY,EAAE,CAAC;QACtD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,kEAAkE;IAClE,KAAK,CAAC,KAAwB;QAC5B,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;IAC1B,CAAC;IAED,oHAAoH;IACpH,OAAO;QACL,oBAAoB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACrC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC;IAChC,CAAC;IAED,oFAAoF;IACpF,MAAM;QACJ,oBAAoB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACrC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;IACrB,CAAC;IAED,iGAAiG;IACjG,IAAI;QACF,oBAAoB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACvC,CAAC;IAEO,KAAK,CAAC,GAAW;QACvB,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;QACnB,IAAI,CAAC;YACH,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACpB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjB,CAAC;gBAAS,CAAC;YACT,4DAA4D;YAC5D,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACvB,CAAC;IACH,CAAC;IAEO,IAAI,CAAC,GAAW;QACtB,IAAI,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC;YAAE,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAEvE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;QACjC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QAChF,MAAM,KAAK,GAAG,GAAG,KAAK,IAAI,CAAC,UAAU,CAAC;QAEtC,IAAI,KAAK,EAAE,CAAC;YACV,6BAA6B;YAC7B,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,UAAU,KAAK,EAAE,EAAE,CAAC;gBAC3C,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;gBACnB,SAAS,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;YACtC,CAAC;YACD,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC;YACtB,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACjC,CAAC;aAAM,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACjE,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;YACpB,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QACpC,CAAC;QAED,iFAAiF;QACjF,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC;QAEhC,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;YAC5B,kGAAkG;YAClG,IAAI,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC3B,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACpG,CAAC;QACH,CAAC;QAED,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAE7B,wGAAwG;QACxG,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,oGAAoG;QACpG,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QAExE,MAAM,MAAM,GAAG,GAAY,EAAE;YAC3B,IAAI,CAAC;gBACH,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC;YAChC,CAAC;oBAAS,CAAC;gBACT,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;YAC3B,CAAC;QACH,CAAC,CAAC;QACF,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC;QAEzB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACpB,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QACzD,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,kFAAkF;QAClF,IAAI,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC;YAAE,IAAI,CAAC,OAAO,EAAE,CAAC;QAC7D,+GAA+G;QAC/G,oBAAoB;QACpB,IAAI,OAAO,IAAI,IAAI,CAAC,SAAS,EAAE,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS,KAAK,CAAC,EAAE,CAAC;YAC1E,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACxB,CAAC;aAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC1B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;YACrB,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;CACF","sourcesContent":["/**\n * The frame loop of a map: frames drawn on demand only (an idle map costs nothing), the running animation stepped in\n * each, and the events of a frame sent with it: the camera's moves, the pointer's position (coalesced to one per\n * frame, so the values computed for it are drawn in the same frame), 'render', and 'idle' once everything is loaded.\n */\n\nimport type { Point } from '../types.ts';\nimport type { Step } from '../util/animation.ts';\nimport type { Camera, Engine } from '../wasm/isard.js';\nimport type { MapListeners } from './events.ts';\n\n/** What the frame loop needs of its map */\nexport interface FrameHost {\n /** The map's engine of the moment */\n engine(): Engine;\n /** The map's camera */\n camera(): Camera;\n /** The WebGL context is lost: nothing is drawn */\n lost(): boolean;\n /** The pointer or the keys are moving the camera: no 'moveend' yet */\n interacting(): boolean;\n /** Custom layers are drawn: they read the camera of the frame */\n customLayers(): boolean;\n /** The engine with 3D Tiles is loading: not idle */\n upgrading(): boolean;\n /** The frame is drawn: what follows it (the overlays placed, the hover picking asked for at `hovered`) */\n drawn(hovered: Point | undefined): void;\n}\n\n/** The frames of a map, asked for and drawn */\nexport class FrameLoop {\n private readonly host: FrameHost;\n private readonly listeners: MapListeners;\n /** Frame asked for, 0 if none */\n private requested = 0;\n private inFrame = false;\n private animation: Step | undefined;\n /** The pointer's position for the next frame */\n private hoverPoint: Point | undefined;\n private lastCamera = '';\n /** The camera moved since the last 'moveend' */\n private moving = false;\n #settled = false;\n #camera: Camera | undefined;\n\n /** `listeners`: the map's, told of the frame's events */\n constructor(host: FrameHost, listeners: MapListeners) {\n this.host = host;\n this.listeners = listeners;\n }\n\n /** The last frame found everything loaded ('idle' sent) */\n get settled(): boolean {\n return this.#settled;\n }\n\n /** The camera of the frame being drawn: what `getCamera` gives the custom layers while the engine is busy */\n get camera(): Camera | undefined {\n return this.#camera;\n }\n\n /** Asks for a frame; several calls before the next frame draw it once */\n request(): void {\n // Changes made by listeners during a frame are drawn by that frame; nothing is drawn without a context\n if (this.inFrame || this.host.lost()) return;\n this.requested ||= requestAnimationFrame((now) => this.frame(now));\n }\n\n /** Asks for a frame that sends 'idle' once everything is loaded, even if the last one already did: the waiters of\n * `whenIdle` on a map already idle (else no frame would change from loading to loaded, and none would send it) */\n requestIdle(): void {\n this.#settled = false;\n this.request();\n }\n\n /** Runs `step` every frame until it returns false; replaces the running animation */\n animate(step: Step | undefined): void {\n // A flight cut short no longer needs its destination\n if (this.animation) this.host.engine().clearPreload();\n this.animation = step;\n this.request();\n }\n\n /** The pointer's position for the next frame (undefined: none) */\n hover(point: Point | undefined): void {\n this.hoverPoint = point;\n }\n\n /** Draws a frame now, in place of the one asked for (a resized canvas is cleared: waiting one frame would flash) */\n drawNow(): void {\n cancelAnimationFrame(this.requested);\n this.frame(performance.now());\n }\n\n /** Cancels the frame asked for (the context is lost); a new one can be asked for */\n cancel(): void {\n cancelAnimationFrame(this.requested);\n this.requested = 0;\n }\n\n /** Cancels the frame asked for, for good (the map is destroyed): it stays marked as asked for */\n stop(): void {\n cancelAnimationFrame(this.requested);\n }\n\n private frame(now: number): void {\n this.requested = 0;\n try {\n this.inFrame = true;\n this.draw(now);\n } finally {\n // Whatever throws in a frame, the next ones are still drawn\n this.inFrame = false;\n }\n }\n\n private draw(now: number): void {\n if (this.animation && !this.animation(now)) this.animation = undefined;\n\n const { host, listeners } = this;\n const camera = host.camera();\n const key = `${camera.center}|${camera.zoom}|${camera.pitch}|${camera.bearing}`;\n const moved = key !== this.lastCamera;\n\n if (moved) {\n // The first frame is no move\n if (!this.moving && this.lastCamera !== '') {\n this.moving = true;\n listeners.emit('movestart', camera);\n }\n this.lastCamera = key;\n listeners.emit('move', camera);\n } else if (this.moving && !this.animation && !host.interacting()) {\n this.moving = false;\n listeners.emit('moveend', camera);\n }\n\n // Values for the pointer position are computed before drawing, in the same frame\n const hovered = this.hoverPoint;\n\n if (hovered) {\n this.hoverPoint = undefined;\n // The position under the pointer for its listeners only (a 'hoverfeature' alone does not need it)\n if (listeners.has('hover')) {\n listeners.emit('hover', { point: hovered, lonLat: host.engine().ground(hovered[0], hovered[1]) });\n }\n }\n\n const t0 = performance.now();\n\n // The engine asks for the next frame while it draws (uploads past the frame budget, fades): not ignored\n this.inFrame = false;\n // As the engine has it now (a listener may have moved it), for the custom layers drawn in the frame\n this.#camera = host.customLayers() ? host.engine().camera() : undefined;\n\n const render = (): boolean => {\n try {\n return host.engine().render();\n } finally {\n this.#camera = undefined;\n }\n };\n const loading = render();\n\n this.inFrame = true;\n host.drawn(hovered);\n listeners.emit('render', { ms: performance.now() - t0 });\n this.inFrame = false;\n // A move goes on until a frame finds the camera still: that frame sends 'moveend'\n if (this.animation || (moved && this.moving)) this.request();\n // Idle: nothing loading (the engine with 3D Tiles neither), no animation, no frame asked for (uploads waiting,\n // fades, listeners)\n if (loading || host.upgrading() || this.animation || this.requested !== 0) {\n this.#settled = false;\n } else if (!this.#settled) {\n this.#settled = true;\n listeners.emit('idle', {});\n }\n }\n}\n"]}
|
package/dist/map/layer-spec.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** A layer described by its type and options, as an application's configuration gives it, and the map adding it. */
|
|
2
2
|
import type { ExtrusionOptions } from '../layers/extrusions.ts';
|
|
3
3
|
import type { CircleOptions, FillOptions, LineOptions } from '../layers/features.ts';
|
|
4
|
+
import type { FlowOptions } from '../layers/flow.ts';
|
|
4
5
|
import type { GroundOptions, Layer, ModelOptions } from '../layers/layers.ts';
|
|
5
6
|
import type { PointCloudOptions } from '../layers/pointclouds.ts';
|
|
6
7
|
import type { SymbolOptions } from '../layers/symbols.ts';
|
|
@@ -37,6 +38,8 @@ export type LayerSpec<P = Record<string, unknown>> = ({
|
|
|
37
38
|
type: 'models';
|
|
38
39
|
} & ModelOptions & {
|
|
39
40
|
before?: Layer;
|
|
40
|
-
})
|
|
41
|
+
}) | ({
|
|
42
|
+
type: 'flow';
|
|
43
|
+
} & FlowOptions);
|
|
41
44
|
/** Adds the layer a description gives with the `add…` method of its type; an unknown type throws */
|
|
42
45
|
export declare const addSpec: <P = Record<string, unknown>>(map: GeoMap, spec: LayerSpec<P>) => Layer;
|
package/dist/map/layer-spec.js
CHANGED
|
@@ -24,6 +24,8 @@ export const addSpec = (map, spec) => {
|
|
|
24
24
|
return map.addPointCloud(spec);
|
|
25
25
|
case 'models':
|
|
26
26
|
return map.addModels(spec);
|
|
27
|
+
case 'flow':
|
|
28
|
+
return map.addFlow(spec);
|
|
27
29
|
default: {
|
|
28
30
|
// Only from an application's configuration, untyped: the cases above cover every type
|
|
29
31
|
const { type } = spec;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layer-spec.js","sourceRoot":"","sources":["../../src/map/layer-spec.ts"],"names":[],"mappings":"AAAA,oHAAoH;
|
|
1
|
+
{"version":3,"file":"layer-spec.js","sourceRoot":"","sources":["../../src/map/layer-spec.ts"],"names":[],"mappings":"AAAA,oHAAoH;AA0BpH,oGAAoG;AACpG,MAAM,CAAC,MAAM,OAAO,GAAG,CAA8B,GAAW,EAAE,IAAkB,EAAS,EAAE;IAC7F,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,OAAO;YACV,OAAO,GAAG,CAAC,QAAQ,CAAI,IAAI,CAAC,CAAC;QAC/B,KAAK,SAAS;YACZ,OAAO,GAAG,CAAC,UAAU,CAAI,IAAI,CAAC,CAAC;QACjC,KAAK,OAAO;YACV,OAAO,GAAG,CAAC,QAAQ,CAAI,IAAI,CAAC,CAAC;QAC/B,KAAK,SAAS;YACZ,OAAO,GAAG,CAAC,UAAU,CAAI,IAAI,CAAC,CAAC;QACjC,KAAK,YAAY;YACf,OAAO,GAAG,CAAC,aAAa,CAAI,IAAI,CAAC,CAAC;QACpC,KAAK,QAAQ;YACX,OAAO,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC7B,KAAK,QAAQ;YACX,OAAO,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC7B,KAAK,SAAS;YACZ,OAAO,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAC9B,KAAK,SAAS;YACZ,OAAO,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAC9B,KAAK,YAAY;YACf,OAAO,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QACjC,KAAK,QAAQ;YACX,OAAO,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC7B,KAAK,MAAM;YACT,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC3B,OAAO,CAAC,CAAC,CAAC;YACR,sFAAsF;YACtF,MAAM,EAAE,IAAI,EAAE,GAAuB,IAAI,CAAC;YAE1C,MAAM,IAAI,KAAK,CAAC,2BAA2B,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;AACH,CAAC,CAAC","sourcesContent":["/** A layer described by its type and options, as an application's configuration gives it, and the map adding it. */\n\nimport type { ExtrusionOptions } from '../layers/extrusions.ts';\nimport type { CircleOptions, FillOptions, LineOptions } from '../layers/features.ts';\nimport type { FlowOptions } from '../layers/flow.ts';\nimport type { GroundOptions, Layer, ModelOptions } from '../layers/layers.ts';\nimport type { PointCloudOptions } from '../layers/pointclouds.ts';\nimport type { SymbolOptions } from '../layers/symbols.ts';\nimport type { GeoMap } from '../map.ts';\nimport type { NetworkOptions, RasterOptions, Tiles3dOptions } from '../types.ts';\n\n/** A layer by its type and the options of its `add…` method (`GeoMap.add`) */\nexport type LayerSpec<P = Record<string, unknown>> =\n | ({ type: 'lines' } & LineOptions<P>)\n | ({ type: 'circles' } & CircleOptions<P>)\n | ({ type: 'fills' } & FillOptions<P>)\n | ({ type: 'symbols' } & SymbolOptions<P>)\n | ({ type: 'extrusions' } & ExtrusionOptions<P>)\n | ({ type: 'raster' } & RasterOptions & { before?: Layer })\n | ({ type: 'ground' } & GroundOptions & { before?: Layer })\n | ({ type: 'network' } & NetworkOptions)\n | ({ type: 'tiles3d' } & Tiles3dOptions)\n | ({ type: 'pointcloud' } & PointCloudOptions & { before?: Layer })\n | ({ type: 'models' } & ModelOptions & { before?: Layer })\n | ({ type: 'flow' } & FlowOptions);\n\n/** Adds the layer a description gives with the `add…` method of its type; an unknown type throws */\nexport const addSpec = <P = Record<string, unknown>>(map: GeoMap, spec: LayerSpec<P>): Layer => {\n switch (spec.type) {\n case 'lines':\n return map.addLines<P>(spec);\n case 'circles':\n return map.addCircles<P>(spec);\n case 'fills':\n return map.addFills<P>(spec);\n case 'symbols':\n return map.addSymbols<P>(spec);\n case 'extrusions':\n return map.addExtrusions<P>(spec);\n case 'raster':\n return map.addRaster(spec);\n case 'ground':\n return map.addGround(spec);\n case 'network':\n return map.addNetwork(spec);\n case 'tiles3d':\n return map.addTiles3d(spec);\n case 'pointcloud':\n return map.addPointCloud(spec);\n case 'models':\n return map.addModels(spec);\n case 'flow':\n return map.addFlow(spec);\n default: {\n // Only from an application's configuration, untyped: the cases above cover every type\n const { type }: { type?: unknown } = spec;\n\n throw new Error(`isard: no layer of type ${String(type)}`);\n }\n }\n};\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Where a raster layer's tiles come from: a PMTiles archive, Web Mercator tiles, or tiles reprojected from a grid. */
|
|
2
2
|
import { equirectangularGrid, gridLoader, gridZooms, resolveGrid } from "../basemap/grid.js";
|
|
3
|
-
import { pmtilesRasterLoader } from "../basemap/
|
|
3
|
+
import { pmtilesRasterLoader } from "../basemap/pmtileslayer.js";
|
|
4
4
|
/** The loader of a raster layer's tiles and its zooms; `remote` reprojects in the workers */
|
|
5
5
|
export const rasterSource = (options, remote) => {
|
|
6
6
|
const { url, grid = 'mercator', size } = options;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"raster-source.js","sourceRoot":"","sources":["../../src/map/raster-source.ts"],"names":[],"mappings":"AAAA,uHAAuH;AAEvH,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,SAAS,EAA2B,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtH,OAAO,EAAE,mBAAmB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"raster-source.js","sourceRoot":"","sources":["../../src/map/raster-source.ts"],"names":[],"mappings":"AAAA,uHAAuH;AAEvH,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,SAAS,EAA2B,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtH,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAUjE,6FAA6F;AAC7F,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,OAAsB,EAAE,MAA0B,EAAgB,EAAE;IAC/F,MAAM,EAAE,GAAG,EAAE,IAAI,GAAG,UAAU,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IACjD,MAAM,EAAE,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC;IAC9C,sEAAsE;IACtE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,mBAAmB,CAAC,GAAG,EAAE,IAAI,IAAI,GAAG,CAAC,CAAC;IAEvE,IAAI,IAAI,KAAK,UAAU,IAAI,MAAM;QAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;IACvE,IAAI,IAAI,KAAK,iBAAiB,EAAE,CAAC;QAC/B,kHAAkH;QAClH,UAAU;QACV,MAAM,WAAW,GAAG,UAAU,CAAC,GAAG,EAAE,WAAW,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,EAAE,IAAI,IAAI,GAAG,EAAE,MAAM,CAAC,CAAC;QAE7G,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,GAAG,CAAC,EAAE,CAAC;IAC7E,CAAC;IAED,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,KAAK,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;IAElC,OAAO;QACL,MAAM,EAAE,UAAU,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,IAAI,GAAG,EAAE,MAAM,CAAC;QACtD,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO;QACzC,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO;KAC1C,CAAC;AACJ,CAAC,CAAC","sourcesContent":["/** Where a raster layer's tiles come from: a PMTiles archive, Web Mercator tiles, or tiles reprojected from a grid. */\n\nimport { equirectangularGrid, gridLoader, gridZooms, type RemoteReprojection, resolveGrid } from '../basemap/grid.ts';\nimport { pmtilesRasterLoader } from '../basemap/pmtileslayer.ts';\nimport type { RasterOptions } from '../types.ts';\n\n/** The loader of a raster layer's tiles (none: the engine fetches them) and its zooms, in Web Mercator levels */\nexport interface RasterSource {\n loader: RasterOptions['loader'];\n minZoom: number;\n maxZoom: number;\n}\n\n/** The loader of a raster layer's tiles and its zooms; `remote` reprojects in the workers */\nexport const rasterSource = (options: RasterOptions, remote: RemoteReprojection): RasterSource => {\n const { url, grid = 'mercator', size } = options;\n const { minZoom = 0, maxZoom = 19 } = options;\n // A PMTiles archive (`pmtiles://…`): its tiles read by range requests\n const loader = options.loader ?? pmtilesRasterLoader(url, size ?? 256);\n\n if (grid === 'mercator' || loader) return { loader, minZoom, maxZoom };\n if (grid === 'equirectangular') {\n // `minZoom` and `maxZoom` are levels of the source: its level n has the pixel size of Mercator level n + 1 at the\n // equator\n const reprojected = gridLoader(url, resolveGrid(equirectangularGrid(minZoom, maxZoom)), size ?? 256, remote);\n\n return { loader: reprojected, minZoom: minZoom + 1, maxZoom: maxZoom + 1 };\n }\n\n const resolved = resolveGrid(grid);\n const zooms = gridZooms(resolved);\n\n return {\n loader: gridLoader(url, resolved, size ?? 256, remote),\n minZoom: options.minZoom ?? zooms.minZoom,\n maxZoom: options.maxZoom ?? zooms.maxZoom,\n };\n};\n"]}
|
package/dist/map/workers.d.ts
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import type { RemoteReprojection } from '../basemap/grid.ts';
|
|
6
6
|
import { type PngEncoding } from '../basemap/terrain.ts';
|
|
7
|
-
import { BasemapWorkers } from '../basemap/
|
|
7
|
+
import { BasemapWorkers } from '../basemap/workerpool.ts';
|
|
8
|
+
import { type Grid } from '../grids.ts';
|
|
8
9
|
import type { TerrainLoader } from '../settings.ts';
|
|
9
10
|
import type { GeoMapOptions } from '../types.ts';
|
|
10
11
|
/** The workers of a map, created on first use */
|
|
@@ -38,6 +39,9 @@ export declare class MapWorkers {
|
|
|
38
39
|
/** The loader of the relief tiles of `url` in a PNG encoding (one per URL, encoding and floor) */
|
|
39
40
|
readonly terrainLoader: (url: string, encoding: PngEncoding, floor?: number) => TerrainLoader;
|
|
40
41
|
private readonly remoteHeights;
|
|
42
|
+
/** A GRIB2 or NetCDF file read into grids by the grid module (`module`), in a worker (in the page without them, or if
|
|
43
|
+
* the worker fails) */
|
|
44
|
+
readGrids(source: string | URL | ArrayBuffer | Uint8Array, module: string, signal?: AbortSignal): Promise<Grid[]>;
|
|
41
45
|
/**
|
|
42
46
|
* The workers decoding the relief and reprojecting rasters: the shared pool, unless the map has no workers
|
|
43
47
|
* (`workers: false` or 0, or none in this browser): that is done in the page then
|
package/dist/map/workers.js
CHANGED
|
@@ -3,7 +3,10 @@
|
|
|
3
3
|
* reprojects rasters off the page; and the loaders of the relief, one per tile source.
|
|
4
4
|
*/
|
|
5
5
|
import { encodedTerrainLoader } from "../basemap/terrain.js";
|
|
6
|
-
import { BasemapWorkers, defaultWorkerCount } from "../basemap/
|
|
6
|
+
import { BasemapWorkers, defaultWorkerCount } from "../basemap/workerpool.js";
|
|
7
|
+
import { withHeaders } from "../engine/requests.js";
|
|
8
|
+
import { decodeGrids } from "../grid-module.js";
|
|
9
|
+
import { gridOf } from "../grids.js";
|
|
7
10
|
/** The workers of a map, created on first use */
|
|
8
11
|
export class MapWorkers {
|
|
9
12
|
/** URL of the workers' script */
|
|
@@ -57,6 +60,38 @@ export class MapWorkers {
|
|
|
57
60
|
return loader;
|
|
58
61
|
};
|
|
59
62
|
remoteHeights = (url, encoding, floor, tile, signal) => this.decodingPool()?.heights(url, encoding, floor, tile, signal, this.owner);
|
|
63
|
+
/** A GRIB2 or NetCDF file read into grids by the grid module (`module`), in a worker (in the page without them, or if
|
|
64
|
+
* the worker fails) */
|
|
65
|
+
async readGrids(source, module, signal) {
|
|
66
|
+
const pool = this.decodingPool();
|
|
67
|
+
const url = typeof source === 'string' || source instanceof URL ? String(source) : undefined;
|
|
68
|
+
const copy = source instanceof Uint8Array ? source.slice().buffer : undefined;
|
|
69
|
+
const bytes = copy ?? (source instanceof ArrayBuffer ? source : undefined);
|
|
70
|
+
// Against the page: the workers fetch it, and a relative URL would be theirs
|
|
71
|
+
const absolute = url && typeof document !== 'undefined' ? new URL(url, document.baseURI).href : url;
|
|
72
|
+
const fetchFile = async (at) => {
|
|
73
|
+
const response = await fetch(at, withHeaders(at, signal ? { signal } : {}));
|
|
74
|
+
if (!response.ok)
|
|
75
|
+
throw new Error(`isard: ${at}: ${response.status}`);
|
|
76
|
+
return response.arrayBuffer();
|
|
77
|
+
};
|
|
78
|
+
const inPage = async () => decodeGrids(new Uint8Array(bytes ?? (await fetchFile(absolute ?? ''))), module);
|
|
79
|
+
const read = async () => {
|
|
80
|
+
if (!pool)
|
|
81
|
+
return inPage();
|
|
82
|
+
return pool
|
|
83
|
+
.grids(absolute ? { url: absolute } : { bytes: bytes ?? new ArrayBuffer(0) }, module, signal, this.owner)
|
|
84
|
+
.catch((error) => {
|
|
85
|
+
// A worker's failure (the module not fetched, a worker of an older build): read again in the page, unless
|
|
86
|
+
// cancelled or its bytes handed over
|
|
87
|
+
if (signal?.aborted || bytes?.byteLength === 0)
|
|
88
|
+
throw error;
|
|
89
|
+
return inPage();
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
const { grids, values } = await read();
|
|
93
|
+
return grids.map((g, i) => gridOf(g, values[i] ?? new Float32Array()));
|
|
94
|
+
}
|
|
60
95
|
/**
|
|
61
96
|
* The workers decoding the relief and reprojecting rasters: the shared pool, unless the map has no workers
|
|
62
97
|
* (`workers: false` or 0, or none in this browser): that is done in the page then
|
package/dist/map/workers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workers.js","sourceRoot":"","sources":["../../src/map/workers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,oBAAoB,EAAwC,MAAM,uBAAuB,CAAC;AACnG,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAI/E,iDAAiD;AACjD,MAAM,OAAO,UAAU;IACrB,iCAAiC;IACxB,GAAG,CAAe;IACV,OAAO,CAA2B;IACnD,gEAAgE;IAC/C,IAAI,CAAgB;IACrC,8DAA8D;IAC7C,KAAK,CAAS;IAC/B,4CAA4C;IACpC,MAAM,CAA6B;IAC3C;mDAC+C;IAC9B,cAAc,GAAG,IAAI,GAAG,EAAyB,CAAC;IAEnE,4EAA4E;IAC5E,YAAY,GAAiB,EAAE,OAAiC,EAAE,IAAmB,EAAE,KAAa;QAClG,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED;;;OAGG;IACH,IAAI,CAAC,KAAc,EAAE,GAAkB;QACrC,MAAM,MAAM,GAAG,kBAAkB,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,IAAI,MAAM,CAAC,CAAC;QAC7C,MAAM,SAAS,GAAG,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;QAElC,IAAI,OAAO,KAAK,MAAM,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACjE,IAAI,CAAC,MAAM,KAAK,IAAI,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;YAErD,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;QAC3C,CAAC;QAED,OAAO,EAAE,IAAI,EAAE,IAAI,cAAc,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;IACrE,CAAC;IAED,4BAA4B;IAC5B,SAAS;QACP,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;IAC1B,CAAC;IAED,oEAAoE;IAC3D,kBAAkB,GAAuB,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,CACtE,IAAI,CAAC,YAAY,EAAE,EAAE,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAEhE,kGAAkG;IACzF,aAAa,GAAG,CAAC,GAAW,EAAE,QAAqB,EAAE,KAAc,EAAiB,EAAE;QAC7F,MAAM,GAAG,GAAG,GAAG,QAAQ,IAAI,KAAK,IAAI,EAAE,IAAI,GAAG,EAAE,CAAC;QAChD,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAE5C,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;QAE1B,MAAM,MAAM,GAAG,oBAAoB,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QAE9E,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAErC,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;IAEe,aAAa,GAAkB,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,CACrF,IAAI,CAAC,YAAY,EAAE,EAAE,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAE/E;;;OAGG;IACK,YAAY;QAClB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAE7B,IAAI,IAAI,CAAC,IAAI,EAAE,IAAI,OAAO,KAAK,KAAK,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,IAAI,CAAC,CAAC;YAAE,OAAO,SAAS,CAAC;QAClG,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,eAAe,KAAK,WAAW;YAAE,OAAO,SAAS,CAAC;QAE9F,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC;IAC1B,CAAC;CACF","sourcesContent":["/**\n * A map's workers: the pool drawing vector tiles, shared by the map's `VectorTiles`, which also decodes the relief and\n * reprojects rasters off the page; and the loaders of the relief, one per tile source.\n */\n\nimport type { RemoteReprojection } from '../basemap/grid.ts';\nimport { encodedTerrainLoader, type PngEncoding, type RemoteHeights } from '../basemap/terrain.ts';\nimport { BasemapWorkers, defaultWorkerCount } from '../basemap/vectortiles.ts';\nimport type { TerrainLoader } from '../settings.ts';\nimport type { GeoMapOptions } from '../types.ts';\n\n/** The workers of a map, created on first use */\nexport class MapWorkers {\n /** URL of the workers' script */\n readonly url: string | URL;\n private readonly workers: GeoMapOptions['workers'];\n /** The map is destroyed: nothing more is sent to the workers */\n private readonly gone: () => boolean;\n /** Whose requests the workers' answer (cancelled together) */\n private readonly owner: object;\n /** The shared pool, created on first use */\n private shared: BasemapWorkers | undefined;\n /** The loaders of the relief by encoding, URL and floor: the same loader for the same tiles (the engine keeps its\n * tiles when only the exaggeration changes) */\n private readonly terrainLoaders = new Map<string, TerrainLoader>();\n\n /** `workers`: the map's option (false or 0, no worker); `owner`: the map */\n constructor(url: string | URL, workers: GeoMapOptions['workers'], gone: () => boolean, owner: object) {\n this.url = url;\n this.workers = workers;\n this.gone = gone;\n this.owner = owner;\n }\n\n /**\n * The workers for a `VectorTiles`: the shared pool, or a pool of its own (`own`, to stop with it) when it asks for\n * another count or URL\n */\n pool(count?: number, url?: string | URL): { pool: BasemapWorkers; own: boolean } {\n const shared = defaultWorkerCount();\n const workers = Math.max(1, count ?? shared);\n const workerUrl = url ?? this.url;\n\n if (workers === shared && String(workerUrl) === String(this.url)) {\n this.shared ??= new BasemapWorkers(shared, this.url);\n\n return { pool: this.shared, own: false };\n }\n\n return { pool: new BasemapWorkers(workers, workerUrl), own: true };\n }\n\n /** Stops the shared pool */\n terminate(): void {\n this.shared?.terminate();\n this.shared = undefined;\n }\n\n /** Rasters reprojected by the workers (in the page without them) */\n readonly remoteReprojection: RemoteReprojection = (job, tile, signal) =>\n this.decodingPool()?.reproject(job, tile, signal, this.owner);\n\n /** The loader of the relief tiles of `url` in a PNG encoding (one per URL, encoding and floor) */\n readonly terrainLoader = (url: string, encoding: PngEncoding, floor?: number): TerrainLoader => {\n const key = `${encoding} ${floor ?? ''} ${url}`;\n const cached = this.terrainLoaders.get(key);\n\n if (cached) return cached;\n\n const loader = encodedTerrainLoader(url, encoding, floor, this.remoteHeights);\n\n this.terrainLoaders.set(key, loader);\n\n return loader;\n };\n\n private readonly remoteHeights: RemoteHeights = (url, encoding, floor, tile, signal) =>\n this.decodingPool()?.heights(url, encoding, floor, tile, signal, this.owner);\n\n /**\n * The workers decoding the relief and reprojecting rasters: the shared pool, unless the map has no workers\n * (`workers: false` or 0, or none in this browser): that is done in the page then\n */\n private decodingPool(): BasemapWorkers | undefined {\n const workers = this.workers;\n\n if (this.gone() || workers === false || (workers !== undefined && workers <= 0)) return undefined;\n if (typeof Worker === 'undefined' || typeof OffscreenCanvas === 'undefined') return undefined;\n\n return this.pool().pool;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"workers.js","sourceRoot":"","sources":["../../src/map/workers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A map's workers: the pool drawing vector tiles, shared by the map's `VectorTiles`, which also decodes the relief and\n * reprojects rasters off the page; and the loaders of the relief, one per tile source.\n */\n\nimport type { RemoteReprojection } from '../basemap/grid.ts';\nimport { encodedTerrainLoader, type PngEncoding, type RemoteHeights } from '../basemap/terrain.ts';\nimport { BasemapWorkers, defaultWorkerCount } from '../basemap/workerpool.ts';\nimport { withHeaders } from '../engine/requests.ts';\nimport { decodeGrids } from '../grid-module.ts';\nimport { type Grid, gridOf } from '../grids.ts';\nimport type { TerrainLoader } from '../settings.ts';\nimport type { GeoMapOptions } from '../types.ts';\n\n/** The workers of a map, created on first use */\nexport class MapWorkers {\n /** URL of the workers' script */\n readonly url: string | URL;\n private readonly workers: GeoMapOptions['workers'];\n /** The map is destroyed: nothing more is sent to the workers */\n private readonly gone: () => boolean;\n /** Whose requests the workers' answer (cancelled together) */\n private readonly owner: object;\n /** The shared pool, created on first use */\n private shared: BasemapWorkers | undefined;\n /** The loaders of the relief by encoding, URL and floor: the same loader for the same tiles (the engine keeps its\n * tiles when only the exaggeration changes) */\n private readonly terrainLoaders = new Map<string, TerrainLoader>();\n\n /** `workers`: the map's option (false or 0, no worker); `owner`: the map */\n constructor(url: string | URL, workers: GeoMapOptions['workers'], gone: () => boolean, owner: object) {\n this.url = url;\n this.workers = workers;\n this.gone = gone;\n this.owner = owner;\n }\n\n /**\n * The workers for a `VectorTiles`: the shared pool, or a pool of its own (`own`, to stop with it) when it asks for\n * another count or URL\n */\n pool(count?: number, url?: string | URL): { pool: BasemapWorkers; own: boolean } {\n const shared = defaultWorkerCount();\n const workers = Math.max(1, count ?? shared);\n const workerUrl = url ?? this.url;\n\n if (workers === shared && String(workerUrl) === String(this.url)) {\n this.shared ??= new BasemapWorkers(shared, this.url);\n\n return { pool: this.shared, own: false };\n }\n\n return { pool: new BasemapWorkers(workers, workerUrl), own: true };\n }\n\n /** Stops the shared pool */\n terminate(): void {\n this.shared?.terminate();\n this.shared = undefined;\n }\n\n /** Rasters reprojected by the workers (in the page without them) */\n readonly remoteReprojection: RemoteReprojection = (job, tile, signal) =>\n this.decodingPool()?.reproject(job, tile, signal, this.owner);\n\n /** The loader of the relief tiles of `url` in a PNG encoding (one per URL, encoding and floor) */\n readonly terrainLoader = (url: string, encoding: PngEncoding, floor?: number): TerrainLoader => {\n const key = `${encoding} ${floor ?? ''} ${url}`;\n const cached = this.terrainLoaders.get(key);\n\n if (cached) return cached;\n\n const loader = encodedTerrainLoader(url, encoding, floor, this.remoteHeights);\n\n this.terrainLoaders.set(key, loader);\n\n return loader;\n };\n\n private readonly remoteHeights: RemoteHeights = (url, encoding, floor, tile, signal) =>\n this.decodingPool()?.heights(url, encoding, floor, tile, signal, this.owner);\n\n /** A GRIB2 or NetCDF file read into grids by the grid module (`module`), in a worker (in the page without them, or if\n * the worker fails) */\n async readGrids(\n source: string | URL | ArrayBuffer | Uint8Array,\n module: string,\n signal?: AbortSignal,\n ): Promise<Grid[]> {\n const pool = this.decodingPool();\n const url = typeof source === 'string' || source instanceof URL ? String(source) : undefined;\n const copy = source instanceof Uint8Array ? source.slice().buffer : undefined;\n const bytes = copy ?? (source instanceof ArrayBuffer ? source : undefined);\n // Against the page: the workers fetch it, and a relative URL would be theirs\n const absolute = url && typeof document !== 'undefined' ? new URL(url, document.baseURI).href : url;\n const fetchFile = async (at: string) => {\n const response = await fetch(at, withHeaders(at, signal ? { signal } : {}));\n\n if (!response.ok) throw new Error(`isard: ${at}: ${response.status}`);\n\n return response.arrayBuffer();\n };\n const inPage = async () => decodeGrids(new Uint8Array(bytes ?? (await fetchFile(absolute ?? ''))), module);\n const read = async () => {\n if (!pool) return inPage();\n\n return pool\n .grids(absolute ? { url: absolute } : { bytes: bytes ?? new ArrayBuffer(0) }, module, signal, this.owner)\n .catch((error: unknown) => {\n // A worker's failure (the module not fetched, a worker of an older build): read again in the page, unless\n // cancelled or its bytes handed over\n if (signal?.aborted || bytes?.byteLength === 0) throw error;\n\n return inPage();\n });\n };\n const { grids, values } = await read();\n\n return grids.map((g, i) => gridOf(g, values[i] ?? new Float32Array()));\n }\n\n /**\n * The workers decoding the relief and reprojecting rasters: the shared pool, unless the map has no workers\n * (`workers: false` or 0, or none in this browser): that is done in the page then\n */\n private decodingPool(): BasemapWorkers | undefined {\n const workers = this.workers;\n\n if (this.gone() || workers === false || (workers !== undefined && workers <= 0)) return undefined;\n if (typeof Worker === 'undefined' || typeof OffscreenCanvas === 'undefined') return undefined;\n\n return this.pool().pool;\n }\n}\n"]}
|
package/dist/map.d.ts
CHANGED
|
@@ -5,9 +5,12 @@
|
|
|
5
5
|
* the camera animations in animation.ts; the parts of the map with a state of their own (the drawing order of the
|
|
6
6
|
* layers, the overlays and controls, the frame loop, the hover picking, the workers…) in map/.
|
|
7
7
|
*/
|
|
8
|
-
import { type PmtilesOptions
|
|
8
|
+
import { type PmtilesOptions } from './basemap/pmtileslayer.ts';
|
|
9
|
+
import { VectorTiles, type VectorTilesOptions } from './basemap/vectortiles.ts';
|
|
10
|
+
import type { Grid } from './grids.ts';
|
|
9
11
|
import { ExtrusionLayer, type ExtrusionOptions } from './layers/extrusions.ts';
|
|
10
12
|
import { CircleLayer, type CircleOptions, FillLayer, type FillOptions, LineLayer, type LineOptions } from './layers/features.ts';
|
|
13
|
+
import { FlowLayer, type FlowOptions } from './layers/flow.ts';
|
|
11
14
|
import type { ImageOptions, Pixels } from './layers/icons.ts';
|
|
12
15
|
import { CustomLayer, type CustomLayerInterface, GroundLayer, type GroundOptions, type Layer, ModelLayer, type ModelOptions, NetworkLayer, RasterLayer, Tiles3dLayer } from './layers/layers.ts';
|
|
13
16
|
import { type PanoramaOptions, type Panoramas } from './layers/panoramas.ts';
|
|
@@ -15,7 +18,7 @@ import { PointCloudLayer, type PointCloudOptions } from './layers/pointclouds.ts
|
|
|
15
18
|
import { SymbolLayer, type SymbolOptions } from './layers/symbols.ts';
|
|
16
19
|
import { type HoverPicking } from './map/hover-pick.ts';
|
|
17
20
|
import { type LayerSpec } from './map/layer-spec.ts';
|
|
18
|
-
import type { AnimationOptions, AtmosphereOptions, Basemap, FeatureHit, FirstPersonView, FlyToOptions, GeoMapOptions, LoadingMode, LonLat, MapEvents, NetworkOptions, Point, Projection, RasterOptions, SwipeOptions, TerrainModel, TerrainOptions, Tiles3dOptions, ViewshedOptions } from './types.ts';
|
|
21
|
+
import type { AnimationOptions, AtmosphereOptions, Basemap, FeatureHit, FirstPersonView, FlyToOptions, GeoMapOptions, LoadingMode, LonLat, MapEvents, NetworkOptions, Point, Projection, RasterOptions, SunOptions, SwipeOptions, TerrainModel, TerrainOptions, Tiles3dOptions, ViewshedOptions } from './types.ts';
|
|
19
22
|
import { type Control, type ControlPosition } from './ui/controls.ts';
|
|
20
23
|
import type { Camera, PickHit, RasterLayerStats } from './wasm/isard.js';
|
|
21
24
|
export type { LayerSpec } from './map/layer-spec.ts';
|
|
@@ -95,7 +98,8 @@ export declare class GeoMap {
|
|
|
95
98
|
/**
|
|
96
99
|
* Compares two states of a place: `layers` shown on one side of a vertical line only, at `position` CSS pixels
|
|
97
100
|
* from the left of the map (left of it by default, `side: 'right'` for the other), the layers beneath them on the
|
|
98
|
-
* other side
|
|
101
|
+
* other side; `other`: layers shown on the other side only (two meshes of a place, each on its side). Set again as
|
|
102
|
+
* the line moves (a slider, a drag); undefined stops
|
|
99
103
|
*/
|
|
100
104
|
setSwipe(options: SwipeOptions | undefined): void;
|
|
101
105
|
private applySwipe;
|
|
@@ -134,9 +138,10 @@ export declare class GeoMap {
|
|
|
134
138
|
readonly elevationAt: (lonLat: LonLat) => number | undefined;
|
|
135
139
|
readonly metersPerPixel: (point?: Point) => number | undefined;
|
|
136
140
|
};
|
|
137
|
-
/** What is drawn over the scene, together: `viewshed` (`setViewshed`), `swipe` (`setSwipe`) */
|
|
141
|
+
/** What is drawn over the scene, together: `viewshed` (`setViewshed`), `sun` (`setSun`), `swipe` (`setSwipe`) */
|
|
138
142
|
readonly effects: {
|
|
139
143
|
readonly viewshed: (options: ViewshedOptions | readonly ViewshedOptions[] | undefined) => void;
|
|
144
|
+
readonly sun: (options: SunOptions | undefined) => void;
|
|
140
145
|
readonly swipe: (options: SwipeOptions | undefined) => void;
|
|
141
146
|
};
|
|
142
147
|
getCamera(): Camera;
|
|
@@ -164,6 +169,18 @@ export declare class GeoMap {
|
|
|
164
169
|
setSky(enabled: boolean): void;
|
|
165
170
|
/** The viewshed set, set again in a new engine */
|
|
166
171
|
private viewshed;
|
|
172
|
+
/** The sun set, set again in a new engine */
|
|
173
|
+
private sun;
|
|
174
|
+
/**
|
|
175
|
+
* The sun casting shadows: the buildings, trees, models, 3D Tiles and the relief shade the ground and one another,
|
|
176
|
+
* the walls turned away from it are in their own shade; the labels stay over them. The sun stands where it is at
|
|
177
|
+
* `date` over the map's center (now by default), or at `azimuth` and `altitude`. As it sets the night falls (`night`
|
|
178
|
+
* to set it by hand): the scene tinted in its blue, the windows of the buildings and the streets of `vectors()` lit,
|
|
179
|
+
* the labels light on dark.
|
|
180
|
+
* The shadows cover the ground around the view's center, fading out away from it, and cost two more depth passes
|
|
181
|
+
* of the solid scene each frame. Undefined removes them
|
|
182
|
+
*/
|
|
183
|
+
setSun(options: SunOptions | undefined): void;
|
|
167
184
|
/** Tints what can be seen from a point and what is hidden from it, within a range, all around or within a cone
|
|
168
185
|
* (`direction`): the relief, extrusions, 3D Tiles and models hide what lies behind them (only what the map has
|
|
169
186
|
* loaded for its view). Several observers (16 at most): what any of them sees is seen, what is hidden from all those
|
|
@@ -279,8 +296,8 @@ export declare class GeoMap {
|
|
|
279
296
|
removeImage(name: string): void;
|
|
280
297
|
/**
|
|
281
298
|
* Vector tiles with a MapLibre style (OpenFreeMap's Positron by default): `tiles.raster(…)` draws its fills and lines
|
|
282
|
-
* (or a subset) as a raster layer, `tiles.
|
|
283
|
-
* basemap.
|
|
299
|
+
* (or a subset) as a raster layer, `tiles.vectors(…)` as geometry, `tiles.labels(…)` its labels.
|
|
300
|
+
* `setBasemap('osm-positron')` draws the basemap with a raster layer and the labels.
|
|
284
301
|
*/
|
|
285
302
|
vectorTiles(options?: VectorTilesOptions): VectorTiles;
|
|
286
303
|
/** Adds a layer, under `before` if given */
|
|
@@ -294,6 +311,18 @@ export declare class GeoMap {
|
|
|
294
311
|
addPointCloud(options: PointCloudOptions & {
|
|
295
312
|
before?: Layer;
|
|
296
313
|
}): PointCloudLayer;
|
|
314
|
+
/**
|
|
315
|
+
* The grids of a GRIB2 or classic NetCDF file (its URL, or its bytes): a weather or ocean model's fields on grids of
|
|
316
|
+
* longitudes and latitudes, read in a worker by the grid module (loaded with the first file). GRIB2 on a regular
|
|
317
|
+
* latitude/longitude grid, packed simply, in groups or in groups of spatial differences (NOAA's GFS); NetCDF-3 with
|
|
318
|
+
* the CF conventions. `windFields` pairs a wind's components into the fields of `addFlow`
|
|
319
|
+
*/
|
|
320
|
+
readGrids(source: string | URL | ArrayBuffer | Uint8Array, options?: {
|
|
321
|
+
signal?: AbortSignal;
|
|
322
|
+
}): Promise<Grid[]>;
|
|
323
|
+
/** Particles carried by a field of velocities (a wind, a current), their trails animated and colored by speed on
|
|
324
|
+
* the globe and the relief (see `FlowOptions`) */
|
|
325
|
+
addFlow(options: FlowOptions): FlowLayer;
|
|
297
326
|
/** A glTF model drawn at positions (see `ModelOptions`), with depth; on the engine with 3D Tiles, as they are */
|
|
298
327
|
addModels(options: ModelOptions & {
|
|
299
328
|
before?: Layer;
|