astro-viewer 3.0.0 → 3.1.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 (110) hide show
  1. package/dist/astroviewer.cjs +2505 -1335
  2. package/dist/astroviewer.js +1 -1
  3. package/dist/astroviewer.min.js +1 -1
  4. package/lib-esm/AstroSphere.d.ts +26 -6
  5. package/lib-esm/AstroSphere.js +215 -18
  6. package/lib-esm/AstroViewer.d.ts +18 -5
  7. package/lib-esm/AstroViewer.js +47 -0
  8. package/lib-esm/Camera.js +24 -8
  9. package/lib-esm/Config.js +12 -0
  10. package/lib-esm/Global.js +12 -0
  11. package/lib-esm/index.d.ts +6 -4
  12. package/lib-esm/index.js +16 -3
  13. package/lib-esm/model/AbstractSkyEntity.js +12 -0
  14. package/lib-esm/model/AstroGL.js +12 -0
  15. package/lib-esm/model/ColorMaps.js +12 -0
  16. package/lib-esm/model/MetadataColumn.js +12 -0
  17. package/lib-esm/model/MetadataManager.js +12 -0
  18. package/lib-esm/model/Point.js +12 -0
  19. package/lib-esm/model/Point2D.js +12 -0
  20. package/lib-esm/model/Source.js +12 -0
  21. package/lib-esm/model/SphereFoV.d.ts +30 -0
  22. package/lib-esm/model/SphereFoV.js +195 -0
  23. package/lib-esm/model/catalogues/CatalogueGL.js +12 -0
  24. package/lib-esm/model/catalogues/CatalogueProps.js +13 -1
  25. package/lib-esm/model/earth/{wmts/WMTSAdapter.d.ts → WMTSAdapter.d.ts} +2 -1
  26. package/lib-esm/model/earth/{wmts/WMTSAdapter.js → WMTSAdapter.js} +12 -0
  27. package/lib-esm/model/earth/XYZAnchestorTile.d.ts +17 -0
  28. package/lib-esm/model/earth/XYZAnchestorTile.js +87 -0
  29. package/lib-esm/model/earth/{types.d.ts → XYZConfig.d.ts} +2 -17
  30. package/lib-esm/model/earth/XYZConfig.js +13 -0
  31. package/lib-esm/model/earth/XYZFoVHelper.d.ts +9 -0
  32. package/lib-esm/model/earth/XYZFoVHelper.js +101 -0
  33. package/lib-esm/model/earth/XYZMap.d.ts +31 -0
  34. package/lib-esm/model/earth/XYZMap.js +208 -0
  35. package/lib-esm/model/earth/XYZMapDescriptor.d.ts +29 -0
  36. package/lib-esm/model/earth/XYZMapDescriptor.js +77 -0
  37. package/lib-esm/model/earth/XYZMeshBuilder.d.ts +1 -1
  38. package/lib-esm/model/earth/XYZMeshBuilder.js +13 -2
  39. package/lib-esm/model/earth/XYZTile.d.ts +20 -21
  40. package/lib-esm/model/earth/XYZTile.js +82 -102
  41. package/lib-esm/model/earth/XYZTileBuffer.d.ts +24 -26
  42. package/lib-esm/model/earth/XYZTileBuffer.js +60 -70
  43. package/lib-esm/model/earth/XYZTileRequestScheduler.d.ts +1 -1
  44. package/lib-esm/model/earth/XYZTileRequestScheduler.js +13 -2
  45. package/lib-esm/model/earth/XYZTypes.d.ts +24 -0
  46. package/lib-esm/model/earth/XYZTypes.js +13 -0
  47. package/lib-esm/model/earth/XYZVisibleTilesManager.d.ts +16 -27
  48. package/lib-esm/model/earth/XYZVisibleTilesManager.js +61 -192
  49. package/lib-esm/model/footprints/Footprint.js +12 -0
  50. package/lib-esm/model/footprints/FootprintProps.js +13 -1
  51. package/lib-esm/model/footprints/FootprintSetGL.js +12 -0
  52. package/lib-esm/model/grid/EquatorialGrid.js +20 -6
  53. package/lib-esm/model/grid/GridTextHelper.d.ts +10 -19
  54. package/lib-esm/model/grid/GridTextHelper.js +70 -67
  55. package/lib-esm/model/grid/HealpixGrid.d.ts +4 -4
  56. package/lib-esm/model/grid/HealpixGrid.js +19 -6
  57. package/lib-esm/model/grid/LonLatGrid.d.ts +40 -0
  58. package/lib-esm/model/grid/LonLatGrid.js +258 -0
  59. package/lib-esm/model/hips/AllSky.js +12 -0
  60. package/lib-esm/model/hips/AncestorTile.js +12 -0
  61. package/lib-esm/model/hips/FoVHelper.js +12 -0
  62. package/lib-esm/model/hips/HiPS.js +12 -9
  63. package/lib-esm/model/hips/HiPSDescriptor.js +12 -0
  64. package/lib-esm/model/hips/Tile.js +12 -0
  65. package/lib-esm/model/hips/TileBuffer.js +12 -0
  66. package/lib-esm/model/hips/VisibleTilesManager.js +12 -0
  67. package/lib-esm/model/tap/TapMetadata.js +12 -0
  68. package/lib-esm/model/tap/TapMetadataList.js +12 -0
  69. package/lib-esm/model/tap/TapRepo.js +12 -0
  70. package/lib-esm/model/terra/TerraFootprintSetGL.js +12 -0
  71. package/lib-esm/model/terra/TerraPointSetGL.js +12 -0
  72. package/lib-esm/services/SesameService.js +11 -3
  73. package/lib-esm/services/helpers.js +12 -0
  74. package/lib-esm/services/hipsNodeService.js +12 -0
  75. package/lib-esm/services/parse-hipslist.js +12 -0
  76. package/lib-esm/services/queryCatalogueByFoV.js +13 -1
  77. package/lib-esm/services/queryFootprintSetByFov.js +13 -1
  78. package/lib-esm/services/tapRepoService.js +13 -1
  79. package/lib-esm/services/types.js +12 -0
  80. package/lib-esm/shader/CatalogueShaderProgram.js +12 -0
  81. package/lib-esm/shader/FootprintShaderProgram.js +12 -0
  82. package/lib-esm/shader/GridShaderManager.js +12 -0
  83. package/lib-esm/shader/HiPSShaderProgram.js +12 -0
  84. package/lib-esm/shader/ShaderManager.js +12 -1
  85. package/lib-esm/shader/ShaderManagerMutliHiPS.js +12 -1
  86. package/lib-esm/shader/XYZShaderProgram.d.ts +14 -1
  87. package/lib-esm/shader/XYZShaderProgram.js +127 -2
  88. package/lib-esm/utils/CoordsType.js +12 -0
  89. package/lib-esm/utils/FoVUtils.js +12 -0
  90. package/lib-esm/utils/GeomUtils.js +12 -0
  91. package/lib-esm/utils/MouseHelper.js +12 -0
  92. package/lib-esm/utils/PerspectiveMatrixManager.js +12 -0
  93. package/lib-esm/utils/RayPickingUtils.js +12 -0
  94. package/lib-esm/utils/STCSParser.js +12 -0
  95. package/lib-esm/utils/ShaderUtility.js +13 -1
  96. package/lib-esm/utils/Utils.js +12 -0
  97. package/lib-esm/utils/XYZRayPickingUtils.d.ts +27 -0
  98. package/lib-esm/utils/XYZRayPickingUtils.js +226 -0
  99. package/package.json +1 -1
  100. package/lib-esm/model/FoV.d.ts +0 -62
  101. package/lib-esm/model/FoV.js +0 -274
  102. package/lib-esm/model/earth/XYZAncestorMeshCache.d.ts +0 -10
  103. package/lib-esm/model/earth/XYZAncestorMeshCache.js +0 -31
  104. package/lib-esm/model/earth/XYZLayer.d.ts +0 -31
  105. package/lib-esm/model/earth/XYZLayer.js +0 -231
  106. package/lib-esm/model/earth/XYZTileProvider.d.ts +0 -29
  107. package/lib-esm/model/earth/XYZTileProvider.js +0 -187
  108. package/lib-esm/model/earth/types.js +0 -1
  109. package/lib-esm/model/earth/wmts/types.d.ts +0 -1
  110. package/lib-esm/model/earth/wmts/types.js +0 -1
@@ -1,52 +1,53 @@
1
- import { xyzTileRequestScheduler, XYZTileRequestError } from './XYZTileRequestScheduler.js';
1
+ /*
2
+ * AstroViewer
3
+ * Copyright (C) Fabrizio Giordano
4
+ * SPDX-License-Identifier: LicenseRef-AstroViewer-Dual-License
5
+ *
6
+ * This file is part of AstroViewer.
7
+ * AstroViewer is distributed under a dual-license model.
8
+ * Commercial use requires a separate commercial license.
9
+ * Non-commercial use is governed by LICENSE-NONCOMMERCIAL.md.
10
+ *
11
+ * See LICENSE.md, LICENSE-COMMERCIAL.md, and LICENSE-NONCOMMERCIAL.md for details.
12
+ */
13
+ import { XYZMeshBuilder } from './XYZMeshBuilder.js';
2
14
  export class XYZTile {
3
15
  _coord;
4
16
  _url;
5
17
  _webgl;
6
18
  _shaderProgram;
7
- _positionBuffer;
8
- _uvBuffer;
9
- _indexBuffer;
19
+ _meshBuilder;
20
+ _gpuMesh;
10
21
  _texture = null;
11
- _indices;
12
- _indexType;
22
+ _image;
13
23
  _ready = false;
14
- _aborted = false;
15
24
  _loading = false;
25
+ _aborted = false;
16
26
  _failedUntil = 0;
17
27
  _lastUsedAt = 0;
18
28
  _createdAt = Date.now();
19
- _image;
20
- _objectUrl = null;
21
- constructor(coord, url, mesh, webgl, shaderProgram) {
29
+ constructor(coord, url, webgl, shaderProgram, meshBuilder = new XYZMeshBuilder(), segmentsPerSide = 16) {
22
30
  this._coord = coord;
23
31
  this._url = url;
24
32
  this._webgl = webgl;
25
33
  this._shaderProgram = shaderProgram;
26
- this._positionBuffer = webgl.createBuffer();
27
- this._uvBuffer = webgl.createBuffer();
28
- this._indexBuffer = webgl.createBuffer();
29
- this._indices = mesh.indices;
30
- this._indexType = mesh.indices instanceof Uint32Array ? webgl.UNSIGNED_INT : webgl.UNSIGNED_SHORT;
31
- webgl.bindBuffer(webgl.ARRAY_BUFFER, this._positionBuffer);
32
- webgl.bufferData(webgl.ARRAY_BUFFER, mesh.positions, webgl.STATIC_DRAW);
33
- webgl.bindBuffer(webgl.ARRAY_BUFFER, this._uvBuffer);
34
- webgl.bufferData(webgl.ARRAY_BUFFER, mesh.uvs, webgl.STATIC_DRAW);
35
- webgl.bindBuffer(webgl.ELEMENT_ARRAY_BUFFER, this._indexBuffer);
36
- webgl.bufferData(webgl.ELEMENT_ARRAY_BUFFER, mesh.indices, webgl.STATIC_DRAW);
37
- }
38
- get ready() {
39
- return this._ready;
34
+ this._meshBuilder = meshBuilder;
35
+ const mesh = this._meshBuilder.buildTileMesh(coord, segmentsPerSide);
36
+ this._gpuMesh = this._meshBuilder.uploadMesh(mesh, this._webgl);
37
+ this.initImage();
40
38
  }
41
39
  get coord() {
42
40
  return this._coord;
43
41
  }
44
- get failedUntil() {
45
- return this._failedUntil;
42
+ get ready() {
43
+ return this._ready;
46
44
  }
47
45
  get loading() {
48
46
  return this._loading;
49
47
  }
48
+ get failedUntil() {
49
+ return this._failedUntil;
50
+ }
50
51
  get lastUsedAt() {
51
52
  return this._lastUsedAt;
52
53
  }
@@ -56,10 +57,7 @@ export class XYZTile {
56
57
  touch() {
57
58
  this._lastUsedAt = Date.now();
58
59
  }
59
- primeLoad(priority = 0) {
60
- this.loadTexture(priority);
61
- }
62
- loadTexture(priority = 0) {
60
+ initImage() {
63
61
  if (this._loading || this._ready || this._aborted) {
64
62
  return;
65
63
  }
@@ -68,80 +66,88 @@ export class XYZTile {
68
66
  return;
69
67
  }
70
68
  this._loading = true;
71
- xyzTileRequestScheduler.load(this._url, priority)
72
- .then((blob) => this.loadImageFromBlob(blob))
73
- .catch((error) => {
74
- this._loading = false;
75
- this._ready = false;
76
- const cooldownMs = error instanceof XYZTileRequestError ? error.cooldownMs : 10000;
77
- this._failedUntil = Date.now() + cooldownMs;
78
- });
79
- }
80
- loadImageFromBlob(blob) {
81
69
  const image = new Image();
82
70
  this._image = image;
83
- this._objectUrl = URL.createObjectURL(blob);
84
- image.onload = () => this.onImageLoaded();
71
+ image.crossOrigin = 'anonymous';
72
+ image.onload = () => this.imageLoaded();
85
73
  image.onerror = () => {
86
- this._loading = false;
87
74
  this._ready = false;
88
- this._failedUntil = Date.now() + 30000;
89
- this.revokeObjectUrl();
75
+ this._loading = false;
76
+ this._failedUntil = Date.now() + 30_000;
90
77
  };
91
- image.src = this._objectUrl;
78
+ image.src = this._url;
92
79
  }
93
- onImageLoaded() {
80
+ imageLoaded() {
94
81
  if (!this._image || this._aborted) {
95
82
  return;
96
83
  }
84
+ this.textureLoaded(this._image);
85
+ this._loading = false;
86
+ this._failedUntil = 0;
87
+ this._ready = true;
88
+ }
89
+ textureLoaded(image) {
97
90
  const gl = this._webgl;
91
+ this._shaderProgram.enableProgram();
98
92
  const texture = gl.createTexture();
99
93
  if (!texture) {
100
- throw new Error('Could not create XYZ texture');
94
+ throw new Error(`Could not create XYZ texture for ${this.key}`);
101
95
  }
102
96
  this._texture = texture;
103
97
  gl.activeTexture(gl.TEXTURE0);
104
- gl.bindTexture(gl.TEXTURE_2D, texture);
105
98
  gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
106
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._image);
99
+ gl.bindTexture(gl.TEXTURE_2D, texture);
100
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
107
101
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
108
102
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
109
103
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
110
104
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
111
- this._loading = false;
112
- this._failedUntil = 0;
113
- this._ready = true;
114
- this.revokeObjectUrl();
115
105
  }
116
- draw(pMatrix, vMatrix, mMatrix, priority = 0, allowLoad = true) {
106
+ draw(pMatrix, vMatrix, mMatrix, colorMapIdx) {
117
107
  this.touch();
118
- if (!this._ready && allowLoad) {
119
- this.loadTexture(priority);
120
- }
121
- if (!this._ready || !this._texture) {
122
- return;
108
+ if (!this._ready || !this._texture || this._aborted) {
109
+ return false;
123
110
  }
124
- this.drawWithGpuMesh({
125
- positionBuffer: this._positionBuffer,
126
- uvBuffer: this._uvBuffer,
127
- indexBuffer: this._indexBuffer,
128
- indexCount: this._indices.length,
129
- indexType: this._indexType,
130
- }, pMatrix, vMatrix, mMatrix);
131
- }
132
- drawRemapped(mesh, pMatrix, vMatrix, mMatrix) {
111
+ this.drawWithGpuMesh(this._gpuMesh, pMatrix, vMatrix, mMatrix, colorMapIdx);
112
+ return true;
113
+ }
114
+ drawRemapped(mesh, pMatrix, vMatrix, mMatrix, colorMapIdx) {
133
115
  this.touch();
134
- if (!this._ready || !this._texture) {
135
- return;
116
+ if (!this._ready || !this._texture || this._aborted) {
117
+ return false;
136
118
  }
137
- this.drawWithGpuMesh(mesh, pMatrix, vMatrix, mMatrix);
119
+ this.drawWithGpuMesh(mesh, pMatrix, vMatrix, mMatrix, colorMapIdx);
120
+ return true;
121
+ }
122
+ dispose() {
123
+ const gl = this._webgl;
124
+ if (this._texture) {
125
+ gl.deleteTexture(this._texture);
126
+ this._texture = null;
127
+ }
128
+ if (this._gpuMesh.positionBuffer) {
129
+ gl.deleteBuffer(this._gpuMesh.positionBuffer);
130
+ this._gpuMesh.positionBuffer = null;
131
+ }
132
+ if (this._gpuMesh.uvBuffer) {
133
+ gl.deleteBuffer(this._gpuMesh.uvBuffer);
134
+ this._gpuMesh.uvBuffer = null;
135
+ }
136
+ if (this._gpuMesh.indexBuffer) {
137
+ gl.deleteBuffer(this._gpuMesh.indexBuffer);
138
+ this._gpuMesh.indexBuffer = null;
139
+ }
140
+ this._image = undefined;
141
+ this._ready = false;
142
+ this._loading = false;
143
+ this._aborted = true;
138
144
  }
139
- drawWithGpuMesh(mesh, pMatrix, vMatrix, mMatrix) {
145
+ drawWithGpuMesh(mesh, pMatrix, vMatrix, mMatrix, colorMapIdx) {
140
146
  if (!this._texture) {
141
147
  return;
142
148
  }
143
149
  const gl = this._webgl;
144
- this._shaderProgram.enableShaders(pMatrix, vMatrix, mMatrix);
150
+ this._shaderProgram.enableShaders(pMatrix, vMatrix, mMatrix, colorMapIdx);
145
151
  gl.bindBuffer(gl.ARRAY_BUFFER, mesh.positionBuffer);
146
152
  gl.vertexAttribPointer(this._shaderProgram.locations.vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
147
153
  gl.enableVertexAttribArray(this._shaderProgram.locations.vertexPositionAttribute);
@@ -155,33 +161,7 @@ export class XYZTile {
155
161
  gl.disableVertexAttribArray(this._shaderProgram.locations.vertexPositionAttribute);
156
162
  gl.disableVertexAttribArray(this._shaderProgram.locations.textureCoordAttribute);
157
163
  }
158
- dispose() {
159
- const gl = this._webgl;
160
- if (this._texture) {
161
- gl.deleteTexture(this._texture);
162
- this._texture = null;
163
- }
164
- if (this._positionBuffer) {
165
- gl.deleteBuffer(this._positionBuffer);
166
- this._positionBuffer = null;
167
- }
168
- if (this._uvBuffer) {
169
- gl.deleteBuffer(this._uvBuffer);
170
- this._uvBuffer = null;
171
- }
172
- if (this._indexBuffer) {
173
- gl.deleteBuffer(this._indexBuffer);
174
- this._indexBuffer = null;
175
- }
176
- this._image = undefined;
177
- this.revokeObjectUrl();
178
- this._loading = false;
179
- this._ready = false;
180
- }
181
- revokeObjectUrl() {
182
- if (this._objectUrl) {
183
- URL.revokeObjectURL(this._objectUrl);
184
- this._objectUrl = null;
185
- }
164
+ get key() {
165
+ return `${this._coord.z}/${this._coord.x}/${this._coord.y}`;
186
166
  }
187
167
  }
@@ -1,39 +1,37 @@
1
- import { XYZShaderProgram } from '../../shader/XYZShaderProgram.js';
2
- import { XYZMeshBuilder } from './XYZMeshBuilder.js';
3
- import { XYZTile } from './XYZTile.js';
4
- import type { XYZTileCoord } from './types.js';
5
- export type XYZTileRequest = {
6
- tileCoord: XYZTileCoord;
7
- url: string;
8
- priority: number;
9
- role: 'current' | 'coverage' | 'fallback' | 'base';
1
+ import type { XYZTileCoord } from './XYZTypes.js';
2
+ export type XYZBufferedTile = {
3
+ coord: XYZTileCoord;
4
+ loading?: boolean;
5
+ lastUsedAt?: number;
6
+ createdAt?: number;
7
+ touch?: () => void;
8
+ dispose?: () => void;
10
9
  };
11
- type XYZTileBufferEntry = {
12
- tile: XYZTile;
10
+ export type XYZTileBufferEntry<TTile extends XYZBufferedTile = XYZBufferedTile> = {
11
+ tile: TTile;
13
12
  cacheTime0?: number;
14
- role: 'current' | 'coverage' | 'fallback' | 'base';
15
13
  };
16
- export declare class XYZTileBuffer {
14
+ export type XYZTileFactory<TTile extends XYZBufferedTile = XYZBufferedTile> = (coord: XYZTileCoord) => TTile;
15
+ export declare class XYZTileBuffer<TTile extends XYZBufferedTile = XYZBufferedTile> {
17
16
  private _tiles;
18
17
  private _cachedTiles;
19
18
  private _cacheAliveMilliSeconds;
20
19
  private _cleanerId;
21
- private _webgl;
22
- private _meshBuilder;
23
- private _shaderProgram;
24
- constructor(minutesToLiveInCache: number | undefined, webgl: WebGL2RenderingContext, meshBuilder: XYZMeshBuilder, shaderProgram: XYZShaderProgram);
25
- get activeTiles(): Map<string, XYZTileBufferEntry>;
26
- get cachedTiles(): Map<string, XYZTileBufferEntry>;
20
+ constructor(minutesToLiveInCache?: number);
21
+ get activeTiles(): Map<string, XYZTileBufferEntry<TTile>>;
22
+ get cachedTiles(): Map<string, XYZTileBufferEntry<TTile>>;
27
23
  get size(): number;
28
- getTile(tileCoord: XYZTileCoord, url: string, segmentsPerSide: number, role: 'current' | 'coverage' | 'fallback' | 'base'): XYZTile;
29
- private getExistingTile;
30
- ensureTiles(requests: XYZTileRequest[], segmentsPerSide: number): string[];
31
- getActiveTile(tileKey: string): XYZTile | null;
32
- getAnyTile(tileKey: string): XYZTile | null;
24
+ ensureTiles(visibleTiles: XYZTileCoord[], tileFactory: XYZTileFactory<TTile>): string[];
25
+ getTile(tileCoord: XYZTileCoord, tileFactory: XYZTileFactory<TTile>): TTile;
26
+ getActiveTile(tileKey: string): TTile | null;
27
+ getAnyTile(tileKey: string): TTile | null;
28
+ getActiveTiles(): TTile[];
33
29
  syncVisibleTiles(visibleTileKeys: string[]): void;
34
30
  evictCached(maxCachedTiles: number): void;
35
31
  dispose(): void;
32
+ key(tileCoord: XYZTileCoord): string;
33
+ static key(tileCoord: XYZTileCoord): string;
36
34
  private cacheCleaner;
37
- private key;
35
+ private touchTile;
36
+ private getTileAgeScore;
38
37
  }
39
- export {};
@@ -1,20 +1,27 @@
1
- import { XYZTile } from './XYZTile.js';
1
+ /*
2
+ * AstroViewer
3
+ * Copyright (C) Fabrizio Giordano
4
+ * SPDX-License-Identifier: LicenseRef-AstroViewer-Dual-License
5
+ *
6
+ * This file is part of AstroViewer.
7
+ * AstroViewer is distributed under a dual-license model.
8
+ * Commercial use requires a separate commercial license.
9
+ * Non-commercial use is governed by LICENSE-NONCOMMERCIAL.md.
10
+ *
11
+ * See LICENSE.md, LICENSE-COMMERCIAL.md, and LICENSE-NONCOMMERCIAL.md for details.
12
+ */
2
13
  export class XYZTileBuffer {
3
14
  _tiles = new Map();
4
15
  _cachedTiles = new Map();
5
16
  _cacheAliveMilliSeconds;
6
17
  _cleanerId;
7
- _webgl;
8
- _meshBuilder;
9
- _shaderProgram;
10
- constructor(minutesToLiveInCache = 1, webgl, meshBuilder, shaderProgram) {
18
+ constructor(minutesToLiveInCache = 1) {
11
19
  this._cacheAliveMilliSeconds = minutesToLiveInCache * 60 * 1000;
12
- this._webgl = webgl;
13
- this._meshBuilder = meshBuilder;
14
- this._shaderProgram = shaderProgram;
15
- this._cleanerId = window.setInterval(() => {
16
- this.cacheCleaner();
17
- }, 10_000);
20
+ if (typeof window !== 'undefined') {
21
+ this._cleanerId = window.setInterval(() => {
22
+ this.cacheCleaner();
23
+ }, 10_000);
24
+ }
18
25
  }
19
26
  get activeTiles() {
20
27
  return this._tiles;
@@ -25,64 +32,31 @@ export class XYZTileBuffer {
25
32
  get size() {
26
33
  return this._tiles.size + this._cachedTiles.size;
27
34
  }
28
- getTile(tileCoord, url, segmentsPerSide, role) {
29
- const tileKey = this.key(tileCoord);
30
- if (!this._tiles.has(tileKey)) {
31
- if (this._cachedTiles.has(tileKey)) {
32
- const entry = this._cachedTiles.get(tileKey);
33
- entry.cacheTime0 = undefined;
34
- entry.role = role;
35
- this._tiles.set(tileKey, entry);
36
- this._cachedTiles.delete(tileKey);
37
- }
38
- else {
39
- const mesh = this._meshBuilder.buildTileMesh(tileCoord, segmentsPerSide);
40
- this._tiles.set(tileKey, {
41
- tile: new XYZTile(tileCoord, url, mesh, this._webgl, this._shaderProgram),
42
- role,
43
- });
44
- }
45
- }
46
- else {
47
- const entry = this._tiles.get(tileKey);
48
- entry.role = role;
35
+ ensureTiles(visibleTiles, tileFactory) {
36
+ const visibleTileKeys = [];
37
+ for (const tileCoord of visibleTiles) {
38
+ const tile = this.getTile(tileCoord, tileFactory);
39
+ this.touchTile(tile);
40
+ visibleTileKeys.push(this.key(tileCoord));
49
41
  }
50
- return this._tiles.get(tileKey).tile;
42
+ this.syncVisibleTiles(visibleTileKeys);
43
+ return visibleTileKeys;
51
44
  }
52
- getExistingTile(tileCoord, role) {
45
+ getTile(tileCoord, tileFactory) {
53
46
  const tileKey = this.key(tileCoord);
54
47
  if (this._tiles.has(tileKey)) {
55
- const entry = this._tiles.get(tileKey);
56
- entry.role = role;
57
- return entry.tile;
48
+ return this._tiles.get(tileKey).tile;
58
49
  }
59
50
  if (this._cachedTiles.has(tileKey)) {
60
51
  const entry = this._cachedTiles.get(tileKey);
61
52
  entry.cacheTime0 = undefined;
62
- entry.role = role;
63
53
  this._tiles.set(tileKey, entry);
64
54
  this._cachedTiles.delete(tileKey);
65
55
  return entry.tile;
66
56
  }
67
- return null;
68
- }
69
- ensureTiles(requests, segmentsPerSide) {
70
- const visibleTileKeys = [];
71
- for (const request of requests) {
72
- const tile = request.role === 'fallback'
73
- ? this.getExistingTile(request.tileCoord, 'fallback')
74
- : this.getTile(request.tileCoord, request.url, segmentsPerSide, request.role);
75
- if (!tile) {
76
- continue;
77
- }
78
- tile.touch();
79
- if (request.role !== 'fallback') {
80
- tile.primeLoad(request.priority);
81
- }
82
- visibleTileKeys.push(this.key(request.tileCoord));
83
- }
84
- this.syncVisibleTiles(visibleTileKeys);
85
- return visibleTileKeys;
57
+ const tile = tileFactory(tileCoord);
58
+ this._tiles.set(tileKey, { tile });
59
+ return tile;
86
60
  }
87
61
  getActiveTile(tileKey) {
88
62
  return this._tiles.get(tileKey)?.tile ?? null;
@@ -90,11 +64,14 @@ export class XYZTileBuffer {
90
64
  getAnyTile(tileKey) {
91
65
  return this._tiles.get(tileKey)?.tile ?? this._cachedTiles.get(tileKey)?.tile ?? null;
92
66
  }
67
+ getActiveTiles() {
68
+ return Array.from(this._tiles.values(), (entry) => entry.tile);
69
+ }
93
70
  syncVisibleTiles(visibleTileKeys) {
94
71
  const visibleKeySet = new Set(visibleTileKeys);
95
72
  for (const [tileKey, entry] of this._tiles) {
96
73
  if (visibleKeySet.has(tileKey)) {
97
- entry.tile.touch();
74
+ this.touchTile(entry.tile);
98
75
  continue;
99
76
  }
100
77
  entry.cacheTime0 = Date.now();
@@ -107,9 +84,7 @@ export class XYZTileBuffer {
107
84
  return;
108
85
  }
109
86
  const candidates = Array.from(this._cachedTiles.entries()).sort((a, b) => {
110
- const scoreA = Math.min(a[1].tile.lastUsedAt || a[1].tile.createdAt, a[1].tile.createdAt);
111
- const scoreB = Math.min(b[1].tile.lastUsedAt || b[1].tile.createdAt, b[1].tile.createdAt);
112
- return scoreA - scoreB;
87
+ return this.getTileAgeScore(a[1].tile) - this.getTileAgeScore(b[1].tile);
113
88
  });
114
89
  for (const [tileKey, entry] of candidates) {
115
90
  if (this.size <= maxCachedTiles) {
@@ -118,32 +93,47 @@ export class XYZTileBuffer {
118
93
  if (entry.tile.loading) {
119
94
  continue;
120
95
  }
121
- entry.tile.dispose();
96
+ entry.tile.dispose?.();
122
97
  this._cachedTiles.delete(tileKey);
123
98
  }
124
99
  }
125
100
  dispose() {
126
- window.clearInterval(this._cleanerId);
101
+ if (this._cleanerId !== undefined && typeof window !== 'undefined') {
102
+ window.clearInterval(this._cleanerId);
103
+ this._cleanerId = undefined;
104
+ }
127
105
  for (const entry of this._tiles.values()) {
128
- entry.tile.dispose();
106
+ entry.tile.dispose?.();
129
107
  }
130
108
  for (const entry of this._cachedTiles.values()) {
131
- entry.tile.dispose();
109
+ entry.tile.dispose?.();
132
110
  }
133
111
  this._tiles.clear();
134
112
  this._cachedTiles.clear();
135
113
  }
114
+ key(tileCoord) {
115
+ return XYZTileBuffer.key(tileCoord);
116
+ }
117
+ static key(tileCoord) {
118
+ return `${tileCoord.z}/${tileCoord.x}/${tileCoord.y}`;
119
+ }
136
120
  cacheCleaner() {
137
121
  const now = Date.now();
138
122
  for (const [tileKey, entry] of this._cachedTiles) {
139
123
  const t0 = entry.cacheTime0;
140
- if (t0 !== undefined && now - t0 > this._cacheAliveMilliSeconds && !entry.tile.loading) {
141
- entry.tile.dispose();
142
- this._cachedTiles.delete(tileKey);
124
+ if (t0 === undefined || now - t0 <= this._cacheAliveMilliSeconds || entry.tile.loading) {
125
+ continue;
143
126
  }
127
+ entry.tile.dispose?.();
128
+ this._cachedTiles.delete(tileKey);
144
129
  }
145
130
  }
146
- key(tileCoord) {
147
- return `${tileCoord.z}/${tileCoord.x}/${tileCoord.y}`;
131
+ touchTile(tile) {
132
+ tile.touch?.();
133
+ }
134
+ getTileAgeScore(tile) {
135
+ const lastUsedAt = tile.lastUsedAt ?? 0;
136
+ const createdAt = tile.createdAt ?? lastUsedAt;
137
+ return Math.min(lastUsedAt || createdAt, createdAt);
148
138
  }
149
139
  }
@@ -1,4 +1,4 @@
1
- import type { XYZRequestSchedulerDebugStats } from './types.js';
1
+ import type { XYZRequestSchedulerDebugStats } from './XYZConfig.js';
2
2
  export declare class XYZTileRequestError extends Error {
3
3
  cooldownMs: number;
4
4
  retryable: boolean;
@@ -1,3 +1,15 @@
1
+ /*
2
+ * AstroViewer
3
+ * Copyright (C) Fabrizio Giordano
4
+ * SPDX-License-Identifier: LicenseRef-AstroViewer-Dual-License
5
+ *
6
+ * This file is part of AstroViewer.
7
+ * AstroViewer is distributed under a dual-license model.
8
+ * Commercial use requires a separate commercial license.
9
+ * Non-commercial use is governed by LICENSE-NONCOMMERCIAL.md.
10
+ *
11
+ * See LICENSE.md, LICENSE-COMMERCIAL.md, and LICENSE-NONCOMMERCIAL.md for details.
12
+ */
1
13
  export class XYZTileRequestError extends Error {
2
14
  cooldownMs;
3
15
  retryable;
@@ -73,9 +85,8 @@ export class XYZTileRequestScheduler {
73
85
  pump() {
74
86
  while (this._activeCount < this._maxConcurrent && this._queue.length > 0) {
75
87
  const item = this._queue.shift();
76
- if (!item) {
88
+ if (!item)
77
89
  return;
78
- }
79
90
  const hostCooldown = this.getHostCooldown(item.url);
80
91
  const now = Date.now();
81
92
  if (hostCooldown > now) {
@@ -0,0 +1,24 @@
1
+ export type XYZTileCoord = {
2
+ z: number;
3
+ x: number;
4
+ y: number;
5
+ };
6
+ export type XYZVisibleTileSelection = {
7
+ key: string;
8
+ currentZoom: number;
9
+ visibleTiles: XYZTileCoord[];
10
+ visibleTilesMap: Map<string, XYZTileCoord>;
11
+ ancestorsMap: Map<string, XYZTileCoord>;
12
+ };
13
+ export type XYZTileMesh = {
14
+ positions: Float32Array;
15
+ uvs: Float32Array;
16
+ indices: Uint16Array | Uint32Array;
17
+ };
18
+ export type XYZTileGpuMesh = {
19
+ positionBuffer: WebGLBuffer | null;
20
+ uvBuffer: WebGLBuffer | null;
21
+ indexBuffer: WebGLBuffer | null;
22
+ indexCount: number;
23
+ indexType: number;
24
+ };
@@ -0,0 +1,13 @@
1
+ /*
2
+ * AstroViewer
3
+ * Copyright (C) Fabrizio Giordano
4
+ * SPDX-License-Identifier: LicenseRef-AstroViewer-Dual-License
5
+ *
6
+ * This file is part of AstroViewer.
7
+ * AstroViewer is distributed under a dual-license model.
8
+ * Commercial use requires a separate commercial license.
9
+ * Non-commercial use is governed by LICENSE-NONCOMMERCIAL.md.
10
+ *
11
+ * See LICENSE.md, LICENSE-COMMERCIAL.md, and LICENSE-NONCOMMERCIAL.md for details.
12
+ */
13
+ export {};
@@ -1,30 +1,19 @@
1
- import type { XYZTileCoord } from './types.js';
2
- import { XYZTileProvider } from './XYZTileProvider.js';
3
- import type { SkyEntityDrawInput } from '../AbstractSkyEntity.js';
4
- export type XYZTileSelection = {
5
- key: string;
6
- currentTiles: XYZTileCoord[];
7
- fallbackTiles: XYZTileCoord[];
8
- currentZoom: number;
9
- coreTileCount: number;
10
- coverageTileCount: number;
11
- };
1
+ import { ReadonlyMat4 } from 'gl-matrix';
2
+ import Camera from '../../Camera.js';
3
+ import { AbstractSkyEntity } from '../AbstractSkyEntity.js';
4
+ import type { XYZTileCoord, XYZVisibleTileSelection } from './XYZTypes.js';
12
5
  export declare class XYZVisibleTilesManager {
13
- private _provider;
14
- constructor(provider: XYZTileProvider);
15
- selectTiles(input: SkyEntityDrawInput): XYZTileSelection;
16
- private buildCoreVisibleTiles;
17
- private buildCoverageTiles;
18
- private collectCoverageSamples;
19
- private interpolateFoVPolygon;
20
- private getNeighborRing;
21
- private isBoundaryTile;
22
- private normalizeTile;
23
- private normalizePhi;
24
- private buildFallbackMap;
25
- private buildFallbackSeedTiles;
26
- private orderTilesByScreenRelevance;
27
- private orderFallbackTiles;
28
- private getCenterTileCoord;
6
+ private _ancestorsMap;
7
+ private _visibleTilesMap;
8
+ private _visibleTiles;
9
+ private _selection;
10
+ get ancestorsMap(): Map<string, XYZTileCoord>;
11
+ get visibleTiles(): XYZTileCoord[];
12
+ get visibleTilesMap(): Map<string, XYZTileCoord>;
13
+ get selection(): XYZVisibleTileSelection;
14
+ computeVisibleTiles(z: number, xyzModel: AbstractSkyEntity, webgl: WebGL2RenderingContext, camera: Camera, pMatrix: ReadonlyMat4, sampleCount?: number, padding?: number): XYZVisibleTileSelection;
15
+ private refreshAncestorsMap;
16
+ private buildTileMap;
17
+ private buildSelectionKey;
29
18
  private key;
30
19
  }