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
package/lib-esm/AstroSphere.js
CHANGED
|
@@ -1,20 +1,34 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
import {
|
|
14
|
-
import
|
|
15
|
-
import
|
|
16
|
-
import
|
|
17
|
-
import
|
|
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 { bootSetup } from "./Config.js";
|
|
14
|
+
import Camera from "./Camera.js";
|
|
15
|
+
import RayPickingUtils from "./utils/RayPickingUtils.js";
|
|
16
|
+
import global from "./Global.js";
|
|
17
|
+
import MouseHelper from "./utils/MouseHelper.js";
|
|
18
|
+
import { cartesianToSpherical, sphericalToAstroDeg, raDegToHMS, decDegToDMS, } from "./utils/Utils.js";
|
|
19
|
+
import { HiPS } from "./model/hips/HiPS.js";
|
|
20
|
+
import { PerspectiveMatrixManager } from "./utils/PerspectiveMatrixManager.js";
|
|
21
|
+
import { Point } from "./model/Point.js";
|
|
22
|
+
import { FoVUtils } from "./utils/FoVUtils.js";
|
|
23
|
+
import { EquatorialGrid } from "./model/grid/EquatorialGrid.js";
|
|
24
|
+
import { HealpixGrid } from "./model/grid/HealpixGrid.js";
|
|
25
|
+
import { CoordsType } from "./utils/CoordsType.js";
|
|
26
|
+
import ColorMaps from "./model/ColorMaps.js";
|
|
27
|
+
import { xyzTileRequestScheduler } from "./model/earth/XYZTileRequestScheduler.js";
|
|
28
|
+
import { WMTSAdapter } from "./model/earth/WMTSAdapter.js";
|
|
29
|
+
import { XYZMapDescriptor } from "./model/earth/XYZMapDescriptor.js";
|
|
30
|
+
import { XYZMap } from "./model/earth/XYZMap.js";
|
|
31
|
+
import { mat4, vec3, vec4 } from "gl-matrix";
|
|
18
32
|
/**
|
|
19
33
|
* AstroSphere — main WebGL scene controller (TS port)
|
|
20
34
|
*/
|
|
@@ -39,7 +53,7 @@ class AstroSphere {
|
|
|
39
53
|
pointerDownY = null;
|
|
40
54
|
pointerDownAt = 0;
|
|
41
55
|
_activeHiPS = null;
|
|
42
|
-
|
|
56
|
+
_activeXYZ2 = null;
|
|
43
57
|
_activeBaseLayer = null;
|
|
44
58
|
startup = true;
|
|
45
59
|
fov;
|
|
@@ -48,16 +62,21 @@ class AstroSphere {
|
|
|
48
62
|
_webgl;
|
|
49
63
|
_selectedColorMap;
|
|
50
64
|
_cameraStatusChanged = false;
|
|
65
|
+
lastCameraChangedAt = 0;
|
|
66
|
+
lastCameraMotionAt = 0;
|
|
51
67
|
lastHoveredSource = null;
|
|
52
68
|
lastHoveredCatalogue = null;
|
|
53
69
|
zoomSensitivity = 1.0;
|
|
70
|
+
lockedEastWestRaDeg = null;
|
|
71
|
+
lockedNorthSouthDecDeg = null;
|
|
72
|
+
keepCameraNorthUp = true;
|
|
54
73
|
constructor(canvas, webgl) {
|
|
55
|
-
console.log(
|
|
74
|
+
console.log("[AstroSphere] new instance for canvas", canvas.id);
|
|
56
75
|
// Keep global GL context (as in original JS)
|
|
57
76
|
this._webgl = webgl;
|
|
58
77
|
this.mouseHelper = new MouseHelper();
|
|
59
78
|
this.canvas = canvas;
|
|
60
|
-
const nativeColorMap =
|
|
79
|
+
const nativeColorMap = "native";
|
|
61
80
|
this._selectedColorMap = ColorMaps[nativeColorMap];
|
|
62
81
|
global.insideSphere = bootSetup.insideSphere;
|
|
63
82
|
this.initCamera();
|
|
@@ -105,20 +124,26 @@ class AstroSphere {
|
|
|
105
124
|
astroDeg: astroCoords,
|
|
106
125
|
sphericalDeg: sphericalCoords,
|
|
107
126
|
raHMS: raHMS,
|
|
108
|
-
decDMS: decDMS
|
|
127
|
+
decDMS: decDMS,
|
|
109
128
|
};
|
|
110
129
|
return this.centralPoinCoords;
|
|
111
130
|
}
|
|
112
131
|
updateLastMousePoint() {
|
|
113
|
-
const sphericalCoords = {
|
|
114
|
-
|
|
132
|
+
const sphericalCoords = {
|
|
133
|
+
phi: this.mouseHelper.phi,
|
|
134
|
+
theta: this.mouseHelper.theta,
|
|
135
|
+
};
|
|
136
|
+
const astroCoords = {
|
|
137
|
+
ra: this.mouseHelper.ra,
|
|
138
|
+
dec: this.mouseHelper.dec,
|
|
139
|
+
};
|
|
115
140
|
const raHMS = this.mouseHelper.raHMS;
|
|
116
141
|
const decDMS = this.mouseHelper.decDMS;
|
|
117
142
|
this.mousePointCoords = {
|
|
118
143
|
astroDeg: astroCoords,
|
|
119
144
|
sphericalDeg: sphericalCoords,
|
|
120
145
|
raHMS: raHMS,
|
|
121
|
-
decDMS: decDMS
|
|
146
|
+
decDMS: decDMS,
|
|
122
147
|
};
|
|
123
148
|
return this.mousePointCoords;
|
|
124
149
|
}
|
|
@@ -138,9 +163,6 @@ class AstroSphere {
|
|
|
138
163
|
computeZoomStep(currentFov, deltaY) {
|
|
139
164
|
const direction = deltaY < 0 ? -1 : 1;
|
|
140
165
|
const wheelScale = this.clamp(Math.abs(deltaY) / 120, AstroSphere.MIN_WHEEL_SCALE, AstroSphere.MAX_WHEEL_SCALE);
|
|
141
|
-
// Continuous wheel response:
|
|
142
|
-
// - broad FoV stays responsive without large jumps
|
|
143
|
-
// - narrow FoV keeps a usable floor to avoid the 0.1 -> 0.02 deg stall
|
|
144
166
|
const baseMagnitude = this.clamp(0.0012 + 0.0025 * Math.sqrt(Math.max(currentFov, 0)), 0.0012, 0.04);
|
|
145
167
|
return direction * baseMagnitude * wheelScale * this.zoomSensitivity;
|
|
146
168
|
}
|
|
@@ -150,6 +172,119 @@ class AstroSphere {
|
|
|
150
172
|
getZoomSensitivity() {
|
|
151
173
|
return this.zoomSensitivity;
|
|
152
174
|
}
|
|
175
|
+
filterRotationDeltaByAstroLocks(deltaX, deltaY) {
|
|
176
|
+
const lockEastWest = this._camera.isRotationLockedY();
|
|
177
|
+
const lockNorthSouth = this._camera.isRotationLockedX();
|
|
178
|
+
if (!lockEastWest && !lockNorthSouth) {
|
|
179
|
+
return { deltaX, deltaY };
|
|
180
|
+
}
|
|
181
|
+
const center = RayPickingUtils.getIntersectionPointWithSingleModel(this.canvas.clientWidth / 2, this.canvas.clientHeight / 2, this._healpixGrid, this._webgl, this._camera, this._perspectiveMatrixManager.pMatrix);
|
|
182
|
+
if (!center || center.length < 3) {
|
|
183
|
+
return { deltaX, deltaY };
|
|
184
|
+
}
|
|
185
|
+
const centerVec = vec3.normalize(vec3.create(), vec3.fromValues(center[0], center[1], center[2]));
|
|
186
|
+
const northAxis = vec3.fromValues(0, 0, 1);
|
|
187
|
+
const eastVec = vec3.cross(vec3.create(), northAxis, centerVec);
|
|
188
|
+
if (vec3.length(eastVec) < 1e-6) {
|
|
189
|
+
vec3.set(eastVec, 1, 0, 0);
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
vec3.normalize(eastVec, eastVec);
|
|
193
|
+
}
|
|
194
|
+
const northProjection = vec3.scale(vec3.create(), centerVec, vec3.dot(northAxis, centerVec));
|
|
195
|
+
const northVec = vec3.subtract(vec3.create(), northAxis, northProjection);
|
|
196
|
+
if (vec3.length(northVec) < 1e-6) {
|
|
197
|
+
vec3.cross(northVec, centerVec, eastVec);
|
|
198
|
+
}
|
|
199
|
+
vec3.normalize(northVec, northVec);
|
|
200
|
+
const eastScreen = this.projectModelDirectionToScreen(centerVec, eastVec);
|
|
201
|
+
const northScreen = this.projectModelDirectionToScreen(centerVec, northVec);
|
|
202
|
+
if (!eastScreen || !northScreen) {
|
|
203
|
+
return { deltaX, deltaY };
|
|
204
|
+
}
|
|
205
|
+
let nextDeltaX = deltaX;
|
|
206
|
+
let nextDeltaY = deltaY;
|
|
207
|
+
if (lockEastWest) {
|
|
208
|
+
const amount = nextDeltaX * eastScreen.x + nextDeltaY * eastScreen.y;
|
|
209
|
+
nextDeltaX -= amount * eastScreen.x;
|
|
210
|
+
nextDeltaY -= amount * eastScreen.y;
|
|
211
|
+
}
|
|
212
|
+
if (lockNorthSouth) {
|
|
213
|
+
const amount = nextDeltaX * northScreen.x + nextDeltaY * northScreen.y;
|
|
214
|
+
nextDeltaX -= amount * northScreen.x;
|
|
215
|
+
nextDeltaY -= amount * northScreen.y;
|
|
216
|
+
}
|
|
217
|
+
return {
|
|
218
|
+
deltaX: nextDeltaX,
|
|
219
|
+
deltaY: nextDeltaY,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
projectModelDirectionToScreen(centerModel, directionModel) {
|
|
223
|
+
const offsetModel = vec3.scaleAndAdd(vec3.create(), centerModel, directionModel, 0.01);
|
|
224
|
+
const centerScreen = this.projectModelPointToScreen(centerModel);
|
|
225
|
+
const offsetScreen = this.projectModelPointToScreen(offsetModel);
|
|
226
|
+
if (!centerScreen || !offsetScreen) {
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
const x = offsetScreen.x - centerScreen.x;
|
|
230
|
+
const y = offsetScreen.y - centerScreen.y;
|
|
231
|
+
const len = Math.hypot(x, y);
|
|
232
|
+
if (len < 1e-6) {
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
return { x: x / len, y: y / len };
|
|
236
|
+
}
|
|
237
|
+
projectModelPointToScreen(pointModel) {
|
|
238
|
+
const vMatrix = this._camera.getCameraMatrix();
|
|
239
|
+
const mMatrix = this._healpixGrid.getModelMatrix();
|
|
240
|
+
const mvMatrix = mat4.create();
|
|
241
|
+
const mvpMatrix = mat4.create();
|
|
242
|
+
mat4.multiply(mvMatrix, vMatrix, mMatrix);
|
|
243
|
+
mat4.multiply(mvpMatrix, this._perspectiveMatrixManager.pMatrix, mvMatrix);
|
|
244
|
+
const clip = vec4.fromValues(pointModel[0], pointModel[1], pointModel[2], 1);
|
|
245
|
+
vec4.transformMat4(clip, clip, mvpMatrix);
|
|
246
|
+
if (Math.abs(clip[3]) < 1e-6) {
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
249
|
+
return {
|
|
250
|
+
x: clip[0] / clip[3],
|
|
251
|
+
y: -(clip[1] / clip[3]),
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
enforceAstronomicalRotationLocks() {
|
|
255
|
+
if (this.lockedEastWestRaDeg == null &&
|
|
256
|
+
this.lockedNorthSouthDecDeg == null) {
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
const center = this.updateCentralPoint();
|
|
260
|
+
if (!center) {
|
|
261
|
+
return false;
|
|
262
|
+
}
|
|
263
|
+
const nextRa = this.lockedEastWestRaDeg ?? center.astroDeg.ra;
|
|
264
|
+
const nextDec = this.lockedNorthSouthDecDeg ?? center.astroDeg.dec;
|
|
265
|
+
const needsCorrection = Math.abs(nextRa - center.astroDeg.ra) > 1e-6 ||
|
|
266
|
+
Math.abs(nextDec - center.astroDeg.dec) > 1e-6;
|
|
267
|
+
if (!needsCorrection) {
|
|
268
|
+
return false;
|
|
269
|
+
}
|
|
270
|
+
this._camera.goTo(nextRa, nextDec);
|
|
271
|
+
this._perspectiveMatrixManager.computePerspectiveMatrix(this.canvas, this._camera, bootSetup.camera_fov_deg, bootSetup.camera_near_plane, global.insideSphere);
|
|
272
|
+
this.updateCentralPoint();
|
|
273
|
+
return true;
|
|
274
|
+
}
|
|
275
|
+
enforceCameraNorthUp() {
|
|
276
|
+
if (!this.keepCameraNorthUp) {
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
const center = this.updateCentralPoint();
|
|
280
|
+
if (!center) {
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
this._camera.goTo(center.astroDeg.ra, center.astroDeg.dec);
|
|
284
|
+
this._perspectiveMatrixManager.computePerspectiveMatrix(this.canvas, this._camera, bootSetup.camera_fov_deg, bootSetup.camera_near_plane, global.insideSphere);
|
|
285
|
+
this.updateCentralPoint();
|
|
286
|
+
return true;
|
|
287
|
+
}
|
|
153
288
|
emitCameraChanged(reason) {
|
|
154
289
|
// avoid dispatch before scene is ready
|
|
155
290
|
if (!this._activeHiPS)
|
|
@@ -161,7 +296,7 @@ class AstroSphere {
|
|
|
161
296
|
return;
|
|
162
297
|
// optional debug
|
|
163
298
|
// console.log('[AstroSphere] emit camera-changed:', reason);
|
|
164
|
-
this.canvas.dispatchEvent(new CustomEvent(
|
|
299
|
+
this.canvas.dispatchEvent(new CustomEvent("camera-changed", {
|
|
165
300
|
detail,
|
|
166
301
|
bubbles: true,
|
|
167
302
|
composed: true,
|
|
@@ -169,7 +304,7 @@ class AstroSphere {
|
|
|
169
304
|
}
|
|
170
305
|
addEventListeners(canvas) {
|
|
171
306
|
if (global.debug) {
|
|
172
|
-
console.log(
|
|
307
|
+
console.log("[AstroSphere::addEventListeners]");
|
|
173
308
|
}
|
|
174
309
|
const CLICK_MAX_DISTANCE_PX = 4;
|
|
175
310
|
const CLICK_MAX_DURATION_MS = 250;
|
|
@@ -199,7 +334,7 @@ class AstroSphere {
|
|
|
199
334
|
const handleMouseUp = (event) => {
|
|
200
335
|
canvas.releasePointerCapture(event.pointerId);
|
|
201
336
|
this.mouseDown = false;
|
|
202
|
-
document.body.style.cursor =
|
|
337
|
+
document.body.style.cursor = "auto";
|
|
203
338
|
if (event.button !== 0) {
|
|
204
339
|
event.preventDefault();
|
|
205
340
|
return false;
|
|
@@ -221,7 +356,7 @@ class AstroSphere {
|
|
|
221
356
|
const clickResult = cat.selectPrimarySourceFromClick(this.mouseHelper);
|
|
222
357
|
if (!clickResult?.sources.length)
|
|
223
358
|
continue;
|
|
224
|
-
this._webgl.canvas.dispatchEvent(new CustomEvent(
|
|
359
|
+
this._webgl.canvas.dispatchEvent(new CustomEvent("source-clicked", {
|
|
225
360
|
detail: {
|
|
226
361
|
source: clickResult.sources,
|
|
227
362
|
selectionState: clickResult.selectionState,
|
|
@@ -235,7 +370,7 @@ class AstroSphere {
|
|
|
235
370
|
const clickResult = fset.selectPrimaryFootprintFromClick(this.mouseHelper);
|
|
236
371
|
if (!clickResult?.footprints.length)
|
|
237
372
|
continue;
|
|
238
|
-
this._webgl.canvas.dispatchEvent(new CustomEvent(
|
|
373
|
+
this._webgl.canvas.dispatchEvent(new CustomEvent("footprint-clicked", {
|
|
239
374
|
detail: {
|
|
240
375
|
footprint: clickResult.footprints,
|
|
241
376
|
selectionState: clickResult.selectionState,
|
|
@@ -262,12 +397,16 @@ class AstroSphere {
|
|
|
262
397
|
if (!this._healpixGrid)
|
|
263
398
|
return;
|
|
264
399
|
if (this.mouseDown) {
|
|
265
|
-
document.body.style.cursor =
|
|
266
|
-
|
|
267
|
-
const
|
|
268
|
-
const
|
|
269
|
-
|
|
270
|
-
this.
|
|
400
|
+
document.body.style.cursor = "grab";
|
|
401
|
+
const dragDirection = global.insideSphere ? -1 : 1;
|
|
402
|
+
const dragSpeed = global.insideSphere ? 10.0 : 1;
|
|
403
|
+
const deltaX = (dragDirection * dragSpeed * (newX - (this.lastMouseX ?? newX)) * Math.PI) /
|
|
404
|
+
canvas.width;
|
|
405
|
+
const deltaY = (dragDirection * dragSpeed * (newY - (this.lastMouseY ?? newY)) * Math.PI) /
|
|
406
|
+
canvas.height;
|
|
407
|
+
const filteredDelta = this.filterRotationDeltaByAstroLocks(deltaX, deltaY);
|
|
408
|
+
this.inertiaX += 0.1 * filteredDelta.deltaX;
|
|
409
|
+
this.inertiaY += 0.1 * filteredDelta.deltaY;
|
|
271
410
|
this.updateCentralPoint();
|
|
272
411
|
}
|
|
273
412
|
else {
|
|
@@ -299,10 +438,11 @@ class AstroSphere {
|
|
|
299
438
|
// direction feels responsive instead of "buffered".
|
|
300
439
|
this.zoomInertia = 0;
|
|
301
440
|
this._camera.zoom(zoomStep);
|
|
441
|
+
this.lastCameraMotionAt = performance.now();
|
|
302
442
|
this.fov = this._healpixGrid.refreshFoV(this._camera, this._perspectiveMatrixManager.pMatrix);
|
|
303
443
|
this._camera.refreshFoV(this.fov.minFoV);
|
|
304
444
|
this._cameraStatusChanged = true;
|
|
305
|
-
this.emitCameraChanged(
|
|
445
|
+
this.emitCameraChanged("wheel");
|
|
306
446
|
event.preventDefault();
|
|
307
447
|
};
|
|
308
448
|
const handleContextMenu = (event) => {
|
|
@@ -320,7 +460,7 @@ class AstroSphere {
|
|
|
320
460
|
const pickResult = cat.getSourcesFromPointer(this.mouseHelper);
|
|
321
461
|
if (!pickResult?.sources.length)
|
|
322
462
|
continue;
|
|
323
|
-
this._webgl.canvas.dispatchEvent(new CustomEvent(
|
|
463
|
+
this._webgl.canvas.dispatchEvent(new CustomEvent("source-contextmenu", {
|
|
324
464
|
detail: {
|
|
325
465
|
source: pickResult.sources,
|
|
326
466
|
catalogue: cat,
|
|
@@ -336,7 +476,7 @@ class AstroSphere {
|
|
|
336
476
|
const pickResult = fset.getFootprintsFromPointer(this.mouseHelper);
|
|
337
477
|
if (!pickResult?.footprints.length)
|
|
338
478
|
continue;
|
|
339
|
-
this._webgl.canvas.dispatchEvent(new CustomEvent(
|
|
479
|
+
this._webgl.canvas.dispatchEvent(new CustomEvent("footprint-contextmenu", {
|
|
340
480
|
detail: {
|
|
341
481
|
footprint: pickResult.footprints,
|
|
342
482
|
footprintSet: fset,
|
|
@@ -356,40 +496,40 @@ class AstroSphere {
|
|
|
356
496
|
}
|
|
357
497
|
// console.log('[AstroSphere::onKeyDown] key=', evt.key)
|
|
358
498
|
switch (evt.key) {
|
|
359
|
-
case
|
|
499
|
+
case "1":
|
|
360
500
|
// Free camera
|
|
361
501
|
this._camera.clearRotationLock();
|
|
362
502
|
break;
|
|
363
|
-
case
|
|
503
|
+
case "2":
|
|
364
504
|
// Lock X axis rotation
|
|
365
505
|
this._camera.setRotationLock({ x: true, y: false, z: false });
|
|
366
506
|
break;
|
|
367
|
-
case
|
|
507
|
+
case "3":
|
|
368
508
|
// Lock Y axis rotation
|
|
369
509
|
this._camera.setRotationLock({ x: false, y: true, z: false });
|
|
370
510
|
break;
|
|
371
|
-
case
|
|
511
|
+
case "4":
|
|
372
512
|
// Lock Z axis rotation
|
|
373
513
|
this._camera.setRotationLock({ x: false, y: false, z: true });
|
|
374
514
|
break;
|
|
375
515
|
}
|
|
376
516
|
};
|
|
377
|
-
console.log(
|
|
517
|
+
console.log("[AstroSphere] registering pointer and wheel listeners on canvas");
|
|
378
518
|
canvas.onpointerdown = handleMouseDown;
|
|
379
519
|
canvas.onpointerup = handleMouseUp;
|
|
380
520
|
canvas.onpointermove = handleMouseMove;
|
|
381
521
|
canvas.onpointerleave = () => {
|
|
382
522
|
this.clearLastMousePoint();
|
|
383
523
|
this._cameraStatusChanged = true;
|
|
384
|
-
this.emitCameraChanged(
|
|
524
|
+
this.emitCameraChanged("pointerleave");
|
|
385
525
|
};
|
|
386
|
-
console.log(
|
|
387
|
-
canvas.addEventListener(
|
|
388
|
-
canvas.addEventListener(
|
|
389
|
-
console.log(
|
|
390
|
-
document.addEventListener(
|
|
526
|
+
console.log("[AstroSphere] adding wheel event listener with passive: false");
|
|
527
|
+
canvas.addEventListener("wheel", handleMouseWheel, { passive: false });
|
|
528
|
+
canvas.addEventListener("contextmenu", handleContextMenu);
|
|
529
|
+
console.log("[AstroSphere] registering global keydown listener on document");
|
|
530
|
+
document.addEventListener("keydown", onKeyDown, { capture: true });
|
|
391
531
|
}
|
|
392
|
-
// REVIEW THIS METHOD AND MOVE IT
|
|
532
|
+
// REVIEW THIS METHOD AND MOVE IT
|
|
393
533
|
getPhiThetaDeg(canvas) {
|
|
394
534
|
const rect = canvas.getBoundingClientRect();
|
|
395
535
|
const maxX = rect.width;
|
|
@@ -416,16 +556,21 @@ class AstroSphere {
|
|
|
416
556
|
}
|
|
417
557
|
activateHiPS(hipsDescriptor) {
|
|
418
558
|
this._activeHiPS = new HiPS(1, [0.0, 0.0, 0.0], 0, 0, hipsDescriptor, this._webgl, this._healpixGrid);
|
|
419
|
-
this._activeBaseLayer =
|
|
559
|
+
this._activeBaseLayer = "hips";
|
|
420
560
|
}
|
|
421
561
|
activateXYZ(config) {
|
|
422
|
-
this.
|
|
423
|
-
this._activeBaseLayer =
|
|
562
|
+
this.activateXYZ2(new XYZMapDescriptor(config.name ?? "XYZ Earth2 Layer", config.urlTemplate, config.minZoom ?? 0, config.maxZoom ?? 8, config.segmentsPerSide ?? 48, config.maxCachedTiles ?? 384, 8, config.urlResolver));
|
|
563
|
+
this._activeBaseLayer = "xyz";
|
|
564
|
+
}
|
|
565
|
+
activateXYZ2(config) {
|
|
566
|
+
this._activeXYZ2 = new XYZMap(1, [0.0, 0.0, 0.0], 0, 0, config, this._webgl);
|
|
567
|
+
this._activeBaseLayer = "xyz";
|
|
424
568
|
}
|
|
425
569
|
activateWMTS(config) {
|
|
426
570
|
const adapter = new WMTSAdapter(config);
|
|
427
|
-
|
|
428
|
-
this.
|
|
571
|
+
const xyzConfig = adapter.toXYZLayerConfig();
|
|
572
|
+
this._activeXYZ2 = new XYZMap(1, [0.0, 0.0, 0.0], 0, 0, new XYZMapDescriptor(config.layer ? `WMTS ${config.layer}` : "WMTS Earth2 Layer", xyzConfig.urlTemplate, xyzConfig.minZoom ?? 0, xyzConfig.maxZoom ?? 8, xyzConfig.segmentsPerSide ?? 48, xyzConfig.maxCachedTiles ?? 384, 8, xyzConfig.urlResolver), this._webgl);
|
|
573
|
+
this._activeBaseLayer = "xyz";
|
|
429
574
|
}
|
|
430
575
|
// Catalogue section
|
|
431
576
|
async showCatalogue(cat) {
|
|
@@ -435,7 +580,7 @@ class AstroSphere {
|
|
|
435
580
|
return cat;
|
|
436
581
|
}
|
|
437
582
|
deleteCatalogue(catalogue) {
|
|
438
|
-
this.activeCatalogues = this.activeCatalogues.filter(c => c !== catalogue);
|
|
583
|
+
this.activeCatalogues = this.activeCatalogues.filter((c) => c !== catalogue);
|
|
439
584
|
}
|
|
440
585
|
// End Catalogue section
|
|
441
586
|
// Footprint section
|
|
@@ -446,11 +591,11 @@ class AstroSphere {
|
|
|
446
591
|
return fset;
|
|
447
592
|
}
|
|
448
593
|
deleteFootprintSet(footprintSet) {
|
|
449
|
-
this.activeFootprintSets = this.activeFootprintSets.filter(fst => fst !== footprintSet);
|
|
594
|
+
this.activeFootprintSets = this.activeFootprintSets.filter((fst) => fst !== footprintSet);
|
|
450
595
|
}
|
|
451
596
|
getHoveredFootprints() {
|
|
452
597
|
let footprintsHovered = [];
|
|
453
|
-
this.activeFootprintSets.forEach(fset => {
|
|
598
|
+
this.activeFootprintSets.forEach((fset) => {
|
|
454
599
|
footprintsHovered.push(fset.hoveredFootprints);
|
|
455
600
|
});
|
|
456
601
|
return footprintsHovered;
|
|
@@ -459,7 +604,39 @@ class AstroSphere {
|
|
|
459
604
|
goTo(raDeg, decDeg) {
|
|
460
605
|
this._camera.goTo(raDeg, decDeg);
|
|
461
606
|
}
|
|
607
|
+
getActiveCoordinateMode() {
|
|
608
|
+
if (this._activeBaseLayer === "xyz") {
|
|
609
|
+
return "lonlat";
|
|
610
|
+
}
|
|
611
|
+
if (this._activeBaseLayer === "hips" && this._activeHiPS?.isGalacticHips) {
|
|
612
|
+
return "galactic";
|
|
613
|
+
}
|
|
614
|
+
return "equatorial";
|
|
615
|
+
}
|
|
616
|
+
resetAxesOrientation() {
|
|
617
|
+
const center = this.updateCentralPoint();
|
|
618
|
+
if (!center)
|
|
619
|
+
return;
|
|
620
|
+
this.inertiaX = 0;
|
|
621
|
+
this.inertiaY = 0;
|
|
622
|
+
this._camera.goTo(center.astroDeg.ra, center.astroDeg.dec);
|
|
623
|
+
this._perspectiveMatrixManager.computePerspectiveMatrix(this.canvas, this._camera, bootSetup.camera_fov_deg, bootSetup.camera_near_plane, global.insideSphere);
|
|
624
|
+
this.updateCentralPoint();
|
|
625
|
+
this._cameraStatusChanged = true;
|
|
626
|
+
}
|
|
627
|
+
setKeepCameraNorthUp(enabled) {
|
|
628
|
+
this.keepCameraNorthUp = enabled;
|
|
629
|
+
if (enabled) {
|
|
630
|
+
this.resetAxesOrientation();
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
isKeepCameraNorthUp() {
|
|
634
|
+
return this.keepCameraNorthUp;
|
|
635
|
+
}
|
|
462
636
|
getFoV() {
|
|
637
|
+
if (this._activeBaseLayer === "xyz" && this._activeXYZ2) {
|
|
638
|
+
return this._activeXYZ2.getFoV();
|
|
639
|
+
}
|
|
463
640
|
return this.fov;
|
|
464
641
|
}
|
|
465
642
|
getFoVPolygon() {
|
|
@@ -474,11 +651,15 @@ class AstroSphere {
|
|
|
474
651
|
this._camera.refreshFoV(this.fov.minFoV);
|
|
475
652
|
}
|
|
476
653
|
changeFoV2(deg) {
|
|
477
|
-
const newCameraPos = this._healpixGrid
|
|
654
|
+
const newCameraPos = this._healpixGrid
|
|
655
|
+
.getFoV()
|
|
656
|
+
.computeCameraPositionForFoV(deg);
|
|
478
657
|
this._camera.setCameraPosition(newCameraPos);
|
|
479
658
|
}
|
|
480
659
|
changeFoV3(deg) {
|
|
481
|
-
const newPos = this._healpixGrid
|
|
660
|
+
const newPos = this._healpixGrid
|
|
661
|
+
.getFoV()
|
|
662
|
+
.computeCameraPositionForAngularDiameter(deg);
|
|
482
663
|
this._camera.setCameraPosition(newPos);
|
|
483
664
|
// Recompute projection after moving the camera
|
|
484
665
|
this._perspectiveMatrixManager.computePerspectiveMatrix(this.canvas, this._camera, bootSetup.camera_fov_deg, bootSetup.camera_near_plane, false);
|
|
@@ -487,9 +668,22 @@ class AstroSphere {
|
|
|
487
668
|
return global.insideSphere;
|
|
488
669
|
}
|
|
489
670
|
toggleInsideSphere() {
|
|
671
|
+
const centerBeforeToggle = this.updateCentralPoint();
|
|
672
|
+
this.inertiaX = 0;
|
|
673
|
+
this.inertiaY = 0;
|
|
674
|
+
this.zoomInertia = 0;
|
|
490
675
|
global.insideSphere = !global.insideSphere;
|
|
491
676
|
// console.log(global.insideSphere)
|
|
492
677
|
this._camera.toggleInsideSphere();
|
|
678
|
+
this._camera.goTo(centerBeforeToggle.astroDeg.ra, centerBeforeToggle.astroDeg.dec);
|
|
679
|
+
this._perspectiveMatrixManager.computePerspectiveMatrix(this.canvas, this._camera, bootSetup.camera_fov_deg, bootSetup.camera_near_plane, global.insideSphere);
|
|
680
|
+
this.fov = this._healpixGrid.refreshFoV(this._camera, this._perspectiveMatrixManager.pMatrix);
|
|
681
|
+
this._camera.refreshFoV(this.fov.minFoV);
|
|
682
|
+
this.updateCentralPoint();
|
|
683
|
+
this.lastCameraMotionAt = performance.now();
|
|
684
|
+
this._cameraStatusChanged = true;
|
|
685
|
+
this.emitCameraChanged("inside-sphere-toggle");
|
|
686
|
+
requestAnimationFrame(() => this.draw(this.canvas));
|
|
493
687
|
}
|
|
494
688
|
// imposta posizione camera
|
|
495
689
|
setCameraPosition(pos) {
|
|
@@ -538,17 +732,18 @@ class AstroSphere {
|
|
|
538
732
|
centralPoint: new Point({ raDeg: centralradeg, decDeg: centraldecdeg }, CoordsType.ASTRO),
|
|
539
733
|
mouseHoverPoint: this.mousePointCoords,
|
|
540
734
|
colorMap: this._selectedColorMap,
|
|
541
|
-
getFoVPolygon:
|
|
735
|
+
getFoVPolygon: [],
|
|
542
736
|
};
|
|
543
737
|
return detail;
|
|
544
738
|
// }
|
|
545
739
|
// return null
|
|
546
740
|
}
|
|
547
741
|
changeColorMap(cm) {
|
|
548
|
-
if (!this._activeHiPS)
|
|
742
|
+
if (!this._activeHiPS && !this._activeXYZ2)
|
|
549
743
|
return;
|
|
550
744
|
this._selectedColorMap = cm;
|
|
551
745
|
this._activeHiPS?.changeColorMap(cm);
|
|
746
|
+
this._activeXYZ2?.changeColorMap(cm);
|
|
552
747
|
}
|
|
553
748
|
prevFov = 0;
|
|
554
749
|
prevCentralRaDeg = null;
|
|
@@ -557,21 +752,54 @@ class AstroSphere {
|
|
|
557
752
|
return this._activeHiPS;
|
|
558
753
|
}
|
|
559
754
|
get activeXYZ() {
|
|
560
|
-
return this.
|
|
755
|
+
return this._activeXYZ2;
|
|
756
|
+
}
|
|
757
|
+
isLonLatGridVisible() {
|
|
758
|
+
return this._activeXYZ2?.isLonLatGridVisible() ?? false;
|
|
759
|
+
}
|
|
760
|
+
toggleLonLatGrid() {
|
|
761
|
+
return this._activeXYZ2?.toggleLonLatGrid() ?? false;
|
|
762
|
+
}
|
|
763
|
+
setEastWestRotationLocked(locked) {
|
|
764
|
+
this._camera.setRotationLock({ y: locked });
|
|
765
|
+
if (locked)
|
|
766
|
+
this.inertiaX = 0;
|
|
767
|
+
this.lockedEastWestRaDeg = locked
|
|
768
|
+
? (this.updateCentralPoint()?.astroDeg.ra ?? null)
|
|
769
|
+
: null;
|
|
770
|
+
}
|
|
771
|
+
isEastWestRotationLocked() {
|
|
772
|
+
return this._camera.isRotationLockedY();
|
|
773
|
+
}
|
|
774
|
+
setNorthSouthRotationLocked(locked) {
|
|
775
|
+
this._camera.setRotationLock({ x: locked });
|
|
776
|
+
if (locked)
|
|
777
|
+
this.inertiaY = 0;
|
|
778
|
+
this.lockedNorthSouthDecDeg = locked
|
|
779
|
+
? (this.updateCentralPoint()?.astroDeg.dec ?? null)
|
|
780
|
+
: null;
|
|
781
|
+
}
|
|
782
|
+
isNorthSouthRotationLocked() {
|
|
783
|
+
return this._camera.isRotationLockedX();
|
|
561
784
|
}
|
|
562
785
|
getXYZDebugStats() {
|
|
563
786
|
return {
|
|
564
787
|
activeBaseLayer: this._activeBaseLayer,
|
|
565
|
-
layer: this.
|
|
788
|
+
layer: this._activeXYZ2?.getDebugStats() ?? null,
|
|
566
789
|
requests: xyzTileRequestScheduler.getDebugStats(),
|
|
567
790
|
};
|
|
568
791
|
}
|
|
792
|
+
getHiPSDebugStats() {
|
|
793
|
+
if (!this._activeHiPS)
|
|
794
|
+
return null;
|
|
795
|
+
return this._activeHiPS.getDebugStats();
|
|
796
|
+
}
|
|
569
797
|
draw(canvas) {
|
|
570
798
|
if (this._refreshingStatus)
|
|
571
799
|
return;
|
|
572
800
|
if (!this._webgl)
|
|
573
801
|
return;
|
|
574
|
-
if (!this._activeHiPS && !this.
|
|
802
|
+
if (!this._activeHiPS && !this._activeXYZ2)
|
|
575
803
|
return;
|
|
576
804
|
if (!this._healpixGrid || Object.keys(this._healpixGrid).length === 0)
|
|
577
805
|
return;
|
|
@@ -591,6 +819,7 @@ class AstroSphere {
|
|
|
591
819
|
if (Math.abs(this.zoomInertia) > 0.0001) {
|
|
592
820
|
this._camera.zoom(this.zoomInertia);
|
|
593
821
|
this.zoomInertia *= 0.95;
|
|
822
|
+
this.lastCameraMotionAt = performance.now();
|
|
594
823
|
this.fov = this._healpixGrid.refreshFoV(this._camera, this._perspectiveMatrixManager.pMatrix);
|
|
595
824
|
this._camera.refreshFoV(this.fov.minFoV);
|
|
596
825
|
if (this.prevFov !== this.fov.minFoV) {
|
|
@@ -606,19 +835,33 @@ class AstroSphere {
|
|
|
606
835
|
this._cameraStatusChanged = true;
|
|
607
836
|
}
|
|
608
837
|
// Rotation inertia
|
|
609
|
-
if (this.mouseDown ||
|
|
838
|
+
if (this.mouseDown ||
|
|
839
|
+
Math.abs(this.inertiaX) > 0.02 ||
|
|
840
|
+
Math.abs(this.inertiaY) > 0.02) {
|
|
610
841
|
cameraRotated = true;
|
|
611
|
-
|
|
612
|
-
PHI =
|
|
613
|
-
|
|
614
|
-
this.
|
|
842
|
+
const filteredInertia = this.filterRotationDeltaByAstroLocks(this.inertiaX, this.inertiaY);
|
|
843
|
+
PHI = filteredInertia.deltaX;
|
|
844
|
+
THETA = filteredInertia.deltaY;
|
|
845
|
+
this.inertiaX = filteredInertia.deltaX * 0.95;
|
|
846
|
+
this.inertiaY = filteredInertia.deltaY * 0.95;
|
|
615
847
|
this._camera.rotate(PHI, THETA);
|
|
848
|
+
this.lastCameraMotionAt = performance.now();
|
|
616
849
|
this._perspectiveMatrixManager.computePerspectiveMatrix(canvas, this._camera, bootSetup.camera_fov_deg, bootSetup.camera_near_plane, global.insideSphere);
|
|
850
|
+
const lockCorrected = this.enforceAstronomicalRotationLocks();
|
|
851
|
+
if (!lockCorrected) {
|
|
852
|
+
this.enforceCameraNorthUp();
|
|
853
|
+
}
|
|
617
854
|
}
|
|
618
855
|
else {
|
|
619
856
|
this.inertiaY = 0;
|
|
620
857
|
this.inertiaX = 0;
|
|
621
858
|
}
|
|
859
|
+
const nextFoV = this._healpixGrid.refreshFoV(this._camera, this._perspectiveMatrixManager.pMatrix);
|
|
860
|
+
if (Number.isFinite(nextFoV.minFoV) && nextFoV.minFoV > 0) {
|
|
861
|
+
this.fov = nextFoV;
|
|
862
|
+
this._camera.refreshFoV(this.fov.minFoV);
|
|
863
|
+
this.prevFov = this.fov.minFoV;
|
|
864
|
+
}
|
|
622
865
|
// Se la camera è ruotata (anche solo per inerzia), aggiorna punto centrale + emetti cameraChanged
|
|
623
866
|
if (cameraRotated) {
|
|
624
867
|
// Ricalcola il punto centrale
|
|
@@ -636,16 +879,20 @@ class AstroSphere {
|
|
|
636
879
|
}
|
|
637
880
|
}
|
|
638
881
|
if (this._cameraStatusChanged) {
|
|
639
|
-
const
|
|
882
|
+
const now = performance.now();
|
|
883
|
+
const shouldEmitCameraChanged = !this.mouseDown || now - this.lastCameraChangedAt > 100;
|
|
884
|
+
const detail = shouldEmitCameraChanged ? this.getCurrentStatus() : null;
|
|
640
885
|
if (detail) {
|
|
641
886
|
// console.log('[AstroSphere::draw] emitting camera-changed event due to camera status change', detail)
|
|
642
887
|
// console.log('[AstroSphere::draw] inertia', this.zoomInertia, this.inertiaX, this.inertiaY)
|
|
643
|
-
this.canvas.dispatchEvent(new CustomEvent(
|
|
888
|
+
this.canvas.dispatchEvent(new CustomEvent("camera-changed", {
|
|
644
889
|
detail,
|
|
645
|
-
bubbles: true,
|
|
890
|
+
bubbles: true,
|
|
891
|
+
composed: true,
|
|
646
892
|
}));
|
|
893
|
+
this.lastCameraChangedAt = now;
|
|
647
894
|
}
|
|
648
|
-
if (!this.startup) {
|
|
895
|
+
if (!this.startup && shouldEmitCameraChanged) {
|
|
649
896
|
this._cameraStatusChanged = false;
|
|
650
897
|
}
|
|
651
898
|
}
|
|
@@ -655,24 +902,40 @@ class AstroSphere {
|
|
|
655
902
|
this._webgl.enable(this._webgl.CULL_FACE);
|
|
656
903
|
this._webgl.cullFace(global.insideSphere ? this._webgl.FRONT : this._webgl.BACK);
|
|
657
904
|
this._webgl.blendFunc(this._webgl.SRC_ALPHA, this._webgl.ONE_MINUS_SRC_ALPHA);
|
|
658
|
-
if (this._activeBaseLayer ===
|
|
905
|
+
if (this._activeBaseLayer === "hips" && this._activeHiPS) {
|
|
659
906
|
const visibleOrder = Math.min(this._healpixGrid.visibleorder, this._activeHiPS.maxOrder);
|
|
660
907
|
this._healpixGrid.visibleTilesManager.computeVisiblePixels(visibleOrder, this._webgl, this._camera, this._perspectiveMatrixManager.pMatrix);
|
|
661
908
|
}
|
|
662
909
|
// DRAW HiPS
|
|
910
|
+
const stableFovDeg = this.fov?.minFoV ?? this._healpixGrid.getMinFoV();
|
|
911
|
+
const nowForGrid = performance.now();
|
|
912
|
+
const cameraMovingForGrid = this.mouseDown ||
|
|
913
|
+
Math.abs(this.zoomInertia) > 0.0001 ||
|
|
914
|
+
Math.abs(this.inertiaX) > 0.02 ||
|
|
915
|
+
Math.abs(this.inertiaY) > 0.02 ||
|
|
916
|
+
nowForGrid - this.lastCameraMotionAt < 220;
|
|
917
|
+
// const skyEntityDrawInput: SkyEntityDrawInput = {
|
|
918
|
+
// fovDeg: this._healpixGrid.getMinFoV(),
|
|
919
|
+
// camera: this._camera,
|
|
920
|
+
// pMatrix: this._perspectiveMatrixManager.pMatrix,
|
|
921
|
+
// centerSphericalDeg: this.updateCentralPoint().sphericalDeg,
|
|
922
|
+
// fovPolygon: this._activeBaseLayer === 'xyz' ? this.getFoVPolygon() : undefined,
|
|
923
|
+
// viewportSphericalSamples: this._activeBaseLayer === 'xyz' ? this.collectViewportSphericalSamples(7) : undefined,
|
|
924
|
+
// }
|
|
663
925
|
const skyEntityDrawInput = {
|
|
664
|
-
fovDeg:
|
|
926
|
+
fovDeg: stableFovDeg,
|
|
665
927
|
camera: this._camera,
|
|
666
928
|
pMatrix: this._perspectiveMatrixManager.pMatrix,
|
|
667
929
|
centerSphericalDeg: this.updateCentralPoint().sphericalDeg,
|
|
668
|
-
fovPolygon:
|
|
669
|
-
viewportSphericalSamples:
|
|
930
|
+
fovPolygon: undefined,
|
|
931
|
+
viewportSphericalSamples: undefined,
|
|
932
|
+
cameraMoving: cameraMovingForGrid,
|
|
670
933
|
};
|
|
671
|
-
if (this._activeBaseLayer ===
|
|
934
|
+
if (this._activeBaseLayer === "hips") {
|
|
672
935
|
this._activeHiPS?.draw(skyEntityDrawInput);
|
|
673
936
|
}
|
|
674
|
-
if (this._activeBaseLayer ===
|
|
675
|
-
this.
|
|
937
|
+
if (this._activeBaseLayer === "xyz") {
|
|
938
|
+
this._activeXYZ2?.draw(skyEntityDrawInput);
|
|
676
939
|
}
|
|
677
940
|
this._healpixGrid.draw(skyEntityDrawInput);
|
|
678
941
|
this._equatorialGrid.draw(skyEntityDrawInput);
|
|
@@ -684,24 +947,27 @@ class AstroSphere {
|
|
|
684
947
|
const raDecDeg = sphericalToAstroDeg(phiTheta.phi, phiTheta.theta);
|
|
685
948
|
const raHMS = raDegToHMS(raDecDeg.ra);
|
|
686
949
|
const decDMS = decDegToDMS(raDecDeg.dec);
|
|
687
|
-
this.prevFov = this._healpixGrid.getMinFoV();
|
|
950
|
+
// this.prevFov = this._healpixGrid.getMinFoV();
|
|
951
|
+
this.prevFov = this.fov?.minFoV ?? this._healpixGrid.getMinFoV();
|
|
688
952
|
this._cameraStatusChanged = true;
|
|
689
|
-
console.log(
|
|
953
|
+
console.log("(startup coords)", {
|
|
690
954
|
raDeg: raDecDeg.ra,
|
|
691
955
|
decDeg: raDecDeg.dec,
|
|
692
956
|
raHMS,
|
|
693
957
|
decDMS,
|
|
694
958
|
});
|
|
695
959
|
}
|
|
696
|
-
this.activeCatalogues.forEach(cat => {
|
|
697
|
-
const activeModelMatrix = this._activeHiPS?.getModelMatrix() ??
|
|
960
|
+
this.activeCatalogues.forEach((cat) => {
|
|
961
|
+
const activeModelMatrix = this._activeHiPS?.getModelMatrix() ??
|
|
962
|
+
this._activeXYZ2?.getModelMatrix();
|
|
698
963
|
if (activeModelMatrix) {
|
|
699
964
|
cat.draw(activeModelMatrix, this.mouseHelper, this._camera.getCameraMatrix(), this._perspectiveMatrixManager.pMatrix);
|
|
700
965
|
}
|
|
701
966
|
});
|
|
702
967
|
this.emitHoveredSourceIfChanged();
|
|
703
|
-
this.activeFootprintSets.forEach(fst => {
|
|
704
|
-
const activeModelMatrix = this._activeHiPS?.getModelMatrix() ??
|
|
968
|
+
this.activeFootprintSets.forEach((fst) => {
|
|
969
|
+
const activeModelMatrix = this._activeHiPS?.getModelMatrix() ??
|
|
970
|
+
this._activeXYZ2?.getModelMatrix();
|
|
705
971
|
if (activeModelMatrix) {
|
|
706
972
|
fst.draw(activeModelMatrix, this.mouseHelper, this._camera.getCameraMatrix(), this._perspectiveMatrixManager.pMatrix);
|
|
707
973
|
}
|
|
@@ -718,13 +984,13 @@ class AstroSphere {
|
|
|
718
984
|
nextHoveredCatalogue = cat;
|
|
719
985
|
break;
|
|
720
986
|
}
|
|
721
|
-
const unchanged = nextHoveredSource === this.lastHoveredSource
|
|
722
|
-
|
|
987
|
+
const unchanged = nextHoveredSource === this.lastHoveredSource &&
|
|
988
|
+
nextHoveredCatalogue === this.lastHoveredCatalogue;
|
|
723
989
|
if (unchanged)
|
|
724
990
|
return;
|
|
725
991
|
this.lastHoveredSource = nextHoveredSource;
|
|
726
992
|
this.lastHoveredCatalogue = nextHoveredCatalogue;
|
|
727
|
-
this._webgl.canvas.dispatchEvent(new CustomEvent(
|
|
993
|
+
this._webgl.canvas.dispatchEvent(new CustomEvent("source-hovered", {
|
|
728
994
|
detail: { source: nextHoveredSource, catalogue: nextHoveredCatalogue },
|
|
729
995
|
bubbles: true,
|
|
730
996
|
composed: true,
|