astro-viewer 3.1.0 → 3.2.1
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 +713 -204
- package/dist/astroviewer.js +1 -1
- package/dist/astroviewer.min.js +1 -1
- package/lib-esm/AstroSphere.d.ts +19 -15
- package/lib-esm/AstroSphere.js +170 -94
- package/lib-esm/AstroViewer.d.ts +2 -0
- package/lib-esm/AstroViewer.js +3 -0
- package/lib-esm/Camera.js +4 -6
- package/lib-esm/Config.d.ts +2 -0
- package/lib-esm/Config.js +3 -1
- package/lib-esm/index.d.ts +2 -0
- package/lib-esm/index.js +1 -0
- package/lib-esm/model/AbstractSkyEntity.d.ts +1 -0
- package/lib-esm/model/MetadataManager.d.ts +1 -0
- package/lib-esm/model/MetadataManager.js +4 -1
- package/lib-esm/model/Point.d.ts +9 -1
- package/lib-esm/model/Point.js +18 -0
- package/lib-esm/model/SphereFoV.js +4 -3
- package/lib-esm/model/earth/XYZConfig.d.ts +4 -0
- package/lib-esm/model/earth/XYZFoVHelper.d.ts +5 -2
- package/lib-esm/model/earth/XYZFoVHelper.js +40 -3
- package/lib-esm/model/footprints/Footprint.d.ts +4 -1
- package/lib-esm/model/footprints/Footprint.js +18 -2
- package/lib-esm/model/footprints/FootprintSetGL.d.ts +4 -2
- package/lib-esm/model/footprints/FootprintSetGL.js +9 -6
- package/lib-esm/model/grid/EquatorialGrid.d.ts +2 -1
- package/lib-esm/model/grid/EquatorialGrid.js +10 -6
- package/lib-esm/model/grid/HealpixGrid.js +5 -2
- package/lib-esm/model/grid/LonLatGrid.d.ts +3 -0
- package/lib-esm/model/grid/LonLatGrid.js +61 -10
- package/lib-esm/model/hips/FoVHelper.d.ts +5 -2
- package/lib-esm/model/hips/FoVHelper.js +40 -3
- package/lib-esm/model/hips/HiPS.d.ts +2 -0
- package/lib-esm/model/hips/HiPS.js +26 -5
- package/lib-esm/model/hips/HiPSConfig.d.ts +13 -0
- package/lib-esm/model/hips/HiPSConfig.js +1 -0
- package/lib-esm/model/hips/Tile.d.ts +1 -0
- package/lib-esm/model/hips/Tile.js +3 -0
- package/lib-esm/model/hips/TileBuffer.d.ts +5 -0
- package/lib-esm/model/hips/TileBuffer.js +49 -0
- package/lib-esm/model/terra/TerraFootprintSetGL.d.ts +6 -0
- package/lib-esm/model/terra/TerraFootprintSetGL.js +42 -0
- package/lib-esm/utils/CoordsType.d.ts +2 -1
- package/lib-esm/utils/CoordsType.js +1 -0
- package/lib-esm/utils/GeoJSONParser.d.ts +19 -0
- package/lib-esm/utils/GeoJSONParser.js +112 -0
- package/lib-esm/utils/PerspectiveMatrixManager.js +4 -1
- package/lib-esm/utils/STCSParser.d.ts +7 -3
- package/lib-esm/utils/STCSParser.js +15 -9
- package/package.json +3 -2
package/lib-esm/AstroSphere.d.ts
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import Camera from
|
|
2
|
-
import { AstroCoords, HMS, SphericalCoords, DMS } from
|
|
3
|
-
import { HiPS } from
|
|
4
|
-
import { HiPSDescriptor } from
|
|
5
|
-
import { SphereFoV } from
|
|
6
|
-
import { Point } from
|
|
7
|
-
import { CatalogueGL } from
|
|
8
|
-
import { FootprintSetGL, HoveredFootprintDetail } from
|
|
9
|
-
import { EquatorialGrid } from
|
|
10
|
-
import { HealpixGrid } from
|
|
11
|
-
import { ColorMap } from
|
|
12
|
-
import type { WMTSLayerConfig, XYZDebugStats, XYZLayerConfig } from
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
1
|
+
import Camera from "./Camera.js";
|
|
2
|
+
import { AstroCoords, HMS, SphericalCoords, DMS } from "./utils/Utils.js";
|
|
3
|
+
import { HiPS } from "./model/hips/HiPS.js";
|
|
4
|
+
import { HiPSDescriptor } from "./model/hips/HiPSDescriptor.js";
|
|
5
|
+
import { SphereFoV } from "./model/SphereFoV.js";
|
|
6
|
+
import { Point } from "./model/Point.js";
|
|
7
|
+
import { CatalogueGL } from "./model/catalogues/CatalogueGL.js";
|
|
8
|
+
import { FootprintSetGL, HoveredFootprintDetail } from "./model/footprints/FootprintSetGL.js";
|
|
9
|
+
import { EquatorialGrid } from "./model/grid/EquatorialGrid.js";
|
|
10
|
+
import { HealpixGrid } from "./model/grid/HealpixGrid.js";
|
|
11
|
+
import { ColorMap } from "./model/ColorMaps.js";
|
|
12
|
+
import type { WMTSLayerConfig, XYZDebugStats, XYZLayerConfig } from "./model/earth/XYZConfig.js";
|
|
13
|
+
import type { HiPSDebugStats } from "./model/hips/HiPSConfig.js";
|
|
14
|
+
import { XYZMapDescriptor } from "./model/earth/XYZMapDescriptor.js";
|
|
15
|
+
import { XYZMap } from "./model/earth/XYZMap.js";
|
|
15
16
|
export type PointCoordinates = {
|
|
16
17
|
astroDeg: AstroCoords;
|
|
17
18
|
raHMS: HMS;
|
|
@@ -66,6 +67,8 @@ declare class AstroSphere {
|
|
|
66
67
|
private _webgl;
|
|
67
68
|
private _selectedColorMap;
|
|
68
69
|
private _cameraStatusChanged;
|
|
70
|
+
private lastCameraChangedAt;
|
|
71
|
+
private lastCameraMotionAt;
|
|
69
72
|
private lastHoveredSource;
|
|
70
73
|
private lastHoveredCatalogue;
|
|
71
74
|
private zoomSensitivity;
|
|
@@ -107,7 +110,7 @@ declare class AstroSphere {
|
|
|
107
110
|
deleteFootprintSet(footprintSet: FootprintSetGL): void;
|
|
108
111
|
getHoveredFootprints(): HoveredFootprintDetail[];
|
|
109
112
|
goTo(raDeg: number, decDeg: number): void;
|
|
110
|
-
getActiveCoordinateMode():
|
|
113
|
+
getActiveCoordinateMode(): "equatorial" | "galactic" | "lonlat";
|
|
111
114
|
resetAxesOrientation(): void;
|
|
112
115
|
setKeepCameraNorthUp(enabled: boolean): void;
|
|
113
116
|
isKeepCameraNorthUp(): boolean;
|
|
@@ -136,6 +139,7 @@ declare class AstroSphere {
|
|
|
136
139
|
setNorthSouthRotationLocked(locked: boolean): void;
|
|
137
140
|
isNorthSouthRotationLocked(): boolean;
|
|
138
141
|
getXYZDebugStats(): XYZDebugStats;
|
|
142
|
+
getHiPSDebugStats(): HiPSDebugStats | null;
|
|
139
143
|
draw(canvas: HTMLCanvasElement): void;
|
|
140
144
|
private emitHoveredSourceIfChanged;
|
|
141
145
|
}
|
package/lib-esm/AstroSphere.js
CHANGED
|
@@ -10,25 +10,25 @@
|
|
|
10
10
|
*
|
|
11
11
|
* See LICENSE.md, LICENSE-COMMERCIAL.md, and LICENSE-NONCOMMERCIAL.md for details.
|
|
12
12
|
*/
|
|
13
|
-
import { bootSetup } from
|
|
14
|
-
import Camera from
|
|
15
|
-
import RayPickingUtils from
|
|
16
|
-
import global from
|
|
17
|
-
import MouseHelper from
|
|
18
|
-
import { cartesianToSpherical, sphericalToAstroDeg, raDegToHMS, decDegToDMS, } from
|
|
19
|
-
import { HiPS } from
|
|
20
|
-
import { PerspectiveMatrixManager } from
|
|
21
|
-
import { Point } from
|
|
22
|
-
import { FoVUtils } from
|
|
23
|
-
import { EquatorialGrid } from
|
|
24
|
-
import { HealpixGrid } from
|
|
25
|
-
import { CoordsType } from
|
|
26
|
-
import ColorMaps from
|
|
27
|
-
import { xyzTileRequestScheduler } from
|
|
28
|
-
import { WMTSAdapter } from
|
|
29
|
-
import { XYZMapDescriptor } from
|
|
30
|
-
import { XYZMap } from
|
|
31
|
-
import { mat4, vec3, vec4 } from
|
|
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";
|
|
32
32
|
/**
|
|
33
33
|
* AstroSphere — main WebGL scene controller (TS port)
|
|
34
34
|
*/
|
|
@@ -62,19 +62,21 @@ class AstroSphere {
|
|
|
62
62
|
_webgl;
|
|
63
63
|
_selectedColorMap;
|
|
64
64
|
_cameraStatusChanged = false;
|
|
65
|
+
lastCameraChangedAt = 0;
|
|
66
|
+
lastCameraMotionAt = 0;
|
|
65
67
|
lastHoveredSource = null;
|
|
66
68
|
lastHoveredCatalogue = null;
|
|
67
69
|
zoomSensitivity = 1.0;
|
|
68
70
|
lockedEastWestRaDeg = null;
|
|
69
71
|
lockedNorthSouthDecDeg = null;
|
|
70
|
-
keepCameraNorthUp =
|
|
72
|
+
keepCameraNorthUp = true;
|
|
71
73
|
constructor(canvas, webgl) {
|
|
72
|
-
console.log(
|
|
74
|
+
console.log("[AstroSphere] new instance for canvas", canvas.id);
|
|
73
75
|
// Keep global GL context (as in original JS)
|
|
74
76
|
this._webgl = webgl;
|
|
75
77
|
this.mouseHelper = new MouseHelper();
|
|
76
78
|
this.canvas = canvas;
|
|
77
|
-
const nativeColorMap =
|
|
79
|
+
const nativeColorMap = "native";
|
|
78
80
|
this._selectedColorMap = ColorMaps[nativeColorMap];
|
|
79
81
|
global.insideSphere = bootSetup.insideSphere;
|
|
80
82
|
this.initCamera();
|
|
@@ -122,20 +124,26 @@ class AstroSphere {
|
|
|
122
124
|
astroDeg: astroCoords,
|
|
123
125
|
sphericalDeg: sphericalCoords,
|
|
124
126
|
raHMS: raHMS,
|
|
125
|
-
decDMS: decDMS
|
|
127
|
+
decDMS: decDMS,
|
|
126
128
|
};
|
|
127
129
|
return this.centralPoinCoords;
|
|
128
130
|
}
|
|
129
131
|
updateLastMousePoint() {
|
|
130
|
-
const sphericalCoords = {
|
|
131
|
-
|
|
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
|
+
};
|
|
132
140
|
const raHMS = this.mouseHelper.raHMS;
|
|
133
141
|
const decDMS = this.mouseHelper.decDMS;
|
|
134
142
|
this.mousePointCoords = {
|
|
135
143
|
astroDeg: astroCoords,
|
|
136
144
|
sphericalDeg: sphericalCoords,
|
|
137
145
|
raHMS: raHMS,
|
|
138
|
-
decDMS: decDMS
|
|
146
|
+
decDMS: decDMS,
|
|
139
147
|
};
|
|
140
148
|
return this.mousePointCoords;
|
|
141
149
|
}
|
|
@@ -155,9 +163,6 @@ class AstroSphere {
|
|
|
155
163
|
computeZoomStep(currentFov, deltaY) {
|
|
156
164
|
const direction = deltaY < 0 ? -1 : 1;
|
|
157
165
|
const wheelScale = this.clamp(Math.abs(deltaY) / 120, AstroSphere.MIN_WHEEL_SCALE, AstroSphere.MAX_WHEEL_SCALE);
|
|
158
|
-
// Continuous wheel response:
|
|
159
|
-
// - broad FoV stays responsive without large jumps
|
|
160
|
-
// - narrow FoV keeps a usable floor to avoid the 0.1 -> 0.02 deg stall
|
|
161
166
|
const baseMagnitude = this.clamp(0.0012 + 0.0025 * Math.sqrt(Math.max(currentFov, 0)), 0.0012, 0.04);
|
|
162
167
|
return direction * baseMagnitude * wheelScale * this.zoomSensitivity;
|
|
163
168
|
}
|
|
@@ -247,7 +252,8 @@ class AstroSphere {
|
|
|
247
252
|
};
|
|
248
253
|
}
|
|
249
254
|
enforceAstronomicalRotationLocks() {
|
|
250
|
-
if (this.lockedEastWestRaDeg == null &&
|
|
255
|
+
if (this.lockedEastWestRaDeg == null &&
|
|
256
|
+
this.lockedNorthSouthDecDeg == null) {
|
|
251
257
|
return false;
|
|
252
258
|
}
|
|
253
259
|
const center = this.updateCentralPoint();
|
|
@@ -290,7 +296,7 @@ class AstroSphere {
|
|
|
290
296
|
return;
|
|
291
297
|
// optional debug
|
|
292
298
|
// console.log('[AstroSphere] emit camera-changed:', reason);
|
|
293
|
-
this.canvas.dispatchEvent(new CustomEvent(
|
|
299
|
+
this.canvas.dispatchEvent(new CustomEvent("camera-changed", {
|
|
294
300
|
detail,
|
|
295
301
|
bubbles: true,
|
|
296
302
|
composed: true,
|
|
@@ -298,7 +304,7 @@ class AstroSphere {
|
|
|
298
304
|
}
|
|
299
305
|
addEventListeners(canvas) {
|
|
300
306
|
if (global.debug) {
|
|
301
|
-
console.log(
|
|
307
|
+
console.log("[AstroSphere::addEventListeners]");
|
|
302
308
|
}
|
|
303
309
|
const CLICK_MAX_DISTANCE_PX = 4;
|
|
304
310
|
const CLICK_MAX_DURATION_MS = 250;
|
|
@@ -328,7 +334,7 @@ class AstroSphere {
|
|
|
328
334
|
const handleMouseUp = (event) => {
|
|
329
335
|
canvas.releasePointerCapture(event.pointerId);
|
|
330
336
|
this.mouseDown = false;
|
|
331
|
-
document.body.style.cursor =
|
|
337
|
+
document.body.style.cursor = "auto";
|
|
332
338
|
if (event.button !== 0) {
|
|
333
339
|
event.preventDefault();
|
|
334
340
|
return false;
|
|
@@ -350,7 +356,7 @@ class AstroSphere {
|
|
|
350
356
|
const clickResult = cat.selectPrimarySourceFromClick(this.mouseHelper);
|
|
351
357
|
if (!clickResult?.sources.length)
|
|
352
358
|
continue;
|
|
353
|
-
this._webgl.canvas.dispatchEvent(new CustomEvent(
|
|
359
|
+
this._webgl.canvas.dispatchEvent(new CustomEvent("source-clicked", {
|
|
354
360
|
detail: {
|
|
355
361
|
source: clickResult.sources,
|
|
356
362
|
selectionState: clickResult.selectionState,
|
|
@@ -364,7 +370,7 @@ class AstroSphere {
|
|
|
364
370
|
const clickResult = fset.selectPrimaryFootprintFromClick(this.mouseHelper);
|
|
365
371
|
if (!clickResult?.footprints.length)
|
|
366
372
|
continue;
|
|
367
|
-
this._webgl.canvas.dispatchEvent(new CustomEvent(
|
|
373
|
+
this._webgl.canvas.dispatchEvent(new CustomEvent("footprint-clicked", {
|
|
368
374
|
detail: {
|
|
369
375
|
footprint: clickResult.footprints,
|
|
370
376
|
selectionState: clickResult.selectionState,
|
|
@@ -391,10 +397,13 @@ class AstroSphere {
|
|
|
391
397
|
if (!this._healpixGrid)
|
|
392
398
|
return;
|
|
393
399
|
if (this.mouseDown) {
|
|
394
|
-
document.body.style.cursor =
|
|
395
|
-
|
|
396
|
-
const
|
|
397
|
-
const
|
|
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;
|
|
398
407
|
const filteredDelta = this.filterRotationDeltaByAstroLocks(deltaX, deltaY);
|
|
399
408
|
this.inertiaX += 0.1 * filteredDelta.deltaX;
|
|
400
409
|
this.inertiaY += 0.1 * filteredDelta.deltaY;
|
|
@@ -429,10 +438,11 @@ class AstroSphere {
|
|
|
429
438
|
// direction feels responsive instead of "buffered".
|
|
430
439
|
this.zoomInertia = 0;
|
|
431
440
|
this._camera.zoom(zoomStep);
|
|
441
|
+
this.lastCameraMotionAt = performance.now();
|
|
432
442
|
this.fov = this._healpixGrid.refreshFoV(this._camera, this._perspectiveMatrixManager.pMatrix);
|
|
433
443
|
this._camera.refreshFoV(this.fov.minFoV);
|
|
434
444
|
this._cameraStatusChanged = true;
|
|
435
|
-
this.emitCameraChanged(
|
|
445
|
+
this.emitCameraChanged("wheel");
|
|
436
446
|
event.preventDefault();
|
|
437
447
|
};
|
|
438
448
|
const handleContextMenu = (event) => {
|
|
@@ -450,7 +460,7 @@ class AstroSphere {
|
|
|
450
460
|
const pickResult = cat.getSourcesFromPointer(this.mouseHelper);
|
|
451
461
|
if (!pickResult?.sources.length)
|
|
452
462
|
continue;
|
|
453
|
-
this._webgl.canvas.dispatchEvent(new CustomEvent(
|
|
463
|
+
this._webgl.canvas.dispatchEvent(new CustomEvent("source-contextmenu", {
|
|
454
464
|
detail: {
|
|
455
465
|
source: pickResult.sources,
|
|
456
466
|
catalogue: cat,
|
|
@@ -466,7 +476,7 @@ class AstroSphere {
|
|
|
466
476
|
const pickResult = fset.getFootprintsFromPointer(this.mouseHelper);
|
|
467
477
|
if (!pickResult?.footprints.length)
|
|
468
478
|
continue;
|
|
469
|
-
this._webgl.canvas.dispatchEvent(new CustomEvent(
|
|
479
|
+
this._webgl.canvas.dispatchEvent(new CustomEvent("footprint-contextmenu", {
|
|
470
480
|
detail: {
|
|
471
481
|
footprint: pickResult.footprints,
|
|
472
482
|
footprintSet: fset,
|
|
@@ -486,40 +496,40 @@ class AstroSphere {
|
|
|
486
496
|
}
|
|
487
497
|
// console.log('[AstroSphere::onKeyDown] key=', evt.key)
|
|
488
498
|
switch (evt.key) {
|
|
489
|
-
case
|
|
499
|
+
case "1":
|
|
490
500
|
// Free camera
|
|
491
501
|
this._camera.clearRotationLock();
|
|
492
502
|
break;
|
|
493
|
-
case
|
|
503
|
+
case "2":
|
|
494
504
|
// Lock X axis rotation
|
|
495
505
|
this._camera.setRotationLock({ x: true, y: false, z: false });
|
|
496
506
|
break;
|
|
497
|
-
case
|
|
507
|
+
case "3":
|
|
498
508
|
// Lock Y axis rotation
|
|
499
509
|
this._camera.setRotationLock({ x: false, y: true, z: false });
|
|
500
510
|
break;
|
|
501
|
-
case
|
|
511
|
+
case "4":
|
|
502
512
|
// Lock Z axis rotation
|
|
503
513
|
this._camera.setRotationLock({ x: false, y: false, z: true });
|
|
504
514
|
break;
|
|
505
515
|
}
|
|
506
516
|
};
|
|
507
|
-
console.log(
|
|
517
|
+
console.log("[AstroSphere] registering pointer and wheel listeners on canvas");
|
|
508
518
|
canvas.onpointerdown = handleMouseDown;
|
|
509
519
|
canvas.onpointerup = handleMouseUp;
|
|
510
520
|
canvas.onpointermove = handleMouseMove;
|
|
511
521
|
canvas.onpointerleave = () => {
|
|
512
522
|
this.clearLastMousePoint();
|
|
513
523
|
this._cameraStatusChanged = true;
|
|
514
|
-
this.emitCameraChanged(
|
|
524
|
+
this.emitCameraChanged("pointerleave");
|
|
515
525
|
};
|
|
516
|
-
console.log(
|
|
517
|
-
canvas.addEventListener(
|
|
518
|
-
canvas.addEventListener(
|
|
519
|
-
console.log(
|
|
520
|
-
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 });
|
|
521
531
|
}
|
|
522
|
-
// REVIEW THIS METHOD AND MOVE IT
|
|
532
|
+
// REVIEW THIS METHOD AND MOVE IT
|
|
523
533
|
getPhiThetaDeg(canvas) {
|
|
524
534
|
const rect = canvas.getBoundingClientRect();
|
|
525
535
|
const maxX = rect.width;
|
|
@@ -546,21 +556,21 @@ class AstroSphere {
|
|
|
546
556
|
}
|
|
547
557
|
activateHiPS(hipsDescriptor) {
|
|
548
558
|
this._activeHiPS = new HiPS(1, [0.0, 0.0, 0.0], 0, 0, hipsDescriptor, this._webgl, this._healpixGrid);
|
|
549
|
-
this._activeBaseLayer =
|
|
559
|
+
this._activeBaseLayer = "hips";
|
|
550
560
|
}
|
|
551
561
|
activateXYZ(config) {
|
|
552
|
-
this.activateXYZ2(new XYZMapDescriptor(config.name ??
|
|
553
|
-
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";
|
|
554
564
|
}
|
|
555
565
|
activateXYZ2(config) {
|
|
556
566
|
this._activeXYZ2 = new XYZMap(1, [0.0, 0.0, 0.0], 0, 0, config, this._webgl);
|
|
557
|
-
this._activeBaseLayer =
|
|
567
|
+
this._activeBaseLayer = "xyz";
|
|
558
568
|
}
|
|
559
569
|
activateWMTS(config) {
|
|
560
570
|
const adapter = new WMTSAdapter(config);
|
|
561
571
|
const xyzConfig = adapter.toXYZLayerConfig();
|
|
562
|
-
this._activeXYZ2 = new XYZMap(1, [0.0, 0.0, 0.0], 0, 0, new XYZMapDescriptor(config.layer ? `WMTS ${config.layer}` :
|
|
563
|
-
this._activeBaseLayer =
|
|
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";
|
|
564
574
|
}
|
|
565
575
|
// Catalogue section
|
|
566
576
|
async showCatalogue(cat) {
|
|
@@ -570,7 +580,7 @@ class AstroSphere {
|
|
|
570
580
|
return cat;
|
|
571
581
|
}
|
|
572
582
|
deleteCatalogue(catalogue) {
|
|
573
|
-
this.activeCatalogues = this.activeCatalogues.filter(c => c !== catalogue);
|
|
583
|
+
this.activeCatalogues = this.activeCatalogues.filter((c) => c !== catalogue);
|
|
574
584
|
}
|
|
575
585
|
// End Catalogue section
|
|
576
586
|
// Footprint section
|
|
@@ -581,11 +591,11 @@ class AstroSphere {
|
|
|
581
591
|
return fset;
|
|
582
592
|
}
|
|
583
593
|
deleteFootprintSet(footprintSet) {
|
|
584
|
-
this.activeFootprintSets = this.activeFootprintSets.filter(fst => fst !== footprintSet);
|
|
594
|
+
this.activeFootprintSets = this.activeFootprintSets.filter((fst) => fst !== footprintSet);
|
|
585
595
|
}
|
|
586
596
|
getHoveredFootprints() {
|
|
587
597
|
let footprintsHovered = [];
|
|
588
|
-
this.activeFootprintSets.forEach(fset => {
|
|
598
|
+
this.activeFootprintSets.forEach((fset) => {
|
|
589
599
|
footprintsHovered.push(fset.hoveredFootprints);
|
|
590
600
|
});
|
|
591
601
|
return footprintsHovered;
|
|
@@ -595,13 +605,13 @@ class AstroSphere {
|
|
|
595
605
|
this._camera.goTo(raDeg, decDeg);
|
|
596
606
|
}
|
|
597
607
|
getActiveCoordinateMode() {
|
|
598
|
-
if (this._activeBaseLayer ===
|
|
599
|
-
return
|
|
608
|
+
if (this._activeBaseLayer === "xyz") {
|
|
609
|
+
return "lonlat";
|
|
600
610
|
}
|
|
601
|
-
if (this._activeBaseLayer ===
|
|
602
|
-
return
|
|
611
|
+
if (this._activeBaseLayer === "hips" && this._activeHiPS?.isGalacticHips) {
|
|
612
|
+
return "galactic";
|
|
603
613
|
}
|
|
604
|
-
return
|
|
614
|
+
return "equatorial";
|
|
605
615
|
}
|
|
606
616
|
resetAxesOrientation() {
|
|
607
617
|
const center = this.updateCentralPoint();
|
|
@@ -624,7 +634,7 @@ class AstroSphere {
|
|
|
624
634
|
return this.keepCameraNorthUp;
|
|
625
635
|
}
|
|
626
636
|
getFoV() {
|
|
627
|
-
if (this._activeBaseLayer ===
|
|
637
|
+
if (this._activeBaseLayer === "xyz" && this._activeXYZ2) {
|
|
628
638
|
return this._activeXYZ2.getFoV();
|
|
629
639
|
}
|
|
630
640
|
return this.fov;
|
|
@@ -641,11 +651,15 @@ class AstroSphere {
|
|
|
641
651
|
this._camera.refreshFoV(this.fov.minFoV);
|
|
642
652
|
}
|
|
643
653
|
changeFoV2(deg) {
|
|
644
|
-
const newCameraPos = this._healpixGrid
|
|
654
|
+
const newCameraPos = this._healpixGrid
|
|
655
|
+
.getFoV()
|
|
656
|
+
.computeCameraPositionForFoV(deg);
|
|
645
657
|
this._camera.setCameraPosition(newCameraPos);
|
|
646
658
|
}
|
|
647
659
|
changeFoV3(deg) {
|
|
648
|
-
const newPos = this._healpixGrid
|
|
660
|
+
const newPos = this._healpixGrid
|
|
661
|
+
.getFoV()
|
|
662
|
+
.computeCameraPositionForAngularDiameter(deg);
|
|
649
663
|
this._camera.setCameraPosition(newPos);
|
|
650
664
|
// Recompute projection after moving the camera
|
|
651
665
|
this._perspectiveMatrixManager.computePerspectiveMatrix(this.canvas, this._camera, bootSetup.camera_fov_deg, bootSetup.camera_near_plane, false);
|
|
@@ -654,9 +668,22 @@ class AstroSphere {
|
|
|
654
668
|
return global.insideSphere;
|
|
655
669
|
}
|
|
656
670
|
toggleInsideSphere() {
|
|
671
|
+
const centerBeforeToggle = this.updateCentralPoint();
|
|
672
|
+
this.inertiaX = 0;
|
|
673
|
+
this.inertiaY = 0;
|
|
674
|
+
this.zoomInertia = 0;
|
|
657
675
|
global.insideSphere = !global.insideSphere;
|
|
658
676
|
// console.log(global.insideSphere)
|
|
659
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));
|
|
660
687
|
}
|
|
661
688
|
// imposta posizione camera
|
|
662
689
|
setCameraPosition(pos) {
|
|
@@ -691,6 +718,13 @@ class AstroSphere {
|
|
|
691
718
|
if (centralradeg == null || centraldecdeg == null) {
|
|
692
719
|
return null;
|
|
693
720
|
}
|
|
721
|
+
let fovPolygon = [];
|
|
722
|
+
try {
|
|
723
|
+
fovPolygon = this.getFoVPolygon();
|
|
724
|
+
}
|
|
725
|
+
catch (error) {
|
|
726
|
+
console.warn("[AstroSphere] getCurrentStatus: FoV polygon is not available.", error);
|
|
727
|
+
}
|
|
694
728
|
// if (this._rotating && centraldecdeg && centralradeg) {
|
|
695
729
|
const detail = {
|
|
696
730
|
fovDeg: this.fov.minFoV,
|
|
@@ -705,7 +739,7 @@ class AstroSphere {
|
|
|
705
739
|
centralPoint: new Point({ raDeg: centralradeg, decDeg: centraldecdeg }, CoordsType.ASTRO),
|
|
706
740
|
mouseHoverPoint: this.mousePointCoords,
|
|
707
741
|
colorMap: this._selectedColorMap,
|
|
708
|
-
getFoVPolygon:
|
|
742
|
+
getFoVPolygon: fovPolygon,
|
|
709
743
|
};
|
|
710
744
|
return detail;
|
|
711
745
|
// }
|
|
@@ -737,7 +771,9 @@ class AstroSphere {
|
|
|
737
771
|
this._camera.setRotationLock({ y: locked });
|
|
738
772
|
if (locked)
|
|
739
773
|
this.inertiaX = 0;
|
|
740
|
-
this.lockedEastWestRaDeg = locked
|
|
774
|
+
this.lockedEastWestRaDeg = locked
|
|
775
|
+
? (this.updateCentralPoint()?.astroDeg.ra ?? null)
|
|
776
|
+
: null;
|
|
741
777
|
}
|
|
742
778
|
isEastWestRotationLocked() {
|
|
743
779
|
return this._camera.isRotationLockedY();
|
|
@@ -746,7 +782,9 @@ class AstroSphere {
|
|
|
746
782
|
this._camera.setRotationLock({ x: locked });
|
|
747
783
|
if (locked)
|
|
748
784
|
this.inertiaY = 0;
|
|
749
|
-
this.lockedNorthSouthDecDeg = locked
|
|
785
|
+
this.lockedNorthSouthDecDeg = locked
|
|
786
|
+
? (this.updateCentralPoint()?.astroDeg.dec ?? null)
|
|
787
|
+
: null;
|
|
750
788
|
}
|
|
751
789
|
isNorthSouthRotationLocked() {
|
|
752
790
|
return this._camera.isRotationLockedX();
|
|
@@ -758,6 +796,11 @@ class AstroSphere {
|
|
|
758
796
|
requests: xyzTileRequestScheduler.getDebugStats(),
|
|
759
797
|
};
|
|
760
798
|
}
|
|
799
|
+
getHiPSDebugStats() {
|
|
800
|
+
if (!this._activeHiPS)
|
|
801
|
+
return null;
|
|
802
|
+
return this._activeHiPS.getDebugStats();
|
|
803
|
+
}
|
|
761
804
|
draw(canvas) {
|
|
762
805
|
if (this._refreshingStatus)
|
|
763
806
|
return;
|
|
@@ -783,6 +826,7 @@ class AstroSphere {
|
|
|
783
826
|
if (Math.abs(this.zoomInertia) > 0.0001) {
|
|
784
827
|
this._camera.zoom(this.zoomInertia);
|
|
785
828
|
this.zoomInertia *= 0.95;
|
|
829
|
+
this.lastCameraMotionAt = performance.now();
|
|
786
830
|
this.fov = this._healpixGrid.refreshFoV(this._camera, this._perspectiveMatrixManager.pMatrix);
|
|
787
831
|
this._camera.refreshFoV(this.fov.minFoV);
|
|
788
832
|
if (this.prevFov !== this.fov.minFoV) {
|
|
@@ -798,7 +842,9 @@ class AstroSphere {
|
|
|
798
842
|
this._cameraStatusChanged = true;
|
|
799
843
|
}
|
|
800
844
|
// Rotation inertia
|
|
801
|
-
if (this.mouseDown ||
|
|
845
|
+
if (this.mouseDown ||
|
|
846
|
+
Math.abs(this.inertiaX) > 0.02 ||
|
|
847
|
+
Math.abs(this.inertiaY) > 0.02) {
|
|
802
848
|
cameraRotated = true;
|
|
803
849
|
const filteredInertia = this.filterRotationDeltaByAstroLocks(this.inertiaX, this.inertiaY);
|
|
804
850
|
PHI = filteredInertia.deltaX;
|
|
@@ -806,6 +852,7 @@ class AstroSphere {
|
|
|
806
852
|
this.inertiaX = filteredInertia.deltaX * 0.95;
|
|
807
853
|
this.inertiaY = filteredInertia.deltaY * 0.95;
|
|
808
854
|
this._camera.rotate(PHI, THETA);
|
|
855
|
+
this.lastCameraMotionAt = performance.now();
|
|
809
856
|
this._perspectiveMatrixManager.computePerspectiveMatrix(canvas, this._camera, bootSetup.camera_fov_deg, bootSetup.camera_near_plane, global.insideSphere);
|
|
810
857
|
const lockCorrected = this.enforceAstronomicalRotationLocks();
|
|
811
858
|
if (!lockCorrected) {
|
|
@@ -816,6 +863,12 @@ class AstroSphere {
|
|
|
816
863
|
this.inertiaY = 0;
|
|
817
864
|
this.inertiaX = 0;
|
|
818
865
|
}
|
|
866
|
+
const nextFoV = this._healpixGrid.refreshFoV(this._camera, this._perspectiveMatrixManager.pMatrix);
|
|
867
|
+
if (Number.isFinite(nextFoV.minFoV) && nextFoV.minFoV > 0) {
|
|
868
|
+
this.fov = nextFoV;
|
|
869
|
+
this._camera.refreshFoV(this.fov.minFoV);
|
|
870
|
+
this.prevFov = this.fov.minFoV;
|
|
871
|
+
}
|
|
819
872
|
// Se la camera è ruotata (anche solo per inerzia), aggiorna punto centrale + emetti cameraChanged
|
|
820
873
|
if (cameraRotated) {
|
|
821
874
|
// Ricalcola il punto centrale
|
|
@@ -833,16 +886,20 @@ class AstroSphere {
|
|
|
833
886
|
}
|
|
834
887
|
}
|
|
835
888
|
if (this._cameraStatusChanged) {
|
|
836
|
-
const
|
|
889
|
+
const now = performance.now();
|
|
890
|
+
const shouldEmitCameraChanged = !this.mouseDown || now - this.lastCameraChangedAt > 100;
|
|
891
|
+
const detail = shouldEmitCameraChanged ? this.getCurrentStatus() : null;
|
|
837
892
|
if (detail) {
|
|
838
893
|
// console.log('[AstroSphere::draw] emitting camera-changed event due to camera status change', detail)
|
|
839
894
|
// console.log('[AstroSphere::draw] inertia', this.zoomInertia, this.inertiaX, this.inertiaY)
|
|
840
|
-
this.canvas.dispatchEvent(new CustomEvent(
|
|
895
|
+
this.canvas.dispatchEvent(new CustomEvent("camera-changed", {
|
|
841
896
|
detail,
|
|
842
|
-
bubbles: true,
|
|
897
|
+
bubbles: true,
|
|
898
|
+
composed: true,
|
|
843
899
|
}));
|
|
900
|
+
this.lastCameraChangedAt = now;
|
|
844
901
|
}
|
|
845
|
-
if (!this.startup) {
|
|
902
|
+
if (!this.startup && shouldEmitCameraChanged) {
|
|
846
903
|
this._cameraStatusChanged = false;
|
|
847
904
|
}
|
|
848
905
|
}
|
|
@@ -852,23 +909,39 @@ class AstroSphere {
|
|
|
852
909
|
this._webgl.enable(this._webgl.CULL_FACE);
|
|
853
910
|
this._webgl.cullFace(global.insideSphere ? this._webgl.FRONT : this._webgl.BACK);
|
|
854
911
|
this._webgl.blendFunc(this._webgl.SRC_ALPHA, this._webgl.ONE_MINUS_SRC_ALPHA);
|
|
855
|
-
if (this._activeBaseLayer ===
|
|
912
|
+
if (this._activeBaseLayer === "hips" && this._activeHiPS) {
|
|
856
913
|
const visibleOrder = Math.min(this._healpixGrid.visibleorder, this._activeHiPS.maxOrder);
|
|
857
914
|
this._healpixGrid.visibleTilesManager.computeVisiblePixels(visibleOrder, this._webgl, this._camera, this._perspectiveMatrixManager.pMatrix);
|
|
858
915
|
}
|
|
859
916
|
// DRAW HiPS
|
|
917
|
+
const stableFovDeg = this.fov?.minFoV ?? this._healpixGrid.getMinFoV();
|
|
918
|
+
const nowForGrid = performance.now();
|
|
919
|
+
const cameraMovingForGrid = this.mouseDown ||
|
|
920
|
+
Math.abs(this.zoomInertia) > 0.0001 ||
|
|
921
|
+
Math.abs(this.inertiaX) > 0.02 ||
|
|
922
|
+
Math.abs(this.inertiaY) > 0.02 ||
|
|
923
|
+
nowForGrid - this.lastCameraMotionAt < 220;
|
|
924
|
+
// const skyEntityDrawInput: SkyEntityDrawInput = {
|
|
925
|
+
// fovDeg: this._healpixGrid.getMinFoV(),
|
|
926
|
+
// camera: this._camera,
|
|
927
|
+
// pMatrix: this._perspectiveMatrixManager.pMatrix,
|
|
928
|
+
// centerSphericalDeg: this.updateCentralPoint().sphericalDeg,
|
|
929
|
+
// fovPolygon: this._activeBaseLayer === 'xyz' ? this.getFoVPolygon() : undefined,
|
|
930
|
+
// viewportSphericalSamples: this._activeBaseLayer === 'xyz' ? this.collectViewportSphericalSamples(7) : undefined,
|
|
931
|
+
// }
|
|
860
932
|
const skyEntityDrawInput = {
|
|
861
|
-
fovDeg:
|
|
933
|
+
fovDeg: stableFovDeg,
|
|
862
934
|
camera: this._camera,
|
|
863
935
|
pMatrix: this._perspectiveMatrixManager.pMatrix,
|
|
864
936
|
centerSphericalDeg: this.updateCentralPoint().sphericalDeg,
|
|
865
|
-
fovPolygon:
|
|
866
|
-
viewportSphericalSamples:
|
|
937
|
+
fovPolygon: undefined,
|
|
938
|
+
viewportSphericalSamples: undefined,
|
|
939
|
+
cameraMoving: cameraMovingForGrid,
|
|
867
940
|
};
|
|
868
|
-
if (this._activeBaseLayer ===
|
|
941
|
+
if (this._activeBaseLayer === "hips") {
|
|
869
942
|
this._activeHiPS?.draw(skyEntityDrawInput);
|
|
870
943
|
}
|
|
871
|
-
if (this._activeBaseLayer ===
|
|
944
|
+
if (this._activeBaseLayer === "xyz") {
|
|
872
945
|
this._activeXYZ2?.draw(skyEntityDrawInput);
|
|
873
946
|
}
|
|
874
947
|
this._healpixGrid.draw(skyEntityDrawInput);
|
|
@@ -881,24 +954,27 @@ class AstroSphere {
|
|
|
881
954
|
const raDecDeg = sphericalToAstroDeg(phiTheta.phi, phiTheta.theta);
|
|
882
955
|
const raHMS = raDegToHMS(raDecDeg.ra);
|
|
883
956
|
const decDMS = decDegToDMS(raDecDeg.dec);
|
|
884
|
-
this.prevFov = this._healpixGrid.getMinFoV();
|
|
957
|
+
// this.prevFov = this._healpixGrid.getMinFoV();
|
|
958
|
+
this.prevFov = this.fov?.minFoV ?? this._healpixGrid.getMinFoV();
|
|
885
959
|
this._cameraStatusChanged = true;
|
|
886
|
-
console.log(
|
|
960
|
+
console.log("(startup coords)", {
|
|
887
961
|
raDeg: raDecDeg.ra,
|
|
888
962
|
decDeg: raDecDeg.dec,
|
|
889
963
|
raHMS,
|
|
890
964
|
decDMS,
|
|
891
965
|
});
|
|
892
966
|
}
|
|
893
|
-
this.activeCatalogues.forEach(cat => {
|
|
894
|
-
const activeModelMatrix = this._activeHiPS?.getModelMatrix() ??
|
|
967
|
+
this.activeCatalogues.forEach((cat) => {
|
|
968
|
+
const activeModelMatrix = this._activeHiPS?.getModelMatrix() ??
|
|
969
|
+
this._activeXYZ2?.getModelMatrix();
|
|
895
970
|
if (activeModelMatrix) {
|
|
896
971
|
cat.draw(activeModelMatrix, this.mouseHelper, this._camera.getCameraMatrix(), this._perspectiveMatrixManager.pMatrix);
|
|
897
972
|
}
|
|
898
973
|
});
|
|
899
974
|
this.emitHoveredSourceIfChanged();
|
|
900
|
-
this.activeFootprintSets.forEach(fst => {
|
|
901
|
-
const activeModelMatrix = this._activeHiPS?.getModelMatrix() ??
|
|
975
|
+
this.activeFootprintSets.forEach((fst) => {
|
|
976
|
+
const activeModelMatrix = this._activeHiPS?.getModelMatrix() ??
|
|
977
|
+
this._activeXYZ2?.getModelMatrix();
|
|
902
978
|
if (activeModelMatrix) {
|
|
903
979
|
fst.draw(activeModelMatrix, this.mouseHelper, this._camera.getCameraMatrix(), this._perspectiveMatrixManager.pMatrix);
|
|
904
980
|
}
|
|
@@ -915,13 +991,13 @@ class AstroSphere {
|
|
|
915
991
|
nextHoveredCatalogue = cat;
|
|
916
992
|
break;
|
|
917
993
|
}
|
|
918
|
-
const unchanged = nextHoveredSource === this.lastHoveredSource
|
|
919
|
-
|
|
994
|
+
const unchanged = nextHoveredSource === this.lastHoveredSource &&
|
|
995
|
+
nextHoveredCatalogue === this.lastHoveredCatalogue;
|
|
920
996
|
if (unchanged)
|
|
921
997
|
return;
|
|
922
998
|
this.lastHoveredSource = nextHoveredSource;
|
|
923
999
|
this.lastHoveredCatalogue = nextHoveredCatalogue;
|
|
924
|
-
this._webgl.canvas.dispatchEvent(new CustomEvent(
|
|
1000
|
+
this._webgl.canvas.dispatchEvent(new CustomEvent("source-hovered", {
|
|
925
1001
|
detail: { source: nextHoveredSource, catalogue: nextHoveredCatalogue },
|
|
926
1002
|
bubbles: true,
|
|
927
1003
|
composed: true,
|