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
@@ -43,6 +43,7 @@ __webpack_require__.d(vec3_namespaceObject, {
43
43
  dot: () => (dot),
44
44
  fromValues: () => (vec3_fromValues),
45
45
  length: () => (vec3_length),
46
+ lerp: () => (lerp),
46
47
  normalize: () => (normalize),
47
48
  scale: () => (vec3_scale),
48
49
  scaleAndAdd: () => (scaleAndAdd),
@@ -3895,6 +3896,7 @@ class AstroSphere {
3895
3896
  const handleMouseDown = (event) => {
3896
3897
  canvas.setPointerCapture(event.pointerId);
3897
3898
  this.mouseDown = true;
3899
+ this._camera.cancelFlyTo();
3898
3900
  const rect = canvas.getBoundingClientRect();
3899
3901
  this.lastMouseX = event.clientX - rect.left; // locale al canvas
3900
3902
  this.lastMouseY = event.clientY - rect.top; // locale al canvas
@@ -4021,6 +4023,7 @@ class AstroSphere {
4021
4023
  const handleMouseWheel = (event) => {
4022
4024
  const currentFov = this._healpixGrid.getMinFoV();
4023
4025
  const zoomStep = this.computeZoomStep(currentFov, event.deltaY);
4026
+ this._camera.cancelFlyTo();
4024
4027
  // Apply wheel zoom immediately and discard any queued inertia so reversing
4025
4028
  // direction feels responsive instead of "buffered".
4026
4029
  this.zoomInertia = 0;
@@ -4286,6 +4289,9 @@ class AstroSphere {
4286
4289
  goTo(raDeg, decDeg) {
4287
4290
  this._camera.goTo(raDeg, decDeg);
4288
4291
  }
4292
+ flyTo(raDeg, decDeg, durationMs = 1200) {
4293
+ this._camera.flyTo(raDeg, decDeg, durationMs);
4294
+ }
4289
4295
  getActiveCoordinateMode() {
4290
4296
  if (this._activeBaseLayer === "xyz") {
4291
4297
  return "lonlat";
@@ -4521,6 +4527,16 @@ class AstroSphere {
4521
4527
  let PHI = 0;
4522
4528
  this._webgl.viewport(0, 0, this._webgl.drawingBufferWidth, this._webgl.drawingBufferHeight);
4523
4529
  this._webgl.clear(this._webgl.COLOR_BUFFER_BIT | this._webgl.DEPTH_BUFFER_BIT);
4530
+ const now = performance.now();
4531
+ const cameraFlying = this._camera.updateFlyTo(now);
4532
+ if (cameraFlying) {
4533
+ this.inertiaX = 0;
4534
+ this.inertiaY = 0;
4535
+ this.lastCameraMotionAt = now;
4536
+ this._cameraStatusChanged = true;
4537
+ this.updateCentralPoint();
4538
+ 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);
4539
+ }
4524
4540
  // Zoom inertia
4525
4541
  if (this.zoomInertia !== 0) {
4526
4542
  if (Math.abs(this.zoomInertia) > 0.0001) {
@@ -4826,7 +4842,7 @@ class AstroViewer {
4826
4842
  }
4827
4843
  //FOOTPRINT
4828
4844
  createFootprintSet(footprintSetName, footprintSetDescription, providerUrl, metadataManager) {
4829
- return new FootprintSetGL_js_1.FootprintSetGL(footprintSetName, footprintSetDescription, providerUrl, metadataManager, this.webgl, this.astroSphere.healpixGrid.visibleTilesManager);
4845
+ return new FootprintSetGL_js_1.FootprintSetGL(footprintSetName, footprintSetDescription, providerUrl, metadataManager, this.webgl);
4830
4846
  }
4831
4847
  showFootprintSet(footprintSet) {
4832
4848
  this.astroSphere.showFootprintSet(footprintSet);
@@ -4851,7 +4867,7 @@ class AstroViewer {
4851
4867
  this.astroSphere.deleteCatalogue(pointSet);
4852
4868
  }
4853
4869
  createTerraFootprintSet(footprintSetName, footprintSetDescription, providerUrl, metadataManager) {
4854
- return new TerraFootprintSetGL_js_1.TerraFootprintSetGL(footprintSetName, footprintSetDescription, providerUrl, metadataManager, this.webgl, this.astroSphere.healpixGrid.visibleTilesManager);
4870
+ return new TerraFootprintSetGL_js_1.TerraFootprintSetGL(footprintSetName, footprintSetDescription, providerUrl, metadataManager, this.webgl);
4855
4871
  }
4856
4872
  showTerraFootprintSet(footprintSet) {
4857
4873
  this.astroSphere.showFootprintSet(footprintSet);
@@ -4863,7 +4879,7 @@ class AstroViewer {
4863
4879
  this.astroSphere.deleteFootprintSet(footprintSet);
4864
4880
  }
4865
4881
  createTerraPolylineSet(polylineSetName, polylineSetDescription, providerUrl, metadataManager) {
4866
- return new TerraPolylineSetGL_js_1.TerraPolylineSetGL(polylineSetName, polylineSetDescription, providerUrl, metadataManager, this.webgl, this.astroSphere.healpixGrid.visibleTilesManager);
4882
+ return new TerraPolylineSetGL_js_1.TerraPolylineSetGL(polylineSetName, polylineSetDescription, providerUrl, metadataManager, this.webgl);
4867
4883
  }
4868
4884
  showTerraPolylineSet(polylineSet) {
4869
4885
  this.astroSphere.showPolylineSet(polylineSet);
@@ -5051,6 +5067,9 @@ class AstroViewer {
5051
5067
  // console.log(`AstroViewer.goTo goto(${raDeg}, ${decDeg})`)
5052
5068
  this.astroSphere.goTo(raDeg, decDeg);
5053
5069
  }
5070
+ flyTo(raDeg, decDeg, durationMs = 1200) {
5071
+ this.astroSphere.flyTo(raDeg, decDeg, durationMs);
5072
+ }
5054
5073
  getActiveCoordinateMode() {
5055
5074
  return this.astroSphere.getActiveCoordinateMode();
5056
5075
  }
@@ -5372,6 +5391,7 @@ class Camera {
5372
5391
  lockRotX = false;
5373
5392
  lockRotY = false;
5374
5393
  lockRotZ = false;
5394
+ flyToAnimation = null;
5375
5395
  constructor(in_position, in_sphere) {
5376
5396
  this.init(in_position, in_sphere);
5377
5397
  }
@@ -5381,7 +5401,11 @@ class Camera {
5381
5401
  this.vMatrix = gl_matrix_1.mat4.create();
5382
5402
  this.T = gl_matrix_1.mat4.create();
5383
5403
  this.R = gl_matrix_1.mat4.create();
5384
- gl_matrix_1.mat4.translate(this.T, this.T, [this.cam_pos[0], this.cam_pos[1], this.cam_pos[2]]);
5404
+ gl_matrix_1.mat4.translate(this.T, this.T, [
5405
+ this.cam_pos[0],
5406
+ this.cam_pos[1],
5407
+ this.cam_pos[2],
5408
+ ]);
5385
5409
  // reset helpers
5386
5410
  this.FoV = this.previousFoV = 180.0;
5387
5411
  this.move = gl_matrix_1.vec3.clone([0, 0, 0]);
@@ -5390,11 +5414,15 @@ class Camera {
5390
5414
  this.goTo(raDeg, decDeg);
5391
5415
  }
5392
5416
  goTo(raDeg, decDeg) {
5417
+ this.cancelFlyTo();
5393
5418
  this.goToPhiTheta((0, Utils_js_1.astroDegToSpherical)(raDeg, decDeg));
5394
5419
  }
5395
5420
  goToPhiTheta(ptDeg) {
5396
5421
  const xyz = (0, Utils_js_1.sphericalToCartesian)(ptDeg.phi, ptDeg.theta, this.cam_pos[2]);
5397
- const targetDirection = gl_matrix_1.vec3.normalize(gl_matrix_1.vec3.create(), gl_matrix_1.vec3.fromValues(xyz[0], xyz[1], xyz[2]));
5422
+ this.applyCameraPosition(gl_matrix_1.vec3.fromValues(xyz[0], xyz[1], xyz[2]));
5423
+ }
5424
+ applyCameraPosition(cameraPosition) {
5425
+ const targetDirection = gl_matrix_1.vec3.normalize(gl_matrix_1.vec3.create(), cameraPosition);
5398
5426
  const celestialNorth = gl_matrix_1.vec3.fromValues(0.0, 0.0, 1.0);
5399
5427
  const northProjection = gl_matrix_1.vec3.scale(gl_matrix_1.vec3.create(), targetDirection, gl_matrix_1.vec3.dot(celestialNorth, targetDirection));
5400
5428
  const cameraUp = gl_matrix_1.vec3.subtract(gl_matrix_1.vec3.create(), celestialNorth, northProjection);
@@ -5405,9 +5433,13 @@ class Camera {
5405
5433
  gl_matrix_1.vec3.normalize(cameraUp, cameraUp);
5406
5434
  }
5407
5435
  let cameraMatrix = gl_matrix_1.mat4.create();
5408
- cameraMatrix = gl_matrix_1.mat4.translate(cameraMatrix, cameraMatrix, gl_matrix_1.vec3.fromValues(xyz[0], xyz[1], xyz[2]));
5436
+ cameraMatrix = gl_matrix_1.mat4.translate(cameraMatrix, cameraMatrix, cameraPosition);
5409
5437
  const focusPoint = [0.0, 0.0, 0.0];
5410
- const cameraPos = [cameraMatrix[12], cameraMatrix[13], cameraMatrix[14]];
5438
+ const cameraPos = [
5439
+ cameraMatrix[12],
5440
+ cameraMatrix[13],
5441
+ cameraMatrix[14],
5442
+ ];
5411
5443
  cameraMatrix = gl_matrix_1.mat4.targetTo(cameraMatrix, cameraPos, focusPoint, cameraUp);
5412
5444
  this.R = gl_matrix_1.mat4.clone(cameraMatrix);
5413
5445
  this.R[12] = 0;
@@ -5419,6 +5451,81 @@ class Camera {
5419
5451
  }
5420
5452
  this.vMatrix = viewMatrix;
5421
5453
  }
5454
+ flyTo(raDeg, decDeg, durationMs = 1200) {
5455
+ const targetSpherical = (0, Utils_js_1.astroDegToSpherical)(raDeg, decDeg);
5456
+ const targetPositionValues = (0, Utils_js_1.sphericalToCartesian)(targetSpherical.phi, targetSpherical.theta, this.cam_pos[2]);
5457
+ const targetPosition = gl_matrix_1.vec3.fromValues(targetPositionValues[0], targetPositionValues[1], targetPositionValues[2]);
5458
+ const currentPosition = this.getCameraPosition();
5459
+ const startDirection = gl_matrix_1.vec3.normalize(gl_matrix_1.vec3.create(), gl_matrix_1.vec3.fromValues(currentPosition[0], currentPosition[1], currentPosition[2]));
5460
+ const targetDirection = gl_matrix_1.vec3.normalize(gl_matrix_1.vec3.create(), targetPosition);
5461
+ this.flyToAnimation = {
5462
+ startDirection,
5463
+ targetDirection,
5464
+ targetPosition,
5465
+ startTime: performance.now(),
5466
+ durationMs: Math.max(1, durationMs),
5467
+ };
5468
+ }
5469
+ updateFlyTo(now) {
5470
+ const animation = this.flyToAnimation;
5471
+ if (!animation) {
5472
+ return false;
5473
+ }
5474
+ const elapsed = now - animation.startTime;
5475
+ const progress = Math.min(1, elapsed / animation.durationMs);
5476
+ const easedProgress = progress < 0.5
5477
+ ? 4 * progress * progress * progress
5478
+ : 1 - Math.pow(-2 * progress + 2, 3) / 2;
5479
+ const direction = this.slerpDirection(animation.startDirection, animation.targetDirection, easedProgress);
5480
+ const radius = Math.abs(this.cam_pos[2]);
5481
+ const cameraPosition = gl_matrix_1.vec3.scale(gl_matrix_1.vec3.create(), direction, radius);
5482
+ this.applyCameraPosition(cameraPosition);
5483
+ if (progress >= 1) {
5484
+ this.applyCameraPosition(animation.targetPosition);
5485
+ this.flyToAnimation = null;
5486
+ }
5487
+ return true;
5488
+ }
5489
+ slerpDirection(start, end, t) {
5490
+ const dot = Math.max(-1, Math.min(1, gl_matrix_1.vec3.dot(start, end)));
5491
+ /*
5492
+ * For almost identical directions, normalized linear interpolation is
5493
+ * numerically more stable than the general SLERP formula.
5494
+ */
5495
+ if (dot > 0.999999) {
5496
+ const result = gl_matrix_1.vec3.lerp(gl_matrix_1.vec3.create(), start, end, t);
5497
+ return gl_matrix_1.vec3.normalize(result, result);
5498
+ }
5499
+ /*
5500
+ * The normal SLERP formula becomes singular for antipodal vectors because
5501
+ * sin(pi) = 0. In that case choose a stable vector orthogonal to start and
5502
+ * rotate through that great circle.
5503
+ */
5504
+ if (dot < -0.999999) {
5505
+ const referenceAxis = Math.abs(start[0]) < 0.9
5506
+ ? gl_matrix_1.vec3.fromValues(1, 0, 0)
5507
+ : gl_matrix_1.vec3.fromValues(0, 1, 0);
5508
+ const orthogonal = gl_matrix_1.vec3.cross(gl_matrix_1.vec3.create(), start, referenceAxis);
5509
+ gl_matrix_1.vec3.normalize(orthogonal, orthogonal);
5510
+ const angle = Math.PI * t;
5511
+ const result = gl_matrix_1.vec3.create();
5512
+ gl_matrix_1.vec3.scale(result, start, Math.cos(angle));
5513
+ gl_matrix_1.vec3.scaleAndAdd(result, result, orthogonal, Math.sin(angle));
5514
+ return gl_matrix_1.vec3.normalize(result, result);
5515
+ }
5516
+ const angle = Math.acos(dot);
5517
+ const sinAngle = Math.sin(angle);
5518
+ const startWeight = Math.sin((1 - t) * angle) / sinAngle;
5519
+ const endWeight = Math.sin(t * angle) / sinAngle;
5520
+ const result = gl_matrix_1.vec3.create();
5521
+ result[0] = start[0] * startWeight + end[0] * endWeight;
5522
+ result[1] = start[1] * startWeight + end[1] * endWeight;
5523
+ result[2] = start[2] * startWeight + end[2] * endWeight;
5524
+ return gl_matrix_1.vec3.normalize(result, result);
5525
+ }
5526
+ cancelFlyTo() {
5527
+ this.flyToAnimation = null;
5528
+ }
5422
5529
  toggleInsideSphere() {
5423
5530
  // if (inside !== global.insideSphere) {
5424
5531
  // global.insideSphere = inside;
@@ -5676,9 +5783,15 @@ class Camera {
5676
5783
  clearRotationLock() {
5677
5784
  this.lockRotX = this.lockRotY = this.lockRotZ = false;
5678
5785
  }
5679
- isRotationLockedX() { return this.lockRotX; }
5680
- isRotationLockedY() { return this.lockRotY; }
5681
- isRotationLockedZ() { return this.lockRotZ; }
5786
+ isRotationLockedX() {
5787
+ return this.lockRotX;
5788
+ }
5789
+ isRotationLockedY() {
5790
+ return this.lockRotY;
5791
+ }
5792
+ isRotationLockedZ() {
5793
+ return this.lockRotZ;
5794
+ }
5682
5795
  }
5683
5796
  exports["default"] = Camera;
5684
5797
 
@@ -5762,7 +5875,7 @@ class Global {
5762
5875
  // private _gl: GL | null;
5763
5876
  _healpix;
5764
5877
  // --- config/state flags ---
5765
- _selectionnside;
5878
+ // private _selectionnside: number;
5766
5879
  // private _healpix4footprints: boolean;
5767
5880
  _useCORSProxy;
5768
5881
  _corsProxyUrl;
@@ -5770,6 +5883,7 @@ class Global {
5770
5883
  _debug;
5771
5884
  _insideSphere;
5772
5885
  _version;
5886
+ _selectionOrder;
5773
5887
  constructor() {
5774
5888
  this._useCORSProxy = Config_js_1.bootSetup.useCORSProxy;
5775
5889
  this._corsProxyUrl = Config_js_1.bootSetup.corsProxyUrl;
@@ -5778,18 +5892,34 @@ class Global {
5778
5892
  this._insideSphere = Config_js_1.bootSetup.insideView;
5779
5893
  this._version = Config_js_1.bootSetup.version;
5780
5894
  this._healpix = {};
5781
- this._selectionnside = 32;
5895
+ // this._selectionnside = 32;
5896
+ this._selectionOrder = 5;
5897
+ }
5898
+ get selectionOrder() {
5899
+ return this._selectionOrder;
5782
5900
  }
5783
5901
  init() {
5784
- console.log('Global.init()');
5902
+ console.log("Global.init()");
5785
5903
  }
5786
5904
  // --- getters/setters ---
5787
- get version() { return this._version; }
5788
- set corsProxyUrl(url) { this._corsProxyUrl = url; }
5789
- get corsProxyUrl() { return this._corsProxyUrl; }
5790
- get useCORSProxy() { return this._useCORSProxy; }
5791
- set useCORSProxy(enabled) { this._useCORSProxy = enabled; }
5792
- get debug() { return this._debug; }
5905
+ get version() {
5906
+ return this._version;
5907
+ }
5908
+ set corsProxyUrl(url) {
5909
+ this._corsProxyUrl = url;
5910
+ }
5911
+ get corsProxyUrl() {
5912
+ return this._corsProxyUrl;
5913
+ }
5914
+ get useCORSProxy() {
5915
+ return this._useCORSProxy;
5916
+ }
5917
+ set useCORSProxy(enabled) {
5918
+ this._useCORSProxy = enabled;
5919
+ }
5920
+ get debug() {
5921
+ return this._debug;
5922
+ }
5793
5923
  getHealpix(order) {
5794
5924
  if (this._healpix[order] === undefined) {
5795
5925
  // order is HEALPix "order" ⇒ nside = 2^order
@@ -5797,10 +5927,15 @@ class Global {
5797
5927
  }
5798
5928
  return this._healpix[order];
5799
5929
  }
5800
- get MAX_DECIMALS() { return this._maxDecimals; }
5801
- set insideSphere(v) { this._insideSphere = v; }
5802
- get insideSphere() { return this._insideSphere; }
5803
- get nsideForSelection() { return this._selectionnside; }
5930
+ get MAX_DECIMALS() {
5931
+ return this._maxDecimals;
5932
+ }
5933
+ set insideSphere(v) {
5934
+ this._insideSphere = v;
5935
+ }
5936
+ get insideSphere() {
5937
+ return this._insideSphere;
5938
+ }
5804
5939
  }
5805
5940
  const global = new Global();
5806
5941
  exports["default"] = global;
@@ -7858,6 +7993,7 @@ class Source {
7858
7993
  _h_pix;
7859
7994
  _shapesize;
7860
7995
  _brightnessFactor;
7996
+ _mediaStyle;
7861
7997
  /**
7862
7998
  * @param in_point Point.js (Cartesian/RA-Dec wrapper)
7863
7999
  * @param in_details Optional array of key/value metadata
@@ -7880,7 +8016,8 @@ class Source {
7880
8016
  }
7881
8017
  computeHealpixPixel() {
7882
8018
  // Get Healpix instance from global
7883
- const healpix = Global_js_1.default.getHealpix(Global_js_1.default.nsideForSelection);
8019
+ // const healpix: Healpix = global.getHealpix(global.nsideForSelection);
8020
+ const healpix = Global_js_1.default.getHealpix(Global_js_1.default.selectionOrder);
7884
8021
  const vec3 = new healpix_1.Vec3(this._point.x, this._point.y, this._point.z);
7885
8022
  const ptg = new healpix_1.Pointing(vec3, false);
7886
8023
  this._h_pix = healpix.ang2pix(ptg, false);
@@ -7909,6 +8046,12 @@ class Source {
7909
8046
  set brightnessFactor(factor) {
7910
8047
  this._brightnessFactor = factor;
7911
8048
  }
8049
+ get mediaStyle() {
8050
+ return this._mediaStyle;
8051
+ }
8052
+ set mediaStyle(style) {
8053
+ this._mediaStyle = style;
8054
+ }
7912
8055
  }
7913
8056
  exports.Source = Source;
7914
8057
 
@@ -8134,6 +8277,9 @@ exports.SphereFoV = SphereFoV;
8134
8277
  *
8135
8278
  * See LICENSE.md, LICENSE-AGPL.md, and LICENSE-COMMERCIAL.md for details.
8136
8279
  */
8280
+ var __importDefault = (this && this.__importDefault) || function (mod) {
8281
+ return (mod && mod.__esModule) ? mod : { "default": mod };
8282
+ };
8137
8283
  Object.defineProperty(exports, "__esModule", ({ value: true }));
8138
8284
  exports.CatalogueGL = void 0;
8139
8285
  const Source_js_1 = __webpack_require__(146);
@@ -8142,6 +8288,8 @@ const CoordsType_js_1 = __webpack_require__(8145);
8142
8288
  const Utils_js_1 = __webpack_require__(7930);
8143
8289
  const CatalogueShaderProgram_js_1 = __webpack_require__(3559);
8144
8290
  const MetadataManager_js_1 = __webpack_require__(5403);
8291
+ const gl_matrix_1 = __webpack_require__(3890);
8292
+ const Global_js_1 = __importDefault(__webpack_require__(4382));
8145
8293
  class CatalogueGL {
8146
8294
  _kind = "CatalogueGL";
8147
8295
  static ELEM_SIZE = 6;
@@ -8168,16 +8316,19 @@ class CatalogueGL {
8168
8316
  _oldMouseCoords;
8169
8317
  _metadataManager;
8170
8318
  _isVisible = true;
8171
- _shapeColor = '#8F00FF';
8319
+ _shapeColor = "#8F00FF";
8172
8320
  _healpixDensityMap;
8173
8321
  _providerUrl;
8174
8322
  _catalogueShaderProgram;
8175
8323
  _visibleTilesManager;
8324
+ _mediaOverlayHost = null;
8325
+ _mediaElements = [];
8326
+ _svgMediaDataUrls = new Map();
8176
8327
  constructor(catalogueName, catalogueDescription, providerUrl, metadataManager, webgl, visibleTilesManager) {
8177
8328
  this._webgl = webgl;
8178
8329
  this._ready = false;
8179
8330
  this._visibleTilesManager = visibleTilesManager;
8180
- this.TYPE = 'SOURCE_CATALOGUE';
8331
+ this.TYPE = "SOURCE_CATALOGUE";
8181
8332
  this._name = catalogueName;
8182
8333
  this._description = catalogueDescription;
8183
8334
  this._providerUrl = providerUrl;
@@ -8195,7 +8346,7 @@ class CatalogueGL {
8195
8346
  this._oldMouseCoords = null;
8196
8347
  this._healpixDensityMap = new Map();
8197
8348
  // this.catalogueProps = new CatalogueProps(metadataManager, defaultColor);
8198
- // call catalogueShaderProgram to init shaders if they are not yet initialised
8349
+ // call catalogueShaderProgram to init shaders if they are not yet initialised
8199
8350
  this._catalogueShaderProgram = new CatalogueShaderProgram_js_1.CatalogueShaderProgram(this._webgl);
8200
8351
  this._catalogueShaderProgram.shaderProgram;
8201
8352
  // catalogueShaderProgram.shaderProgram
@@ -8240,7 +8391,7 @@ class CatalogueGL {
8240
8391
  }
8241
8392
  return {
8242
8393
  min: Number(min),
8243
- max: Number(max)
8394
+ max: Number(max),
8244
8395
  };
8245
8396
  }
8246
8397
  get metadataManager() {
@@ -8289,7 +8440,7 @@ class CatalogueGL {
8289
8440
  const raw = Number(source.getDetailByindex(idx));
8290
8441
  const min = Number(minmax.min);
8291
8442
  const max = Number(minmax.max);
8292
- const norm = (raw - min) / Math.max(1e-12, (max - min));
8443
+ const norm = (raw - min) / Math.max(1e-12, max - min);
8293
8444
  const size = norm * (20 - 8) + 8;
8294
8445
  source.shapeSize = size;
8295
8446
  }
@@ -8326,7 +8477,7 @@ class CatalogueGL {
8326
8477
  const raw = Number(source.getDetailByindex(idx));
8327
8478
  const min = Number(minmax.min);
8328
8479
  const max = Number(minmax.max);
8329
- const norm = (raw - min) / Math.max(1e-12, (max - min));
8480
+ const norm = (raw - min) / Math.max(1e-12, max - min);
8330
8481
  // map [0,1] -> [1,-1]
8331
8482
  source.brightnessFactor = -(norm * 2 - 1);
8332
8483
  }
@@ -8343,9 +8494,10 @@ class CatalogueGL {
8343
8494
  * @param in_data Rows of TAP results
8344
8495
  * @param columnsmeta TapMetadataList (unused here because `CatalogueProps` already holds indices)
8345
8496
  */
8346
- addSources(in_data, columnsmeta) {
8497
+ addSources(in_data, columnsmeta, options = {}) {
8347
8498
  this._ready = false;
8348
8499
  this._sources = [];
8500
+ this.clearMediaOverlay();
8349
8501
  this._metadataManager = new MetadataManager_js_1.MetadataManager(columnsmeta);
8350
8502
  // const raDataIndex = (this.catalogueProps.raColumn as any).index ?? (this.catalogueProps.raColumn as any)._index;
8351
8503
  // const decDataIndex = (this.catalogueProps.decColumn as any).index ?? (this.catalogueProps.decColumn as any)._index;
@@ -8356,9 +8508,13 @@ class CatalogueGL {
8356
8508
  for (let j = 0; j < in_data.length; j++) {
8357
8509
  const point = new Point_js_1.Point({
8358
8510
  raDeg: in_data[j][raDataIndex],
8359
- decDeg: in_data[j][decDataIndex]
8511
+ decDeg: in_data[j][decDataIndex],
8360
8512
  }, CoordsType_js_1.CoordsType.ASTRO);
8361
8513
  const source = new Source_js_1.Source(point, in_data[j]);
8514
+ const mediaStyle = this.extractMediaStyle(in_data[j], columnsmeta, options.mediaColumns);
8515
+ if (mediaStyle) {
8516
+ source.mediaStyle = mediaStyle;
8517
+ }
8362
8518
  // Ensure optional fields exist
8363
8519
  source.shapeSize = source.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8364
8520
  source.brightnessFactor = 3;
@@ -8378,11 +8534,222 @@ class CatalogueGL {
8378
8534
  this._ready = true;
8379
8535
  this._bufferInitialised = false;
8380
8536
  }
8537
+ getColumnIndex(columnsmeta, columnName) {
8538
+ if (!columnName)
8539
+ return -1;
8540
+ return columnsmeta.find((column) => column.name === columnName)?.index ?? -1;
8541
+ }
8542
+ readCell(row, columnsmeta, columnName) {
8543
+ const idx = this.getColumnIndex(columnsmeta, columnName);
8544
+ return idx >= 0 ? row[idx] : undefined;
8545
+ }
8546
+ extractMediaStyle(row, columnsmeta, mediaColumns) {
8547
+ if (!mediaColumns?.src)
8548
+ return undefined;
8549
+ const rawSrc = this.readCell(row, columnsmeta, mediaColumns.src);
8550
+ const src = String(rawSrc ?? "").trim();
8551
+ if (!src)
8552
+ return undefined;
8553
+ const rawKind = String(this.readCell(row, columnsmeta, mediaColumns.type) ?? "sprite").trim().toLowerCase();
8554
+ const kind = rawKind === "model"
8555
+ ? "model"
8556
+ : rawKind === "image"
8557
+ ? "image"
8558
+ : rawKind === "icon"
8559
+ ? "icon"
8560
+ : rawKind === "circle"
8561
+ ? "circle"
8562
+ : "sprite";
8563
+ if (kind === "circle" || kind === "model")
8564
+ return undefined;
8565
+ const scale = Number(this.readCell(row, columnsmeta, mediaColumns.scale));
8566
+ const rotationDeg = Number(this.readCell(row, columnsmeta, mediaColumns.rotation));
8567
+ const opacity = Number(this.readCell(row, columnsmeta, mediaColumns.opacity));
8568
+ return {
8569
+ kind,
8570
+ src,
8571
+ scale: Number.isFinite(scale) && scale > 0 ? scale : undefined,
8572
+ rotationDeg: Number.isFinite(rotationDeg) ? rotationDeg : undefined,
8573
+ opacity: Number.isFinite(opacity) ? Math.max(0, Math.min(1, opacity)) : undefined,
8574
+ };
8575
+ }
8381
8576
  clearSources() {
8382
8577
  this._sources = [];
8383
8578
  this.hoveredIndexes = [];
8384
8579
  this._healpixDensityMap.clear();
8385
8580
  this.vertexCataloguePosition = new Float32Array(0);
8581
+ this.clearMediaOverlay();
8582
+ }
8583
+ clearMediaOverlay() {
8584
+ this._mediaElements.forEach((el) => el.remove());
8585
+ this._mediaElements = [];
8586
+ if (this._mediaOverlayHost) {
8587
+ this._mediaOverlayHost.remove();
8588
+ this._mediaOverlayHost = null;
8589
+ }
8590
+ }
8591
+ ensureMediaOverlayHost() {
8592
+ const canvas = this._webgl?.canvas;
8593
+ const parent = canvas?.parentElement;
8594
+ if (!canvas || !parent)
8595
+ return null;
8596
+ const parentStyle = window.getComputedStyle(parent);
8597
+ if (parentStyle.position === "static") {
8598
+ parent.style.position = "relative";
8599
+ }
8600
+ if (!this._mediaOverlayHost) {
8601
+ const host = document.createElement("div");
8602
+ host.dataset.astroCatalogueMedia = "true";
8603
+ host.style.position = "absolute";
8604
+ host.style.left = `${canvas.offsetLeft}px`;
8605
+ host.style.top = `${canvas.offsetTop}px`;
8606
+ host.style.width = `${canvas.clientWidth}px`;
8607
+ host.style.height = `${canvas.clientHeight}px`;
8608
+ host.style.pointerEvents = "none";
8609
+ host.style.overflow = "hidden";
8610
+ host.style.zIndex = "4";
8611
+ canvas.style.position = canvas.style.position || "relative";
8612
+ canvas.style.zIndex = canvas.style.zIndex || "0";
8613
+ parent.appendChild(host);
8614
+ this._mediaOverlayHost = host;
8615
+ }
8616
+ else {
8617
+ this._mediaOverlayHost.style.left = `${canvas.offsetLeft}px`;
8618
+ this._mediaOverlayHost.style.top = `${canvas.offsetTop}px`;
8619
+ this._mediaOverlayHost.style.width = `${canvas.clientWidth}px`;
8620
+ this._mediaOverlayHost.style.height = `${canvas.clientHeight}px`;
8621
+ }
8622
+ return this._mediaOverlayHost;
8623
+ }
8624
+ ensureMediaElement(index, style) {
8625
+ let img = this._mediaElements[index];
8626
+ if (!img) {
8627
+ img = document.createElement("img");
8628
+ img.loading = "lazy";
8629
+ img.decoding = "async";
8630
+ img.style.position = "absolute";
8631
+ img.style.objectFit = "contain";
8632
+ img.style.pointerEvents = "none";
8633
+ img.style.transformOrigin = "center center";
8634
+ img.style.filter = "drop-shadow(0 1px 2px rgba(0, 0, 0, 0.55))";
8635
+ img.style.willChange = "transform, left, top";
8636
+ this._mediaElements[index] = img;
8637
+ }
8638
+ const src = String(style.src ?? "").trim();
8639
+ const resolvedSrc = src ? new URL(src, document.baseURI).href : "";
8640
+ if (resolvedSrc && img.getAttribute("src") !== resolvedSrc) {
8641
+ img.removeAttribute("data-astro-media-src-index");
8642
+ img.removeAttribute("data-astro-media-loaded");
8643
+ img.onerror = null;
8644
+ img.onload = null;
8645
+ img.setAttribute("src", resolvedSrc);
8646
+ if (/\.svg(?:[?#].*)?$/i.test(resolvedSrc)) {
8647
+ void this.loadSvgMediaAsDataUrl(img, resolvedSrc);
8648
+ }
8649
+ }
8650
+ return img;
8651
+ }
8652
+ async loadSvgMediaAsDataUrl(img, resolvedSrc) {
8653
+ try {
8654
+ let dataUrl = this._svgMediaDataUrls.get(resolvedSrc);
8655
+ if (!dataUrl) {
8656
+ const response = await fetch(resolvedSrc);
8657
+ if (!response.ok)
8658
+ return;
8659
+ const svg = await response.text();
8660
+ if (!/^\s*<svg[\s>]/i.test(svg))
8661
+ return;
8662
+ dataUrl = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;
8663
+ this._svgMediaDataUrls.set(resolvedSrc, dataUrl);
8664
+ }
8665
+ if (img.getAttribute("src") === resolvedSrc) {
8666
+ img.setAttribute("src", dataUrl);
8667
+ }
8668
+ }
8669
+ catch {
8670
+ // Keep the direct image src; remote servers may already provide a valid MIME type.
8671
+ }
8672
+ }
8673
+ isSourceOnVisibleHemisphere(source, in_mMatrix, vMatrix) {
8674
+ if (Global_js_1.default.insideSphere)
8675
+ return true;
8676
+ const invView = gl_matrix_1.mat4.create();
8677
+ if (!gl_matrix_1.mat4.invert(invView, vMatrix))
8678
+ return true;
8679
+ const cameraPos = gl_matrix_1.vec3.fromValues(invView[12], invView[13], invView[14]);
8680
+ const worldPoint4 = gl_matrix_1.vec4.fromValues(source.point.x, source.point.y, source.point.z, 1);
8681
+ gl_matrix_1.vec4.transformMat4(worldPoint4, worldPoint4, in_mMatrix);
8682
+ const worldPoint = gl_matrix_1.vec3.fromValues(worldPoint4[0], worldPoint4[1], worldPoint4[2]);
8683
+ const normal = gl_matrix_1.vec3.normalize(gl_matrix_1.vec3.create(), worldPoint);
8684
+ const toCamera = gl_matrix_1.vec3.subtract(gl_matrix_1.vec3.create(), cameraPos, worldPoint);
8685
+ return gl_matrix_1.vec3.dot(normal, toCamera) > 0;
8686
+ }
8687
+ updateMediaOverlay(in_mMatrix, vMatrix, pMatrix) {
8688
+ const sourcesWithMedia = this._sources.filter((source) => !!source.mediaStyle?.src);
8689
+ if (!sourcesWithMedia.length) {
8690
+ this.clearMediaOverlay();
8691
+ return;
8692
+ }
8693
+ const host = this.ensureMediaOverlayHost();
8694
+ const canvas = this._webgl.canvas;
8695
+ if (!host || !canvas.clientWidth || !canvas.clientHeight)
8696
+ return;
8697
+ const modelView = gl_matrix_1.mat4.create();
8698
+ const mvp = gl_matrix_1.mat4.create();
8699
+ gl_matrix_1.mat4.multiply(modelView, vMatrix, in_mMatrix);
8700
+ gl_matrix_1.mat4.multiply(mvp, pMatrix, modelView);
8701
+ const width = canvas.clientWidth;
8702
+ const height = canvas.clientHeight;
8703
+ for (let i = 0; i < this._sources.length; i++) {
8704
+ const source = this._sources[i];
8705
+ const style = source.mediaStyle;
8706
+ const img = this._mediaElements[i];
8707
+ if (!style?.src) {
8708
+ if (img)
8709
+ img.style.display = "none";
8710
+ continue;
8711
+ }
8712
+ if (!this.isSourceOnVisibleHemisphere(source, in_mMatrix, vMatrix)) {
8713
+ if (img)
8714
+ img.style.display = "none";
8715
+ continue;
8716
+ }
8717
+ const projected = gl_matrix_1.vec4.fromValues(source.point.x, source.point.y, source.point.z, 1);
8718
+ gl_matrix_1.vec4.transformMat4(projected, projected, mvp);
8719
+ if (!projected[3]) {
8720
+ if (img)
8721
+ img.style.display = "none";
8722
+ continue;
8723
+ }
8724
+ const ndcX = projected[0] / projected[3];
8725
+ const ndcY = projected[1] / projected[3];
8726
+ const ndcZ = projected[2] / projected[3];
8727
+ if (ndcX < -1.15 ||
8728
+ ndcX > 1.15 ||
8729
+ ndcY < -1.15 ||
8730
+ ndcY > 1.15 ||
8731
+ ndcZ < -1.15 ||
8732
+ ndcZ > 1.15) {
8733
+ if (img)
8734
+ img.style.display = "none";
8735
+ continue;
8736
+ }
8737
+ const mediaEl = this.ensureMediaElement(i, style);
8738
+ if (!mediaEl.parentElement)
8739
+ host.appendChild(mediaEl);
8740
+ const px = (ndcX * 0.5 + 0.5) * width;
8741
+ const py = (1 - (ndcY * 0.5 + 0.5)) * height;
8742
+ const baseSize = source.shapeSize || CatalogueGL.STANDARD_SHAPE_SIZE;
8743
+ const size = Math.max(8, baseSize * (style.scale ?? 2.4));
8744
+ const rotation = style.rotationDeg ?? 0;
8745
+ mediaEl.style.display = "block";
8746
+ mediaEl.style.left = `${px - size / 2}px`;
8747
+ mediaEl.style.top = `${py - size / 2}px`;
8748
+ mediaEl.style.width = `${size}px`;
8749
+ mediaEl.style.height = `${size}px`;
8750
+ mediaEl.style.opacity = `${style.opacity ?? 1}`;
8751
+ mediaEl.style.transform = `rotate(${rotation}deg)`;
8752
+ }
8386
8753
  }
8387
8754
  sourceMatches(left, right) {
8388
8755
  if (left === right)
@@ -8427,7 +8794,8 @@ class CatalogueGL {
8427
8794
  if (i >= 0) {
8428
8795
  this.hoveredIndexes.splice(i, 1);
8429
8796
  this.vertexCataloguePosition[base + 3] = 0.0; // not hovered
8430
- this.vertexCataloguePosition[base + 4] = this._sources[sIdx]?.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8797
+ this.vertexCataloguePosition[base + 4] =
8798
+ this._sources[sIdx]?.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8431
8799
  }
8432
8800
  }
8433
8801
  }
@@ -8451,7 +8819,8 @@ class CatalogueGL {
8451
8819
  if (i >= 0) {
8452
8820
  this.selectedIndexes.splice(i, 1);
8453
8821
  this.vertexCataloguePosition[base + 3] = 0.0; // not selected
8454
- 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;
8455
8824
  }
8456
8825
  }
8457
8826
  }
@@ -8482,9 +8851,11 @@ class CatalogueGL {
8482
8851
  // hovered flag
8483
8852
  this.vertexCataloguePosition[positionIndex + 3] = 0.0;
8484
8853
  // size
8485
- this.vertexCataloguePosition[positionIndex + 4] = currSource.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8854
+ this.vertexCataloguePosition[positionIndex + 4] =
8855
+ currSource.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8486
8856
  // brightness
8487
- this.vertexCataloguePosition[positionIndex + 5] = currSource.brightnessFactor ?? 0.0;
8857
+ this.vertexCataloguePosition[positionIndex + 5] =
8858
+ currSource.brightnessFactor ?? 0.0;
8488
8859
  positionIndex += CatalogueGL.ELEM_SIZE;
8489
8860
  }
8490
8861
  this._webgl.bufferData(this._webgl.ARRAY_BUFFER, this.vertexCataloguePosition, this._webgl.STATIC_DRAW);
@@ -8518,50 +8889,8 @@ class CatalogueGL {
8518
8889
  return 0.0001;
8519
8890
  }
8520
8891
  }
8521
- checkClicking(in_mouseHelper) {
8522
- if (in_mouseHelper.x == null || in_mouseHelper.y == null || in_mouseHelper.z == null) {
8523
- console.log('CatalogueGL.checkClicking: missing mouse coords');
8524
- return [];
8525
- }
8526
- const clickedIndexes = [];
8527
- const mousePix = in_mouseHelper.computeNpix();
8528
- if (mousePix != null && this._healpixDensityMap.has(mousePix)) {
8529
- const candidates = this._healpixDensityMap.get(mousePix);
8530
- const selR = this.getSelectionRadius();
8531
- for (let i = 0; i < candidates.length; i++) {
8532
- const sourceIdx = candidates[i];
8533
- const source = this._sources[sourceIdx];
8534
- if (!source)
8535
- continue;
8536
- const dx = source.point.x - in_mouseHelper.x;
8537
- const dy = source.point.y - in_mouseHelper.y;
8538
- const dz = source.point.z - in_mouseHelper.z;
8539
- const dist = Math.sqrt(dx * dx + dy * dy + dz * dz);
8540
- if (dist <= selR) {
8541
- clickedIndexes.push(sourceIdx);
8542
- }
8543
- }
8544
- }
8545
- return clickedIndexes;
8546
- }
8547
- // private setSelectedIndexes(nextSelected: number[]) {
8548
- // const deduped = Array.from(new Set(nextSelected))
8549
- // .filter((idx) => idx >= 0 && idx < this._sources.length);
8550
- // if (this.vertexCataloguePosition.length) {
8551
- // for (const prevIdx of this.selectedIndexes) {
8552
- // if (deduped.includes(prevIdx)) continue;
8553
- // const base = prevIdx * CatalogueGL.ELEM_SIZE;
8554
- // if (base + 4 >= this.vertexCataloguePosition.length) continue;
8555
- // if (!this.hoveredIndexes.includes(prevIdx) && !this.extHoveredIndexes.includes(prevIdx)) {
8556
- // this.vertexCataloguePosition[base + 3] = 0.0;
8557
- // }
8558
- // this.vertexCataloguePosition[base + 4] = this._sources[prevIdx]?.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8559
- // }
8560
- // }
8561
- // this.selectedIndexes = deduped;
8562
- // }
8563
8892
  setSelectedIndexes(selectedIndex) {
8564
- selectedIndex.forEach(idx => {
8893
+ selectedIndex.forEach((idx) => {
8565
8894
  if (idx < 0 || idx >= this._sources.length)
8566
8895
  return;
8567
8896
  const base = idx * CatalogueGL.ELEM_SIZE;
@@ -8570,12 +8899,14 @@ class CatalogueGL {
8570
8899
  if (this.selectedIndexes.includes(idx)) {
8571
8900
  this.selectedIndexes.splice(this.selectedIndexes.indexOf(idx), 1);
8572
8901
  this.vertexCataloguePosition[base + 3] = 0.0; // not selected
8573
- this.vertexCataloguePosition[base + 4] = this._sources[idx]?.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8902
+ this.vertexCataloguePosition[base + 4] =
8903
+ this._sources[idx]?.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8574
8904
  }
8575
8905
  else {
8576
8906
  this.selectedIndexes.push(idx);
8577
8907
  this.vertexCataloguePosition[base + 3] = 2.0; // selected
8578
- this.vertexCataloguePosition[base + 4] = this._sources[idx]?.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8908
+ this.vertexCataloguePosition[base + 4] =
8909
+ this._sources[idx]?.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8579
8910
  }
8580
8911
  });
8581
8912
  }
@@ -8592,7 +8923,7 @@ class CatalogueGL {
8592
8923
  };
8593
8924
  }
8594
8925
  const sources = [];
8595
- pickedIndexes.forEach(idx => {
8926
+ pickedIndexes.forEach((idx) => {
8596
8927
  const source = this._sources[idx];
8597
8928
  if (source)
8598
8929
  sources.push(source);
@@ -8622,7 +8953,7 @@ class CatalogueGL {
8622
8953
  }
8623
8954
  const selectionState = [];
8624
8955
  const selectedSources = [];
8625
- clickedIndexes.forEach(idx => {
8956
+ clickedIndexes.forEach((idx) => {
8626
8957
  const source = this._sources[idx];
8627
8958
  if (!source)
8628
8959
  return;
@@ -8640,31 +8971,43 @@ class CatalogueGL {
8640
8971
  const idx = this.hoveredIndexes[0];
8641
8972
  return this._sources[idx] ?? null;
8642
8973
  }
8643
- checkHovering(in_mouseHelper) {
8644
- if (in_mouseHelper.x == null || in_mouseHelper.y == null || in_mouseHelper.z == null) {
8645
- console.log('CatalogueGL.checkHovering: missing mouse coords');
8646
- return [];
8974
+ findNearestSourceIndex(in_mouseHelper) {
8975
+ if (in_mouseHelper.x == null ||
8976
+ in_mouseHelper.y == null ||
8977
+ in_mouseHelper.z == null) {
8978
+ return null;
8647
8979
  }
8648
- const hoveredIndexes = [];
8649
8980
  const mousePix = in_mouseHelper.computeNpix();
8650
- if (mousePix != null && this._healpixDensityMap.has(mousePix)) {
8651
- const candidates = this._healpixDensityMap.get(mousePix);
8652
- const selR = this.getSelectionRadius();
8653
- for (let i = 0; i < candidates.length; i++) {
8654
- const sourceIdx = candidates[i];
8655
- const source = this._sources[sourceIdx];
8656
- if (!source)
8657
- continue;
8658
- const dx = source.point.x - in_mouseHelper.x;
8659
- const dy = source.point.y - in_mouseHelper.y;
8660
- const dz = source.point.z - in_mouseHelper.z;
8661
- const dist = Math.sqrt(dx * dx + dy * dy + dz * dz);
8662
- if (dist <= selR) {
8663
- hoveredIndexes.push(sourceIdx);
8664
- }
8981
+ if (mousePix == null)
8982
+ return null;
8983
+ const candidates = this._healpixDensityMap.get(mousePix);
8984
+ if (!candidates?.length)
8985
+ return null;
8986
+ const selR = this.getSelectionRadius();
8987
+ let nearestIndex = null;
8988
+ let nearestDistance = Number.POSITIVE_INFINITY;
8989
+ for (const sourceIdx of candidates) {
8990
+ const source = this._sources[sourceIdx];
8991
+ if (!source)
8992
+ continue;
8993
+ const dx = source.point.x - in_mouseHelper.x;
8994
+ const dy = source.point.y - in_mouseHelper.y;
8995
+ const dz = source.point.z - in_mouseHelper.z;
8996
+ const dist = Math.sqrt(dx * dx + dy * dy + dz * dz);
8997
+ if (dist <= selR && dist < nearestDistance) {
8998
+ nearestDistance = dist;
8999
+ nearestIndex = sourceIdx;
8665
9000
  }
8666
9001
  }
8667
- return hoveredIndexes;
9002
+ return nearestIndex;
9003
+ }
9004
+ checkClicking(in_mouseHelper) {
9005
+ const nearestIndex = this.findNearestSourceIndex(in_mouseHelper);
9006
+ return nearestIndex == null ? [] : [nearestIndex];
9007
+ }
9008
+ checkHovering(in_mouseHelper) {
9009
+ const nearestIndex = this.findNearestSourceIndex(in_mouseHelper);
9010
+ return nearestIndex == null ? [] : [nearestIndex];
8668
9011
  }
8669
9012
  /**
8670
9013
  * @param in_mMatrix Model matrix the current catalogue is associated to (e.g. HiPS matrix)
@@ -8711,7 +9054,8 @@ class CatalogueGL {
8711
9054
  const base = this.hoveredIndexes[k] * CatalogueGL.ELEM_SIZE;
8712
9055
  // if (this.vertexCataloguePosition[base + 3] == 2.0) continue; // selected, skip hover
8713
9056
  this.vertexCataloguePosition[base + 3] = 0.0; // not hovered
8714
- this.vertexCataloguePosition[base + 4] = this._sources[this.hoveredIndexes[k]].shapeSize; // size
9057
+ this.vertexCataloguePosition[base + 4] =
9058
+ this._sources[this.hoveredIndexes[k]].shapeSize; // size
8715
9059
  }
8716
9060
  // Hover logic on mouse move
8717
9061
  if (in_mouseHelper != null && in_mouseHelper.xyz !== this._oldMouseCoords) {
@@ -8745,6 +9089,7 @@ class CatalogueGL {
8745
9089
  // draw
8746
9090
  const numItems = this.vertexCataloguePosition.length / CatalogueGL.ELEM_SIZE;
8747
9091
  this._webgl.drawArrays(this._webgl.POINTS, 0, numItems);
9092
+ this.updateMediaOverlay(in_mMatrix, vMatrix, pMatrix);
8748
9093
  this._oldMouseCoords = in_mouseHelper.xyz;
8749
9094
  }
8750
9095
  }
@@ -10336,11 +10681,9 @@ class FootprintSetGL {
10336
10681
  _metadataManager;
10337
10682
  _providerUrl;
10338
10683
  _footprintShaderProgram;
10339
- _visibleTilesManager;
10340
- constructor(fsetName, fsetDescription, providerUrl, metadataManager, webgl, visibleTilesManager) {
10684
+ constructor(fsetName, fsetDescription, providerUrl, metadataManager, webgl) {
10341
10685
  this._webgl = webgl;
10342
10686
  this._ready = false;
10343
- this._visibleTilesManager = visibleTilesManager;
10344
10687
  this.TYPE = "FOOTPRINT_SET";
10345
10688
  this._name = fsetName;
10346
10689
  this._description = fsetDescription;
@@ -14643,7 +14986,9 @@ class MeshHiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
14643
14986
  const orders = Array.from(byOrder.keys()).sort((a, b) => a - b);
14644
14987
  for (const order of orders) {
14645
14988
  for (const coord of byOrder.get(order) ?? []) {
14646
- this._tiles.get(this.tileKey(coord))?.draw(pMatrix, vMatrix, mMatrix, this._descriptor.color, this._descriptor.wireframe);
14989
+ this._tiles
14990
+ .get(this.tileKey(coord))
14991
+ ?.draw(pMatrix, vMatrix, mMatrix, this._descriptor.color, this._descriptor.wireframe);
14647
14992
  }
14648
14993
  }
14649
14994
  if (wasCullFace)
@@ -14656,7 +15001,7 @@ class MeshHiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
14656
15001
  getDebugStats() {
14657
15002
  const tiles = Array.from(this._tiles.values());
14658
15003
  return {
14659
- activeBaseLayer: 'meships',
15004
+ activeBaseLayer: "meships",
14660
15005
  meshHiPSName: this._descriptor.name,
14661
15006
  meshHiPSUrl: this._descriptor.baseUrl,
14662
15007
  currentOrder: this._currentOrder,
@@ -14675,33 +15020,47 @@ class MeshHiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
14675
15020
  ? byOrder.pixels
14676
15021
  : [];
14677
15022
  if (pixels.length > 0) {
14678
- return pixels.map((ipix) => ({ order: this._currentOrder, ipix }));
15023
+ return pixels.map((ipix) => ({
15024
+ order: this._currentOrder,
15025
+ ipix,
15026
+ }));
14679
15027
  }
14680
15028
  const tileCount = 12 * 4 ** this._currentOrder;
14681
- return Array.from({ length: tileCount }, (_, ipix) => ({ order: this._currentOrder, ipix }));
15029
+ return Array.from({ length: tileCount }, (_, ipix) => ({
15030
+ order: this._currentOrder,
15031
+ ipix,
15032
+ }));
14682
15033
  }
14683
15034
  resolveCoverageTiles(visibleTiles) {
14684
15035
  const tiles = new Map();
14685
15036
  const add = (coord) => {
14686
- if (coord.order < this._descriptor.minOrder || coord.order > this._descriptor.maxOrder)
15037
+ if (coord.order < this._descriptor.minOrder ||
15038
+ coord.order > this._descriptor.maxOrder) {
14687
15039
  return;
15040
+ }
14688
15041
  tiles.set(this.tileKey(coord), coord);
14689
15042
  };
14690
15043
  for (const coord of visibleTiles) {
14691
15044
  add(coord);
14692
15045
  for (let order = coord.order - 1; order >= this._descriptor.minOrder; order--) {
14693
15046
  const shift = 2 * (coord.order - order);
14694
- add({ order, ipix: coord.ipix >> shift });
15047
+ add({
15048
+ order,
15049
+ ipix: coord.ipix >> shift,
15050
+ });
14695
15051
  }
14696
15052
  }
14697
15053
  const manager = this._healpixGrid.visibleTilesManager;
14698
15054
  const ancestorsMap = manager?.ancestorsMap;
14699
15055
  if (ancestorsMap) {
14700
15056
  for (const [order, ipixes] of ancestorsMap) {
14701
- if (order < this._descriptor.minOrder || order > this._descriptor.maxOrder)
15057
+ if (order < this._descriptor.minOrder ||
15058
+ order > this._descriptor.maxOrder) {
14702
15059
  continue;
14703
- for (const ipix of ipixes)
15060
+ }
15061
+ for (const ipix of ipixes) {
14704
15062
  add({ order, ipix });
15063
+ }
14705
15064
  }
14706
15065
  }
14707
15066
  return Array.from(tiles.values());
@@ -16318,6 +16677,9 @@ function normalizeLongitudeDeg(longitudeDeg) {
16318
16677
  *
16319
16678
  * See LICENSE.md, LICENSE-AGPL.md, and LICENSE-COMMERCIAL.md for details.
16320
16679
  */
16680
+ var __importDefault = (this && this.__importDefault) || function (mod) {
16681
+ return (mod && mod.__esModule) ? mod : { "default": mod };
16682
+ };
16321
16683
  Object.defineProperty(exports, "__esModule", ({ value: true }));
16322
16684
  exports.TerraFootprintSetGL = void 0;
16323
16685
  const FootprintSetGL_js_1 = __webpack_require__(592);
@@ -16326,6 +16688,8 @@ const Footprint_js_1 = __webpack_require__(2475);
16326
16688
  const MetadataColumn_js_1 = __webpack_require__(1072);
16327
16689
  const MetadataManager_js_1 = __webpack_require__(5403);
16328
16690
  const MetadataColumn_js_2 = __webpack_require__(1072);
16691
+ const Point_js_1 = __webpack_require__(6553);
16692
+ const GeomUtils_js_1 = __importDefault(__webpack_require__(2930));
16329
16693
  class TerraFootprintSetGL extends FootprintSetGL_js_1.FootprintSetGL {
16330
16694
  _kind = 'TerraFootprintSetGL';
16331
16695
  _coordsType = CoordsType_js_1.CoordsType.GEOGRAPHIC;
@@ -16344,6 +16708,23 @@ class TerraFootprintSetGL extends FootprintSetGL_js_1.FootprintSetGL {
16344
16708
  this._ready = true;
16345
16709
  this._bufferInitialised = false;
16346
16710
  }
16711
+ checkSelection(mouseHelper) {
16712
+ if (mouseHelper.x == null || mouseHelper.y == null || mouseHelper.z == null)
16713
+ return;
16714
+ const hoverState = this;
16715
+ hoverState._hoveredFootprints = [];
16716
+ this.totHoveredPoints = 0;
16717
+ const mousePoint = new Point_js_1.Point({ x: mouseHelper.x, y: mouseHelper.y, z: mouseHelper.z }, CoordsType_js_1.CoordsType.CARTESIAN);
16718
+ for (const footprint of this.footprintPolygons) {
16719
+ if (!footprint.selectionObj)
16720
+ continue;
16721
+ if (GeomUtils_js_1.default.checkPointInsidePolygon5(footprint.selectionObj, mousePoint)) {
16722
+ hoverState._hoveredFootprints.push(footprint);
16723
+ this.totHoveredPoints += footprint.totPoints;
16724
+ }
16725
+ }
16726
+ this.initHoveringBuffer();
16727
+ }
16347
16728
  createGeoJSONMetadataColumns(features) {
16348
16729
  const names = new Set();
16349
16730
  features.forEach(feature => Object.keys(feature.properties).forEach(name => names.add(name)));
@@ -16388,8 +16769,44 @@ exports.TerraFootprintSetGL = TerraFootprintSetGL;
16388
16769
  Object.defineProperty(exports, "__esModule", ({ value: true }));
16389
16770
  exports.TerraPointSetGL = void 0;
16390
16771
  const CatalogueGL_js_1 = __webpack_require__(1232);
16772
+ const MetadataManager_js_1 = __webpack_require__(5403);
16773
+ const Point_js_1 = __webpack_require__(6553);
16774
+ const CoordsType_js_1 = __webpack_require__(8145);
16391
16775
  class TerraPointSetGL extends CatalogueGL_js_1.CatalogueGL {
16392
16776
  _kind = 'TerraPointSetGL';
16777
+ addSources(inData, columnsMeta) {
16778
+ this._ready = false;
16779
+ this._sources = [];
16780
+ const metadataManager = new MetadataManager_js_1.MetadataManager(columnsMeta);
16781
+ this._metadataManager = metadataManager;
16782
+ const lonDataIndex = metadataManager.selectedRaColumn?.index ?? -1;
16783
+ const latDataIndex = metadataManager.selectedDecColumn?.index ?? -1;
16784
+ if (lonDataIndex < 0 || latDataIndex < 0) {
16785
+ throw new Error(`(lon, lat) idx not defined (${lonDataIndex}, ${latDataIndex}) `);
16786
+ }
16787
+ for (const row of inData) {
16788
+ const point = new Point_js_1.Point({
16789
+ lonDeg: Number(row[lonDataIndex]),
16790
+ latDeg: Number(row[latDataIndex]),
16791
+ }, CoordsType_js_1.CoordsType.GEOGRAPHIC);
16792
+ this.addSource({
16793
+ point,
16794
+ details: row,
16795
+ healpixPixel: 0,
16796
+ shapeSize: CatalogueGL_js_1.CatalogueGL.STANDARD_SHAPE_SIZE,
16797
+ brightnessFactor: 3,
16798
+ getDetailByindex(index) {
16799
+ return index < 0 || index >= row.length ? undefined : row[index];
16800
+ },
16801
+ });
16802
+ }
16803
+ this._ready = true;
16804
+ this._bufferInitialised = false;
16805
+ }
16806
+ draw(inMatrix, inMouseHelper, viewMatrix, projectionMatrix) {
16807
+ this._oldMouseCoords = inMouseHelper?.xyz ?? null;
16808
+ super.draw(inMatrix, inMouseHelper, viewMatrix, projectionMatrix);
16809
+ }
16393
16810
  }
16394
16811
  exports.TerraPointSetGL = TerraPointSetGL;
16395
16812
 
@@ -16422,7 +16839,6 @@ class TerraPolylineSetGL {
16422
16839
  _providerUrl;
16423
16840
  _metadataManager;
16424
16841
  _webgl;
16425
- _visibleTilesManager;
16426
16842
  static ELEM_SIZE = 3;
16427
16843
  static BYTES_X_ELEM = new Float32Array().BYTES_PER_ELEMENT;
16428
16844
  _kind = 'TerraPolylineSetGL';
@@ -16433,13 +16849,12 @@ class TerraPolylineSetGL {
16433
16849
  paths = [];
16434
16850
  renderSegments = [];
16435
16851
  _polylineShaderProgram;
16436
- constructor(_name, _description, _providerUrl, _metadataManager, _webgl, _visibleTilesManager) {
16852
+ constructor(_name, _description, _providerUrl, _metadataManager, _webgl) {
16437
16853
  this._name = _name;
16438
16854
  this._description = _description;
16439
16855
  this._providerUrl = _providerUrl;
16440
16856
  this._metadataManager = _metadataManager;
16441
16857
  this._webgl = _webgl;
16442
- this._visibleTilesManager = _visibleTilesManager;
16443
16858
  this._polylineShaderProgram = new FootprintShaderProgram_js_1.FootprintShaderProgram(this._webgl);
16444
16859
  }
16445
16860
  addPath(points, metadata) {
@@ -18765,7 +19180,8 @@ class MouseHelper {
18765
19180
  computeNpix() {
18766
19181
  if (!this._xyz)
18767
19182
  return null;
18768
- const hp = Global_js_1.default.getHealpix(Global_js_1.default.nsideForSelection);
19183
+ // const hp: Healpix = global.getHealpix(global.nsideForSelection);
19184
+ const hp = Global_js_1.default.getHealpix(Global_js_1.default.selectionOrder);
18769
19185
  const v = new healpix_1.Vec3(this._xyz[0], this._xyz[1], this._xyz[2]);
18770
19186
  const ptg = new healpix_1.Pointing(v, false);
18771
19187
  return hp.ang2pix(ptg, false);