astro-viewer 3.13.0 → 3.14.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.
@@ -9518,12 +9518,19 @@ class CatalogueGL {
9518
9518
  if (this._catalogueShaderProgram.locations.color) {
9519
9519
  this._webgl.uniform4f(this._catalogueShaderProgram.locations.color, rgb[0], rgb[1], rgb[2], 1.0);
9520
9520
  }
9521
- const interactionColors = (0, Utils_js_1.interactionColorsFromHex)(this._shapeColor);
9521
+ // const interactionColors = interactionColorsFromHex(this._shapeColor);
9522
+ // Complementary RGB colour for catalogue interactions.
9523
+ // Keep the original catalogue colour unchanged.
9524
+ const complementaryColor = rgb.map((component) => 1.0 - component);
9522
9525
  if (this._catalogueShaderProgram.locations.hoverColor) {
9523
- this._webgl.uniform4f(this._catalogueShaderProgram.locations.hoverColor, ...interactionColors.hover, 1.0);
9526
+ this._webgl.uniform4f(this._catalogueShaderProgram.locations.hoverColor,
9527
+ // ...interactionColors.hover,
9528
+ ...complementaryColor, 1.0);
9524
9529
  }
9525
9530
  if (this._catalogueShaderProgram.locations.selectedColor) {
9526
- this._webgl.uniform4f(this._catalogueShaderProgram.locations.selectedColor, ...interactionColors.selected, 1.0);
9531
+ this._webgl.uniform4f(this._catalogueShaderProgram.locations.selectedColor,
9532
+ // ...interactionColors.selected,
9533
+ ...complementaryColor, 1.0);
9527
9534
  }
9528
9535
  // selected flags
9529
9536
  for (let s = 0; s < this.selectedIndexes.length; s++) {
@@ -11186,6 +11193,8 @@ class FootprintSetGL {
11186
11193
  hoveredIndexBuffer;
11187
11194
  selectedVertexPositionBuffer;
11188
11195
  selectedIndexBuffer;
11196
+ selectedFillBuffer;
11197
+ selectedFillVertices = new Float32Array(0);
11189
11198
  indexes;
11190
11199
  footprintPolygons = [];
11191
11200
  vertexCataloguePosition;
@@ -11241,6 +11250,7 @@ class FootprintSetGL {
11241
11250
  this.totSelectedPoints = 0;
11242
11251
  this.selectedIndexes = [];
11243
11252
  this.selectedElementIndexes = new Uint32Array();
11253
+ this.selectedFillVertices = new Float32Array();
11244
11254
  }
11245
11255
  initGLBuffers() {
11246
11256
  if (!this._webgl)
@@ -11251,6 +11261,7 @@ class FootprintSetGL {
11251
11261
  this.hoveredIndexBuffer = this._webgl.createBuffer();
11252
11262
  this.selectedVertexPositionBuffer = this._webgl.createBuffer();
11253
11263
  this.selectedIndexBuffer = this._webgl.createBuffer();
11264
+ this.selectedFillBuffer = this._webgl.createBuffer();
11254
11265
  }
11255
11266
  setIsVisible(visibility) {
11256
11267
  this._isVisible = visibility;
@@ -11428,9 +11439,11 @@ class FootprintSetGL {
11428
11439
  this.selectedVertexPosition = new Float32Array();
11429
11440
  this.selectedElementIndexes = new Uint32Array();
11430
11441
  this.nSlectedPrimitiveFlags = 0;
11442
+ this.selectedFillVertices = new Float32Array();
11431
11443
  return;
11432
11444
  }
11433
11445
  this.initSelectionBuffer();
11446
+ this.selectedFillVertices = this.buildSelectedFillVertices();
11434
11447
  }
11435
11448
  getFootprintsFromPointer(in_mouseHelper) {
11436
11449
  const pickedIndexes = this.checkClicking(in_mouseHelper);
@@ -11683,6 +11696,70 @@ class FootprintSetGL {
11683
11696
  }
11684
11697
  }
11685
11698
  }
11699
+ /** Triangulate selected simple rings in the same 2D projection used for picking.
11700
+ * A failed/degenerate ring is left unfilled; its outline remains visible.
11701
+ */
11702
+ buildSelectedFillVertices() {
11703
+ const vertices = [];
11704
+ const cross = (a, b, c) => (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
11705
+ for (const footprint of this._selectedFootprints) {
11706
+ const projected = footprint.selectionObj?.poly4selection;
11707
+ if (!projected)
11708
+ continue;
11709
+ footprint.polygons.forEach((ring, ringIndex) => {
11710
+ const coords = projected[ringIndex];
11711
+ if (!coords || coords.length !== ring.length || ring.length < 3)
11712
+ return;
11713
+ const indices = ring.map((_, i) => i);
11714
+ // STC-S normally omits the duplicated closing vertex; fromPolygons may not.
11715
+ if (indices.length > 3 &&
11716
+ Math.abs(coords[0].x - coords[indices[indices.length - 1]].x) < 1e-12 &&
11717
+ Math.abs(coords[0].y - coords[indices[indices.length - 1]].y) < 1e-12)
11718
+ indices.pop();
11719
+ if (indices.length < 3)
11720
+ return;
11721
+ const area = indices.reduce((sum, idx, i) => {
11722
+ const next = indices[(i + 1) % indices.length];
11723
+ return sum + coords[idx].x * coords[next].y - coords[next].x * coords[idx].y;
11724
+ }, 0);
11725
+ if (Math.abs(area) < 1e-14)
11726
+ return;
11727
+ const orientation = Math.sign(area);
11728
+ const triangles = [];
11729
+ let attempts = 0;
11730
+ while (indices.length > 3 && attempts++ < ring.length * ring.length) {
11731
+ let clipped = false;
11732
+ for (let i = 0; i < indices.length; i++) {
11733
+ const a = indices[(i + indices.length - 1) % indices.length];
11734
+ const b = indices[i];
11735
+ const c = indices[(i + 1) % indices.length];
11736
+ if (orientation * cross(coords[a], coords[b], coords[c]) <= 1e-14)
11737
+ continue;
11738
+ const contains = indices.some(idx => idx !== a && idx !== b && idx !== c &&
11739
+ orientation * cross(coords[a], coords[b], coords[idx]) >= -1e-14 &&
11740
+ orientation * cross(coords[b], coords[c], coords[idx]) >= -1e-14 &&
11741
+ orientation * cross(coords[c], coords[a], coords[idx]) >= -1e-14);
11742
+ if (contains)
11743
+ continue;
11744
+ triangles.push(a, b, c);
11745
+ indices.splice(i, 1);
11746
+ clipped = true;
11747
+ break;
11748
+ }
11749
+ if (!clipped)
11750
+ break;
11751
+ }
11752
+ if (indices.length !== 3)
11753
+ return;
11754
+ triangles.push(...indices);
11755
+ for (const idx of triangles) {
11756
+ const point = ring[idx];
11757
+ vertices.push(point.x, point.y, point.z);
11758
+ }
11759
+ });
11760
+ }
11761
+ return new Float32Array(vertices);
11762
+ }
11686
11763
  changeColor(color) {
11687
11764
  this._shapeColor = color;
11688
11765
  }
@@ -11699,11 +11776,6 @@ class FootprintSetGL {
11699
11776
  if (!this._webgl)
11700
11777
  return;
11701
11778
  this._footprintShaderProgram.enableShaders(pMatrix, in_mMatrix, vMatrix);
11702
- // this._footprintShaderProgram.enableShaders(
11703
- // computePerspectiveMatrixSingleton.pMatrix as Float32Array,
11704
- // in_mMatrix,
11705
- // vMatrix
11706
- // )
11707
11779
  if (in_mouseHelper != null && in_mouseHelper.xyz != this.oldMouseCoords) {
11708
11780
  this.checkSelection(in_mouseHelper);
11709
11781
  }
@@ -11726,6 +11798,31 @@ class FootprintSetGL {
11726
11798
  }
11727
11799
  if (this._selectedFootprints.length > 0) {
11728
11800
  const rgb = interactionColors.selected;
11801
+ if (this.selectedFillVertices.length > 0) {
11802
+ this._webgl.uniform4f(this._footprintShaderProgram.locations.color, rgb[0], rgb[1], rgb[2], 0.25);
11803
+ this._webgl.bindBuffer(this._webgl.ARRAY_BUFFER, this.selectedFillBuffer);
11804
+ this._webgl.bufferData(this._webgl.ARRAY_BUFFER, this.selectedFillVertices, this._webgl.DYNAMIC_DRAW);
11805
+ this._webgl.vertexAttribPointer(this._footprintShaderProgram.locations.position, FootprintSetGL.ELEM_SIZE, this._webgl.FLOAT, false, FootprintSetGL.BYTES_X_ELEM * FootprintSetGL.ELEM_SIZE, 0);
11806
+ this._webgl.enableVertexAttribArray(this._footprintShaderProgram.locations.position);
11807
+ // Keep translucent fills from writing depth and push them slightly
11808
+ // behind the outlines. Preserve the incoming GL state.
11809
+ const previousDepthMask = this._webgl.getParameter(this._webgl.DEPTH_WRITEMASK);
11810
+ const previousOffsetEnabled = this._webgl.isEnabled(this._webgl.POLYGON_OFFSET_FILL);
11811
+ const previousOffsetFactor = this._webgl.getParameter(this._webgl.POLYGON_OFFSET_FACTOR);
11812
+ const previousOffsetUnits = this._webgl.getParameter(this._webgl.POLYGON_OFFSET_UNITS);
11813
+ this._webgl.depthMask(false);
11814
+ this._webgl.enable(this._webgl.POLYGON_OFFSET_FILL);
11815
+ this._webgl.polygonOffset(1, 1);
11816
+ try {
11817
+ this._webgl.drawArrays(this._webgl.TRIANGLES, 0, this.selectedFillVertices.length / FootprintSetGL.ELEM_SIZE);
11818
+ }
11819
+ finally {
11820
+ this._webgl.depthMask(previousDepthMask);
11821
+ this._webgl.polygonOffset(previousOffsetFactor, previousOffsetUnits);
11822
+ if (!previousOffsetEnabled)
11823
+ this._webgl.disable(this._webgl.POLYGON_OFFSET_FILL);
11824
+ }
11825
+ }
11729
11826
  const alpha = 1.0;
11730
11827
  this._webgl.uniform4f(this._footprintShaderProgram.locations.color, rgb[0], rgb[1], rgb[2], alpha);
11731
11828
  this._webgl.uniform1f(this._footprintShaderProgram.locations.pointSize, 14.0); // <--- POINT_SIZE in LINE_LOOP is not applicable
@@ -13804,6 +13901,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
13804
13901
  };
13805
13902
  Object.defineProperty(exports, "__esModule", ({ value: true }));
13806
13903
  exports.HiPS = void 0;
13904
+ exports.normalizeHiPSBaseURL = normalizeHiPSBaseURL;
13807
13905
  /**
13808
13906
  * @author Fabrizio Giordano (Fab77)
13809
13907
  */
@@ -13813,6 +13911,9 @@ const ColorMaps_js_1 = __importDefault(__webpack_require__(619));
13813
13911
  const AncestorTile_js_1 = __importDefault(__webpack_require__(2885));
13814
13912
  const AllSky_js_1 = __importDefault(__webpack_require__(2368));
13815
13913
  const HiPSCoverage_js_1 = __webpack_require__(9912);
13914
+ function normalizeHiPSBaseURL(url) {
13915
+ return url.replace(/\/+$/, "");
13916
+ }
13816
13917
  const FITS_SCALE_FUNCTION_INDEX = {
13817
13918
  linear: 0,
13818
13919
  sqrt: 1,
@@ -13877,7 +13978,7 @@ class HiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
13877
13978
  this.initGL(webgl);
13878
13979
  this._healpixGrid = healpixGrid;
13879
13980
  this._format = this.selectDefaultFormat(descriptor.imgFormats);
13880
- this._baseurl = descriptor.url;
13981
+ this._baseurl = normalizeHiPSBaseURL(descriptor.url);
13881
13982
  this._maxorder = descriptor.maxOrder;
13882
13983
  this._minorder = descriptor.minOrder;
13883
13984
  this._coverage = new HiPSCoverage_js_1.HiPSCoverage();
@@ -18532,14 +18633,29 @@ class ShaderManager {
18532
18633
  alpha = 1.0 - smoothstep(1.0 - delta, 1.0 + delta, r);
18533
18634
  #endif
18534
18635
 
18535
- if (v_selected == 1.0){
18536
- fragColor = u_hovercolor * alpha;
18537
- } else if (v_selected == 2.0){
18538
- // Persistent selection: keep the dataset colour as an outer ring
18539
- // and use the hover colour for the fill. This remains visible for
18540
- // both light and dark user-selected base colours.
18636
+ if (v_selected == 1.0) {
18637
+ // Hover: original catalogue colour on the outer ring,
18638
+ // complementary colour in the centre.
18541
18639
  fragColor = (r > 0.72 ? u_fragcolor : u_hovercolor) * alpha;
18542
- }else{
18640
+
18641
+ } else if (v_selected == 2.0) {
18642
+ // Selected: same ring and fill, plus a contrasting centre dot.
18643
+ if (r < 0.09) {
18644
+ float luminance = dot(
18645
+ u_selectedcolor.rgb,
18646
+ vec3(0.2126, 0.7152, 0.0722)
18647
+ );
18648
+
18649
+ vec3 dotColor = luminance > 0.5
18650
+ ? vec3(0.0)
18651
+ : vec3(1.0);
18652
+
18653
+ fragColor = vec4(dotColor, 1.0) * alpha;
18654
+ } else {
18655
+ fragColor = (r > 0.72 ? u_fragcolor : u_selectedcolor) * alpha;
18656
+ }
18657
+
18658
+ } else {
18543
18659
  if (r < 0.4) {
18544
18660
  discard;
18545
18661
  }
@@ -20342,7 +20458,7 @@ function interactionColorsFromHex(hexColor) {
20342
20458
  ];
20343
20459
  return {
20344
20460
  hover: mix(0.45),
20345
- selected: mix(0.45),
20461
+ selected: mix(0.75),
20346
20462
  };
20347
20463
  }
20348
20464
  function degToRad(degrees) {