Compare commits

..

1 Commits

Author SHA1 Message Date
Thomas Boch
7f1f69983f Create AUTHORS file 2025-04-22 15:23:56 +02:00
33 changed files with 231 additions and 228 deletions

25
AUTHORS Normal file
View File

@@ -0,0 +1,25 @@
AUTHORS
=======
This file lists the main developers and contributors to this project.
For a full list of commit authors, see: https://github.com/cds-astro/aladin-lite/graphs/contributors
Institutional Affiliation
--------------------------
Centre de Données astronomiques de Strasbourg (CDS)
https://cds.unistra.fr/
Main Developers
---------------
Thomas Boch (@tboch)
Matthieu Baumann (@bmatthieu3)
Acknowledgments
---------------
We also acknowledge all contributors who have submitted bug reports, feature requests,
documentation improvements, and patches through GitHub issues and pull requests.
This project is hosted on GitHub:
https://github.com/cds-astro/aladin-lite

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.1",
"softwareVersion": "3.6.1",
"description": "An astronomical HiPS visualizer in the browser.",
"identifier": "10.5281/zenodo.7638833",
"applicationCategory": "Astronomy, Visualization",

View File

@@ -11,9 +11,9 @@
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);
/*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, 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

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

View File

@@ -2,7 +2,7 @@
"homepage": "https://aladin.u-strasbg.fr/",
"name": "aladin-lite",
"type": "module",
"version": "3.6.5",
"version": "3.6.1",
"description": "An astronomical HiPS visualizer in the browser",
"author": "Thomas Boch and Matthieu Baumann",
"license": "GPL-3",

View File

@@ -3,7 +3,7 @@ name = "aladin-lite"
description = "Aladin Lite v3 introduces a new graphical engine written in Rust with the use of WebGL"
license = "BSD-3-Clause"
repository = "https://github.com/cds-astro/aladin-lite"
version = "3.6.5"
version = "3.6.1"
authors = [ "baumannmatthieu0@gmail.com", "matthieu.baumann@astro.unistra.fr",]
edition = "2018"
@@ -22,7 +22,7 @@ url-lite = "0.1.0"
serde_json = "1.0.104"
serde-wasm-bindgen = "0.5"
enum_dispatch = "0.3.8"
wasm-bindgen = "=0.2.92"
wasm-bindgen = "0.2.100"
wasm-streams = "0.3.0"
async-channel = "1.8.0"
mapproj = "0.3.0"
@@ -64,7 +64,7 @@ path = "./al-core"
path = "./al-api"
[dependencies.web-sys]
version = "0.3.56"
version = "*"
features = [ "console", "CssStyleDeclaration", "Document", "Element", "HtmlCollection", "HtmlElement", "HtmlImageElement", "HtmlCanvasElement", "Blob", "ImageBitmap", "ImageData", "CanvasRenderingContext2d", "WebGlBuffer", "WebGlContextAttributes", "WebGlFramebuffer", "WebGlProgram", "WebGlShader", "WebGlUniformLocation", "WebGlTexture", "WebGlActiveInfo", "Headers", "Window", "Request", "RequestInit", "RequestMode", "Response", "XmlHttpRequest", "XmlHttpRequestResponseType", "PerformanceTiming", "Performance", "Url", "ReadableStream", "File", "FileList",]
[dev-dependencies.image-decoder]

View File

@@ -1,6 +1,6 @@
[package]
name = "al-api"
version = "3.6.5"
version = "0.1.0"
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 = "0.1.0"
authors = ["baumannmatthieu0@gmail.com", "matthieu.baumann@astro.unistra.fr"]
edition = "2018"
@@ -17,7 +17,9 @@ serde-wasm-bindgen = "0.4"
wasm-streams = "0.3.0"
futures = "0.3.25"
colorgrad = "0.6.2"
wasm-bindgen = "0.2.92"
[dependencies.wasm-bindgen]
version = "0.2.92"
[dev-dependencies]
fontdue = "0.7.2"
@@ -36,7 +38,7 @@ webgl2 = [
]
[dependencies.web-sys]
version = "0.3.56"
version = "0.3.77"
features = [
'console',
'CssStyleDeclaration',

View File

@@ -1,7 +1,6 @@
use crate::renderable::ImageLayer;
use crate::tile_fetcher::HiPSLocalFiles;
use crate::math::angle::ToAngle;
use crate::renderable::hips::HiPS;
use crate::{
//async_task::{BuildCatalogIndex, ParseTableTask, TaskExecutor, TaskResult, TaskType},
@@ -22,6 +21,7 @@ use crate::{
time::DeltaTime,
};
use al_api::moc::MOCOptions;
use crate::math::angle::ToAngle;
use wcs::WCS;
use wasm_bindgen::prelude::*;
@@ -188,7 +188,7 @@ impl App {
let request_for_new_tiles = true;
let moc = MOCRenderer::new(&gl)?;
gl.clear_color(0.1, 0.1, 0.1, 1.0);
gl.clear_color(0.0, 0.0, 0.0, 1.0);
let (img_send, img_recv) = async_channel::unbounded::<ImageLayer>();
let (ack_img_send, ack_img_recv) = async_channel::unbounded::<ImageParams>();
@@ -714,8 +714,8 @@ impl App {
)?,
}
self.time_start_blending = Time::now();
}
_ => (),
},
_ => ()
};
}
}
@@ -1277,7 +1277,8 @@ impl App {
// Set the new meta
// keep the old meta data
let new_img_ext = meta.img_format;
self.layers.set_layer_cfg(layer.clone(), meta)?;
self.layers
.set_layer_cfg(layer.clone(), meta)?;
if old_meta.img_format != new_img_ext {
// The image format has been changed

View File

@@ -5,8 +5,8 @@ pub enum UserAction {
Moving = 3,
Starting = 4,
}
use web_sys::WebGl2RenderingContext;
// Longitude reversed identity matrix
const ID_R: &Matrix4<f64> = &Matrix4::new(
-1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
@@ -488,11 +488,11 @@ impl CameraViewPort {
pub fn set_center(&mut self, lonlat: &LonLatT<f64>, proj: &ProjectionType) {
let icrs_pos: Vector4<_> = lonlat.vector();
let center = (CooSystem::ICRS.to(self.get_coo_system()) * icrs_pos).truncate();
let rot_to_center = Rotation::from_sky_position(&center);
let view_pos = CooSystem::ICRS.to(self.get_coo_system()) * icrs_pos;
let rot_to_center = Rotation::from_sky_position(&view_pos);
let phi = self.get_center_pos_angle();
let third_euler_rot = Rotation::from_axis_angle(&center, phi);
let third_euler_rot = Rotation::from_axis_angle(&view_pos.truncate(), phi);
let rot = third_euler_rot * rot_to_center;
@@ -502,9 +502,8 @@ impl CameraViewPort {
}
pub fn set_center_pos_angle(&mut self, phi: Angle<f64>, proj: &ProjectionType) {
let c = self.center.truncate();
let rot_to_center = Rotation::from_sky_position(&c);
let third_euler_rot = Rotation::from_axis_angle(&c, phi);
let rot_to_center = Rotation::from_sky_position(&self.center);
let third_euler_rot = Rotation::from_axis_angle(&self.center.truncate(), phi);
let total_rot = third_euler_rot * rot_to_center;
self.set_rotation(&total_rot, proj);
@@ -524,7 +523,7 @@ impl CameraViewPort {
// Compute the center position according to the new coordinate frame system
let new_center = coosys::apply_coo_system(self.coo_sys, new_coo_sys, &self.center);
// Create a rotation object from that position
let new_rotation = Rotation::from_sky_position(&new_center.truncate());
let new_rotation = Rotation::from_sky_position(&new_center);
// Apply it to the center of the view
self.set_rotation(&new_rotation, proj);

View File

@@ -130,9 +130,9 @@ impl From<query::Allsky> for AllskyRequest {
Ok(allsky_tiles)
}
_ => {
let mut opts = RequestInit::new();
opts.method("GET");
opts.mode(RequestMode::Cors);
let opts = RequestInit::new();
opts.set_method("GET");
opts.set_mode(RequestMode::Cors);
let window = web_sys::window().unwrap_abort();
let request = web_sys::Request::new_with_str_and_init(&url_clone, &opts)?;
@@ -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

@@ -61,9 +61,9 @@ impl From<query::PixelMetadata> for PixelMetadataRequest {
let request = match channel {
ChannelType::R32F | ChannelType::R32I | ChannelType::R16I | ChannelType::R8UI => {
Request::new(async move {
let mut opts = RequestInit::new();
opts.method("GET");
opts.mode(RequestMode::Cors);
let opts = RequestInit::new();
opts.set_method("GET");
opts.set_mode(RequestMode::Cors);
let request =
web_sys::Request::new_with_str_and_init(&url_clone, &opts).unwrap_abort();

View File

@@ -61,9 +61,9 @@ impl From<query::Moc> for MOCRequest {
let window = web_sys::window().unwrap_abort();
let request = Request::new(async move {
let mut opts = RequestInit::new();
opts.method("GET");
opts.mode(RequestMode::Cors);
let opts = RequestInit::new();
opts.set_method("GET");
opts.set_mode(RequestMode::Cors);
let request = web_sys::Request::new_with_str_and_init(&url_clone, &opts).unwrap_abort();
let resp_value = JsFuture::from(window.fetch_with_request(&request)).await?;

View File

@@ -142,9 +142,9 @@ impl From<query::Tile> for TileRequest {
| ChannelType::R32I
| ChannelType::R16I
| ChannelType::R8UI => Request::new(async move {
let mut opts = RequestInit::new();
opts.method("GET");
opts.mode(RequestMode::Cors);
let opts = RequestInit::new();
opts.set_method("GET");
opts.set_mode(RequestMode::Cors);
let request =
web_sys::Request::new_with_str_and_init(&url_clone, &opts).unwrap_abort();

View File

@@ -523,7 +523,7 @@ impl WebClient {
/// Get if the longitude axis is reversed
#[wasm_bindgen(js_name = getLongitudeReversed)]
pub fn get_longitude_reversed(&self) -> bool {
pub fn get_longitude_reversed(&mut self) -> bool {
self.app.get_longitude_reversed()
}

View File

@@ -1,8 +1,8 @@
use crate::math;
use crate::math::angle::ToAngle;
use cgmath::{BaseFloat, InnerSpace};
use cgmath::{Euler, Quaternion};
use cgmath::{Vector3, Vector4};
use crate::math::angle::ToAngle;
#[derive(Clone, Copy, Debug)]
// Internal structure of a rotation, a quaternion
@@ -109,13 +109,13 @@ where
// Define a rotation from an axis and a angle
pub fn from_axis_angle(axis: &Vector3<S>, angle: Angle<S>) -> Rotation<S> {
let angle: Rad<S> = angle.into();
let mat4 = Matrix4::from_axis_angle(axis.normalize(), angle);
let mat4 = Matrix4::from_axis_angle(*axis, angle);
(&mat4).into()
}
// Define a rotation from a normalized vector
pub fn from_sky_position(pos: &Vector3<S>) -> Rotation<S> {
let (lon, lat) = math::lonlat::xyz_to_radec(&pos);
pub fn from_sky_position(pos: &Vector4<S>) -> Rotation<S> {
let (lon, lat) = math::lonlat::xyzw_to_radec(&pos.normalize());
let rot_y = Matrix4::from_angle_y(lon);
let rot_x = Matrix4::from_angle_x(-lat);

View File

@@ -95,7 +95,7 @@ impl Renderer for TextRenderManager {
// reset the font and color
self.ctx
.set_font(&format!("{}px verdana, sans-serif", self.font_size));
self.ctx.set_fill_style(&JsValue::from_str(&self.color));
self.ctx.set_fill_style_str(&self.color);
}
fn end(&mut self) {}

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

@@ -505,15 +505,12 @@
.aladin-form .aladin-form-input {
display: flex;
justify-content: flex-end;
align-items: center;
justify-content: space-between;
}
.aladin-form-group > * {
margin-bottom: 0.4rem;
}
.aladin-form-group > *:last-of-type {
.aladin-form .aladin-form-input:last-of-type {
margin-bottom: 0;
}
@@ -530,6 +527,10 @@
width: 100%;
}
.aladin-form .aladin-form-input > label {
flex: 1;
}
.aladin-form .aladin-form-input .aladin-input {
flex: 2;
}
@@ -839,18 +840,13 @@
box-shadow: 0 0 1em 0 rgba(0, 0, 0, 0.2);
cursor: pointer;
font-family: monospace;
width: 100%;
box-sizing: content-box;
/* <option> colors */
/* Remove focus outline */
/* Remove IE arrow */
}
/* This is done so that the select shrink to the size of its parent (coupled with flex)
otherwise it fits its content options. If those are too big the select can go out of its parent */
.aladin-horizontal-list .aladin-input-select {
width: 100%;
}
.aladin-input-select option {
color: inherit;
background-color: #320a28;

View File

@@ -1036,7 +1036,7 @@ A.init = (async () => {
.createElement('canvas')
.getContext('webgl2');
await init();
await init({});
// Check for webgl2 support
if (isWebGL2Supported) {
Aladin.wasmLibs.core = module;

View File

@@ -426,8 +426,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);
@@ -447,7 +445,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);
}
@@ -483,24 +485,22 @@ 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) {
// 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);
}
self.toggleFullscreen(options.realFullscreen);
var fullScreenToggledFn =
self.callbacksByEventName["fullScreenToggled"];
typeof fullScreenToggledFn === "function" &&
fullScreenToggledFn(self.isInFullscreen);
}
}
);
@@ -716,6 +716,7 @@ export let Aladin = (function () {
Aladin.prototype.toggleFullscreen = function (realFullscreen) {
let self = this;
realFullscreen = Boolean(realFullscreen);
self.isInFullscreen = !self.isInFullscreen;
ContextMenu.hideAll();
@@ -726,7 +727,13 @@ 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,8 +764,6 @@ export let Aladin = (function () {
}
}
this.aladinDiv.classList.toggle("aladin-fullscreen");
// Delay the fixLayoutDimensions layout for firefox
/*setTimeout(function () {
self.view.fixLayoutDimensions();
@@ -1564,8 +1569,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)
}
@@ -1922,14 +1929,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 {
@@ -1949,7 +1954,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,6 +613,7 @@ 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

@@ -35,7 +35,6 @@ import cameraIconUrl from '../../assets/icons/camera.svg'
import targetIconUrl from '../../assets/icons/target.svg';
import uploadIconUrl from '../../assets/icons/upload.svg';
import selectIconUrl from '../../assets/icons/select.svg';
import { Utils } from "./Utils";
export let DefaultActionsForContextMenu = (function () {
@@ -56,7 +55,7 @@ export let DefaultActionsForContextMenu = (function () {
return false;
}
Utils.copy2Clipboard(text)
navigator.clipboard.writeText(text)
.then(() => {
msg = 'successful'
if (aladinInstance.statusBar) {

View File

@@ -30,8 +30,6 @@ import { ColorCfg } from "./ColorCfg.js";
import { HiPSProperties } from "./HiPSProperties.js";
import { Aladin } from "./Aladin.js";
import { CooFrameEnum } from "./CooFrameEnum.js";
import { Utils } from "./Utils"
let PropertyParser = {};
// Utilitary functions for parsing the properties and giving default values
/// Mandatory tileSize property
@@ -862,8 +860,9 @@ export let HiPS = (function () {
let isIncompleteOptions = true;
let isID = Utils.isUrl(this.url) === undefined;
// This is very dirty but it allows me to differentiate the location from whether it is an ID or a plain url
let isID = this.url.includes("P/") || this.url.includes("C/")
if (this.imgFormat === "fits") {
// a fits is given
isIncompleteOptions = !(
@@ -888,6 +887,7 @@ export let HiPS = (function () {
if (isIncompleteOptions) {
// ID typed url
if (self.startUrl && isID) {
// First download the properties from the start url
await HiPSProperties.fetchFromUrl(self.startUrl)
.then((p) => {
@@ -909,16 +909,9 @@ export let HiPS = (function () {
HiPSProperties.fetchFromID(id)
.then((p) => {
//self.url = self.startUrl;
self._fetchFasterUrlFromProperties(p);
})
.catch(() => {
// If no ID has been found then it may actually be a path
// url pointing to a local HiPS
return HiPSProperties.fetchFromUrl(id)
.then((p) => {
self._parseProperties(p);
})
})
},
1000
);
@@ -939,14 +932,6 @@ export let HiPS = (function () {
self._parseProperties(p);
self._fetchFasterUrlFromProperties(p);
})
.catch(() => {
// If no ID has been found then it may actually be a path
// url pointing to a local HiPS
return HiPSProperties.fetchFromUrl(id)
.then((p) => {
self._parseProperties(p);
})
})
} catch (e) {
throw e;
}

View File

@@ -38,7 +38,7 @@ HiPSProperties.fetchFromID = async function(ID) {
const params = {
get: "record",
fmt: "json",
ID: "*" + decodeURI(ID) + "*",
ID: "*" + ID + "*",
};
let metadata = await Utils.loadFromUrls(MocServer.MIRRORS_HTTPS, {

View File

@@ -246,6 +246,8 @@ export let View = (function () {
// some variables for mouse handling
this.dragging = false;
this.dragCoo = null;
this.rightclickx = null;
this.rightclicky = null;
this.selectedLayer = 'base';
this.needRedraw = true;
@@ -616,7 +618,6 @@ export let View = (function () {
};
var longTouchTimer;
var longTouchDuration = 800;
var showContextMenu = true;
var xystart;
var handleSelect = function(xy, tolerance) {
@@ -630,7 +631,6 @@ 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();
@@ -649,22 +649,11 @@ 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 {
@@ -699,7 +688,9 @@ export let View = (function () {
if (e.which === 3 || e.button === 2) {
view.rightClick = true;
showContextMenu = true;
view.rightClickTimeStart = Date.now();
view.rightclickx = xymouse.x;
view.rightclicky = xymouse.y;
if (view.selectedLayer) {
const imageLayer = view.imageLayers.get(view.selectedLayer);
@@ -785,11 +776,15 @@ export let View = (function () {
});
if (view.rightClick) {
if (showContextMenu) {
const rightClickDurationMs = Date.now() - view.rightClickTimeStart;
if (rightClickDurationMs < 100) {
view.aladin.contextMenu && view.aladin.contextMenu.show({e});
}
view.rightClick = false;
view.rightclickx = null;
view.rightclicky = null;
view.rightClickTimeStart = undefined;
return;
}
@@ -820,10 +815,11 @@ export let View = (function () {
view.aladin.statusBar.removeMessage('opening-ctxmenu')
}
clearTimeout(longTouchTimer)
longTouchTimer = undefined;
}
}
xystart = undefined;
if ((e.type === 'touchend' || e.type === 'touchcancel') && view.pinchZoomParameters.isPinching) {
view.pinchZoomParameters.isPinching = false;
view.pinchZoomParameters.initialFov = view.pinchZoomParameters.initialDistance = undefined;
@@ -925,6 +921,7 @@ export let View = (function () {
var lastMouseMovePos = null;
Utils.on(view.catalogCanvas, "mousemove touchmove", function (e) {
e.preventDefault();
//e.stopPropagation();
const xymouse = Utils.relMouseCoords(e);
@@ -938,18 +935,16 @@ export let View = (function () {
xy: xymouse,
});
let dist;
if (xystart) {
dist = (xymouse.x - xystart.x)*(xymouse.x - xystart.x) + (xymouse.y - xystart.y)*(xymouse.y - xystart.y);
}
if (e.type === 'touchmove' && xystart) {
let dist = (() => {
return (xymouse.x - xystart.x)*(xymouse.x - xystart.x) + (xymouse.y - xystart.y)*(xymouse.y - xystart.y)
})();
if (longTouchTimer && dist > 100) {
if (view.aladin.statusBar) {
view.aladin.statusBar.removeMessage('opening-ctxmenu')
}
clearTimeout(longTouchTimer)
longTouchTimer = undefined;
xystart = undefined;
}
}
@@ -962,12 +957,11 @@ export let View = (function () {
return;
}
if (dist < 100) {
const rightClickDurationMs = Date.now() - view.rightClickTimeStart;
if (rightClickDurationMs < 100) {
return;
}
showContextMenu = false;
if(view.selectedLayer) {
let selectedLayer = view.imageLayers.get(view.selectedLayer);
@@ -1261,9 +1255,17 @@ export let View = (function () {
return;
switch (e.keyCode) {
// shift
case 16:
view.aladin.select('rect', (selection) => {
view.selectObjects(selection);
})
break;
// escape
case 27:
// Called when realfullscreen is false. Escaping from real fullscreen does not seem to trigger the keydown event
// if there is a selection occuring
view.selector && view.selector.cancel()
if (view.aladin.isInFullscreen) {
view.aladin.toggleFullscreen(view.aladin.options.realFullscreen);
}
@@ -2172,21 +2174,26 @@ export let View = (function () {
}
let closests = [];
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);
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);
}
})
footprint.setLineWidth(originLineWidth);
/* if (closests.length > 0) {
break;
}
})
}*/
return closests;
};
@@ -2198,11 +2205,13 @@ 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

@@ -279,7 +279,7 @@ import { ActionButton } from "../Widgets/ActionButton.js";
header: Layout.horizontal([selectorBtn, 'Cone search']),
subInputs: [
{
label: "RA:",
label: "ra:",
name: "ra",
type: "text",
value: defaultRa,
@@ -291,7 +291,7 @@ import { ActionButton } from "../Widgets/ActionButton.js";
}
},
{
label: "Dec:",
label: "dec:",
name: "dec",
type: "text",
value: defaultDec,

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,

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

@@ -22,7 +22,7 @@ import shareIconUrl from '../../../../assets/icons/share.svg';
import cameraIconUrl from '../../../../assets/icons/camera.svg';
import linkIconUrl from '../../../../assets/icons/link.svg';
import jupyterIconUrl from '../../../../assets/icons/jupyter.svg';
import { Utils } from "../../Utils";
/******************************************************************************
* Aladin Lite project
*
@@ -62,16 +62,15 @@ import { Utils } from "../../Utils";
},
action(o) {
var url = aladin.getShareURL();
Utils.copy2Clipboard(url)
.then(() => {
if (aladin.statusBar) {
aladin.statusBar.appendMessage({
message: 'View URL saved into your clipboard!',
duration: 2000,
type: 'info'
})
}
navigator.clipboard.writeText(url);
if (aladin.statusBar) {
aladin.statusBar.appendMessage({
message: 'View URL saved into your clipboard!',
duration: 2000,
type: 'info'
})
}
}
},
{

View File

@@ -48,7 +48,7 @@ export let Circle = (function() {
this.color = options['color'] || undefined;
this.fillColor = options['fillColor'] || undefined;
this.lineWidth = options["lineWidth"] || undefined;
this.lineWidth = options["lineWidth"] || 2;
this.selectionColor = options["selectionColor"] || '#00ff00';
this.hoverColor = options["hoverColor"] || undefined;
this.opacity = options['opacity'] || 1;
@@ -297,10 +297,6 @@ 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"] || undefined;
this.lineWidth = options["lineWidth"] || 2;
this.selectionColor = options["selectionColor"] || '#00ff00';
this.hoverColor = options["hoverColor"] || undefined;
this.opacity = options['opacity'] || 1;
@@ -283,10 +283,6 @@ 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();