isard 1.16.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +4 -4
  3. package/dist/basemap/vectortiles/placed.js +7 -4
  4. package/dist/basemap/vectortiles/placed.js.map +1 -1
  5. package/dist/basemap/vectortiles/tiles.d.ts +1 -1
  6. package/dist/basemap/vectortiles/tiles.js.map +1 -1
  7. package/dist/basemap/workerpool.d.ts +1 -1
  8. package/dist/basemap/workerpool.js.map +1 -1
  9. package/dist/decoder.worker.js +4 -5
  10. package/dist/decoder.worker.js.map +6 -6
  11. package/dist/decoding/decoders.d.ts +1 -1
  12. package/dist/decoding/decoders.js.map +1 -1
  13. package/dist/decoding/loader.d.ts +6 -3
  14. package/dist/decoding/loader.js +7 -5
  15. package/dist/decoding/loader.js.map +1 -1
  16. package/dist/decoding/protocol.d.ts +3 -2
  17. package/dist/decoding/protocol.js.map +1 -1
  18. package/dist/engine-loader.d.ts +20 -18
  19. package/dist/engine-loader.js +45 -42
  20. package/dist/engine-loader.js.map +1 -1
  21. package/dist/index.d.ts +3 -3
  22. package/dist/index.js.map +1 -1
  23. package/dist/isard_grid_bg.wasm +0 -0
  24. package/dist/isard_tess_bg.wasm +0 -0
  25. package/dist/isard_tiles3d_bg.wasm +0 -0
  26. package/dist/isard_webgl2_bg.wasm +0 -0
  27. package/dist/isard_webgpu_bg.wasm +0 -0
  28. package/dist/layers/custom.d.ts +35 -29
  29. package/dist/layers/custom.js +60 -46
  30. package/dist/layers/custom.js.map +1 -1
  31. package/dist/layers/extrusions.js.map +1 -1
  32. package/dist/layers/features.js.map +1 -1
  33. package/dist/layers/flow.js.map +1 -1
  34. package/dist/layers/glyphs.d.ts +1 -1
  35. package/dist/layers/glyphs.js.map +1 -1
  36. package/dist/layers/ground.d.ts +20 -13
  37. package/dist/layers/ground.js +29 -8
  38. package/dist/layers/ground.js.map +1 -1
  39. package/dist/layers/icons.d.ts +1 -1
  40. package/dist/layers/icons.js.map +1 -1
  41. package/dist/layers/layers.d.ts +1 -2
  42. package/dist/layers/layers.js +2 -11
  43. package/dist/layers/layers.js.map +1 -1
  44. package/dist/layers/models.js +0 -4
  45. package/dist/layers/models.js.map +1 -1
  46. package/dist/layers/network.d.ts +1 -1
  47. package/dist/layers/network.js.map +1 -1
  48. package/dist/layers/panoramas.d.ts +1 -0
  49. package/dist/layers/panoramas.js +3 -2
  50. package/dist/layers/panoramas.js.map +1 -1
  51. package/dist/layers/pointclouds.d.ts +1 -1
  52. package/dist/layers/pointclouds.js +0 -4
  53. package/dist/layers/pointclouds.js.map +1 -1
  54. package/dist/layers/raster.js.map +1 -1
  55. package/dist/layers/symbols.js.map +1 -1
  56. package/dist/layers/tiles3d.d.ts +1 -1
  57. package/dist/layers/tiles3d.js +0 -4
  58. package/dist/layers/tiles3d.js.map +1 -1
  59. package/dist/layers/vectors.d.ts +4 -5
  60. package/dist/layers/vectors.js +7 -15
  61. package/dist/layers/vectors.js.map +1 -1
  62. package/dist/map/engine-settings.d.ts +1 -1
  63. package/dist/map/engine-settings.js.map +1 -1
  64. package/dist/map/engines.d.ts +11 -26
  65. package/dist/map/engines.js +10 -48
  66. package/dist/map/engines.js.map +1 -1
  67. package/dist/map/frame-loop.d.ts +1 -3
  68. package/dist/map/frame-loop.js +3 -3
  69. package/dist/map/frame-loop.js.map +1 -1
  70. package/dist/map/hover-pick.d.ts +9 -3
  71. package/dist/map/hover-pick.js +29 -6
  72. package/dist/map/hover-pick.js.map +1 -1
  73. package/dist/map/layer-stack.d.ts +2 -2
  74. package/dist/map/layer-stack.js +1 -3
  75. package/dist/map/layer-stack.js.map +1 -1
  76. package/dist/map/symbol-atlases.d.ts +5 -4
  77. package/dist/map/symbol-atlases.js +8 -13
  78. package/dist/map/symbol-atlases.js.map +1 -1
  79. package/dist/map/viewshed.d.ts +1 -1
  80. package/dist/map/viewshed.js.map +1 -1
  81. package/dist/map.d.ts +26 -20
  82. package/dist/map.js +93 -78
  83. package/dist/map.js.map +1 -1
  84. package/dist/react/IsardMap.d.ts +1 -1
  85. package/dist/react/IsardMap.js.map +1 -1
  86. package/dist/react/index.d.ts +1 -1
  87. package/dist/react/index.js.map +1 -1
  88. package/dist/types.d.ts +29 -18
  89. package/dist/types.js.map +1 -1
  90. package/dist/ui/interaction.d.ts +1 -1
  91. package/dist/ui/interaction.js.map +1 -1
  92. package/dist/util/animation.d.ts +1 -1
  93. package/dist/util/animation.js.map +1 -1
  94. package/dist/wasm/isard_tiles3d.d.ts +181 -0
  95. package/dist/wasm/isard_tiles3d.js +387 -0
  96. package/dist/wasm/{isard_core.d.ts → isard_webgl2.d.ts} +373 -182
  97. package/dist/wasm/{isard_core.js → isard_webgl2.js} +2155 -413
  98. package/dist/wasm/{isard.d.ts → isard_webgpu.d.ts} +176 -353
  99. package/dist/wasm/{isard.js → isard_webgpu.js} +1361 -1104
  100. package/package.json +4 -3
  101. package/vite.js +5 -4
  102. package/dist/isard_bg.wasm +0 -0
  103. package/dist/isard_core_bg.wasm +0 -0
@@ -1,9 +1,29 @@
1
1
  /**
2
- * The picking of what is under the pointer for 'hoverfeature', without stalling the GPU: the engine is asked once the
3
- * frame is drawn, its answer read on a later frame, when the GPU is done.
2
+ * The picking of what is under a point, without stalling the GPU: the engine draws its picking pass at once, its
3
+ * answer is read on a later frame, when the GPU is done. For 'hoverfeature' (the latest request only) and for
4
+ * `map.pick` (`pickOnce`).
4
5
  */
5
- /** Frames the hover picking waits for its answer at most (usually one) */
6
+ /** Frames a picking waits for its answer at most (usually one or two) */
6
7
  const MAX_POLLS = 30;
8
+ /** What the engine finds under a point (CSS pixels), within `radius` CSS pixels, in the layers of `only` if given;
9
+ * undefined if it cannot pick, or no answer came in time */
10
+ export const pickOnce = (engine, point, radius, only) => {
11
+ const id = engine().requestPick(point[0], point[1], radius, only);
12
+ if (!id)
13
+ return Promise.resolve(undefined);
14
+ return new Promise((resolve) => {
15
+ let polls = 0;
16
+ const next = () => {
17
+ const result = engine().pollPick(id);
18
+ polls += 1;
19
+ if (result || polls >= MAX_POLLS)
20
+ resolve(result);
21
+ else
22
+ requestAnimationFrame(next);
23
+ };
24
+ requestAnimationFrame(next);
25
+ });
26
+ };
7
27
  /** The hover picking of a map: one request in flight at most, its answer polled frame after frame */
8
28
  export class HoverPick {
9
29
  engine;
@@ -14,6 +34,8 @@ export class HoverPick {
14
34
  poll = 0;
15
35
  /** Polls under way: given up after `MAX_POLLS` (an answer that never comes) */
16
36
  polls = 0;
37
+ /** The request whose answer is awaited */
38
+ id = 0;
17
39
  /** `engine`: the map's engine of the moment; `answer`: called with what the engine found */
18
40
  constructor(engine, lost, answer) {
19
41
  this.engine = engine;
@@ -23,12 +45,13 @@ export class HoverPick {
23
45
  /** Asks the engine what is under the pointer; its answer, read without waiting for the GPU, comes on a later frame */
24
46
  request(point, { radius = 0, layers }) {
25
47
  const only = layers && Uint32Array.from(layers.map((l) => l.id));
48
+ this.id = this.engine().requestPick(point[0], point[1], radius, only);
26
49
  // The engine cannot pick (no request in flight): the poll under way would wait for nothing
27
- if (!this.engine().requestPick(point[0], point[1], radius, only)) {
50
+ if (!this.id) {
28
51
  this.cancel();
29
52
  return;
30
53
  }
31
- // A new request replaces the one in flight (in the engine too): one poll loop at most
54
+ // A new request replaces the one awaited: one poll loop at most
32
55
  this.polls = 0;
33
56
  if (!this.poll)
34
57
  this.poll = requestAnimationFrame(this.next);
@@ -42,7 +65,7 @@ export class HoverPick {
42
65
  this.poll = 0;
43
66
  if (this.lost())
44
67
  return;
45
- const result = this.engine().pollPick();
68
+ const result = this.engine().pollPick(this.id);
46
69
  if (!result) {
47
70
  // The GPU is not done yet (usually a frame): asked again next frame, without drawing; given up at last
48
71
  this.polls += 1;
@@ -1 +1 @@
1
- {"version":3,"file":"hover-pick.js","sourceRoot":"","sources":["../../src/map/hover-pick.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,0EAA0E;AAC1E,MAAM,SAAS,GAAG,EAAE,CAAC;AAQrB,qGAAqG;AACrG,MAAM,OAAO,SAAS;IACH,MAAM,CAAe;IACtC,qDAAqD;IACpC,IAAI,CAAgB;IACpB,MAAM,CAA+B;IACtD,yDAAyD;IACjD,IAAI,GAAG,CAAC,CAAC;IACjB,+EAA+E;IACvE,KAAK,GAAG,CAAC,CAAC;IAElB,4FAA4F;IAC5F,YAAY,MAAoB,EAAE,IAAmB,EAAE,MAAoC;QACzF,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,sHAAsH;IACtH,OAAO,CAAC,KAAY,EAAE,EAAE,MAAM,GAAG,CAAC,EAAE,MAAM,EAAgB;QACxD,MAAM,IAAI,GAAG,MAAM,IAAI,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAEjE,2FAA2F;QAC3F,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC;YACjE,IAAI,CAAC,MAAM,EAAE,CAAC;YAEd,OAAO;QACT,CAAC;QACD,sFAAsF;QACtF,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,CAAC,IAAI;YAAE,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/D,CAAC;IAED,mCAAmC;IACnC,MAAM;QACJ,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;IAChB,CAAC;IAEgB,IAAI,GAAG,GAAS,EAAE;QACjC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;QACd,IAAI,IAAI,CAAC,IAAI,EAAE;YAAE,OAAO;QAExB,MAAM,MAAM,GAA2B,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC;QAEhE,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,uGAAuG;YACvG,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC;YAChB,IAAI,IAAI,CAAC,KAAK,GAAG,SAAS;gBAAE,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAEzE,OAAO;QACT,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACtB,CAAC,CAAC;CACH","sourcesContent":["/**\n * The picking of what is under the pointer for 'hoverfeature', without stalling the GPU: the engine is asked once the\n * frame is drawn, its answer read on a later frame, when the GPU is done.\n */\n\nimport type { Layer } from '../layers/layers.ts';\nimport type { Point } from '../types.ts';\nimport type { Engine, PickResult } from '../wasm/isard.js';\n\n/** Frames the hover picking waits for its answer at most (usually one) */\nconst MAX_POLLS = 30;\n\n/** What 'hoverfeature' looks for: within `radius` CSS pixels, in `layers` only if given */\nexport interface HoverPicking {\n radius?: number;\n layers?: readonly Layer[];\n}\n\n/** The hover picking of a map: one request in flight at most, its answer polled frame after frame */\nexport class HoverPick {\n private readonly engine: () => Engine;\n /** The WebGL context is lost: no answer will come */\n private readonly lost: () => boolean;\n private readonly answer: (result: PickResult) => void;\n /** Frame polling the engine for the answer, 0 if none */\n private poll = 0;\n /** Polls under way: given up after `MAX_POLLS` (an answer that never comes) */\n private polls = 0;\n\n /** `engine`: the map's engine of the moment; `answer`: called with what the engine found */\n constructor(engine: () => Engine, lost: () => boolean, answer: (result: PickResult) => void) {\n this.engine = engine;\n this.lost = lost;\n this.answer = answer;\n }\n\n /** Asks the engine what is under the pointer; its answer, read without waiting for the GPU, comes on a later frame */\n request(point: Point, { radius = 0, layers }: HoverPicking): void {\n const only = layers && Uint32Array.from(layers.map((l) => l.id));\n\n // The engine cannot pick (no request in flight): the poll under way would wait for nothing\n if (!this.engine().requestPick(point[0], point[1], radius, only)) {\n this.cancel();\n\n return;\n }\n // A new request replaces the one in flight (in the engine too): one poll loop at most\n this.polls = 0;\n if (!this.poll) this.poll = requestAnimationFrame(this.next);\n }\n\n /** Stops waiting for the answer */\n cancel(): void {\n cancelAnimationFrame(this.poll);\n this.poll = 0;\n }\n\n private readonly next = (): void => {\n this.poll = 0;\n if (this.lost()) return;\n\n const result: PickResult | undefined = this.engine().pollPick();\n\n if (!result) {\n // The GPU is not done yet (usually a frame): asked again next frame, without drawing; given up at last\n this.polls += 1;\n if (this.polls < MAX_POLLS) this.poll = requestAnimationFrame(this.next);\n\n return;\n }\n this.answer(result);\n };\n}\n"]}
1
+ {"version":3,"file":"hover-pick.js","sourceRoot":"","sources":["../../src/map/hover-pick.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The picking of what is under a point, without stalling the GPU: the engine draws its picking pass at once, its\n * answer is read on a later frame, when the GPU is done. For 'hoverfeature' (the latest request only) and for\n * `map.pick` (`pickOnce`).\n */\n\nimport type { Layer } from '../layers/layers.ts';\nimport type { Point } from '../types.ts';\nimport type { Engine, PickResult } from '../wasm/isard_webgpu.js';\n\n/** Frames a picking waits for its answer at most (usually one or two) */\nconst MAX_POLLS = 30;\n\n/** What the engine finds under a point (CSS pixels), within `radius` CSS pixels, in the layers of `only` if given;\n * undefined if it cannot pick, or no answer came in time */\nexport const pickOnce = (\n engine: () => Engine,\n point: Point,\n radius: number,\n only: Uint32Array | undefined,\n): Promise<PickResult | undefined> => {\n const id = engine().requestPick(point[0], point[1], radius, only);\n\n if (!id) return Promise.resolve(undefined);\n\n return new Promise((resolve) => {\n let polls = 0;\n const next = () => {\n const result: PickResult | undefined = engine().pollPick(id);\n\n polls += 1;\n if (result || polls >= MAX_POLLS) resolve(result);\n else requestAnimationFrame(next);\n };\n\n requestAnimationFrame(next);\n });\n};\n\n/** What 'hoverfeature' looks for: within `radius` CSS pixels, in `layers` only if given */\nexport interface HoverPicking {\n radius?: number;\n layers?: readonly Layer[];\n}\n\n/** The hover picking of a map: one request in flight at most, its answer polled frame after frame */\nexport class HoverPick {\n private readonly engine: () => Engine;\n /** The WebGL context is lost: no answer will come */\n private readonly lost: () => boolean;\n private readonly answer: (result: PickResult) => void;\n /** Frame polling the engine for the answer, 0 if none */\n private poll = 0;\n /** Polls under way: given up after `MAX_POLLS` (an answer that never comes) */\n private polls = 0;\n /** The request whose answer is awaited */\n private id = 0;\n\n /** `engine`: the map's engine of the moment; `answer`: called with what the engine found */\n constructor(engine: () => Engine, lost: () => boolean, answer: (result: PickResult) => void) {\n this.engine = engine;\n this.lost = lost;\n this.answer = answer;\n }\n\n /** Asks the engine what is under the pointer; its answer, read without waiting for the GPU, comes on a later frame */\n request(point: Point, { radius = 0, layers }: HoverPicking): void {\n const only = layers && Uint32Array.from(layers.map((l) => l.id));\n\n this.id = this.engine().requestPick(point[0], point[1], radius, only);\n // The engine cannot pick (no request in flight): the poll under way would wait for nothing\n if (!this.id) {\n this.cancel();\n\n return;\n }\n // A new request replaces the one awaited: one poll loop at most\n this.polls = 0;\n if (!this.poll) this.poll = requestAnimationFrame(this.next);\n }\n\n /** Stops waiting for the answer */\n cancel(): void {\n cancelAnimationFrame(this.poll);\n this.poll = 0;\n }\n\n private readonly next = (): void => {\n this.poll = 0;\n if (this.lost()) return;\n\n const result: PickResult | undefined = this.engine().pollPick(this.id);\n\n if (!result) {\n // The GPU is not done yet (usually a frame): asked again next frame, without drawing; given up at last\n this.polls += 1;\n if (this.polls < MAX_POLLS) this.poll = requestAnimationFrame(this.next);\n\n return;\n }\n this.answer(result);\n };\n}\n"]}
@@ -3,7 +3,7 @@
3
3
  * in the order but not in the engine yet, and the order recreates the layers in a new engine after a context loss.
4
4
  */
5
5
  import type { Layer } from '../layers/layers.ts';
6
- import type { Engine } from '../wasm/isard.js';
6
+ import type { Engine } from '../wasm/isard_webgpu.js';
7
7
  /** A map's layers in drawing order, bottom first, and those kept on top */
8
8
  export declare class LayerStack {
9
9
  /** Layers in drawing order (bottom first), to recreate them after a context loss */
@@ -26,7 +26,7 @@ export declare class LayerStack {
26
26
  toBottom(layer: Layer): void;
27
27
  /** Creates the layers in a new engine, in order, but those still `waiting` (for the engine with 3D Tiles); a layer
28
28
  * that fails is reported and left out */
29
- reattach(engine: Engine, waiting: (layer: Layer) => boolean): void;
29
+ reattach(engine: Engine): void;
30
30
  /** Frees what the layers hold beside the engine (custom layers' WebGL objects, models' data) */
31
31
  dispose(): void;
32
32
  /** Takes a layer out of the drawing order (to put it back elsewhere, or for good) */
@@ -54,14 +54,12 @@ export class LayerStack {
54
54
  }
55
55
  /** Creates the layers in a new engine, in order, but those still `waiting` (for the engine with 3D Tiles); a layer
56
56
  * that fails is reported and left out */
57
- reattach(engine, waiting) {
57
+ reattach(engine) {
58
58
  // No layer refers to an id of the old engine while the others are created
59
59
  this.layers.forEach((layer) => {
60
60
  layer.forgetEngine();
61
61
  });
62
62
  this.layers.forEach((layer) => {
63
- if (waiting(layer))
64
- return;
65
63
  try {
66
64
  layer.attach(engine);
67
65
  }
@@ -1 +1 @@
1
- {"version":3,"file":"layer-stack.js","sourceRoot":"","sources":["../../src/map/layer-stack.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,2EAA2E;AAC3E,MAAM,OAAO,UAAU;IACrB,oFAAoF;IAC3E,MAAM,GAAY,EAAE,CAAC;IAC9B,iCAAiC;IACxB,KAAK,GAAG,IAAI,GAAG,EAAS,CAAC;IACjB,MAAM,CAAe;IAEtC,+CAA+C;IAC/C,YAAY,MAAoB;QAC9B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,GAAG,CAAC,KAAY;QACd,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC;IAED,mFAAmF;IACnF,GAAG,CAAC,KAAY;QACd,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAExB,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC;QAEtE,IAAI,GAAG;YAAE,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACjC,CAAC;IAED,8BAA8B;IAC9B,MAAM,CAAC,KAAY;QACjB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACnB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IAED,qDAAqD;IACrD,IAAI,CAAC,KAAY,EAAE,MAAyB;QAC1C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAEnB,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxD,MAAM,EAAE,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;QAElD,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;QACjC,IAAI,KAAK,CAAC,EAAE,IAAI,CAAC;YAAE,IAAI,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7E,CAAC;IAED,6GAA6G;IAC7G,OAAO,CAAC,KAAY,EAAE,GAAW;QAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAE7B,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAExB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAEzC,IAAI,KAAK,IAAI,CAAC;YAAE,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;IACtE,CAAC;IAED,yCAAyC;IACzC,QAAQ,CAAC,KAAY;QACnB,IAAI,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACnB,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IAED;6CACyC;IACzC,QAAQ,CAAC,MAAc,EAAE,OAAkC;QACzD,0EAA0E;QAC1E,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;YAC5B,KAAK,CAAC,YAAY,EAAE,CAAC;QACvB,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;YAC5B,IAAI,OAAO,CAAC,KAAK,CAAC;gBAAE,OAAO;YAC3B,IAAI,CAAC;gBACH,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACvB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,KAAK,CAAC,CAAC;YAChB,CAAC;QACH,CAAC,CAAC,CAAC;QACH,oGAAoG;QACpG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;YAC5B,IAAI,KAAK,CAAC,EAAE,GAAG,CAAC;gBAAE,OAAO;YACzB,IAAI,CAAC;gBACH,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACvB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,KAAK,CAAC,CAAC;YAChB,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,gGAAgG;IAChG,OAAO;QACL,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;YAC5B,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,qFAAqF;IAC7E,MAAM,CAAC,KAAY;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAEzC,IAAI,KAAK,IAAI,CAAC;YAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAC/C,CAAC;IAED,qHAAqH;IAC7G,WAAW,CAAC,KAAa;QAC/B,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;IAC7E,CAAC;CACF","sourcesContent":["/**\n * The drawing order of a map's layers, kept beside the engine's: the layers waiting for the engine with 3D Tiles are\n * in the order but not in the engine yet, and the order recreates the layers in a new engine after a context loss.\n */\n\nimport type { Layer } from '../layers/layers.ts';\nimport type { Engine } from '../wasm/isard.js';\nimport { report } from './checks.ts';\n\n/** A map's layers in drawing order, bottom first, and those kept on top */\nexport class LayerStack {\n /** Layers in drawing order (bottom first), to recreate them after a context loss */\n readonly layers: Layer[] = [];\n /** Layers new layers go under */\n readonly onTop = new Set<Layer>();\n private readonly engine: () => Engine;\n\n /** `engine`: the map's engine of the moment */\n constructor(engine: () => Engine) {\n this.engine = engine;\n }\n\n has(layer: Layer): boolean {\n return this.layers.includes(layer);\n }\n\n /** Puts a new layer on top, under the layers kept on top (the basemap's labels) */\n add(layer: Layer): void {\n this.layers.push(layer);\n\n const top = this.layers.find((l) => this.onTop.has(l) && l !== layer);\n\n if (top) this.move(layer, top);\n }\n\n /** Forgets a removed layer */\n forget(layer: Layer): void {\n this.unlist(layer);\n this.onTop.delete(layer);\n }\n\n /** Moves a layer under `before`, or on top of all */\n move(layer: Layer, before: Layer | undefined): void {\n this.unlist(layer);\n\n const index = before ? this.layers.indexOf(before) : -1;\n const at = index < 0 ? this.layers.length : index;\n\n this.layers.splice(at, 0, layer);\n if (layer.id >= 0) this.engine().moveLayer(layer.id, this.engineIndex(at));\n }\n\n /** A layer made again in the engine under a new id: `old` removed, the new one moved to the layer's place */\n replace(layer: Layer, old: number): void {\n const engine = this.engine();\n\n engine.removeLayer(old);\n\n const index = this.layers.indexOf(layer);\n\n if (index >= 0) engine.moveLayer(layer.id, this.engineIndex(index));\n }\n\n /** Moves a layer under all the others */\n toBottom(layer: Layer): void {\n this.engine().moveLayer(layer.id, 0);\n this.unlist(layer);\n this.layers.unshift(layer);\n }\n\n /** Creates the layers in a new engine, in order, but those still `waiting` (for the engine with 3D Tiles); a layer\n * that fails is reported and left out */\n reattach(engine: Engine, waiting: (layer: Layer) => boolean): void {\n // No layer refers to an id of the old engine while the others are created\n this.layers.forEach((layer) => {\n layer.forgetEngine();\n });\n this.layers.forEach((layer) => {\n if (waiting(layer)) return;\n try {\n layer.attach(engine);\n } catch (error) {\n report(error);\n }\n });\n // Links between layers, once every layer has its new id (buildings colored by a network above them)\n this.layers.forEach((layer) => {\n if (layer.id < 0) return;\n try {\n layer.relink(engine);\n } catch (error) {\n report(error);\n }\n });\n }\n\n /** Frees what the layers hold beside the engine (custom layers' WebGL objects, models' data) */\n dispose(): void {\n this.layers.forEach((layer) => {\n layer.dispose();\n });\n }\n\n /** Takes a layer out of the drawing order (to put it back elsewhere, or for good) */\n private unlist(layer: Layer): void {\n const index = this.layers.indexOf(layer);\n\n if (index >= 0) this.layers.splice(index, 1);\n }\n\n /** Index in the engine of the layer at `index`: the layers waiting for the engine with 3D Tiles are not in it yet */\n private engineIndex(index: number): number {\n return this.layers.slice(0, index).filter((layer) => layer.id >= 0).length;\n }\n}\n"]}
1
+ {"version":3,"file":"layer-stack.js","sourceRoot":"","sources":["../../src/map/layer-stack.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The drawing order of a map's layers, kept beside the engine's: the layers waiting for the engine with 3D Tiles are\n * in the order but not in the engine yet, and the order recreates the layers in a new engine after a context loss.\n */\n\nimport type { Layer } from '../layers/layers.ts';\nimport type { Engine } from '../wasm/isard_webgpu.js';\nimport { report } from './checks.ts';\n\n/** A map's layers in drawing order, bottom first, and those kept on top */\nexport class LayerStack {\n /** Layers in drawing order (bottom first), to recreate them after a context loss */\n readonly layers: Layer[] = [];\n /** Layers new layers go under */\n readonly onTop = new Set<Layer>();\n private readonly engine: () => Engine;\n\n /** `engine`: the map's engine of the moment */\n constructor(engine: () => Engine) {\n this.engine = engine;\n }\n\n has(layer: Layer): boolean {\n return this.layers.includes(layer);\n }\n\n /** Puts a new layer on top, under the layers kept on top (the basemap's labels) */\n add(layer: Layer): void {\n this.layers.push(layer);\n\n const top = this.layers.find((l) => this.onTop.has(l) && l !== layer);\n\n if (top) this.move(layer, top);\n }\n\n /** Forgets a removed layer */\n forget(layer: Layer): void {\n this.unlist(layer);\n this.onTop.delete(layer);\n }\n\n /** Moves a layer under `before`, or on top of all */\n move(layer: Layer, before: Layer | undefined): void {\n this.unlist(layer);\n\n const index = before ? this.layers.indexOf(before) : -1;\n const at = index < 0 ? this.layers.length : index;\n\n this.layers.splice(at, 0, layer);\n if (layer.id >= 0) this.engine().moveLayer(layer.id, this.engineIndex(at));\n }\n\n /** A layer made again in the engine under a new id: `old` removed, the new one moved to the layer's place */\n replace(layer: Layer, old: number): void {\n const engine = this.engine();\n\n engine.removeLayer(old);\n\n const index = this.layers.indexOf(layer);\n\n if (index >= 0) engine.moveLayer(layer.id, this.engineIndex(index));\n }\n\n /** Moves a layer under all the others */\n toBottom(layer: Layer): void {\n this.engine().moveLayer(layer.id, 0);\n this.unlist(layer);\n this.layers.unshift(layer);\n }\n\n /** Creates the layers in a new engine, in order, but those still `waiting` (for the engine with 3D Tiles); a layer\n * that fails is reported and left out */\n reattach(engine: Engine): void {\n // No layer refers to an id of the old engine while the others are created\n this.layers.forEach((layer) => {\n layer.forgetEngine();\n });\n this.layers.forEach((layer) => {\n try {\n layer.attach(engine);\n } catch (error) {\n report(error);\n }\n });\n // Links between layers, once every layer has its new id (buildings colored by a network above them)\n this.layers.forEach((layer) => {\n if (layer.id < 0) return;\n try {\n layer.relink(engine);\n } catch (error) {\n report(error);\n }\n });\n }\n\n /** Frees what the layers hold beside the engine (custom layers' WebGL objects, models' data) */\n dispose(): void {\n this.layers.forEach((layer) => {\n layer.dispose();\n });\n }\n\n /** Takes a layer out of the drawing order (to put it back elsewhere, or for good) */\n private unlist(layer: Layer): void {\n const index = this.layers.indexOf(layer);\n\n if (index >= 0) this.layers.splice(index, 1);\n }\n\n /** Index in the engine of the layer at `index`: the layers waiting for the engine with 3D Tiles are not in it yet */\n private engineIndex(index: number): number {\n return this.layers.slice(0, index).filter((layer) => layer.id >= 0).length;\n }\n}\n"]}
@@ -1,15 +1,16 @@
1
1
  /** The atlases of a map's symbol layers, the glyphs and the icons: created on first use, moved to each new engine. */
2
2
  import { Glyphs } from '../layers/glyphs.ts';
3
3
  import { Icons, type ImageOptions, type Pixels } from '../layers/icons.ts';
4
- import type { Engine } from '../wasm/isard.js';
4
+ import type { Engine } from '../wasm/isard_webgpu.js';
5
5
  /** The glyphs and icons of a map */
6
6
  export declare class SymbolAtlases {
7
7
  #private;
8
- private readonly canvas;
8
+ private readonly maxSize;
9
9
  private readonly glyphsUrl;
10
10
  private readonly engine;
11
- /** `canvas`: the engine's; `glyphsUrl`: the map's option; `engine`: the map's engine of the moment */
12
- constructor(canvas: HTMLCanvasElement, glyphsUrl: string | undefined, engine: () => Engine);
11
+ /** `maxSize`: the largest texture the engine takes (undefined if unknown); `glyphsUrl`: the map's option; `engine`:
12
+ * the map's engine of the moment */
13
+ constructor(maxSize: () => number | undefined, glyphsUrl: string | undefined, engine: () => Engine);
13
14
  /** The glyphs of the symbol layers, loaded on first use */
14
15
  get glyphs(): Glyphs;
15
16
  /** The icons of the symbol layers: the application's images and the vector basemaps' sprites */
@@ -1,30 +1,25 @@
1
1
  /** The atlases of a map's symbol layers, the glyphs and the icons: created on first use, moved to each new engine. */
2
2
  import { Glyphs } from "../layers/glyphs.js";
3
3
  import { Icons, readPixels } from "../layers/icons.js";
4
- /** The largest texture the canvas's WebGL context takes, undefined if unknown: the atlases stay within it */
5
- const maxTextureSize = (canvas) => {
6
- const gl = canvas.getContext('webgl2');
7
- const max = gl?.getParameter(gl.MAX_TEXTURE_SIZE);
8
- return typeof max === 'number' ? max : undefined;
9
- };
10
4
  /** The glyphs and icons of a map */
11
5
  export class SymbolAtlases {
12
- canvas;
6
+ maxSize;
13
7
  glyphsUrl;
14
8
  engine;
15
9
  #glyphs;
16
10
  #icons;
17
- /** `canvas`: the engine's; `glyphsUrl`: the map's option; `engine`: the map's engine of the moment */
18
- constructor(canvas, glyphsUrl, engine) {
19
- this.canvas = canvas;
11
+ /** `maxSize`: the largest texture the engine takes (undefined if unknown); `glyphsUrl`: the map's option; `engine`:
12
+ * the map's engine of the moment */
13
+ constructor(maxSize, glyphsUrl, engine) {
14
+ this.maxSize = maxSize;
20
15
  this.glyphsUrl = glyphsUrl;
21
16
  this.engine = engine;
22
17
  }
23
18
  /** The glyphs of the symbol layers, loaded on first use */
24
19
  get glyphs() {
25
20
  if (!this.#glyphs) {
26
- // The engine's context: the atlas stays within its texture size limit
27
- this.#glyphs = new Glyphs(this.glyphsUrl, maxTextureSize(this.canvas));
21
+ // The engine's device: the atlas stays within its texture size limit
22
+ this.#glyphs = new Glyphs(this.glyphsUrl, this.maxSize());
28
23
  this.#glyphs.attach(this.engine());
29
24
  }
30
25
  return this.#glyphs;
@@ -32,7 +27,7 @@ export class SymbolAtlases {
32
27
  /** The icons of the symbol layers: the application's images and the vector basemaps' sprites */
33
28
  get icons() {
34
29
  if (!this.#icons) {
35
- this.#icons = new Icons(maxTextureSize(this.canvas));
30
+ this.#icons = new Icons(this.maxSize());
36
31
  this.#icons.attach(this.engine());
37
32
  }
38
33
  return this.#icons;
@@ -1 +1 @@
1
- {"version":3,"file":"symbol-atlases.js","sourceRoot":"","sources":["../../src/map/symbol-atlases.ts"],"names":[],"mappings":"AAAA,sHAAsH;AAEtH,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAkC,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGvF,6GAA6G;AAC7G,MAAM,cAAc,GAAG,CAAC,MAAyB,EAAsB,EAAE;IACvE,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,GAAG,GAAG,EAAE,EAAE,YAAY,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC;IAElD,OAAO,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;AACnD,CAAC,CAAC;AAEF,oCAAoC;AACpC,MAAM,OAAO,aAAa;IACP,MAAM,CAAoB;IAC1B,SAAS,CAAqB;IAC9B,MAAM,CAAe;IACtC,OAAO,CAAqB;IAC5B,MAAM,CAAoB;IAE1B,sGAAsG;IACtG,YAAY,MAAyB,EAAE,SAA6B,EAAE,MAAoB;QACxF,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,2DAA2D;IAC3D,IAAI,MAAM;QACR,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,sEAAsE;YACtE,IAAI,CAAC,OAAO,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;YACvE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACrC,CAAC;QAED,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,gGAAgG;IAChG,IAAI,KAAK;QACP,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,IAAI,CAAC,MAAM,GAAG,IAAI,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;YACrD,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACpC,CAAC;QAED,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,0FAA0F;IAC1F,QAAQ,CACN,IAAY,EACZ,KAAuE,EACvE,OAAqB;QAErB,MAAM,MAAM,GAAG,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAE3D,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,IAAI,gBAAgB,CAAC,CAAC;QACvE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC;IAED,QAAQ,CAAC,IAAY;QACnB,OAAO,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC;IACzC,CAAC;IAED,WAAW,CAAC,IAAY;QACtB,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAED,mHAAmH;IACnH,MAAM,CAAC,MAAc;QACnB,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAC7B,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;CACF","sourcesContent":["/** The atlases of a map's symbol layers, the glyphs and the icons: created on first use, moved to each new engine. */\n\nimport { Glyphs } from '../layers/glyphs.ts';\nimport { Icons, type ImageOptions, type Pixels, readPixels } from '../layers/icons.ts';\nimport type { Engine } from '../wasm/isard.js';\n\n/** The largest texture the canvas's WebGL context takes, undefined if unknown: the atlases stay within it */\nconst maxTextureSize = (canvas: HTMLCanvasElement): number | undefined => {\n const gl = canvas.getContext('webgl2');\n const max = gl?.getParameter(gl.MAX_TEXTURE_SIZE);\n\n return typeof max === 'number' ? max : undefined;\n};\n\n/** The glyphs and icons of a map */\nexport class SymbolAtlases {\n private readonly canvas: HTMLCanvasElement;\n private readonly glyphsUrl: string | undefined;\n private readonly engine: () => Engine;\n #glyphs: Glyphs | undefined;\n #icons: Icons | undefined;\n\n /** `canvas`: the engine's; `glyphsUrl`: the map's option; `engine`: the map's engine of the moment */\n constructor(canvas: HTMLCanvasElement, glyphsUrl: string | undefined, engine: () => Engine) {\n this.canvas = canvas;\n this.glyphsUrl = glyphsUrl;\n this.engine = engine;\n }\n\n /** The glyphs of the symbol layers, loaded on first use */\n get glyphs(): Glyphs {\n if (!this.#glyphs) {\n // The engine's context: the atlas stays within its texture size limit\n this.#glyphs = new Glyphs(this.glyphsUrl, maxTextureSize(this.canvas));\n this.#glyphs.attach(this.engine());\n }\n\n return this.#glyphs;\n }\n\n /** The icons of the symbol layers: the application's images and the vector basemaps' sprites */\n get icons(): Icons {\n if (!this.#icons) {\n this.#icons = new Icons(maxTextureSize(this.canvas));\n this.#icons.attach(this.engine());\n }\n\n return this.#icons;\n }\n\n /** An image for the icons, from its pixels or from an image; one without pixels throws */\n addImage(\n name: string,\n image: Pixels | (CanvasImageSource & { width: number; height: number }),\n options: ImageOptions,\n ): void {\n const pixels = 'data' in image ? image : readPixels(image);\n\n if (!pixels) throw new Error(`isard: the image ${name} has no pixels`);\n this.icons.add(name, pixels, options);\n }\n\n hasImage(name: string): boolean {\n return this.#icons?.has(name) ?? false;\n }\n\n removeImage(name: string): void {\n this.#icons?.remove(name);\n }\n\n /** Uploads the atlases made so far to a new engine (after a context loss, or the one left once the map is gone) */\n attach(engine: Engine): void {\n this.#glyphs?.attach(engine);\n this.#icons?.attach(engine);\n }\n}\n"]}
1
+ {"version":3,"file":"symbol-atlases.js","sourceRoot":"","sources":["../../src/map/symbol-atlases.ts"],"names":[],"mappings":"AAAA,sHAAsH;AAEtH,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAkC,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGvF,oCAAoC;AACpC,MAAM,OAAO,aAAa;IACP,OAAO,CAA2B;IAClC,SAAS,CAAqB;IAC9B,MAAM,CAAe;IACtC,OAAO,CAAqB;IAC5B,MAAM,CAAoB;IAE1B;wCACoC;IACpC,YAAY,OAAiC,EAAE,SAA6B,EAAE,MAAoB;QAChG,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,2DAA2D;IAC3D,IAAI,MAAM;QACR,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,qEAAqE;YACrE,IAAI,CAAC,OAAO,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;YAC1D,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACrC,CAAC;QAED,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,gGAAgG;IAChG,IAAI,KAAK;QACP,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,IAAI,CAAC,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;YACxC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACpC,CAAC;QAED,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,0FAA0F;IAC1F,QAAQ,CACN,IAAY,EACZ,KAAuE,EACvE,OAAqB;QAErB,MAAM,MAAM,GAAG,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAE3D,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,IAAI,gBAAgB,CAAC,CAAC;QACvE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC;IAED,QAAQ,CAAC,IAAY;QACnB,OAAO,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC;IACzC,CAAC;IAED,WAAW,CAAC,IAAY;QACtB,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAED,mHAAmH;IACnH,MAAM,CAAC,MAAc;QACnB,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAC7B,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;CACF","sourcesContent":["/** The atlases of a map's symbol layers, the glyphs and the icons: created on first use, moved to each new engine. */\n\nimport { Glyphs } from '../layers/glyphs.ts';\nimport { Icons, type ImageOptions, type Pixels, readPixels } from '../layers/icons.ts';\nimport type { Engine } from '../wasm/isard_webgpu.js';\n\n/** The glyphs and icons of a map */\nexport class SymbolAtlases {\n private readonly maxSize: () => number | undefined;\n private readonly glyphsUrl: string | undefined;\n private readonly engine: () => Engine;\n #glyphs: Glyphs | undefined;\n #icons: Icons | undefined;\n\n /** `maxSize`: the largest texture the engine takes (undefined if unknown); `glyphsUrl`: the map's option; `engine`:\n * the map's engine of the moment */\n constructor(maxSize: () => number | undefined, glyphsUrl: string | undefined, engine: () => Engine) {\n this.maxSize = maxSize;\n this.glyphsUrl = glyphsUrl;\n this.engine = engine;\n }\n\n /** The glyphs of the symbol layers, loaded on first use */\n get glyphs(): Glyphs {\n if (!this.#glyphs) {\n // The engine's device: the atlas stays within its texture size limit\n this.#glyphs = new Glyphs(this.glyphsUrl, this.maxSize());\n this.#glyphs.attach(this.engine());\n }\n\n return this.#glyphs;\n }\n\n /** The icons of the symbol layers: the application's images and the vector basemaps' sprites */\n get icons(): Icons {\n if (!this.#icons) {\n this.#icons = new Icons(this.maxSize());\n this.#icons.attach(this.engine());\n }\n\n return this.#icons;\n }\n\n /** An image for the icons, from its pixels or from an image; one without pixels throws */\n addImage(\n name: string,\n image: Pixels | (CanvasImageSource & { width: number; height: number }),\n options: ImageOptions,\n ): void {\n const pixels = 'data' in image ? image : readPixels(image);\n\n if (!pixels) throw new Error(`isard: the image ${name} has no pixels`);\n this.icons.add(name, pixels, options);\n }\n\n hasImage(name: string): boolean {\n return this.#icons?.has(name) ?? false;\n }\n\n removeImage(name: string): void {\n this.#icons?.remove(name);\n }\n\n /** Uploads the atlases made so far to a new engine (after a context loss, or the one left once the map is gone) */\n attach(engine: Engine): void {\n this.#glyphs?.attach(engine);\n this.#icons?.attach(engine);\n }\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  /** The viewshed's observers given to the engine, in the arrays it reads. */
2
2
  import type { ViewshedOptions } from '../types.ts';
3
- import type { Engine } from '../wasm/isard.js';
3
+ import type { Engine } from '../wasm/isard_webgpu.js';
4
4
  /** Sets the viewshed of the engine, or clears it without observers; true if one is set (a frame to draw) */
5
5
  export declare const applyViewshed: (engine: Engine, options: ViewshedOptions | readonly ViewshedOptions[] | undefined) => boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"viewshed.js","sourceRoot":"","sources":["../../src/map/viewshed.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAE5E,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAIrC,gEAAgE;AAChE,MAAM,WAAW,GAAG,CAAC,OAAiE,EAA8B,EAAE;IACpH,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IAExB,OAAO,UAAU,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;AACrD,CAAC,CAAC;AAEF,4GAA4G;AAC5G,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,MAAc,EACd,OAAiE,EACxD,EAAE;IACX,MAAM,SAAS,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACvC,MAAM,CAAC,KAAK,CAAC,GAAG,SAAS,CAAC;IAE1B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,CAAC,aAAa,EAAE,CAAC;QAEvB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,CAAC,WAAW,CAChB,IAAI,YAAY,CACd,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QACvB,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QACb,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QACb,CAAC,CAAC,MAAM,IAAI,GAAG;QACf,CAAC,CAAC,KAAK,IAAI,IAAI;QACf,GAAG,CAAC,CAAC,CAAC,SAAS,KAAK,SAAS;YAC3B,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YACvB,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;KAClE,CAAC,CACH,EACD,IAAI,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,IAAI,SAAS,CAAC,CAAC,EACtD,IAAI,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,IAAI,SAAS,CAAC,CAAC,EACrD,KAAK,CAAC,OAAO,IAAI,GAAG,EACpB,IAAI,YAAY,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAC9D,CAAC;IAEF,OAAO,IAAI,CAAC;AACd,CAAC,CAAC","sourcesContent":["/** The viewshed's observers given to the engine, in the arrays it reads. */\n\nimport { rgb } from '../settings.ts';\nimport type { ViewshedOptions } from '../types.ts';\nimport type { Engine } from '../wasm/isard.js';\n\n/** The observers of a viewshed option: none, one, or several */\nconst observersOf = (options: ViewshedOptions | readonly ViewshedOptions[] | undefined): readonly ViewshedOptions[] => {\n if (!options) return [];\n\n return 'position' in options ? [options] : options;\n};\n\n/** Sets the viewshed of the engine, or clears it without observers; true if one is set (a frame to draw) */\nexport const applyViewshed = (\n engine: Engine,\n options: ViewshedOptions | readonly ViewshedOptions[] | undefined,\n): boolean => {\n const observers = observersOf(options);\n const [first] = observers;\n\n if (!first) {\n engine.clearViewshed();\n\n return false;\n }\n engine.setViewshed(\n new Float64Array(\n observers.flatMap((o) => [\n o.position[0],\n o.position[1],\n o.height ?? 1.7,\n o.range ?? 1000,\n ...(o.direction === undefined\n ? [Number.NaN, 0, 0, 0]\n : [o.direction, o.tilt ?? 0, o.fov ?? 60, o.verticalFov ?? 40]),\n ]),\n ),\n new Float32Array(rgb(first.visibleColor ?? '#2f9e44')),\n new Float32Array(rgb(first.hiddenColor ?? '#e03131')),\n first.opacity ?? 0.7,\n new Float32Array(first.coneColor ? rgb(first.coneColor) : []),\n );\n\n return true;\n};\n"]}
1
+ {"version":3,"file":"viewshed.js","sourceRoot":"","sources":["../../src/map/viewshed.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAE5E,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAIrC,gEAAgE;AAChE,MAAM,WAAW,GAAG,CAAC,OAAiE,EAA8B,EAAE;IACpH,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IAExB,OAAO,UAAU,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;AACrD,CAAC,CAAC;AAEF,4GAA4G;AAC5G,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,MAAc,EACd,OAAiE,EACxD,EAAE;IACX,MAAM,SAAS,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACvC,MAAM,CAAC,KAAK,CAAC,GAAG,SAAS,CAAC;IAE1B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,CAAC,aAAa,EAAE,CAAC;QAEvB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,CAAC,WAAW,CAChB,IAAI,YAAY,CACd,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QACvB,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QACb,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QACb,CAAC,CAAC,MAAM,IAAI,GAAG;QACf,CAAC,CAAC,KAAK,IAAI,IAAI;QACf,GAAG,CAAC,CAAC,CAAC,SAAS,KAAK,SAAS;YAC3B,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YACvB,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;KAClE,CAAC,CACH,EACD,IAAI,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,IAAI,SAAS,CAAC,CAAC,EACtD,IAAI,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,IAAI,SAAS,CAAC,CAAC,EACrD,KAAK,CAAC,OAAO,IAAI,GAAG,EACpB,IAAI,YAAY,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAC9D,CAAC;IAEF,OAAO,IAAI,CAAC;AACd,CAAC,CAAC","sourcesContent":["/** The viewshed's observers given to the engine, in the arrays it reads. */\n\nimport { rgb } from '../settings.ts';\nimport type { ViewshedOptions } from '../types.ts';\nimport type { Engine } from '../wasm/isard_webgpu.js';\n\n/** The observers of a viewshed option: none, one, or several */\nconst observersOf = (options: ViewshedOptions | readonly ViewshedOptions[] | undefined): readonly ViewshedOptions[] => {\n if (!options) return [];\n\n return 'position' in options ? [options] : options;\n};\n\n/** Sets the viewshed of the engine, or clears it without observers; true if one is set (a frame to draw) */\nexport const applyViewshed = (\n engine: Engine,\n options: ViewshedOptions | readonly ViewshedOptions[] | undefined,\n): boolean => {\n const observers = observersOf(options);\n const [first] = observers;\n\n if (!first) {\n engine.clearViewshed();\n\n return false;\n }\n engine.setViewshed(\n new Float64Array(\n observers.flatMap((o) => [\n o.position[0],\n o.position[1],\n o.height ?? 1.7,\n o.range ?? 1000,\n ...(o.direction === undefined\n ? [Number.NaN, 0, 0, 0]\n : [o.direction, o.tilt ?? 0, o.fov ?? 60, o.verticalFov ?? 40]),\n ]),\n ),\n new Float32Array(rgb(first.visibleColor ?? '#2f9e44')),\n new Float32Array(rgb(first.hiddenColor ?? '#e03131')),\n first.opacity ?? 0.7,\n new Float32Array(first.coneColor ? rgb(first.coneColor) : []),\n );\n\n return true;\n};\n"]}
package/dist/map.d.ts CHANGED
@@ -26,14 +26,15 @@ import { Tiles3dLayer } from './layers/tiles3d.ts';
26
26
  import { type TreeOptions } from './layers/trees.ts';
27
27
  import { type HoverPicking } from './map/hover-pick.ts';
28
28
  import { type LayerSpec } from './map/layer-spec.ts';
29
- import type { AnimationOptions, AtmosphereOptions, Basemap, FeatureHit, FirstPersonView, FlyToOptions, GeoMapOptions, LoadingMode, LonLat, MapEvents, NetworkOptions, PickOptions, Point, Projection, Quality, RasterOptions, SunOptions, SwipeOptions, TerrainModel, TerrainOptions, Tiles3dOptions, ViewshedOptions } from './types.ts';
29
+ import type { AnimationOptions, AtmosphereOptions, Basemap, FeatureHit, FirstPersonView, FlyToOptions, GeoMapOptions, LoadingMode, LonLat, MapEvents, MapGpuTimings, NetworkOptions, PickOptions, Point, Projection, Quality, RasterOptions, SunOptions, SwipeOptions, TerrainModel, TerrainOptions, Tiles3dOptions, ViewshedOptions } from './types.ts';
30
30
  import { type Control, type ControlPosition } from './ui/controls.ts';
31
- import type { Camera, PickHit, RasterLayerStats } from './wasm/isard.js';
31
+ import type { Camera, PickHit, RasterLayerStats } from './wasm/isard_webgpu.js';
32
32
  export type { LayerSpec } from './map/layer-spec.ts';
33
- /** A map (see `GeoMap.create`); layers take it as their host */
34
33
  export declare class GeoMap {
35
34
  #private;
36
35
  readonly canvas: HTMLCanvasElement;
36
+ /** The frames' parts timed on the GPU (`setGpuTiming`), again on a new engine */
37
+ private gpuTiming;
37
38
  /** The engine class (core, or with 3D Tiles) and the engine with 3D Tiles loaded when needed */
38
39
  private readonly engines;
39
40
  /** The layers in drawing order and those kept on top */
@@ -84,13 +85,6 @@ export declare class GeoMap {
84
85
  private get layers();
85
86
  /** Layers new layers go under */
86
87
  private get onTop();
87
- private createEngine;
88
- /** A 3D Tiles layer or a model on the core engine: loads the engine with 3D Tiles, then rebuilds the map on it
89
- * (camera, settings and layers kept, as after a context loss); the layer is created then */
90
- private upgrade;
91
- /** Downloads and compiles the engine with 3D Tiles once the map is idle (`tiles3d: 'preload'`), without running
92
- * it: the first 3D Tiles layer then only instantiates it */
93
- private preloadTiles3d;
94
88
  /**
95
89
  * The context is lost: its engine freed at once, the map's calls going to one that does nothing until `restore`
96
90
  * builds the next. The old engine's GPU objects went with the context: deleted now, it is silent (on the context
@@ -98,8 +92,12 @@ export declare class GeoMap {
98
92
  * would fail on the lost context, whose limits read 0
99
93
  */
100
94
  private dropLostEngine;
101
- /** After a context loss: a new engine with the same camera, settings and layers (same handles, same order) */
95
+ /** After a context loss: a new engine with the same camera, settings and layers (same handles, same order); the
96
+ * engine made asynchronously, adopted once there */
102
97
  private restore;
98
+ /** A new engine in place of the map's (a placeholder, or a lost one): the same camera, settings and layers (same
99
+ * handles, same order) */
100
+ private adopt;
103
101
  /** The street-level eye, if the camera is one */
104
102
  get firstPerson(): Readonly<Required<FirstPersonView>> | undefined;
105
103
  /**
@@ -182,18 +180,25 @@ export declare class GeoMap {
182
180
  setBackground(color: string): void;
183
181
  /** Tile counters of the raster layers, for diagnostics */
184
182
  stats(): RasterLayerStats[];
183
+ /** Times the parts of each frame on the GPU, for profiling (`gpuTimings`): timer queries, read a few frames later.
184
+ * An engine built to profile only (`PROFILE=1 bun run build`); false without one, or if the browser cannot
185
+ * (`EXT_disjoint_timer_query_webgl2`) */
186
+ setGpuTiming(on: boolean): boolean;
187
+ /** The GPU time of the last frame measured (`setGpuTiming`), in all and by part: the backdrop, the ground (the raster
188
+ * layers over the relief), each layer, the shadows, the panorama, the viewshed (ms) */
189
+ gpuTimings(): MapGpuTimings | undefined;
185
190
  /**
186
- * The feature under a screen point (CSS pixels), undefined if none: its layer id and index. Reads one pixel of an
187
- * offscreen picking pass, whatever the number of features, but waits for the GPU to finish the frame (a stall): for
188
- * clicks and one-off queries. On hover, listen to 'hoverfeature' instead, which picks without waiting.
191
+ * The feature under a screen point (CSS pixels), undefined if none: its layer id and index. Reads the pixels around
192
+ * the point of an offscreen picking pass, whatever the number of features, once the GPU is done (a frame or two
193
+ * later: the GPU is not waited for). On hover, listen to 'hoverfeature' instead.
189
194
  */
190
- pick(point: Point, { radius, layers }?: PickOptions): PickHit | undefined;
195
+ pick(point: Point, { radius, layers }?: PickOptions): Promise<PickHit | undefined>;
191
196
  /**
192
197
  * The feature under a screen point (CSS pixels), or the nearest one within `radius` pixels: its layer handle, its
193
198
  * index there and, for line, circle and fill layers, the feature itself; undefined if none. `layers` restricts the
194
199
  * search to some layers (the others hide nothing).
195
200
  */
196
- pickFeature(point: Point, options?: PickOptions): FeatureHit | undefined;
201
+ pickFeature(point: Point, options?: PickOptions): Promise<FeatureHit | undefined>;
197
202
  /** A hit with its layer handle and feature; undefined if the layer is gone */
198
203
  private featureHit;
199
204
  /** Screen point (CSS pixels) of a position on the ground (the relief), or `height` metres above it, undefined
@@ -220,15 +225,16 @@ export declare class GeoMap {
220
225
  * where it starts, a roof or a mesh as the relief (on by default), or around the screen center */
221
226
  setRotateAroundPointer(enabled: boolean): void;
222
227
  /** What is drawn under a screen point (CSS pixels), on the relief or standing on it (a roof, a wall, a mesh): its
223
- * position and its height above the relief, in metres; undefined where nothing was drawn. The last frame's scene is
224
- * drawn again and read back, waiting for the GPU (a stall): for clicks and drags */
228
+ * position and its height above the relief, in metres; undefined where nothing was drawn. Read from the last copy of
229
+ * the scene's depth (a frame or two old, a pixel every 4 CSS pixels): at once, without waiting for the GPU */
225
230
  pickSurface(point: Point): {
226
231
  lonLat: LonLat;
227
232
  height: number;
228
233
  } | undefined;
229
234
  /** The height above the relief, in metres, of the top of what stands at a position: a roof, a mesh, 0 on the bare
230
- * ground; undefined where nothing of the last frame is there. The scene is drawn from above into a single pixel and
231
- * read back: cheap, but it waits for the GPU */
235
+ * ground; undefined where nothing of the last frame is there, or until measured: the scene is drawn looking down at
236
+ * it after a frame and read back a frame or two later, the answer kept and measured again every 250 ms at most (ask
237
+ * again on the next `render` event) */
232
238
  surfaceAt(lonLat: LonLat): number | undefined;
233
239
  /** Adds a control in a corner of the map; controls stack from the corner inward */
234
240
  addControl(control: Control, position?: ControlPosition): this;