mirror of
https://github.com/cds-astro/aladin-lite.git
synced 2025-12-12 07:40:26 -08:00
fix some bugs: zoom buttons, fits image display
This commit is contained in:
@@ -8,8 +8,8 @@
|
||||
"dateModified": "2023-01-31",
|
||||
"issueTracker": "https://github.com/cds-astro/aladin-lite/issues",
|
||||
"name": "Aladin Lite",
|
||||
"version": "3.4.1-beta",
|
||||
"softwareVersion": "3.4.1-beta",
|
||||
"version": "3.4.2-beta",
|
||||
"softwareVersion": "3.4.2-beta",
|
||||
"description": "An astronomical HiPS visualizer in the browser.",
|
||||
"identifier": "10.5281/zenodo.7638833",
|
||||
"applicationCategory": "Astronomy, Visualization",
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
fov *= 0.997;
|
||||
rotation += 0.07;
|
||||
|
||||
aladin.setRotation(rotation)
|
||||
aladin.setViewCenter2NorthPoleAngle(rotation)
|
||||
aladin.setFoV(fov);
|
||||
|
||||
if (fov < 3 && fov > 0.5) {
|
||||
|
||||
@@ -11699,7 +11699,7 @@
|
||||
aladin.addOverlay(overlay);
|
||||
var polygons = [];
|
||||
verticesArr.forEach(function(vertices) {
|
||||
polygons.push(A.polygon(vertices, {color: '#808080', fillColor: '#808080', opacity: .4, lineWidth: 1, fill: true}))
|
||||
polygons.push(A.polygon(vertices, {closed: true, color: '#808080', fillColor: '#808080', opacity: .4, lineWidth: 1, fill: true}))
|
||||
});
|
||||
overlay.addFootprints(polygons);
|
||||
aladin.gotoRaDec(156.2162606, 63.8522344);
|
||||
|
||||
@@ -195,7 +195,7 @@
|
||||
|
||||
async function s10() {
|
||||
for await(const it of interval(50, 80)) {
|
||||
aladin.setRotation(0.5 * it)
|
||||
aladin.setViewCenter2NorthPoleAngle(0.5 * it)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,7 +264,7 @@
|
||||
for await(const it of interval(intervalMs, nbIt+1)) {
|
||||
fov = fovStart / Math.pow(fovEnd/fovStart, -it/nbIt)
|
||||
aladin.setFoV(fov)
|
||||
aladin.setRotation(40 - 40 * it/nbIt)
|
||||
aladin.setViewCenter2NorthPoleAngle(40 - 40 * it/nbIt)
|
||||
}
|
||||
aladin.setFoV(fovEnd)
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
//'data/fits/irac.fits',
|
||||
//'data/fits/FOCx38i0101t_c0f.fits',
|
||||
{
|
||||
name: 'horsehead',
|
||||
minCut: 5000,
|
||||
maxCut: 17000,
|
||||
colormap: 'viridis'
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
{
|
||||
survey: 'P/allWISE/color', // set initial image survey
|
||||
projection: 'AIT', // set a projection
|
||||
fov: 1.5, // initial field of view in degrees
|
||||
fov: 0.1, // initial field of view in degrees
|
||||
target: 'NGC 2175', // initial target
|
||||
cooFrame: 'galactic', // set galactic frame
|
||||
reticleColor: '#00ff00', // change reticle color
|
||||
|
||||
@@ -23,8 +23,11 @@
|
||||
showContextMenu: true,
|
||||
showCooGrid: true,
|
||||
showFrame: true,
|
||||
showZoomControl:true
|
||||
}
|
||||
);
|
||||
|
||||
aladin.removeHiPSFromFavorites('CDS/P/allWISE/color')
|
||||
});
|
||||
</script>
|
||||
<style>
|
||||
|
||||
@@ -6,10 +6,9 @@
|
||||
<body>
|
||||
|
||||
<div id="aladin-lite-div" style="width: 1024px; height: 768px"></div>
|
||||
|
||||
<script>var aladin;</script>
|
||||
<script type="module">
|
||||
import A from '../src/js/A.js';
|
||||
let aladin;
|
||||
A.init.then(() => {
|
||||
// Start up Aladin Lite
|
||||
aladin = A.aladin('#aladin-lite-div', {
|
||||
@@ -17,7 +16,6 @@
|
||||
target: '0 0',
|
||||
fullScreen: true,
|
||||
survey: ["azef", "jfjfj", "jfj", "P/allWISE/color"],
|
||||
showCooGrid: true,
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -29,17 +29,22 @@ mapproj = "0.3.0"
|
||||
fitsrs = "0.2.9"
|
||||
wcs = "0.2.8"
|
||||
colorgrad = "0.6.2"
|
||||
#lyon = "1.0.1"
|
||||
console_error_panic_hook = {version = "0.1.7", optional = true}
|
||||
|
||||
[features]
|
||||
webgl1 = [ "al-core/webgl1", "al-api/webgl1", "web-sys/WebGlRenderingContext", "web-sys/AngleInstancedArrays", "web-sys/ExtSRgb", "web-sys/OesTextureFloat",]
|
||||
webgl2 = [ "al-core/webgl2", "al-api/webgl2", "web-sys/WebGl2RenderingContext", "web-sys/WebGlVertexArrayObject", "web-sys/ExtColorBufferFloat",]
|
||||
dbg = ['dep:console_error_panic_hook']
|
||||
dbg = [ "dep:console_error_panic_hook",]
|
||||
|
||||
[dev-dependencies]
|
||||
rand = "0.8"
|
||||
|
||||
[build-dependencies]
|
||||
walkdir = "2.3.2"
|
||||
|
||||
[dependencies.console_error_panic_hook]
|
||||
version = "0.1.7"
|
||||
optional = true
|
||||
|
||||
[dependencies.healpix]
|
||||
package = "cdshealpix"
|
||||
git = "https://github.com/cds-astro/cds-healpix-rust"
|
||||
@@ -47,7 +52,6 @@ branch = "master"
|
||||
|
||||
[dependencies.moclib]
|
||||
package = "moc"
|
||||
#path = "../../../cds-moc-rust/"
|
||||
git = "https://github.com/bmatthieu3/cds-moc-rust"
|
||||
branch = "overlap"
|
||||
|
||||
@@ -71,10 +75,6 @@ version = "0.24.2"
|
||||
default-features = false
|
||||
features = [ "jpeg", "png",]
|
||||
|
||||
[build-dependencies]
|
||||
# Shader preprocessing
|
||||
walkdir = "2.3.2"
|
||||
|
||||
[profile.dev]
|
||||
debug = true
|
||||
|
||||
|
||||
@@ -1526,7 +1526,7 @@ impl App {
|
||||
|
||||
pub(crate) fn set_view_center_pos_angle(&mut self, theta: ArcDeg<f64>) {
|
||||
self.camera
|
||||
.set_view_center_pos_angle(theta.into(), &self.projection);
|
||||
.set_center_pos_angle(theta.into(), &self.projection);
|
||||
// New tiles can be needed and some tiles can be removed
|
||||
self.request_for_new_tiles = true;
|
||||
|
||||
@@ -1534,7 +1534,7 @@ impl App {
|
||||
}
|
||||
|
||||
pub(crate) fn get_north_shift_angle(&self) -> Angle<f64> {
|
||||
self.camera.get_north_shift_angle()
|
||||
self.camera.get_center_pos_angle()
|
||||
}
|
||||
|
||||
pub(crate) fn set_fov(&mut self, fov: Angle<f64>) {
|
||||
@@ -1578,7 +1578,7 @@ impl App {
|
||||
let d = math::vector::angle3(&prev_pos, &cur_pos);
|
||||
|
||||
self.prev_cam_position = self.camera.get_center().truncate();
|
||||
self.camera.rotate(&(-axis), d, &self.projection);
|
||||
self.camera.apply_rotation(&(-axis), d, &self.projection);
|
||||
|
||||
/* 2. Or just set the center to the current position */
|
||||
//self.set_center(&cur_pos.lonlat());
|
||||
|
||||
@@ -460,7 +460,7 @@ impl CameraViewPort {
|
||||
self.texture_depth
|
||||
}
|
||||
|
||||
pub fn rotate(
|
||||
pub fn apply_rotation(
|
||||
&mut self,
|
||||
axis: &cgmath::Vector3<f64>,
|
||||
angle: Angle<f64>,
|
||||
@@ -485,6 +485,14 @@ impl CameraViewPort {
|
||||
self.set_rotation(&rot, proj);
|
||||
}
|
||||
|
||||
pub fn set_center_pos_angle(&mut self, phi: Angle<f64>, proj: &ProjectionType) {
|
||||
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);
|
||||
}
|
||||
|
||||
fn set_rotation(&mut self, rot: &Rotation<f64>, proj: &ProjectionType) {
|
||||
self.w2m_rot = *rot;
|
||||
|
||||
@@ -614,13 +622,7 @@ impl CameraViewPort {
|
||||
self.coo_sys
|
||||
}
|
||||
|
||||
pub fn set_view_center_pos_angle(&mut self, phi: Angle<f64>, proj: &ProjectionType) {
|
||||
self.center_rot = phi;
|
||||
|
||||
self.update_rot_matrices(proj);
|
||||
}
|
||||
|
||||
pub fn get_north_shift_angle(&self) -> Angle<f64> {
|
||||
pub fn get_center_pos_angle(&self) -> Angle<f64> {
|
||||
(self.w2m.x.y).atan2(self.w2m.y.y).to_angle()
|
||||
}
|
||||
}
|
||||
@@ -632,8 +634,12 @@ impl CameraViewPort {
|
||||
fn update_rot_matrices(&mut self, proj: &ProjectionType) {
|
||||
self.w2m = (&(self.w2m_rot)).into();
|
||||
|
||||
// Update the center with the new rotation
|
||||
self.update_center();
|
||||
if self.reversed_longitude {
|
||||
self.w2m = self.w2m * ID_R;
|
||||
}
|
||||
self.m2w = self.w2m.transpose();
|
||||
|
||||
self.center = self.w2m.z;
|
||||
|
||||
// Rotate the fov vertices
|
||||
self.fov.set_rotation(&self.w2m);
|
||||
@@ -651,22 +657,6 @@ impl CameraViewPort {
|
||||
proj,
|
||||
);
|
||||
}
|
||||
|
||||
fn update_center(&mut self) {
|
||||
self.center = self.w2m.z;
|
||||
// The center position is on the 3rd column of the w2m matrix
|
||||
let center_axis = &self.center.truncate();
|
||||
// Re-update the model matrix to take into account the rotation
|
||||
// by theta around the center axis
|
||||
let r = Rotation::from_axis_angle(center_axis, self.center_rot) * self.w2m_rot;
|
||||
|
||||
self.w2m = (&r).into();
|
||||
if self.reversed_longitude {
|
||||
self.w2m = self.w2m * ID_R;
|
||||
}
|
||||
|
||||
self.m2w = self.w2m.transpose();
|
||||
}
|
||||
}
|
||||
|
||||
use al_core::shader::{SendUniforms, ShaderBound};
|
||||
|
||||
@@ -41,7 +41,7 @@ impl Inertia {
|
||||
/*let alpha = 1_f32 + (0_f32 - 1_f32) * (10_f32 * t + 1_f32) * (-10_f32 * t).exp();
|
||||
let alpha = alpha * alpha;
|
||||
let fov = start_fov * (1_f32 - alpha) + goal_fov * alpha;*/
|
||||
camera.rotate(&self.axis, self.speed.to_angle(), proj)
|
||||
camera.apply_rotation(&self.axis, self.speed.to_angle(), proj)
|
||||
}
|
||||
|
||||
pub fn get_start_ampl(&self) -> f64 {
|
||||
|
||||
@@ -494,7 +494,7 @@ impl WebClient {
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `theta` - The rotation angle in degrees
|
||||
#[wasm_bindgen(js_name = setViewCenterPosAngle)]
|
||||
#[wasm_bindgen(js_name = setViewCenter2NorthPoleAngle)]
|
||||
pub fn set_view_center_pos_angle(&mut self, theta: f64) -> Result<(), JsValue> {
|
||||
let theta = ArcDeg(theta);
|
||||
self.app.set_view_center_pos_angle(theta);
|
||||
@@ -503,7 +503,7 @@ impl WebClient {
|
||||
}
|
||||
|
||||
/// Get the absolute orientation angle of the view
|
||||
#[wasm_bindgen(js_name = getViewCenterFromNorthPoleAngle)]
|
||||
#[wasm_bindgen(js_name = getViewCenter2NorthPoleAngle)]
|
||||
pub fn get_north_shift_angle(&mut self) -> Result<f64, JsValue> {
|
||||
let phi = self.app.get_north_shift_angle();
|
||||
Ok(phi.to_degrees())
|
||||
|
||||
@@ -166,7 +166,7 @@ fn build_range_indices(it: impl Iterator<Item = (u64, f32)> + Clone) -> Vec<Rang
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn get_grid_vertices(
|
||||
pub fn vertices(
|
||||
xy_min: &(f64, f64),
|
||||
xy_max: &(f64, f64),
|
||||
max_tex_size: u64,
|
||||
@@ -175,7 +175,7 @@ pub fn get_grid_vertices(
|
||||
wcs: &WCS,
|
||||
image_coo_sys: CooSystem,
|
||||
projection: &ProjectionType,
|
||||
) -> (Vec<[f32; 2]>, Vec<[f32; 2]>, Vec<u16>, Vec<u32>) {
|
||||
) -> (Vec<f32>, Vec<f32>, Vec<u16>, Vec<u32>) {
|
||||
let (x_it, y_it) = get_grid_params(xy_min, xy_max, max_tex_size, num_tri_per_tex_patch);
|
||||
|
||||
let idx_x_ranges = build_range_indices(x_it.clone());
|
||||
@@ -183,8 +183,9 @@ pub fn get_grid_vertices(
|
||||
|
||||
let num_x_vertices = idx_x_ranges.last().unwrap().end() + 1;
|
||||
|
||||
let (pos, uv): (Vec<_>, Vec<_>) = y_it
|
||||
.map(move |(y, uvy)| {
|
||||
let mut uv = vec![];
|
||||
let pos = y_it
|
||||
.map(|(y, uvy)| {
|
||||
x_it.clone().map(move |(x, uvx)| {
|
||||
let ndc = if let Some(lonlat) = wcs.unproj(&ImgXY::new(x as f64, y as f64)) {
|
||||
let lon = lonlat.lon();
|
||||
@@ -208,7 +209,11 @@ pub fn get_grid_vertices(
|
||||
})
|
||||
})
|
||||
.flatten()
|
||||
.unzip();
|
||||
.map(|(p, uu)| {
|
||||
uv.extend_from_slice(&uu);
|
||||
p
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut indices = vec![];
|
||||
let mut num_indices = vec![];
|
||||
@@ -230,7 +235,7 @@ pub fn get_grid_vertices(
|
||||
|
||||
let pos = pos
|
||||
.into_iter()
|
||||
.map(|ndc| if let Some(ndc) = ndc { ndc } else { [0.0, 0.0] })
|
||||
.flat_map(|ndc| ndc.unwrap_or([0.0, 0.0]))
|
||||
.collect();
|
||||
|
||||
(pos, uv, indices, num_indices)
|
||||
|
||||
@@ -7,6 +7,7 @@ use std::marker::Unpin;
|
||||
use std::vec;
|
||||
|
||||
use al_api::coo_system::CooSystem;
|
||||
use al_core::log::console_log;
|
||||
use cgmath::Zero;
|
||||
use futures::stream::TryStreamExt;
|
||||
use futures::AsyncRead;
|
||||
@@ -407,18 +408,6 @@ impl Image {
|
||||
Ok(image)
|
||||
}
|
||||
|
||||
pub fn update(
|
||||
&mut self,
|
||||
camera: &CameraViewPort,
|
||||
projection: &ProjectionType,
|
||||
) -> Result<(), JsValue> {
|
||||
if camera.has_moved() {
|
||||
self.recompute_vertices(camera, projection)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn recompute_vertices(
|
||||
&mut self,
|
||||
camera: &CameraViewPort,
|
||||
@@ -517,7 +506,7 @@ impl Image {
|
||||
let num_vertices =
|
||||
((self.centered_fov.fov / 360.0) * (MAX_NUM_TRI_PER_SIDE_IMAGE as f64)).ceil() as u64;
|
||||
|
||||
let (pos, uv, indices, num_indices) = grid::get_grid_vertices(
|
||||
let (pos, uv, indices, num_indices) = grid::vertices(
|
||||
&(x_mesh_range.start, y_mesh_range.start),
|
||||
&(x_mesh_range.end.ceil(), y_mesh_range.end.ceil()),
|
||||
self.max_tex_size as u64,
|
||||
@@ -527,8 +516,8 @@ impl Image {
|
||||
self.image_coo_sys,
|
||||
projection,
|
||||
);
|
||||
self.pos = unsafe { crate::utils::transmute_vec(pos).map_err(|s| JsValue::from_str(s))? };
|
||||
self.uv = unsafe { crate::utils::transmute_vec(uv).map_err(|s| JsValue::from_str(s))? };
|
||||
self.pos = pos;
|
||||
self.uv = uv;
|
||||
|
||||
// Update num_indices
|
||||
self.indices = indices;
|
||||
@@ -557,11 +546,21 @@ impl Image {
|
||||
|
||||
// Draw the image
|
||||
pub fn draw(
|
||||
&self,
|
||||
&mut self,
|
||||
shaders: &mut ShaderManager,
|
||||
colormaps: &Colormaps,
|
||||
cfg: &ImageMetadata,
|
||||
camera: &CameraViewPort,
|
||||
projection: &ProjectionType,
|
||||
) -> Result<(), JsValue> {
|
||||
if camera.has_moved() {
|
||||
self.recompute_vertices(camera, projection)?;
|
||||
}
|
||||
|
||||
if self.num_indices.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
self.gl.enable(WebGl2RenderingContext::BLEND);
|
||||
|
||||
let ImageMetadata {
|
||||
@@ -602,6 +601,7 @@ impl Image {
|
||||
//self.gl.disable(WebGl2RenderingContext::CULL_FACE);
|
||||
|
||||
// 2. Draw it if its opacity is not null
|
||||
|
||||
blend_cfg.enable(&self.gl, || {
|
||||
let mut off_indices = 0;
|
||||
for (idx, &idx_tex) in self.idx_tex.iter().enumerate() {
|
||||
@@ -625,7 +625,7 @@ impl Image {
|
||||
((off_indices as usize) * std::mem::size_of::<u16>()) as i32,
|
||||
);
|
||||
|
||||
off_indices += self.num_indices[idx];
|
||||
off_indices += num_indices;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -290,10 +290,8 @@ impl Layers {
|
||||
// 2. Draw it if its opacity is not null
|
||||
survey.draw(shaders, colormaps, camera, raytracer, draw_opt, projection)?;
|
||||
} else if let Some(image) = self.images.get_mut(id) {
|
||||
image.update(camera, projection)?;
|
||||
|
||||
// 2. Draw it if its opacity is not null
|
||||
image.draw(shaders, colormaps, draw_opt)?;
|
||||
image.draw(shaders, colormaps, draw_opt, camera, projection)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -376,6 +376,8 @@ export let Aladin = (function () {
|
||||
}
|
||||
}
|
||||
|
||||
this._setupUI(options);
|
||||
|
||||
if (options.survey) {
|
||||
if (Array.isArray(options.survey)) {
|
||||
let i = 0;
|
||||
@@ -562,8 +564,6 @@ export let Aladin = (function () {
|
||||
if (options.inertia !== undefined) {
|
||||
this.wasm.setInertia(options.inertia);
|
||||
}
|
||||
|
||||
this._setupUI(options);
|
||||
};
|
||||
|
||||
Aladin.prototype._setupUI = function (options) {
|
||||
@@ -1631,7 +1631,6 @@ export let Aladin = (function () {
|
||||
* @memberof Aladin
|
||||
* @static
|
||||
* @param {string} url - The url of the fits.
|
||||
* @param {string} [name] - A human readable name for that fits.
|
||||
* @param {ImageFITSOptions} [options] - Options for rendering the image
|
||||
* @param {function} [success] - A success callback
|
||||
* @param {function} [error] - A success callback
|
||||
@@ -1639,7 +1638,6 @@ export let Aladin = (function () {
|
||||
*/
|
||||
Aladin.prototype.createImageFITS = function (
|
||||
url,
|
||||
name,
|
||||
options,
|
||||
successCallback,
|
||||
errorCallback
|
||||
@@ -1675,7 +1673,6 @@ export let Aladin = (function () {
|
||||
* @memberof Aladin
|
||||
* @static
|
||||
* @param {string} url - The url of the fits.
|
||||
* @param {string} [name] - A human readable name for that fits.
|
||||
* @param {ImageFITSOptions} [options] - Options for rendering the image
|
||||
* @param {function} [success] - A success callback
|
||||
* @param {function} [error] - A success callback
|
||||
@@ -1874,8 +1871,8 @@ export let Aladin = (function () {
|
||||
* @param {number} rotation - The center rotation in degrees. Positive angles rotates the
|
||||
* view in the counter clockwise order (or towards the east)
|
||||
*/
|
||||
Aladin.prototype.setViewCenterPosAngle = function (rotation) {
|
||||
this.view.setViewCenterPosAngle(rotation);
|
||||
Aladin.prototype.setViewCenter2NorthPoleAngle = function (rotation) {
|
||||
this.view.setViewCenter2NorthPoleAngle(rotation);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1885,8 +1882,8 @@ export let Aladin = (function () {
|
||||
*
|
||||
* @returns {number} - Angle between the position center and the north pole
|
||||
*/
|
||||
Aladin.prototype.getCenter2NorthPoleAngle = function () {
|
||||
return this.view.wasm.getViewCenterFromNorthPoleAngle();
|
||||
Aladin.prototype.getViewCenter2NorthPoleAngle = function () {
|
||||
return this.view.wasm.getViewCenter2NorthPoleAngle();
|
||||
};
|
||||
|
||||
// @api
|
||||
@@ -2372,7 +2369,7 @@ aladin.on("positionChanged", ({ra, dec}) => {
|
||||
if (isProjZenithal) {
|
||||
// zenithal projections
|
||||
// express the 3rd euler angle for zenithal projection
|
||||
let thirdEulerAngle = this.getCenter2NorthPoleAngle();
|
||||
let thirdEulerAngle = this.getViewCenter2NorthPoleAngle();
|
||||
WCS.LONPOLE = 180 - thirdEulerAngle
|
||||
} else {
|
||||
// cylindrical or pseudo-cylindrical projections
|
||||
@@ -2388,7 +2385,7 @@ aladin.on("positionChanged", ({ra, dec}) => {
|
||||
|
||||
// dlon angle must lie between -PI and PI
|
||||
// For dlon angle between -PI;-PI/2 or PI/2;PI one must invert LATPOLE
|
||||
if (dLon < -90 || dLon > 90) {
|
||||
if (this.getViewCenter2NorthPoleAngle() < -90 || this.getViewCenter2NorthPoleAngle() > 90) {
|
||||
// so that the south pole becomes upward to the ref point
|
||||
WCS.LATPOLE = -90
|
||||
}
|
||||
@@ -2405,8 +2402,6 @@ aladin.on("positionChanged", ({ra, dec}) => {
|
||||
// ref point is located in the south hemisphere
|
||||
WCS.LONPOLE = -180 - WCS.LONPOLE;
|
||||
}
|
||||
|
||||
console.log("euler rot ?:", 180 - WCS.LONPOLE)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2425,17 +2420,7 @@ aladin.on("positionChanged", ({ra, dec}) => {
|
||||
* aladin.setFoVRange(30, 60);
|
||||
*/
|
||||
Aladin.prototype.setFoVRange = function (minFoV, maxFoV) {
|
||||
if (minFoV > maxFoV) {
|
||||
var tmp = minFoV;
|
||||
minFoV = maxFoV;
|
||||
maxFoV = tmp;
|
||||
}
|
||||
|
||||
this.view.minFoV = minFoV;
|
||||
this.view.maxFoV = maxFoV;
|
||||
|
||||
// reset the field of view
|
||||
this.setFoV(this.view.fov);
|
||||
this.view.setFoVRange(minFoV, maxFoV);
|
||||
};
|
||||
|
||||
Aladin.prototype.setFOVRange = Aladin.prototype.setFoVRange;
|
||||
@@ -2789,7 +2774,6 @@ aladin.displayFITS(
|
||||
this.setFoV(fov);
|
||||
});
|
||||
const imageFits = this.createImageFITS(
|
||||
url,
|
||||
url,
|
||||
options,
|
||||
successCallback,
|
||||
|
||||
@@ -140,14 +140,12 @@ export let DefaultActionsForContextMenu = (function () {
|
||||
// Consider other cases
|
||||
const image = a.createImageFITS(
|
||||
url,
|
||||
name,
|
||||
undefined,
|
||||
{name},
|
||||
(ra, dec, fov, _) => {
|
||||
// Center the view around the new fits object
|
||||
a.gotoRaDec(ra, dec);
|
||||
a.setFoV(fov * 1.1);
|
||||
},
|
||||
undefined
|
||||
}
|
||||
);
|
||||
|
||||
a.setOverlayImageLayer(image, name)
|
||||
|
||||
@@ -30,22 +30,34 @@ import { ALEvent } from "./events/ALEvent.js";
|
||||
export let HiPSCache = (function () {
|
||||
function HiPSCache() {}
|
||||
|
||||
/*
|
||||
* key can be a CDS ID or an url. TODO could be an options.name too.
|
||||
*/
|
||||
HiPSCache.append = function (key, image) {
|
||||
HiPSCache.cache[key] = image;
|
||||
|
||||
ALEvent.HIPS_CACHE_UPDATED.dispatchedTo(document.body);
|
||||
};
|
||||
|
||||
/*
|
||||
* key can be a CDS ID or an url. TODO could be an options.name too.
|
||||
*/
|
||||
HiPSCache.delete = function (key) {
|
||||
delete HiPSCache.cache[key];
|
||||
|
||||
ALEvent.HIPS_CACHE_UPDATED.dispatchedTo(document.body);
|
||||
};
|
||||
|
||||
/*
|
||||
* key can be a CDS ID or an url. TODO could be an options.name too.
|
||||
*/
|
||||
HiPSCache.get = function (key) {
|
||||
return HiPSCache.cache[key];
|
||||
};
|
||||
|
||||
/*
|
||||
* key can be a CDS ID or an url. TODO could be an options.name too.
|
||||
*/
|
||||
HiPSCache.contains = function (key) {
|
||||
return HiPSCache.cache[key] !== undefined && HiPSCache.cache[key] !== null;
|
||||
};
|
||||
|
||||
@@ -67,6 +67,7 @@ export let ImageFITS = (function () {
|
||||
// Set it to a default value
|
||||
this.url = url;
|
||||
this.id = url;
|
||||
this.ext = options && options.ext;
|
||||
this.name = (options && options.name) || this.url;
|
||||
|
||||
this.imgFormat = "fits";
|
||||
@@ -208,7 +209,8 @@ export let ImageFITS = (function () {
|
||||
imagesParams.forEach((imageParams) => {
|
||||
// This fits has HDU extensions
|
||||
let image = new ImageFITS(imageParams.url, {
|
||||
name: self.name + "_ext_" + hduIdx.toString(),
|
||||
name: self.name,
|
||||
ext: hduIdx.toString()
|
||||
});
|
||||
|
||||
// Set the layer corresponding to the onein the backend
|
||||
|
||||
@@ -97,14 +97,12 @@ export let View = (function () {
|
||||
try {
|
||||
const image = self.aladin.createImageFITS(
|
||||
url,
|
||||
file.name,
|
||||
undefined,
|
||||
{name: file.name},
|
||||
(ra, dec, fov, _) => {
|
||||
// Center the view around the new fits object
|
||||
aladin.gotoRaDec(ra, dec);
|
||||
aladin.setFoV(fov * 1.1);
|
||||
},
|
||||
undefined
|
||||
}
|
||||
);
|
||||
self.setOverlayImageLayer(image, file.name)
|
||||
} catch(e) {
|
||||
@@ -158,7 +156,9 @@ export let View = (function () {
|
||||
this.mustClearCatalog = true;
|
||||
this.mode = View.PAN;
|
||||
|
||||
this.minFOV = this.maxFOV = null; // by default, no restriction
|
||||
// 0.1 arcsec
|
||||
this.minFoV = 1 / 36000;
|
||||
this.maxFoV = null;
|
||||
|
||||
this.healpixGrid = new HealpixGrid();
|
||||
this.then = Date.now();
|
||||
@@ -338,6 +338,20 @@ export let View = (function () {
|
||||
this.imageCanvas = createCanvas('aladin-imageCanvas');
|
||||
};
|
||||
|
||||
View.prototype.setFoVRange = function(minFoV, maxFoV) {
|
||||
if (minFoV && maxFoV && minFoV > maxFoV) {
|
||||
var tmp = minFoV;
|
||||
minFoV = maxFoV;
|
||||
maxFoV = tmp;
|
||||
}
|
||||
|
||||
this.minFoV = minFoV || (1.0 / 36000);
|
||||
this.maxFoV = maxFoV;
|
||||
|
||||
// reset the field of view
|
||||
this.setZoom(this.fov);
|
||||
}
|
||||
|
||||
// called at startup and when window is resized
|
||||
// The WebGL backend is resized
|
||||
View.prototype.fixLayoutDimensions = function () {
|
||||
@@ -547,7 +561,7 @@ export let View = (function () {
|
||||
const [lon, lat] = view.aladin.pix2world(xymouse.x, xymouse.y, 'icrs');
|
||||
view.pointTo(lon, lat);
|
||||
// reset the rotation around center view
|
||||
view.setViewCenterPosAngle(0.0);
|
||||
view.setViewCenter2NorthPoleAngle(0.0);
|
||||
}
|
||||
catch (err) {
|
||||
return;
|
||||
@@ -711,7 +725,7 @@ export let View = (function () {
|
||||
view.pinchZoomParameters.initialFov = fov;
|
||||
view.pinchZoomParameters.initialDistance = Math.sqrt(Math.pow(e.targetTouches[0].clientX - e.targetTouches[1].clientX, 2) + Math.pow(e.targetTouches[0].clientY - e.targetTouches[1].clientY, 2));
|
||||
|
||||
view.fingersRotationParameters.initialViewAngleFromCenter = view.wasm.getNorthShiftAngle();
|
||||
view.fingersRotationParameters.initialViewAngleFromCenter = view.wasm.getViewCenter2NorthPoleAngle();
|
||||
view.fingersRotationParameters.initialFingerAngle = Math.atan2(e.targetTouches[1].clientY - e.targetTouches[0].clientY, e.targetTouches[1].clientX - e.targetTouches[0].clientX) * 180.0 / Math.PI;
|
||||
|
||||
return;
|
||||
@@ -934,6 +948,7 @@ export let View = (function () {
|
||||
|
||||
if(view.selectedLayer) {
|
||||
let selectedLayer = view.imageLayers.get(view.selectedLayer);
|
||||
|
||||
// We try to match DS9 contrast adjustment behaviour with right click
|
||||
const cs = {
|
||||
x: view.catalogCanvas.clientWidth * 0.5,
|
||||
@@ -975,7 +990,7 @@ export let View = (function () {
|
||||
// planetary survey case
|
||||
rotation -= fingerAngleDiff;
|
||||
}
|
||||
view.setViewCenterPosAngle(rotation);
|
||||
view.setViewCenter2NorthPoleAngle(rotation);
|
||||
}
|
||||
|
||||
// zoom
|
||||
@@ -1202,21 +1217,6 @@ export let View = (function () {
|
||||
const factor = 4;
|
||||
let newFov = view.delta > 0 ? view.fov * factor : view.fov / factor;
|
||||
|
||||
// standard mouse wheel zooming
|
||||
newFov = Math.min(newFov, view.projection.fov);
|
||||
|
||||
// then clamp the fov between minFov and maxFov
|
||||
const minFoV = view.minFoV;
|
||||
const maxFoV = view.maxFoV;
|
||||
|
||||
if (minFoV) {
|
||||
fov = Math.max(fov, minFoV);
|
||||
}
|
||||
|
||||
if (maxFoV) {
|
||||
fov = Math.min(fov, maxFoV);
|
||||
}
|
||||
|
||||
view.zoom.apply({
|
||||
stop: newFov,
|
||||
duration: 300
|
||||
@@ -1248,8 +1248,6 @@ export let View = (function () {
|
||||
const factor = 5
|
||||
let newFov = view.delta > 0 ? view.fov * factor : view.fov / factor;
|
||||
// standard mouse wheel zooming
|
||||
|
||||
newFov = Math.max(Math.min(newFov, Zoom.MAX), Zoom.MIN)
|
||||
|
||||
view.zoom.apply({
|
||||
stop: newFov,
|
||||
@@ -1567,20 +1565,20 @@ export let View = (function () {
|
||||
|
||||
View.prototype.increaseZoom = function () {
|
||||
this.zoom.apply({
|
||||
stop: Zoom.determineNextFov(this, 6),
|
||||
stop: this.fov / 3,
|
||||
duration: 300
|
||||
});
|
||||
}
|
||||
|
||||
View.prototype.decreaseZoom = function () {
|
||||
this.zoom.apply({
|
||||
stop: Zoom.determineNextFov(this, -6),
|
||||
stop: this.fov * 3,
|
||||
duration: 300
|
||||
});
|
||||
}
|
||||
|
||||
View.prototype.setViewCenterPosAngle = function(rotation) {
|
||||
this.wasm.setViewCenterPosAngle(rotation);
|
||||
View.prototype.setViewCenter2NorthPoleAngle = function(rotation) {
|
||||
this.wasm.setViewCenter2NorthPoleAngle(rotation);
|
||||
}
|
||||
|
||||
View.prototype.setGridOptions = function (options) {
|
||||
@@ -1705,9 +1703,12 @@ export let View = (function () {
|
||||
this.empty = false;
|
||||
|
||||
if (imageLayer.children) {
|
||||
imageLayer.children.forEach((imageLayer) => {
|
||||
this._addLayer(imageLayer);
|
||||
imageLayer.children.forEach((imageExtLayer) => {
|
||||
this._addLayer(imageExtLayer);
|
||||
})
|
||||
|
||||
// remove the original fits from the cache as we add separately its extensions instead
|
||||
//HiPSCache.delete(imageLayer.id)
|
||||
} else {
|
||||
this._addLayer(imageLayer);
|
||||
}
|
||||
@@ -1776,6 +1777,10 @@ export let View = (function () {
|
||||
this.imageLayers.delete(layer);
|
||||
this.imageLayers.set(newLayer, imageLayer);
|
||||
|
||||
if (this.selectedLayer === layer) {
|
||||
this.selectedLayer = newLayer;
|
||||
}
|
||||
|
||||
// Tell the layer hierarchy has changed
|
||||
ALEvent.HIPS_LAYER_RENAMED.dispatchedTo(this.aladinDiv, { layer, newLayer });
|
||||
}
|
||||
|
||||
@@ -27,10 +27,8 @@
|
||||
* Author: Matthieu Baumann[CDS]
|
||||
*
|
||||
*****************************************************************************/
|
||||
import { Utils } from "./Utils";
|
||||
import { requestAnimFrame } from "./libs/RequestAnimationFrame.js";
|
||||
|
||||
|
||||
export let Zoom = (function() {
|
||||
// constructor
|
||||
function Zoom(view) {
|
||||
@@ -44,6 +42,21 @@ import { requestAnimFrame } from "./libs/RequestAnimationFrame.js";
|
||||
if (!finalZoom)
|
||||
return;
|
||||
|
||||
// clamp the zoom to the view params minFov and maxFov and the projection bounds
|
||||
finalZoom = Math.min(finalZoom, this.view.projection.fov);
|
||||
|
||||
// then clamp the fov between minFov and maxFov
|
||||
const minFoV = this.view.minFoV;
|
||||
const maxFoV = this.view.maxFoV;
|
||||
|
||||
if (minFoV) {
|
||||
finalZoom = Math.max(finalZoom, minFoV);
|
||||
}
|
||||
|
||||
if (maxFoV) {
|
||||
finalZoom = Math.min(finalZoom, maxFoV);
|
||||
}
|
||||
|
||||
this.finalZoom = finalZoom;
|
||||
|
||||
if (!this.isZooming) {
|
||||
|
||||
@@ -77,7 +77,7 @@ export class ServiceQueryBox extends Box {
|
||||
const url = URL.createObjectURL(blob);
|
||||
|
||||
try {
|
||||
let image = self.aladin.createImageFITS(url, name);
|
||||
let image = self.aladin.createImageFITS(url, {name});
|
||||
self.aladin.setOverlayImageLayer(image, Utils.uuidv4())
|
||||
} catch(e) {
|
||||
throw('Fail to interpret ' + url + ' as a fits file')
|
||||
|
||||
@@ -587,15 +587,13 @@ export class OverlayStackBox extends Box {
|
||||
|
||||
const image = self.aladin.createImageFITS(
|
||||
url,
|
||||
file.name,
|
||||
undefined,
|
||||
{name: file.name},
|
||||
(ra, dec, fov, _) => {
|
||||
// Center the view around the new fits object
|
||||
self.aladin.gotoRaDec(ra, dec);
|
||||
self.aladin.setFoV(fov * 1.1);
|
||||
//self.aladin.selectLayer(image.layer);
|
||||
},
|
||||
undefined
|
||||
}
|
||||
);
|
||||
|
||||
self.aladin.setOverlayImageLayer(
|
||||
@@ -723,12 +721,21 @@ export class OverlayStackBox extends Box {
|
||||
}
|
||||
|
||||
// Update the options of the selector
|
||||
const options = Object.keys(self.cachedHiPS);
|
||||
options.sort();
|
||||
const favorites = Object.keys(self.cachedHiPS);
|
||||
|
||||
// one must add the current HiPS too!
|
||||
favorites.sort();
|
||||
|
||||
for (var key in self.HiPSui) {
|
||||
let hips = self.HiPSui[key];
|
||||
hips.HiPSSelector.update({value: hips.HiPSSelector.options.value, options});
|
||||
let currentHiPS = hips.HiPSSelector.options.value
|
||||
|
||||
let favoritesCopy = [...favorites];
|
||||
if (!(currentHiPS in favoritesCopy)) {
|
||||
favoritesCopy.push(currentHiPS)
|
||||
}
|
||||
|
||||
hips.HiPSSelector.update({value: currentHiPS, options: favoritesCopy});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ export let Datalink = (function() {
|
||||
aladinInstance.setFoV(fov);
|
||||
});
|
||||
|
||||
let image = aladinInstance.createImageFITS(url, url, {}, successCallback);
|
||||
let image = aladinInstance.createImageFITS(url, {name: url}, successCallback);
|
||||
aladinInstance.setOverlayImageLayer(image, Utils.uuidv4())
|
||||
};
|
||||
|
||||
|
||||
@@ -204,7 +204,7 @@
|
||||
aladinInstance.setFoV(fov);
|
||||
});
|
||||
|
||||
let image = aladinInstance.createImageFITS(url, name, {}, successCallback);
|
||||
let image = aladinInstance.createImageFITS(url, {name}, successCallback);
|
||||
|
||||
aladinInstance.setOverlayImageLayer(image, Utils.uuidv4())
|
||||
};
|
||||
|
||||
@@ -81,8 +81,7 @@ export class SAMPConnector {
|
||||
let params = message["samp.params"];
|
||||
|
||||
const {url, name} = params;
|
||||
|
||||
const image = aladin.createImageFITS(url, name, options, (e) => window.alert(e));
|
||||
const image = aladin.createImageFITS(url, {name}, (e) => window.alert(e));
|
||||
|
||||
aladin.setOverlayImageLayer(image, name);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user