Compare commits

..

16 Commits

Author SHA1 Message Date
Matthieu Baumann
645bab7cd9 Subdivision tuning
Cells are all subdivided at the same level.
One subdivision is added if:
* the cell is on a pole
* the cell is at a frontier of a base cells (and in collignon zona)
2025-04-09 13:35:20 +02:00
bmatthieu3
62f9e61978 New option to make the north pole remain up to the view
* lockNorthUp new Aladin init option. False by default.
* setRotation is still allowed if lockNorthUp=true but when panning, the
view resets its orientation so that the north pole is up
2025-04-09 13:35:20 +02:00
bmatthieu3
addbd555c1 Performance
Do all CPU computations on Vec3 and not Vec4
2025-04-09 13:35:20 +02:00
bmatthieu3
db70a6b9cd Set zoomfactor when using smartphones
Refers back to PR #249
2025-04-09 13:35:20 +02:00
bmatthieu3
258781d078 update readme, make the release page link more visible 2025-04-09 13:35:20 +02:00
bmatthieu3
7418ed822d add getZoomFactor method in Aladin 2025-04-09 13:35:20 +02:00
bmatthieu3
ba728c23c7 Enhance zooming on mouse/trackpad
When zooming with a mouse or a trackpad a wheel event is triggered.
Originally the fov of the viewport was changed but it happened setting
the fov is projection dependant therefore leading to big zooming effect
for TAN projection for example.
Now there is a new way of zooming which is done by setting the screen
zoom factor instead of the fov. Zooming with this factor is projection
agnostic.
With that the pr adds:
* an interpolated zooming effect moving the viewport from a start screen
zoom factor to another by following a hermite cubic interpolation
function
* bugfix: originally, multiple wheel events done shortly in time resulted in a
zooming "congestion" bug leading to a zoom effect similar to only one
isolated wheel event. Now triggering several wheel event allow to zoom
more than only one isolated.
* a new listener `wheelTriggered` allowing the user to define its own zooming.
When wheelTriggered is set, the default zooming is not executed
2025-04-09 13:35:20 +02:00
bmatthieu3
89f760c1db Update changelog 2025-04-09 13:35:20 +02:00
Matthieu Baumann
c5d0875265 First commit for 3.7.0
* add MOC setable properties: fill, edge and perimeter
* change package.json to 3.7.0-beta
2025-04-09 13:35:18 +02:00
Matthieu Baumann
4a8d3bfa65 Fix selection of footprints not associated with catalog sources
Targets #274

* fix: handleSelect now call selectObjects with not only the list of catalog sources but also with the footprints
* fix: View.closestFootprints: if no lineWidth was given to a footprint then it could happen that this method set it to 1px, erasing its previous undefined value
* Circle and Ellipse now behaves like PolyLine and Vector, if no linewidth is given, the one from its GraphicOverlay is taken.
2025-04-09 13:34:38 +02:00
Matthieu Baumann
bde5a37b51 codemeta 3.6.5 2025-04-09 13:33:29 +02:00
Matthieu Baumann
fbdc7e2e76 3.6.5 2025-04-09 11:57:10 +02:00
Matthieu Baumann
312b9844d1 Fix allsky fits display
Bug introduced in #254. Allsky is also downloaded if the tile_size is <= 256
2025-04-09 11:47:53 +02:00
bmatthieu3
0e740454bd Fix #278
When creating a new default survey the DSS2 survey is chosen. We use
the one cached instead of creating a plain new one.
2025-04-08 18:09:09 +02:00
bmatthieu3
18e98e9f5f fix: fullscreen closing
Bug happening when realFullscreen is true and we click on the
fullscreen button. Following #151 fix, commit #a19a050
2025-04-03 18:01:58 +02:00
Matthieu Baumann
c938a58cbc Fix selection of footprints not associated with catalog sources
Targets #274

* fix: handleSelect now call selectObjects with not only the list of catalog sources but also with the footprints
* fix: View.closestFootprints: if no lineWidth was given to a footprint then it could happen that this method set it to 1px, erasing its previous undefined value
* Circle and Ellipse now behaves like PolyLine and Vector, if no linewidth is given, the one from its GraphicOverlay is taken.
2025-04-03 18:01:46 +02:00
95 changed files with 462 additions and 291 deletions

View File

@@ -8,8 +8,8 @@
"dateModified": "2023-01-31",
"issueTracker": "https://github.com/cds-astro/aladin-lite/issues",
"name": "Aladin Lite",
"version": "3.6.4",
"softwareVersion": "3.6.4",
"version": "3.6.5",
"softwareVersion": "3.6.5",
"description": "An astronomical HiPS visualizer in the browser.",
"identifier": "10.5281/zenodo.7638833",
"applicationCategory": "Astronomy, Visualization",

View File

@@ -4,7 +4,7 @@
</head>
<body>
<div id="aladin-lite-div" style="width: 1024px; height: 256px;"></div>
<div id="aladin-lite-div" style="width: 1024px; height: 768px;"></div>
<script type="module">
import A from '../src/js/A.js';
@@ -13,12 +13,14 @@
var aladin = A.aladin(
'#aladin-lite-div',
{
survey: 'https://alasky.cds.unistra.fr/Pan-STARRS/DR1/color-z-zg-g/', // set initial image survey
survey: 'data/hips/wcs', // set initial image survey
projection: 'SIN', // set a projection
fov: 114.19, // initial field of view in degrees
target: '19 24 51.556 +45 16 44.36', // initial target
cooFrame: 'equatorial', // set galactic frame
showCooGrid: true, // set the grid
fov: 80.0, // initial field of view in degrees
target: '96.5279427 -88.0037230', // initial target
cooFrame: 'galactic', // set galactic frame
showCooGrid: true, // set the grid,
fullScreen: true,
showSettingsControl: true,
}
);
});

View File

@@ -11,9 +11,9 @@
let aladin;
A.init.then(() => {
// Start up Aladin Lite
aladin = A.aladin('#aladin-lite-div', {survey: "CDS/P/DSS2/color", target: 'M 1', fov: 0.2, showContextMenu: true, fullScreen: true});
aladin = A.aladin('#aladin-lite-div', {target: 'M 1', fov: 0.2, showContextMenu: true, fullScreen: true});
var overlay = A.graphicOverlay({color: '#ee2345', lineWidth: 3, lineDash: [2, 2]});
/*aladin.addOverlay(overlay);
aladin.addOverlay(overlay);
overlay.addFootprints([
A.polygon([[83.64287, 22.01713], [83.59872, 22.01692], [83.59852, 21.97629], [83.64295, 21.97629]], {hoverColor: 'green'}),
A.polygon([[83.62807, 22.06330], [83.58397, 22.02280], [83.62792, 22.02258]]),
@@ -21,7 +21,7 @@
]);
overlay.add(A.circle(83.66067, 22.03081, 0.04, {color: 'cyan'})); // radius in degrees
overlay.add(A.vector(83.66067, 22.03081, 0.04, {color: 'cyan'})); // radius in degrees
*/
aladin.on("footprintClicked", (footprint, xyMouseCoords) => {
console.log("footprint clicked catched: ", footprint, "mouse coords xy: ", xyMouseCoords.x, xyMouseCoords.y);
})
@@ -35,8 +35,8 @@
console.log("Object hovered stopped: ", object, "mouse coords xy: ", xyMouseCoords.x, xyMouseCoords.y);
})
const cat = A.catalogFromVizieR('B/assocdata/obscore', 'M 1', 10, {onClick: 'showTable', selectionColor: "orange", hoverColor: 'red', limit: 10000});
aladin.addCatalog(cat);
//const cat = A.catalogFromVizieR('B/assocdata/obscore', 'M 1', 10, {onClick: 'showTable', selectionColor: "orange", hoverColor: 'red', limit: 10000});
//aladin.addCatalog(cat);
});
</script>
</body>

View File

@@ -7,7 +7,7 @@
<script type="module">
import A from '../src/js/A.js';
A.init.then(() => {
let aladin = A.aladin('#aladin-lite-div', {fov: 30, survey: "CDS/P/DSS2/color", target: "280 +0", projection: "AIT", showShareControl:true, showSettingsControl: true, showContextMenu:true});
let aladin = A.aladin('#aladin-lite-div', {fov: 30, target: "280 +0", projection: "AIT", showShareControl:true, showSettingsControl: true, showContextMenu:true});
aladin.setOverlayImageLayer(A.image(
"https://www.virtualastronomy.org/images/sig05-013.jpg",

View File

@@ -29,6 +29,7 @@
showCooGrid: true,
fullScreen: true,
samp: true,
realFullscreen: true,
lockNorthUp: true,
}
);

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@@ -0,0 +1,33 @@
creator_did = ivo://UNK.AUTH/P/474-2244-wcs
obs_title = 474-2244-wcs.fits
hips_builder = Aladin/HipsGen v12.135
hips_version = 1.4
hips_frame = galactic
hips_order = 10
hips_order_min = 0
hips_tile_width = 512
hips_status = public master clonableOnce
hips_tile_format = png
hips_pixel_bitpix = -32
hips_pixel_cut = -670.2 64044
hips_data_range = -38085 98627
hips_initial_ra = 11.66767
hips_initial_dec = -24.86479
hips_initial_fov = 5.90651
hips_pixel_scale = 1.118E-4
s_pixel_scale = 1.222E-4
dataproduct_type = image
hipsgen_date = 2024-11-13T17:07Z
hipsgen_params = in=NAROO/474-2244-wcs.fits out=/var/www/tmp/HiPS/474-2244-wcs id=474-2244-wcs maxThread=20
data_pixel_bitpix = -32
hips_sampling = bilinear
hips_overlay = overlayMean mergeOverwrite treeMean
hips_release_date = 2024-11-13T18:33Z
hips_data_minmax = -21385 73221
moc_sky_fraction = 0.001074
hipsgen_date_1 = 2024-11-13T18:25Z
hipsgen_params_1 = in=NAROO/474-2244-wcs.fits out=/var/www/tmp/HiPS/474-2244-wcs id=474-2244-wcs maxThread=20
hips_creation_date = 2024-11-13T18:25Z
hips_estsize = 24116525
hips_nb_tiles = 36636
hips_check_code = png:735272809

View File

@@ -1,6 +1,6 @@
[package]
name = "al-api"
version = "3.6.4"
version = "3.6.5"
authors = ["baumannmatthieu0@gmail.com", "matthieu.baumann@astro.unistra.fr"]
edition = "2018"

View File

@@ -1,6 +1,6 @@
[package]
name = "al-core"
version = "3.6.4"
version = "3.6.5"
authors = ["baumannmatthieu0@gmail.com", "matthieu.baumann@astro.unistra.fr"]
edition = "2018"

View File

@@ -185,14 +185,24 @@ impl From<query::Allsky> for AllskyRequest {
.collect())
}
InMemData::F32(data) => {
let data = unsafe { std::slice::from_raw_parts(data.as_ptr() as *const u8, data.len() * 4) };
let data = unsafe {
std::slice::from_raw_parts(
data.as_ptr() as *const u8,
data.len() * 4,
)
};
Ok(handle_allsky_fits(&data, tile_size, texture_size)?
.map(|image| ImageType::RawRgba8u { image })
.collect())
}
InMemData::F64(data) => {
let data = data.iter().map(|v| *v as f32).collect::<Vec<_>>();
let data = unsafe { std::slice::from_raw_parts(data.as_ptr() as *const u8, data.len() * 4) };
let data = unsafe {
std::slice::from_raw_parts(
data.as_ptr() as *const u8,
data.len() * 4,
)
};
Ok(handle_allsky_fits(&data, tile_size, texture_size)?
.map(|image| ImageType::RawRgba8u { image })
@@ -228,71 +238,77 @@ fn handle_allsky_file<F: ImageFormat>(
let num_allsky_tiles_per_tile = (tile_size / allsky_tile_size) * (tile_size / allsky_tile_size);
let mut src_idx = 0;
let tiles = (0..num_tiles)
.map(move |_| {
let mut base_tile =
let tiles = (0..num_tiles).map(move |_| {
let mut base_tile =
ImageBuffer::<F>::allocate(&<F as ImageFormat>::P::BLACK, tile_size, tile_size);
for idx_tile in 0..num_allsky_tiles_per_tile {
let (x, y) = crate::utils::unmortonize(idx_tile as u64);
let dx = x * (allsky_tile_size as u32);
let dy = y * (allsky_tile_size as u32);
for idx_tile in 0..num_allsky_tiles_per_tile {
let (x, y) = crate::utils::unmortonize(idx_tile as u64);
let dx = x * (allsky_tile_size as u32);
let dy = y * (allsky_tile_size as u32);
let sx = (src_idx % 27) * allsky_tile_size;
let sy = (src_idx / 27) * allsky_tile_size;
let s = ImageBufferView {
x: sx as i32,
y: sy as i32,
w: allsky_tile_size as i32,
h: allsky_tile_size as i32,
};
let d = ImageBufferView {
x: dx as i32,
y: dy as i32,
w: allsky_tile_size as i32,
h: allsky_tile_size as i32,
};
let sx = (src_idx % 27) * allsky_tile_size;
let sy = (src_idx / 27) * allsky_tile_size;
let s = ImageBufferView {
x: sx as i32,
y: sy as i32,
w: allsky_tile_size as i32,
h: allsky_tile_size as i32,
};
let d = ImageBufferView {
x: dx as i32,
y: dy as i32,
w: allsky_tile_size as i32,
h: allsky_tile_size as i32,
};
base_tile.tex_sub(&allsky, &s, &d);
base_tile.tex_sub(&allsky, &s, &d);
src_idx += 1;
}
src_idx += 1;
}
base_tile
});
base_tile
});
Ok(tiles)
}
fn handle_allsky_fits<F: ImageFormat>(
allsky_data: &[<<F as ImageFormat>::P as Pixel>::Item],
tile_size: i32,
texture_size: i32,
) -> Result<impl Iterator<Item=ImageBuffer<F>>, JsValue> {
) -> Result<impl Iterator<Item = ImageBuffer<F>>, JsValue> {
let allsky_tile_size = std::cmp::min(tile_size, 64);
let width_allsky_px = 27 * allsky_tile_size;
let height_allsky_px = 29 * allsky_tile_size;
// The fits image layout stores rows in reverse
let reversed_rows_data = allsky_data
.chunks(width_allsky_px as usize)
.chunks(width_allsky_px as usize * F::NUM_CHANNELS)
.rev()
.flatten()
.copied()
.collect::<Vec<_>>();
let allsky = ImageBuffer::<F>::new(reversed_rows_data, width_allsky_px, height_allsky_px);
let allsky_tiles_iter = handle_allsky_file::<F>(allsky, allsky_tile_size, texture_size, tile_size)?
.map(move |image| {
// The GPU does a specific transformation on the UV
// for FITS tiles
// We must revert this to be compatible with this GPU transformation
let mut new_image_data = Vec::with_capacity(tile_size as usize);
for c in image.get_data().chunks((tile_size * tile_size) as usize) {
new_image_data.extend(c.chunks(tile_size as usize).rev().flatten());
}
let allsky_tiles_iter =
handle_allsky_file::<F>(allsky, allsky_tile_size, texture_size, tile_size)?.map(
move |image| {
// The GPU does a specific transformation on the UV for FITS tiles
// We must revert this to be compatible with this GPU transformation
let new_image_data = image
.get_data()
.chunks((tile_size * tile_size) as usize * F::NUM_CHANNELS)
.flat_map(|c| {
c.chunks(tile_size as usize * F::NUM_CHANNELS)
.rev()
.flatten()
})
.cloned()
.collect();
ImageBuffer::<F>::new(new_image_data, tile_size, tile_size)
});
ImageBuffer::<F>::new(new_image_data, tile_size, tile_size)
},
);
Ok(allsky_tiles_iter)
}

View File

@@ -76,15 +76,20 @@ impl HEALPixCell {
}
#[inline(always)]
pub fn idx(&self) -> u64 {
pub(crate) const fn idx(&self) -> u64 {
self.1
}
#[inline(always)]
pub fn depth(&self) -> u8 {
pub(crate) const fn depth(&self) -> u8 {
self.0
}
#[inline(always)]
pub fn nside(&self) -> u64 {
1 << self.depth()
}
#[inline(always)]
pub fn is_root(&self) -> bool {
self.depth() == 0
@@ -168,6 +173,19 @@ impl HEALPixCell {
HEALPixTilesIter::new(depth_children, first_idx..last_idx)
}
#[inline]
pub(crate) const fn subdivide(&self) -> [HEALPixCell; 4] {
let children_depth = self.depth() + 1;
let children_idx = self.idx() << 2;
[
HEALPixCell(children_depth, children_idx),
HEALPixCell(children_depth, children_idx + 1),
HEALPixCell(children_depth, children_idx + 2),
HEALPixCell(children_depth, children_idx + 3),
]
}
#[inline]
pub fn allsky(depth: u8) -> impl Iterator<Item = HEALPixCell> {
let npix = 12 << ((depth as usize) << 1);
@@ -193,7 +211,7 @@ impl HEALPixCell {
}
#[inline(always)]
pub fn is_on_pole(&self) -> bool {
pub(crate) fn is_on_pole(&self) -> bool {
let HEALPixCell(depth, idx) = *self;
let two_times_depth = 2 * depth;
@@ -207,6 +225,40 @@ impl HEALPixCell {
}
}
#[inline(always)]
pub(crate) fn has_7_neigh(&self) -> bool {
let base_cell = self.ancestor(self.depth());
let nside_minus_one = (self.nside() - 1) as u32;
let (x, y) = self.offset_in_parent(&base_cell);
match base_cell.idx() {
0..=3 => (x == 0 && y == nside_minus_one) || (y == 0 && x == nside_minus_one),
4..=7 => (x == 0 && y == 0) || (x == nside_minus_one && y == nside_minus_one),
8..=11 => (x == 0 && y == nside_minus_one) || (y == 0 && x == nside_minus_one),
_ => unreachable!()
}
}
#[inline(always)]
pub(crate) fn is_on_base_cell_edges(&self) -> bool {
let base_cell = self.ancestor(self.depth());
let nside_minus_one = (self.nside() - 1) as u32;
let (x, y) = self.offset_in_parent(&base_cell);
if x == 0 || x == nside_minus_one {
return true;
}
if y == 0 || y == nside_minus_one {
return true;
}
false
}
// Given in ICRS
#[inline]
pub fn new(depth: u8, theta: f64, delta: f64) -> Self {

View File

@@ -10,6 +10,7 @@ use al_core::colormap::Colormaps;
use al_core::image::format::ChannelType;
use cgmath::Vector3;
use crate::math::angle::ToAngle;
use crate::downloader::query;
use al_core::image::Image;
@@ -31,10 +32,7 @@ use crate::{math::lonlat::LonLatT, utils};
use crate::downloader::request::allsky::Allsky;
use crate::healpix::{cell::HEALPixCell, coverage::HEALPixCoverage};
use crate::renderable::utils::index_patch::DefaultPatchIndexIter;
use crate::time::Time;
use crate::math::angle::ToAngle;
use super::config::HiPSConfig;
use std::collections::HashSet;
@@ -451,7 +449,15 @@ impl HiPS2D {
// Retrieve the model and inverse model matrix
let mut off_indices = 0;
// Define a global level of subdivisions for all the healpix tile cells in the view
// This should prevent seeing many holes
// We compute it from the first cell in the view but it might be an under/over estimate for the other cells in the view
let num_sub = self.hpx_cells_in_view.iter()
.map(|cell| super::subdivide::num_hpx_subdivision(cell, camera, projection))
.max().unwrap();
//let num_sub =
// super::subdivide::num_hpx_subdivision(&self.hpx_cells_in_view[0], camera, projection);
for cell in &self.hpx_cells_in_view {
// filter textures that are not in the moc
let cell_in_cov = if let Some(moc) = self.footprint_moc.as_ref() {
@@ -559,64 +565,70 @@ impl HiPS2D {
let d01e = uv_1[TileCorner::BottomRight].x - uv_1[TileCorner::BottomLeft].x;
let d02e = uv_1[TileCorner::TopLeft].y - uv_1[TileCorner::BottomLeft].y;
let sub_cells =
super::subdivide::subdivide_hpx_cell(cell, num_sub, camera);
let num_subdivision =
super::subdivide::num_hpxcell_subdivision(cell, camera, projection);
let mut pos = Vec::with_capacity(sub_cells.len() * 4);
let n_segments_by_side: usize = 1 << (num_subdivision as usize);
let n_segments_by_side_f32 = n_segments_by_side as f32;
let mut idx = 0;
let n_vertices_per_segment = n_segments_by_side + 1;
for sub_cell in sub_cells {
let (i, j) = sub_cell.offset_in_parent(cell);
let nside = (1 << (sub_cell.depth() - cell.depth())) as f32;
let mut pos = Vec::with_capacity((n_segments_by_side + 1) * 4);
for ((lon, lat), (di, dj)) in
sub_cell
.vertices()
.iter()
.zip([(0, 0), (1, 0), (1, 1), (0, 1)])
{
let hj0 = ((j + dj) as f32) / nside;
let hi0 = ((i + di) as f32) / nside;
let grid_lonlat =
healpix::nested::grid(cell.depth(), cell.idx(), n_segments_by_side as u16);
let grid_lonlat_iter = grid_lonlat.iter();
let uv_start = [
uv_0[TileCorner::BottomLeft].x + hj0 * d01s,
uv_0[TileCorner::BottomLeft].y + hi0 * d02s,
uv_0[TileCorner::BottomLeft].z,
];
for (idx, &(lon, lat)) in grid_lonlat_iter.enumerate() {
let i: usize = idx / n_vertices_per_segment;
let j: usize = idx % n_vertices_per_segment;
let uv_end = [
uv_1[TileCorner::BottomLeft].x + hj0 * d01e,
uv_1[TileCorner::BottomLeft].y + hi0 * d02e,
uv_1[TileCorner::BottomLeft].z,
];
let hj0 = (j as f32) / n_segments_by_side_f32;
let hi0 = (i as f32) / n_segments_by_side_f32;
self.uv_start.extend(uv_start);
self.uv_end.extend(uv_end);
self.time_tile_received.push(start_time);
let uv_start = [
uv_0[TileCorner::BottomLeft].x + hj0 * d01s,
uv_0[TileCorner::BottomLeft].y + hi0 * d02s,
uv_0[TileCorner::BottomLeft].z,
];
let xyz = crate::math::lonlat::radec_to_xyz(lon.to_angle(), lat.to_angle());
pos.push([xyz.x as f32, xyz.y as f32, xyz.z as f32]);
}
let uv_end = [
uv_1[TileCorner::BottomLeft].x + hj0 * d01e,
uv_1[TileCorner::BottomLeft].y + hi0 * d02e,
uv_1[TileCorner::BottomLeft].z,
];
// GL TRIANGLES
self.idx_vertices.extend([
idx + off_indices,
idx + 1 + off_indices,
idx + 2 + off_indices,
idx + off_indices,
idx + 2 + off_indices,
idx + 3 + off_indices,
]);
// GL LINES
/*self.idx_vertices.extend([
idx + off_indices,
idx + 1 + off_indices,
idx + 1 + off_indices,
idx + 2 + off_indices,
idx + 2 + off_indices,
idx + 3 + off_indices,
idx + 3 + off_indices,
idx + off_indices,
]);*/
self.uv_start.extend(uv_start);
self.uv_end.extend(uv_end);
self.time_tile_received.push(start_time);
let xyz = crate::math::lonlat::radec_to_xyz(lon.to_angle(), lat.to_angle());
pos.push([xyz.x as f32, xyz.y as f32, xyz.z as f32]);
idx += 4;
}
let patch_indices_iter = DefaultPatchIndexIter::new(
&(0..=n_segments_by_side),
&(0..=n_segments_by_side),
n_vertices_per_segment,
)
.flatten()
.map(|indices| {
[
indices.0 + off_indices,
indices.1 + off_indices,
indices.2 + off_indices,
]
})
.flatten();
self.idx_vertices.extend(patch_indices_iter);
off_indices += pos.len() as u16;
// Replace options with an arbitrary vertex
@@ -773,6 +785,7 @@ impl HiPS2D {
.bind_vertex_array_object_ref(&self.vao)
.draw_elements_with_i32(
WebGl2RenderingContext::TRIANGLES,
//WebGl2RenderingContext::LINES,
Some(self.num_idx as i32),
WebGl2RenderingContext::UNSIGNED_SHORT,
0,

View File

@@ -28,7 +28,6 @@ use crate::math::lonlat::LonLatT;
use crate::downloader::request::allsky::Allsky;
use crate::healpix::{cell::HEALPixCell, coverage::HEALPixCoverage};
use crate::renderable::utils::index_patch::DefaultPatchIndexIter;
use crate::time::Time;
use super::config::HiPSConfig;
@@ -94,47 +93,6 @@ pub fn get_raster_shader<'a>(
}
}
/*
pub fn get_raytracer_shader<'a>(
cmap: &Colormap,
gl: &WebGlContext,
shaders: &'a mut ShaderManager,
config: &HiPSConfig,
) -> Result<&'a Shader, JsValue> {
//let colored_hips = config.is_colored();
if config.get_format().is_colored() && cmap.label() == "native" {
crate::shader::get_shader(
gl,
shaders,
"hips_raytracer_raytracer.vert",
"hips_raytracer_color.frag",
)
} else {
if config.tex_storing_unsigned_int {
crate::shader::get_shader(
gl,
shaders,
"hips_raytracer_raytracer.vert",
"hips_raytracer_grayscale_to_colormap_u.frag",
)
} else if config.tex_storing_integers {
crate::shader::get_shader(
gl,
shaders,
"hips_raytracer_raytracer.vert",
"hips_raytracer_grayscale_to_colormap_i.frag",
)
} else {
crate::shader::get_shader(
gl,
shaders,
"hips_raytracer_raytracer.vert",
"hips_raytracer_grayscale_to_colormap.frag",
)
}
}
}*/
pub struct HiPS3D {
//color: Color,
// The image survey texture buffer
@@ -355,6 +313,15 @@ impl HiPS3D {
let channel = self.get_config().get_format().get_channel();
// Define a global level of subdivisions for all the healpix tile cells in the view
// This should prevent seeing many holes
// We compute it from the first cell in the view but it might be an under/over estimate for the other cells in the view
//let num_sub = super::subdivide::num_hpx_subdivision(&self.hpx_cells_in_view[0], camera, proj);
let num_sub = self.hpx_cells_in_view.iter()
.map(|cell| super::subdivide::num_hpx_subdivision(cell, camera, proj))
.max().unwrap();
for cell in &self.hpx_cells_in_view {
// filter textures that are not in the moc
let cell = if let Some(moc) = self.footprint_moc.as_ref() {
@@ -405,62 +372,68 @@ impl HiPS3D {
let d01e = uv_1[TileCorner::BottomRight].x - uv_1[TileCorner::BottomLeft].x;
let d02e = uv_1[TileCorner::TopLeft].y - uv_1[TileCorner::BottomLeft].y;
let num_subdivision =
super::subdivide::num_hpxcell_subdivision(cell, camera, proj);
let sub_cells = super::subdivide::subdivide_hpx_cell(cell, num_sub, camera);
let n_segments_by_side: usize = 1 << (num_subdivision as usize);
let n_segments_by_side_f32 = n_segments_by_side as f32;
let mut pos = Vec::with_capacity(sub_cells.len() * 4);
let n_vertices_per_segment = n_segments_by_side + 1;
let mut idx = 0;
let mut pos = Vec::with_capacity((n_segments_by_side + 1) * 4);
let tmp = self.idx_vertices.len();
let grid_lonlat =
healpix::nested::grid(cell.depth(), cell.idx(), n_segments_by_side as u16);
let grid_lonlat_iter = grid_lonlat.iter();
for sub_cell in sub_cells {
let (i, j) = sub_cell.offset_in_parent(cell);
let nside = (1 << (sub_cell.depth() - cell.depth())) as f32;
for (idx, &(lon, lat)) in grid_lonlat_iter.enumerate() {
let i: usize = idx / n_vertices_per_segment;
let j: usize = idx % n_vertices_per_segment;
for ((lon, lat), (di, dj)) in sub_cell.vertices().iter().zip([(0, 0), (1, 0), (1, 1), (0, 1)]) {
let hj0 = ((j + dj) as f32) / nside;
let hi0 = ((i + di) as f32) / nside;
let hj0 = (j as f32) / n_segments_by_side_f32;
let hi0 = (i as f32) / n_segments_by_side_f32;
let uv_end = [
uv_1[TileCorner::BottomLeft].x + hj0 * d01e,
uv_1[TileCorner::BottomLeft].y + hi0 * d02e,
uv_1[TileCorner::BottomLeft].z,
];
let uv_end = [
uv_1[TileCorner::BottomLeft].x + hj0 * d01e,
uv_1[TileCorner::BottomLeft].y + hi0 * d02e,
uv_1[TileCorner::BottomLeft].z,
];
self.uv.extend(uv_end);
self.uv.extend(uv_end);
pos.push([*lon as f32, *lat as f32]);
}
pos.push([lon as f32, lat as f32]);
// GL TRIANGLES
self.idx_vertices.extend([
idx + off_indices,
idx + 2 + off_indices,
idx + 1 + off_indices,
idx + off_indices,
idx + 3 + off_indices,
idx + 2 + off_indices,
]);
// GL LINES
/*self.idx_vertices.extend([
idx + off_indices,
idx + 1 + off_indices,
idx + 1 + off_indices,
idx + 2 + off_indices,
idx + 2 + off_indices,
idx + 3 + off_indices,
idx + 3 + off_indices,
idx + off_indices,
]);*/
idx += 4;
}
let patch_indices_iter = DefaultPatchIndexIter::new(
&(0..=n_segments_by_side),
&(0..=n_segments_by_side),
n_vertices_per_segment,
)
.flatten()
.map(|indices| {
[
indices.0 + off_indices,
indices.1 + off_indices,
indices.2 + off_indices,
]
})
.flatten();
let tmp = self.idx_vertices.len();
self.idx_vertices.extend(patch_indices_iter);
off_indices += pos.len() as u16;
self.num_indices.push(self.idx_vertices.len() - tmp);
off_indices += pos.len() as u16;
// Replace options with an arbitrary vertex
let position_iter = pos
.into_iter()
//.map(|ndc| ndc.unwrap_or([0.0, 0.0]))
.flatten();
self.position.extend(position_iter);
}

View File

@@ -3,9 +3,9 @@ use crate::math::projection::ProjectionType;
use crate::math::vector::dist2;
use crate::HEALPixCell;
use crate::math::angle::ToAngle;
const M: f64 = 280.0 * 280.0;
const N: f64 = 150.0 * 150.0;
const RAP: f64 = 0.7;
const M: f64 = 220.0 * 220.0;
fn is_too_large(cell: &HEALPixCell, camera: &CameraViewPort, projection: &ProjectionType) -> bool {
let vertices = cell
.vertices()
@@ -21,47 +21,128 @@ fn is_too_large(cell: &HEALPixCell, camera: &CameraViewPort, projection: &Projec
} else {
let d1 = dist2(vertices[0].as_ref(), &vertices[2].as_ref());
let d2 = dist2(vertices[1].as_ref(), &vertices[3].as_ref());
if d1 > M || d2 > M {
true
} else if d1 < N && d2 < N {
false
} else {
let rap = if d2 > d1 { d1 / d2 } else { d2 / d1 };
rap < RAP
}
d1 > M || d2 > M
}
}
pub fn num_hpxcell_subdivision(
pub(crate) fn num_hpx_subdivision(
cell: &HEALPixCell,
camera: &CameraViewPort,
projection: &ProjectionType,
) -> u8 {
let d = cell.depth();
// Subdivide all cells at least one time.
// TODO: use a single subdivision number computed from the current cells inside the view
// i.e. subdivide all cells in the view with the cell that has to be the most subdivided
let mut num_sub = 1;
if d < 2 {
num_sub = 2 - d;
let d0 = cell.depth();
let num_sub = num_hpx_subdivision_rec(cell, d0, camera, projection);
// Ensure that the HEALPix cells wireframe is at least composed of order 3 cells
let sub_cells_depth = d0 + num_sub;
if sub_cells_depth < 3 {
num_sub + (3 - sub_cells_depth)
} else {
num_sub
}
// Largest deformation cell among the cells of a specific depth
let largest_center_to_vertex_dist =
healpix::largest_center_to_vertex_distance(d, 0.0, healpix::TRANSITION_LATITUDE);
let smallest_center_to_vertex_dist =
healpix::largest_center_to_vertex_distance(d, 0.0, healpix::LAT_OF_SQUARE_CELL);
let (lon, lat) = cell.center();
let center_to_vertex_dist = healpix::largest_center_to_vertex_distance(d, lon, lat);
let skewed_factor = (center_to_vertex_dist - smallest_center_to_vertex_dist)
/ (largest_center_to_vertex_dist - smallest_center_to_vertex_dist);
if skewed_factor > 0.25 || is_too_large(cell, camera, projection) || cell.is_on_pole() {
num_sub += 1;
}
num_sub
}
fn num_hpx_subdivision_rec(
cell: &HEALPixCell,
d0: u8,
camera: &CameraViewPort,
projection: &ProjectionType,
) -> u8 {
if (cell.depth() - d0) < MAX_HPX_CELL_SUBDIVISION
&& cell.depth() < 29
&& is_too_large(cell, camera, projection)
{
let sub_cells = cell.subdivide();
1 + [
num_hpx_subdivision_rec(&sub_cells[0], d0, camera, projection),
num_hpx_subdivision_rec(&sub_cells[1], d0, camera, projection),
num_hpx_subdivision_rec(&sub_cells[2], d0, camera, projection),
num_hpx_subdivision_rec(&sub_cells[3], d0, camera, projection),
]
.iter()
.max()
.unwrap()
} else {
0
}
}
const MAX_HPX_CELL_SUBDIVISION: u8 = 4;
/// Subdivide a HEALPix cell that is directly mapped to a tile image in many sub cells
/// taking into account the distortion occuring when projecting its vertices into the screen pixel space
pub(crate) fn subdivide_hpx_cell(
cell: &HEALPixCell,
num_subdivisions: u8,
camera: &CameraViewPort,
) -> Box<[HEALPixCell]> {
cell.get_children_cells(num_subdivisions)
.map(|child_cell| {
/*let cell_depth = child_cell.depth();
// Largest deformation cell among the cells of a specific depth
let largest_center_to_vertex_dist = healpix::largest_center_to_vertex_distance(
cell_depth,
0.0,
healpix::TRANSITION_LATITUDE,
);
let smallest_center_to_vertex_dist = healpix::largest_center_to_vertex_distance(
cell_depth,
0.0,
healpix::LAT_OF_SQUARE_CELL,
);
let (lon, lat) = child_cell.center();
let center_to_vertex_dist =
healpix::largest_center_to_vertex_distance(cell_depth, lon, lat);
let skewed_factor = (center_to_vertex_dist - smallest_center_to_vertex_dist)
/ (largest_center_to_vertex_dist - smallest_center_to_vertex_dist);*/
let lat = child_cell.center().1;
let c0 = child_cell.ancestor(child_cell.depth()).idx();
let c3 = child_cell.ancestor(child_cell.depth() - 3);
let (x3i, y3i) = c3.get_offset_in_texture_cell(c3.depth());
let nside3i = c3.nside() as u32;
let c3_s = (x3i, y3i) == (0, nside3i - 1) || (x3i, y3i) == (nside3i - 1, 0);
let (x, y) = child_cell.get_offset_in_texture_cell(child_cell.depth());
let nside = child_cell.nside() as u32;
let collignon_equatorial_frontier = ((0..=3).contains(&c0) || (8..=11).contains(&c0)) && ((x + y) as i32 - (nside as i32) + 1).abs() <= 1;
// A HEALPix cell would be distorted if
let hpx_num_sub = if camera.get_aperture() >= 15.0_f64.to_radians() &&
// cells at the frontier between collignon and equatorial HEALpix zones
((0..=3).contains(&c0) || (8..=11).contains(&c0)) &&
// neighbors of cells having only 7 neighbors (the most distorted ones)
c3_s
{
// more specific cells needing a subdivision
2
} else if collignon_equatorial_frontier && c3_s {
// on the collignon/equatorial fence and part of a 3 order cell having only 7 neighbors
1
} else if child_cell.is_on_pole() {
// it lies on a pole
1
} else if child_cell.is_on_base_cell_edges() && lat.abs() >= healpix::TRANSITION_LATITUDE {
// it lies on a frontier between base cells and at a high absolute latitude
1
} else {
0
};
// Subdivide one more time if the HEALPix cell is distorted
child_cell.get_children_cells(hpx_num_sub)
})
.flatten()
.collect::<Vec<_>>()
.into_boxed_slice()
}

View File

@@ -2,10 +2,10 @@ use crate::downloader::{query, Downloader};
use crate::time::{DeltaTime, Time};
use crate::Abort;
use al_api::moc::MOCOptions;
use std::cell::RefCell;
use std::collections::{HashMap, VecDeque};
use std::rc::Rc;
use al_api::moc::MOCOptions;
const MAX_NUM_TILE_FETCHING: usize = 8;
const MAX_QUERY_QUEUE_LENGTH: usize = 100;
@@ -214,7 +214,7 @@ impl TileFetcherQueue {
let tile_size = cfg.get_tile_size();
//Request the allsky for the small tile size or if base tiles are not available
if tile_size <= 128 || cfg.get_min_depth_tile() > 0 {
if tile_size <= 256 || cfg.get_min_depth_tile() > 0 {
// Request the allsky
downloader.borrow_mut().fetch(query::Allsky::new(
cfg,

View File

@@ -413,6 +413,8 @@ export let Aladin = (function () {
// Merge what is already in the cache for that HiPS with new properties
// coming from the MOCServer
this.hipsFavorites.push(hipsObj);
// Favorites are also directly pushed to the cache
this.hipsCache.append(hipsObj.id, hipsObj)
}
this._setupUI(options);
@@ -432,11 +434,7 @@ export let Aladin = (function () {
});
} else if (options.survey === HiPS.DEFAULT_SURVEY_ID) {
// DSS is cached inside HiPS class, no need to provide any further information
const survey = this.createImageSurvey(
HiPS.DEFAULT_SURVEY_ID
);
this.setBaseImageLayer(survey);
this.setBaseImageLayer(HiPS.DEFAULT_SURVEY_ID);
} else {
this.setBaseImageLayer(options.survey);
}
@@ -472,22 +470,24 @@ export let Aladin = (function () {
// maximize control
if (options.showFullscreenControl) {
// react to fullscreenchange event to restore initial width/height (if user pressed ESC to go back from full screen)
// This event is only triggered with realFullscreen on
Utils.on(
document,
"fullscreenchange webkitfullscreenchange mozfullscreenchange MSFullscreenChange",
function (e) {
() => {
var fullscreenElt =
document.fullscreenElement ||
document.webkitFullscreenElement ||
document.mozFullScreenElement ||
document.msFullscreenElement;
if (fullscreenElt === null || fullscreenElt === undefined) {
self.toggleFullscreen(options.realFullscreen);
var fullScreenToggledFn =
self.callbacksByEventName["fullScreenToggled"];
typeof fullScreenToggledFn === "function" &&
fullScreenToggledFn(self.isInFullscreen);
// fix: Only toggle off the screen once because in case of closing the real fullscreen from the ui button, this could be called 2 times
// * one toggleFullscreen from the button itself
// * one toggleFullscreen from the fullscreenchange event
// => resulting in closing and opening the fullscreen again.
if (self.isInFullscreen) {
self.toggleFullscreen(options.realFullscreen);
}
}
}
);
@@ -709,7 +709,6 @@ export let Aladin = (function () {
Aladin.prototype.toggleFullscreen = function (realFullscreen) {
let self = this;
realFullscreen = Boolean(realFullscreen);
self.isInFullscreen = !self.isInFullscreen;
ContextMenu.hideAll();
@@ -720,13 +719,7 @@ export let Aladin = (function () {
ui.toggle();
}
})
if (this.aladinDiv.classList.contains("aladin-fullscreen")) {
this.aladinDiv.classList.remove("aladin-fullscreen");
} else {
this.aladinDiv.classList.add("aladin-fullscreen");
}
if (realFullscreen) {
// go to "real" full screen mode
if (self.isInFullscreen) {
@@ -757,6 +750,8 @@ export let Aladin = (function () {
}
}
this.aladinDiv.classList.toggle("aladin-fullscreen");
// Delay the fixLayoutDimensions layout for firefox
/*setTimeout(function () {
self.view.fixLayoutDimensions();
@@ -1579,10 +1574,8 @@ export let Aladin = (function () {
let hipsOptions = { id, name, maxOrder, url, cooFrame, ...options };
let hips = new HiPS(id, url || id, hipsOptions)
// This allows to retrieve the survey's options when it will be
// added later to the view.
if (this instanceof Aladin && !this.hipsCache.contains(hips.id)) {
// Add it to the cache as soon as possible if we have a reference to the aladin object
// A HiPS can be refered by its unique ID thus we add it to the cache (cf excample/al-cfht.html that refers to HiPS object just by their unique ID)
if (this instanceof Aladin) {
this.hipsCache.append(hips.id, hipsOptions)
}
@@ -1939,12 +1932,14 @@ export let Aladin = (function () {
let imageLayer;
let hipsCache = this.hipsCache;
// 1. User gives an ID
if (typeof urlOrHiPSOrFITS === "string") {
const idOrUrl = urlOrHiPSOrFITS;
// many cases here
// 1/ It has been already added to the cache
let cachedOptions = hipsCache.get(idOrUrl)
if (cachedOptions) {
imageLayer = A.HiPS(idOrUrl, cachedOptions);
} else {
@@ -1964,7 +1959,7 @@ export let Aladin = (function () {
if (!cachedLayerOptions) {
hipsCache.append(imageLayer.id, imageLayer.options)
} else {
// set the options from what is in the cache
// Set the options from what is in the cache
imageLayer.setOptions(cachedLayerOptions);
}
}

View File

@@ -613,7 +613,6 @@ export let Catalog = (function () {
// Set the same color of the shape than the catalog.
// FIXME: the color/shape could be a parameter at the source level, allowing the user single catalogs handling different shapes
shape.setColor(this.color)
shape.setSelectionColor(this.selectionColor);
shape.setHoverColor(this.hoverColor);
}

View File

@@ -640,6 +640,7 @@ export let View = (function () {
var footprintClickedFunction = view.aladin.callbacksByEventName['footprintClicked'];
let objsByCats = {};
let shapes = [];
for (let o of objs) {
// classify the different objects by catalog
let cat = o.getCatalog && o.getCatalog();
@@ -658,11 +659,22 @@ export let View = (function () {
footprintClickedFunction(o, xy);
}
}
// If this shape has a catalog then it will be selected from its source
// so we will not add it
if (!cat) {
shapes.push(o);
}
}
// rewrite objs
// Rewrite objs
objs = Array.from(Object.values(objsByCats));
// Add the external shapes (i.e. which are not associated with catalog sources e.g. those from GraphicOverlay)
if (shapes.length > 0) {
objs.push(shapes)
}
view.selectObjects(objs);
view.lastClickedObject = objs;
} else {
@@ -1209,7 +1221,7 @@ export let View = (function () {
switch (e.keyCode) {
// escape
case 27:
// if there is a selection occuring
// Called when realfullscreen is false. Escaping from real fullscreen does not seem to trigger the keydown event
if (view.aladin.isInFullscreen) {
view.aladin.toggleFullscreen(view.aladin.options.realFullscreen);
}
@@ -2101,26 +2113,21 @@ export let View = (function () {
}
let closests = [];
const fLineWidth = (footprints && footprints[0] && footprints[0].getLineWidth()) || 1;
let lw = fLineWidth + 3;
//for (var lw = startLw + 1; lw <= startLw + 3; lw++) {
footprints.forEach((footprint) => {
if (!footprint.source || !footprint.source.tooSmallFootprint) {
// Hidden footprints are not considered
//let originLineWidth = footprint.getLineWidth();
footprint.setLineWidth(lw);
if (footprint.isShowing && footprint.isInStroke(ctx, this, x * window.devicePixelRatio, y * window.devicePixelRatio)) {
closests.push(footprint);
}
footprint.setLineWidth(fLineWidth);
}
})
/* if (closests.length > 0) {
break;
footprints.forEach((footprint) => {
if (!footprint.source || !footprint.source.tooSmallFootprint) {
const originLineWidth = footprint.getLineWidth();
let spreadedLineWidth = (originLineWidth || 1) + 3;
footprint.setLineWidth(spreadedLineWidth);
if (footprint.isShowing && footprint.isInStroke(ctx, this, x * window.devicePixelRatio, y * window.devicePixelRatio)) {
closests.push(footprint);
}
footprint.setLineWidth(originLineWidth);
}
}*/
})
return closests;
};
@@ -2132,13 +2139,11 @@ export let View = (function () {
var canvas = this.catalogCanvas;
var ctx = canvas.getContext("2d");
// this makes footprint selection easier as the catch-zone is larger
//let pastLineWidth = ctx.lineWidth;
let closests = [];
if (this.overlays) {
for (var k = 0; k < this.overlays.length; k++) {
overlay = this.overlays[k];
closests = closests.concat(this.closestFootprints(overlay.overlayItems, ctx, x, y));
}
}

View File

@@ -528,15 +528,7 @@ export class OverlayStackBox extends Box {
position: self.position,
});*/
self.aladin.addNewImageLayer(
A.imageHiPS('P/DSS2/color', {
errorCallback: (e) => {
aladin.addStatusBarMessage({
duration: 2000,
type: 'info',
message: 'DSS2 colored HiPS could not plot',
})
}
})
'P/DSS2/color'
);
},
},
@@ -940,6 +932,7 @@ export class OverlayStackBox extends Box {
options.push(value)
}
let HiPSSelector = Input.select({
value,
options,

View File

@@ -57,8 +57,8 @@ export class FullScreenActionButton extends ActionButton {
if (aladin.statusBar) {
aladin.statusBar.removeMessage('tooltip')
}
aladin.toggleFullscreen(aladin.options.realFullscreen);
aladin.toggleFullscreen(aladin.options.realFullscreen);
}
})

View File

@@ -48,7 +48,7 @@ export let Circle = (function() {
this.color = options['color'] || undefined;
this.fillColor = options['fillColor'] || undefined;
this.lineWidth = options["lineWidth"] || 2;
this.lineWidth = options["lineWidth"] || undefined;
this.selectionColor = options["selectionColor"] || '#00ff00';
this.hoverColor = options["hoverColor"] || undefined;
this.opacity = options['opacity'] || 1;
@@ -297,6 +297,10 @@ export let Circle = (function() {
ctx.strokeStyle = baseColor;
}
if (!this.lineWidth) {
this.lineWidth = (this.overlay && this.overlay.lineWidth) || 2;
}
ctx.lineWidth = this.lineWidth;
ctx.globalAlpha = this.opacity;
ctx.beginPath();

View File

@@ -51,7 +51,7 @@ export let Ellipse = (function() {
this.color = options['color'] || undefined;
this.fillColor = options['fillColor'] || undefined;
this.lineWidth = options["lineWidth"] || 2;
this.lineWidth = options["lineWidth"] || undefined;
this.selectionColor = options["selectionColor"] || '#00ff00';
this.hoverColor = options["hoverColor"] || undefined;
this.opacity = options['opacity'] || 1;
@@ -283,6 +283,10 @@ export let Ellipse = (function() {
ctx.strokeStyle = baseColor;
}
if (!this.lineWidth) {
this.lineWidth = (this.overlay && this.overlay.lineWidth) || 2;
}
ctx.lineWidth = this.lineWidth;
ctx.globalAlpha = this.opacity;
ctx.beginPath();