for HiPSColor {
+ fn attach_uniforms_with_params<'a>(&self, shader: &'a ShaderBound<'a>, cmaps: &Colormaps) -> &'a ShaderBound<'a> {
+ let reversed = self.reversed as u8 as f32;
+
+ let cmap = cmaps.get(&self.cmap_name.as_ref());
+ shader
+ .attach_uniforms_with_params_from(cmap, cmaps)
+ .attach_uniform("H", &self.stretch)
+ .attach_uniform("min_value", &self.min_cut.unwrap_or(0.0))
+ .attach_uniform("max_value", &self.max_cut.unwrap_or(1.0))
+ .attach_uniform("k_gamma", &self.k_gamma)
+ .attach_uniform("k_saturation", &self.k_saturation)
+ .attach_uniform("k_brightness", &self.k_brightness)
+ .attach_uniform("k_contrast", &self.k_contrast)
+ .attach_uniform("reversed", &reversed);
+
shader
}
}
@@ -380,6 +375,12 @@ impl<'a> ShaderBound<'a> {
self
}
+ pub fn attach_uniforms_with_params_from>(&'a self, t: &T, params: &P) -> &'a Self {
+ t.attach_uniforms_with_params(self, params);
+
+ self
+ }
+
pub fn attach_uniforms_from(&'a self, t: &T) -> &'a Self {
t.attach_uniforms(self);
@@ -419,3 +420,7 @@ impl<'a> Drop for ShaderBound<'a> {
pub trait SendUniforms {
fn attach_uniforms<'a>(&self, shader: &'a ShaderBound<'a>) -> &'a ShaderBound<'a>;
}
+
+pub trait SendUniformsWithParams {
+ fn attach_uniforms_with_params<'a>(&self, shader: &'a ShaderBound<'a>, params: &T) -> &'a ShaderBound<'a>;
+}
diff --git a/src/core/al-ui/js/hpxImageSurvey.js b/src/core/al-ui/js/hpxImageSurvey.js
deleted file mode 100644
index e56e6909..00000000
--- a/src/core/al-ui/js/hpxImageSurvey.js
+++ /dev/null
@@ -1,33 +0,0 @@
-
-import { HiPSDefinition } from "../../../../../js/HiPSDefinition.js";
-import { HpxImageSurvey } from "../../../../../js/HpxImageSurvey.js";
-import { Utils } from "../../../../../js/Utils.js";
-
-export async function fetchSurveyMetadata(rootURL) {
- // Use the url for retrieving the HiPS properties
- // remove final slash
- if (rootURL.slice(-1) === '/') {
- rootURL = rootURL.substr(0, rootURL.length-1);
- }
-
- // make URL absolute
- rootURL = Utils.getAbsoluteURL(rootURL);
-
- // fast fix for HTTPS support --> will work for all HiPS served by CDS
- if (Utils.isHttpsContext() && ( /u-strasbg.fr/i.test(rootURL) || /unistra.fr/i.test(rootURL) ) ) {
- rootURL = rootURL.replace('http://', 'https://');
- }
-
- const url = rootURL + '/properties';
- let metadata = await fetch(url)
- .then((response) => response.text());
- // We get the property here
- metadata = HiPSDefinition.parseHiPSProperties(metadata);
-
- // 1. Ensure there is exactly one survey matching
- if (!metadata) {
- throw 'no surveys matching';
- }
- //console.log(metadata);
- return metadata;
-}
diff --git a/src/core/al-ui/src/widgets/survey.rs b/src/core/al-ui/src/widgets/survey.rs
index 921ff85a..4128f193 100644
--- a/src/core/al-ui/src/widgets/survey.rs
+++ b/src/core/al-ui/src/widgets/survey.rs
@@ -108,7 +108,7 @@ impl PropertiesParsed {
use egui::{Color32, InnerResponse, Response};
use wasm_bindgen::prelude::*;
-#[wasm_bindgen(module = "/js/hpxImageSurvey.js")]
+#[wasm_bindgen(module = "/js/ImageSurvey.js")]
extern "C" {
#[wasm_bindgen(catch, js_name = fetchSurveyMetadata)]
async fn fetch_survey_metadata(url: String) -> Result;
@@ -535,7 +535,7 @@ impl SurveyWidget {
.selectable_value(&mut self.colormap, Colormap::Plasma, "plasma")
.clicked();
*ui_changed |= ui
- .selectable_value(&mut self.colormap, Colormap::Rainbow, "rainbow")
+ .selectable_value(&mut self.colormap, Colormap::Rainbow, "sinebow")
.clicked();
*ui_changed |= ui
.selectable_value(&mut self.colormap, Colormap::Rdbu, "rdbu")
diff --git a/src/core/src/app.rs b/src/core/src/app.rs
index e4dc31cc..d0f7d8f0 100644
--- a/src/core/src/app.rs
+++ b/src/core/src/app.rs
@@ -1,7 +1,6 @@
use crate::{
async_task::{BuildCatalogIndex, ParseTableTask, TaskExecutor, TaskResult, TaskType},
camera::CameraViewPort,
- colormap::Colormaps,
downloader::Downloader,
math::{
self,
@@ -22,6 +21,7 @@ use crate::{
};
use al_core::WebGlContext;
+use al_core::colormap::{Colormap, Colormaps};
use al_api::{
coo_system::CooSystem,
@@ -182,7 +182,7 @@ impl App {
let out_of_fov = false;
let catalog_loaded = false;
- let colormaps = Colormaps::new(&gl, &resources)?;
+ let colormaps = Colormaps::new(&gl)?;
let _final_rendering_pass = RenderPass::new(&gl)?;
let tile_fetcher = TileFetcherQueue::new();
@@ -383,7 +383,6 @@ impl App {
}*/
}
-use al_api::hips::HiPSTileFormat;
use al_api::cell::HEALPixCellProjeted;
use crate::downloader::request::Resource;
@@ -834,27 +833,7 @@ impl App {
self.layers.set_image_surveys(hipses, &self.gl, &mut self.camera, &self.projection)?;
for hips in self.layers.values_hips() {
- let cfg = hips.get_config();
- // Request for the allsky first
- // 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()));
-
- let tile_size = cfg.get_tile_size();
- //Request the allsky for the small tile size or if base tiles are not available
- if tile_size <= 128 || cfg.get_min_depth_tile() > 0 {
- // Request the allsky
- self.downloader.fetch(query::Allsky::new(cfg));
- } else {
- for texture_cell in crate::healpix::cell::ALLSKY_HPX_CELLS_D0 {
- for cell in texture_cell.get_tile_cells(cfg) {
- let query = query::Tile::new(&cell, cfg);
- self.tile_fetcher
- .append_base_tile(query, &mut self.downloader);
- }
- }
- }
+ self.tile_fetcher.launch_starting_hips_requests(hips, &mut self.downloader);
}
// Once its added, request the tiles in the view (unless the viewer is at depth 0)
@@ -872,29 +851,9 @@ impl App {
pub(crate) fn set_hips_url(&mut self, past_url: String, new_url: String) -> Result<(), JsValue> {
self.layers.set_survey_url(past_url, new_url.clone())?;
- let hips = self.layers.get_mut_hips(&new_url).unwrap();
+ let hips = self.layers.get_hips(&new_url).unwrap();
// Relaunch the base tiles for the survey to be ready with the new url
- let cfg = hips.get_config();
- // Request for the allsky first
- // 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()));
-
- let tile_size = cfg.get_tile_size();
- //Request the allsky for the small tile size or if base tiles are not available
- if tile_size <= 128 || cfg.get_min_depth_tile() > 0 {
- // Request the allsky
- self.downloader.fetch(query::Allsky::new(cfg));
- } else {
- for texture_cell in crate::healpix::cell::ALLSKY_HPX_CELLS_D0 {
- for cell in texture_cell.get_tile_cells(cfg) {
- let query = query::Tile::new(&cell, cfg);
- self.tile_fetcher
- .append_base_tile(query, &mut self.downloader);
- }
- }
- }
+ self.tile_fetcher.launch_starting_hips_requests(hips, &mut self.downloader);
Ok(())
}
@@ -906,45 +865,23 @@ impl App {
) -> Result<(), JsValue> {
self.request_redraw = true;
- self.layers.set_layer_cfg(layer, meta, &self.camera, &self.projection)
- }
+ let old_meta = self.layers.get_layer_cfg(&layer)?;
+ if old_meta.img_format != meta.img_format {
+ // the image format has been changed
+ let hips = self.layers
+ .get_mut_hips_from_layer(&layer)
+ .ok_or_else(|| JsValue::from_str("Layer not found"))?;
+ hips.set_img_format(meta.img_format)?;
+ // Relaunch the base tiles for the survey to be ready with the new url
+ self.tile_fetcher.launch_starting_hips_requests(hips, &mut self.downloader);
- pub(crate) fn set_image_survey_img_format(&mut self, layer: String, format: HiPSTileFormat) -> Result<(), JsValue> {
- let survey = self.layers.get_mut_hips_from_layer(&layer)
- .ok_or_else(|| JsValue::from_str("Layer not found"))?;
- survey.set_img_format(format)?;
- // Request for the allsky first
- // The allsky is not mandatory present in a HiPS service but it is better to first try to search for it
- let cfg = survey.get_config();
-
- //Request the allsky for the small tile size
- let tile_size = cfg.get_tile_size();
-
- // 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()));
- //Request the allsky for the small tile size
- if tile_size <= 128 || cfg.get_min_depth_tile() > 0 {
- // Request the allsky
- self.downloader.fetch(query::Allsky::new(cfg));
- } else {
- for texture_cell in crate::healpix::cell::ALLSKY_HPX_CELLS_D0 {
- for cell in texture_cell.get_tile_cells(cfg) {
- let query = query::Tile::new(&cell, cfg);
- self.tile_fetcher
- .append_base_tile(query, &mut self.downloader);
- }
- }
+ // Once its added, request the tiles in the view (unless the viewer is at depth 0)
+ self.request_for_new_tiles = true;
+ self.request_redraw = true;
}
-
- // Once its added, request the tiles in the view (unless the viewer is at depth 0)
- self.request_for_new_tiles = true;
-
- self.request_redraw = true;
-
- Ok(())
+ // Set the new meta
+ self.layers.set_layer_cfg(layer, meta, &self.camera, &self.projection)
}
// Width and height given are in pixels
@@ -970,10 +907,9 @@ impl App {
self.camera.get_longitude_reversed()
}
- pub(crate) fn add_catalog(&mut self, name: String, table: JsValue, colormap: String) {
+ pub(crate) fn add_catalog(&mut self, name: String, table: JsValue, _colormap: String) {
let mut exec_ref = self.exec.borrow_mut();
let table = table;
- let c = self.colormaps.get(&colormap);
exec_ref
.spawner()
@@ -995,7 +931,6 @@ impl App {
TaskResult::TableParsed {
name,
sources: results.into_boxed_slice(),
- colormap: c,
}
});
}
@@ -1219,6 +1154,10 @@ impl App {
self.out_of_fov = true;
}
+ pub(crate) fn add_cmap(&mut self, label: String, cmap: Colormap) -> Result<(), JsValue> {
+ self.colormaps.add_cmap(label, cmap)
+ }
+
// Accessors
pub(crate) fn get_center(&self) -> LonLatT {
self.camera.get_center().lonlat()
@@ -1237,6 +1176,10 @@ impl App {
deg.0
}
+ pub(crate) fn get_colormaps(&self) -> &Colormaps {
+ &self.colormaps
+ }
+
pub(crate) fn get_gl_canvas(&self) -> Option {
self.gl.canvas()
}
diff --git a/src/core/src/async_task.rs b/src/core/src/async_task.rs
index ac67d069..09930637 100644
--- a/src/core/src/async_task.rs
+++ b/src/core/src/async_task.rs
@@ -7,12 +7,10 @@ use al_task_exec::Executor;
pub type TaskExecutor = Executor;
pub use crate::renderable::catalog::Source;
-pub use al_api::colormap::Colormap;
pub enum TaskResult {
TableParsed {
name: String,
sources: Box<[Source]>,
- colormap: Colormap,
},
/*TileSentToGPU {
tile: Tile,
diff --git a/src/core/src/colormap.rs b/src/core/src/colormap.rs
deleted file mode 100644
index b3974968..00000000
--- a/src/core/src/colormap.rs
+++ /dev/null
@@ -1,117 +0,0 @@
-use al_api::resources::Resources;
-use std::collections::HashMap;
-
-use al_core::Texture2D;
-use al_core::WebGlContext;
-
-use wasm_bindgen::JsValue;
-use web_sys::WebGl2RenderingContext;
-
-pub struct Colormaps {
- tex: Texture2D,
- colormaps: HashMap<&'static str, Colormap>,
-}
-
-use crate::Abort;
-use al_api::colormap::Colormap;
-impl Colormaps {
- pub fn new(gl: &WebGlContext, rs: &Resources) -> Result {
- let colormaps: HashMap<&str, Colormap> = [
- ("blues", Colormap::Blues),
- ("cividis", Colormap::Cividis),
- ("cubehelix", Colormap::Cubehelix),
- ("eosb", Colormap::Eosb),
- ("grayscale", Colormap::Grayscale),
- ("inferno", Colormap::Inferno),
- ("magma", Colormap::Magma),
- ("parula", Colormap::Parula),
- ("plasma", Colormap::Plasma),
- ("rainbow", Colormap::Rainbow),
- ("rdbu", Colormap::Rdbu),
- ("rdyibu", Colormap::Rdyibu),
- ("redtemperature", Colormap::Redtemperature),
- ("spectral", Colormap::Spectral),
- ("summer", Colormap::Summer),
- ("viridis", Colormap::Viridis),
- ("ylgnbu", Colormap::Ylgnbu),
- ("ylorbr", Colormap::Ylorbr),
- ]
- .iter()
- .cloned()
- .collect();
- let colormap_filename = rs.get_filename("colormaps").unwrap_abort();
- let tex = Texture2D::create_from_path::<_, al_core::image::format::RGBA8U>(
- gl,
- "colormap",
- &colormap_filename,
- &[
- (
- WebGl2RenderingContext::TEXTURE_MIN_FILTER,
- WebGl2RenderingContext::LINEAR,
- ),
- (
- WebGl2RenderingContext::TEXTURE_MAG_FILTER,
- WebGl2RenderingContext::LINEAR,
- ),
- // 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,
- ),
- ],
- )?;
-
- Ok(Self { colormaps, tex })
- }
-
- #[inline]
- pub const fn get_list_available_colormaps() -> &'static [&'static str] {
- &[
- "blues",
- "cividis",
- "cubehelix",
- "eosb",
- "grayscale",
- "inferno",
- "magma",
- "parula",
- "plasma",
- "rainbow",
- "rdbu",
- "rdyibu",
- "redtemperature",
- "spectral",
- "summer",
- "viridis",
- "ylgnbu",
- "ylorbr",
- ]
- }
-
- pub fn get(&self, name: &str) -> Colormap {
- let c = if let Some(c) = self.colormaps.get(name) {
- c
- } else {
- self.colormaps.get("grayscale").unwrap_abort()
- };
-
- *c
- }
-}
-
-use al_core::shader::{SendUniforms, ShaderBound};
-
-impl SendUniforms for Colormaps {
- fn attach_uniforms<'a>(&self, shader: &'a ShaderBound<'a>) -> &'a ShaderBound<'a> {
- shader
- .attach_uniform("colormaps", &self.tex)
- .attach_uniform("num_colormaps", &(self.colormaps.len() as f32));
-
- shader
- }
-}
diff --git a/src/core/src/lib.rs b/src/core/src/lib.rs
index 89093544..770d45a3 100644
--- a/src/core/src/lib.rs
+++ b/src/core/src/lib.rs
@@ -16,10 +16,6 @@
//extern crate itertools_num;
//extern crate num;
//extern crate num_traits;
-extern crate wasm_streams;
-extern crate console_error_panic_hook;
-extern crate mapproj;
-extern crate wcs;
use std::panic;
pub trait Abort {
@@ -68,6 +64,7 @@ pub fn unwrap_abort(o: Option) -> T {
#[macro_use]
mod utils;
+use al_api::color::{Color, ColorRGBA};
use math::projection::*;
use wasm_bindgen::prelude::*;
@@ -75,7 +72,6 @@ mod app;
pub mod async_task;
mod camera;
-mod colormap;
mod coosys;
mod downloader;
mod healpix;
@@ -89,7 +85,7 @@ mod time;
mod fifo_cache;
use crate::{
- camera::CameraViewPort, colormap::Colormaps, math::lonlat::LonLatT, shader::ShaderManager, time::DeltaTime,
+ camera::CameraViewPort, math::lonlat::LonLatT, shader::ShaderManager, time::DeltaTime,
healpix::coverage::HEALPixCoverage,
};
use crate::downloader::request::moc::from_fits_hpx;
@@ -100,7 +96,10 @@ use moclib::deser::fits;
use std::io::Cursor;
use al_api::hips::{HiPSColor, HiPSProperties, SimpleHiPS};
+
+use al_core::Colormap;
use al_core::{WebGlContext};
+use al_core::colormap::Colormaps;
use al_api::coo_system::CooSystem;
@@ -304,12 +303,9 @@ impl WebClient {
// Deserialize the survey objects that compose the survey
let surveys: Result, serde_wasm_bindgen::Error> = surveys
.into_iter()
- .map(|h| {
- serde_wasm_bindgen::from_value(h)
- })
+ .map(|hips| serde_wasm_bindgen::from_value(hips))
.collect::, _>>();
- //let surveys: Vec = surveys.iter().map(SimpleHiPS::from).collect::>();
let surveys = surveys?;
self.app.set_image_surveys(surveys)?;
@@ -334,13 +330,6 @@ impl WebClient {
self.app.set_image_survey_color_cfg(layer, meta)
}
- #[wasm_bindgen(js_name = setImageSurveyImageFormat)]
- pub fn set_image_survey_img_format(&mut self, layer: String, format: JsValue) -> Result<(), JsValue> {
- let format = serde_wasm_bindgen::from_value(format)?;
-
- self.app.set_image_survey_img_format(layer, format)
- }
-
#[wasm_bindgen(js_name = setImageSurveyUrl)]
pub fn set_survey_url(&mut self, past_url: String, new_url: String) -> Result<(), JsValue> {
self.app.set_survey_url(past_url, new_url)
@@ -712,14 +701,43 @@ impl WebClient {
/// in core/img/colormaps/colormaps.png
#[wasm_bindgen(js_name = getAvailableColormapList)]
pub fn get_available_colormap_list(&self) -> Result, JsValue> {
- let colormaps = Colormaps::get_list_available_colormaps()
+ let colormaps = self.app.get_colormaps()
+ .get_list_available_colormaps()
.iter()
- .map(|&s| JsValue::from_str(s))
+ .map(|s| JsValue::from_str(s))
.collect::>();
Ok(colormaps)
}
+ #[wasm_bindgen(js_name = createCustomColormap)]
+ pub fn add_custom_colormap(&mut self, label: String, hex_colors: Vec) -> Result<(), JsValue> {
+ let rgba_colors: Result, JsValue> = hex_colors
+ .into_iter()
+ .map(|hex_color| {
+ let hex_color = serde_wasm_bindgen::from_value(hex_color)?;
+ let color = Color::hexToRgba(hex_color);
+ let color_rgba: ColorRGBA = color.try_into()?;
+
+ Ok(colorgrad::Color::new(
+ color_rgba.r as f64,
+ color_rgba.g as f64,
+ color_rgba.b as f64,
+ color_rgba.a as f64)
+ )
+ })
+ .collect();
+
+ let grad = colorgrad::CustomGradient::new()
+ .colors(&rgba_colors?)
+ .build()
+ .map_err(|err| JsValue::from_str(&format!("{:?}", err)))?;
+
+ let cmap = Colormap::new(&label, grad);
+ self.app.add_cmap(label, cmap)?;
+ Ok(())
+ }
+
/// Get the image canvas where the webgl rendering is done
#[wasm_bindgen(js_name = canvas)]
pub fn get_gl_canvas(&mut self) -> Result