diff --git a/examples/al-adass2022.html b/examples/al-adass2022.html index 50561fd9..b802f34a 100644 --- a/examples/al-adass2022.html +++ b/examples/al-adass2022.html @@ -10,8 +10,9 @@ import A from '../src/js/A.js'; let aladin; A.init.then(() => { - aladin = A.aladin('#aladin-lite-div', {showSettingsControl: true, survey: "P/PanSTARRS/DR1/color-z-zg-g", showReticle: false, projection: "AIT", cooFrame: 'icrs', target: "stephan's quintet", fov: 1000, showGotoControl: false, showFrame: false, fullScreen: true, showLayersControl: true, showCooGridControl: false}); - aladin.showHealpixGrid(true); + let startFov = 1000; + aladin = A.aladin('#aladin-lite-div', {showSettingsControl: true, survey: "P/PanSTARRS/DR1/color-z-zg-g", showReticle: false, projection: "AIT", cooFrame: 'icrs', target: "stephan's quintet", fov: startFov, showGotoControl: false, showFrame: false, fullScreen: true, showLayersControl: true, showCooGridControl: false}); + const chft = aladin.createImageSurvey('CFHT', "CFHT deep view of NGC7331 and Stephan's quintet u+g+r", "https://cds.unistra.fr/~derriere/PR_HiPS/2022_Duc/", null, null, {imgFormat: 'png'}); const nircamJWST = aladin.createImageSurvey('Nircam', "Stephans Quintet NIRCam+MIRI", "http://alasky.cds.unistra.fr/JWST/CDS_P_JWST_Stephans-Quintet_NIRCam+MIRI/", null, null, {imgFormat: 'png', colormap: "viridis"}); @@ -21,7 +22,7 @@ aladin.getOverlayImageLayer("CFHT").toggle(); aladin.getOverlayImageLayer("Nircam").toggle(); - let fov = 360; + let fov = startFov; let rotation = 0; setInterval(function zoom() { diff --git a/src/core/src/app.rs b/src/core/src/app.rs index 6cab744a..d043702e 100644 --- a/src/core/src/app.rs +++ b/src/core/src/app.rs @@ -902,12 +902,12 @@ impl App { //let fbo_view = &self.fbo_view; //catalogs.draw(&gl, shaders, camera, colormaps, fbo_view)?; //catalogs.draw(&gl, shaders, camera, colormaps, None, self.projection)?; - gl.blend_func_separate( + /*gl.blend_func_separate( WebGl2RenderingContext::SRC_ALPHA, WebGl2RenderingContext::ONE, WebGl2RenderingContext::ONE, WebGl2RenderingContext::ONE, - ); + );*/ moc.draw(camera, projection, shaders)?; gl.blend_func_separate( @@ -1399,7 +1399,7 @@ impl App { } pub(crate) fn set_grid_cfg(&mut self, cfg: GridCfg) -> Result<(), JsValue> { - self.grid.set_cfg(cfg, &self.camera, &self.projection)?; + self.grid.set_cfg(cfg)?; self.request_redraw = true; Ok(()) diff --git a/src/core/src/camera/viewport.rs b/src/core/src/camera/viewport.rs index 92cb9f78..8a4973a8 100644 --- a/src/core/src/camera/viewport.rs +++ b/src/core/src/camera/viewport.rs @@ -337,7 +337,7 @@ impl CameraViewPort { self.last_user_action }; - let _can_unzoom_more = match proj { + let can_unzoom_more = match proj { ProjectionType::Tan(_) | ProjectionType::Mer(_) //| ProjectionType::Air(_) @@ -351,32 +351,45 @@ impl CameraViewPort { let aperture_start: Angle = ArcDeg(proj.aperture_start()).into(); - self.aperture = aperture.min(aperture_start); - // Compute the new clip zoom factor - let a = aperture.abs(); - - let v0 = math::lonlat::radec_to_xyzw(-a / 2.0, Angle(0.0)); - let v1 = math::lonlat::radec_to_xyzw(a / 2.0, Angle(0.0)); - - // Vertex in the WCS of the FOV - self.clip_zoom_factor = if self.width < self.height { - if let (Some(p0), Some(p1)) = - (proj.world_to_clip_space(&v0), proj.world_to_clip_space(&v1)) - { - (0.5 * (p1.x - p0.x).abs()).min(1.0) + self.clip_zoom_factor = if aperture > aperture_start { + //al_core::log(&format!("a: {:?}, as: {:?}", aperture, aperture_start)); + if can_unzoom_more { + aperture.0 / aperture_start.0 } else { 1.0 } } else { - if let (Some(p0), Some(p1)) = - (proj.world_to_clip_space(&v0), proj.world_to_clip_space(&v1)) - { - (0.5 * (p1.x - p0.x).abs()).min(1.0) + // Compute the new clip zoom factor + let a = aperture.abs(); + + let v0 = math::lonlat::radec_to_xyzw(-a / 2.0, Angle(0.0)); + let v1 = math::lonlat::radec_to_xyzw(a / 2.0, Angle(0.0)); + + // Vertex in the WCS of the FOV + if self.width < self.height { + if let (Some(p0), Some(p1)) = + (proj.world_to_clip_space(&v0), proj.world_to_clip_space(&v1)) + { + (0.5 * (p1.x - p0.x).abs()).min(1.0) + } else { + 1.0 + } } else { - 1.0 + if let (Some(p0), Some(p1)) = + (proj.world_to_clip_space(&v0), proj.world_to_clip_space(&v1)) + { + (0.5 * (p1.x - p0.x).abs()).min(1.0) + } else { + 1.0 + } } }; + self.aperture = aperture.min(aperture_start); + //self.aperture = aperture; + + //al_core::log(&format!("zoom factor {:?}", self.clip_zoom_factor)); + //console_log(&format!("clip factor {:?}", self.aperture)); // Project this vertex into the screen diff --git a/src/core/src/lib.rs b/src/core/src/lib.rs index e3eb4303..13fc19fa 100644 --- a/src/core/src/lib.rs +++ b/src/core/src/lib.rs @@ -505,11 +505,9 @@ impl WebClient { /// * `fov` - The field of view in degrees #[wasm_bindgen(js_name = setFieldOfView)] pub fn set_fov(&mut self, fov: f64) -> Result<(), JsValue> { - //let fov = fov as f32; let fov = ArcDeg(fov).into(); self.app.set_fov(fov); - //self.projection.set_fov(&mut self.app, ArcDeg(fov).into()); Ok(()) } diff --git a/src/core/src/renderable/grid/mod.rs b/src/core/src/renderable/grid/mod.rs index 7aef4437..bc9bae4f 100644 --- a/src/core/src/renderable/grid/mod.rs +++ b/src/core/src/renderable/grid/mod.rs @@ -114,12 +114,7 @@ impl ProjetedGrid { Ok(grid) } - pub fn set_cfg( - &mut self, - new_cfg: GridCfg, - _camera: &CameraViewPort, - _projection: &ProjectionType, - ) -> Result<(), JsValue> { + pub fn set_cfg(&mut self, new_cfg: GridCfg) -> Result<(), JsValue> { let GridCfg { color, opacity, @@ -165,10 +160,6 @@ impl ProjetedGrid { if let Some(enabled) = enabled { self.enabled = enabled; - - /*if !self.enabled { - self.text_renderer.clear_text_canvas(); - }*/ } Ok(()) diff --git a/src/js/DefaultActionsForContextMenu.js b/src/js/DefaultActionsForContextMenu.js index 26e5cae7..a6a8b8ca 100644 --- a/src/js/DefaultActionsForContextMenu.js +++ b/src/js/DefaultActionsForContextMenu.js @@ -229,12 +229,10 @@ export let DefaultActionsForContextMenu = (function () { }, { label: "HiPS2FITS cutout", action(o) { - let hips2fitsUrl = 'https://alasky.cds.unistra.fr/hips-image-services/hips2fits#'; - let radec = a.getRaDec(); - let fov = Math.max.apply(null, a.getFov()); + let hips2fitsUrl = 'https://alasky.cds.unistra.fr/hips-image-services/hips2fits?'; let hipsId = a.getBaseImageLayer().id; - let proj = a.getProjectionName(); - hips2fitsUrl += 'ra=' + radec[0] + '&dec=' + radec[1] + '&fov=' + fov + '&projection=' + proj + '&hips=' + encodeURIComponent(hipsId); + let wcs = JSON.stringify(a.getViewWCS()); + hips2fitsUrl += 'wcs=' + encodeURIComponent(wcs) + '&hips=' + encodeURIComponent(hipsId); window.open(hips2fitsUrl, '_blank'); } }, diff --git a/src/js/ProjectionEnum.js b/src/js/ProjectionEnum.js index a8e2760b..aeb74341 100644 --- a/src/js/ProjectionEnum.js +++ b/src/js/ProjectionEnum.js @@ -31,9 +31,9 @@ export let ProjectionEnum = { // Zenithal TAN: {id: 1, fov: 150, label: "Tangential"}, /* Gnomonic projection */ STG: {id: 2, fov: 240, label: "Stereographic"}, /* Stereographic projection */ - SIN: {id: 3, fov: 180, label: "Spheric"}, /* Orthographic */ + SIN: {id: 3, fov: 1000, label: "Spheric"}, /* Orthographic */ // TODO: fix why the projection disappears at fov = 360.0 - ZEA: {id: 4, fov: 359.999, label: "Zenital equal-area"}, /* Equal-area */ + ZEA: {id: 4, fov: 1000, label: "Zenital equal-area"}, /* Equal-area */ //FEYE: {id: 5, fov: 190, label: "fish eye"}, //AIR: {id: 6, fov: 360, label: "airy"}, //AZP: {fov: 180}, @@ -45,10 +45,10 @@ export let ProjectionEnum = { //CEA: {id: 11, fov: 360, label: "cylindrical equal area"}, //CYP: {id: 12, fov: 360, label: "cylindrical perspective"}, // Pseudo-cylindrical - AIT: {id: 13, fov: 360, label: "Hammer-Aïtoff"}, + AIT: {id: 13, fov: 1000, label: "Hammer-Aïtoff"}, //PAR: {id: 14, fov: 360, label: "parabolic"}, //SFL: {id: 15, fov: 360, label: "sanson-flamsteed"}, - MOL: {id: 16, fov: 360, label: "Mollweide"}, + MOL: {id: 16, fov: 1000, label: "Mollweide"}, // Conic //COD: {id: 17, fov: 360, label: "conic equidistant"}, // Hybrid diff --git a/src/js/View.js b/src/js/View.js index a70edf1b..9854d5b1 100644 --- a/src/js/View.js +++ b/src/js/View.js @@ -71,6 +71,9 @@ export let View = (function () { // MOCs this.mocs = []; + this.outsideFov = 0; + this.outside = false; + self.redrawClbk = this.redraw.bind(this); // Init the WebGL context // At this point, the view has been created so the image canvas too @@ -195,8 +198,7 @@ export let View = (function () { this.setProjection(projName) // Then set the zoom properly once the projection is defined - this.wasm.setFieldOfView(initialFov); - this.updateZoomState(); + this.setZoom(initialFov) // Target position settings this.viewCenter = { lon, lat }; // position of center of view @@ -398,6 +400,7 @@ export let View = (function () { this.imageCtx.canvas.style.width = this.width + "px"; this.imageCtx.canvas.style.height = this.height + "px"; this.wasm.resize(this.width, this.height); + this.setZoom(this.fov) pixelateCanvasContext(this.imageCtx, this.aladin.options.pixelateCanvas); @@ -1130,23 +1133,15 @@ export let View = (function () { // disable text selection on IE //Utils.on(view.aladinDiv, "selectstart", function () { return false; }) - var eventCount = 0; + /*var eventCount = 0; var eventCountStart; var isTouchPad; - let id; + let id;*/ Utils.on(view.catalogCanvas, 'wheel', function (e) { e.preventDefault(); e.stopPropagation(); - view.wheelTriggered = true; - - clearTimeout(id); - id = setTimeout(() => { - view.wheelTriggered = false; - view.zoom.stopAnimation(); - }, 100); - const xymouse = Utils.relMouseCoords(e); view.xy = xymouse ALEvent.CANVAS_EVENT.dispatchedTo(view.aladinDiv, { @@ -1178,7 +1173,7 @@ export let View = (function () { // First detect the device // See https://stackoverflow.com/questions/10744645/detect-touchpad-vs-mouse-in-javascript // for detecting the use of a touchpad - view.isTouchPadDefined = isTouchPad || typeof isTouchPad !== "undefined"; + /*view.isTouchPadDefined = isTouchPad || typeof isTouchPad !== "undefined"; if (!view.isTouchPadDefined) { if (eventCount === 0) { view.delta = 0; @@ -1195,28 +1190,23 @@ export let View = (function () { } view.isTouchPadDefined = true; } - } + }*/ // only ensure the touch pad test has been done before zooming - if (!view.isTouchPadDefined) { + /*if (!view.isTouchPadDefined) { return false; - } + }*/ // touch pad defined view.delta = e.deltaY || e.detail || (-e.wheelDelta); - if (isTouchPad) { + //if (isTouchPad) { if (!view.throttledTouchPadZoom) { - //let radec; view.throttledTouchPadZoom = () => { - /*if (!view.zoom.isZooming && !view.wheelTriggered) { - // start zooming detected - radec = view.aladin.pix2world(view.xy.x, view.xy.y); - }*/ - const factor = 2.0; let newFov = view.delta > 0 ? view.fov * factor : view.fov / factor; + // inside case view.zoom.apply({ stop: newFov, duration: 100 @@ -1225,22 +1215,21 @@ export let View = (function () { } view.throttledTouchPadZoom(); - } else { + /*} else { if (!view.throttledMouseScrollZoom) { - view.throttledMouseScrollZoom = Utils.throttle(() => { - const factor = 5 + view.throttledMouseScrollZoom = () => { + const factor = 2 let newFov = view.delta > 0 ? view.fov * factor : view.fov / factor; // standard mouse wheel zooming - view.zoom.apply({ stop: newFov, - duration: 300 + duration: 100 }); - }, 50); + }; } view.throttledMouseScrollZoom() - } + }*/ return false; }); @@ -1588,7 +1577,7 @@ export let View = (function () { } this.wasm.setFieldOfView(fov); - this.updateZoomState(); + this.updateZoomState(fov); }; View.prototype.increaseZoom = function () { @@ -1613,9 +1602,7 @@ export let View = (function () { this.gridCfg = {...this.gridCfg, ...options}; this.wasm.setGridOptions(this.gridCfg); - if (!this.gridCfg.enabled) { - this.mustClearCatalog = true; - } + this.mustClearCatalog = true; ALEvent.COO_GRID_UPDATED.dispatchedTo(this.aladinDiv, this.gridCfg); @@ -1626,12 +1613,24 @@ export let View = (function () { return this.gridCfg; } - View.prototype.updateZoomState = function () { + View.prototype.updateZoomState = function (fov) { // Get the new zoom values from the backend - let fov = this.wasm.getFieldOfView(); + const newFov = fov || this.wasm.getFieldOfView() + + // Disable the coo grid labels if we are too unzoomed + const maxFovGridLabels = 360; + if (this.fov <= maxFovGridLabels && newFov > maxFovGridLabels) { + let gridOptions = this.getGridOptions() + if (gridOptions) { + this.originalShowLabels = gridOptions.showLabels; + this.aladin.setCooGrid({showLabels: false}); + } + + } else if (this.fov > maxFovGridLabels && newFov <= maxFovGridLabels) { + this.aladin.setCooGrid({showLabels:this.originalShowLabels}); + } - // Save it - this.fov = fov; + this.fov = newFov; this.computeNorder(); let fovX = this.fov; @@ -1942,7 +1941,8 @@ export let View = (function () { // Change the projection here this.wasm.setProjection(projName); - this.updateZoomState(); + let newProjFov = Math.min(this.fov, this.projection.fov); + this.setZoom(newProjFov) const projFn = this.aladin.callbacksByEventName['projectionChanged']; (typeof projFn === 'function') && projFn(projName); diff --git a/src/js/Zoom.js b/src/js/Zoom.js index d77151c3..ae5aac64 100644 --- a/src/js/Zoom.js +++ b/src/js/Zoom.js @@ -43,8 +43,7 @@ import { requestAnimFrame } from "./libs/RequestAnimationFrame.js"; return; // clamp the zoom to the view params minFov and maxFov and the projection bounds - finalZoom = Math.min(finalZoom, this.view.projection.fov); - + //finalZoom = Math.min(finalZoom, this.view.projection.fov); // then clamp the fov between minFov and maxFov const minFoV = this.view.minFoV; const maxFoV = this.view.maxFoV; @@ -94,31 +93,31 @@ import { requestAnimFrame } from "./libs/RequestAnimationFrame.js"; let self = this; // Recursive function to perform interpolation for each frame function interpolateFrame() { - //fps = 1000 / self.dt; - //totalFrames = interpolationDuration * fps; // Total number of frames - self.x = ( performance.now() - self.startTime ) / interpolationDuration; - // Calculate step size for each frame - //stepSize = (desiredZoom - currentZoom) / totalFrames; - interpolatedZoom = Zoom.hermiteCubic.f(self.x, self.x1, self.x2, self.y1, self.y2, self.m1, self.m2); - // Clamp the interpolation in case it is < 0 for a time - interpolatedZoom = Math.max(0, interpolatedZoom); - - // Apply zoom level to map or perform any necessary rendering - self.view.setZoom(interpolatedZoom); - - self.fov = interpolatedZoom; - // Check if interpolation is complete if (self.stop) { + console.log("stop") self.isZooming = false; self.stop = false; - } else if (self.x >= self.x2 || Math.abs(interpolatedZoom - self.finalZoom) < 1e-4) { - self.view.setZoom(self.finalZoom); - - self.isZooming = false; } else { - // Request the next frame - self.requestAnimID = requestAnimFrame(interpolateFrame); + self.x = ( performance.now() - self.startTime ) / interpolationDuration; + interpolatedZoom = Zoom.hermiteCubic.f(self.x, self.x1, self.x2, self.y1, self.y2, self.m1, self.m2); + // Clamp the interpolation in case it is < 0 for a time + interpolatedZoom = Math.max(0, interpolatedZoom); + + // Apply zoom level to map or perform any necessary rendering + self.view.setZoom(interpolatedZoom); + + self.fov = interpolatedZoom; + + if (self.x >= self.x2 || Math.abs(interpolatedZoom - self.finalZoom) < 1e-4) { + console.log("finish") + self.view.setZoom(self.finalZoom); + + self.isZooming = false; + } else { + // Request the next frame + self.requestAnimID = requestAnimFrame(interpolateFrame); + } } } diff --git a/tests/run-examples.spec.ts-snapshots/GW-MOC-plot-1-chromium-darwin.jpg b/tests/run-examples.spec.ts-snapshots/GW-MOC-plot-1-chromium-darwin.jpg index ac79c585..a906cad8 100644 Binary files a/tests/run-examples.spec.ts-snapshots/GW-MOC-plot-1-chromium-darwin.jpg and b/tests/run-examples.spec.ts-snapshots/GW-MOC-plot-1-chromium-darwin.jpg differ diff --git a/tests/run-examples.spec.ts-snapshots/GW-MOC-plot-1-webkit-darwin.jpg b/tests/run-examples.spec.ts-snapshots/GW-MOC-plot-1-webkit-darwin.jpg index 4b40de18..ab3f20f8 100644 Binary files a/tests/run-examples.spec.ts-snapshots/GW-MOC-plot-1-webkit-darwin.jpg and b/tests/run-examples.spec.ts-snapshots/GW-MOC-plot-1-webkit-darwin.jpg differ diff --git a/tests/run-examples.spec.ts-snapshots/multiple-HiPS-display-each-referenced-by-an-ID-string-1-webkit-darwin.jpg b/tests/run-examples.spec.ts-snapshots/multiple-HiPS-display-each-referenced-by-an-ID-string-1-webkit-darwin.jpg index f969cb2d..416ab394 100644 Binary files a/tests/run-examples.spec.ts-snapshots/multiple-HiPS-display-each-referenced-by-an-ID-string-1-webkit-darwin.jpg and b/tests/run-examples.spec.ts-snapshots/multiple-HiPS-display-each-referenced-by-an-ID-string-1-webkit-darwin.jpg differ