fetch moc from js and handle callbacks

This commit is contained in:
bmatthieu3
2022-09-20 14:27:40 +02:00
parent fd33e14aa4
commit d03c8dfac5
15 changed files with 111 additions and 554 deletions

View File

@@ -24,8 +24,11 @@
let aladin;
A.init.then(() => {
aladin = A.aladin('#aladin-lite-div', {target: '00 00 00 +07 00 00', fov: 130, survey: 'P/Mellinger/color'});
var moc11 = A.MOCFromURL('http://skies.esac.esa.int/HST/NICMOS/Moc.fits', {color: '#84f', lineWidth: 1, opacity: 0.5}, () => {
console.log("dfsds")
var moc11 = A.MOCFromURL('http://skies.esac.esa.int/HST/NICMOS/Moc.fits', {color: '#84f', lineWidth: 1, opacity: 0.5}, (moc) => {
// moc is ready
console.log(moc.contains(205.9019247, +2.4492764));
console.log(moc.contains(-205.9019247, +2.4492764));
});
var moc10 = A.MOCFromURL('https://alasky.unistra.fr/MocServer/query?ivorn=ivo%3A%2F%2FCDS%2FV%2F139%2Fsdss9&get=moc&order=7&fmt=fits', {color: '#aabbcc', lineWidth: 1});
var moc9 = A.MOCFromURL('https://alasky.unistra.fr/MocServer/query?ivorn=ivo%3A%2F%2FCDS%2FV%2F139%2Fsdss9&get=moc&order=4&fmt=fits', {color: '#00ff00', lineWidth: 1});

View File

@@ -1,5 +1,4 @@
use wasm_bindgen::prelude::wasm_bindgen;
use crate::color::ColorRGBA;
use super::color::{Color, ColorRGB};
@@ -9,7 +8,6 @@ pub struct MOC {
uuid: String,
opacity: f32,
line_width: f32,
adaptative_display: bool,
is_showing: bool,
color: ColorRGB,
}
@@ -17,14 +15,13 @@ pub struct MOC {
#[wasm_bindgen]
impl MOC {
#[wasm_bindgen(constructor)]
pub fn new(uuid: String, opacity: f32, line_width: f32, adaptative_display: bool, is_showing: bool, hex_color: String) -> Self {
pub fn new(uuid: String, opacity: f32, line_width: f32, is_showing: bool, hex_color: String) -> Self {
let color = Color::hexToRgb(hex_color);
let color = color.into();
Self {
uuid,
opacity,
line_width,
adaptative_display,
color,
is_showing,
}
@@ -48,6 +45,10 @@ impl MOC {
pub fn get_opacity(&self) -> f32 {
self.opacity
}
pub fn get_line_width(&self) -> f32 {
self.line_width
}
pub fn is_showing(&self) -> bool {
self.is_showing
@@ -60,7 +61,6 @@ impl Default for MOC {
uuid: String::from("moc"),
opacity: 1.0,
line_width: 1.0,
adaptative_display: true,
is_showing: true,
color: ColorRGB {r: 1.0, g: 0.0, b: 0.0},
}

View File

@@ -29,7 +29,6 @@ use al_api::{
coo_system::CooSystem,
grid::GridCfg,
hips::{ImageSurveyMeta, SimpleHiPS},
color::ColorRGB,
};
use super::coosys;
@@ -156,8 +155,6 @@ pub enum AppType {
use al_api::resources::Resources;
use crate::downloader::query;
use crate::downloader::request;
use al_core::log;
use al_core::{info, inforec};
impl<P> App<P>
where
@@ -299,7 +296,7 @@ where
}
// Do not request the cells where we know from its moc that there is no data
if let Some(moc) = (*survey.get_moc().lock().unwrap()).as_ref() {
if let Some(moc) = survey.get_moc() {
tile_cells = tile_cells.drain()
.filter(|tile_cell| {
moc.contains(&tile_cell)
@@ -457,7 +454,6 @@ pub trait AppTrait {
fn reset_north_orientation(&mut self);
// MOCs
fn add_fits_moc(&mut self, params: al_api::moc::MOC, data_url: String, callback: Option<js_sys::Function>) -> Result<(), JsValue>;
fn get_moc(&self, params: &al_api::moc::MOC) -> Option<&HEALPixCoverage>;
fn add_moc(&mut self, params: al_api::moc::MOC, moc: HEALPixCoverage) -> Result<(), JsValue>;
fn remove_moc(&mut self, params: &al_api::moc::MOC) -> Result<(), JsValue>;
@@ -517,12 +513,6 @@ where
self.moc.get(params)
}
fn add_fits_moc(&mut self, params: al_api::moc::MOC, data_url: String, callback: Option<js_sys::Function>) -> Result<(), JsValue> {
self.downloader.fetch(query::MOC::new(data_url, params, false, callback));
Ok(())
}
fn add_moc(&mut self, params: al_api::moc::MOC, moc: HEALPixCoverage) -> Result<(), JsValue> {
self.moc.insert::<P>(moc, params, &self.camera);
@@ -670,28 +660,18 @@ where
}
},
Resource::MOC(moc) => {
if let Some(hips_url) = moc.from_hips() {
if let Some(survey) = self.surveys.get_mut(&hips_url) {
let request::moc::MOC {
moc,
..
} = moc;
survey.set_moc(moc);
let url = moc.get_url();
if let Some(survey) = self.surveys.get_mut(&url) {
let request::moc::MOC {
moc,
..
} = moc;
if let Some(moc) = &*moc.lock().unwrap() {
survey.set_moc(moc.clone());
self.look_for_new_tiles();
self.request_redraw = true;
}
} else {
let request::moc::MOC {
moc,
url,
params,
..
} = moc;
if let Some(moc) = (*moc.lock().unwrap()).as_ref() {
self.moc.insert::<P>(moc.clone(), params.clone(), &self.camera);
};
}
},
@@ -897,7 +877,7 @@ where
// The allsky is not mandatory present in a HiPS service but it is better to first try to search for it
self.downloader.fetch(query::PixelMetadata::new(cfg));
// Try to fetch the MOC
self.downloader.fetch(query::MOC::new(format!("{}/Moc.fits", cfg.get_root_url()), al_api::moc::MOC::default(), true, None));
self.downloader.fetch(query::MOC::new(format!("{}/Moc.fits", cfg.get_root_url()), al_api::moc::MOC::default()));
let tile_size = cfg.get_tile_size();
//Request the allsky for the small tile size
@@ -951,7 +931,7 @@ where
// The allsky is not mandatory present in a HiPS service but it is better to first try to search for it
self.downloader.fetch(query::PixelMetadata::new(cfg));
// Try to fetch the MOC
self.downloader.fetch(query::MOC::new(format!("{}/Moc.fits", cfg.get_root_url()), al_api::moc::MOC::default(), true, None));
self.downloader.fetch(query::MOC::new(format!("{}/Moc.fits", cfg.get_root_url()), al_api::moc::MOC::default()));
//Request the allsky for the small tile size
if tile_size <= 128 {
// Request the allsky

View File

@@ -2,7 +2,7 @@ pub mod query;
pub mod request;
use crate::survey::Url;
use std::{collections::HashSet, hash::Hash};
use std::collections::HashSet;
use query::QueryId;

View File

@@ -160,18 +160,13 @@ impl Query for PixelMetadata {
pub struct MOC {
// The total url of the query
pub url: Url,
pub is_hips_moc: bool,
pub params: al_api::moc::MOC,
pub callback: Option<js_sys::Function>,
}
impl MOC {
pub fn new(url: String, params: al_api::moc::MOC, is_hips_moc: bool, callback: Option<js_sys::Function>) -> Self {
pub fn new(url: String, params: al_api::moc::MOC) -> Self {
MOC {
url,
params,
is_hips_moc,
callback,
}
}
}

View File

@@ -1,4 +1,3 @@
use crate::app::App;
use crate::downloader::query;
use super::{Request, RequestType};
@@ -6,12 +5,11 @@ use moclib::qty::Hpx;
use moclib::deser::fits::MocType;
use crate::healpix::coverage::SMOC;
use crate::downloader::QueryId;
pub struct MOCRequest {
pub id: QueryId,
pub url: Url,
pub params: al_api::moc::MOC,
is_hips_moc: bool,
request: Request<HEALPixCoverage>,
}
@@ -29,7 +27,7 @@ use moclib::deser::fits;
use moclib::moc::range::op::convert::convert_to_u64;
/// Convenient type for Space-MOCs
fn from_fits_hpx<T: Idx>(
pub fn from_fits_hpx<T: Idx>(
moc: MocType<T, Hpx<T>, Cursor<&[u8]>>
) -> SMOC {
match moc {
@@ -54,8 +52,6 @@ impl From<query::MOC> for MOCRequest {
let query::MOC {
url,
params,
is_hips_moc,
callback,
} = query;
let url_clone = url.clone();
@@ -74,18 +70,14 @@ impl From<query::MOC> for MOCRequest {
let array_buffer = JsFuture::from(resp.array_buffer()?).await?;
let bytes = js_sys::Uint8Array::new(&array_buffer).to_vec();
let coosys_permissive = is_hips_moc;
let smoc = match fits::from_fits_ivoa_custom(Cursor::new(&bytes[..]), coosys_permissive).map_err(|e| JsValue::from_str(&e.to_string()))? {
// Coosys is permissive because we load a moc
let smoc = match fits::from_fits_ivoa_custom(Cursor::new(&bytes[..]), true).map_err(|e| JsValue::from_str(&e.to_string()))? {
MocIdxType::U16(MocQtyType::<u16, _>::Hpx(moc)) => Ok(from_fits_hpx(moc)),
MocIdxType::U32(MocQtyType::<u32, _>::Hpx(moc)) => Ok(from_fits_hpx(moc)),
MocIdxType::U64(MocQtyType::<u64, _>::Hpx(moc)) => Ok(from_fits_hpx(moc)),
_ => Err(JsValue::from_str("MOC not supported. Must be a HPX MOC"))
}?;
if let Some(callback) = callback {
callback.call0(&JsValue::null())?;
}
Ok(HEALPixCoverage(smoc))
});
@@ -94,7 +86,6 @@ impl From<query::MOC> for MOCRequest {
url,
request,
params,
is_hips_moc,
}
}
}
@@ -104,21 +95,12 @@ pub struct MOC {
pub moc: Arc<Mutex<Option<HEALPixCoverage>>>,
pub params: al_api::moc::MOC,
pub url: Url,
is_hips_moc: bool,
}
impl MOC {
pub fn get_url(&self) -> &Url {
&self.url
}
pub fn from_hips(&self) -> Option<&Url> {
if self.is_hips_moc {
Some(&self.url)
} else {
None
}
}
}
impl<'a> From<&'a MOCRequest> for Option<MOC> {
@@ -126,7 +108,6 @@ impl<'a> From<&'a MOCRequest> for Option<MOC> {
let MOCRequest {
request,
url,
is_hips_moc,
params,
..
} = request;
@@ -138,7 +119,6 @@ impl<'a> From<&'a MOCRequest> for Option<MOC> {
// This is a clone on a Arc, it is supposed to be fast
moc: data.clone(),
url: url.clone(),
is_hips_moc: *is_hips_moc,
params: params.clone()
})
} else {

View File

@@ -49,6 +49,13 @@ use crate::{
camera::CameraViewPort, colormap::Colormaps, math::lonlat::LonLatT, shader::ShaderManager, time::DeltaTime,
healpix::coverage::HEALPixCoverage,
};
use crate::downloader::request::moc::from_fits_hpx;
use moclib::deser::fits::MocQtyType;
use moclib::deser::fits::MocIdxType;
use moclib::deser::fits;
use std::io::Cursor;
use al_api::grid::GridCfg;
use al_api::hips::{HiPSColor, HiPSProperties, SimpleHiPS};
use al_api::resources::Resources;
@@ -62,8 +69,6 @@ use cgmath::{Vector2};
use math::angle::ArcDeg;
use moclib::{qty::Hpx, moc::{CellMOCIterator, CellMOCIntoIterator, RangeMOCIterator}};
use al_core::{info, log, inforec};
#[wasm_bindgen]
pub struct WebClient {
// The app
@@ -78,7 +83,6 @@ use crate::shader::FileSrc;
use crate::app::AppTrait;
use crate::app::AppType;
use al_api::color::ColorRGB;
use al_api::hips::ImageSurveyMeta;
#[wasm_bindgen]
@@ -863,10 +867,7 @@ impl WebClient {
#[wasm_bindgen(js_name = addJSONMoc)]
pub fn add_json_moc(&mut self, params: &al_api::moc::MOC, data: &JsValue) -> Result<(), JsValue> {
//let str = data.as_string().ok_or(JsValue::from_str("Could not convert the MOC to String"))?;
let str: String = js_sys::JSON::stringify(data)?.into();
//let str = serde_json::ser::to_string::<JsValue>(&data)
// .map_err(|e| JsValue::from(js_sys::Error::new(&e.to_string())))?;
let moc = moclib::deser::json::from_json_aladin::<u64, Hpx<u64>>(&str)
.map_err(|e| JsValue::from(js_sys::Error::new(&e.to_string())))?
@@ -874,14 +875,22 @@ impl WebClient {
.ranges()
.into_range_moc();
self.app.add_moc(params.clone(), HEALPixCoverage(moc));
self.app.add_moc(params.clone(), HEALPixCoverage(moc))?;
Ok(())
}
#[wasm_bindgen(js_name = addFITSMoc)]
pub fn add_fits_moc(&mut self, params: &al_api::moc::MOC, data_url: String, callback: Option<js_sys::Function>) -> Result<(), JsValue> {
self.app.add_fits_moc(params.clone(), data_url, callback)?;
pub fn add_fits_moc(&mut self, params: &al_api::moc::MOC, array_buffer: &JsValue) -> Result<(), JsValue> {
let bytes = js_sys::Uint8Array::new(array_buffer).to_vec();
let moc = match fits::from_fits_ivoa_custom(Cursor::new(&bytes[..]), false).map_err(|e| JsValue::from_str(&e.to_string()))? {
MocIdxType::U16(MocQtyType::<u16, _>::Hpx(moc)) => Ok(crate::downloader::request::moc::from_fits_hpx(moc)),
MocIdxType::U32(MocQtyType::<u32, _>::Hpx(moc)) => Ok(from_fits_hpx(moc)),
MocIdxType::U64(MocQtyType::<u64, _>::Hpx(moc)) => Ok(from_fits_hpx(moc)),
_ => Err(JsValue::from_str("MOC not supported. Must be a HPX MOC"))
}?;
self.app.add_moc(params.clone(), HEALPixCoverage(moc))?;
Ok(())
}
@@ -901,15 +910,18 @@ impl WebClient {
}
#[wasm_bindgen(js_name = mocContains)]
pub fn contains(&mut self, params: &al_api::moc::MOC, lon: f64, lat: f64) -> Result<bool, JsValue> {
al_core::info!(params);
pub fn moc_contains(&mut self, params: &al_api::moc::MOC, lon: f64, lat: f64) -> Result<bool, JsValue> {
let moc = self.app.get_moc(params).ok_or(JsValue::from(js_sys::Error::new("MOC not found")))?;
Ok(moc.is_in(lon, lat))
let location = LonLatT::new(ArcDeg(lon).into(), ArcDeg(lat).into());
Ok(moc.is_in(location.lon().0, location.lat().0))
}
#[wasm_bindgen(js_name = mocSkyFraction)]
pub fn sky_fraction(&mut self, params: &al_api::moc::MOC) -> Result<f32, JsValue> {
al_core::info!(params);
Ok(0.0)
pub fn moc_sky_fraction(&mut self, params: &al_api::moc::MOC) -> Result<f32, JsValue> {
let moc = self.app.get_moc(params).ok_or(JsValue::from(js_sys::Error::new("MOC not found")))?;
Ok(moc.coverage_percentage() as f32)
}
}

View File

@@ -205,53 +205,3 @@ pub fn radec_to_basis<S: BaseFloat>(theta: Angle<S>, delta: Angle<S>) -> Matrix3
-theta.sin()
)
}
struct Basis<S> {
mat: Matrix3<S>,
}
impl<S> Basis<S>
where
S: BaseFloat
{
fn new(theta: Angle<S>, delta: Angle<S>) -> Self {
Self { mat: Matrix3::<S>::new(
// e_r
delta.cos() * theta.sin(),
delta.sin(),
delta.cos() * theta.cos(),
// e_delta
delta.sin() * theta.sin(),
-delta.cos(),
delta.sin() * theta.cos(),
// e_theta
theta.cos(),
S::zero(),
-theta.sin()
) }
}
fn e_r(theta: Angle<S>, delta: Angle<S>) -> Vector3<S> {
Vector3::<S>::new(
delta.cos() * theta.sin(),
delta.sin(),
delta.cos() * theta.cos(),
)
}
fn e_delta(theta: Angle<S>, delta: Angle<S>) -> Vector3<S> {
Vector3::<S>::new(
delta.sin() * theta.sin(),
-delta.cos(),
delta.sin() * theta.cos(),
)
}
fn e_theta(theta: Angle<S>, delta: Angle<S>) -> Vector3<S> {
Vector3::<S>::new(
theta.cos(),
S::zero(),
-theta.sin()
)
}
}

View File

@@ -508,7 +508,6 @@ use crate::math::{
angle::ArcDeg,
lonlat::{LonLat, LonLatT},
};
use al_core::{info, inforec, log};
impl GridLine {
fn meridian<P: Projection>(
lon: f64,

View File

@@ -1,15 +1,10 @@
use cdshealpix::ring::n_isolatitude_rings;
use moclib::moc::CellMOCIntoIterator;
use crate::{healpix::{
coverage::HEALPixCoverage,
cell::HEALPixCell
}, camera, Projection, shader::ShaderId, math::angle::Angle, CameraViewPort, ShaderManager};
use al_api::color::ColorRGB;
}, Projection, shader::ShaderId, math::angle::Angle, CameraViewPort, ShaderManager};
use al_core::{WebGlContext, VertexArrayObject, VecData};
use moclib::{moc::{RangeMOCIterator, RangeMOCIntoIterator}, elem::cell::Cell};
use std::{borrow::Cow, collections::HashMap};
use crate::survey::ImageSurveys;
use web_sys::WebGl2RenderingContext;
use al_api::coo_system::CooSystem;
@@ -36,7 +31,6 @@ pub struct MOC {
use crate::survey::view::HEALPixCellsInView;
use cgmath::Vector2;
use al_core::{log, info, inforec};
fn path_along_edge<P: Projection>(cell: &HEALPixCell, n_segment_by_side: usize, camera: &CameraViewPort, idx_off: &mut u32) -> Option<(Vec<f32>, Vec<u32>)> {
let vertices = cell
@@ -351,7 +345,6 @@ impl MOC {
let depth_sub_cell = 3;
let delta_depth_sub_cell = depth_max - depth_sub_cell;
let n_segment_by_side_sub_cell = (1 << delta_depth_sub_cell) as usize;
let num_vertices = (4 * n_segment_by_side_sub_cell) as u32;
for sub_cell in cell.get_children_cells(3 - depth) {
if let Some((vertices_sub_cell, indices_sub_cell)) = path_along_edge::<P>(
@@ -402,7 +395,6 @@ impl MOC {
let depth_sub_cell = 3;
let delta_depth_sub_cell = depth_max - depth_sub_cell;
let n_segment_by_side_sub_cell = (1 << delta_depth_sub_cell) as usize;
let num_vertices = (4 * n_segment_by_side_sub_cell) as u32;
for sub_cell in cell.get_children_cells(3 - depth) {
if let Some((vertices_sub_cell, indices_sub_cell)) = rasterize_hpx_cell::<P>(

View File

@@ -51,7 +51,7 @@ fn is_too_large<P: Projection>(cell: &HEALPixCell, camera: &CameraViewPort) -> b
}
}
fn num_subdivision<P: Projection>(cell: &HEALPixCell, delta_depth: u8, camera: &CameraViewPort) -> u8 {
fn num_subdivision<P: Projection>(cell: &HEALPixCell, camera: &CameraViewPort) -> u8 {
let d = cell.depth();
let mut num_sub = 0;
if d < 3 {
@@ -367,9 +367,8 @@ fn add_vertices_grid<P: Projection>(
camera: &CameraViewPort,
v2w: &Matrix4<f64>,
delta_depth: u8,
) {
let num_subdivision = num_subdivision::<P>(cell, delta_depth, camera);
let num_subdivision = num_subdivision::<P>(cell, camera);
let n_segments_by_side: usize = 1 << (num_subdivision as usize);
let n_vertices_per_segment = n_segments_by_side + 1;
@@ -506,7 +505,7 @@ pub struct ImageSurvey {
depth: u8,
depth_tile: u8,
footprint_moc: Arc<Mutex<Option<HEALPixCoverage>>>,
footprint_moc: Option<HEALPixCoverage>,
}
use crate::{
camera::UserAction,
@@ -515,14 +514,9 @@ use crate::{
};
use web_sys::{WebGl2RenderingContext};
use std::sync::{Arc, Mutex};
use al_core::image::ImageType;
use crate::math::lonlat::LonLat;
use crate::downloader::request::allsky::Allsky;
use al_core::{log, info};
use al_core::inforec;
impl ImageSurvey {
fn new(
config: HiPSConfig,
@@ -649,7 +643,7 @@ impl ImageSurvey {
let depth = 0;
let depth_tile = 0;
let footprint_moc = Arc::new(Mutex::new(None));
let footprint_moc = None;
// request the allsky texture
Ok(ImageSurvey {
//color,
@@ -689,13 +683,13 @@ impl ImageSurvey {
}
#[inline]
pub fn set_moc(&mut self, moc: Arc<Mutex<Option<HEALPixCoverage>>>) {
self.footprint_moc = moc;
pub fn set_moc(&mut self, moc: HEALPixCoverage) {
self.footprint_moc = Some(moc);
}
#[inline]
pub fn get_moc(&self) -> Arc<Mutex<Option<HEALPixCoverage>>> {
self.footprint_moc.clone()
pub fn get_moc(&self) -> Option<&HEALPixCoverage> {
self.footprint_moc.as_ref()
}
pub fn set_img_format(&mut self, fmt: HiPSTileFormat) -> Result<(), JsValue> {
@@ -784,15 +778,13 @@ impl ImageSurvey {
let survey_config = self.textures.config();
let mut textures = T::get_textures_from_survey(&self.view, &self.textures);
if let Some(moc) = (*self.footprint_moc.lock().unwrap()).as_ref() {
if let Some(moc) = self.footprint_moc.as_ref() {
textures = textures.into_iter()
// filter textures that are not in the moc
.filter(|TextureToDraw { cell, .. }| {
moc.contains(cell)
}).collect::<Vec<_>>();
}
let num_tiles = textures.len();
//al_core::info!(num_tiles);
// Get the coo system transformation matrix
let selected_frame = camera.get_system();
@@ -802,7 +794,6 @@ impl ImageSurvey {
// Retrieve the model and inverse model matrix
let w2v = c * (*camera.get_w2m());
let v2w = w2v.transpose();
let delta_depth = self.get_config().delta_depth();
for TextureToDraw {
starting_texture,
@@ -831,7 +822,6 @@ impl ImageSurvey {
start_time.as_millis(),
camera,
&v2w,
delta_depth
);
}
self.num_idx = self.idx_vertices.len();
@@ -962,11 +952,6 @@ impl ImageSurvey {
self.depth
}
#[inline]
pub fn get_tile_depth(&self) -> u8 {
self.depth_tile
}
#[inline]
pub fn is_ready(&self) -> bool {
self.textures.is_ready()

View File

@@ -45,7 +45,6 @@ impl TileUVW {
let (idx_col_in_tex, idx_row_in_tex) = cell.offset_in_parent(texture.cell());
let num_textures_by_side_slice_f32 = num_textures_by_side_slice as f32;
let texture_slice_px = cfg.get_texture_size() * num_textures_by_side_slice;
let nside = (1 << (cell.depth() - texture.cell().depth())) as f32;
let u = ((idx_row_in_slice as f32) + ((idx_row_in_tex as f32) / nside)) / num_textures_by_side_slice_f32;

View File

@@ -1,11 +1,11 @@
use crate::math::projection::HEALPix;
use crate::{coosys, healpix::cell::HEALPixCell, math};
use std::collections::HashMap;
/*
use crate::math::angle::Angle;
use crate::Projection;
use cgmath::Vector2;
use al_core::{log, inforec};
pub fn project_vertices<P: Projection>(cell: &HEALPixCell, camera: &CameraViewPort) -> [Vector2<f64>; 4] {
let project_vertex = |(lon, lat): (f64, f64)| -> Vector2<f64> {
let vertex = crate::math::lonlat::radec_to_xyzw(Angle(lon), Angle(lat));
@@ -20,7 +20,7 @@ pub fn project_vertices<P: Projection>(cell: &HEALPixCell, camera: &CameraViewPo
project_vertex(vertices[2]),
project_vertex(vertices[3])
]
}
}*/
// Compute a depth from a number of pixels on screen
pub fn depth_from_pixels_on_screen(camera: &CameraViewPort, num_pixels: i32) -> u8 {
@@ -101,7 +101,6 @@ pub fn compute_view_coverage(camera: &CameraViewPort, depth: u8, dst_frame: &Coo
use crate::healpix;
use al_api::coo_system::CooSystem;
use cgmath::Vector4;
pub fn get_tile_cells_in_camera(
depth_tile: u8,
camera: &CameraViewPort,
@@ -136,7 +135,7 @@ pub struct HEALPixCellsInView {
coverage: HEALPixCoverage,
}
use crate::camera::{CameraViewPort, UserAction};
use crate::camera::CameraViewPort;
impl HEALPixCellsInView {
pub fn new() -> Self {
let cells = HashMap::new();
@@ -174,10 +173,10 @@ impl HEALPixCellsInView {
self.coverage = coverage;
// Update cells in the fov
self.update_cells_in_fov(&tile_cells, camera);
self.update_cells_in_fov(&tile_cells);
}
fn update_cells_in_fov(&mut self, cells_in_fov: &[HEALPixCell], camera: &CameraViewPort) {
fn update_cells_in_fov(&mut self, cells_in_fov: &[HEALPixCell]) {
let new_cells = cells_in_fov
.iter()
.map(|cell| {
@@ -239,16 +238,4 @@ impl HEALPixCellsInView {
//self.new_cells.is_there_new_cells_added()
!self.view_unchanged
}
#[inline]
fn has_depth_decreased(&self) -> bool {
let depth = self.get_depth();
depth < self.prev_depth
}
#[inline]
fn has_depth_changed(&self) -> bool {
let depth = self.get_depth();
depth != self.prev_depth
}
}

View File

@@ -892,8 +892,6 @@ export let Aladin = (function () {
};
Aladin.prototype.addMOC = function (moc) {
this.view.addMOC(moc);
ALEvent.GRAPHIC_OVERLAY_LAYER_ADDED.dispatchedTo(this.aladinDiv, {layer: moc});
};
// @API

View File

@@ -5,19 +5,14 @@
*
* This class represents a MOC (Multi Order Coverage map) layer
*
* Author: Thomas Boch[CDS]
* Author: Thomas Boch[CDS], Matthieu Baumann[CDS]
*
*****************************************************************************/
import { astro } from "./libs/fits.js";
import { CooFrameEnum } from "./CooFrameEnum.js";
import { Aladin } from "./Aladin.js";
import { ProjectionEnum } from "./ProjectionEnum.js";
import { Utils } from "./Utils.js";
import { AladinUtils } from "./AladinUtils.js";
import { CooConversion } from "./CooConversion.js";
import { Color } from "./Color";
import { ALEvent } from "./events/ALEvent.js";
export let MOC = (function() {
let MOC = function(options) {
@@ -41,114 +36,17 @@ export let MOC = (function() {
//this.proxyCalled = false; // this is a flag to check whether we already tried to load the MOC through the proxy
// index of MOC cells at high and low resolution
/*this._highResIndexOrder3 = new Array(768);
this._lowResIndexOrder3 = new Array(768);
for (var k=0; k<768; k++) {
this._highResIndexOrder3[k] = {};
this._lowResIndexOrder3[k] = {};
}
this.nbCellsDeepestLevel = 0; // needed to compute the sky fraction of the MOC*/
this.isShowing = true;
this.ready = false;
this.skyFrac = undefined;
}
/*function log2(val) {
return Math.log(val) / Math.LN2;
}*/
// max norder we can currently handle (limitation of healpix.js)
//MOC.MAX_NORDER = 13; // NSIDE = 8192
//MOC.LOWRES_MAXORDER = 6; // 5 or 6 ??
//MOC.HIGHRES_MAXORDER = 11; // ??
// TODO: options to modifiy this ?
//MOC.PIVOT_FOV = 30; // when do we switch from low res cells to high res cells (fov in degrees)
// at end of parsing, we need to remove duplicates from the 2 indexes
/*MOC.prototype._removeDuplicatesFromIndexes = function() {
var a, aDedup;
for (var k=0; k<768; k++) {
for (var key in this._highResIndexOrder3[k]) {
a = this._highResIndexOrder3[k][key];
aDedup = uniq(a);
this._highResIndexOrder3[k][key] = aDedup;
}
for (var key in this._lowResIndexOrder3[k]) {
a = this._lowResIndexOrder3[k][key];
aDedup = uniq(a);
this._lowResIndexOrder3[k][key] = aDedup;
}
}
}*/
// add pixel (order, ipix)
/*MOC.prototype._addPix = function(order, ipix) {
var ipixOrder3 = Math.floor( ipix * Math.pow(4, (3 - order)) );
// fill low and high level cells
// 1. if order <= LOWRES_MAXORDER, just store value in low and high res cells
if (order<=MOC.LOWRES_MAXORDER) {
if (! (order in this._lowResIndexOrder3[ipixOrder3])) {
this._lowResIndexOrder3[ipixOrder3][order] = [];
this._highResIndexOrder3[ipixOrder3][order] = [];
}
this._lowResIndexOrder3[ipixOrder3][order].push(ipix);
this._highResIndexOrder3[ipixOrder3][order].push(ipix);
}
// 2. if LOWRES_MAXORDER < order <= HIGHRES_MAXORDER , degrade ipix for low res cells
else if (order<=MOC.HIGHRES_MAXORDER) {
if (! (order in this._highResIndexOrder3[ipixOrder3])) {
this._highResIndexOrder3[ipixOrder3][order] = [];
}
this._highResIndexOrder3[ipixOrder3][order].push(ipix);
var degradedOrder = MOC.LOWRES_MAXORDER;
var degradedIpix = Math.floor(ipix / Math.pow(4, (order - degradedOrder)));
var degradedIpixOrder3 = Math.floor( degradedIpix * Math.pow(4, (3 - degradedOrder)) );
if (! (degradedOrder in this._lowResIndexOrder3[degradedIpixOrder3])) {
this._lowResIndexOrder3[degradedIpixOrder3][degradedOrder]= [];
}
this._lowResIndexOrder3[degradedIpixOrder3][degradedOrder].push(degradedIpix);
}
// 3. if order > HIGHRES_MAXORDER , degrade ipix for low res and high res cells
else {
// low res cells
var degradedOrder = MOC.LOWRES_MAXORDER;
var degradedIpix = Math.floor(ipix / Math.pow(4, (order - degradedOrder)));
var degradedIpixOrder3 = Math.floor(degradedIpix * Math.pow(4, (3 - degradedOrder)) );
if (! (degradedOrder in this._lowResIndexOrder3[degradedIpixOrder3])) {
this._lowResIndexOrder3[degradedIpixOrder3][degradedOrder]= [];
}
this._lowResIndexOrder3[degradedIpixOrder3][degradedOrder].push(degradedIpix);
// high res cells
degradedOrder = MOC.HIGHRES_MAXORDER;
degradedIpix = Math.floor(ipix / Math.pow(4, (order - degradedOrder)));
var degradedIpixOrder3 = Math.floor(degradedIpix * Math.pow(4, (3 - degradedOrder)) );
if (! (degradedOrder in this._highResIndexOrder3[degradedIpixOrder3])) {
this._highResIndexOrder3[degradedIpixOrder3][degradedOrder]= [];
}
this._highResIndexOrder3[degradedIpixOrder3][degradedOrder].push(degradedIpix);
}
this.nbCellsDeepestLevel += Math.pow(4, (this.order - order));
};*/
/**
* Return a value between 0 and 1 denoting the fraction of the sky
* covered by the MOC
*/
MOC.prototype.skyFraction = function() {
if (this.view) {
// update the new moc params to the backend
return this.view.aladin.webglAPI.mocSkyFraction(this.mocParams);
}
return this.skyFrac;
};
/**
@@ -156,246 +54,59 @@ export let MOC = (function() {
* (as defined in IVOA MOC document, section 3.1.1)
*/
MOC.prototype.dataFromJSON = function(jsonMOC) {
/*var order, ipix;
// 1. Compute the order (order of the deepest cells contained in the moc)
for (var orderStr in jsonMOC) {
if (jsonMOC.hasOwnProperty(orderStr)) {
order = parseInt(orderStr);
if (this.order===undefined || order > this.order) {
this.order = order;
}
}
}
// 2. Build the mocs (LOW and HIGH res ones)
for (var orderStr in jsonMOC) {
if (jsonMOC.hasOwnProperty(orderStr)) {
order = parseInt(orderStr);
for (var k=0; k<jsonMOC[orderStr].length; k++) {
ipix = jsonMOC[orderStr][k];
this._addPix(order, ipix);
}
}
}
this.reportChange();*/
this.ready = true;
this.dataJSON = jsonMOC;
};
/**
* set MOC data by parsing a URL pointing to a FITS MOC file
*/
MOC.prototype.dataFromFITSURL = function(mocURL, successCallback) {
var self = this;
/*var callback = function() {
// note: in the callback, 'this' refers to the FITS instance
// first, let's find MOC norder
var hdr0;
try {
// A zero-length hdus array might mean the served URL does not have CORS header
// --> let's try again through the proxy
if (this.hdus.length == 0) {
if (self.proxyCalled !== true) {
self.proxyCalled = true;
var proxiedURL = Aladin.JSONP_PROXY + '?url=' + encodeURIComponent(self.dataURL);
new astro.FITS(proxiedURL, callback);
}
return;
}
hdr0 = this.getHeader(0);
}
catch (e) {
console.error('Could not get header of extension #0');
return;
}
var hdr1 = this.getHeader(1);
if (hdr0.contains('HPXMOC')) {
self.order = hdr0.get('HPXMOC')
}
else if (hdr0.contains('MOCORDER')) {
self.order = hdr0.get('MOCORDER')
}
else if (hdr1.contains('HPXMOC')) {
self.order = hdr1.get('HPXMOC')
}
else if (hdr1.contains('MOCORDER')) {
self.order = hdr1.get('MOCORDER')
}
else {
console.error('Can not find MOC order in FITS file');
return;
}
var data = this.getDataUnit(1);
var colName = data.columns[0];
data.getRows(0, data.rows, function(rows) {
for (var k=0; k<rows.length; k++) {
var uniq = rows[k][colName];
var order = Math.floor(Math.floor(log2(Math.floor(uniq/4))) / 2);
var ipix = uniq - 4 *(Math.pow(4, order));
self._addPix(order, ipix);
}
});
data = null; // this helps releasing memory
self._removeDuplicatesFromIndexes();
if (successCallback) {
successCallback();
}
self.reportChange();
self.ready = true;
}; // end of callback function
*/
MOC.prototype.dataFromFITSURL = function(mocURL, successCallback) {
this.dataURL = mocURL;
this.promiseFetchData = fetch(this.dataURL)
.then((resp) => resp.arrayBuffer());
this.successCallback = successCallback;
// instantiate the FITS object which will fetch the URL passed as parameter
//new astro.FITS(this.dataURL, callback);
};
MOC.prototype.setView = function(view) {
let self = this;
this.view = view;
this.mocParams = new Aladin.wasmLibs.webgl.MOC(this.uuid, this.opacity, this.lineWidth, this.adaptativeDisplay, this.isShowing, this.color);
this.mocParams = new Aladin.wasmLibs.webgl.MOC(this.uuid, this.opacity, this.lineWidth, this.isShowing, this.color);
if (this.dataURL) {
view.aladin.webglAPI.addFITSMoc(this.mocParams, this.dataURL, this.successCallback);
this.promiseFetchData
.then((arrayBuffer) => {
// Add the fetched moc to the rust backend
self.view.aladin.webglAPI.addFITSMoc(self.mocParams, arrayBuffer);
self.ready = true;
if (self.successCallback) {
self.successCallback(self)
}
// Cache the sky fraction
self.skyFrac = self.view.aladin.webglAPI.mocSkyFraction(this.mocParams);
// Tell the MOC has been fully loaded and can be sent as an event
ALEvent.GRAPHIC_OVERLAY_LAYER_ADDED.dispatchedTo(self.view.aladinDiv, {layer: self});
self.view.requestRedraw();
})
} else if (this.dataFromJSON) {
view.aladin.webglAPI.addJSONMoc(this.mocParams, this.dataJSON);
}
self.view.aladin.webglAPI.addJSONMoc(self.mocParams, self.dataJSON);
self.ready = true;
view.requestRedraw();
};
// Cache the sky fraction
self.skyFrac = self.view.aladin.webglAPI.mocSkyFraction(self.mocParams);
/*MOC.prototype.draw = function(ctx, projection, viewFrame, width, height, largestDim, zoomFactor, fov) {
if (! this.isShowing || ! this.ready) {
return;
}
var mocCells = fov > MOC.PIVOT_FOV && this.adaptativeDisplay ? this._lowResIndexOrder3 : this._highResIndexOrder3;
// Tell the MOC has been fully loaded and can be sent as an event
ALEvent.GRAPHIC_OVERLAY_LAYER_ADDED.dispatchedTo(self.view.aladinDiv, {layer: self});
this._drawCells(ctx, mocCells, fov, projection, viewFrame, CooFrameEnum.J2000, width, height, largestDim, zoomFactor);
};
MOC.prototype._drawCells = function(ctx, mocCellsIdxOrder3, fov, projection, viewFrame, surveyFrame, width, height, largestDim, zoomFactor) {
ctx.lineWidth = this.lineWidth;
// if opacity==1, we draw solid lines, else we fill each HEALPix cell
if (this.opacity==1) {
ctx.strokeStyle = this.color;
}
else {
ctx.fillStyle = this.color;
ctx.globalAlpha = this.opacity;
}
ctx.beginPath();
var orderedKeys = [];
for (var k=0; k<768; k++) {
var mocCells = mocCellsIdxOrder3[k];
for (var key in mocCells) {
orderedKeys.push(parseInt(key));
}
}
orderedKeys.sort(function(a, b) {return a - b;});
var norderMax = orderedKeys[orderedKeys.length-1];
var nside, xyCorners, ipix;
var potentialVisibleHpxCellsOrder3 = this.view.getVisiblePixList(3);
var visibleHpxCellsOrder3 = [];
// let's test first all potential visible cells and keep only the one with a projection inside the view
for (var k=0; k<potentialVisibleHpxCellsOrder3.length; k++) {
var ipix = potentialVisibleHpxCellsOrder3[k];
xyCorners = getXYCorners(8, ipix, viewFrame, surveyFrame, width, height, largestDim, zoomFactor, projection, this.view);
if (xyCorners) {
visibleHpxCellsOrder3.push(ipix);
}
}
var counter = 0;
var mocCells;
var norder3Ipix;
for (var norder=0; norder<=norderMax; norder++) {
nside = 1 << norder;
for (var i=0; i<visibleHpxCellsOrder3.length; i++) {
var ipixOrder3 = visibleHpxCellsOrder3[i];
mocCells = mocCellsIdxOrder3[ipixOrder3];
if (typeof mocCells[norder]==='undefined') {
continue;
}
if (norder<=3) {
for (var j=0; j<mocCells[norder].length; j++) {
ipix = mocCells[norder][j];
var factor = Math.pow(4, (3-norder));
var startIpix = ipix * factor;
for (var k=0; k<factor; k++) {
norder3Ipix = startIpix + k;
xyCorners = getXYCorners(8, norder3Ipix, viewFrame, surveyFrame, width, height, largestDim, zoomFactor, projection, this.view);
if (xyCorners) {
drawCorners(ctx, xyCorners);
}
}
}
}
else {
for (var j=0; j<mocCells[norder].length; j++) {
ipix = mocCells[norder][j];
var parentIpixOrder3 = Math.floor(ipix/Math.pow(4, norder-3));
xyCorners = getXYCorners(nside, ipix, viewFrame, surveyFrame, width, height, largestDim, zoomFactor, projection, this.view);
if (xyCorners) {
drawCorners(ctx, xyCorners);
}
}
}
}
}
if (this.opacity==1) {
ctx.stroke();
}
else {
ctx.fill();
ctx.globalAlpha = 1.0;
self.view.requestRedraw();
}
};
var drawCorners = function(ctx, xyCorners) {
ctx.moveTo(xyCorners[0].vx, xyCorners[0].vy);
ctx.lineTo(xyCorners[1].vx, xyCorners[1].vy);
ctx.lineTo(xyCorners[2].vx, xyCorners[2].vy);
ctx.lineTo(xyCorners[3].vx, xyCorners[3].vy);
ctx.lineTo(xyCorners[0].vx, xyCorners[0].vy);
}
// remove duplicate items from array a
var uniq = function(a) {
var seen = {};
var out = [];
var len = a.length;
var j = 0;
for (var i = 0; i < len; i++) {
var item = a[i];
if (seen[item] !== 1) {
seen[item] = 1;
out[j++] = item;
}
}
return out;
};*/
MOC.prototype.reportChange = function() {
if (this.view) {
// update the new moc params to the backend
@@ -433,46 +144,12 @@ export let MOC = (function() {
//
// returns true if point is contained, false otherwise
MOC.prototype.contains = function(ra, dec) {
/*var hpxIdx = new HealpixIndex(Math.pow(2, this.order));
hpxIdx.init();
var polar = HealpixIndex.utils.radecToPolar(ra, dec);
var ipix = hpxIdx.ang2pix_nest(polar.theta, polar.phi);
var ipixMapByOrder = {};
for (var curOrder=0; curOrder<=this.order; curOrder++) {
ipixMapByOrder[curOrder] = Math.floor(ipix / Math.pow(4, this.order - curOrder));
if (!this.ready) {
throw this.name + " is not yet ready, either because it has not been downloaded yet or because it has not been added to the aladin instance."
}
// first look for large HEALPix cells (order<3)
for (var ipixOrder3=0; ipixOrder3<768; ipixOrder3++) {
var mocCells = this._highResIndexOrder3[ipixOrder3];
for (var order in mocCells) {
if (order<3) {
for (var k=mocCells[order].length; k>=0; k--) {
if (ipixMapByOrder[order] == mocCells[order][k]) {
return true;
}
}
}
}
}
// look for finer cells
var ipixOrder3 = ipixMapByOrder[3];
var mocCells = this._highResIndexOrder3[ipixOrder3];
for (var order in mocCells) {
for (var k=mocCells[order].length; k>=0; k--) {
if (ipixMapByOrder[order] == mocCells[order][k]) {
return true;
}
}
}
return false;*/
if (this.view) {
console.log("contains")
// update the new moc params to the backend
//return this.view.aladin.webglAPI.mocContains(this.mocParams, ra, dec);
}
// update the new moc params to the backend
return this.view.aladin.webglAPI.mocContains(this.mocParams, ra, dec);
};
return MOC;