Compare commits

..

10 Commits

Author SHA1 Message Date
Matthieu Baumann
191d1628f3 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-03 18:09:26 +02:00
bmatthieu3
ee2e79e310 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-03 18:04:06 +02:00
bmatthieu3
abf6dcc9ec Performance
Do all CPU computations on Vec3 and not Vec4
2025-04-03 18:04:06 +02:00
bmatthieu3
822d5dd952 Set zoomfactor when using smartphones
Refers back to PR #249
2025-04-03 18:04:06 +02:00
bmatthieu3
5ca9f9833e update readme, make the release page link more visible 2025-04-03 18:04:06 +02:00
bmatthieu3
4f25177434 add getZoomFactor method in Aladin 2025-04-03 18:04:06 +02:00
bmatthieu3
b6a6dd15e4 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-03 18:04:06 +02:00
bmatthieu3
247f14f2c0 Update changelog 2025-04-03 18:04:06 +02:00
Matthieu Baumann
6158aa5b1d First commit for 3.7.0
* add MOC setable properties: fill, edge and perimeter
* change package.json to 3.7.0-beta
2025-04-03 18:04:06 +02:00
Matthieu Baumann
b66d832a46 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:04:04 +02:00
9 changed files with 69 additions and 76 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.5",
"softwareVersion": "3.6.5",
"version": "3.6.4",
"softwareVersion": "3.6.4",
"description": "An astronomical HiPS visualizer in the browser.",
"identifier": "10.5281/zenodo.7638833",
"applicationCategory": "Astronomy, Visualization",

View File

@@ -11,7 +11,7 @@
let aladin;
A.init.then(() => {
// Start up Aladin Lite
aladin = A.aladin('#aladin-lite-div', {target: 'M 1', fov: 0.2, showContextMenu: true, fullScreen: true});
aladin = A.aladin('#aladin-lite-div', {survey: "CDS/P/DSS2/color", target: 'M 1', fov: 0.2, showContextMenu: true, fullScreen: true});
var overlay = A.graphicOverlay({color: '#ee2345', lineWidth: 3, lineDash: [2, 2]});
aladin.addOverlay(overlay);
overlay.addFootprints([

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, target: "280 +0", projection: "AIT", showShareControl:true, showSettingsControl: true, showContextMenu:true});
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});
aladin.setOverlayImageLayer(A.image(
"https://www.virtualastronomy.org/images/sig05-013.jpg",

View File

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

View File

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

View File

@@ -185,24 +185,14 @@ 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 })
@@ -238,77 +228,71 @@ 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 * F::NUM_CHANNELS)
.chunks(width_allsky_px as usize)
.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 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();
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());
}
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

@@ -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 <= 256 || cfg.get_min_depth_tile() > 0 {
if tile_size <= 128 || cfg.get_min_depth_tile() > 0 {
// Request the allsky
downloader.borrow_mut().fetch(query::Allsky::new(
cfg,

View File

@@ -413,8 +413,6 @@ 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);
@@ -434,7 +432,11 @@ 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
this.setBaseImageLayer(HiPS.DEFAULT_SURVEY_ID);
const survey = this.createImageSurvey(
HiPS.DEFAULT_SURVEY_ID
);
this.setBaseImageLayer(survey);
} else {
this.setBaseImageLayer(options.survey);
}
@@ -1574,8 +1576,10 @@ export let Aladin = (function () {
let hipsOptions = { id, name, maxOrder, url, cooFrame, ...options };
let hips = new HiPS(id, url || id, hipsOptions)
// 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 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
this.hipsCache.append(hips.id, hipsOptions)
}
@@ -1932,14 +1936,12 @@ 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 {
@@ -1959,7 +1961,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

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