astro-viewer 3.9.0 → 3.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +66 -4
  2. package/dist/astroviewer.cjs +536 -120
  3. package/dist/astroviewer.cjs.map +1 -1
  4. package/dist/astroviewer.js +536 -120
  5. package/dist/astroviewer.js.map +1 -1
  6. package/dist/astroviewer.min.js +1 -1
  7. package/dist/astroviewer.min.js.map +1 -1
  8. package/lib-esm/AstroSphere.d.ts +1 -0
  9. package/lib-esm/AstroSphere.d.ts.map +1 -1
  10. package/lib-esm/AstroSphere.js +15 -0
  11. package/lib-esm/AstroSphere.js.map +1 -1
  12. package/lib-esm/AstroViewer.d.ts +1 -0
  13. package/lib-esm/AstroViewer.d.ts.map +1 -1
  14. package/lib-esm/AstroViewer.js +6 -3
  15. package/lib-esm/AstroViewer.js.map +1 -1
  16. package/lib-esm/Camera.d.ts +6 -0
  17. package/lib-esm/Camera.d.ts.map +1 -1
  18. package/lib-esm/Camera.js +102 -8
  19. package/lib-esm/Camera.js.map +1 -1
  20. package/lib-esm/Global.d.ts +3 -3
  21. package/lib-esm/Global.d.ts.map +1 -1
  22. package/lib-esm/Global.js +38 -16
  23. package/lib-esm/Global.js.map +1 -1
  24. package/lib-esm/model/Source.d.ts +11 -0
  25. package/lib-esm/model/Source.d.ts.map +1 -1
  26. package/lib-esm/model/Source.js +9 -1
  27. package/lib-esm/model/Source.js.map +1 -1
  28. package/lib-esm/model/catalogues/CatalogueGL.d.ts +31 -8
  29. package/lib-esm/model/catalogues/CatalogueGL.d.ts.map +1 -1
  30. package/lib-esm/model/catalogues/CatalogueGL.js +286 -87
  31. package/lib-esm/model/catalogues/CatalogueGL.js.map +1 -1
  32. package/lib-esm/model/footprints/FootprintSetGL.d.ts +1 -3
  33. package/lib-esm/model/footprints/FootprintSetGL.d.ts.map +1 -1
  34. package/lib-esm/model/footprints/FootprintSetGL.js +1 -3
  35. package/lib-esm/model/footprints/FootprintSetGL.js.map +1 -1
  36. package/lib-esm/model/hips/VisibleTilesManager.d.ts +6 -3
  37. package/lib-esm/model/hips/VisibleTilesManager.d.ts.map +1 -1
  38. package/lib-esm/model/hips/VisibleTilesManager.js.map +1 -1
  39. package/lib-esm/model/meships/MeshHiPS.d.ts +4 -4
  40. package/lib-esm/model/meships/MeshHiPS.d.ts.map +1 -1
  41. package/lib-esm/model/meships/MeshHiPS.js +28 -12
  42. package/lib-esm/model/meships/MeshHiPS.js.map +1 -1
  43. package/lib-esm/model/terra/TerraFootprintSetGL.d.ts +2 -0
  44. package/lib-esm/model/terra/TerraFootprintSetGL.d.ts.map +1 -1
  45. package/lib-esm/model/terra/TerraFootprintSetGL.js +19 -0
  46. package/lib-esm/model/terra/TerraFootprintSetGL.js.map +1 -1
  47. package/lib-esm/model/terra/TerraPointSetGL.d.ts +4 -0
  48. package/lib-esm/model/terra/TerraPointSetGL.d.ts.map +1 -1
  49. package/lib-esm/model/terra/TerraPointSetGL.js +36 -0
  50. package/lib-esm/model/terra/TerraPointSetGL.js.map +1 -1
  51. package/lib-esm/model/terra/TerraPolylineSetGL.d.ts +1 -3
  52. package/lib-esm/model/terra/TerraPolylineSetGL.d.ts.map +1 -1
  53. package/lib-esm/model/terra/TerraPolylineSetGL.js +1 -3
  54. package/lib-esm/model/terra/TerraPolylineSetGL.js.map +1 -1
  55. package/lib-esm/utils/MouseHelper.d.ts.map +1 -1
  56. package/lib-esm/utils/MouseHelper.js +2 -1
  57. package/lib-esm/utils/MouseHelper.js.map +1 -1
  58. package/package.json +1 -1
@@ -53,6 +53,7 @@ __webpack_require__.d(vec3_namespaceObject, {
53
53
  dot: () => (dot),
54
54
  fromValues: () => (vec3_fromValues),
55
55
  length: () => (vec3_length),
56
+ lerp: () => (lerp),
56
57
  normalize: () => (normalize),
57
58
  scale: () => (vec3_scale),
58
59
  scaleAndAdd: () => (scaleAndAdd),
@@ -3906,6 +3907,7 @@ class AstroSphere {
3906
3907
  const handleMouseDown = (event) => {
3907
3908
  canvas.setPointerCapture(event.pointerId);
3908
3909
  this.mouseDown = true;
3910
+ this._camera.cancelFlyTo();
3909
3911
  const rect = canvas.getBoundingClientRect();
3910
3912
  this.lastMouseX = event.clientX - rect.left; // locale al canvas
3911
3913
  this.lastMouseY = event.clientY - rect.top; // locale al canvas
@@ -4032,6 +4034,7 @@ class AstroSphere {
4032
4034
  const handleMouseWheel = (event) => {
4033
4035
  const currentFov = this._healpixGrid.getMinFoV();
4034
4036
  const zoomStep = this.computeZoomStep(currentFov, event.deltaY);
4037
+ this._camera.cancelFlyTo();
4035
4038
  // Apply wheel zoom immediately and discard any queued inertia so reversing
4036
4039
  // direction feels responsive instead of "buffered".
4037
4040
  this.zoomInertia = 0;
@@ -4297,6 +4300,9 @@ class AstroSphere {
4297
4300
  goTo(raDeg, decDeg) {
4298
4301
  this._camera.goTo(raDeg, decDeg);
4299
4302
  }
4303
+ flyTo(raDeg, decDeg, durationMs = 1200) {
4304
+ this._camera.flyTo(raDeg, decDeg, durationMs);
4305
+ }
4300
4306
  getActiveCoordinateMode() {
4301
4307
  if (this._activeBaseLayer === "xyz") {
4302
4308
  return "lonlat";
@@ -4532,6 +4538,16 @@ class AstroSphere {
4532
4538
  let PHI = 0;
4533
4539
  this._webgl.viewport(0, 0, this._webgl.drawingBufferWidth, this._webgl.drawingBufferHeight);
4534
4540
  this._webgl.clear(this._webgl.COLOR_BUFFER_BIT | this._webgl.DEPTH_BUFFER_BIT);
4541
+ const now = performance.now();
4542
+ const cameraFlying = this._camera.updateFlyTo(now);
4543
+ if (cameraFlying) {
4544
+ this.inertiaX = 0;
4545
+ this.inertiaY = 0;
4546
+ this.lastCameraMotionAt = now;
4547
+ this._cameraStatusChanged = true;
4548
+ this.updateCentralPoint();
4549
+ this._perspectiveMatrixManager.computePerspectiveMatrix(canvas, this._camera, Config_js_1.bootSetup.camera_fov_deg, Config_js_1.bootSetup.camera_near_plane, Global_js_1.default.insideSphere);
4550
+ }
4535
4551
  // Zoom inertia
4536
4552
  if (this.zoomInertia !== 0) {
4537
4553
  if (Math.abs(this.zoomInertia) > 0.0001) {
@@ -4838,7 +4854,7 @@ class AstroViewer {
4838
4854
  }
4839
4855
  //FOOTPRINT
4840
4856
  createFootprintSet(footprintSetName, footprintSetDescription, providerUrl, metadataManager) {
4841
- return new FootprintSetGL_js_1.FootprintSetGL(footprintSetName, footprintSetDescription, providerUrl, metadataManager, this.webgl, this.astroSphere.healpixGrid.visibleTilesManager);
4857
+ return new FootprintSetGL_js_1.FootprintSetGL(footprintSetName, footprintSetDescription, providerUrl, metadataManager, this.webgl);
4842
4858
  }
4843
4859
  showFootprintSet(footprintSet) {
4844
4860
  this.astroSphere.showFootprintSet(footprintSet);
@@ -4863,7 +4879,7 @@ class AstroViewer {
4863
4879
  this.astroSphere.deleteCatalogue(pointSet);
4864
4880
  }
4865
4881
  createTerraFootprintSet(footprintSetName, footprintSetDescription, providerUrl, metadataManager) {
4866
- return new TerraFootprintSetGL_js_1.TerraFootprintSetGL(footprintSetName, footprintSetDescription, providerUrl, metadataManager, this.webgl, this.astroSphere.healpixGrid.visibleTilesManager);
4882
+ return new TerraFootprintSetGL_js_1.TerraFootprintSetGL(footprintSetName, footprintSetDescription, providerUrl, metadataManager, this.webgl);
4867
4883
  }
4868
4884
  showTerraFootprintSet(footprintSet) {
4869
4885
  this.astroSphere.showFootprintSet(footprintSet);
@@ -4875,7 +4891,7 @@ class AstroViewer {
4875
4891
  this.astroSphere.deleteFootprintSet(footprintSet);
4876
4892
  }
4877
4893
  createTerraPolylineSet(polylineSetName, polylineSetDescription, providerUrl, metadataManager) {
4878
- return new TerraPolylineSetGL_js_1.TerraPolylineSetGL(polylineSetName, polylineSetDescription, providerUrl, metadataManager, this.webgl, this.astroSphere.healpixGrid.visibleTilesManager);
4894
+ return new TerraPolylineSetGL_js_1.TerraPolylineSetGL(polylineSetName, polylineSetDescription, providerUrl, metadataManager, this.webgl);
4879
4895
  }
4880
4896
  showTerraPolylineSet(polylineSet) {
4881
4897
  this.astroSphere.showPolylineSet(polylineSet);
@@ -5063,6 +5079,9 @@ class AstroViewer {
5063
5079
  // console.log(`AstroViewer.goTo goto(${raDeg}, ${decDeg})`)
5064
5080
  this.astroSphere.goTo(raDeg, decDeg);
5065
5081
  }
5082
+ flyTo(raDeg, decDeg, durationMs = 1200) {
5083
+ this.astroSphere.flyTo(raDeg, decDeg, durationMs);
5084
+ }
5066
5085
  getActiveCoordinateMode() {
5067
5086
  return this.astroSphere.getActiveCoordinateMode();
5068
5087
  }
@@ -5385,6 +5404,7 @@ class Camera {
5385
5404
  lockRotX = false;
5386
5405
  lockRotY = false;
5387
5406
  lockRotZ = false;
5407
+ flyToAnimation = null;
5388
5408
  constructor(in_position, in_sphere) {
5389
5409
  this.init(in_position, in_sphere);
5390
5410
  }
@@ -5394,7 +5414,11 @@ class Camera {
5394
5414
  this.vMatrix = gl_matrix_1.mat4.create();
5395
5415
  this.T = gl_matrix_1.mat4.create();
5396
5416
  this.R = gl_matrix_1.mat4.create();
5397
- gl_matrix_1.mat4.translate(this.T, this.T, [this.cam_pos[0], this.cam_pos[1], this.cam_pos[2]]);
5417
+ gl_matrix_1.mat4.translate(this.T, this.T, [
5418
+ this.cam_pos[0],
5419
+ this.cam_pos[1],
5420
+ this.cam_pos[2],
5421
+ ]);
5398
5422
  // reset helpers
5399
5423
  this.FoV = this.previousFoV = 180.0;
5400
5424
  this.move = gl_matrix_1.vec3.clone([0, 0, 0]);
@@ -5403,11 +5427,15 @@ class Camera {
5403
5427
  this.goTo(raDeg, decDeg);
5404
5428
  }
5405
5429
  goTo(raDeg, decDeg) {
5430
+ this.cancelFlyTo();
5406
5431
  this.goToPhiTheta((0, Utils_js_1.astroDegToSpherical)(raDeg, decDeg));
5407
5432
  }
5408
5433
  goToPhiTheta(ptDeg) {
5409
5434
  const xyz = (0, Utils_js_1.sphericalToCartesian)(ptDeg.phi, ptDeg.theta, this.cam_pos[2]);
5410
- const targetDirection = gl_matrix_1.vec3.normalize(gl_matrix_1.vec3.create(), gl_matrix_1.vec3.fromValues(xyz[0], xyz[1], xyz[2]));
5435
+ this.applyCameraPosition(gl_matrix_1.vec3.fromValues(xyz[0], xyz[1], xyz[2]));
5436
+ }
5437
+ applyCameraPosition(cameraPosition) {
5438
+ const targetDirection = gl_matrix_1.vec3.normalize(gl_matrix_1.vec3.create(), cameraPosition);
5411
5439
  const celestialNorth = gl_matrix_1.vec3.fromValues(0.0, 0.0, 1.0);
5412
5440
  const northProjection = gl_matrix_1.vec3.scale(gl_matrix_1.vec3.create(), targetDirection, gl_matrix_1.vec3.dot(celestialNorth, targetDirection));
5413
5441
  const cameraUp = gl_matrix_1.vec3.subtract(gl_matrix_1.vec3.create(), celestialNorth, northProjection);
@@ -5418,9 +5446,13 @@ class Camera {
5418
5446
  gl_matrix_1.vec3.normalize(cameraUp, cameraUp);
5419
5447
  }
5420
5448
  let cameraMatrix = gl_matrix_1.mat4.create();
5421
- cameraMatrix = gl_matrix_1.mat4.translate(cameraMatrix, cameraMatrix, gl_matrix_1.vec3.fromValues(xyz[0], xyz[1], xyz[2]));
5449
+ cameraMatrix = gl_matrix_1.mat4.translate(cameraMatrix, cameraMatrix, cameraPosition);
5422
5450
  const focusPoint = [0.0, 0.0, 0.0];
5423
- const cameraPos = [cameraMatrix[12], cameraMatrix[13], cameraMatrix[14]];
5451
+ const cameraPos = [
5452
+ cameraMatrix[12],
5453
+ cameraMatrix[13],
5454
+ cameraMatrix[14],
5455
+ ];
5424
5456
  cameraMatrix = gl_matrix_1.mat4.targetTo(cameraMatrix, cameraPos, focusPoint, cameraUp);
5425
5457
  this.R = gl_matrix_1.mat4.clone(cameraMatrix);
5426
5458
  this.R[12] = 0;
@@ -5432,6 +5464,81 @@ class Camera {
5432
5464
  }
5433
5465
  this.vMatrix = viewMatrix;
5434
5466
  }
5467
+ flyTo(raDeg, decDeg, durationMs = 1200) {
5468
+ const targetSpherical = (0, Utils_js_1.astroDegToSpherical)(raDeg, decDeg);
5469
+ const targetPositionValues = (0, Utils_js_1.sphericalToCartesian)(targetSpherical.phi, targetSpherical.theta, this.cam_pos[2]);
5470
+ const targetPosition = gl_matrix_1.vec3.fromValues(targetPositionValues[0], targetPositionValues[1], targetPositionValues[2]);
5471
+ const currentPosition = this.getCameraPosition();
5472
+ const startDirection = gl_matrix_1.vec3.normalize(gl_matrix_1.vec3.create(), gl_matrix_1.vec3.fromValues(currentPosition[0], currentPosition[1], currentPosition[2]));
5473
+ const targetDirection = gl_matrix_1.vec3.normalize(gl_matrix_1.vec3.create(), targetPosition);
5474
+ this.flyToAnimation = {
5475
+ startDirection,
5476
+ targetDirection,
5477
+ targetPosition,
5478
+ startTime: performance.now(),
5479
+ durationMs: Math.max(1, durationMs),
5480
+ };
5481
+ }
5482
+ updateFlyTo(now) {
5483
+ const animation = this.flyToAnimation;
5484
+ if (!animation) {
5485
+ return false;
5486
+ }
5487
+ const elapsed = now - animation.startTime;
5488
+ const progress = Math.min(1, elapsed / animation.durationMs);
5489
+ const easedProgress = progress < 0.5
5490
+ ? 4 * progress * progress * progress
5491
+ : 1 - Math.pow(-2 * progress + 2, 3) / 2;
5492
+ const direction = this.slerpDirection(animation.startDirection, animation.targetDirection, easedProgress);
5493
+ const radius = Math.abs(this.cam_pos[2]);
5494
+ const cameraPosition = gl_matrix_1.vec3.scale(gl_matrix_1.vec3.create(), direction, radius);
5495
+ this.applyCameraPosition(cameraPosition);
5496
+ if (progress >= 1) {
5497
+ this.applyCameraPosition(animation.targetPosition);
5498
+ this.flyToAnimation = null;
5499
+ }
5500
+ return true;
5501
+ }
5502
+ slerpDirection(start, end, t) {
5503
+ const dot = Math.max(-1, Math.min(1, gl_matrix_1.vec3.dot(start, end)));
5504
+ /*
5505
+ * For almost identical directions, normalized linear interpolation is
5506
+ * numerically more stable than the general SLERP formula.
5507
+ */
5508
+ if (dot > 0.999999) {
5509
+ const result = gl_matrix_1.vec3.lerp(gl_matrix_1.vec3.create(), start, end, t);
5510
+ return gl_matrix_1.vec3.normalize(result, result);
5511
+ }
5512
+ /*
5513
+ * The normal SLERP formula becomes singular for antipodal vectors because
5514
+ * sin(pi) = 0. In that case choose a stable vector orthogonal to start and
5515
+ * rotate through that great circle.
5516
+ */
5517
+ if (dot < -0.999999) {
5518
+ const referenceAxis = Math.abs(start[0]) < 0.9
5519
+ ? gl_matrix_1.vec3.fromValues(1, 0, 0)
5520
+ : gl_matrix_1.vec3.fromValues(0, 1, 0);
5521
+ const orthogonal = gl_matrix_1.vec3.cross(gl_matrix_1.vec3.create(), start, referenceAxis);
5522
+ gl_matrix_1.vec3.normalize(orthogonal, orthogonal);
5523
+ const angle = Math.PI * t;
5524
+ const result = gl_matrix_1.vec3.create();
5525
+ gl_matrix_1.vec3.scale(result, start, Math.cos(angle));
5526
+ gl_matrix_1.vec3.scaleAndAdd(result, result, orthogonal, Math.sin(angle));
5527
+ return gl_matrix_1.vec3.normalize(result, result);
5528
+ }
5529
+ const angle = Math.acos(dot);
5530
+ const sinAngle = Math.sin(angle);
5531
+ const startWeight = Math.sin((1 - t) * angle) / sinAngle;
5532
+ const endWeight = Math.sin(t * angle) / sinAngle;
5533
+ const result = gl_matrix_1.vec3.create();
5534
+ result[0] = start[0] * startWeight + end[0] * endWeight;
5535
+ result[1] = start[1] * startWeight + end[1] * endWeight;
5536
+ result[2] = start[2] * startWeight + end[2] * endWeight;
5537
+ return gl_matrix_1.vec3.normalize(result, result);
5538
+ }
5539
+ cancelFlyTo() {
5540
+ this.flyToAnimation = null;
5541
+ }
5435
5542
  toggleInsideSphere() {
5436
5543
  // if (inside !== global.insideSphere) {
5437
5544
  // global.insideSphere = inside;
@@ -5689,9 +5796,15 @@ class Camera {
5689
5796
  clearRotationLock() {
5690
5797
  this.lockRotX = this.lockRotY = this.lockRotZ = false;
5691
5798
  }
5692
- isRotationLockedX() { return this.lockRotX; }
5693
- isRotationLockedY() { return this.lockRotY; }
5694
- isRotationLockedZ() { return this.lockRotZ; }
5799
+ isRotationLockedX() {
5800
+ return this.lockRotX;
5801
+ }
5802
+ isRotationLockedY() {
5803
+ return this.lockRotY;
5804
+ }
5805
+ isRotationLockedZ() {
5806
+ return this.lockRotZ;
5807
+ }
5695
5808
  }
5696
5809
  exports["default"] = Camera;
5697
5810
 
@@ -5777,7 +5890,7 @@ class Global {
5777
5890
  // private _gl: GL | null;
5778
5891
  _healpix;
5779
5892
  // --- config/state flags ---
5780
- _selectionnside;
5893
+ // private _selectionnside: number;
5781
5894
  // private _healpix4footprints: boolean;
5782
5895
  _useCORSProxy;
5783
5896
  _corsProxyUrl;
@@ -5785,6 +5898,7 @@ class Global {
5785
5898
  _debug;
5786
5899
  _insideSphere;
5787
5900
  _version;
5901
+ _selectionOrder;
5788
5902
  constructor() {
5789
5903
  this._useCORSProxy = Config_js_1.bootSetup.useCORSProxy;
5790
5904
  this._corsProxyUrl = Config_js_1.bootSetup.corsProxyUrl;
@@ -5793,18 +5907,34 @@ class Global {
5793
5907
  this._insideSphere = Config_js_1.bootSetup.insideView;
5794
5908
  this._version = Config_js_1.bootSetup.version;
5795
5909
  this._healpix = {};
5796
- this._selectionnside = 32;
5910
+ // this._selectionnside = 32;
5911
+ this._selectionOrder = 5;
5912
+ }
5913
+ get selectionOrder() {
5914
+ return this._selectionOrder;
5797
5915
  }
5798
5916
  init() {
5799
- console.log('Global.init()');
5917
+ console.log("Global.init()");
5800
5918
  }
5801
5919
  // --- getters/setters ---
5802
- get version() { return this._version; }
5803
- set corsProxyUrl(url) { this._corsProxyUrl = url; }
5804
- get corsProxyUrl() { return this._corsProxyUrl; }
5805
- get useCORSProxy() { return this._useCORSProxy; }
5806
- set useCORSProxy(enabled) { this._useCORSProxy = enabled; }
5807
- get debug() { return this._debug; }
5920
+ get version() {
5921
+ return this._version;
5922
+ }
5923
+ set corsProxyUrl(url) {
5924
+ this._corsProxyUrl = url;
5925
+ }
5926
+ get corsProxyUrl() {
5927
+ return this._corsProxyUrl;
5928
+ }
5929
+ get useCORSProxy() {
5930
+ return this._useCORSProxy;
5931
+ }
5932
+ set useCORSProxy(enabled) {
5933
+ this._useCORSProxy = enabled;
5934
+ }
5935
+ get debug() {
5936
+ return this._debug;
5937
+ }
5808
5938
  getHealpix(order) {
5809
5939
  if (this._healpix[order] === undefined) {
5810
5940
  // order is HEALPix "order" ⇒ nside = 2^order
@@ -5812,10 +5942,15 @@ class Global {
5812
5942
  }
5813
5943
  return this._healpix[order];
5814
5944
  }
5815
- get MAX_DECIMALS() { return this._maxDecimals; }
5816
- set insideSphere(v) { this._insideSphere = v; }
5817
- get insideSphere() { return this._insideSphere; }
5818
- get nsideForSelection() { return this._selectionnside; }
5945
+ get MAX_DECIMALS() {
5946
+ return this._maxDecimals;
5947
+ }
5948
+ set insideSphere(v) {
5949
+ this._insideSphere = v;
5950
+ }
5951
+ get insideSphere() {
5952
+ return this._insideSphere;
5953
+ }
5819
5954
  }
5820
5955
  const global = new Global();
5821
5956
  exports["default"] = global;
@@ -7881,6 +8016,7 @@ class Source {
7881
8016
  _h_pix;
7882
8017
  _shapesize;
7883
8018
  _brightnessFactor;
8019
+ _mediaStyle;
7884
8020
  /**
7885
8021
  * @param in_point Point.js (Cartesian/RA-Dec wrapper)
7886
8022
  * @param in_details Optional array of key/value metadata
@@ -7903,7 +8039,8 @@ class Source {
7903
8039
  }
7904
8040
  computeHealpixPixel() {
7905
8041
  // Get Healpix instance from global
7906
- const healpix = Global_js_1.default.getHealpix(Global_js_1.default.nsideForSelection);
8042
+ // const healpix: Healpix = global.getHealpix(global.nsideForSelection);
8043
+ const healpix = Global_js_1.default.getHealpix(Global_js_1.default.selectionOrder);
7907
8044
  const vec3 = new healpix_1.Vec3(this._point.x, this._point.y, this._point.z);
7908
8045
  const ptg = new healpix_1.Pointing(vec3, false);
7909
8046
  this._h_pix = healpix.ang2pix(ptg, false);
@@ -7932,6 +8069,12 @@ class Source {
7932
8069
  set brightnessFactor(factor) {
7933
8070
  this._brightnessFactor = factor;
7934
8071
  }
8072
+ get mediaStyle() {
8073
+ return this._mediaStyle;
8074
+ }
8075
+ set mediaStyle(style) {
8076
+ this._mediaStyle = style;
8077
+ }
7935
8078
  }
7936
8079
  exports.Source = Source;
7937
8080
 
@@ -8159,6 +8302,9 @@ exports.SphereFoV = SphereFoV;
8159
8302
  *
8160
8303
  * See LICENSE.md, LICENSE-AGPL.md, and LICENSE-COMMERCIAL.md for details.
8161
8304
  */
8305
+ var __importDefault = (this && this.__importDefault) || function (mod) {
8306
+ return (mod && mod.__esModule) ? mod : { "default": mod };
8307
+ };
8162
8308
  Object.defineProperty(exports, "__esModule", ({ value: true }));
8163
8309
  exports.CatalogueGL = void 0;
8164
8310
  const Source_js_1 = __webpack_require__(146);
@@ -8167,6 +8313,8 @@ const CoordsType_js_1 = __webpack_require__(8145);
8167
8313
  const Utils_js_1 = __webpack_require__(7930);
8168
8314
  const CatalogueShaderProgram_js_1 = __webpack_require__(3559);
8169
8315
  const MetadataManager_js_1 = __webpack_require__(5403);
8316
+ const gl_matrix_1 = __webpack_require__(3890);
8317
+ const Global_js_1 = __importDefault(__webpack_require__(4382));
8170
8318
  class CatalogueGL {
8171
8319
  _kind = "CatalogueGL";
8172
8320
  static ELEM_SIZE = 6;
@@ -8193,16 +8341,19 @@ class CatalogueGL {
8193
8341
  _oldMouseCoords;
8194
8342
  _metadataManager;
8195
8343
  _isVisible = true;
8196
- _shapeColor = '#8F00FF';
8344
+ _shapeColor = "#8F00FF";
8197
8345
  _healpixDensityMap;
8198
8346
  _providerUrl;
8199
8347
  _catalogueShaderProgram;
8200
8348
  _visibleTilesManager;
8349
+ _mediaOverlayHost = null;
8350
+ _mediaElements = [];
8351
+ _svgMediaDataUrls = new Map();
8201
8352
  constructor(catalogueName, catalogueDescription, providerUrl, metadataManager, webgl, visibleTilesManager) {
8202
8353
  this._webgl = webgl;
8203
8354
  this._ready = false;
8204
8355
  this._visibleTilesManager = visibleTilesManager;
8205
- this.TYPE = 'SOURCE_CATALOGUE';
8356
+ this.TYPE = "SOURCE_CATALOGUE";
8206
8357
  this._name = catalogueName;
8207
8358
  this._description = catalogueDescription;
8208
8359
  this._providerUrl = providerUrl;
@@ -8220,7 +8371,7 @@ class CatalogueGL {
8220
8371
  this._oldMouseCoords = null;
8221
8372
  this._healpixDensityMap = new Map();
8222
8373
  // this.catalogueProps = new CatalogueProps(metadataManager, defaultColor);
8223
- // call catalogueShaderProgram to init shaders if they are not yet initialised
8374
+ // call catalogueShaderProgram to init shaders if they are not yet initialised
8224
8375
  this._catalogueShaderProgram = new CatalogueShaderProgram_js_1.CatalogueShaderProgram(this._webgl);
8225
8376
  this._catalogueShaderProgram.shaderProgram;
8226
8377
  // catalogueShaderProgram.shaderProgram
@@ -8265,7 +8416,7 @@ class CatalogueGL {
8265
8416
  }
8266
8417
  return {
8267
8418
  min: Number(min),
8268
- max: Number(max)
8419
+ max: Number(max),
8269
8420
  };
8270
8421
  }
8271
8422
  get metadataManager() {
@@ -8314,7 +8465,7 @@ class CatalogueGL {
8314
8465
  const raw = Number(source.getDetailByindex(idx));
8315
8466
  const min = Number(minmax.min);
8316
8467
  const max = Number(minmax.max);
8317
- const norm = (raw - min) / Math.max(1e-12, (max - min));
8468
+ const norm = (raw - min) / Math.max(1e-12, max - min);
8318
8469
  const size = norm * (20 - 8) + 8;
8319
8470
  source.shapeSize = size;
8320
8471
  }
@@ -8351,7 +8502,7 @@ class CatalogueGL {
8351
8502
  const raw = Number(source.getDetailByindex(idx));
8352
8503
  const min = Number(minmax.min);
8353
8504
  const max = Number(minmax.max);
8354
- const norm = (raw - min) / Math.max(1e-12, (max - min));
8505
+ const norm = (raw - min) / Math.max(1e-12, max - min);
8355
8506
  // map [0,1] -> [1,-1]
8356
8507
  source.brightnessFactor = -(norm * 2 - 1);
8357
8508
  }
@@ -8368,9 +8519,10 @@ class CatalogueGL {
8368
8519
  * @param in_data Rows of TAP results
8369
8520
  * @param columnsmeta TapMetadataList (unused here because `CatalogueProps` already holds indices)
8370
8521
  */
8371
- addSources(in_data, columnsmeta) {
8522
+ addSources(in_data, columnsmeta, options = {}) {
8372
8523
  this._ready = false;
8373
8524
  this._sources = [];
8525
+ this.clearMediaOverlay();
8374
8526
  this._metadataManager = new MetadataManager_js_1.MetadataManager(columnsmeta);
8375
8527
  // const raDataIndex = (this.catalogueProps.raColumn as any).index ?? (this.catalogueProps.raColumn as any)._index;
8376
8528
  // const decDataIndex = (this.catalogueProps.decColumn as any).index ?? (this.catalogueProps.decColumn as any)._index;
@@ -8381,9 +8533,13 @@ class CatalogueGL {
8381
8533
  for (let j = 0; j < in_data.length; j++) {
8382
8534
  const point = new Point_js_1.Point({
8383
8535
  raDeg: in_data[j][raDataIndex],
8384
- decDeg: in_data[j][decDataIndex]
8536
+ decDeg: in_data[j][decDataIndex],
8385
8537
  }, CoordsType_js_1.CoordsType.ASTRO);
8386
8538
  const source = new Source_js_1.Source(point, in_data[j]);
8539
+ const mediaStyle = this.extractMediaStyle(in_data[j], columnsmeta, options.mediaColumns);
8540
+ if (mediaStyle) {
8541
+ source.mediaStyle = mediaStyle;
8542
+ }
8387
8543
  // Ensure optional fields exist
8388
8544
  source.shapeSize = source.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8389
8545
  source.brightnessFactor = 3;
@@ -8403,11 +8559,222 @@ class CatalogueGL {
8403
8559
  this._ready = true;
8404
8560
  this._bufferInitialised = false;
8405
8561
  }
8562
+ getColumnIndex(columnsmeta, columnName) {
8563
+ if (!columnName)
8564
+ return -1;
8565
+ return columnsmeta.find((column) => column.name === columnName)?.index ?? -1;
8566
+ }
8567
+ readCell(row, columnsmeta, columnName) {
8568
+ const idx = this.getColumnIndex(columnsmeta, columnName);
8569
+ return idx >= 0 ? row[idx] : undefined;
8570
+ }
8571
+ extractMediaStyle(row, columnsmeta, mediaColumns) {
8572
+ if (!mediaColumns?.src)
8573
+ return undefined;
8574
+ const rawSrc = this.readCell(row, columnsmeta, mediaColumns.src);
8575
+ const src = String(rawSrc ?? "").trim();
8576
+ if (!src)
8577
+ return undefined;
8578
+ const rawKind = String(this.readCell(row, columnsmeta, mediaColumns.type) ?? "sprite").trim().toLowerCase();
8579
+ const kind = rawKind === "model"
8580
+ ? "model"
8581
+ : rawKind === "image"
8582
+ ? "image"
8583
+ : rawKind === "icon"
8584
+ ? "icon"
8585
+ : rawKind === "circle"
8586
+ ? "circle"
8587
+ : "sprite";
8588
+ if (kind === "circle" || kind === "model")
8589
+ return undefined;
8590
+ const scale = Number(this.readCell(row, columnsmeta, mediaColumns.scale));
8591
+ const rotationDeg = Number(this.readCell(row, columnsmeta, mediaColumns.rotation));
8592
+ const opacity = Number(this.readCell(row, columnsmeta, mediaColumns.opacity));
8593
+ return {
8594
+ kind,
8595
+ src,
8596
+ scale: Number.isFinite(scale) && scale > 0 ? scale : undefined,
8597
+ rotationDeg: Number.isFinite(rotationDeg) ? rotationDeg : undefined,
8598
+ opacity: Number.isFinite(opacity) ? Math.max(0, Math.min(1, opacity)) : undefined,
8599
+ };
8600
+ }
8406
8601
  clearSources() {
8407
8602
  this._sources = [];
8408
8603
  this.hoveredIndexes = [];
8409
8604
  this._healpixDensityMap.clear();
8410
8605
  this.vertexCataloguePosition = new Float32Array(0);
8606
+ this.clearMediaOverlay();
8607
+ }
8608
+ clearMediaOverlay() {
8609
+ this._mediaElements.forEach((el) => el.remove());
8610
+ this._mediaElements = [];
8611
+ if (this._mediaOverlayHost) {
8612
+ this._mediaOverlayHost.remove();
8613
+ this._mediaOverlayHost = null;
8614
+ }
8615
+ }
8616
+ ensureMediaOverlayHost() {
8617
+ const canvas = this._webgl?.canvas;
8618
+ const parent = canvas?.parentElement;
8619
+ if (!canvas || !parent)
8620
+ return null;
8621
+ const parentStyle = window.getComputedStyle(parent);
8622
+ if (parentStyle.position === "static") {
8623
+ parent.style.position = "relative";
8624
+ }
8625
+ if (!this._mediaOverlayHost) {
8626
+ const host = document.createElement("div");
8627
+ host.dataset.astroCatalogueMedia = "true";
8628
+ host.style.position = "absolute";
8629
+ host.style.left = `${canvas.offsetLeft}px`;
8630
+ host.style.top = `${canvas.offsetTop}px`;
8631
+ host.style.width = `${canvas.clientWidth}px`;
8632
+ host.style.height = `${canvas.clientHeight}px`;
8633
+ host.style.pointerEvents = "none";
8634
+ host.style.overflow = "hidden";
8635
+ host.style.zIndex = "4";
8636
+ canvas.style.position = canvas.style.position || "relative";
8637
+ canvas.style.zIndex = canvas.style.zIndex || "0";
8638
+ parent.appendChild(host);
8639
+ this._mediaOverlayHost = host;
8640
+ }
8641
+ else {
8642
+ this._mediaOverlayHost.style.left = `${canvas.offsetLeft}px`;
8643
+ this._mediaOverlayHost.style.top = `${canvas.offsetTop}px`;
8644
+ this._mediaOverlayHost.style.width = `${canvas.clientWidth}px`;
8645
+ this._mediaOverlayHost.style.height = `${canvas.clientHeight}px`;
8646
+ }
8647
+ return this._mediaOverlayHost;
8648
+ }
8649
+ ensureMediaElement(index, style) {
8650
+ let img = this._mediaElements[index];
8651
+ if (!img) {
8652
+ img = document.createElement("img");
8653
+ img.loading = "lazy";
8654
+ img.decoding = "async";
8655
+ img.style.position = "absolute";
8656
+ img.style.objectFit = "contain";
8657
+ img.style.pointerEvents = "none";
8658
+ img.style.transformOrigin = "center center";
8659
+ img.style.filter = "drop-shadow(0 1px 2px rgba(0, 0, 0, 0.55))";
8660
+ img.style.willChange = "transform, left, top";
8661
+ this._mediaElements[index] = img;
8662
+ }
8663
+ const src = String(style.src ?? "").trim();
8664
+ const resolvedSrc = src ? new URL(src, document.baseURI).href : "";
8665
+ if (resolvedSrc && img.getAttribute("src") !== resolvedSrc) {
8666
+ img.removeAttribute("data-astro-media-src-index");
8667
+ img.removeAttribute("data-astro-media-loaded");
8668
+ img.onerror = null;
8669
+ img.onload = null;
8670
+ img.setAttribute("src", resolvedSrc);
8671
+ if (/\.svg(?:[?#].*)?$/i.test(resolvedSrc)) {
8672
+ void this.loadSvgMediaAsDataUrl(img, resolvedSrc);
8673
+ }
8674
+ }
8675
+ return img;
8676
+ }
8677
+ async loadSvgMediaAsDataUrl(img, resolvedSrc) {
8678
+ try {
8679
+ let dataUrl = this._svgMediaDataUrls.get(resolvedSrc);
8680
+ if (!dataUrl) {
8681
+ const response = await fetch(resolvedSrc);
8682
+ if (!response.ok)
8683
+ return;
8684
+ const svg = await response.text();
8685
+ if (!/^\s*<svg[\s>]/i.test(svg))
8686
+ return;
8687
+ dataUrl = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;
8688
+ this._svgMediaDataUrls.set(resolvedSrc, dataUrl);
8689
+ }
8690
+ if (img.getAttribute("src") === resolvedSrc) {
8691
+ img.setAttribute("src", dataUrl);
8692
+ }
8693
+ }
8694
+ catch {
8695
+ // Keep the direct image src; remote servers may already provide a valid MIME type.
8696
+ }
8697
+ }
8698
+ isSourceOnVisibleHemisphere(source, in_mMatrix, vMatrix) {
8699
+ if (Global_js_1.default.insideSphere)
8700
+ return true;
8701
+ const invView = gl_matrix_1.mat4.create();
8702
+ if (!gl_matrix_1.mat4.invert(invView, vMatrix))
8703
+ return true;
8704
+ const cameraPos = gl_matrix_1.vec3.fromValues(invView[12], invView[13], invView[14]);
8705
+ const worldPoint4 = gl_matrix_1.vec4.fromValues(source.point.x, source.point.y, source.point.z, 1);
8706
+ gl_matrix_1.vec4.transformMat4(worldPoint4, worldPoint4, in_mMatrix);
8707
+ const worldPoint = gl_matrix_1.vec3.fromValues(worldPoint4[0], worldPoint4[1], worldPoint4[2]);
8708
+ const normal = gl_matrix_1.vec3.normalize(gl_matrix_1.vec3.create(), worldPoint);
8709
+ const toCamera = gl_matrix_1.vec3.subtract(gl_matrix_1.vec3.create(), cameraPos, worldPoint);
8710
+ return gl_matrix_1.vec3.dot(normal, toCamera) > 0;
8711
+ }
8712
+ updateMediaOverlay(in_mMatrix, vMatrix, pMatrix) {
8713
+ const sourcesWithMedia = this._sources.filter((source) => !!source.mediaStyle?.src);
8714
+ if (!sourcesWithMedia.length) {
8715
+ this.clearMediaOverlay();
8716
+ return;
8717
+ }
8718
+ const host = this.ensureMediaOverlayHost();
8719
+ const canvas = this._webgl.canvas;
8720
+ if (!host || !canvas.clientWidth || !canvas.clientHeight)
8721
+ return;
8722
+ const modelView = gl_matrix_1.mat4.create();
8723
+ const mvp = gl_matrix_1.mat4.create();
8724
+ gl_matrix_1.mat4.multiply(modelView, vMatrix, in_mMatrix);
8725
+ gl_matrix_1.mat4.multiply(mvp, pMatrix, modelView);
8726
+ const width = canvas.clientWidth;
8727
+ const height = canvas.clientHeight;
8728
+ for (let i = 0; i < this._sources.length; i++) {
8729
+ const source = this._sources[i];
8730
+ const style = source.mediaStyle;
8731
+ const img = this._mediaElements[i];
8732
+ if (!style?.src) {
8733
+ if (img)
8734
+ img.style.display = "none";
8735
+ continue;
8736
+ }
8737
+ if (!this.isSourceOnVisibleHemisphere(source, in_mMatrix, vMatrix)) {
8738
+ if (img)
8739
+ img.style.display = "none";
8740
+ continue;
8741
+ }
8742
+ const projected = gl_matrix_1.vec4.fromValues(source.point.x, source.point.y, source.point.z, 1);
8743
+ gl_matrix_1.vec4.transformMat4(projected, projected, mvp);
8744
+ if (!projected[3]) {
8745
+ if (img)
8746
+ img.style.display = "none";
8747
+ continue;
8748
+ }
8749
+ const ndcX = projected[0] / projected[3];
8750
+ const ndcY = projected[1] / projected[3];
8751
+ const ndcZ = projected[2] / projected[3];
8752
+ if (ndcX < -1.15 ||
8753
+ ndcX > 1.15 ||
8754
+ ndcY < -1.15 ||
8755
+ ndcY > 1.15 ||
8756
+ ndcZ < -1.15 ||
8757
+ ndcZ > 1.15) {
8758
+ if (img)
8759
+ img.style.display = "none";
8760
+ continue;
8761
+ }
8762
+ const mediaEl = this.ensureMediaElement(i, style);
8763
+ if (!mediaEl.parentElement)
8764
+ host.appendChild(mediaEl);
8765
+ const px = (ndcX * 0.5 + 0.5) * width;
8766
+ const py = (1 - (ndcY * 0.5 + 0.5)) * height;
8767
+ const baseSize = source.shapeSize || CatalogueGL.STANDARD_SHAPE_SIZE;
8768
+ const size = Math.max(8, baseSize * (style.scale ?? 2.4));
8769
+ const rotation = style.rotationDeg ?? 0;
8770
+ mediaEl.style.display = "block";
8771
+ mediaEl.style.left = `${px - size / 2}px`;
8772
+ mediaEl.style.top = `${py - size / 2}px`;
8773
+ mediaEl.style.width = `${size}px`;
8774
+ mediaEl.style.height = `${size}px`;
8775
+ mediaEl.style.opacity = `${style.opacity ?? 1}`;
8776
+ mediaEl.style.transform = `rotate(${rotation}deg)`;
8777
+ }
8411
8778
  }
8412
8779
  sourceMatches(left, right) {
8413
8780
  if (left === right)
@@ -8452,7 +8819,8 @@ class CatalogueGL {
8452
8819
  if (i >= 0) {
8453
8820
  this.hoveredIndexes.splice(i, 1);
8454
8821
  this.vertexCataloguePosition[base + 3] = 0.0; // not hovered
8455
- this.vertexCataloguePosition[base + 4] = this._sources[sIdx]?.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8822
+ this.vertexCataloguePosition[base + 4] =
8823
+ this._sources[sIdx]?.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8456
8824
  }
8457
8825
  }
8458
8826
  }
@@ -8476,7 +8844,8 @@ class CatalogueGL {
8476
8844
  if (i >= 0) {
8477
8845
  this.selectedIndexes.splice(i, 1);
8478
8846
  this.vertexCataloguePosition[base + 3] = 0.0; // not selected
8479
- this.vertexCataloguePosition[base + 4] = this._sources[sIdx]?.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8847
+ this.vertexCataloguePosition[base + 4] =
8848
+ this._sources[sIdx]?.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8480
8849
  }
8481
8850
  }
8482
8851
  }
@@ -8507,9 +8876,11 @@ class CatalogueGL {
8507
8876
  // hovered flag
8508
8877
  this.vertexCataloguePosition[positionIndex + 3] = 0.0;
8509
8878
  // size
8510
- this.vertexCataloguePosition[positionIndex + 4] = currSource.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8879
+ this.vertexCataloguePosition[positionIndex + 4] =
8880
+ currSource.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8511
8881
  // brightness
8512
- this.vertexCataloguePosition[positionIndex + 5] = currSource.brightnessFactor ?? 0.0;
8882
+ this.vertexCataloguePosition[positionIndex + 5] =
8883
+ currSource.brightnessFactor ?? 0.0;
8513
8884
  positionIndex += CatalogueGL.ELEM_SIZE;
8514
8885
  }
8515
8886
  this._webgl.bufferData(this._webgl.ARRAY_BUFFER, this.vertexCataloguePosition, this._webgl.STATIC_DRAW);
@@ -8543,50 +8914,8 @@ class CatalogueGL {
8543
8914
  return 0.0001;
8544
8915
  }
8545
8916
  }
8546
- checkClicking(in_mouseHelper) {
8547
- if (in_mouseHelper.x == null || in_mouseHelper.y == null || in_mouseHelper.z == null) {
8548
- console.log('CatalogueGL.checkClicking: missing mouse coords');
8549
- return [];
8550
- }
8551
- const clickedIndexes = [];
8552
- const mousePix = in_mouseHelper.computeNpix();
8553
- if (mousePix != null && this._healpixDensityMap.has(mousePix)) {
8554
- const candidates = this._healpixDensityMap.get(mousePix);
8555
- const selR = this.getSelectionRadius();
8556
- for (let i = 0; i < candidates.length; i++) {
8557
- const sourceIdx = candidates[i];
8558
- const source = this._sources[sourceIdx];
8559
- if (!source)
8560
- continue;
8561
- const dx = source.point.x - in_mouseHelper.x;
8562
- const dy = source.point.y - in_mouseHelper.y;
8563
- const dz = source.point.z - in_mouseHelper.z;
8564
- const dist = Math.sqrt(dx * dx + dy * dy + dz * dz);
8565
- if (dist <= selR) {
8566
- clickedIndexes.push(sourceIdx);
8567
- }
8568
- }
8569
- }
8570
- return clickedIndexes;
8571
- }
8572
- // private setSelectedIndexes(nextSelected: number[]) {
8573
- // const deduped = Array.from(new Set(nextSelected))
8574
- // .filter((idx) => idx >= 0 && idx < this._sources.length);
8575
- // if (this.vertexCataloguePosition.length) {
8576
- // for (const prevIdx of this.selectedIndexes) {
8577
- // if (deduped.includes(prevIdx)) continue;
8578
- // const base = prevIdx * CatalogueGL.ELEM_SIZE;
8579
- // if (base + 4 >= this.vertexCataloguePosition.length) continue;
8580
- // if (!this.hoveredIndexes.includes(prevIdx) && !this.extHoveredIndexes.includes(prevIdx)) {
8581
- // this.vertexCataloguePosition[base + 3] = 0.0;
8582
- // }
8583
- // this.vertexCataloguePosition[base + 4] = this._sources[prevIdx]?.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8584
- // }
8585
- // }
8586
- // this.selectedIndexes = deduped;
8587
- // }
8588
8917
  setSelectedIndexes(selectedIndex) {
8589
- selectedIndex.forEach(idx => {
8918
+ selectedIndex.forEach((idx) => {
8590
8919
  if (idx < 0 || idx >= this._sources.length)
8591
8920
  return;
8592
8921
  const base = idx * CatalogueGL.ELEM_SIZE;
@@ -8595,12 +8924,14 @@ class CatalogueGL {
8595
8924
  if (this.selectedIndexes.includes(idx)) {
8596
8925
  this.selectedIndexes.splice(this.selectedIndexes.indexOf(idx), 1);
8597
8926
  this.vertexCataloguePosition[base + 3] = 0.0; // not selected
8598
- this.vertexCataloguePosition[base + 4] = this._sources[idx]?.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8927
+ this.vertexCataloguePosition[base + 4] =
8928
+ this._sources[idx]?.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8599
8929
  }
8600
8930
  else {
8601
8931
  this.selectedIndexes.push(idx);
8602
8932
  this.vertexCataloguePosition[base + 3] = 2.0; // selected
8603
- this.vertexCataloguePosition[base + 4] = this._sources[idx]?.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8933
+ this.vertexCataloguePosition[base + 4] =
8934
+ this._sources[idx]?.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8604
8935
  }
8605
8936
  });
8606
8937
  }
@@ -8617,7 +8948,7 @@ class CatalogueGL {
8617
8948
  };
8618
8949
  }
8619
8950
  const sources = [];
8620
- pickedIndexes.forEach(idx => {
8951
+ pickedIndexes.forEach((idx) => {
8621
8952
  const source = this._sources[idx];
8622
8953
  if (source)
8623
8954
  sources.push(source);
@@ -8647,7 +8978,7 @@ class CatalogueGL {
8647
8978
  }
8648
8979
  const selectionState = [];
8649
8980
  const selectedSources = [];
8650
- clickedIndexes.forEach(idx => {
8981
+ clickedIndexes.forEach((idx) => {
8651
8982
  const source = this._sources[idx];
8652
8983
  if (!source)
8653
8984
  return;
@@ -8665,31 +8996,43 @@ class CatalogueGL {
8665
8996
  const idx = this.hoveredIndexes[0];
8666
8997
  return this._sources[idx] ?? null;
8667
8998
  }
8668
- checkHovering(in_mouseHelper) {
8669
- if (in_mouseHelper.x == null || in_mouseHelper.y == null || in_mouseHelper.z == null) {
8670
- console.log('CatalogueGL.checkHovering: missing mouse coords');
8671
- return [];
8999
+ findNearestSourceIndex(in_mouseHelper) {
9000
+ if (in_mouseHelper.x == null ||
9001
+ in_mouseHelper.y == null ||
9002
+ in_mouseHelper.z == null) {
9003
+ return null;
8672
9004
  }
8673
- const hoveredIndexes = [];
8674
9005
  const mousePix = in_mouseHelper.computeNpix();
8675
- if (mousePix != null && this._healpixDensityMap.has(mousePix)) {
8676
- const candidates = this._healpixDensityMap.get(mousePix);
8677
- const selR = this.getSelectionRadius();
8678
- for (let i = 0; i < candidates.length; i++) {
8679
- const sourceIdx = candidates[i];
8680
- const source = this._sources[sourceIdx];
8681
- if (!source)
8682
- continue;
8683
- const dx = source.point.x - in_mouseHelper.x;
8684
- const dy = source.point.y - in_mouseHelper.y;
8685
- const dz = source.point.z - in_mouseHelper.z;
8686
- const dist = Math.sqrt(dx * dx + dy * dy + dz * dz);
8687
- if (dist <= selR) {
8688
- hoveredIndexes.push(sourceIdx);
8689
- }
9006
+ if (mousePix == null)
9007
+ return null;
9008
+ const candidates = this._healpixDensityMap.get(mousePix);
9009
+ if (!candidates?.length)
9010
+ return null;
9011
+ const selR = this.getSelectionRadius();
9012
+ let nearestIndex = null;
9013
+ let nearestDistance = Number.POSITIVE_INFINITY;
9014
+ for (const sourceIdx of candidates) {
9015
+ const source = this._sources[sourceIdx];
9016
+ if (!source)
9017
+ continue;
9018
+ const dx = source.point.x - in_mouseHelper.x;
9019
+ const dy = source.point.y - in_mouseHelper.y;
9020
+ const dz = source.point.z - in_mouseHelper.z;
9021
+ const dist = Math.sqrt(dx * dx + dy * dy + dz * dz);
9022
+ if (dist <= selR && dist < nearestDistance) {
9023
+ nearestDistance = dist;
9024
+ nearestIndex = sourceIdx;
8690
9025
  }
8691
9026
  }
8692
- return hoveredIndexes;
9027
+ return nearestIndex;
9028
+ }
9029
+ checkClicking(in_mouseHelper) {
9030
+ const nearestIndex = this.findNearestSourceIndex(in_mouseHelper);
9031
+ return nearestIndex == null ? [] : [nearestIndex];
9032
+ }
9033
+ checkHovering(in_mouseHelper) {
9034
+ const nearestIndex = this.findNearestSourceIndex(in_mouseHelper);
9035
+ return nearestIndex == null ? [] : [nearestIndex];
8693
9036
  }
8694
9037
  /**
8695
9038
  * @param in_mMatrix Model matrix the current catalogue is associated to (e.g. HiPS matrix)
@@ -8736,7 +9079,8 @@ class CatalogueGL {
8736
9079
  const base = this.hoveredIndexes[k] * CatalogueGL.ELEM_SIZE;
8737
9080
  // if (this.vertexCataloguePosition[base + 3] == 2.0) continue; // selected, skip hover
8738
9081
  this.vertexCataloguePosition[base + 3] = 0.0; // not hovered
8739
- this.vertexCataloguePosition[base + 4] = this._sources[this.hoveredIndexes[k]].shapeSize; // size
9082
+ this.vertexCataloguePosition[base + 4] =
9083
+ this._sources[this.hoveredIndexes[k]].shapeSize; // size
8740
9084
  }
8741
9085
  // Hover logic on mouse move
8742
9086
  if (in_mouseHelper != null && in_mouseHelper.xyz !== this._oldMouseCoords) {
@@ -8770,6 +9114,7 @@ class CatalogueGL {
8770
9114
  // draw
8771
9115
  const numItems = this.vertexCataloguePosition.length / CatalogueGL.ELEM_SIZE;
8772
9116
  this._webgl.drawArrays(this._webgl.POINTS, 0, numItems);
9117
+ this.updateMediaOverlay(in_mMatrix, vMatrix, pMatrix);
8773
9118
  this._oldMouseCoords = in_mouseHelper.xyz;
8774
9119
  }
8775
9120
  }
@@ -10373,11 +10718,9 @@ class FootprintSetGL {
10373
10718
  _metadataManager;
10374
10719
  _providerUrl;
10375
10720
  _footprintShaderProgram;
10376
- _visibleTilesManager;
10377
- constructor(fsetName, fsetDescription, providerUrl, metadataManager, webgl, visibleTilesManager) {
10721
+ constructor(fsetName, fsetDescription, providerUrl, metadataManager, webgl) {
10378
10722
  this._webgl = webgl;
10379
10723
  this._ready = false;
10380
- this._visibleTilesManager = visibleTilesManager;
10381
10724
  this.TYPE = "FOOTPRINT_SET";
10382
10725
  this._name = fsetName;
10383
10726
  this._description = fsetDescription;
@@ -14695,7 +15038,9 @@ class MeshHiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
14695
15038
  const orders = Array.from(byOrder.keys()).sort((a, b) => a - b);
14696
15039
  for (const order of orders) {
14697
15040
  for (const coord of byOrder.get(order) ?? []) {
14698
- this._tiles.get(this.tileKey(coord))?.draw(pMatrix, vMatrix, mMatrix, this._descriptor.color, this._descriptor.wireframe);
15041
+ this._tiles
15042
+ .get(this.tileKey(coord))
15043
+ ?.draw(pMatrix, vMatrix, mMatrix, this._descriptor.color, this._descriptor.wireframe);
14699
15044
  }
14700
15045
  }
14701
15046
  if (wasCullFace)
@@ -14708,7 +15053,7 @@ class MeshHiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
14708
15053
  getDebugStats() {
14709
15054
  const tiles = Array.from(this._tiles.values());
14710
15055
  return {
14711
- activeBaseLayer: 'meships',
15056
+ activeBaseLayer: "meships",
14712
15057
  meshHiPSName: this._descriptor.name,
14713
15058
  meshHiPSUrl: this._descriptor.baseUrl,
14714
15059
  currentOrder: this._currentOrder,
@@ -14727,33 +15072,47 @@ class MeshHiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
14727
15072
  ? byOrder.pixels
14728
15073
  : [];
14729
15074
  if (pixels.length > 0) {
14730
- return pixels.map((ipix) => ({ order: this._currentOrder, ipix }));
15075
+ return pixels.map((ipix) => ({
15076
+ order: this._currentOrder,
15077
+ ipix,
15078
+ }));
14731
15079
  }
14732
15080
  const tileCount = 12 * 4 ** this._currentOrder;
14733
- return Array.from({ length: tileCount }, (_, ipix) => ({ order: this._currentOrder, ipix }));
15081
+ return Array.from({ length: tileCount }, (_, ipix) => ({
15082
+ order: this._currentOrder,
15083
+ ipix,
15084
+ }));
14734
15085
  }
14735
15086
  resolveCoverageTiles(visibleTiles) {
14736
15087
  const tiles = new Map();
14737
15088
  const add = (coord) => {
14738
- if (coord.order < this._descriptor.minOrder || coord.order > this._descriptor.maxOrder)
15089
+ if (coord.order < this._descriptor.minOrder ||
15090
+ coord.order > this._descriptor.maxOrder) {
14739
15091
  return;
15092
+ }
14740
15093
  tiles.set(this.tileKey(coord), coord);
14741
15094
  };
14742
15095
  for (const coord of visibleTiles) {
14743
15096
  add(coord);
14744
15097
  for (let order = coord.order - 1; order >= this._descriptor.minOrder; order--) {
14745
15098
  const shift = 2 * (coord.order - order);
14746
- add({ order, ipix: coord.ipix >> shift });
15099
+ add({
15100
+ order,
15101
+ ipix: coord.ipix >> shift,
15102
+ });
14747
15103
  }
14748
15104
  }
14749
15105
  const manager = this._healpixGrid.visibleTilesManager;
14750
15106
  const ancestorsMap = manager?.ancestorsMap;
14751
15107
  if (ancestorsMap) {
14752
15108
  for (const [order, ipixes] of ancestorsMap) {
14753
- if (order < this._descriptor.minOrder || order > this._descriptor.maxOrder)
15109
+ if (order < this._descriptor.minOrder ||
15110
+ order > this._descriptor.maxOrder) {
14754
15111
  continue;
14755
- for (const ipix of ipixes)
15112
+ }
15113
+ for (const ipix of ipixes) {
14756
15114
  add({ order, ipix });
15115
+ }
14757
15116
  }
14758
15117
  }
14759
15118
  return Array.from(tiles.values());
@@ -16379,6 +16738,9 @@ function normalizeLongitudeDeg(longitudeDeg) {
16379
16738
  *
16380
16739
  * See LICENSE.md, LICENSE-AGPL.md, and LICENSE-COMMERCIAL.md for details.
16381
16740
  */
16741
+ var __importDefault = (this && this.__importDefault) || function (mod) {
16742
+ return (mod && mod.__esModule) ? mod : { "default": mod };
16743
+ };
16382
16744
  Object.defineProperty(exports, "__esModule", ({ value: true }));
16383
16745
  exports.TerraFootprintSetGL = void 0;
16384
16746
  const FootprintSetGL_js_1 = __webpack_require__(592);
@@ -16387,6 +16749,8 @@ const Footprint_js_1 = __webpack_require__(2475);
16387
16749
  const MetadataColumn_js_1 = __webpack_require__(1072);
16388
16750
  const MetadataManager_js_1 = __webpack_require__(5403);
16389
16751
  const MetadataColumn_js_2 = __webpack_require__(1072);
16752
+ const Point_js_1 = __webpack_require__(6553);
16753
+ const GeomUtils_js_1 = __importDefault(__webpack_require__(2930));
16390
16754
  class TerraFootprintSetGL extends FootprintSetGL_js_1.FootprintSetGL {
16391
16755
  _kind = 'TerraFootprintSetGL';
16392
16756
  _coordsType = CoordsType_js_1.CoordsType.GEOGRAPHIC;
@@ -16405,6 +16769,23 @@ class TerraFootprintSetGL extends FootprintSetGL_js_1.FootprintSetGL {
16405
16769
  this._ready = true;
16406
16770
  this._bufferInitialised = false;
16407
16771
  }
16772
+ checkSelection(mouseHelper) {
16773
+ if (mouseHelper.x == null || mouseHelper.y == null || mouseHelper.z == null)
16774
+ return;
16775
+ const hoverState = this;
16776
+ hoverState._hoveredFootprints = [];
16777
+ this.totHoveredPoints = 0;
16778
+ const mousePoint = new Point_js_1.Point({ x: mouseHelper.x, y: mouseHelper.y, z: mouseHelper.z }, CoordsType_js_1.CoordsType.CARTESIAN);
16779
+ for (const footprint of this.footprintPolygons) {
16780
+ if (!footprint.selectionObj)
16781
+ continue;
16782
+ if (GeomUtils_js_1.default.checkPointInsidePolygon5(footprint.selectionObj, mousePoint)) {
16783
+ hoverState._hoveredFootprints.push(footprint);
16784
+ this.totHoveredPoints += footprint.totPoints;
16785
+ }
16786
+ }
16787
+ this.initHoveringBuffer();
16788
+ }
16408
16789
  createGeoJSONMetadataColumns(features) {
16409
16790
  const names = new Set();
16410
16791
  features.forEach(feature => Object.keys(feature.properties).forEach(name => names.add(name)));
@@ -16450,8 +16831,44 @@ exports.TerraFootprintSetGL = TerraFootprintSetGL;
16450
16831
  Object.defineProperty(exports, "__esModule", ({ value: true }));
16451
16832
  exports.TerraPointSetGL = void 0;
16452
16833
  const CatalogueGL_js_1 = __webpack_require__(1232);
16834
+ const MetadataManager_js_1 = __webpack_require__(5403);
16835
+ const Point_js_1 = __webpack_require__(6553);
16836
+ const CoordsType_js_1 = __webpack_require__(8145);
16453
16837
  class TerraPointSetGL extends CatalogueGL_js_1.CatalogueGL {
16454
16838
  _kind = 'TerraPointSetGL';
16839
+ addSources(inData, columnsMeta) {
16840
+ this._ready = false;
16841
+ this._sources = [];
16842
+ const metadataManager = new MetadataManager_js_1.MetadataManager(columnsMeta);
16843
+ this._metadataManager = metadataManager;
16844
+ const lonDataIndex = metadataManager.selectedRaColumn?.index ?? -1;
16845
+ const latDataIndex = metadataManager.selectedDecColumn?.index ?? -1;
16846
+ if (lonDataIndex < 0 || latDataIndex < 0) {
16847
+ throw new Error(`(lon, lat) idx not defined (${lonDataIndex}, ${latDataIndex}) `);
16848
+ }
16849
+ for (const row of inData) {
16850
+ const point = new Point_js_1.Point({
16851
+ lonDeg: Number(row[lonDataIndex]),
16852
+ latDeg: Number(row[latDataIndex]),
16853
+ }, CoordsType_js_1.CoordsType.GEOGRAPHIC);
16854
+ this.addSource({
16855
+ point,
16856
+ details: row,
16857
+ healpixPixel: 0,
16858
+ shapeSize: CatalogueGL_js_1.CatalogueGL.STANDARD_SHAPE_SIZE,
16859
+ brightnessFactor: 3,
16860
+ getDetailByindex(index) {
16861
+ return index < 0 || index >= row.length ? undefined : row[index];
16862
+ },
16863
+ });
16864
+ }
16865
+ this._ready = true;
16866
+ this._bufferInitialised = false;
16867
+ }
16868
+ draw(inMatrix, inMouseHelper, viewMatrix, projectionMatrix) {
16869
+ this._oldMouseCoords = inMouseHelper?.xyz ?? null;
16870
+ super.draw(inMatrix, inMouseHelper, viewMatrix, projectionMatrix);
16871
+ }
16455
16872
  }
16456
16873
  exports.TerraPointSetGL = TerraPointSetGL;
16457
16874
 
@@ -16485,7 +16902,6 @@ class TerraPolylineSetGL {
16485
16902
  _providerUrl;
16486
16903
  _metadataManager;
16487
16904
  _webgl;
16488
- _visibleTilesManager;
16489
16905
  static ELEM_SIZE = 3;
16490
16906
  static BYTES_X_ELEM = new Float32Array().BYTES_PER_ELEMENT;
16491
16907
  _kind = 'TerraPolylineSetGL';
@@ -16496,13 +16912,12 @@ class TerraPolylineSetGL {
16496
16912
  paths = [];
16497
16913
  renderSegments = [];
16498
16914
  _polylineShaderProgram;
16499
- constructor(_name, _description, _providerUrl, _metadataManager, _webgl, _visibleTilesManager) {
16915
+ constructor(_name, _description, _providerUrl, _metadataManager, _webgl) {
16500
16916
  this._name = _name;
16501
16917
  this._description = _description;
16502
16918
  this._providerUrl = _providerUrl;
16503
16919
  this._metadataManager = _metadataManager;
16504
16920
  this._webgl = _webgl;
16505
- this._visibleTilesManager = _visibleTilesManager;
16506
16921
  this._polylineShaderProgram = new FootprintShaderProgram_js_1.FootprintShaderProgram(this._webgl);
16507
16922
  }
16508
16923
  addPath(points, metadata) {
@@ -18840,7 +19255,8 @@ class MouseHelper {
18840
19255
  computeNpix() {
18841
19256
  if (!this._xyz)
18842
19257
  return null;
18843
- const hp = Global_js_1.default.getHealpix(Global_js_1.default.nsideForSelection);
19258
+ // const hp: Healpix = global.getHealpix(global.nsideForSelection);
19259
+ const hp = Global_js_1.default.getHealpix(Global_js_1.default.selectionOrder);
18844
19260
  const v = new healpix_1.Vec3(this._xyz[0], this._xyz[1], this._xyz[2]);
18845
19261
  const ptg = new healpix_1.Pointing(v, false);
18846
19262
  return hp.ang2pix(ptg, false);