astro-viewer 3.0.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/dist/astroviewer.cjs +3082 -1410
  2. package/dist/astroviewer.js +1 -1
  3. package/dist/astroviewer.min.js +1 -1
  4. package/lib-esm/AstroSphere.d.ts +40 -16
  5. package/lib-esm/AstroSphere.js +359 -93
  6. package/lib-esm/AstroViewer.d.ts +20 -5
  7. package/lib-esm/AstroViewer.js +50 -0
  8. package/lib-esm/Camera.js +28 -14
  9. package/lib-esm/Config.d.ts +2 -0
  10. package/lib-esm/Config.js +15 -1
  11. package/lib-esm/Global.js +12 -0
  12. package/lib-esm/index.d.ts +8 -4
  13. package/lib-esm/index.js +17 -3
  14. package/lib-esm/model/AbstractSkyEntity.d.ts +1 -0
  15. package/lib-esm/model/AbstractSkyEntity.js +12 -0
  16. package/lib-esm/model/AstroGL.js +12 -0
  17. package/lib-esm/model/ColorMaps.js +12 -0
  18. package/lib-esm/model/MetadataColumn.js +12 -0
  19. package/lib-esm/model/MetadataManager.d.ts +1 -0
  20. package/lib-esm/model/MetadataManager.js +16 -1
  21. package/lib-esm/model/Point.d.ts +9 -1
  22. package/lib-esm/model/Point.js +30 -0
  23. package/lib-esm/model/Point2D.js +12 -0
  24. package/lib-esm/model/Source.js +12 -0
  25. package/lib-esm/model/SphereFoV.d.ts +30 -0
  26. package/lib-esm/model/SphereFoV.js +196 -0
  27. package/lib-esm/model/catalogues/CatalogueGL.js +12 -0
  28. package/lib-esm/model/catalogues/CatalogueProps.js +13 -1
  29. package/lib-esm/model/earth/{wmts/WMTSAdapter.d.ts → WMTSAdapter.d.ts} +2 -1
  30. package/lib-esm/model/earth/{wmts/WMTSAdapter.js → WMTSAdapter.js} +12 -0
  31. package/lib-esm/model/earth/XYZAnchestorTile.d.ts +17 -0
  32. package/lib-esm/model/earth/XYZAnchestorTile.js +87 -0
  33. package/lib-esm/model/earth/{types.d.ts → XYZConfig.d.ts} +6 -17
  34. package/lib-esm/model/earth/XYZConfig.js +13 -0
  35. package/lib-esm/model/earth/XYZFoVHelper.d.ts +12 -0
  36. package/lib-esm/model/earth/XYZFoVHelper.js +138 -0
  37. package/lib-esm/model/earth/XYZMap.d.ts +31 -0
  38. package/lib-esm/model/earth/XYZMap.js +208 -0
  39. package/lib-esm/model/earth/XYZMapDescriptor.d.ts +29 -0
  40. package/lib-esm/model/earth/XYZMapDescriptor.js +77 -0
  41. package/lib-esm/model/earth/XYZMeshBuilder.d.ts +1 -1
  42. package/lib-esm/model/earth/XYZMeshBuilder.js +13 -2
  43. package/lib-esm/model/earth/XYZTile.d.ts +20 -21
  44. package/lib-esm/model/earth/XYZTile.js +82 -102
  45. package/lib-esm/model/earth/XYZTileBuffer.d.ts +24 -26
  46. package/lib-esm/model/earth/XYZTileBuffer.js +60 -70
  47. package/lib-esm/model/earth/XYZTileRequestScheduler.d.ts +1 -1
  48. package/lib-esm/model/earth/XYZTileRequestScheduler.js +13 -2
  49. package/lib-esm/model/earth/XYZTypes.d.ts +24 -0
  50. package/lib-esm/model/earth/XYZTypes.js +13 -0
  51. package/lib-esm/model/earth/XYZVisibleTilesManager.d.ts +16 -27
  52. package/lib-esm/model/earth/XYZVisibleTilesManager.js +61 -192
  53. package/lib-esm/model/footprints/Footprint.d.ts +4 -1
  54. package/lib-esm/model/footprints/Footprint.js +30 -2
  55. package/lib-esm/model/footprints/FootprintProps.js +13 -1
  56. package/lib-esm/model/footprints/FootprintSetGL.d.ts +4 -2
  57. package/lib-esm/model/footprints/FootprintSetGL.js +21 -6
  58. package/lib-esm/model/grid/EquatorialGrid.d.ts +2 -1
  59. package/lib-esm/model/grid/EquatorialGrid.js +30 -12
  60. package/lib-esm/model/grid/GridTextHelper.d.ts +10 -19
  61. package/lib-esm/model/grid/GridTextHelper.js +70 -67
  62. package/lib-esm/model/grid/HealpixGrid.d.ts +4 -4
  63. package/lib-esm/model/grid/HealpixGrid.js +24 -8
  64. package/lib-esm/model/grid/LonLatGrid.d.ts +43 -0
  65. package/lib-esm/model/grid/LonLatGrid.js +309 -0
  66. package/lib-esm/model/hips/AllSky.js +12 -0
  67. package/lib-esm/model/hips/AncestorTile.js +12 -0
  68. package/lib-esm/model/hips/FoVHelper.d.ts +5 -2
  69. package/lib-esm/model/hips/FoVHelper.js +52 -3
  70. package/lib-esm/model/hips/HiPS.d.ts +2 -0
  71. package/lib-esm/model/hips/HiPS.js +38 -14
  72. package/lib-esm/model/hips/HiPSConfig.d.ts +13 -0
  73. package/lib-esm/model/hips/HiPSDescriptor.js +12 -0
  74. package/lib-esm/model/hips/Tile.d.ts +1 -0
  75. package/lib-esm/model/hips/Tile.js +15 -0
  76. package/lib-esm/model/hips/TileBuffer.d.ts +5 -0
  77. package/lib-esm/model/hips/TileBuffer.js +61 -0
  78. package/lib-esm/model/hips/VisibleTilesManager.js +12 -0
  79. package/lib-esm/model/tap/TapMetadata.js +12 -0
  80. package/lib-esm/model/tap/TapMetadataList.js +12 -0
  81. package/lib-esm/model/tap/TapRepo.js +12 -0
  82. package/lib-esm/model/terra/TerraFootprintSetGL.d.ts +6 -0
  83. package/lib-esm/model/terra/TerraFootprintSetGL.js +54 -0
  84. package/lib-esm/model/terra/TerraPointSetGL.js +12 -0
  85. package/lib-esm/services/SesameService.js +11 -3
  86. package/lib-esm/services/helpers.js +12 -0
  87. package/lib-esm/services/hipsNodeService.js +12 -0
  88. package/lib-esm/services/parse-hipslist.js +12 -0
  89. package/lib-esm/services/queryCatalogueByFoV.js +13 -1
  90. package/lib-esm/services/queryFootprintSetByFov.js +13 -1
  91. package/lib-esm/services/tapRepoService.js +13 -1
  92. package/lib-esm/services/types.js +12 -0
  93. package/lib-esm/shader/CatalogueShaderProgram.js +12 -0
  94. package/lib-esm/shader/FootprintShaderProgram.js +12 -0
  95. package/lib-esm/shader/GridShaderManager.js +12 -0
  96. package/lib-esm/shader/HiPSShaderProgram.js +12 -0
  97. package/lib-esm/shader/ShaderManager.js +12 -1
  98. package/lib-esm/shader/ShaderManagerMutliHiPS.js +12 -1
  99. package/lib-esm/shader/XYZShaderProgram.d.ts +14 -1
  100. package/lib-esm/shader/XYZShaderProgram.js +127 -2
  101. package/lib-esm/utils/CoordsType.d.ts +2 -1
  102. package/lib-esm/utils/CoordsType.js +13 -0
  103. package/lib-esm/utils/FoVUtils.js +12 -0
  104. package/lib-esm/utils/GeoJSONParser.d.ts +19 -0
  105. package/lib-esm/utils/GeoJSONParser.js +112 -0
  106. package/lib-esm/utils/GeomUtils.js +12 -0
  107. package/lib-esm/utils/MouseHelper.js +12 -0
  108. package/lib-esm/utils/PerspectiveMatrixManager.js +16 -1
  109. package/lib-esm/utils/RayPickingUtils.js +12 -0
  110. package/lib-esm/utils/STCSParser.d.ts +7 -3
  111. package/lib-esm/utils/STCSParser.js +27 -9
  112. package/lib-esm/utils/ShaderUtility.js +13 -1
  113. package/lib-esm/utils/Utils.js +12 -0
  114. package/lib-esm/utils/XYZRayPickingUtils.d.ts +27 -0
  115. package/lib-esm/utils/XYZRayPickingUtils.js +226 -0
  116. package/package.json +2 -2
  117. package/lib-esm/model/FoV.d.ts +0 -62
  118. package/lib-esm/model/FoV.js +0 -274
  119. package/lib-esm/model/earth/XYZAncestorMeshCache.d.ts +0 -10
  120. package/lib-esm/model/earth/XYZAncestorMeshCache.js +0 -31
  121. package/lib-esm/model/earth/XYZLayer.d.ts +0 -31
  122. package/lib-esm/model/earth/XYZLayer.js +0 -231
  123. package/lib-esm/model/earth/XYZTileProvider.d.ts +0 -29
  124. package/lib-esm/model/earth/XYZTileProvider.js +0 -187
  125. package/lib-esm/model/earth/wmts/types.d.ts +0 -1
  126. package/lib-esm/model/earth/wmts/types.js +0 -1
  127. /package/lib-esm/model/{earth/types.js → hips/HiPSConfig.js} +0 -0
@@ -1,62 +0,0 @@
1
- /**
2
- * FoV singleton (TypeScript)
3
- * - Uses computePerspectiveMatrixSingleton.pMatrix
4
- * - Guards acos domain (numeric safety)
5
- * - Uses vec3.transformMat4 instead of custom mat4*vec3
6
- * - Keeps original “insideSphere ? 360 - angle : angle” behavior
7
- */
8
- import { ReadonlyMat4 } from 'gl-matrix';
9
- import { HealpixGrid } from './grid/HealpixGrid.js';
10
- import Camera from '../Camera.js';
11
- export declare class FoV {
12
- private static readonly MIN_FOV_DEG;
13
- private fovXDeg;
14
- private fovYDeg;
15
- private ratio;
16
- private _minFoV;
17
- private _webgl;
18
- constructor(webgl: WebGL2RenderingContext);
19
- /** Recomputes FoV for current camera + projection */
20
- getFoV(insideSphere: boolean, healpixGridSingleton: HealpixGrid, camera: Camera, pMatrix: ReadonlyMat4): FoV;
21
- private computeRatio;
22
- changeMinFov(deg: number): void;
23
- get minFoV(): number;
24
- get xFoV(): number;
25
- get yFoV(): number;
26
- computeDistanceFromAngle(angleDeg: number): number;
27
- /** FoV half-screen chord angle doubled (deg) along a given canvas axis */
28
- private computeAngle;
29
- /**
30
- * Computes the camera position (x,y,z) along the current view direction that would
31
- * yield the requested minFoV (in degrees), assuming the camera is OUTSIDE the sphere.
32
- * This method does NOT mutate the camera; it only returns the suggested position.
33
- *
34
- * Geometry: for a sphere of radius R observed from distance d (from center),
35
- * the apparent angular diameter is 2*arcsin(R/d). Our minFoV is that angular diameter
36
- * along the tighter axis; we solve for d and place the camera on the current
37
- * center→camera direction with that distance.
38
- *
39
- * @param targetMinFoVDeg Desired min FoV in degrees, 0 < targetMinFoVDeg < 180
40
- * @returns Tuple [x, y, z] for the recommended camera position in world coordinates.
41
- */
42
- computeCameraPositionForMinFoV(targetMinFoVDeg: number): [number, number, number];
43
- /**
44
- * Computes the camera world-space position required to achieve a target FoV (deg),
45
- * keeping the same viewing direction. Acts as the inverse of computeAngle().
46
- *
47
- * @param targetFoVDeg desired full FoV angle in degrees (0 < FoV < 180)
48
- * @param canvasWidth canvas width in pixels
49
- * @param canvasHeight canvas height in pixels
50
- * @returns [x, y, z] coordinates for the new camera position
51
- */
52
- computeCameraPositionForFoV(targetFoVDeg: number): [number, number, number];
53
- /**
54
- * Return a camera position such that the sphere's apparent angular diameter
55
- * (the silhouette, not the surface coverage) equals targetAngularDiameterDeg.
56
- * Keeps current view direction; does not mutate the camera.
57
- *
58
- * @param targetAngularDiameterDeg desired apparent diameter in degrees (0<α<180)
59
- * @returns [x,y,z] world position
60
- */
61
- computeCameraPositionForAngularDiameter(targetAngularDiameterDeg: number): [number, number, number];
62
- }
@@ -1,274 +0,0 @@
1
- 'use strict';
2
- /**
3
- * FoV singleton (TypeScript)
4
- * - Uses computePerspectiveMatrixSingleton.pMatrix
5
- * - Guards acos domain (numeric safety)
6
- * - Uses vec3.transformMat4 instead of custom mat4*vec3
7
- * - Keeps original “insideSphere ? 360 - angle : angle” behavior
8
- */
9
- import { vec3, mat4 } from 'gl-matrix';
10
- import RayPickingUtils from '../utils/RayPickingUtils.js';
11
- import { radToDeg } from '../utils/Utils.js';
12
- export class FoV {
13
- static MIN_FOV_DEG = 1e-6;
14
- fovXDeg = 180;
15
- fovYDeg = 180;
16
- ratio = +0;
17
- _minFoV = 180;
18
- _webgl;
19
- constructor(webgl) {
20
- this._webgl = webgl;
21
- }
22
- /** Recomputes FoV for current camera + projection */
23
- getFoV(insideSphere, healpixGridSingleton, camera, pMatrix) {
24
- // const gl = webgl
25
- const gl = this._webgl;
26
- if (!gl || !gl.canvas) {
27
- // Handle the error or assign default values
28
- this.fovXDeg = 180;
29
- this.fovYDeg = 180;
30
- this._minFoV = this.minFoV;
31
- return this;
32
- }
33
- // horizontal FoV: ray through (centerY)
34
- // const xFoVComputed = this.computeAngle(0, gl.canvas.height / 2, insideSphere, healpixGridSingleton, camera)
35
- const canvas = gl.canvas;
36
- const rect = canvas.getBoundingClientRect();
37
- const canvasWidth = rect.width;
38
- const canvasHeight = rect.height;
39
- // const xFoVComputed = this.computeAngle(0, gl.canvas.height / 2, insideSphere, healpixGridSingleton, camera, pMatrix)
40
- const xFoVComputed = this.computeAngle(0, canvasHeight / 2, insideSphere, healpixGridSingleton, camera, pMatrix);
41
- this.fovXDeg = xFoVComputed.angleDeg;
42
- // vertical FoV: ray through (centerX)
43
- // const yFoVComputed = this.computeAngle(gl.canvas.width / 2, 0, insideSphere, healpixGridSingleton, camera, pMatrix)
44
- const yFoVComputed = this.computeAngle(canvasWidth / 2, 0, insideSphere, healpixGridSingleton, camera, pMatrix);
45
- this.fovYDeg = yFoVComputed.angleDeg;
46
- this._minFoV = this.minFoV;
47
- this.ratio = this.computeRatio(camera);
48
- return this;
49
- }
50
- computeRatio(camera) {
51
- // const camera = global.camera
52
- if (!camera)
53
- throw Error("Camera not defined");
54
- const pos = camera.getCameraPosition();
55
- const distanceFromCenter = Math.sqrt(pos[0] * pos[0] + pos[1] * pos[1] + pos[2] * pos[2]);
56
- // const distanceFromSphere = distanceFromCenter - healpixGridSingleton.RADIUS
57
- const ratio = distanceFromCenter / this.fovYDeg;
58
- return ratio;
59
- }
60
- changeMinFov(deg) {
61
- console.log("inside changeMinFov");
62
- if (this.fovYDeg <= this.fovXDeg) {
63
- this.fovYDeg = deg;
64
- }
65
- else {
66
- this.fovXDeg = deg;
67
- }
68
- console.log("changeMinFov: ping");
69
- this.minFoV;
70
- // this.fovYDeg <= this.fovXDeg ? this.fovYDeg = deg : this.fovXDeg = deg
71
- }
72
- get minFoV() {
73
- const minFov = this.fovYDeg <= this.fovXDeg ? this.fovYDeg : this.fovXDeg;
74
- this._minFoV = Math.max(minFov, FoV.MIN_FOV_DEG);
75
- return this._minFoV;
76
- }
77
- get xFoV() {
78
- return this.fovXDeg;
79
- }
80
- get yFoV() {
81
- return this.fovYDeg;
82
- }
83
- computeDistanceFromAngle(angleDeg) {
84
- const desiredFoV = angleDeg;
85
- const distance = desiredFoV * this.ratio;
86
- // return Math.abs(distance)
87
- return distance;
88
- }
89
- /** FoV half-screen chord angle doubled (deg) along a given canvas axis */
90
- computeAngle(canvasX, canvasY, insideSphere, healpixGridSingleton, camera, pMatrix) {
91
- // const pMatrix = computePerspectiveMatrixSingleton.pMatrix
92
- if (!pMatrix) {
93
- // Handle the error or assign a default value
94
- console.warn('FoV: projection matrix is null');
95
- return { angleDeg: 180, distance: 1 };
96
- }
97
- const vMatrix = camera.getCameraMatrix();
98
- if (!camera) {
99
- // Handle the error or assign a default value
100
- console.warn('FoV: camera is null');
101
- return { angleDeg: 180, distance: 1 };
102
- }
103
- const rayWorld = RayPickingUtils.getRayFromMouse(canvasX, canvasY, pMatrix, this._webgl, vMatrix);
104
- const intersectionDistance = RayPickingUtils.raySphere(camera.getCameraPosition(), rayWorld, healpixGridSingleton);
105
- let angleDeg;
106
- if (intersectionDistance > 0) {
107
- // world-space intersection point on the sphere
108
- const hit = vec3.create();
109
- vec3.scale(hit, rayWorld, intersectionDistance);
110
- vec3.add(hit, camera.getCameraPosition(), hit);
111
- const center = healpixGridSingleton.center;
112
- // vectors from sphere center
113
- const vHit = vec3.create();
114
- vec3.subtract(vHit, hit, center);
115
- // reference vector: rotate world +Z into current camera orientation, then from center
116
- const refWorldZ = vec3.fromValues(center[0], center[1], center[2] + healpixGridSingleton.radius);
117
- const vInv = mat4.create();
118
- mat4.invert(vInv, camera.getCameraMatrix());
119
- const refCamZ = vec3.create();
120
- vec3.transformMat4(refCamZ, refWorldZ, vInv);
121
- const vRef = vec3.create();
122
- vec3.subtract(vRef, refCamZ, center);
123
- // angle between vHit and vRef, doubled
124
- const dot = vec3.dot(vHit, vRef);
125
- const n1 = vec3.length(vHit);
126
- const n2 = vec3.length(vRef);
127
- // numeric safety for acos
128
- const c = Math.min(1, Math.max(-1, dot / (n1 * n2)));
129
- const angleRad = Math.acos(c);
130
- angleDeg = 2 * radToDeg(angleRad);
131
- }
132
- else {
133
- angleDeg = 180;
134
- }
135
- const finalAngle = insideSphere ? 360 - angleDeg : angleDeg;
136
- // return insideSphere ? 360 - angleDeg : angleDeg
137
- return { angleDeg: finalAngle, distance: intersectionDistance };
138
- }
139
- /**
140
- * Computes the camera position (x,y,z) along the current view direction that would
141
- * yield the requested minFoV (in degrees), assuming the camera is OUTSIDE the sphere.
142
- * This method does NOT mutate the camera; it only returns the suggested position.
143
- *
144
- * Geometry: for a sphere of radius R observed from distance d (from center),
145
- * the apparent angular diameter is 2*arcsin(R/d). Our minFoV is that angular diameter
146
- * along the tighter axis; we solve for d and place the camera on the current
147
- * center→camera direction with that distance.
148
- *
149
- * @param targetMinFoVDeg Desired min FoV in degrees, 0 < targetMinFoVDeg < 180
150
- * @returns Tuple [x, y, z] for the recommended camera position in world coordinates.
151
- */
152
- computeCameraPositionForMinFoV(targetMinFoVDeg) {
153
- // const camera = global.camera
154
- // const center = healpixGridSingleton.center
155
- // const R = healpixGridSingleton.radius
156
- // if (!camera) {
157
- // console.warn('FoV.computeCameraPositionForMinFoV: camera not available; returning a sensible default.')
158
- // return [center[0], center[1], center[2] + 2 * R]
159
- // }
160
- // // Clamp and validate input
161
- // const eps = 1e-6
162
- // const clamped = Math.max(eps, Math.min(180 - eps, targetMinFoVDeg))
163
- // const halfRad = (clamped * Math.PI / 180) * 0.5
164
- // // Distance from center needed to achieve the angular diameter
165
- // // minFoV = 2 * arcsin(R / d) => d = R / sin(minFoV/2)
166
- // const sinHalf = Math.sin(halfRad)
167
- // if (sinHalf <= 0) {
168
- // console.warn('FoV.computeCameraPositionForMinFoV: invalid targetMinFoVDeg, using fallback.')
169
- // return [center[0], center[1], center[2] + 2 * R]
170
- // }
171
- // let d = R / sinHalf
172
- // // Ensure we remain strictly outside the sphere
173
- // d = Math.max(d, R + 1e-4)
174
- // // Use the current center→camera direction to keep orientation
175
- // const camPos = camera.getCameraPosition()
176
- // let dirX = camPos[0] - center[0]
177
- // let dirY = camPos[1] - center[1]
178
- // let dirZ = camPos[2] - center[2]
179
- // const len = Math.hypot(dirX, dirY, dirZ)
180
- // if (len < eps) {
181
- // // If somehow at the center, use +Z as a default direction
182
- // dirX = 0; dirY = 0; dirZ = 1;
183
- // } else {
184
- // dirX /= len
185
- // dirY /= len
186
- // dirZ /= len
187
- // }
188
- // const newX = center[0] + dirX * d
189
- // const newY = center[1] + dirY * d
190
- // const newZ = center[2] + dirZ * d
191
- // return [newX, newY, newZ]
192
- return [0, 0, 0];
193
- }
194
- /**
195
- * Computes the camera world-space position required to achieve a target FoV (deg),
196
- * keeping the same viewing direction. Acts as the inverse of computeAngle().
197
- *
198
- * @param targetFoVDeg desired full FoV angle in degrees (0 < FoV < 180)
199
- * @param canvasWidth canvas width in pixels
200
- * @param canvasHeight canvas height in pixels
201
- * @returns [x, y, z] coordinates for the new camera position
202
- */
203
- computeCameraPositionForFoV(targetFoVDeg) {
204
- // const camera = global.camera;
205
- // const center = healpixGridSingleton.center;
206
- // const R = healpixGridSingleton.radius;
207
- // if (!camera) {
208
- // console.warn("FoV.computeCameraPositionForFoV: camera missing.");
209
- // return [center[0], center[1], center[2] + 2 * R];
210
- // }
211
- // const eps = 1e-6;
212
- // const clamped = Math.max(eps, Math.min(180 - eps, targetFoVDeg));
213
- // const halfRad = (clamped * Math.PI) / 360.0; // half-angle in radians
214
- // // Distance from center that yields this FoV
215
- // const sinHalf = Math.sin(halfRad);
216
- // if (sinHalf <= 0) {
217
- // console.warn("FoV.computeCameraPositionForFoV: invalid FoV.");
218
- // return [center[0], center[1], center[2] + 2 * R];
219
- // }
220
- // let d = R / sinHalf;
221
- // // Slightly outside sphere to avoid clipping
222
- // d = Math.max(d, R + 1e-4);
223
- // // Get current viewing direction
224
- // const camPos = camera.getCameraPosition();
225
- // let dirX = camPos[0] - center[0];
226
- // let dirY = camPos[1] - center[1];
227
- // let dirZ = camPos[2] - center[2];
228
- // const len = Math.hypot(dirX, dirY, dirZ);
229
- // if (len < eps) {
230
- // dirX = 0; dirY = 0; dirZ = 1;
231
- // } else {
232
- // dirX /= len;
233
- // dirY /= len;
234
- // dirZ /= len;
235
- // }
236
- // const newX = center[0] + dirX * d;
237
- // const newY = center[1] + dirY * d;
238
- // const newZ = center[2] + dirZ * d;
239
- // return [newX, newY, newZ];
240
- return [0, 0, 0];
241
- }
242
- /**
243
- * Return a camera position such that the sphere's apparent angular diameter
244
- * (the silhouette, not the surface coverage) equals targetAngularDiameterDeg.
245
- * Keeps current view direction; does not mutate the camera.
246
- *
247
- * @param targetAngularDiameterDeg desired apparent diameter in degrees (0<α<180)
248
- * @returns [x,y,z] world position
249
- */
250
- computeCameraPositionForAngularDiameter(targetAngularDiameterDeg) {
251
- // const camera = global.camera;
252
- // const center = healpixGridSingleton.center;
253
- // const R = healpixGridSingleton.radius;
254
- // if (!camera) {
255
- // console.warn('computeCameraPositionForAngularDiameter: camera missing.');
256
- // return [center[0], center[1], center[2] + 2 * R];
257
- // }
258
- // const eps = 1e-6;
259
- // const α = Math.max(eps, Math.min(180 - eps, targetAngularDiameterDeg));
260
- // const half = (α * Math.PI) / 360.0;
261
- // const sinHalf = Math.sin(half);
262
- // // d = R / sin(α/2)
263
- // let d = R / sinHalf;
264
- // d = Math.max(d, R + 1e-4); // stay outside
265
- // // project along current center→camera direction
266
- // const [cx, cy, cz] = center as [number, number, number];
267
- // const [px, py, pz] = camera.getCameraPosition();
268
- // let dx = px - cx, dy = py - cy, dz = pz - cz;
269
- // const L = Math.hypot(dx, dy, dz);
270
- // if (L < eps) { dx = 0; dy = 0; dz = 1; } else { dx /= L; dy /= L; dz /= L; }
271
- // return [cx + dx * d, cy + dy * d, cz + dz * d];
272
- return [0, 0, 0];
273
- }
274
- }
@@ -1,10 +0,0 @@
1
- import type { XYZTileCoord, XYZTileGpuMesh } from './types.js';
2
- import { XYZMeshBuilder } from './XYZMeshBuilder.js';
3
- export declare class XYZAncestorMeshCache {
4
- private _webgl;
5
- private _meshBuilder;
6
- private _meshes;
7
- constructor(webgl: WebGL2RenderingContext, meshBuilder: XYZMeshBuilder);
8
- getMesh(targetTile: XYZTileCoord, ancestorTile: XYZTileCoord, segmentsPerSide: number): XYZTileGpuMesh;
9
- dispose(): void;
10
- }
@@ -1,31 +0,0 @@
1
- export class XYZAncestorMeshCache {
2
- _webgl;
3
- _meshBuilder;
4
- _meshes = new Map();
5
- constructor(webgl, meshBuilder) {
6
- this._webgl = webgl;
7
- this._meshBuilder = meshBuilder;
8
- }
9
- getMesh(targetTile, ancestorTile, segmentsPerSide) {
10
- const key = `${targetTile.z}/${targetTile.x}/${targetTile.y}->${ancestorTile.z}/${ancestorTile.x}/${ancestorTile.y}@${segmentsPerSide}`;
11
- const existing = this._meshes.get(key);
12
- if (existing) {
13
- return existing;
14
- }
15
- const mesh = this._meshBuilder.buildAncestorMesh(targetTile, ancestorTile, segmentsPerSide);
16
- const uploaded = this._meshBuilder.uploadMesh(mesh, this._webgl);
17
- this._meshes.set(key, uploaded);
18
- return uploaded;
19
- }
20
- dispose() {
21
- for (const mesh of this._meshes.values()) {
22
- if (mesh.positionBuffer)
23
- this._webgl.deleteBuffer(mesh.positionBuffer);
24
- if (mesh.uvBuffer)
25
- this._webgl.deleteBuffer(mesh.uvBuffer);
26
- if (mesh.indexBuffer)
27
- this._webgl.deleteBuffer(mesh.indexBuffer);
28
- }
29
- this._meshes.clear();
30
- }
31
- }
@@ -1,31 +0,0 @@
1
- import { AbstractSkyEntity, SkyEntityDrawInput } from '../AbstractSkyEntity.js';
2
- import type { XYZLayerConfig, XYZLayerDebugStats } from './types.js';
3
- export declare class XYZLayer extends AbstractSkyEntity {
4
- private static readonly DEFAULT_MAX_CACHED_TILES;
5
- private _config;
6
- private _provider;
7
- private _visibleTilesManager;
8
- private _meshBuilder;
9
- private _xyzShaderProgram;
10
- private _tileBuffer;
11
- private _ancestorMeshCache;
12
- private _visibleTileKeys;
13
- private _fallbackVisibleTileKeys;
14
- private _baseVisibleTileKeys;
15
- private _tilePriorities;
16
- private _tileSelectionKey;
17
- private _currentTileCount;
18
- private _fallbackTileCount;
19
- private _coreTileCount;
20
- private _coverageTileCount;
21
- constructor(config: XYZLayerConfig, webgl: WebGL2RenderingContext);
22
- get config(): XYZLayerConfig;
23
- getDebugStats(): XYZLayerDebugStats;
24
- private bootstrapTiles;
25
- draw(input: SkyEntityDrawInput): void;
26
- private evictCache;
27
- private disposeTiles;
28
- private getTileKey;
29
- private parseTileKey;
30
- private findBestAvailableAncestor;
31
- }
@@ -1,231 +0,0 @@
1
- import { AbstractSkyEntity } from '../AbstractSkyEntity.js';
2
- import { XYZShaderProgram } from '../../shader/XYZShaderProgram.js';
3
- import { XYZAncestorMeshCache } from './XYZAncestorMeshCache.js';
4
- import { XYZMeshBuilder } from './XYZMeshBuilder.js';
5
- import { XYZTileBuffer } from './XYZTileBuffer.js';
6
- import { XYZTileProvider } from './XYZTileProvider.js';
7
- import { XYZVisibleTilesManager } from './XYZVisibleTilesManager.js';
8
- export class XYZLayer extends AbstractSkyEntity {
9
- static DEFAULT_MAX_CACHED_TILES = 384;
10
- _config;
11
- _provider;
12
- _visibleTilesManager;
13
- _meshBuilder;
14
- _xyzShaderProgram;
15
- _tileBuffer;
16
- _ancestorMeshCache;
17
- _visibleTileKeys = [];
18
- _fallbackVisibleTileKeys = [];
19
- _baseVisibleTileKeys = [];
20
- _tilePriorities = new Map();
21
- _tileSelectionKey = null;
22
- _currentTileCount = 0;
23
- _fallbackTileCount = 0;
24
- _coreTileCount = 0;
25
- _coverageTileCount = 0;
26
- constructor(config, webgl) {
27
- super(1, [0, 0, 0], 0, 0, 'XYZ Earth Layer', webgl, false);
28
- this._config = config;
29
- this._provider = new XYZTileProvider(config);
30
- this._visibleTilesManager = new XYZVisibleTilesManager(this._provider);
31
- this._meshBuilder = new XYZMeshBuilder();
32
- this._xyzShaderProgram = new XYZShaderProgram(webgl);
33
- this._tileBuffer = new XYZTileBuffer(1, webgl, this._meshBuilder, this._xyzShaderProgram);
34
- this._ancestorMeshCache = new XYZAncestorMeshCache(webgl, this._meshBuilder);
35
- this.initGL(webgl);
36
- this.bootstrapTiles(180, null, null);
37
- }
38
- get config() {
39
- return this._config;
40
- }
41
- getDebugStats() {
42
- let readyTileCount = 0;
43
- let loadingTileCount = 0;
44
- let coolingDownTileCount = 0;
45
- const now = Date.now();
46
- const allTiles = [
47
- ...Array.from(this._tileBuffer.activeTiles.values(), (entry) => entry.tile),
48
- ...Array.from(this._tileBuffer.cachedTiles.values(), (entry) => entry.tile),
49
- ];
50
- for (const tile of allTiles) {
51
- if (tile.ready) {
52
- readyTileCount += 1;
53
- }
54
- if (tile.loading) {
55
- loadingTileCount += 1;
56
- }
57
- if (tile.failedUntil > now) {
58
- coolingDownTileCount += 1;
59
- }
60
- }
61
- const currentZoom = this._visibleTileKeys.reduce((maxZoom, tileKey) => {
62
- const zoom = Number.parseInt(tileKey.split('/')[0] ?? '', 10);
63
- if (!Number.isFinite(zoom)) {
64
- return maxZoom;
65
- }
66
- return maxZoom == null ? zoom : Math.max(maxZoom, zoom);
67
- }, null);
68
- return {
69
- cacheSize: this._tileBuffer.size,
70
- visibleTileCount: this._visibleTileKeys.length,
71
- currentTileCount: this._currentTileCount,
72
- fallbackTileCount: this._fallbackTileCount,
73
- coreTileCount: this._coreTileCount,
74
- coverageTileCount: this._coverageTileCount,
75
- readyTileCount,
76
- loadingTileCount,
77
- coolingDownTileCount,
78
- currentZoom,
79
- tileSelectionKey: this._tileSelectionKey,
80
- isSettling: false,
81
- coarseTileCount: 0,
82
- hasPendingSelection: false,
83
- pendingSelectionKey: null,
84
- };
85
- }
86
- bootstrapTiles(fovDeg, camera, centerSphericalDeg, fovPolygon = null, viewportSphericalSamples = null) {
87
- const selection = camera
88
- ? this._visibleTilesManager.selectTiles({
89
- fovDeg,
90
- camera,
91
- pMatrix: new Float32Array(),
92
- centerSphericalDeg: centerSphericalDeg ?? undefined,
93
- fovPolygon: fovPolygon ?? undefined,
94
- viewportSphericalSamples: viewportSphericalSamples ?? undefined,
95
- })
96
- : {
97
- key: 'initial',
98
- currentTiles: this._provider.getInitialTiles(),
99
- fallbackTiles: [],
100
- currentZoom: 1,
101
- coreTileCount: this._provider.getInitialTiles().length,
102
- coverageTileCount: 0,
103
- };
104
- if (selection.key === this._tileSelectionKey) {
105
- return;
106
- }
107
- this._tileSelectionKey = selection.key;
108
- this._currentTileCount = selection.currentTiles.length;
109
- this._fallbackTileCount = selection.fallbackTiles.length;
110
- this._coreTileCount = selection.coreTileCount;
111
- this._coverageTileCount = selection.coverageTileCount;
112
- const segments = this._config.segmentsPerSide ?? 16;
113
- const baseTiles = this._provider.getInitialTiles();
114
- const coreTileKeys = new Set(selection.currentTiles
115
- .slice(0, selection.coreTileCount)
116
- .map((tileCoord) => this.getTileKey(tileCoord)));
117
- const baseTileKeys = new Set(baseTiles.map((tileCoord) => this.getTileKey(tileCoord)));
118
- const prioritizedBaseTiles = baseTiles.map((tileCoord, index) => ({
119
- tileCoord,
120
- priority: 5000 + (baseTiles.length - index),
121
- role: 'base',
122
- }));
123
- const prioritizedCurrentTiles = selection.currentTiles.map((tileCoord, index) => ({
124
- tileCoord,
125
- priority: 10000 + (selection.currentTiles.length - index),
126
- role: coreTileKeys.has(this.getTileKey(tileCoord)) ? 'current' : 'coverage',
127
- }));
128
- const prioritizedFallbackTiles = selection.fallbackTiles.map((tileCoord, index) => ({
129
- tileCoord,
130
- priority: 1000 + (selection.fallbackTiles.length - index),
131
- role: 'fallback',
132
- }));
133
- const requestedTiles = [...prioritizedBaseTiles, ...prioritizedCurrentTiles, ...prioritizedFallbackTiles];
134
- this._tilePriorities.clear();
135
- this._fallbackVisibleTileKeys = [];
136
- this._baseVisibleTileKeys = [];
137
- const orderedRequests = requestedTiles
138
- .sort((a, b) => a.tileCoord.z - b.tileCoord.z)
139
- .map(({ tileCoord, priority, role }) => {
140
- const tileKey = this.getTileKey(tileCoord);
141
- this._tilePriorities.set(tileKey, priority);
142
- return {
143
- tileCoord,
144
- priority,
145
- url: this._provider.getTileUrl(tileCoord),
146
- role,
147
- };
148
- });
149
- const ensuredKeys = this._tileBuffer.ensureTiles(orderedRequests, segments);
150
- const fallbackKeySet = new Set(selection.fallbackTiles.map((tileCoord) => this.getTileKey(tileCoord)));
151
- this._baseVisibleTileKeys = ensuredKeys.filter((tileKey) => baseTileKeys.has(tileKey));
152
- this._fallbackVisibleTileKeys = ensuredKeys.filter((tileKey) => fallbackKeySet.has(tileKey) && !baseTileKeys.has(tileKey));
153
- this._visibleTileKeys = ensuredKeys.filter((tileKey) => !fallbackKeySet.has(tileKey) && !baseTileKeys.has(tileKey));
154
- this.evictCache();
155
- }
156
- draw(input) {
157
- const vMatrix = input.camera.getCameraMatrix();
158
- if (!vMatrix)
159
- return;
160
- this.bootstrapTiles(input.fovDeg ?? 180, input.camera, input.centerSphericalDeg ?? null, input.fovPolygon ?? null, input.viewportSphericalSamples ?? null);
161
- const pMatrix = input.pMatrix;
162
- const mMatrix = this.getModelMatrix();
163
- for (const tileKey of this._baseVisibleTileKeys) {
164
- const tile = this._tileBuffer.getActiveTile(tileKey);
165
- if (!tile)
166
- continue;
167
- tile.draw(pMatrix, vMatrix, mMatrix, this._tilePriorities.get(tileKey) ?? 0);
168
- }
169
- for (const tileKey of this._fallbackVisibleTileKeys) {
170
- const tile = this._tileBuffer.getActiveTile(tileKey);
171
- if (!tile)
172
- continue;
173
- tile.draw(pMatrix, vMatrix, mMatrix, this._tilePriorities.get(tileKey) ?? 0, false);
174
- }
175
- for (const tileKey of this._visibleTileKeys) {
176
- const tile = this._tileBuffer.getActiveTile(tileKey);
177
- if (tile?.ready) {
178
- tile.draw(pMatrix, vMatrix, mMatrix, this._tilePriorities.get(tileKey) ?? 0);
179
- continue;
180
- }
181
- const targetCoord = this.parseTileKey(tileKey);
182
- if (targetCoord) {
183
- const ancestorTile = this.findBestAvailableAncestor(targetCoord);
184
- if (ancestorTile) {
185
- const ancestorMesh = this._ancestorMeshCache.getMesh(targetCoord, ancestorTile.coord, this._config.segmentsPerSide ?? 16);
186
- ancestorTile.drawRemapped(ancestorMesh, pMatrix, vMatrix, mMatrix);
187
- }
188
- }
189
- tile?.draw(pMatrix, vMatrix, mMatrix, this._tilePriorities.get(tileKey) ?? 0);
190
- }
191
- }
192
- evictCache() {
193
- const maxCachedTiles = this._config.maxCachedTiles ?? XYZLayer.DEFAULT_MAX_CACHED_TILES;
194
- this._tileBuffer.evictCached(maxCachedTiles);
195
- }
196
- disposeTiles() {
197
- this._tileBuffer.dispose();
198
- this._ancestorMeshCache.dispose();
199
- this._visibleTileKeys = [];
200
- this._fallbackVisibleTileKeys = [];
201
- this._baseVisibleTileKeys = [];
202
- }
203
- getTileKey(tileCoord) {
204
- return `${tileCoord.z}/${tileCoord.x}/${tileCoord.y}`;
205
- }
206
- parseTileKey(tileKey) {
207
- const [zRaw, xRaw, yRaw] = tileKey.split('/');
208
- const z = Number.parseInt(zRaw ?? '', 10);
209
- const x = Number.parseInt(xRaw ?? '', 10);
210
- const y = Number.parseInt(yRaw ?? '', 10);
211
- if (!Number.isFinite(z) || !Number.isFinite(x) || !Number.isFinite(y)) {
212
- return null;
213
- }
214
- return { z, x, y };
215
- }
216
- findBestAvailableAncestor(targetCoord) {
217
- for (let z = targetCoord.z - 1; z >= this._provider.minZoom; z--) {
218
- const dz = targetCoord.z - z;
219
- const ancestorCoord = {
220
- z,
221
- x: targetCoord.x >> dz,
222
- y: targetCoord.y >> dz,
223
- };
224
- const ancestor = this._tileBuffer.getAnyTile(this.getTileKey(ancestorCoord));
225
- if (ancestor?.ready) {
226
- return ancestor;
227
- }
228
- }
229
- return null;
230
- }
231
- }
@@ -1,29 +0,0 @@
1
- import { Point } from '../Point.js';
2
- import type { XYZLayerConfig, XYZTileCoord } from './types.js';
3
- type ViewCenterSpherical = {
4
- phi: number;
5
- theta: number;
6
- };
7
- export declare class XYZTileProvider {
8
- private _config;
9
- constructor(config: XYZLayerConfig);
10
- get config(): XYZLayerConfig;
11
- get minZoom(): number;
12
- get maxZoom(): number;
13
- getInitialTiles(): XYZTileCoord[];
14
- getTileUrl(tile: XYZTileCoord): string;
15
- resolveZoom(fovDeg: number): number;
16
- private clampZoom;
17
- private getEffectiveTileY;
18
- private getSubdomain;
19
- getVisibleTilesAtZoom(z: number, centerSphericalDeg: ViewCenterSpherical | null, fovPolygon: Point[], viewportSphericalSamples: ViewCenterSpherical[], padding?: number): XYZTileCoord[];
20
- tileFromSpherical(zoom: number, sphericalDeg: ViewCenterSpherical): XYZTileCoord;
21
- getNeighborTiles(tile: XYZTileCoord, ring?: number): XYZTileCoord[];
22
- deduplicateTiles(tiles: XYZTileCoord[]): XYZTileCoord[];
23
- private resolveViewCenter;
24
- private latToTileY;
25
- private wrapTileX;
26
- private normalizeLonAround;
27
- private clampTileY;
28
- }
29
- export {};