mirror of
https://github.com/cds-astro/aladin-lite.git
synced 2026-01-25 19:04:56 -08:00
async fits parsing ok
This commit is contained in:
@@ -34,6 +34,7 @@ fitsrs = "0.1.1"
|
||||
enum_dispatch = "0.3.8"
|
||||
wasm-bindgen = "0.2.79"
|
||||
wasm-streams = "0.3.0"
|
||||
async-channel = "1.8.0"
|
||||
al-core = { path = "./al-core" }
|
||||
al-task-exec = { path = "./al-task-exec" }
|
||||
al-api = { path = "./al-api" }
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[wasm_bindgen]
|
||||
pub struct FoV {
|
||||
/// Position of the field of view
|
||||
|
||||
@@ -25,6 +25,7 @@ struct Texture2DMeta {
|
||||
}
|
||||
|
||||
use web_sys::WebGlTexture;
|
||||
#[derive(Clone)]
|
||||
pub struct Texture2D {
|
||||
pub texture: Option<WebGlTexture>,
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ use al_api::{
|
||||
grid::GridCfg,
|
||||
hips::{ImageMetadata, HiPSCfg, FITSCfg}, fov::FoV,
|
||||
};
|
||||
use wasm_bindgen_futures::JsFuture;
|
||||
use crate::Abort;
|
||||
use super::coosys;
|
||||
use cgmath::Vector4;
|
||||
@@ -87,10 +88,17 @@ pub struct App {
|
||||
colormaps: Colormaps,
|
||||
|
||||
projection: ProjectionType,
|
||||
|
||||
// Async data receivers
|
||||
fits_send: async_channel::Sender<FitsCfg>,
|
||||
fits_recv: async_channel::Receiver<FitsCfg>,
|
||||
|
||||
ack_send: async_channel::Sender<()>,
|
||||
ack_recv: async_channel::Receiver<()>,
|
||||
}
|
||||
|
||||
use cgmath::{Vector2, Vector3};
|
||||
use futures::stream::StreamExt; // for `next`
|
||||
use futures::{stream::StreamExt, io::BufReader}; // for `next`
|
||||
|
||||
/// State for inertia
|
||||
struct InertiaAnimation {
|
||||
@@ -189,6 +197,9 @@ impl App {
|
||||
|
||||
gl.clear_color(0.15, 0.15, 0.15, 1.0);
|
||||
|
||||
let (fits_send, fits_recv) = async_channel::unbounded::<FitsCfg>();
|
||||
let (ack_send, ack_recv) = async_channel::unbounded::<()>();
|
||||
|
||||
Ok(App {
|
||||
gl,
|
||||
start_time_frame,
|
||||
@@ -229,6 +240,11 @@ impl App {
|
||||
|
||||
colormaps,
|
||||
projection,
|
||||
|
||||
fits_send,
|
||||
fits_recv,
|
||||
ack_send,
|
||||
ack_recv
|
||||
})
|
||||
}
|
||||
|
||||
@@ -692,6 +708,20 @@ impl App {
|
||||
}
|
||||
}*/
|
||||
|
||||
// Check for async retrieval
|
||||
if let Ok(fits) = self.fits_recv.try_recv() {
|
||||
al_core::log("received");
|
||||
self.layers.add_image_fits(fits, &mut self.camera, &self.projection)?;
|
||||
self.request_redraw = true;
|
||||
|
||||
// Send the ack to the js promise so that she finished
|
||||
let ack_send = self.ack_send.clone();
|
||||
wasm_bindgen_futures::spawn_local(async move {
|
||||
ack_send.send(()).await
|
||||
.unwrap_throw();
|
||||
})
|
||||
}
|
||||
|
||||
self.draw(false)?;
|
||||
|
||||
Ok(())
|
||||
@@ -853,29 +883,74 @@ impl App {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn add_image_fits(&mut self, cfg: FITSCfg, bytes: &[u8]) -> Result<FoV, JsValue> {
|
||||
pub(crate) fn add_image_fits(&mut self, cfg: FITSCfg) -> Result<js_sys::Promise, JsValue> {
|
||||
let FITSCfg { layer, url, meta } = cfg;
|
||||
al_core::log(&format!("url: {:?}", url));
|
||||
let gl = self.gl.clone();
|
||||
|
||||
let fits_sender = self.fits_send.clone();
|
||||
let ack_recv = self.ack_recv.clone();
|
||||
let fut = async move {
|
||||
use wasm_streams::ReadableStream;
|
||||
use js_sys::Uint8Array;
|
||||
use web_sys::Response;
|
||||
use web_sys::window;
|
||||
use wasm_bindgen_futures::JsFuture;
|
||||
use futures::StreamExt;
|
||||
use wasm_bindgen::JsCast;
|
||||
use crate::renderable::image::FitsImage;
|
||||
use futures::TryStreamExt;
|
||||
|
||||
let window = window().unwrap();
|
||||
let resp_value = JsFuture::from(window.fetch_with_str(&url))
|
||||
.await?;
|
||||
let resp: Response = resp_value.dyn_into()?;
|
||||
|
||||
let fits = FitsImage::new(&self.gl, bytes)?;
|
||||
let center = fits.get_center();
|
||||
let fov = FoV {
|
||||
ra: center.lon().to_degrees(),
|
||||
dec: center.lat().to_degrees(),
|
||||
fov: 1.0
|
||||
// Get the response's body as a JS ReadableStream
|
||||
let raw_body = resp.body().unwrap();
|
||||
let body = ReadableStream::from_raw(raw_body.dyn_into()?);
|
||||
|
||||
al_core::log("begin to parse fits!");
|
||||
// Convert the JS ReadableStream to a Rust stream
|
||||
let bytes_reader = body
|
||||
.into_stream()
|
||||
.map_ok(|js_value| js_value.dyn_into::<Uint8Array>().unwrap_throw().to_vec())
|
||||
.map_err(|_js_error| std::io::Error::new(std::io::ErrorKind::Other, "failed to read"))
|
||||
.into_async_read();
|
||||
|
||||
let fits = FitsImage::new_async(&gl, BufReader::new(bytes_reader)).await?;
|
||||
al_core::log("fits parsed");
|
||||
|
||||
let center = fits.get_center();
|
||||
let ra = center.lon().to_degrees();
|
||||
let dec = center.lat().to_degrees();
|
||||
let fov = 1.0;
|
||||
|
||||
let fits_cfg = FitsCfg {
|
||||
fits: fits,
|
||||
layer: layer,
|
||||
url: url,
|
||||
meta: meta
|
||||
};
|
||||
|
||||
fits_sender.send(fits_cfg).await
|
||||
.unwrap();
|
||||
|
||||
// Wait for the ack
|
||||
if let Ok(_) = ack_recv.recv().await {
|
||||
let fov = FoV {
|
||||
ra: ra,
|
||||
dec: dec,
|
||||
fov: fov,
|
||||
};
|
||||
Ok(serde_wasm_bindgen::to_value(&fov).unwrap())
|
||||
} else {
|
||||
Err(JsValue::from_str("Problem receving fits"))
|
||||
}
|
||||
};
|
||||
|
||||
let cfg = FitsCfg {
|
||||
layer,
|
||||
url,
|
||||
fits,
|
||||
meta,
|
||||
};
|
||||
self.layers.add_image_fits(cfg, &mut self.camera, &self.projection)?;
|
||||
|
||||
// Once its added, request the tiles in the view (unless the viewer is at depth 0)
|
||||
self.request_redraw = true;
|
||||
|
||||
Ok(fov)
|
||||
|
||||
let promise = wasm_bindgen_futures::future_to_promise(fut);
|
||||
Ok(promise)
|
||||
}
|
||||
|
||||
pub(crate) fn get_layer_cfg(&self, layer: &str) -> Result<ImageMetadata, JsValue> {
|
||||
|
||||
@@ -66,6 +66,7 @@ mod utils;
|
||||
|
||||
use math::projection::*;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen_futures::JsFuture;
|
||||
|
||||
mod app;
|
||||
pub mod async_task;
|
||||
@@ -98,6 +99,7 @@ use al_api::hips::HiPSProperties;
|
||||
use al_api::coo_system::CooSystem;
|
||||
use al_api::color::{Color, ColorRGBA};
|
||||
use al_api::fov::FoV;
|
||||
use al_api::hips::FITSCfg;
|
||||
|
||||
use al_core::Colormap;
|
||||
use al_core::{WebGlContext};
|
||||
@@ -266,7 +268,7 @@ impl WebClient {
|
||||
/// # Examples
|
||||
///
|
||||
/// ```javascript
|
||||
/// let al = new Aladin.wasmLibs.webgl.WebClient(...);
|
||||
/// let al = new Aladin.wasmLibs.core.WebClient(...);
|
||||
/// const panstarrs = {
|
||||
/// properties: {
|
||||
/// url: "http://alasky.u-strasbg.fr/Pan-STARRS/DR1/r",
|
||||
@@ -309,10 +311,10 @@ impl WebClient {
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = addImageFITS)]
|
||||
pub fn add_image_fits(&mut self, fits_cfg: JsValue, bytes: &[u8]) -> Result<FoV, JsValue> {
|
||||
let fits_cfg = serde_wasm_bindgen::from_value(fits_cfg)?;
|
||||
pub fn add_image_fits(&mut self, fits_cfg: JsValue) -> Result<js_sys::Promise, JsValue> {
|
||||
let fits_cfg: FITSCfg = serde_wasm_bindgen::from_value(fits_cfg)?;
|
||||
|
||||
self.app.add_image_fits(fits_cfg, bytes)
|
||||
self.app.add_image_fits(fits_cfg)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = removeLayer)]
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use std::vec;
|
||||
|
||||
use al_api::hips::ImageMetadata;
|
||||
use futures::StreamExt;
|
||||
use moclib::moc::range::RangeMOC;
|
||||
use moclib::qty::Hpx;
|
||||
use moclib::elem::cell::Cell;
|
||||
@@ -13,7 +14,7 @@ use web_sys::WebGl2RenderingContext;
|
||||
use al_api::cell::HEALPixCellProjeted;
|
||||
use al_api::coo_system::CooSystem;
|
||||
|
||||
use al_core::{VertexArrayObject, Texture2D};
|
||||
use al_core::{VertexArrayObject, Texture2D, pixel};
|
||||
use al_core::WebGlContext;
|
||||
use al_core::VecData;
|
||||
use al_core::webgl_ctx::GlWrapper;
|
||||
@@ -26,16 +27,18 @@ use crate::ShaderManager;
|
||||
use crate::Colormaps;
|
||||
|
||||
use fitsrs::{
|
||||
fits::Fits,
|
||||
fits::{AsyncFits, Fits},
|
||||
hdu::{
|
||||
data_async::DataOwned,
|
||||
HDU,
|
||||
AsyncHDU,
|
||||
data::DataBorrowed
|
||||
}
|
||||
};
|
||||
use wcs::ImgXY;
|
||||
use wcs::WCS;
|
||||
|
||||
use wasm_bindgen::JsValue;
|
||||
use wasm_bindgen::{JsValue, UnwrapThrowExt};
|
||||
|
||||
pub struct FitsImage {
|
||||
// The vertex array object of the screen in NDC
|
||||
@@ -58,13 +61,221 @@ pub struct FitsImage {
|
||||
center: LonLat,
|
||||
}
|
||||
|
||||
use crate::time::Time;
|
||||
use futures::io::BufReader;
|
||||
|
||||
impl FitsImage {
|
||||
pub fn new<'a>(
|
||||
pub fn from_bytes(
|
||||
gl: &WebGlContext,
|
||||
raw_bytes: &'a [u8],
|
||||
bytes: &[u8]
|
||||
) -> Result<Self, JsValue> {
|
||||
// Load the fits file
|
||||
let Fits { hdu: HDU { header, data } } = Fits::from_reader(raw_bytes)
|
||||
al_core::log("jdjdjdj start");
|
||||
|
||||
let Fits { hdu: HDU { header, data } } = Fits::from_reader(bytes)
|
||||
.map_err(|_| JsValue::from_str("Fits cannot be parsed"))?;
|
||||
|
||||
al_core::log("jdjdjdj");
|
||||
let scale = header
|
||||
.get_parsed::<f64>(b"BSCALE ")
|
||||
.unwrap_or(Ok(1.0))
|
||||
.unwrap() as f32;
|
||||
let offset = header
|
||||
.get_parsed::<f64>(b"BZERO ")
|
||||
.unwrap_or(Ok(0.0))
|
||||
.unwrap() as f32;
|
||||
let blank = header
|
||||
.get_parsed::<f64>(b"BLANK ")
|
||||
.unwrap_or(Ok(std::f64::NAN))
|
||||
.unwrap() as f32;
|
||||
al_core::log("jdjdjdj2");
|
||||
|
||||
// Create a WCS from a specific header unit
|
||||
let wcs = WCS::new(&header).map_err(|_| JsValue::from_str("Failed to parse the WCS"))?;
|
||||
|
||||
let (w, h) = wcs.img_dimensions();
|
||||
let width = w as f64;
|
||||
let height = h as f64;
|
||||
let tex_params = &[
|
||||
(
|
||||
WebGl2RenderingContext::TEXTURE_MIN_FILTER,
|
||||
WebGl2RenderingContext::NEAREST,
|
||||
),
|
||||
(
|
||||
WebGl2RenderingContext::TEXTURE_MAG_FILTER,
|
||||
WebGl2RenderingContext::NEAREST,
|
||||
),
|
||||
// Prevents s-coordinate wrapping (repeating)
|
||||
(
|
||||
WebGl2RenderingContext::TEXTURE_WRAP_S,
|
||||
WebGl2RenderingContext::CLAMP_TO_EDGE,
|
||||
),
|
||||
// Prevents t-coordinate wrapping (repeating)
|
||||
(
|
||||
WebGl2RenderingContext::TEXTURE_WRAP_T,
|
||||
WebGl2RenderingContext::CLAMP_TO_EDGE,
|
||||
),
|
||||
];
|
||||
al_core::log("jdjdjdj3");
|
||||
|
||||
let texture = match data {
|
||||
DataBorrowed::U8(data) => {
|
||||
Texture2D::create_from_raw_pixels::<al_core::image::format::R8UI>(gl, w as i32, h as i32, tex_params, Some(&data))?
|
||||
},
|
||||
DataBorrowed::I16(data) => {
|
||||
Texture2D::create_from_raw_pixels::<al_core::image::format::R16I>(gl, w as i32, h as i32, tex_params, Some(&data))?
|
||||
},
|
||||
DataBorrowed::I32(data) => {
|
||||
al_core::log("jdjdjd4");
|
||||
al_core::log("jdjdjdj5");
|
||||
|
||||
Texture2D::create_from_raw_pixels::<al_core::image::format::R32I>(gl, w as i32, h as i32, tex_params, Some(&data))?
|
||||
},
|
||||
DataBorrowed::I64(data) => {
|
||||
let values: Vec<f32> = data.iter().map(|v| {
|
||||
*v as f32
|
||||
})
|
||||
.collect();
|
||||
|
||||
Texture2D::create_from_raw_pixels::<al_core::image::format::R32F>(gl, w as i32, h as i32, tex_params, Some(&values))?
|
||||
},
|
||||
DataBorrowed::F32(data) => {
|
||||
Texture2D::create_from_raw_pixels::<al_core::image::format::R32F>(gl, w as i32, h as i32, tex_params, Some(data))?
|
||||
},
|
||||
DataBorrowed::F64(data) => {
|
||||
let values: Vec<f32> = data.iter().map(|v| {
|
||||
*v as f32
|
||||
})
|
||||
.collect();
|
||||
|
||||
Texture2D::create_from_raw_pixels::<al_core::image::format::R32F>(gl, w as i32, h as i32, tex_params, Some(&values))?
|
||||
},
|
||||
};
|
||||
|
||||
let bl = wcs.unproj_lonlat(&ImgXY::new(0.0, 0.0)).ok_or(JsValue::from_str("(0, 0) px cannot be unprojected"))?;
|
||||
let br = wcs.unproj_lonlat(&ImgXY::new(width - 1.0, 0.0)).ok_or(JsValue::from_str("(w - 1, 0) px cannot be unprojected"))?;
|
||||
let tr = wcs.unproj_lonlat(&ImgXY::new(width - 1.0, height - 1.0)).ok_or(JsValue::from_str("(w - 1, h - 1) px cannot be unprojected"))?;
|
||||
let tl = wcs.unproj_lonlat(&ImgXY::new(0.0, height - 1.0)).ok_or(JsValue::from_str("(0, h - 1) px cannot be unprojected"))?;
|
||||
|
||||
let center = wcs.unproj_lonlat(&ImgXY::new(width / 2.0, height / 2.0)).ok_or(JsValue::from_str("(w / 2, h / 2) px cannot be unprojected"))?;
|
||||
|
||||
let mut num_moc_cells = std::usize::MAX;
|
||||
let mut depth = 11;
|
||||
let mut moc = RangeMOC::new_empty(0);
|
||||
while num_moc_cells > 5 && depth > 3 {
|
||||
depth = depth - 1;
|
||||
moc = RangeMOC::from_polygon_with_control_point(
|
||||
&[
|
||||
(bl.lon(), bl.lat()),
|
||||
(br.lon(), br.lat()),
|
||||
(tr.lon(), tr.lat()),
|
||||
(tl.lon(), tl.lat()),
|
||||
],
|
||||
(center.lon(), center.lat()),
|
||||
depth
|
||||
);
|
||||
|
||||
num_moc_cells = (&moc).into_range_moc_iter().cells().count();
|
||||
}
|
||||
|
||||
let pos = vec![];
|
||||
let uv = vec![];
|
||||
let indices = vec![];
|
||||
// Define the buffers
|
||||
let vao = {
|
||||
let mut vao = VertexArrayObject::new(gl);
|
||||
|
||||
#[cfg(feature = "webgl2")]
|
||||
vao.bind_for_update()
|
||||
// layout (location = 0) in vec2 ndc_pos;
|
||||
.add_array_buffer_single(
|
||||
2,
|
||||
"ndc_pos",
|
||||
WebGl2RenderingContext::DYNAMIC_DRAW,
|
||||
VecData::<f32>(&pos),
|
||||
)
|
||||
.add_array_buffer_single(
|
||||
2,
|
||||
"uv",
|
||||
WebGl2RenderingContext::DYNAMIC_DRAW,
|
||||
VecData::<f32>(&uv),
|
||||
)
|
||||
// Set the element buffer
|
||||
.add_element_buffer(
|
||||
WebGl2RenderingContext::DYNAMIC_DRAW,
|
||||
VecData::<u32>(&indices),
|
||||
)
|
||||
.unbind();
|
||||
#[cfg(feature = "webgl1")]
|
||||
vao.bind_for_update()
|
||||
.add_array_buffer_single(
|
||||
2,
|
||||
"ndc_pos",
|
||||
WebGl2RenderingContext::DYNAMIC_DRAW,
|
||||
VecData::<f32>(&pos),
|
||||
)
|
||||
.add_array_buffer_single(
|
||||
2,
|
||||
"uv",
|
||||
WebGl2RenderingContext::DYNAMIC_DRAW,
|
||||
VecData::<f32>(&uv),
|
||||
)
|
||||
// Set the element buffer
|
||||
.add_element_buffer(
|
||||
WebGl2RenderingContext::DYNAMIC_DRAW,
|
||||
VecData::<u32>(&indices),
|
||||
)
|
||||
.unbind();
|
||||
|
||||
vao
|
||||
};
|
||||
|
||||
// Automatic methods to compute the min and max cut values
|
||||
/*let mut values = values.into_iter()
|
||||
.filter(|x| !x.is_nan() && *x != blank)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let n = values.len();
|
||||
let first_pct_idx = (0.05 * (n as f32)) as usize;
|
||||
let last_pct_idx = (0.95 * (n as f32)) as usize;
|
||||
|
||||
let min_val = crate::utils::select_kth_smallest(&mut values[..], 0, n - 1, first_pct_idx);
|
||||
let max_val = crate::utils::select_kth_smallest(&mut values[..], 0, n - 1, last_pct_idx);
|
||||
*/
|
||||
//al_core::log(&format!("values: {} {}", min_val, max_val));
|
||||
|
||||
let gl = gl.clone();
|
||||
let image = FitsImage {
|
||||
vao,
|
||||
wcs,
|
||||
moc,
|
||||
gl,
|
||||
|
||||
pos,
|
||||
uv,
|
||||
indices,
|
||||
|
||||
texture,
|
||||
scale,
|
||||
offset,
|
||||
blank,
|
||||
|
||||
center,
|
||||
};
|
||||
|
||||
Ok(image)
|
||||
}
|
||||
|
||||
pub async fn new_async<'a, R>(
|
||||
gl: &WebGlContext,
|
||||
reader: BufReader<R>,
|
||||
) -> Result<Self, JsValue>
|
||||
where
|
||||
R: futures::AsyncRead + std::marker::Unpin + std::fmt::Debug
|
||||
{
|
||||
// Load the fits file
|
||||
let AsyncFits { hdu: AsyncHDU { header, data } } = AsyncFits::from_reader(reader)
|
||||
.await
|
||||
.map_err(|_| JsValue::from_str("Fits cannot be parsed"))?;
|
||||
|
||||
let scale = header
|
||||
@@ -108,36 +319,70 @@ impl FitsImage {
|
||||
];
|
||||
|
||||
let texture = match data {
|
||||
DataBorrowed::U8(data) => {
|
||||
Texture2D::create_from_raw_pixels::<al_core::image::format::R8UI>(gl, w as i32, h as i32, tex_params, Some(data))?
|
||||
DataOwned::U8(data) => {
|
||||
let data = data.collect::<Vec<u8>>().await;
|
||||
Texture2D::create_from_raw_pixels::<al_core::image::format::R8UI>(gl, w as i32, h as i32, tex_params, Some(&data))?
|
||||
},
|
||||
DataBorrowed::I16(data) => {
|
||||
let values: Vec<f32> = data.into_iter().map(|v| {
|
||||
*v as f32
|
||||
DataOwned::I16(data) => {
|
||||
let values: Vec<f32> = data.map(|v| {
|
||||
v as f32
|
||||
})
|
||||
.collect();
|
||||
.collect().await;
|
||||
|
||||
Texture2D::create_from_raw_pixels::<al_core::image::format::R32F>(gl, w as i32, h as i32, tex_params, Some(&values))?
|
||||
},
|
||||
DataBorrowed::I32(data) => {
|
||||
Texture2D::create_from_raw_pixels::<al_core::image::format::R32I>(gl, w as i32, h as i32, tex_params, Some(data))?
|
||||
DataOwned::I32(mut data) => {
|
||||
let texture = Texture2D::create_from_raw_pixels::<al_core::image::format::R32F>(gl, w as i32, h as i32, tex_params, None)?;
|
||||
let tex_bound = texture.bind();
|
||||
let mut dy = 0;
|
||||
let mut pixels_processed = 0;
|
||||
let tot_pixels = w * h;
|
||||
let mut bytes_chunk = Vec::new();
|
||||
|
||||
while pixels_processed < tot_pixels {
|
||||
let chunk_num_pixels = w; // todo adapt the size of the chunk
|
||||
|
||||
bytes_chunk.clear();
|
||||
for _ in 0..chunk_num_pixels {
|
||||
let value = data.next().await.unwrap_throw() as f32;
|
||||
bytes_chunk.extend(value.to_le_bytes());
|
||||
}
|
||||
|
||||
tex_bound.tex_sub_image_2d_with_i32_and_i32_and_u32_and_type_and_opt_u8_array(
|
||||
0,
|
||||
dy,
|
||||
w as i32,
|
||||
1,
|
||||
Some(&bytes_chunk)
|
||||
);
|
||||
dy += 1;
|
||||
|
||||
pixels_processed += chunk_num_pixels;
|
||||
}
|
||||
|
||||
texture
|
||||
},
|
||||
DataBorrowed::I64(data) => {
|
||||
let values: Vec<f32> = data.into_iter().map(|v| {
|
||||
*v as f32
|
||||
DataOwned::I64(data) => {
|
||||
let values: Vec<f32> = data.map(|v| {
|
||||
v as f32
|
||||
})
|
||||
.collect();
|
||||
.collect().await;
|
||||
|
||||
Texture2D::create_from_raw_pixels::<al_core::image::format::R32F>(gl, w as i32, h as i32, tex_params, Some(&values))?
|
||||
},
|
||||
DataBorrowed::F32(data) => {
|
||||
Texture2D::create_from_raw_pixels::<al_core::image::format::R32F>(gl, w as i32, h as i32, tex_params, Some(data))?
|
||||
DataOwned::F32(data) => {
|
||||
al_core::log("f32");
|
||||
|
||||
let values: Vec<f32> = data.collect().await;
|
||||
Texture2D::create_from_raw_pixels::<al_core::image::format::R32F>(gl, w as i32, h as i32, tex_params, Some(&values))?
|
||||
},
|
||||
DataBorrowed::F64(data) => {
|
||||
let values: Vec<f32> = data.into_iter().map(|v| {
|
||||
*v as f32
|
||||
DataOwned::F64(data) => {
|
||||
al_core::log("f64");
|
||||
|
||||
let values: Vec<f32> = data.map(|v| {
|
||||
v as f32
|
||||
})
|
||||
.collect();
|
||||
.collect().await;
|
||||
|
||||
Texture2D::create_from_raw_pixels::<al_core::image::format::R32F>(gl, w as i32, h as i32, tex_params, Some(&values))?
|
||||
},
|
||||
|
||||
@@ -45,6 +45,11 @@ pub unsafe fn transmute_boxed_slice<I, O>(s: Box<[I]>) -> Box<[O]> {
|
||||
Box::from_raw(out_slice_ptr)
|
||||
}
|
||||
|
||||
pub unsafe fn transmute_vec_to_u8<I>(mut s: Vec<I>) -> Vec<u8> {
|
||||
s.set_len(std::mem::size_of_val(&s[..]));
|
||||
std::mem::transmute(s)
|
||||
}
|
||||
|
||||
/// Select the kth smallest element in a slice
|
||||
///
|
||||
/// This is a basic implementation of quickselect algorithm: https://fr.wikipedia.org/wiki/Quickselect
|
||||
|
||||
@@ -56,12 +56,13 @@ import { CooGrid } from "./gui/CooGrid.js";
|
||||
import { ALEvent } from "./events/ALEvent.js";
|
||||
import { Color } from './Color.js';
|
||||
import { ColorCfg } from './ColorCfg.js';
|
||||
import { ImageFITS } from "./ImageFITS.js";
|
||||
|
||||
import $ from 'jquery';
|
||||
|
||||
// Import aladin css inside the project
|
||||
import './../css/aladin.css';
|
||||
import { ImageFITS } from "./ImageFITS.js";
|
||||
|
||||
|
||||
export let Aladin = (function () {
|
||||
|
||||
@@ -73,7 +74,7 @@ export let Aladin = (function () {
|
||||
if ($(aladinDiv).length == 0) {
|
||||
return;
|
||||
}
|
||||
this.webglAPI = null;
|
||||
this.wasm = null;
|
||||
var self = this;
|
||||
|
||||
// if not options was set, try to retrieve them from the query string
|
||||
@@ -679,7 +680,7 @@ export let Aladin = (function () {
|
||||
|
||||
coo.parse(targetName);
|
||||
// Convert from view coo sys to icrsj2000
|
||||
const [ra, dec] = this.view.aladin.webglAPI.viewToICRSJ2000CooSys(coo.lon, coo.lat);
|
||||
const [ra, dec] = this.wasm.viewToICRSJ2000CooSys(coo.lon, coo.lat);
|
||||
this.view.pointTo(ra, dec, options);
|
||||
|
||||
(typeof successCallback === 'function') && successCallback(this.getRaDec());
|
||||
@@ -910,9 +911,9 @@ export let Aladin = (function () {
|
||||
return radec;
|
||||
|
||||
}*/
|
||||
let radec = this.webglAPI.getCenter(); // This is given in the frame of the view
|
||||
let radec = this.wasm.getCenter(); // This is given in the frame of the view
|
||||
// We must convert it to ICRSJ2000
|
||||
const radec_j2000 = this.view.aladin.webglAPI.viewToICRSJ2000CooSys(radec[0], radec[1]);
|
||||
const radec_j2000 = this.wasm.viewToICRSJ2000CooSys(radec[0], radec[1]);
|
||||
|
||||
if (radec_j2000[0]<0) {
|
||||
return [radec_j2000[0] + 360.0, radec_j2000[1]];
|
||||
@@ -1076,7 +1077,7 @@ export let Aladin = (function () {
|
||||
} else {
|
||||
color = rgb;
|
||||
}
|
||||
this.webglAPI.setBackgroundColor(color);
|
||||
this.wasm.setBackgroundColor(color);
|
||||
};
|
||||
|
||||
// @api
|
||||
@@ -1345,7 +1346,7 @@ export let Aladin = (function () {
|
||||
}
|
||||
|
||||
try {
|
||||
const [ra, dec] = this.view.aladin.webglAPI.screenToWorld(x, y);
|
||||
const [ra, dec] = this.wasm.screenToWorld(x, y);
|
||||
|
||||
if (ra < 0) {
|
||||
return [ra + 360.0, dec];
|
||||
@@ -1375,7 +1376,7 @@ export let Aladin = (function () {
|
||||
}
|
||||
|
||||
try {
|
||||
return this.view.aladin.webglAPI.worldToScreen(ra, dec);
|
||||
return this.wasm.worldToScreen(ra, dec);
|
||||
} catch (e) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -1406,7 +1407,7 @@ export let Aladin = (function () {
|
||||
y2 = (k == 1 || k == 2) ? this.view.height - 1 : 0;
|
||||
|
||||
for (var step = 0; step < nbSteps; step++) {
|
||||
let radec = this.webglAPI.screenToWorld(x1 + step / nbSteps * (x2 - x1), y1 + step / nbSteps * (y2 - y1));
|
||||
let radec = this.wasm.screenToWorld(x1 + step / nbSteps * (x2 - x1), y1 + step / nbSteps * (y2 - y1));
|
||||
points.push(radec);
|
||||
}
|
||||
}
|
||||
@@ -1456,6 +1457,8 @@ export let Aladin = (function () {
|
||||
/////// Aladin Lite API ///////
|
||||
///////////////////////////////
|
||||
let A = {};
|
||||
console.log("jkjkjkj")
|
||||
|
||||
//// New API ////
|
||||
// For developers using Aladin lite: all objects should be created through the API,
|
||||
// rather than creating directly the corresponding JS objects
|
||||
@@ -1678,7 +1681,7 @@ Aladin.prototype.displayJPG = Aladin.prototype.displayPNG = function (url, optio
|
||||
executeDefaultSuccessAction = successCallback(meta.ra, meta.dec, meta.fov);
|
||||
}
|
||||
if (executeDefaultSuccessAction === true) {
|
||||
self.webglAPI.setCenter(meta.ra, meta.dec);
|
||||
self.wasm.setCenter(meta.ra, meta.dec);
|
||||
self.setFoV(meta.fov);
|
||||
}
|
||||
|
||||
@@ -1812,7 +1815,7 @@ A.init = (async () => {
|
||||
// Check for webgl2 support
|
||||
if (isWebGL2Supported) {
|
||||
const module = await import('./../../pkg-webgl2');
|
||||
Aladin.wasmLibs.webgl = module;
|
||||
Aladin.wasmLibs.core = module;
|
||||
} else {
|
||||
// WebGL1 not supported
|
||||
// According to caniuse, https://caniuse.com/webgl2, webgl2 is supported by 89% of users
|
||||
|
||||
@@ -93,19 +93,7 @@ export let AladinUtils = (function() {
|
||||
return AladinUtils.xyToView(xy.X, xy.Y, width, height, largestDim, zoomFactor, false);
|
||||
},*/
|
||||
radecToViewXy: function(ra, dec, view) {
|
||||
//var xy;
|
||||
//if (currentFrame.system != CooFrameEnum.SYSTEMS.J2000) {
|
||||
// var lonlat = CooConversion.J2000ToGalactic([ra, dec]);
|
||||
// xy = view.aladin.webglAPI.worldToScreen(lonlat[0], lonlat[1]);
|
||||
//}
|
||||
//else {
|
||||
//var lonlat = CooConversion.J2000ToGalactic([ra, dec]);
|
||||
let xy = view.aladin.webglAPI.worldToScreen(ra, dec);
|
||||
//}
|
||||
//if (!xy) {
|
||||
// return null;
|
||||
//}
|
||||
|
||||
let xy = view.wasm.worldToScreen(ra, dec);
|
||||
return xy;
|
||||
},
|
||||
|
||||
|
||||
@@ -548,7 +548,7 @@ export let Catalog = (function() {
|
||||
return;
|
||||
}*/
|
||||
var sourceSize = catalogInstance.sourceSize;
|
||||
//console.log('COMPUTE', aladin.webglAPI.worldToScreen(s.ra, s.dec));
|
||||
//console.log('COMPUTE', aladin.wasm.worldToScreen(s.ra, s.dec));
|
||||
//console.log(sources)
|
||||
let sourcesInView = [];
|
||||
|
||||
@@ -600,7 +600,7 @@ export let Catalog = (function() {
|
||||
return false;
|
||||
}
|
||||
var sourceSize = catalogInstance.sourceSize;
|
||||
//console.log('COMPUTE', aladin.webglAPI.worldToScreen(s.ra, s.dec));
|
||||
//console.log('COMPUTE', aladin.wasm.worldToScreen(s.ra, s.dec));
|
||||
var xy = AladinUtils.radecToViewXy(s.ra, s.dec, catalogInstance.view);
|
||||
|
||||
if (xy) {
|
||||
|
||||
@@ -207,8 +207,8 @@ export let Ellipse = (function() {
|
||||
let toNorth = [this.centerRaDec[0], this.centerRaDec[1] + 1e-3];
|
||||
|
||||
// 2. Project it to the screen
|
||||
let originScreen = this.overlay.view.aladin.webglAPI.worldToScreen(origin[0], origin[1]);
|
||||
let toNorthScreen = this.overlay.view.aladin.webglAPI.worldToScreen(toNorth[0], toNorth[1]);
|
||||
let originScreen = this.overlay.view.wasm.worldToScreen(origin[0], origin[1]);
|
||||
let toNorthScreen = this.overlay.view.wasm.worldToScreen(toNorth[0], toNorth[1]);
|
||||
|
||||
// 3. normalize this vector
|
||||
let toNorthVec = [toNorthScreen[0] - originScreen[0], toNorthScreen[1] - originScreen[1]];
|
||||
|
||||
@@ -35,6 +35,8 @@ export let ImageFITS = (function () {
|
||||
|
||||
function ImageFITS(url, name, view, options, successCallback = undefined, errorCallback = undefined) {
|
||||
this.view = view;
|
||||
this.wasm = view.wasm;
|
||||
|
||||
// Name of the layer
|
||||
this.layer = null;
|
||||
this.added = false;
|
||||
@@ -59,23 +61,11 @@ export let ImageFITS = (function () {
|
||||
updateMetadata(self);
|
||||
ImageLayer.update(self);
|
||||
|
||||
// Return a promise that take the layer name as parameter
|
||||
// and when resolved, will return the ImageFITS object
|
||||
self.query = (async () => {
|
||||
const init = {
|
||||
method: "GET",
|
||||
headers: {
|
||||
Accept: 'application/fits'
|
||||
}
|
||||
};
|
||||
this.query = Promise.resolve(self);
|
||||
}
|
||||
|
||||
return fetch(this.url, init)
|
||||
.then((resp) => resp.arrayBuffer())
|
||||
.then((arrayBuffer) => {
|
||||
self.arrayBuffer = new Uint8Array(arrayBuffer);
|
||||
return self;
|
||||
});
|
||||
})();
|
||||
ImageFITS.prototype.isReady = function() {
|
||||
return this.added;
|
||||
}
|
||||
|
||||
// @api
|
||||
@@ -151,8 +141,8 @@ export let ImageFITS = (function () {
|
||||
try {
|
||||
if (self.added) {
|
||||
const metadata = self.metadata();
|
||||
self.view.aladin.webglAPI.setImageMetadata(self.layer, metadata);
|
||||
// once the meta have been well parsed, we can set the meta
|
||||
self.wasm.setImageMetadata(self.layer, metadata);
|
||||
|
||||
ALEvent.HIPS_LAYER_CHANGED.dispatchedTo(self.view.aladinDiv, { layer: self });
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -165,32 +155,28 @@ export let ImageFITS = (function () {
|
||||
this.layer = layer;
|
||||
|
||||
let self = this;
|
||||
try {
|
||||
const { ra, dec, fov } = this.view.aladin.webglAPI.addImageFITS({
|
||||
layer: self.layer,
|
||||
url: self.url.toString(),
|
||||
meta: self.metadata()
|
||||
},
|
||||
self.arrayBuffer,
|
||||
);
|
||||
self.wasm.addImageFITS({
|
||||
layer: self.layer,
|
||||
url: self.url.toString(),
|
||||
meta: self.metadata()
|
||||
}).then(({ra, dec, fov}) => {
|
||||
console.log("success")
|
||||
self.added = true;
|
||||
|
||||
this.ra = ra;
|
||||
this.dec = dec;
|
||||
this.fov = fov;
|
||||
|
||||
this.added = true;
|
||||
|
||||
// execute the callback if there are
|
||||
if (this.successCallback) {
|
||||
this.successCallback(self.ra, self.dec, self.fov, self);
|
||||
if (self.successCallback) {
|
||||
self.successCallback(ra, dec, fov, this);
|
||||
}
|
||||
} catch (e) {
|
||||
if (this.errorCallback) {
|
||||
this.errorCallback();
|
||||
}).catch((e) => {
|
||||
console.error(e)
|
||||
if (self.errorCallback) {
|
||||
self.errorCallback()
|
||||
}
|
||||
|
||||
throw e;
|
||||
}
|
||||
// This error result from a promise
|
||||
// If I throw it, it will not be catched because
|
||||
// it is run async
|
||||
self.view.removeImageLayer(layer)
|
||||
});
|
||||
};
|
||||
|
||||
// @api
|
||||
@@ -225,7 +211,7 @@ export let ImageFITS = (function () {
|
||||
|
||||
// @api
|
||||
ImageFITS.prototype.readPixel = function (x, y) {
|
||||
return this.view.aladin.webglAPI.readPixel(x, y, this.layer);
|
||||
return this.wasm.readPixel(x, y, this.layer);
|
||||
};
|
||||
|
||||
return ImageFITS;
|
||||
|
||||
@@ -137,6 +137,7 @@ export let ImageSurvey = (function () {
|
||||
function ImageSurvey(id, name, url, view, options) {
|
||||
// A reference to the view
|
||||
this.view = view;
|
||||
this.wasm = view.wasm;
|
||||
this.added = false;
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
@@ -325,13 +326,17 @@ export let ImageSurvey = (function () {
|
||||
})();
|
||||
};
|
||||
|
||||
ImageSurvey.prototype.isReady = function() {
|
||||
return this.added;
|
||||
}
|
||||
|
||||
ImageSurvey.prototype.setUrl = function (url) {
|
||||
if (this.properties.url !== url) {
|
||||
console.info("Change url of ", this.id, " from ", this.properties.url, " to ", url)
|
||||
|
||||
// If added to the backend, then we need to tell it the url has changed
|
||||
if (this.added) {
|
||||
this.view.aladin.webglAPI.setHiPSUrl(this.properties.url, url);
|
||||
this.wasm.setHiPSUrl(this.properties.url, url);
|
||||
}
|
||||
|
||||
this.properties.url = url;
|
||||
@@ -460,7 +465,7 @@ export let ImageSurvey = (function () {
|
||||
try {
|
||||
if (self.added) {
|
||||
const metadata = self.metadata();
|
||||
self.view.aladin.webglAPI.setImageMetadata(self.layer, metadata);
|
||||
self.wasm.setImageMetadata(self.layer, metadata);
|
||||
// once the meta have been well parsed, we can set the meta
|
||||
ALEvent.HIPS_LAYER_CHANGED.dispatchedTo(self.view.aladinDiv, { layer: self });
|
||||
}
|
||||
@@ -477,7 +482,7 @@ export let ImageSurvey = (function () {
|
||||
properties: this.properties,
|
||||
meta: this.metadata(),
|
||||
})*/
|
||||
this.view.aladin.webglAPI.addImageSurvey({
|
||||
this.wasm.addImageSurvey({
|
||||
layer: this.layer,
|
||||
properties: this.properties,
|
||||
meta: this.metadata(),
|
||||
@@ -518,7 +523,7 @@ export let ImageSurvey = (function () {
|
||||
|
||||
// @api
|
||||
ImageSurvey.prototype.readPixel = function (x, y) {
|
||||
return this.view.aladin.webglAPI.readPixel(x, y, this.layer);
|
||||
return this.wasm.readPixel(x, y, this.layer);
|
||||
};
|
||||
|
||||
ImageSurvey.DEFAULT_SURVEY_ID = "P/DSS2/color";
|
||||
|
||||
@@ -71,13 +71,13 @@ export let MOC = (function() {
|
||||
let self = this;
|
||||
|
||||
this.view = view;
|
||||
this.mocParams = new Aladin.wasmLibs.webgl.MOC(this.uuid, this.opacity, this.lineWidth, this.isShowing, this.color, this.adaptativeDisplay);
|
||||
this.mocParams = new Aladin.wasmLibs.core.MOC(this.uuid, this.opacity, this.lineWidth, this.isShowing, this.color, this.adaptativeDisplay);
|
||||
|
||||
if (this.dataURL) {
|
||||
this.promiseFetchData
|
||||
.then((arrayBuffer) => {
|
||||
// Add the fetched moc to the rust backend
|
||||
self.view.aladin.webglAPI.addFITSMoc(self.mocParams, new Uint8Array(arrayBuffer));
|
||||
self.view.wasm.addFITSMoc(self.mocParams, new Uint8Array(arrayBuffer));
|
||||
self.ready = true;
|
||||
|
||||
if (self.successCallback) {
|
||||
@@ -85,7 +85,7 @@ export let MOC = (function() {
|
||||
}
|
||||
|
||||
// Cache the sky fraction
|
||||
self.skyFrac = self.view.aladin.webglAPI.mocSkyFraction(this.mocParams);
|
||||
self.skyFrac = self.view.wasm.mocSkyFraction(this.mocParams);
|
||||
|
||||
// Add it to the view
|
||||
self.view.mocs.push(self);
|
||||
@@ -97,11 +97,11 @@ export let MOC = (function() {
|
||||
self.view.requestRedraw();
|
||||
})
|
||||
} else if (this.dataFromJSON) {
|
||||
self.view.aladin.webglAPI.addJSONMoc(self.mocParams, self.dataJSON);
|
||||
self.view.wasm.addJSONMoc(self.mocParams, self.dataJSON);
|
||||
self.ready = true;
|
||||
|
||||
// Cache the sky fraction
|
||||
self.skyFrac = self.view.aladin.webglAPI.mocSkyFraction(self.mocParams);
|
||||
self.skyFrac = self.view.wasm.mocSkyFraction(self.mocParams);
|
||||
|
||||
// Add it to the view
|
||||
self.view.mocs.push(self);
|
||||
@@ -117,8 +117,8 @@ export let MOC = (function() {
|
||||
MOC.prototype.reportChange = function() {
|
||||
if (this.view) {
|
||||
// update the new moc params to the backend
|
||||
this.mocParams = new Aladin.wasmLibs.webgl.MOC(this.uuid, this.opacity, this.lineWidth, this.isShowing, this.color, this.adaptativeDisplay);
|
||||
this.view.aladin.webglAPI.setMocParams(this.mocParams);
|
||||
this.mocParams = new Aladin.wasmLibs.core.MOC(this.uuid, this.opacity, this.lineWidth, this.isShowing, this.color, this.adaptativeDisplay);
|
||||
this.view.wasm.setMocParams(this.mocParams);
|
||||
this.view.requestRedraw();
|
||||
}
|
||||
};
|
||||
@@ -126,7 +126,7 @@ export let MOC = (function() {
|
||||
MOC.prototype.delete = function() {
|
||||
if (this.view) {
|
||||
// update the new moc params to the backend
|
||||
this.view.aladin.webglAPI.removeMoc(this.mocParams);
|
||||
this.view.wasm.removeMoc(this.mocParams);
|
||||
this.view.requestRedraw();
|
||||
}
|
||||
};
|
||||
@@ -156,7 +156,7 @@ export let MOC = (function() {
|
||||
}
|
||||
|
||||
// update the new moc params to the backend
|
||||
return this.view.aladin.webglAPI.mocContains(this.mocParams, ra, dec);
|
||||
return this.view.wasm.mocContains(this.mocParams, ra, dec);
|
||||
};
|
||||
|
||||
return MOC;
|
||||
|
||||
145
src/js/View.js
145
src/js/View.js
@@ -64,11 +64,12 @@ export let View = (function () {
|
||||
try {
|
||||
// Start our Rust application. You can find `WebClient` in `src/lib.rs`
|
||||
// The Rust part should also create a new WebGL2 or WebGL1 context depending on the WebGL2 brower support.
|
||||
const webglCtx = new WebGLCtx(Aladin.wasmLibs.webgl, this.aladinDiv.id);
|
||||
this.aladin.webglAPI = webglCtx.webclient;
|
||||
const webglCtx = new WebGLCtx(Aladin.wasmLibs.core, this.aladinDiv.id);
|
||||
this.aladin.wasm = webglCtx.webclient;
|
||||
this.wasm = this.aladin.wasm;
|
||||
|
||||
// Retrieve all the possible colormaps
|
||||
ColorCfg.COLORMAPS = this.aladin.webglAPI.getAvailableColormapList();
|
||||
ColorCfg.COLORMAPS = this.wasm.getAvailableColormapList();
|
||||
} catch (e) {
|
||||
// For browsers not supporting WebGL2:
|
||||
// 1. Print the original exception message in the console
|
||||
@@ -82,7 +83,7 @@ export let View = (function () {
|
||||
const files = Utils.getDroppedFilesHandler(event);
|
||||
|
||||
files.forEach((file) => {
|
||||
const reader = new FileReader();
|
||||
/*const reader = new FileReader();
|
||||
reader.readAsArrayBuffer(file);
|
||||
|
||||
reader.addEventListener("load", () => {
|
||||
@@ -100,7 +101,17 @@ export let View = (function () {
|
||||
|
||||
reader.addEventListener('error', (event) => {
|
||||
console.error(event.target.error);
|
||||
});
|
||||
});*/
|
||||
|
||||
const url = URL.createObjectURL(file);
|
||||
|
||||
try {
|
||||
const imageFITS = self.aladin.createImageFITS(url, file.name, undefined, undefined, undefined);
|
||||
self.setOverlayImageLayer(imageFITS, Utils.uuidv4())
|
||||
} catch(e) {
|
||||
console.error("Only valid fits files supported (i.e. containig a WCS)", e)
|
||||
throw e;
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
@@ -120,11 +131,8 @@ export let View = (function () {
|
||||
lon = lat = 0;
|
||||
this.projection = ProjectionEnum.SIN;
|
||||
|
||||
//this.zoomLevel = 0;
|
||||
// Prev time of the last frame
|
||||
this.prev = 0;
|
||||
//this.zoomFactor = this.computeZoomFactor(this.zoomLevel);
|
||||
this.zoomFactor = this.aladin.webglAPI.getClipZoomFactor();
|
||||
this.zoomFactor = this.wasm.getClipZoomFactor();
|
||||
|
||||
this.viewCenter = { lon: lon, lat: lat }; // position of center of view
|
||||
|
||||
@@ -292,7 +300,7 @@ export let View = (function () {
|
||||
//this.aladinDiv.style.width = this.width + "px";
|
||||
//this.aladinDiv.style.height = this.height + "px";
|
||||
|
||||
this.aladin.webglAPI.resize(this.width, this.height);
|
||||
this.wasm.resize(this.width, this.height);
|
||||
|
||||
this.catalogCtx = this.catalogCanvas.getContext("2d");
|
||||
|
||||
@@ -372,7 +380,7 @@ export let View = (function () {
|
||||
.then((img) => {
|
||||
imgType = imgType || "image/png";
|
||||
|
||||
const canvas = this.aladin.webglAPI.canvas();
|
||||
const canvas = this.wasm.canvas();
|
||||
|
||||
var c = document.createElement('canvas');
|
||||
let dpi = window.devicePixelRatio;
|
||||
@@ -411,8 +419,8 @@ export let View = (function () {
|
||||
var xymouse = view.imageCanvas.relMouseCoords(e);
|
||||
|
||||
try {
|
||||
const lonlat = view.aladin.webglAPI.screenToWorld(xymouse.x, xymouse.y);
|
||||
var radec = view.aladin.webglAPI.viewToICRSJ2000CooSys(lonlat[0], lonlat[1]);
|
||||
const lonlat = view.wasm.screenToWorld(xymouse.x, xymouse.y);
|
||||
var radec = view.wasm.viewToICRSJ2000CooSys(lonlat[0], lonlat[1]);
|
||||
view.pointTo(radec[0], radec[1], { forceAnimation: true });
|
||||
}
|
||||
catch (err) {
|
||||
@@ -467,11 +475,11 @@ export let View = (function () {
|
||||
view.pinchZoomParameters.isPinching = true;
|
||||
//var fov = view.aladin.getFov();
|
||||
//view.pinchZoomParameters.initialFov = Math.max(fov[0], fov[1]);
|
||||
var fov = view.aladin.webglAPI.getFieldOfView();
|
||||
var fov = view.wasm.getFieldOfView();
|
||||
view.pinchZoomParameters.initialFov = fov;
|
||||
view.pinchZoomParameters.initialDistance = Math.sqrt(Math.pow(e.originalEvent.targetTouches[0].clientX - e.originalEvent.targetTouches[1].clientX, 2) + Math.pow(e.originalEvent.targetTouches[0].clientY - e.originalEvent.targetTouches[1].clientY, 2));
|
||||
|
||||
view.fingersRotationParameters.initialViewAngleFromCenter = view.aladin.webglAPI.getRotationAroundCenter();
|
||||
view.fingersRotationParameters.initialViewAngleFromCenter = view.wasm.getRotationAroundCenter();
|
||||
view.fingersRotationParameters.initialFingerAngle = Math.atan2(e.originalEvent.targetTouches[1].clientY - e.originalEvent.targetTouches[0].clientY, e.originalEvent.targetTouches[1].clientX - e.originalEvent.targetTouches[0].clientX) * 180.0 / Math.PI;
|
||||
|
||||
return;
|
||||
@@ -488,7 +496,7 @@ export let View = (function () {
|
||||
view.selectStartCoo = { x: view.dragx, y: view.dragy };
|
||||
}
|
||||
|
||||
view.aladin.webglAPI.pressLeftMouseButton(view.dragx, view.dragy);
|
||||
view.wasm.pressLeftMouseButton(view.dragx, view.dragy);
|
||||
return false; // to disable text selection
|
||||
});
|
||||
|
||||
@@ -569,7 +577,7 @@ export let View = (function () {
|
||||
let radec = view.aladin.pix2world(xymouse.x, xymouse.y);
|
||||
|
||||
// Convert from view to ICRSJ2000
|
||||
radec = view.aladin.webglAPI.viewToICRSJ2000CooSys(radec[0], radec[1]);
|
||||
radec = view.wasm.viewToICRSJ2000CooSys(radec[0], radec[1]);
|
||||
|
||||
view.setMode(View.PAN);
|
||||
view.setCursor('wait');
|
||||
@@ -643,7 +651,7 @@ export let View = (function () {
|
||||
view.refreshProgressiveCats();
|
||||
|
||||
//view.requestRedraw();
|
||||
view.aladin.webglAPI.releaseLeftButtonMouse();
|
||||
view.wasm.releaseLeftButtonMouse();
|
||||
});
|
||||
var lastHoveredObject; // save last object hovered by mouse
|
||||
var lastMouseMovePos = null;
|
||||
@@ -685,14 +693,14 @@ export let View = (function () {
|
||||
|
||||
if (view.fingersRotationParameters.rotationInitiated) {
|
||||
let rotation = view.fingersRotationParameters.initialViewAngleFromCenter;
|
||||
if (!view.aladin.webglAPI.getLongitudeReversed()) {
|
||||
if (!view.wasm.getLongitudeReversed()) {
|
||||
// spatial survey case
|
||||
rotation += fingerAngleDiff;
|
||||
} else {
|
||||
// planetary survey case
|
||||
rotation -= fingerAngleDiff;
|
||||
}
|
||||
view.aladin.webglAPI.setRotationAroundCenter(rotation);
|
||||
view.wasm.setRotationAroundCenter(rotation);
|
||||
}
|
||||
|
||||
// zoom
|
||||
@@ -770,10 +778,9 @@ export let View = (function () {
|
||||
|
||||
view.realDragging = true;
|
||||
|
||||
//webglAPI.goFromTo(pos1[0], pos1[1], pos2[0], pos2[1]);
|
||||
view.aladin.webglAPI.goFromTo(s1.x, s1.y, s2.x, s2.y);
|
||||
//webglAPI.setCenter(pos2[0], pos2[1]);
|
||||
const [ra, dec] = view.aladin.webglAPI.getCenter();
|
||||
view.wasm.goFromTo(s1.x, s1.y, s2.x, s2.y);
|
||||
|
||||
const [ra, dec] = view.wasm.getCenter();
|
||||
view.viewCenter.lon = ra;
|
||||
view.viewCenter.lat = dec;
|
||||
if (view.viewCenter.lon < 0.0) {
|
||||
@@ -921,10 +928,10 @@ export let View = (function () {
|
||||
|
||||
View.prototype.updateLocation = function (mouseX, mouseY, isViewCenterPosition) {
|
||||
if (isViewCenterPosition) {
|
||||
//const [ra, dec] = this.aladin.webglAPI.ICRSJ2000ToViewCooSys(this.viewCenter.lon, this.viewCenter.lat);
|
||||
//const [ra, dec] = this.wasm.ICRSJ2000ToViewCooSys(this.viewCenter.lon, this.viewCenter.lat);
|
||||
this.location.update(this.viewCenter.lon, this.viewCenter.lat, this.cooFrame, true);
|
||||
} else {
|
||||
let radec = this.aladin.webglAPI.screenToWorld(mouseX, mouseY); // This is given in the frame of the view
|
||||
let radec = this.wasm.screenToWorld(mouseX, mouseY); // This is given in the frame of the view
|
||||
if (radec) {
|
||||
if (radec[0] < 0) {
|
||||
radec = [radec[0] + 360.0, radec[1]];
|
||||
@@ -969,21 +976,21 @@ export let View = (function () {
|
||||
|
||||
// Drawing code
|
||||
try {
|
||||
this.aladin.webglAPI.update(elapsedTime);
|
||||
this.wasm.update(elapsedTime);
|
||||
} catch (e) {
|
||||
console.warn(e)
|
||||
}
|
||||
|
||||
// check whether a catalog has been parsed and
|
||||
// is ready to be plot
|
||||
/*let catReady = this.aladin.webglAPI.isCatalogLoaded();
|
||||
/*let catReady = this.wasm.isCatalogLoaded();
|
||||
if (catReady) {
|
||||
var callbackFn = this.aladin.callbacksByEventName['catalogReady'];
|
||||
(typeof callbackFn === 'function') && callbackFn();
|
||||
}*/
|
||||
|
||||
////// 2. Draw catalogues////////
|
||||
const isViewRendering = this.aladin.webglAPI.isRendering();
|
||||
const isViewRendering = this.wasm.isRendering();
|
||||
if (isViewRendering || this.needRedraw) {
|
||||
this.drawAllOverlays();
|
||||
}
|
||||
@@ -1156,11 +1163,11 @@ export let View = (function () {
|
||||
|
||||
View.prototype.getVisiblePixList = function (norder) {
|
||||
var pixList = [];
|
||||
let centerWorldPosition = this.aladin.webglAPI.screenToWorld(this.cx, this.cy);
|
||||
const [lon, lat] = this.aladin.webglAPI.viewToICRSJ2000CooSys(centerWorldPosition[0], centerWorldPosition[1]);
|
||||
let centerWorldPosition = this.wasm.screenToWorld(this.cx, this.cy);
|
||||
const [lon, lat] = this.wasm.viewToICRSJ2000CooSys(centerWorldPosition[0], centerWorldPosition[1]);
|
||||
|
||||
var radius = this.fov * 0.5 * this.ratio;
|
||||
this.aladin.webglAPI.queryDisc(norder, lon, lat, radius).forEach(x => pixList.push(Number(x)));
|
||||
this.wasm.queryDisc(norder, lon, lat, radius).forEach(x => pixList.push(Number(x)));
|
||||
|
||||
return pixList;
|
||||
};
|
||||
@@ -1185,12 +1192,12 @@ export let View = (function () {
|
||||
}
|
||||
var cornersXYView = [];
|
||||
//corners = HealpixCache.corners_nest(ipix, nside);
|
||||
corners = this.aladin.webglAPI.hpxNestedVertices(Math.log2(nside), ipix);
|
||||
corners = this.wasm.hpxNestedVertices(Math.log2(nside), ipix);
|
||||
|
||||
for (var k=0; k<4; k++) {
|
||||
const lon = corners[k*2];
|
||||
const lat = corners[k*2 + 1];
|
||||
cornersXY[k] = this.aladin.webglAPI.worldToScreen(lon, lat);
|
||||
cornersXY[k] = this.wasm.worldToScreen(lon, lat);
|
||||
}
|
||||
|
||||
if (cornersXY[0] == null || cornersXY[1] == null || cornersXY[2] == null || cornersXY[3] == null ) {
|
||||
@@ -1257,13 +1264,13 @@ export let View = (function () {
|
||||
}
|
||||
|
||||
return cells;*/
|
||||
return this.aladin.webglAPI.getVisibleCells(norder);
|
||||
return this.wasm.getVisibleCells(norder);
|
||||
};
|
||||
|
||||
// Called for touchmove events
|
||||
// initialAccDelta must be consistent with fovDegrees here
|
||||
View.prototype.setZoom = function (fovDegrees) {
|
||||
this.aladin.webglAPI.setFieldOfView(fovDegrees);
|
||||
this.wasm.setFieldOfView(fovDegrees);
|
||||
this.updateZoomState();
|
||||
};
|
||||
|
||||
@@ -1303,11 +1310,11 @@ export let View = (function () {
|
||||
}
|
||||
|
||||
View.prototype.setRotation = function(rotation) {
|
||||
this.aladin.webglAPI.setRotationAroundCenter(rotation);
|
||||
this.wasm.setRotationAroundCenter(rotation);
|
||||
}
|
||||
|
||||
View.prototype.setGridConfig = function (gridCfg) {
|
||||
this.aladin.webglAPI.setGridConfig(gridCfg);
|
||||
this.wasm.setGridConfig(gridCfg);
|
||||
|
||||
// send events
|
||||
if (gridCfg) {
|
||||
@@ -1331,8 +1338,8 @@ export let View = (function () {
|
||||
|
||||
View.prototype.updateZoomState = function () {
|
||||
// Get the new zoom values from the backend
|
||||
this.zoomFactor = this.aladin.webglAPI.getClipZoomFactor();
|
||||
let fov = this.aladin.webglAPI.getFieldOfView();
|
||||
this.zoomFactor = this.wasm.getClipZoomFactor();
|
||||
let fov = this.wasm.getFieldOfView();
|
||||
|
||||
// Update the pinch zoom parameters consequently
|
||||
const si = 500000.0;
|
||||
@@ -1374,7 +1381,7 @@ export let View = (function () {
|
||||
* compute and set the norder corresponding to the current view resolution
|
||||
*/
|
||||
View.prototype.computeNorder = function () {
|
||||
var norder = this.aladin.webglAPI.getNOrder();
|
||||
var norder = this.wasm.getNOrder();
|
||||
|
||||
this.realNorder = norder;
|
||||
// here, we force norder to 3 (otherwise, the display is "blurry" for too long when zooming in)
|
||||
@@ -1476,7 +1483,7 @@ export let View = (function () {
|
||||
}
|
||||
|
||||
// Throw an exception if either the first or the second layers are not in the stack
|
||||
this.aladin.webglAPI.renameLayer(layer, newLayer);
|
||||
this.wasm.renameLayer(layer, newLayer);
|
||||
|
||||
let imageLayer = this.imageLayers.get(layer);
|
||||
imageLayer.layer = newLayer;
|
||||
@@ -1499,7 +1506,7 @@ export let View = (function () {
|
||||
|
||||
View.prototype.swapLayers = function(firstLayer, secondLayer) {
|
||||
// Throw an exception if either the first or the second layers are not in the stack
|
||||
this.aladin.webglAPI.swapLayers(firstLayer, secondLayer);
|
||||
this.wasm.swapLayers(firstLayer, secondLayer);
|
||||
|
||||
// Swap in overlaylayers
|
||||
const idxFirstLayer = this.overlayLayers.findIndex(overlayLayer => overlayLayer == firstLayer);
|
||||
@@ -1514,22 +1521,21 @@ export let View = (function () {
|
||||
}
|
||||
|
||||
View.prototype.removeImageLayer = function (layer) {
|
||||
if (layer === "base") {
|
||||
throw 'The base layer cannot be removed';
|
||||
// Get the survey to remove to dissociate it from the view
|
||||
let imageLayer = this.imageLayers.get(layer);
|
||||
// Update the backend
|
||||
if (imageLayer.added) {
|
||||
this.wasm.removeLayer(layer);
|
||||
}
|
||||
|
||||
// Update the backend
|
||||
this.aladin.webglAPI.removeLayer(layer);
|
||||
// Get the survey to remove to dissociate it from the view
|
||||
imageLayer.added = false;
|
||||
|
||||
const idxOverlaidLayer = this.overlayLayers.findIndex(overlaidLayer => overlaidLayer == layer);
|
||||
if (idxOverlaidLayer == -1) {
|
||||
// layer not found
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the survey to remove to dissociate it from the view
|
||||
let imageLayer = this.imageLayers.get(layer);
|
||||
imageLayer.added = false;
|
||||
}
|
||||
|
||||
// Delete it
|
||||
this.imageLayers.delete(layer);
|
||||
@@ -1539,20 +1545,31 @@ export let View = (function () {
|
||||
|
||||
if (this.overlayLayers.length === 0) {
|
||||
this.empty = true;
|
||||
}
|
||||
|
||||
// find the toppest layer
|
||||
if (this.selectedLayer === layer) {
|
||||
const toppestLayer = this.overlayLayers[this.overlayLayers.length - 1];
|
||||
this.selectedLayer = toppestLayer;
|
||||
this.selectedLayer = "base";
|
||||
} else {
|
||||
// find the toppest layer
|
||||
if (this.selectedLayer === layer) {
|
||||
const toppestLayer = this.overlayLayers[this.overlayLayers.length - 1];
|
||||
this.selectedLayer = toppestLayer;
|
||||
}
|
||||
}
|
||||
|
||||
ALEvent.HIPS_LAYER_REMOVED.dispatchedTo(this.aladinDiv, { layer: layer });
|
||||
|
||||
// check if there are no more surveys
|
||||
const noMoreLayersToWaitFor = this.promises.length === 0;
|
||||
if (noMoreLayersToWaitFor && this.empty) {
|
||||
// no promises to launch!
|
||||
const idxServiceUrl = Math.round(Math.random());
|
||||
const dssUrl = Aladin.DEFAULT_OPTIONS.surveyUrl[idxServiceUrl]
|
||||
|
||||
this.aladin.setBaseImageLayer(dssUrl);
|
||||
}
|
||||
};
|
||||
|
||||
View.prototype.setHiPSUrl = function (pastUrl, newUrl) {
|
||||
try {
|
||||
this.aladin.webglAPI.setHiPSUrl(pastUrl, newUrl);
|
||||
this.wasm.setHiPSUrl(pastUrl, newUrl);
|
||||
} catch(e) {
|
||||
console.error(e)
|
||||
}
|
||||
@@ -1666,7 +1683,7 @@ export let View = (function () {
|
||||
break;
|
||||
}
|
||||
// Change the projection here
|
||||
this.aladin.webglAPI.setProjection(projectionName);
|
||||
this.wasm.setProjection(projectionName);
|
||||
this.updateZoomState();
|
||||
|
||||
this.requestRedraw();
|
||||
@@ -1677,14 +1694,14 @@ export let View = (function () {
|
||||
|
||||
// Set the new frame to the backend
|
||||
if (this.cooFrame.system == CooFrameEnum.SYSTEMS.GAL) {
|
||||
this.aladin.webglAPI.setCooSystem(Aladin.wasmLibs.webgl.CooSystem.GAL);
|
||||
this.wasm.setCooSystem(Aladin.wasmLibs.core.CooSystem.GAL);
|
||||
}
|
||||
else if (this.cooFrame.system == CooFrameEnum.SYSTEMS.J2000) {
|
||||
this.aladin.webglAPI.setCooSystem(Aladin.wasmLibs.webgl.CooSystem.ICRSJ2000);
|
||||
this.wasm.setCooSystem(Aladin.wasmLibs.core.CooSystem.ICRSJ2000);
|
||||
}
|
||||
|
||||
// Get the new view center position (given in icrsj2000)
|
||||
let [ra, dec] = this.aladin.webglAPI.getCenter();
|
||||
let [ra, dec] = this.wasm.getCenter();
|
||||
this.viewCenter.lon = ra;
|
||||
this.viewCenter.lat = dec;
|
||||
if (this.viewCenter.lon < 0.0) {
|
||||
@@ -1755,7 +1772,7 @@ export let View = (function () {
|
||||
this.location.update(this.viewCenter.lon, this.viewCenter.lat, this.cooFrame, true);
|
||||
|
||||
// Put a javascript code here to do some animation
|
||||
this.aladin.webglAPI.setCenter(this.viewCenter.lon, this.viewCenter.lat);
|
||||
this.wasm.setCenter(this.viewCenter.lon, this.viewCenter.lat);
|
||||
|
||||
this.requestRedraw();
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ export class HiPSLayer {
|
||||
|
||||
// HiPS main options div
|
||||
let cmListStr = '';
|
||||
for (const cm of this.aladin.webglAPI.getAvailableColormapList()) {
|
||||
for (const cm of this.aladin.wasm.getAvailableColormapList()) {
|
||||
cmListStr += '<option>' + cm + '</option>';
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user