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.
- package/dist/astroviewer.cjs +3082 -1410
- package/dist/astroviewer.js +1 -1
- package/dist/astroviewer.min.js +1 -1
- package/lib-esm/AstroSphere.d.ts +40 -16
- package/lib-esm/AstroSphere.js +359 -93
- package/lib-esm/AstroViewer.d.ts +20 -5
- package/lib-esm/AstroViewer.js +50 -0
- package/lib-esm/Camera.js +28 -14
- package/lib-esm/Config.d.ts +2 -0
- package/lib-esm/Config.js +15 -1
- package/lib-esm/Global.js +12 -0
- package/lib-esm/index.d.ts +8 -4
- package/lib-esm/index.js +17 -3
- package/lib-esm/model/AbstractSkyEntity.d.ts +1 -0
- package/lib-esm/model/AbstractSkyEntity.js +12 -0
- package/lib-esm/model/AstroGL.js +12 -0
- package/lib-esm/model/ColorMaps.js +12 -0
- package/lib-esm/model/MetadataColumn.js +12 -0
- package/lib-esm/model/MetadataManager.d.ts +1 -0
- package/lib-esm/model/MetadataManager.js +16 -1
- package/lib-esm/model/Point.d.ts +9 -1
- package/lib-esm/model/Point.js +30 -0
- package/lib-esm/model/Point2D.js +12 -0
- package/lib-esm/model/Source.js +12 -0
- package/lib-esm/model/SphereFoV.d.ts +30 -0
- package/lib-esm/model/SphereFoV.js +196 -0
- package/lib-esm/model/catalogues/CatalogueGL.js +12 -0
- package/lib-esm/model/catalogues/CatalogueProps.js +13 -1
- package/lib-esm/model/earth/{wmts/WMTSAdapter.d.ts → WMTSAdapter.d.ts} +2 -1
- package/lib-esm/model/earth/{wmts/WMTSAdapter.js → WMTSAdapter.js} +12 -0
- package/lib-esm/model/earth/XYZAnchestorTile.d.ts +17 -0
- package/lib-esm/model/earth/XYZAnchestorTile.js +87 -0
- package/lib-esm/model/earth/{types.d.ts → XYZConfig.d.ts} +6 -17
- package/lib-esm/model/earth/XYZConfig.js +13 -0
- package/lib-esm/model/earth/XYZFoVHelper.d.ts +12 -0
- package/lib-esm/model/earth/XYZFoVHelper.js +138 -0
- package/lib-esm/model/earth/XYZMap.d.ts +31 -0
- package/lib-esm/model/earth/XYZMap.js +208 -0
- package/lib-esm/model/earth/XYZMapDescriptor.d.ts +29 -0
- package/lib-esm/model/earth/XYZMapDescriptor.js +77 -0
- package/lib-esm/model/earth/XYZMeshBuilder.d.ts +1 -1
- package/lib-esm/model/earth/XYZMeshBuilder.js +13 -2
- package/lib-esm/model/earth/XYZTile.d.ts +20 -21
- package/lib-esm/model/earth/XYZTile.js +82 -102
- package/lib-esm/model/earth/XYZTileBuffer.d.ts +24 -26
- package/lib-esm/model/earth/XYZTileBuffer.js +60 -70
- package/lib-esm/model/earth/XYZTileRequestScheduler.d.ts +1 -1
- package/lib-esm/model/earth/XYZTileRequestScheduler.js +13 -2
- package/lib-esm/model/earth/XYZTypes.d.ts +24 -0
- package/lib-esm/model/earth/XYZTypes.js +13 -0
- package/lib-esm/model/earth/XYZVisibleTilesManager.d.ts +16 -27
- package/lib-esm/model/earth/XYZVisibleTilesManager.js +61 -192
- package/lib-esm/model/footprints/Footprint.d.ts +4 -1
- package/lib-esm/model/footprints/Footprint.js +30 -2
- package/lib-esm/model/footprints/FootprintProps.js +13 -1
- package/lib-esm/model/footprints/FootprintSetGL.d.ts +4 -2
- package/lib-esm/model/footprints/FootprintSetGL.js +21 -6
- package/lib-esm/model/grid/EquatorialGrid.d.ts +2 -1
- package/lib-esm/model/grid/EquatorialGrid.js +30 -12
- package/lib-esm/model/grid/GridTextHelper.d.ts +10 -19
- package/lib-esm/model/grid/GridTextHelper.js +70 -67
- package/lib-esm/model/grid/HealpixGrid.d.ts +4 -4
- package/lib-esm/model/grid/HealpixGrid.js +24 -8
- package/lib-esm/model/grid/LonLatGrid.d.ts +43 -0
- package/lib-esm/model/grid/LonLatGrid.js +309 -0
- package/lib-esm/model/hips/AllSky.js +12 -0
- package/lib-esm/model/hips/AncestorTile.js +12 -0
- package/lib-esm/model/hips/FoVHelper.d.ts +5 -2
- package/lib-esm/model/hips/FoVHelper.js +52 -3
- package/lib-esm/model/hips/HiPS.d.ts +2 -0
- package/lib-esm/model/hips/HiPS.js +38 -14
- package/lib-esm/model/hips/HiPSConfig.d.ts +13 -0
- package/lib-esm/model/hips/HiPSDescriptor.js +12 -0
- package/lib-esm/model/hips/Tile.d.ts +1 -0
- package/lib-esm/model/hips/Tile.js +15 -0
- package/lib-esm/model/hips/TileBuffer.d.ts +5 -0
- package/lib-esm/model/hips/TileBuffer.js +61 -0
- package/lib-esm/model/hips/VisibleTilesManager.js +12 -0
- package/lib-esm/model/tap/TapMetadata.js +12 -0
- package/lib-esm/model/tap/TapMetadataList.js +12 -0
- package/lib-esm/model/tap/TapRepo.js +12 -0
- package/lib-esm/model/terra/TerraFootprintSetGL.d.ts +6 -0
- package/lib-esm/model/terra/TerraFootprintSetGL.js +54 -0
- package/lib-esm/model/terra/TerraPointSetGL.js +12 -0
- package/lib-esm/services/SesameService.js +11 -3
- package/lib-esm/services/helpers.js +12 -0
- package/lib-esm/services/hipsNodeService.js +12 -0
- package/lib-esm/services/parse-hipslist.js +12 -0
- package/lib-esm/services/queryCatalogueByFoV.js +13 -1
- package/lib-esm/services/queryFootprintSetByFov.js +13 -1
- package/lib-esm/services/tapRepoService.js +13 -1
- package/lib-esm/services/types.js +12 -0
- package/lib-esm/shader/CatalogueShaderProgram.js +12 -0
- package/lib-esm/shader/FootprintShaderProgram.js +12 -0
- package/lib-esm/shader/GridShaderManager.js +12 -0
- package/lib-esm/shader/HiPSShaderProgram.js +12 -0
- package/lib-esm/shader/ShaderManager.js +12 -1
- package/lib-esm/shader/ShaderManagerMutliHiPS.js +12 -1
- package/lib-esm/shader/XYZShaderProgram.d.ts +14 -1
- package/lib-esm/shader/XYZShaderProgram.js +127 -2
- package/lib-esm/utils/CoordsType.d.ts +2 -1
- package/lib-esm/utils/CoordsType.js +13 -0
- package/lib-esm/utils/FoVUtils.js +12 -0
- package/lib-esm/utils/GeoJSONParser.d.ts +19 -0
- package/lib-esm/utils/GeoJSONParser.js +112 -0
- package/lib-esm/utils/GeomUtils.js +12 -0
- package/lib-esm/utils/MouseHelper.js +12 -0
- package/lib-esm/utils/PerspectiveMatrixManager.js +16 -1
- package/lib-esm/utils/RayPickingUtils.js +12 -0
- package/lib-esm/utils/STCSParser.d.ts +7 -3
- package/lib-esm/utils/STCSParser.js +27 -9
- package/lib-esm/utils/ShaderUtility.js +13 -1
- package/lib-esm/utils/Utils.js +12 -0
- package/lib-esm/utils/XYZRayPickingUtils.d.ts +27 -0
- package/lib-esm/utils/XYZRayPickingUtils.js +226 -0
- package/package.json +2 -2
- package/lib-esm/model/FoV.d.ts +0 -62
- package/lib-esm/model/FoV.js +0 -274
- package/lib-esm/model/earth/XYZAncestorMeshCache.d.ts +0 -10
- package/lib-esm/model/earth/XYZAncestorMeshCache.js +0 -31
- package/lib-esm/model/earth/XYZLayer.d.ts +0 -31
- package/lib-esm/model/earth/XYZLayer.js +0 -231
- package/lib-esm/model/earth/XYZTileProvider.d.ts +0 -29
- package/lib-esm/model/earth/XYZTileProvider.js +0 -187
- package/lib-esm/model/earth/wmts/types.d.ts +0 -1
- package/lib-esm/model/earth/wmts/types.js +0 -1
- /package/lib-esm/model/{earth/types.js → hips/HiPSConfig.js} +0 -0
|
@@ -0,0 +1,196 @@
|
|
|
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 { mat4, vec3 } from 'gl-matrix';
|
|
14
|
+
import { radToDeg } from '../utils/Utils.js';
|
|
15
|
+
export class SphereFoV {
|
|
16
|
+
static MIN_FOV_DEG = 1e-6;
|
|
17
|
+
fovXDeg = 180;
|
|
18
|
+
fovYDeg = 180;
|
|
19
|
+
ratio = 0;
|
|
20
|
+
_minFoV = 180;
|
|
21
|
+
_webgl;
|
|
22
|
+
_lastModel = null;
|
|
23
|
+
_lastCamera = null;
|
|
24
|
+
constructor(webgl) {
|
|
25
|
+
this._webgl = webgl;
|
|
26
|
+
}
|
|
27
|
+
getFoV(insideSphere, model, camera, pMatrix) {
|
|
28
|
+
this._lastModel = model;
|
|
29
|
+
this._lastCamera = camera;
|
|
30
|
+
const canvas = this._webgl.canvas;
|
|
31
|
+
if (!canvas) {
|
|
32
|
+
this.fovXDeg = 180;
|
|
33
|
+
this.fovYDeg = 180;
|
|
34
|
+
this._minFoV = this.minFoV;
|
|
35
|
+
return this;
|
|
36
|
+
}
|
|
37
|
+
const rect = canvas.getBoundingClientRect();
|
|
38
|
+
const canvasWidth = rect.width;
|
|
39
|
+
const canvasHeight = rect.height;
|
|
40
|
+
this.fovXDeg = this.computeAngle(0, canvasHeight / 2, insideSphere, model, camera, pMatrix).angleDeg;
|
|
41
|
+
this.fovYDeg = this.computeAngle(canvasWidth / 2, 0, insideSphere, model, camera, pMatrix).angleDeg;
|
|
42
|
+
this._minFoV = this.minFoV;
|
|
43
|
+
this.ratio = this.computeRatio(camera);
|
|
44
|
+
return this;
|
|
45
|
+
}
|
|
46
|
+
computeRatio(camera) {
|
|
47
|
+
const pos = camera.getCameraPosition();
|
|
48
|
+
const distanceFromCenter = Math.sqrt(pos[0] * pos[0] + pos[1] * pos[1] + pos[2] * pos[2]);
|
|
49
|
+
return distanceFromCenter / this.fovYDeg;
|
|
50
|
+
}
|
|
51
|
+
get minFoV() {
|
|
52
|
+
const minFov = this.fovYDeg <= this.fovXDeg ? this.fovYDeg : this.fovXDeg;
|
|
53
|
+
this._minFoV = Math.max(minFov, SphereFoV.MIN_FOV_DEG);
|
|
54
|
+
return this._minFoV;
|
|
55
|
+
}
|
|
56
|
+
get xFoV() {
|
|
57
|
+
return this.fovXDeg;
|
|
58
|
+
}
|
|
59
|
+
get yFoV() {
|
|
60
|
+
return this.fovYDeg;
|
|
61
|
+
}
|
|
62
|
+
computeDistanceFromAngle(angleDeg) {
|
|
63
|
+
return angleDeg * this.ratio;
|
|
64
|
+
}
|
|
65
|
+
changeMinFov(deg) {
|
|
66
|
+
if (this.fovYDeg <= this.fovXDeg) {
|
|
67
|
+
this.fovYDeg = deg;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
this.fovXDeg = deg;
|
|
71
|
+
}
|
|
72
|
+
this.minFoV;
|
|
73
|
+
}
|
|
74
|
+
computeCameraPositionForMinFoV(targetMinFoVDeg) {
|
|
75
|
+
return this.computeCameraPositionForFoV(targetMinFoVDeg);
|
|
76
|
+
}
|
|
77
|
+
computeCameraPositionForFoV(targetFoVDeg) {
|
|
78
|
+
return this.computeCameraPositionForAngularDiameter(targetFoVDeg);
|
|
79
|
+
}
|
|
80
|
+
computeCameraPositionForAngularDiameter(targetAngularDiameterDeg) {
|
|
81
|
+
if (!this._lastModel || !this._lastCamera) {
|
|
82
|
+
return [0, 0, 0];
|
|
83
|
+
}
|
|
84
|
+
const eps = 1e-6;
|
|
85
|
+
const clamped = Math.max(eps, Math.min(180 - eps, targetAngularDiameterDeg));
|
|
86
|
+
const halfRad = (clamped * Math.PI) / 360.0;
|
|
87
|
+
const sinHalf = Math.sin(halfRad);
|
|
88
|
+
if (sinHalf <= 0) {
|
|
89
|
+
return [0, 0, 0];
|
|
90
|
+
}
|
|
91
|
+
const model = this._lastModel;
|
|
92
|
+
const camera = this._lastCamera;
|
|
93
|
+
const targetDistance = Math.max(model.radius / sinHalf, model.radius + 1e-4);
|
|
94
|
+
const camPos = camera.getCameraPosition();
|
|
95
|
+
const direction = vec3.fromValues(camPos[0] - model.center[0], camPos[1] - model.center[1], camPos[2] - model.center[2]);
|
|
96
|
+
if (vec3.length(direction) < eps) {
|
|
97
|
+
vec3.set(direction, 0, 0, 1);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
vec3.normalize(direction, direction);
|
|
101
|
+
}
|
|
102
|
+
return [
|
|
103
|
+
model.center[0] + direction[0] * targetDistance,
|
|
104
|
+
model.center[1] + direction[1] * targetDistance,
|
|
105
|
+
model.center[2] + direction[2] * targetDistance,
|
|
106
|
+
];
|
|
107
|
+
}
|
|
108
|
+
computeAngle(canvasX, canvasY, insideSphere, model, camera, pMatrix) {
|
|
109
|
+
const canvas = this._webgl.canvas;
|
|
110
|
+
const rect = canvas.getBoundingClientRect();
|
|
111
|
+
const centerHit = this.getIntersectionPointWithModel(rect.width / 2, rect.height / 2, model, camera, pMatrix);
|
|
112
|
+
const edgeHit = this.getIntersectionPointWithModel(canvasX, canvasY, model, camera, pMatrix);
|
|
113
|
+
if (!centerHit || !edgeHit) {
|
|
114
|
+
return { angleDeg: 180, distance: -1 };
|
|
115
|
+
}
|
|
116
|
+
const angleDeg = 2 * this.computeAngularDistanceDeg(centerHit.point, edgeHit.point);
|
|
117
|
+
return {
|
|
118
|
+
angleDeg,
|
|
119
|
+
distance: edgeHit.distance,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
computeAngularDistanceDeg(a, b) {
|
|
123
|
+
const aNorm = vec3.normalize(vec3.create(), a);
|
|
124
|
+
const bNorm = vec3.normalize(vec3.create(), b);
|
|
125
|
+
const dot = vec3.dot(aNorm, bNorm);
|
|
126
|
+
const cross = vec3.cross(vec3.create(), aNorm, bNorm);
|
|
127
|
+
const angleRad = Math.atan2(vec3.length(cross), Math.min(1, Math.max(-1, dot)));
|
|
128
|
+
return radToDeg(angleRad);
|
|
129
|
+
}
|
|
130
|
+
getIntersectionPointWithModel(mouseX, mouseY, model, camera, pMatrix) {
|
|
131
|
+
const rayWorld = this.getRayFromMouse(mouseX, mouseY, pMatrix, camera.getCameraMatrix());
|
|
132
|
+
const distance = this.raySphere(camera.getCameraPosition(), rayWorld, model);
|
|
133
|
+
if (distance < 0) {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
const worldHit = vec3.create();
|
|
137
|
+
vec3.scale(worldHit, rayWorld, distance);
|
|
138
|
+
vec3.add(worldHit, camera.getCameraPosition(), worldHit);
|
|
139
|
+
const worldHit4 = [worldHit[0], worldHit[1], worldHit[2], 1.0];
|
|
140
|
+
const modelHit4 = [0, 0, 0, 0];
|
|
141
|
+
this.mat4MultiplyVec4(model.getModelMatrixInverse(), worldHit4, modelHit4);
|
|
142
|
+
return {
|
|
143
|
+
point: vec3.fromValues(modelHit4[0], modelHit4[1], modelHit4[2]),
|
|
144
|
+
distance,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
getRayFromMouse(mouseX, mouseY, pMatrix, vMatrix) {
|
|
148
|
+
const gl = this._webgl;
|
|
149
|
+
const canvas = gl.canvas;
|
|
150
|
+
const rect = canvas.getBoundingClientRect();
|
|
151
|
+
const x = (2.0 * mouseX) / rect.width - 1.0;
|
|
152
|
+
const y = 1.0 - (2.0 * mouseY) / rect.height;
|
|
153
|
+
const rayClip = [x, y, -1.0, 1.0];
|
|
154
|
+
const pInv = mat4.create();
|
|
155
|
+
mat4.invert(pInv, pMatrix);
|
|
156
|
+
const rayEye4 = [0, 0, 0, 0];
|
|
157
|
+
this.mat4MultiplyVec4(pInv, rayClip, rayEye4);
|
|
158
|
+
const rayEye = [rayEye4[0], rayEye4[1], -1.0, 0.0];
|
|
159
|
+
const vInv = mat4.create();
|
|
160
|
+
mat4.invert(vInv, vMatrix);
|
|
161
|
+
const rayWorld4 = [0, 0, 0, 0];
|
|
162
|
+
this.mat4MultiplyVec4(vInv, rayEye, rayWorld4);
|
|
163
|
+
const rayWorld = vec3.fromValues(rayWorld4[0], rayWorld4[1], rayWorld4[2]);
|
|
164
|
+
vec3.normalize(rayWorld, rayWorld);
|
|
165
|
+
return rayWorld;
|
|
166
|
+
}
|
|
167
|
+
raySphere(rayOrigWorld, rayDirectionWorld, sphere) {
|
|
168
|
+
let intersectionDistance = -1;
|
|
169
|
+
const L = vec3.create();
|
|
170
|
+
vec3.subtract(L, rayOrigWorld, sphere.center);
|
|
171
|
+
const b = vec3.dot(rayDirectionWorld, L);
|
|
172
|
+
const c = vec3.dot(L, L) - sphere.radius * sphere.radius;
|
|
173
|
+
const disc = b * b - c;
|
|
174
|
+
if (disc > 0.0) {
|
|
175
|
+
const s = Math.sqrt(disc);
|
|
176
|
+
const ta = -b + s;
|
|
177
|
+
const tb = -b - s;
|
|
178
|
+
if (ta >= 0.0 || tb >= 0.0) {
|
|
179
|
+
intersectionDistance = tb < 0.0 ? ta : Math.min(ta, tb);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
else if (disc === 0.0) {
|
|
183
|
+
const t = -b;
|
|
184
|
+
if (t >= 0.0) {
|
|
185
|
+
intersectionDistance = t;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return intersectionDistance;
|
|
189
|
+
}
|
|
190
|
+
mat4MultiplyVec4(m, v, out) {
|
|
191
|
+
out[0] = m[0] * v[0] + m[4] * v[1] + m[8] * v[2] + m[12] * v[3];
|
|
192
|
+
out[1] = m[1] * v[0] + m[5] * v[1] + m[9] * v[2] + m[13] * v[3];
|
|
193
|
+
out[2] = m[2] * v[0] + m[6] * v[1] + m[10] * v[2] + m[14] * v[3];
|
|
194
|
+
out[3] = m[3] * v[0] + m[7] * v[1] + m[11] * v[2] + m[15] * v[3];
|
|
195
|
+
}
|
|
196
|
+
}
|
|
@@ -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
|
import { Source } from '../Source.js';
|
|
2
14
|
import { Point } from '../Point.js';
|
|
3
15
|
import { CoordsType } from '../..//utils/CoordsType.js';
|
|
@@ -1,6 +1,18 @@
|
|
|
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
14
|
// // CatalogueProps.ts
|
|
2
15
|
// type UCD = string | undefined;
|
|
3
|
-
export {};
|
|
4
16
|
// import {Metadata} from "../tap/TapMetadata.js";
|
|
5
17
|
// import {TapMetadataList} from "../tap/TapMetadataList.js";
|
|
6
18
|
// function colName(col?: Metadata): string | undefined {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { WMTSLayerConfig, XYZLayerConfig
|
|
1
|
+
import type { WMTSLayerConfig, XYZLayerConfig } from './XYZConfig.js';
|
|
2
|
+
import type { XYZTileCoord } from './XYZTypes.js';
|
|
2
3
|
export declare class WMTSAdapter {
|
|
3
4
|
private _config;
|
|
4
5
|
constructor(config: WMTSLayerConfig);
|
|
@@ -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
|
function replaceTokens(template, values) {
|
|
2
14
|
return Object.entries(values).reduce((result, [key, value]) => result.replace(new RegExp(`\\{${key}\\}`, 'g'), value), template);
|
|
3
15
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { XYZShaderProgram } from '../../shader/XYZShaderProgram.js';
|
|
2
|
+
import { XYZMeshBuilder } from './XYZMeshBuilder.js';
|
|
3
|
+
import { XYZTile } from './XYZTile.js';
|
|
4
|
+
import type { XYZTileCoord } from './XYZTypes.js';
|
|
5
|
+
type Mat4 = Float32Array;
|
|
6
|
+
export declare class XYZAnchestorTile extends XYZTile {
|
|
7
|
+
private _ancestorMeshBuilder;
|
|
8
|
+
private _ancestorWebgl;
|
|
9
|
+
private _segmentsPerSide;
|
|
10
|
+
private _meshCache;
|
|
11
|
+
constructor(coord: XYZTileCoord, url: string, webgl: WebGL2RenderingContext, shaderProgram: XYZShaderProgram, meshBuilder?: XYZMeshBuilder, segmentsPerSide?: number);
|
|
12
|
+
draw(pMatrixOrVisibleZoom: Mat4 | number, vMatrixOrVisibleTiles: Mat4 | XYZTileCoord[], mMatrixOrAncestorsMap: Mat4 | Map<string, XYZTileCoord>, colorMapIdxOrPMatrix: number | Mat4, vMatrix?: Mat4, mMatrix?: Mat4, colorMapIdx?: number): boolean;
|
|
13
|
+
dispose(): void;
|
|
14
|
+
private getRemappedMesh;
|
|
15
|
+
private isAncestorOf;
|
|
16
|
+
}
|
|
17
|
+
export { XYZAnchestorTile as XYZAncestorTile };
|
|
@@ -0,0 +1,87 @@
|
|
|
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';
|
|
14
|
+
import { XYZTile } from './XYZTile.js';
|
|
15
|
+
export class XYZAnchestorTile extends XYZTile {
|
|
16
|
+
_ancestorMeshBuilder;
|
|
17
|
+
_ancestorWebgl;
|
|
18
|
+
_segmentsPerSide;
|
|
19
|
+
_meshCache = new Map();
|
|
20
|
+
constructor(coord, url, webgl, shaderProgram, meshBuilder = new XYZMeshBuilder(), segmentsPerSide = 16) {
|
|
21
|
+
super(coord, url, webgl, shaderProgram, meshBuilder, segmentsPerSide);
|
|
22
|
+
this._ancestorMeshBuilder = meshBuilder;
|
|
23
|
+
this._ancestorWebgl = webgl;
|
|
24
|
+
this._segmentsPerSide = segmentsPerSide;
|
|
25
|
+
}
|
|
26
|
+
draw(pMatrixOrVisibleZoom, vMatrixOrVisibleTiles, mMatrixOrAncestorsMap, colorMapIdxOrPMatrix, vMatrix, mMatrix, colorMapIdx) {
|
|
27
|
+
if (typeof pMatrixOrVisibleZoom !== 'number') {
|
|
28
|
+
return super.draw(pMatrixOrVisibleZoom, vMatrixOrVisibleTiles, mMatrixOrAncestorsMap, colorMapIdxOrPMatrix);
|
|
29
|
+
}
|
|
30
|
+
if (!vMatrix || !mMatrix || colorMapIdx === undefined) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
const visibleZoom = pMatrixOrVisibleZoom;
|
|
34
|
+
const visibleTiles = vMatrixOrVisibleTiles;
|
|
35
|
+
const ancestorsMap = mMatrixOrAncestorsMap;
|
|
36
|
+
const pMatrix = colorMapIdxOrPMatrix;
|
|
37
|
+
let drawn = false;
|
|
38
|
+
if (visibleZoom <= this.coord.z) {
|
|
39
|
+
return super.draw(pMatrix, vMatrix, mMatrix, colorMapIdx);
|
|
40
|
+
}
|
|
41
|
+
for (const targetTile of visibleTiles) {
|
|
42
|
+
if (!this.isAncestorOf(targetTile)) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const ancestorKey = `${this.coord.z}/${this.coord.x}/${this.coord.y}`;
|
|
46
|
+
if (!ancestorsMap.has(ancestorKey)) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
const mesh = this.getRemappedMesh(targetTile);
|
|
50
|
+
drawn = super.drawRemapped(mesh, pMatrix, vMatrix, mMatrix, colorMapIdx) || drawn;
|
|
51
|
+
}
|
|
52
|
+
return drawn;
|
|
53
|
+
}
|
|
54
|
+
dispose() {
|
|
55
|
+
for (const mesh of this._meshCache.values()) {
|
|
56
|
+
if (mesh.positionBuffer)
|
|
57
|
+
this._ancestorWebgl.deleteBuffer(mesh.positionBuffer);
|
|
58
|
+
if (mesh.uvBuffer)
|
|
59
|
+
this._ancestorWebgl.deleteBuffer(mesh.uvBuffer);
|
|
60
|
+
if (mesh.indexBuffer)
|
|
61
|
+
this._ancestorWebgl.deleteBuffer(mesh.indexBuffer);
|
|
62
|
+
}
|
|
63
|
+
this._meshCache.clear();
|
|
64
|
+
super.dispose();
|
|
65
|
+
}
|
|
66
|
+
getRemappedMesh(targetTile) {
|
|
67
|
+
const key = `${targetTile.z}/${targetTile.x}/${targetTile.y}->${this.coord.z}/${this.coord.x}/${this.coord.y}`;
|
|
68
|
+
const existing = this._meshCache.get(key);
|
|
69
|
+
if (existing) {
|
|
70
|
+
return existing;
|
|
71
|
+
}
|
|
72
|
+
const mesh = this._ancestorMeshBuilder.buildAncestorMesh(targetTile, this.coord, this._segmentsPerSide);
|
|
73
|
+
const uploaded = this._ancestorMeshBuilder.uploadMesh(mesh, this._ancestorWebgl);
|
|
74
|
+
this._meshCache.set(key, uploaded);
|
|
75
|
+
return uploaded;
|
|
76
|
+
}
|
|
77
|
+
isAncestorOf(targetTile) {
|
|
78
|
+
if (targetTile.z <= this.coord.z) {
|
|
79
|
+
return targetTile.z === this.coord.z
|
|
80
|
+
&& targetTile.x === this.coord.x
|
|
81
|
+
&& targetTile.y === this.coord.y;
|
|
82
|
+
}
|
|
83
|
+
const dz = targetTile.z - this.coord.z;
|
|
84
|
+
return (targetTile.x >> dz) === this.coord.x && (targetTile.y >> dz) === this.coord.y;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
export { XYZAnchestorTile as XYZAncestorTile };
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import type { XYZTileCoord } from './XYZTypes.js';
|
|
1
2
|
export type XYZLayerConfig = {
|
|
2
3
|
urlTemplate: string;
|
|
4
|
+
name?: string;
|
|
3
5
|
minZoom?: number;
|
|
4
6
|
maxZoom?: number;
|
|
5
7
|
segmentsPerSide?: number;
|
|
@@ -27,6 +29,10 @@ export type XYZLayerDebugStats = {
|
|
|
27
29
|
coarseTileCount: number;
|
|
28
30
|
hasPendingSelection: boolean;
|
|
29
31
|
pendingSelectionKey: string | null;
|
|
32
|
+
hipsName?: string;
|
|
33
|
+
hipsUrl?: string;
|
|
34
|
+
isGalactic?: boolean;
|
|
35
|
+
currentOrder?: number | null;
|
|
30
36
|
};
|
|
31
37
|
export type XYZRequestBackoffDebugEntry = {
|
|
32
38
|
host: string;
|
|
@@ -46,23 +52,6 @@ export type XYZDebugStats = {
|
|
|
46
52
|
layer: XYZLayerDebugStats | null;
|
|
47
53
|
requests: XYZRequestSchedulerDebugStats;
|
|
48
54
|
};
|
|
49
|
-
export type XYZTileCoord = {
|
|
50
|
-
z: number;
|
|
51
|
-
x: number;
|
|
52
|
-
y: number;
|
|
53
|
-
};
|
|
54
|
-
export type XYZTileMesh = {
|
|
55
|
-
positions: Float32Array;
|
|
56
|
-
uvs: Float32Array;
|
|
57
|
-
indices: Uint16Array | Uint32Array;
|
|
58
|
-
};
|
|
59
|
-
export type XYZTileGpuMesh = {
|
|
60
|
-
positionBuffer: WebGLBuffer | null;
|
|
61
|
-
uvBuffer: WebGLBuffer | null;
|
|
62
|
-
indexBuffer: WebGLBuffer | null;
|
|
63
|
-
indexCount: number;
|
|
64
|
-
indexType: number;
|
|
65
|
-
};
|
|
66
55
|
export type WMTSRequestEncoding = 'kvp' | 'rest';
|
|
67
56
|
export type WMTSLayerConfig = {
|
|
68
57
|
baseUrl: string;
|
|
@@ -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 {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
declare class XYZFoVHelper {
|
|
2
|
+
private static readonly LEVEL_HYSTERESIS;
|
|
3
|
+
private static readonly ZOOM_MIN_FOV;
|
|
4
|
+
getZoom(fov: number, currentZoom?: number): number;
|
|
5
|
+
private getRawZoom;
|
|
6
|
+
getLonLatSteps(fov: number, coarse?: boolean): {
|
|
7
|
+
lonStep: number;
|
|
8
|
+
latStep: number;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export declare const xyzFovHelper: XYZFoVHelper;
|
|
12
|
+
export default XYZFoVHelper;
|
|
@@ -0,0 +1,138 @@
|
|
|
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
|
+
// FoVHelper.ts
|
|
14
|
+
'use strict';
|
|
15
|
+
class XYZFoVHelper {
|
|
16
|
+
static LEVEL_HYSTERESIS = 0.12;
|
|
17
|
+
static ZOOM_MIN_FOV = {
|
|
18
|
+
2: 179,
|
|
19
|
+
3: 90,
|
|
20
|
+
4: 30,
|
|
21
|
+
5: 20,
|
|
22
|
+
6: 6,
|
|
23
|
+
7: 3.2,
|
|
24
|
+
8: 1.6,
|
|
25
|
+
9: 0.85,
|
|
26
|
+
10: 0.42,
|
|
27
|
+
11: 0.21,
|
|
28
|
+
12: 0.12,
|
|
29
|
+
13: 0.06,
|
|
30
|
+
14: 0.015,
|
|
31
|
+
15: 0,
|
|
32
|
+
};
|
|
33
|
+
getZoom(fov, currentZoom) {
|
|
34
|
+
const rawZoom = this.getRawZoom(fov);
|
|
35
|
+
if (currentZoom === undefined || currentZoom === rawZoom)
|
|
36
|
+
return rawZoom;
|
|
37
|
+
if (rawZoom > currentZoom) {
|
|
38
|
+
const boundary = XYZFoVHelper.ZOOM_MIN_FOV[currentZoom];
|
|
39
|
+
if (boundary > 0 && fov > boundary * (1 - XYZFoVHelper.LEVEL_HYSTERESIS))
|
|
40
|
+
return currentZoom;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
const boundary = XYZFoVHelper.ZOOM_MIN_FOV[rawZoom];
|
|
44
|
+
if (boundary > 0 && fov < boundary * (1 + XYZFoVHelper.LEVEL_HYSTERESIS))
|
|
45
|
+
return currentZoom;
|
|
46
|
+
}
|
|
47
|
+
return rawZoom;
|
|
48
|
+
}
|
|
49
|
+
getRawZoom(fov) {
|
|
50
|
+
if (fov >= 179)
|
|
51
|
+
return 2;
|
|
52
|
+
if (fov >= 90)
|
|
53
|
+
return 3;
|
|
54
|
+
if (fov >= 30)
|
|
55
|
+
return 4;
|
|
56
|
+
if (fov >= 20)
|
|
57
|
+
return 5;
|
|
58
|
+
if (fov >= 6)
|
|
59
|
+
return 6;
|
|
60
|
+
if (fov >= 3.2)
|
|
61
|
+
return 7;
|
|
62
|
+
if (fov >= 1.6)
|
|
63
|
+
return 8;
|
|
64
|
+
if (fov >= 0.85)
|
|
65
|
+
return 9;
|
|
66
|
+
if (fov >= 0.42)
|
|
67
|
+
return 10;
|
|
68
|
+
if (fov >= 0.21)
|
|
69
|
+
return 11;
|
|
70
|
+
if (fov >= 0.12)
|
|
71
|
+
return 12;
|
|
72
|
+
if (fov >= 0.06)
|
|
73
|
+
return 13;
|
|
74
|
+
if (fov >= 0.015)
|
|
75
|
+
return 14;
|
|
76
|
+
return 15;
|
|
77
|
+
}
|
|
78
|
+
// used in grid drawing
|
|
79
|
+
getLonLatSteps(fov, coarse = false) {
|
|
80
|
+
let lonStep;
|
|
81
|
+
let latStep;
|
|
82
|
+
if (coarse && fov < 0.21) {
|
|
83
|
+
lonStep = 10;
|
|
84
|
+
latStep = 10;
|
|
85
|
+
}
|
|
86
|
+
else if (fov >= 179) {
|
|
87
|
+
lonStep = 10;
|
|
88
|
+
latStep = 10;
|
|
89
|
+
}
|
|
90
|
+
else if (fov >= 25) {
|
|
91
|
+
lonStep = 9;
|
|
92
|
+
latStep = 9;
|
|
93
|
+
}
|
|
94
|
+
else if (fov >= 12.5) {
|
|
95
|
+
lonStep = 8;
|
|
96
|
+
latStep = 8;
|
|
97
|
+
}
|
|
98
|
+
else if (fov >= 6) {
|
|
99
|
+
lonStep = 6;
|
|
100
|
+
latStep = 6;
|
|
101
|
+
}
|
|
102
|
+
else if (fov >= 3.2) {
|
|
103
|
+
lonStep = 5;
|
|
104
|
+
latStep = 5;
|
|
105
|
+
}
|
|
106
|
+
else if (fov >= 1.6) {
|
|
107
|
+
lonStep = 4;
|
|
108
|
+
latStep = 4;
|
|
109
|
+
}
|
|
110
|
+
else if (fov >= 0.85) {
|
|
111
|
+
lonStep = 3;
|
|
112
|
+
latStep = 3;
|
|
113
|
+
}
|
|
114
|
+
else if (fov >= 0.42) {
|
|
115
|
+
lonStep = 2;
|
|
116
|
+
latStep = 2;
|
|
117
|
+
}
|
|
118
|
+
else if (fov >= 0.21) {
|
|
119
|
+
lonStep = 1;
|
|
120
|
+
latStep = 1;
|
|
121
|
+
}
|
|
122
|
+
else if (fov >= 0.12) {
|
|
123
|
+
lonStep = 0.5;
|
|
124
|
+
latStep = 0.5;
|
|
125
|
+
}
|
|
126
|
+
else if (fov >= 0.06) {
|
|
127
|
+
lonStep = 0.25;
|
|
128
|
+
latStep = 0.25;
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
lonStep = 10;
|
|
132
|
+
latStep = 10;
|
|
133
|
+
}
|
|
134
|
+
return { lonStep, latStep };
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
export const xyzFovHelper = new XYZFoVHelper();
|
|
138
|
+
export default XYZFoVHelper;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { AbstractSkyEntity, SkyEntityDrawInput } from "../AbstractSkyEntity.js";
|
|
2
|
+
import { XYZMapDescriptor } from "./XYZMapDescriptor.js";
|
|
3
|
+
import { ColorMap } from "../ColorMaps.js";
|
|
4
|
+
import { SphereFoV } from "../SphereFoV.js";
|
|
5
|
+
import type { XYZLayerDebugStats } from "./XYZConfig.js";
|
|
6
|
+
export declare class XYZMap extends AbstractSkyEntity {
|
|
7
|
+
private _xyzShaderProgram;
|
|
8
|
+
private _descriptor;
|
|
9
|
+
private _visibleTilesManager;
|
|
10
|
+
private _tileBuffer;
|
|
11
|
+
private _meshBuilder;
|
|
12
|
+
private _baseurl;
|
|
13
|
+
private _zoom;
|
|
14
|
+
private _latLonGrid;
|
|
15
|
+
private _colorMapIdx;
|
|
16
|
+
private _colorMap;
|
|
17
|
+
constructor(radius: number, position: [number, number, number], xrad: number, yrad: number, descriptor: XYZMapDescriptor, webgl: WebGL2RenderingContext);
|
|
18
|
+
changeColorMap(colorMap: ColorMap): void;
|
|
19
|
+
private initShaders;
|
|
20
|
+
isLonLatGridVisible(): boolean;
|
|
21
|
+
toggleLonLatGrid(): boolean;
|
|
22
|
+
getFoV(): SphereFoV;
|
|
23
|
+
private refresh;
|
|
24
|
+
draw(input: SkyEntityDrawInput): void;
|
|
25
|
+
private createTile;
|
|
26
|
+
private getTilesToEnsure;
|
|
27
|
+
private findBestAvailableAncestor;
|
|
28
|
+
private resolveTileUrl;
|
|
29
|
+
getDebugStats(): XYZLayerDebugStats;
|
|
30
|
+
private tileKey;
|
|
31
|
+
}
|